[pulseaudio-commits] [SCM] PulseAudio Sound Server branch, master, updated. ac032549cd7eba9459f1fcd8983f1d513913f14f

Lennart Poettering gitmailer-noreply at 0pointer.de
Mon Jun 23 17:17:16 PDT 2008


This is an automated email from the git hooks/post-receive script. It was
generated because of a push to the "PulseAudio Sound Server" repository.

The master branch has been updated
      from  398514f577d2f0cb801320b3466a4c4e25b6586e (commit)

- Log -----------------------------------------------------------------
ac03254... Merge branch 'master' of git://git.debian.org/git/pkg-pulseaudio/pulseaudio-upstream
1562671... Merge dead branch 'glitch-free'
126e4cf... Merge dead branch 'lennart'
0be9bc2... Merge dead branch 'lockfree'
63c1eb1... Merge dead branch 'ossman'
a87ba42... Merge dead branch 'liboil-test'
1a3984c... Merge dead branch 'prepare-0.9.10'
3aadad1... update protocol spec
43dfc2a... follow recent alsa sink changes in the alsa source
734f071... decrease default tsched buffer to 2s to reduce overall memory consumption
813d40c... fix up requested latency when we move a record stream
e3c5a77... fix moving of record streams
99a4516... don't access stream before it is valid
74f8a67... fix suspend for alsa sink
f021538... export a couple of more functions from libpulse
e0dc1e4... Print message when stream started playback, use terminal sequence to clear line when printing that message
86ea73a... reduce malloc() usage when logging, to minimize the hit of logging in RT threads. Not complete yet, i18n still uses malloc
b57c520... add pa_vsnprintf()
1a2e5a8... add adaptive resampler to the RTP receiver, other modernizations
cfc4842... export a few more properties for RTP streams
f96a8ad... increase default mempool size, make mempool_slot an abstract struct because the only fields it defined where actually unused
70c5967... increase shm size limit, modernizations
2bc77ff... reduce number of allocated memblocks when receiving RTP data by reusing blocks
d10ee7d... more pa_bool_t'ization
c801d08... use pa_bool_t
076ffa3... add 'stream' as media role
1b7157a... add PA_REFCNT_INIT_ZERO
6895280... add pa_ulog2()
103ceaa... add pa_memblockq_get_nblocks()
df73688... modernizations
37813d9... modernizations
787b869... initialize volume properly, set more properties, modernizations
2eca8c9... don't spam us with wakeup msgs in non-tsched mode
9c48ed1... update pipe source for glitch-free, too
8baa1a4... fix pipe sink for glitch-free
dd29f67... fix braindead mistake
94c269e... some fixes to make the esound protocol work on glitch-free again
8df6529... some fixes to make the simple protocol work on glitch-free again
c5faeb1... store peer name in native-protocol.peer property
aae8beb... if zero is passed to pa_memblock_new() allocate largest memory block possible from mempool
f124445... fix module-sine for glitch-free
df92b23... - Fix moving of sink inputs between sinks - Don't write more than a single buffer size in the ALSA driver at a time, to give the clients time to fill up the memblockq again - Add API for querying the requested latency of a sink input/source output - Drop get_letancy() from vtable of sinks/sources
580d563... modify test to generate data events out-of-order
0ea0e06... make sure the smoother code can deal with incoming data that is out-of-order; start smoothing only when we have at least a configurable number of entries in our history
e97a347... bah, english sucks
1f196e7... fix some comments
7b5c6a3... fix recording
21fa1cf... double default asyncq size
876d5b4... fix a race condition when tearing down the ladspa/remap sink
6f4d44b... apparently alsa expects us to free the memory for card names
d21f458... fix a memory leak
9354da4... make memchunk/memblockq streams work with glitch-free
dafcf20... beefup proplist handling for sound events
8afbdc3... update to new rewinding logic
9d7fde5... rework the rewinding logic once again, fixing
6c28f1d... decrease verbosity a bit
44241ac... define callback function types; allow pa_signal_done() to be called even without prior pa_signal_init()
91fbb69... explain why changing rlimits at this time is safe
dee3555... rename 'routing' to 'filter'
4fa6cb4... add a few more asserts, don't allow pa_limit_caps() to fail
71d14d4... fix remapping sink for glitch-free
a1c10b5... update LADSPA module for glitch-free moed
59835d9... explain why a rewind was requested
82caf5a... when rewinding after the end of an underrun, make sure to rewind as much as we can, so that we deal properly with changed latencies of the sink
3167e0f... follow _unlink() changes from sink-input
d2da344... send PA_SINK_MESSAGE_REMOVE_INPUT only when an asyncmsgq is available, reset resampler only when we really need to
d2be471... make sure to call sink->update_requested_latency() always when we change latency, same for source
59a7467... don't require a module name when resolving a dl symbol
ff09fa3... Fix typo: "now"->"not".
43a30a2... Fix setrlimit() return value comparsion.
bb4f83b... only send PA_SINK_MESSAGE_SET_STATE if there's still an asyncmsqg around to do so
bfb2691... a few modernizations
06b9140... reorderer a few things
792ef5c... fix a compiler warning
775bc6c... some modernizations
7d6269e... add multiarch paths to default LADSPA search path
49b1b15... don't enable prebuffering if we just call is_readable()
52e3628... Yes, yet another evil all-in-one commit of intervowen changes. I suck. * Drop "state" directory, fold that into "runtime directory" * No longer automatically rewind when a new stream connects * Rework sound file stream, to cause a rewind on initialisation, shorten _pop() code a bit * Fix reference counting of pa_socket_server in the protocol implementations * Rework daemon initialization code to be compatible with non-SUID-root setups where RLIMIT_RTPRIO is non-zero * Print warning if RT/HP is enabled in the config, but due to missing caps, rlimits, policy we cannot enable it. * Fix potential memory leak in pa_open_config_file() * Add pa_find_config_file() which works much like pa_open_config_file() but doesn't actually open the config file in question. Just searches for it. * Add portable pa_is_path_absolute() * Add pa_close_all() and use it on daemon startup to close leaking file descriptors (inspired from what I did for libdaemon) * Add pa_unblock_sigs() and use it on daemon startup to unblock all signals (inspired from libdaemon, too) * Add pa_reset_sigs() and use it on daemon startup to reset all signal handlers (inspired from libdaemon as well) * Implement pa_set_env() * Define RLIMIT_RTTIME and friends if not defined by glibc * Add pa_strempty() * rename state testing macros to include _IS_, to make clearer that they are no states, but testing macros * Implement pa_source_output_set_requested_latency_within_thread() to be able to forward latency info to sources from within the IO thread * Similar for sink inputs * generelize since_underrun counter in sink inputs to "playing_for" and "underrun_for". Use only this for ignore potential rewind requests over underruns * Add new native protocol message PLAYBACK_STREAM_MESSAGE_STARTED for notification about the end of an underrun * Port native protocol to use underrun_for/playing_for which is maintained by the sink input anyway * Pass underrun_for/playing_for in timing info to client * Drop pa_sink_skip() since it breaks underrun detection code * Move PID file and unix sockets to the runtime dir (i.e. ~/.pulse). This fixes a potention DoS attack from other users stealing dirs in /tmp from us so that we cannot take them anymore) * Allow setting of more resource limits from the config file. Set RTTIME by default * Streamline daemon startup code * Rework algorithm to find default configuration files * If run in system mode use "system.pa" instead of "default.pa" as default script file * Change ladspa sink to use pa_clamp_samples() for clamping samples * Teach module-null-sink how to deal with rewinding * Try to support ALSA devices with no implicit channel map. Synthesize one by padding with PA_CHANNEL_POSITION_AUX channels. This is not tested since I lack hardware with these problems. * Make use of time smoother in the client libraries. * Add new pa_stream_is_corked() and pa_stream_set_started_callback() functions to public API * Since our native socket moved, add some code for finding sockets created by old versions of PA. This should ease upgrades
f94fae3... move unlinking code to operation_unlink()
f3cc178... some minor updates
11559a6... parse boolean parameters as boolean instead of int wherever applicable. add new function pa_cli_command_execute_file_stream()
414f1d9... install gccmacro.h properly, drop  unused core-def.h file
d7cc1f5... change pa_rtpoll_set_timer_absolute() to take a pa_usec_t instead of struct timeval
5816871... save and restore errno in log functions
b93ea18... minor reformat
4f99c43... check for $PULSE_INTERNAL before enabling padsp
18ad6f8... don't allow overwriting of callback pointers when we're already dead
b70edf7... port pa_sample_clamp() to liboil
9dd8f6c... add new function pa_sample_clamp()
264385a... strip CRLF line breaks from read CLI commands. This should fix the cli interface for people accessing it via telnet.
f49df7a... * Increase history set to 64 to simplify reduction of indexes * Decrease memory consumption a bit by using bitfields for some bools * Rework reduction code * Drop an unnessacary counter * Before adding a new entry to the history, try to figure out if we already have an existing entry with the same x value and replace that. This fixes a division by zero * Fix up input x for all functions, according to the time offset
563f4b6... make check for $DISPLAY=="" more readable, pa_bool_tization
06a05bc... a bit of pa_bool_t'ization
b12b8ee... save errno before calling free()
caf742a... define minimal and maximal wakeup/sleep times; check for underrun condition only once during buffer fillup
5353cf4... fix size of requested_latency
067a68a... fix build for auxiliary modules
c8fc223... add stripnul to build
76031df... Big pile of interdependant changes: * Fix a deadlock when an asyncq overflows and an RT thread needed to wait until space became available again while the main thread was waiting for a operation to complete and thus didn't free any new items. Now, if the asyncq overflows, queue those items temporarily, and return immediately. Then, when the queue becomes writable again, flush it. * Modify pa_thread_mq_init() to also set up pa_rtpoll events properly for the MQ * Some more pa_bool_t'ization * Unify more common code between alsa-sink and alsa-source * The upper limit for the tsched watermark is max_use minus one frame * make module-alsa-source work * make the alsa modules use pa_alsa_build_pollfd() now * fix detection of dB scale for alsa-source
a197644... add new tool 'stripnul' which can be used to drop leading zeros from a file which is useful to do byte-by-byte comparison of what goes in and comes out of PA
f2dffb7... pa_bool_t'ization
0b183fb... respect the resampler's maximum block size to avoid that we get kicked out of the memory pool due to resampling. actually drop data from the delay queue after we used it
998ed8e... add missing header definitions for last commit
3f57d3a... add new function pa_alsa_build_pollfd() to alsa-util to unify a bit more common code from the sink and the source
ed0af46... unify code that fixes up buffering metrics
af03dd4... drop a misplaced newline
3c8e83f... do not fix automatic buffer attrs anymore, the new protocol version doesn't need this anymore and it creates more problems than it solves. Also drop the initial timing info query. Correct programs shouldn't depend on it anyway
5e6aacd... * don't increase tsched_watermark on underrun without limits * fix the watermark when we change the latency * fix latency measurement * move rewinding code into its own function * make use of new function pa_alsa_recover_from_poll() were applicable
6b4b95b... show configure latency metrics
1adbe82... some beautification updates, show msec instead of usec everywhere
cdb077b... if no timer was armed, we don't need to disarm it
4a1971a... if no latency was configure for a sink/source, fill in the max latency automatically
69f6bdf... add new function pa_alsa_recover_from_poll() to merge common core from module-alsa-sink and module-alsa-source
9a486ef... implement --process-time
0d01c43... make sure the client buffer has space for 2*minreq+tlength. Explain why
e16a198... - Change meaning of special values of latency request: 0 -> "minimal latency, please"; (pa_usec_t)-1 -> "don't care" - Remove "source" word from monitor source description - Increase default tsched watermark to 20ms again - For the first iteration after snd_pcm_start() halve the sleep time as workaround for USB devices with quick starts
88227c4... properly initialize memblock->is_silence for imported memory blocks; make is_silence and read_only a bit field
5e7e827... improve dB volume calculation
ba6c0e1... fix C++ compat
8181db1... initialize properties for ALSA sinks/sources more elaborately, re #277
c2c833c... use the sink description instead of the name to choose the description for the monitor source
64e048c... drop a redundant pa_init_proplist(), properly set MEDIA_NAME property on stream, not on context
5971345... rename sink_input->rewind to process_rewind() and set_max_rewind to update_max_rewind()
62e7bc1... Big pile of dependant changes: * Change pa_memblockq to carry silence memchunk instead of memblock and adapt all users * Add new call pa_sink_input_get_silence() to get the suitable silence block for a sink input * Implement monitoring sources properly by adding a delay queue to even out rewinds * Remove pa_{sink|source}_ping() becaused unnecessary these days and not used * Fix naming of various rewind related functions. Downstream is now _request_rewind(), upstream is _process_rewind() * Fix volume adjustments for a single stream in pa_sink_render() * Properly handle prebuf-style buffer underruns in pa_sink_input * Don't allow rewinding to more than the last underrun * Rework default buffering metrics selection for native protocol * New functions pa_memblockq_prebuf_active(), pa_memblockq_silence() * add option "mixer_reset=" to module-alsa-sink * Other cleanups
7556ef5... maintain a global silence memblock cache
a0671aa... fix for new location of gccmacro.h
d1d7a07... we have not periodic timers anymore
33a35b6... update to recent changes of proplist api
33cb589... split user supplied data in multiple memory blocks if necessary to fit in one mempool tile. If the caller supplied a free_cb and we use shm it's better to copy the data immediately to the shm region instead of keeping it around as user memblock
ed36f31... increase the default pool size to 16MB because we now need to keep a lot more memory around due to glitch-free.
03df088... add lower boundary for artifical latencies
af25697... follow pa_pstream_use_shm->pa_pstream_enable_shm rename
687aa29... add new pa_pstream_get_shm() API, rename pa_pstream_use_shm() to pa_pstream_enable_shm(); pa_bool_t-ization
bee409a... remove debug messages
1ddb95a... add new silence memblock caching subsystem
4b1d684... add new API function pa_memchunk_memcpy()
144b237... print a message on xrun
22ceb15... add new rtstutter tool which can be used generate artifical scheduling latencies in the OS to trigger buffer underrun events in your software. it's an awesome debug tool for glitch-free; also move test programs from automake's check_ back to noinst_ to make sure it is built everytime Lennart presses F9 in his emacs
c9d0159... define PA_xxxSEC_PER_yyySEC for usec, too
1f0a52d... the pointer to rewind() may actually be NULL
68e4a93... properly ask the sink to rewind on new sink inputs and when they disappear
6946d2a... make sure to clear all queued RT signals before arm a new timer
04178d4... add _cb suffix to _max_rewind function like with all other functions, too
14fd32e... add missing 'break's in switch
55f273e... s/pulsecore\/gccmacro.h/pulse\/gccmacro.h/
07f5c1d... register sink/source name as first step when creating a new sink/source so that we can hand the valid name string to the hook functions; se tup props for monitor sources correctly; fix implicit flag setting logic
aad9d39... dump all info we know about sinks/sources/... in pactl
dbe3633... properly initialize ->memblockq
cdb273d... add new pa_get_state_dir() function, move pa_strnull() here
dcf7173... fix help string for volume commands
fe3c42d... fix packet formatting for a few commands
2c6176f... mark shm marker struct as packed, to guarantee identical sizes between archs
29cbd88... add new PA_GCC_PACKED macro
096e7f0... make shm magic marker compat with multiarch systems where 64bit and 32bit processes might share SHM areas
c9db6d2... don't fail if a signalled writability of STDOUT is no longer true when we try it because some other thread already wrote something
413656b... update list-xxx commands a bit
28ab2a0... don't print 'signal' each time a rtpoll poll() call is canceled
50d585e... fix linker warning macro code, move pa_strnull() to core-util.h, move PA_LIKELY definitions here from gccmacro.h
d0ebb71... don't use fqdn if we don't have to
78368db... redirect alsa errors to normal PA log system; export buffer settings in device props
1c5f665... make use of new alsa SND_PCM_NO_AUTO_xxx flags; redirect alsa errors to normal PA log system
0f28de6... mark autoload functions as deprecated
d7e260b... remove misplaced PA_GCC_PURE
e832b0c... add C++ safety to header file
7dad635... fix bit depth guarantee for pa_usec_t
919bd98... add new API function pa_timeval_add()
566322a... remove gcc macros from cdecl.h because we have them in gccmacro.h now
007f82d... fix bad memory access when initializing client proplist
d491adf... add gccmacro.h to doxygen docs
e084e4b... add new module module-device-restore
c61c3b6... increase version of required ALSA to 1.0.16. check for gdbm
6cddf61... add new API pa_rtclock_from_wallclock()
e1c1a78... fix proplist serialization
bb9792a... move gccmacro from pulsecore/ to pulse/
5d7128a... add new describe-module CLI command
39afb14... add new pa_proplist_setf() API function
d69aeeb... implement server side of new sink/source reconfiguration commands
fc9d827... remove doxygen \since tag for API changes older than 0.9; properly implement new latency query APIs
cc1e265... init min/max latency properly; fix avail_min updating
f3109be... show configured latency and its ranges
da37a7e... export both min and max latency that is configured for a sink; add API for querying the requested latency of a sink/source from the main thread
ad18107... add new latency argument
0f9e977... bump protocol version
3138928... include proplist.h in doxygen docs
b3b8a63... call snd_pcm_hwsync() expclicitly before we access any of the status fields, since this seems to be necessary. try to find the right mixer device via the card index
c84a64c... fix bug where we silently dropped data that didn't fit into one mempool tile
98b0152... add utility functions to dump alsa PCM state
b9c10f2... propery calculate min_avail in frames instead of bytes. don't use device_id= parameter in alsa modules if parameter wasn't specified
064aa12... drop support for periodic timers, cleanup code a bit
122861f... mark libpulse-browse as obsolete
cdfcf66... - deprecate autoload stuff - allow setting of the requested latency of a sink input/source output before _put() is called - allow sinks/sources to have a "minimal" latency which applies to all requested latencies by sink inputs/source outputs - add new client library flags PA_STREAM_ADJUST_LATENCY, PA_STREAM_START_MUTED - allow client library to fill in 0 to buffer_attr fields - update module-alsa-source following module-alsa-sink - other cleanups and fixes
ecf6439... catch up with trunk HEAD (i.e. 2118:2213)
3e314b7... fix buildsystem to provide pa_log() in all binaries
cf37df4... rework pa_assert_se() to make sure it never gets optmized away, even if NDEBUG is defined
68b131d... make pa_drop_caps() abort on failure
dbf9037... avoid name clash with libc's remove() function
829197d... fix compiler warning
ed5528f... require autoconf 2.60 since we use AC_PROG_MKDIR_P
1c82694... bump soname
a3b8311... merge r2187 from trunk
0a108ec... don't fail on init if the default device does not exist and .nofail is active
fad6b41... don't segfault when module-tunnel is used without a sink_name/source_name parameter. Closes #197
13b9951... if we are run as root, always use 'root' as username, regardless of any env vars
8e60b01... actually set lennart to the user name, not the group name. Set lennart too.
2599213... Fix ioctl() definition for solaris compat. Patch from yippi. Closes #253
b0dc80d... work around yet another solaris braindamage
4ddc327... initialize gconf module before we publish our X11 credentials -- because gconf might cause network support enabled in the first place
e21a69e... merge r2146 from trunk
2b593d2... merge r2134 from trunk
e5e9ed6... merge r2133 from trunk
ac82029... merge r2132 from trunk
95422a8... merge r2131 from trunk
edd1a50... merge r2130 from trunk
02840a3... merge r2129 from trunk
a1ec3d7... merge r2128 from trunk
46cd225... merge r2127 from trunk
daaf70b... merge r2117 from trunk
28b7ddc... merge r2116 from trunk
cca3f49... merge r2113,r2214,r2115 from trunk
184dda8... merge r2112 from trunk
1eb7239... merge r2111 from trunk
5045d26... merge r2110 from trunk
39de4dd... merge r2109 from trunk
bc58240... merge r2108 from trunk
ec39786... merge r2107 from trunk
e704fd3... merge r2106 from trunk
b79c6b6... merge r2105 from trunk
b0a2049... merge r2104 from trunk
a451de1... merge r2098 from trunk
2735309... merge r2097 from trunk
640033a... merge r2096 from trunk
9dfbfce... merge r2095 from trunk
cc59e76... merge r2092,r2093,r2094,r2152 from trunk
db208e3... merge r2091 from trunk
9f0045a... merge r2090 from trunk
f10b531... merge r2084 from trunk
66d9e87... merge r2145 from trunk
d055127... merge r2083 from trunk
cefa0eb... merge r2081 from trunk
0e23606... merge r2079 from trunk
a86a48c... merge r2077 from trunk
5e13249... merge r2076 from trunk
aceb800... merge r2075 from trunk
e721ecd... merge r2073 from trunk
8d5ee50... merge r2074 from trunk
c59a90c... merge r2078 from trunk
05a7f5d... bump revision
e6bb276... create branch for 0.9.10
106ddb9... remaining bits and pieces
b5c5064... commit glitch-free work
d6bd152... commit glitch-free work
ebecf3d... commit glitch-free work
12c01e9... commit glitch-free work
347cfc3... commit glitch-free work
8d9bdac... really create glitch-free branch
dd81a90... create glitch-free branch
90a7f3b... bump revision
4d4dafb... fix CVE-2008-0008.patch
9423e67... prepare 0.9.9
d41744a... Tagging release 0.9.8
575541d... Merge r1502 from trunk: Move pthreads detection as it gets confused by things in LIBS.
f096ca4... Merge r1504 from trunk: Solaris hides inet_ntop in nsl
c6071b0... Merge r1505 from trunk: Make sure we link to the core to get all symbols.
9eb840c... Merge r1503 from trunk: Make -no-undefined actually work (and fix up error found by it).
d8976a2... Merge r1473 from trunk (mixer ioctls on /dev/dsp)
b718d18... fix error handling
daa2863... don't use errno on EOF
94cf167... port module-esound-sink to new core
66dc0b4... don't use SIGRTMAX, for compatibility with valgrind which apparently uses this signal
98d363c... minor cleanup
87faa54... minor fix to make gcc shut up
56804de... minor fixups, to make the test more deterministic
581e7f1... add ability to "pause" the input time temporarily. don't accidently overwrite variables we still need.
55e4a3e... modernize pa_iochannel a bit, add pa_iochannel_get_send_fd()
c4d9a2b... add missing pa_smoother destructor
b4bb747... add pa_rtclock_usec() API
ca744a4... add pa_timeval_load() API
ce5250e... hide smoother test
7ccf40e... Add "support" for plugins that have control output ports, i.e. don't crash on them anymore (the plugins correctly assume that every port is connected to a buffer, so we connect them to a dummy buffer that isn't used anywhere).
81ed6e6... A couple of comment typo fixes.
0d84e4c... fix alsa mmap initialization bogosity, discovered by Jyri Sarha
dc987e9... add better time interpolator: use linear regression to determine gradient from measurements, predict a short distance ahead, and smoothen estimation function with 3rd degree spline interpolation.
9464b9b... add definition of PA_USEC_PER_MSEC
65b570c... properly copy error string
498a156... also port over JACK source to new core
02adb5f... enable jack sink in Makefile
468c13e... Port JACK sink module over from old core
4029504... minor fixup
925eadd... add interleaving/deinterleaving APIs
1900817... Properly handle if ALSA sends us an POLLERR event, this should allow us to survive a system suspend cycle better
2385efe... fix url
b0bce20... add missing poll.h inclusion
215cac8... add missing poll.h inclusion
a687c31... add missing poll.h inclusion
3736246... s/timespec/timeval
2198c2e... fix build
efc81a8... add new API function pa_timeval_store()
d74fa66... Fix build; change return value of pa_rtclock_hrtimer() to pa_bool
87cc073... fix poll.h check, bad boy ossman broke
cb40087... Don't call pa_rtsig_configure() when we lack the necessary defines.
60a935b... module_ladspa used libltdl so make sure it links against it.
586ef22... Platform dependent semaphore implementation for Windows.
cef6563... Assorted minor Windows compatibility fixes for recent code updates.
ce74146... Add stubs when RT signals aren't available.
8dcc1fa... Adapt rtpoll and friends to Windows by replacing timespec with timeval and add a fallback when clock_gettime() isn't available.
ef8812e... Replace all references to sys/poll.h with poll.h as that's what POSIX defines.
7c1768d... update native protocol to make use of pa_memblockq_pop_missing
2e780e8... Move request size handling into pa_memblockq, function pa_memblockq_pop_missing()
d6a2203... Fix race condition between IO thread creation and pa_sink_put(). Move activation of rtpoll fds when we change the state INIT->IDLE.
9d34a1e... fix trivial typo
abd692e... fix silence initializer for alaw and ulaw
dbcd086... Fixed PA_GCC_CONST definition.
bdf9746... Update module-solaris to new structure.
67b899a... treat timer_enabled like a real, grown-up boolean variable
33f2f49... rework module-combine once again. We now run the data generation always in a seperate thread. This should help use to avoid all the awful race conditions we had in previously
229afb5... Move the poll() call outside the #ifdef checking for ppoll, since we want the poll in all cases. Prior to this change the check for negative return values of poll/ppoll was never actually executed when ppoll() was available
f8c1786... use the full range of RTSIGS for our stuff
3cdff5f... Allocate rtsigs from back to front, to avoid clashes with other libraries makeing use of rtsigs
df33b4c... only do IO if we are RUNNING or IDLE, but not when we are in INIT
6d8aea7... Incorrectly used str2sig() instead of sig2str().
584ca61... don't free silence memblocks that don't exist
107f12a... speed up semaphore allocation with an flist
008c709... Use Linux eventfd() if kernel supports it
e99bc33... fix build with compilers that lack __thread
a9e667b... make sure when can shutdown PA cleanly without segfault
5fe1589... work around newest open() magic in fedora glibc
1687226... fix make dist
86ec421... fix suspending in module-combine.c
609ad12... * decouple suspending of monitor sources and their sinks * implement resume-on-uncork
0e3e9e2... only post data into the monitor source when it is not suspended
f0f9df9... * add new state changed hook for streams * update sink->n_corked properly when moving streams
ac86fa1... fix IDLE vs. RUNNING state handling of sinks/sources when changing cork status for streams
3c75d35... rework zeroconf service publishing, to use synchronous hooks instead of asynchronous subscription events. Don't push autoload entries anymore.
e37fa01... add hooks for name/description changes of sinks/source and streams
ef020c6... fix stream corking: ignore pa_sink_input() when we are in corked state
55651ec... don't count streams using the monitor source in pa_sink_used_by(), because this would disallow suspending a sink ehn an rtp stream is connected
ba322a4... drop the PA_SOURCE_CAN_SUSPEND and PA_SINK_CAN_SUSPEND flags, since they were a bad idea in the first place. All sinks/sources are now *required* to handle suspending in one way or another. Luckily all current sink/source implementations handle it fine anyway.
77ed60c... instead of using the mixer ioctl()s on the dsp fd, open a seperate fd for the mixer. This allows us the keep the mixer fd open while closing the dsp device while suspending.
fc00eaf... use O_NOFOLLOW when creating lock files, too
2860685... use O_NOFOLLOW when creating PID file, to avoid symlink vulnerability
de079ac... Added an assertion for the case when the sink programmer hasn't installed the thread_mq properly.
7bcbf16... Comment typo fix.
ecad937... Fix the assignment of control values by using the right variable for indexing.
1c44be2... Correct the parameter positions with the pa_cvolume_set() call.
e04a857... minor optimization
6cfb096... include the name of the master sink in the name for piggy-backed virtual sinks
c6b43bf... prefix by order macros with PA_
6683400... rework a couple of sample type converters, to actually work
78a9ad3... - rework volume adjustment code to not require fp - don't hit an assert when we cannot do a volume adjustment, instead, print a warning and go on
d7a0876... fix selection of working format
9db4267... make use of byte swap builtins of gcc if they are available
f26de80... add test program for the resampler
c34a263... allow _unlink() functions to be called as many times as people want, even before _put() was called
1fc168b... clamp sample data to -1 .. 1, before passing it to the plugin; if a control port data specification is left empty, initialize with the default value of the plugin
29d25ec... add CLAMP macro
e205bb2... don't segfault when the master changes
3b2835d... properly detach/attach when moving sink inputs
f3f44da... rework module-combine again
c40c168... maintain the attach status in a boolean variable 'attach' accessible from the IO thread for sink_inputs/source_outputs
75647bc... render new data always in the master sink's thread, fixing missing locking
a8a9ee4... make sure we initialize thread private data before we move our ghost sink to the rt thread, not after
42b71ff... fix trivial typo
d716e3c... fix check for lrintf, make resample2.c again identical to upstream ffmpeg
75f799a... make O_CLOEXEC, O_NONBLOCK and socket low latency fd ops more uniform: always return void, name them similarly, only pass a single fd
0fcad97... copy free_cb into a temporary variable first, to avoid compiler warning
ac66b6a... fall back to plughw:, if hw: doesn't work, in the alsa source, too
781cf49... properly release memblock always abd as soon as possible
1fd9afd... make use of pa_bool_t on a few places where applicable; really start work_cb
b3093d8... lower SO_PRIORITY priority to 6, since this is the best we get without being root
ef8df41... make rtp send socket low delay
f44ddd1... add new pa_socket_udp_low_delay() API
6b2fd23... add two missing header file inclusions
eb23601... bug fixes for module-rtp-recv
8fdf054... make sure we don't call pa_source_post() for a monitor source after it was unlinked
ca71764... If PTHREAD_PRIO_INHERIT mutexes are not available fall back to normal mutexes
a558e93... port module-rtp-send.c to lock-free core
08d4b23... actually close the alsa device before we try to reopen it as plughw
4ed41f3... strtof() is a rather recent addition to C. Fall back to strtod() if it isn't available.
aff22cf... NSIG seems to be more common than _NSIG.
03d9863... Emulate lrintf with simple truncation if it isn't available.
31dfb31... Make sure the header file is only included on linux (as this is a linux-only feature).
df1d347... NSIG is not defined by neither C99 nor POSIX so we can't rely on it.
4cde507... add LADSPA sink than can be piggy-backed ontop of another sink
7b4f981... print a message when we fall back on plughw
8ff7d56... add a locale-independant pa_atof() implementation
4cdf2ce... hide sig2str-test
1ae473b... fall back to plughw: if hw: doesn't work
26a1ae7... Rename pa_strsignal() to pa_sig2str(), since we return the symbolical signal name, not a human readable string. This follows the Solaris API of sig2str() a bit. Also, add all remaining signals to the list of signal names.
d3b8985... drop a couple of WARNING prefixes in log messages, since we have pa_log_warn anyway for marking warnings especially
19eb7eb... once.c is no longer POSIX specific. Since it is now considerably more advanced than it used to be, use it on windows, too
7f9fea7... on Linu disable lazy binding altogether
a1526f1... add missing initialization
061e806... Add a special ltdl .so loader that avoids lazy frelocations during runtime
2741685... use priority inheritance on mutexes where applicable
61b90a0... add proper boolean type pa_bool_t
116ddaa... use gcc const and pure function attributes wherever applicable
35483ee... add a new module module-remap-sink which can be used to remap the channel maps of an already existant sink. one use case is to create a virtual sink that redirects stereo data to the rear speakers of a surround card.
1d1eda6... add a "length" argument to the seek functions, as an optimization to request a certain block size if any data needs to be generated. this is merely a hint.
5df7a85... split memblocks into multiples of the mempool tile size
ac1ee4e... add new API pa_mempool_block_size_max() to query the maximum tile size
fce8507... * add a new resampler "copy" which is does not change sample rates but copies data unmodified from input to output. * add a new API pa_resampler_max_block_size() which can be used to determine the maximum input buffer size for the resampler so that the bounce buffers don't grow larger then the mempool tile size
d079b48... properly define MAX/MIN macros
87795b0... add missing header file changes for frame alignment apis
e17fbf0... be a little bit more elaborate on the reason why we drop to software volume control if hw is not featureful enough for us
0469c84... add frame alignment APIs; don't require memory to be writable when silencing it (required of the mmap modes drivers where the hw data needs to be silenced, although it is not writable to others)
298d239... trivial typo
8389264... count corked streams per sink/source and make pa_sink_used_by() return only the number of streams that are not corked. Introduce pa_sink_linked_by() returning the number of streams connected at all. This will allow suspending of sinks/sources when all streams connected to a sink are corked.
5ae4eed... Move attaching/detaching from a pa_rtpoll into pa_sink proper, remove it from module-combine
3396b65... simplify rt loops a bit by moving more code into pa_rtpoll. It is now possible to attach "work" functions to a pa_rtpoll_item, which will be called in each loop iteration. This allows us to hide the message processing in the RT loops and to drop the seperate sink_input->process hooks. Basically, only the driver-specific code remains in the RT loops.
f0b9dce... explicitly destory TLS data before destroying TLS
bf274cb... add two new macros PA_ONCE_BEGIN and PA_ONCE_END which allow usage of pa_once without declaring a function to be called
04ed0f9... call dbus_shutdown() before exiting, to make valgrind output more useful
8775309... fix two typos in reference count handling
9be0d70... make newer gcc shut up
ef83a19... extend rtpoll API to allow registration of arbitray functions to be executed in the event loop. Add priority system for specifying the order of these functions.
cf3e9da... add missing config.h inclusion
03f311a... reindent, and s/assert/pa_assert/g
4137865... change pa_modargs_get_channel_map() to take an extra argument for specifying the name of the modargs attribute to parse
d9c4c95... add new pa_pipe_close() API to close two fds at the same time
7f92542... consolidate close() calls to pa_close(), and make sure on every occasion that we handle failures of close() sensibly
54506ab... on systems where we know that POSIX shm is mapped to /dev/shm, add the ability to cleanup stale SHM segments. (Right now only Linux)
d5bedbc... remaining s/assert/pa_assert/ and refcnt.h modernizations
2988c3d... Rework core-error.c on top of PA_STATIC_TLS_DECLARE, the windows specific parts need to be moved to thread-win32.c
abb18d9... explcitly initialize tls memory to NULL
9c523e0... more modernizations, s/assert/pa_assert/g
27f13b3... finish modernizations in pulse/, s/assert/pa_assert/g
038e560... More s/assert/pa_assert/ modernizations
391d09c... add 'wait' parameter to pa_rtpoll_run(), if zero pa_rtpoll_runn will only update the struct pollfd but not wait for an event
597a1c4... port client libs to refcnt.h
55d9fcb... add globally defined PA_PATH_SEP macro, replacing private per-file macros
6ac66e4... add missing config.h includes
e2e2ce7... Instead of including config.h from header files, check whether PACKAGE is defined and if not, fail (thus using PACKAGE as a check for inclusion of config.h)
848a4d7... more s/assert/pa_assert/ modernizations
9b0ab39... unify static TLS support, make use of gcc __thread attribute if available
3d122d0... s/assert/pa_assert/ modernizations
de21b54... add new API pa_threaded_mainloop_in_thread(), update test case for it
a6f8b81... simple modernizations: s/assert/pa_assert
6629886... make sure we send each memblock only once when recording, not twice
d5caa02... minor cleanup
a77158e... make the memchunk writeable before silencing it
841fcb4... beef up comment
98f9bd6... make sure that the device volume is properly read before we call pa_sink_put() and thus make the pa_sink available
69ece66... add pulseaudio logo with text
44e514c... update todo file a little
6c1682c... hide a couple of files
27c3bd4... document that the native amd64 atomic ops implementation is incomplete
06db921... don't call pa_source_process_msg() for PA_SOURCE_MESSAGE_GET_LATENCY, since it makes querying the latency always fail
d9b3c0e... posix_madvise and posix_fadvise aren't present on all systems.
9630e8d... Remove mkdir_p again...
028632f... TIOCINQ isn't present on all systems.
e176601... Monotonic clock is optional so treat is as such.
717b164... POSIX realtime clock functions are in time.h so make sure to include it.
dfdf1d7... Changed PA_SAMPLE_S16_NE to PA_SAMPLE_S16NE in the example code in the Simple API Doxygen documentation.
b41dbfd... fix an assert when runnig module-oss in record only-mode. optimize allocation of memblocks on playback
d60940d... install libpulsecore again, since libtool otherwise links it statically into every single module
e4eefb8... fix copynpaste error
45ba711... downgrade realtime group membership warning to 'info' at be a little bit more elaborate
3b2cf1a... update default config: - check for existance of modules before loading them - disable all event sounds except hotplug by default
b1fd53b... explicitly test for the availability of dbus_watch_get_unix_fd() before using it. The previous version-based check didn't work anyway since the constants checked for weren't set.
a0d19c0... update libltdl copy
a4757a1... add native amd64 atomic int implementation
984ef82... detect whether gcc atomic builtins are available
4c31ff9... fix a couple of compiler warnings
2dbe137... if available, use native gcc atomicity builtins
31c04a9... create config.rpath to fix build on fedora
ac5f978... add a few missing files for make dist
738f7d7... drop initial libtool_lock() call since this is a debian-specific borkage
d1927c7... initialize libltdl for multi-thread support
65ac0ea... When in PA_STREAM_AUTO_TIMING_UPDATE mode, delay completion of initialization until we have the first timing data
c029038... actually add source code of module-default-device-restore
11bf380... add a new module module-default-device-restore which automatically saves and restores the selected default device. Enable it by default.
1d3e70c... header file cleanup
104feb0... only list supported resampling methods when --dump-resample-methods is executed
c9a0df3... add new API function pa_resample_method_supported() which tests whether a resampling method is supported. Fix building with libsamplerate enabled
5bc1221... actually define HAVE_LIBSAMPLERATE with AC_DEFINE
b2c4779... make libpulse-core a noinst lib, because it does not have yet a stable API and won't get one anytime. Also, don't install its header files
b6bfaa9... add missing configure.ac part of the libsamplerate patch from r1753, re #125
2e8244b... Allow compilation without libsamplerate; based on patch from Marc-Andre Lureau; re #125
cc8c499... fix dbus version check for dbus_watch_get_unix_fd()
011dfa5... make argument to pa_memchunk_will_need() const
68981e5... fix build for dbus < 1.1.1, re #126, patch from Marc-Andre Lureau
ca059ab... Don't set RLIMIT_MEMBLOCK to 0 on startup. Retain 4 pages
3e188b1... make use of pa_memchunk_will_need() before handing sample cache audio to the RT threads
7dbabc4... add new pa_memchunk_will_need() API, similar to pa_memblock_will_need()
f36ca79... add new API pa_memblock_will_need() and make use of PA_PAGE_SIZE macro
2f7b6fe... add new pa_will_need() API for paging in memory
8cf822a... make use of new PA_PAGE_SIZE macro
b54e71a... make use of new memory page alignment macros, reindent
fe1f55b... add a couple of macros for memory page alignment
1df817c... add pa_channel_position_to_pretty_string() to header
718b1d2... add pa_channel_position_to_pretty_string() for usage in pavucontrol/pavumeter
02811bf... make sure that we make include paths absolute before calling chdir()
a132226... minor reformatting
6eb2f88... add two new functions pa_make_path_absolute()/pa_getcwd()
c627871... replace a pa_assert() by an pa_assert_se()
f59dd18... - fix suspend handling - set sink description properly - honour resample_method setting
241ad04... port module-combine to new core
4d623f0... Lots of assorted minor cleanups and fixes: * s/disconnect/unlink/ at many places where it makes sense * make "start_corked" a normal pa_sink_input/pa_source_output flag instead of a seperate boolean variable * add generic process() function to pa_sink_input/pa_source_output vtable that can be used by streams to do some arbitrary processing in each rt loop iteration even the sink/source is suspended * add detach()/attach() functions to pa_sink_input/pa_source_output vtable that are called when ever the rtpoll object of the event thread changes * add suspend() functions to pa_sink_input/pa_source_output vtable which are called whenever the sink/source they are attached to suspends/resumes * add PA_SINK_INIT/PA_SOURCE_INIT/PA_SINK_INPUT_INIT/PA_SINK_OUTPUT_INIT states to state machines which is active between _new() and _put() * seperate _put() from _new() for pa_sink/pa_source * add PA_SOURCE_OUTPUT_DONT_MOVE/PA_SINK_INPUT_DONT_MOVE flags * make the pa_rtpoll object a property of pa_sink/pa_source to allow streams attached to them make use of it * fix skipping over move_silence * update module-pipe-source to make use of pa_rtpoll * add pa_sink_skip() as optimization in cases where the actualy data returned by pa_sink_render() doesn't matter
b552541... reorder initialization of pa_core variables
ca72adf... modernize and make use of a static flist for allocating idxset entries
821eb8e... move queue processing code into pa_thread_mq
687f1f1... add new function pa_memblock_ref_is_one()
c2e4328... fix pa_memchunk_make_writable(), make memchunk functions return the memchunk they modify
bfe69ce... add an assert()
6817987... add pa_timespec_reset()
747b01b... make passing a code pointer to pa_asyncmsgq_get() optional
ee97c42... add new PA_SINK_CAN_SUSPEND/PA_SOURCE_CAN_SUSPEND flag
d88514c... drop check for gid < 500, since this isn't really a security improvement, re: #111
0362350... Add option --dump-resample-methods to list available resampler implementations
782d5a5... make floating point speex resampler the default
89fcd51... enable -ffast-math for gcc
f82067f... lower suspend timeout to 1s
f4e2d23... include ffmpeg resampler in build
9439e81... make ffmpeg resampler actually work
f0dbbe9... add makefiles to speex/ and ffmpeg/ to easy compilation from emacs
640ae04... Copy resampler from ffmpeg into our sources
f754a24... make speex resampler the default
ed4dc16... big resampler rework: support integer-only resampling, support speex resampler
4eb9bb0... fix a bad memory access when destructing pa_memimports
c1cdcfd... a couple of modernizations; parse RE sample types properly
c72d4c6... add a small speex wrapper so that we can include both the fp and the fixed-point resampler in the same binary
fdead57... build speex resampler tiwce, once for fixed point, one for floating point
5ff891c... add a copy of the speex resampler to our sources
b3b382d... fix minor typo
9d38159... port remaining sinks to pa_rtpoll
1bfa180... minor cleanups
0ff2afd... support absolute, relative and periodic timers in pa_rtpoll
53b872c... port alsa driver to make use of new pa_rtpoll object
79d3ddd... reverse hrtimer check, add missing #include
b937009... add convenience functions to hook up pa_fdsem and pa_asyncmsgq to an pa_rtpoll; add pa_rtpoll_item_get_userdata(), on EINTR/EAGAIN, reset revents; automatically destory left over items
7490977... add missing include
0449966... make pa_make_power_of_two() and pa_is_power_of_two() inline functions
190648a... add missing #include
0da65cf... add message about hrtimers, and initialize pa_core::high_priority
0af0fb8... hide rtpoll-test from svn
7fca890... check pa_core::high_priority before becoming rt thread
b302946... add new option to pa_core stating whether we are running as high prio process
3546198... add check for ppoll()
8568f70... add rtpoll, rtclock, rtsig to Makefile
dc9d803... add test program for pa_rtpoll
78c362c... add new realtime event loop abstraction which precise time keeping by using hrtimers on Linux, if they are available
8972d06... add facility for managing realtime signals
ef2bc41... add monotonic clock abstraction pa_rtclock
6bfeef1... rename a few things in a macro to make name collisions less likely
531cc3c... make use of new public function pa_is_power_of_two()
b7b119a... add pa_is_power_of_two() and pa_make_power_of_two() functions
a0ad42a... add macro for creating static TLS objects
b0b06b0... add more PA_PTR_TO_XXX macros
fa7fc31... modernizations
2d292be... use realtime scheduling for ALSA and OSS driver threads
876e682... never stay root after startup, even if we don't have capabilites
5e93816... seperately get high nice level and acquire realtime sched
d5cbf4f... Keep CAP_SYS_NICE not only in PERMITTED but also in EFFECTIVE capset
843dcce... only suspend device when server is local
39d1e65... truncate service names if necessary, include user name in service string
03b0b1d... add pa_truncate_utf8() function for truncating a string and guaranteeing it stays valid UTF8 afterwards
81cdb37... add fedora-snapshot target
c0d6684... fix an awful race condition when handling data requests
1ff4786... don't fail if no pa is srunning
a96c5f8... add new tool pasuspender which temporarily suspends all sinks and resumes them later again
33c6f9d... set CLOEXEC on more fds
5679de5... add new commands suspend-source, suspend-sink
d2d0978... add protocol support for muting sink inputs and suspending sinks/sources
0640615... bump protocol revision and soname of libpulse
b20d204... use pa_source_suspend_all/pa_sink_suspend_all for suspending all sinks/sources
a74e804... fix muting for sink inputs
3d92990... actually mute sinks when asked for i, add new function pa_sink_suspend_all
6f714d9... actually mute sinks when asked for i, add new function pa_sink_suspend_all
44f91cf... load module-x11-xsmp from a /etc/xdg/autostart file, to make sure it is loaded when we have XSMP
80f5abf... add load-module and unload-module commands to pactl
8a663d4... a couple of build fixes
1d5e9f0... deactivate module-x11-xsmp by default, due to a deadlock when pa is being started from gnome-session
e381dd9... 64 bit fixes and minor gcc shut ups
5e96d5d... yet another new glibc build fix
3cbcb98... build fix for newer glibc
e6714e1... make make distcheck pass
db7fdf6... make make dist work
55f3d34... ship full libltdl tree in SVN to make sure we can build this crack on fedora
b16d8e2... bump soname and stuff for fedora pre-release
1cecd46... Resurrect ability to move streams between sinks
79a586d... add comments describing the context these functions are called from
3d81dde... modernize pa_play_memblockq() and add a new function pa_memblockq_sink_input_new() which allows creation of memblockq streams without activating them immediately
14d93fc... minor cleanup
45e4954... fix latency reporting for oss and alsa modules
06f2799... minor modernizations
57734ec... hook into move operations for resuming/suspending devices appropriately
44b82a1... Add 'via DMA' to sink/source description if device is accessed with mmap()
e71a347... restore the ability move record streams between sources
50e014e... use single array for storing pa_core hook lists, add sink state changed hook, drop NO_HOOKS flags for sink inputs/source outputs, listen for resume events in module-suspend-on-idle.c
a3cd800... port oss driver to make use of the default fragment sizes as defined in pa_core: store in the sink/source description whether mmap is used; if mmap() fails, fall back to UNIX read/write mode instead of bailing out immediately
b71dde0... make sure that the device access event sound is only generated once
447c4a5... deal with messages properly which are recieved after destruction of a stream
107b23d... fix module-hal when no api= argument is specified
c1c59b4... add proper refcounting to pa_asyncmsgq objects, to allow destruction from the dispatched callbacks
f7b707b... allow destruction of pa_fdsem object that are still in 'poll' state
e1100b5... modify alsa drivers to make use of new global fragment setting variables
793f750... fix default device naming and fix api selection code
a7a5f43... modernization
e2a10de... allow setting the default sample and fragment settings from the config file
b44ce9e... add default fragment settings variables to pa_core
59c9ed5... move pstream item allocation to pa_flist
d2fed9d... make revoke/release thread safe in the native protocol
ff4814c... add callbacks for the revoke/release stuff, so that we can make this thing thread-safe
4e145b6... if no thread-mq is attached to the current thread, return an error, don't hit an assert
3eae903... make use of pa_thread_mq everywhere
b3f1a13... minor update
f7171e8... Wrap two pa_asyncmsq in a new pa_thread_mq object for bidirectional, lock-free communication between a main loop and a thread
aff77c1... update thread test to use pa_once instead of pa_once_t
27f75a5... Rename pa_once_t to pa_once
d4cb042... move pa_queue to an implementation based on pa_flist
ac49cc2... do not acces playback pa_messagq from main thread
72840ab... minor cleanliness fixes
357c0e4... fix closing of fds in gconf module
ffa1708... * drop redundant pa_core argument from module initialization functions * make pa__done() implementations optional * a couple of modernizations * wrap lt_dlsym() at a single place * allow passing of an "api" argument to the HAL module, to choose whether OSS devices or ALSA devices should be picked up * optimize fd closing a little on linux in the forked gconf helper * save a little memory in the xsmp module
e621071... fix minor memory leakage
10b135a... avoid duplicate loading of modules
1e5ca51... handle ACLAdded messages for previously unknown devices identically to a really new device
3b078b2... Avoid a race condition when one PA instance gets HAL's ACLAdded message before the previous owner instance has given up access to the device, and thus the device is blocked
d9e44c5... Add X11 XSMP module for hooking into the X11 session manager, for being notified about X11 disconnects before they actually happen, so that we are not killed by the bloody xlibs
5831677... modernize
3dfdb21... don't assume that sink/source is already unregistered from namereg when disconnect hook is called
1c7b842... play ACL event sound only when gained access, not when losing it
b751f3a... s/login.wav/startup3.wav
02bf2f2... update default configuration
0f15574... protect memimpors with a recursive mutex to avoid deadlock when shutting down
e76efa9... forgot to actually add the new suspend-on-idle module source code
bb46da3... add new module-suspend-on-idle module which suspends sinks/sources which are idle for more than 5s (or any other configurable time). Power saving, here we come\!
9c89f37... if we get access to a device we don't know yet, add it to our tree instead of ignoring it
30ccf9a... add a couple of additional hooks for modules to use
ed01e1a... don't hit an assert when we cannot resume a device
eaddc01... by default, store esd socket in /tmp/.esd-`id -u`/socket, instead of /tmp/.esd/socket, to allow multiple simultaneous esd instances. this is only compatible with a patched esd, which however ubuntu and fedora ship now. other distros need to patch their esd as well, or may pass socket=/tmp/.esd/socket to module-protocol-esound-unix
33cd5e2... listen for HAL ACL events; play an event sound on hw coldplug, hotplug and ACL access
0c29a2f... add new function pa_scache_play_item_by_name
23ba125... fix bug in handling of defer events
a69f470... modernize module-hal-detect.c and check for ALSA pcm_class != modem
26a0246... modernize dbus-util.c
e4e9a06... be more verbose when device does not support sampling parameters
fedca91... Remove warning when client is too slow to handle our data
df9522c... properly reinitialize pollfd array after resume
54b9f55... properly reinitialize pollfd array after resume
981d5fa... don't print error on socket read/write failure
366d1d3... reinitialize sw params after resume
0a6f9af... add global suspend command to cli
1f9ce59... port esound protocol to new lock-free core
243f2fc... minor fixes and cleanups
74b3b6d... fix playback status querying
455ff8d... fix a memory leak
62790cc... fix playback over native protocol
c306b83... initialize 'length' properly
6775386... make sure to handle disconnecting our own connection properly
41d67c4... minor optimization for cacheing in of samples by using posix_fadvise
872951c... use posix_fadvise to avoid page faults when reading audio files from disk
9d1eb1b... play memchunks completely
bd0782e... initialize method pointers properly
241a9e1... follow rename of pstream_close() to pstream_unlink()
55e0866... typesafe casts
23d01bb... Modernize pstream.[ch], reintroduce defer event to make things actually work
36dd781... modernize play-memchunk and port it to the new core
34e4165... minor cleanups
81760ad... merge compat changes from trunk
95fab18... Don't stop hardware on buffer underruns. Instead continue playing to guarantee that our time function stays as linear as possible.
a6c44c0... Remove unnecessary snd_pcm_hwsync()
9a4e84a... On recommendation of Takashi Iwai prefer Master volume control over PCM and don't control Mic control
d3eca28... rename pa_source_output_new_data::corked to start_corked to match pa_sink_input_new_data::start_corked
0defdfb... A lot of updates, all necessary to get the native protocol ported:
a82505e... port module-alsa-source to new lock-free core
13a4327... minor cleanups
6afbbba... fix suspending logic
81aa8ea... drop data from inputs only when in running state
1615450... It is now allowed to call pa_sink_get_volume() from thread context
8aee345... Fix suspending/resuming
5fbb8e1... add PA_SINK_OPENED/PA_SOURCE_OPENED macros for easier checking for _IDLE or _RUNNING states
10cb048... restore proper mixer volume control
9dac60c... reload OSS volume after unsuspend
dd40020... bring back alsa fd list managemet, since we need it for proper mixer change notification
787f935... port module-alsa-sink to new lock-free core. also add mmmap'ing support while doing so.
c7df4ba... minor modernizations
8e4660a... Disable memory mapping if we open the device in O_WRONLY. Unfortunately we cannot do mmap() in Linux without opening the device for reading as well.
c936e53... Fix channel remapping in resample; other modernizations
4cc0d0a... remove some log messages
86abfbf... remove debug messages; don't queue request messages like nothing when send file is finished
bbb347f... properly free memblocks when skipping over them
042cb09... make valgrind shut up regarding non-freed ident strings. other modernizations
bc17b8e... reverse order flist destruction and mempool allocation warning
222a6d2... Increase ref counter of sink input as long as it is included in the sink idxset
d80fd10... properly deref sink_input/source_output objects when removing them from a sink/source
58af737... Add fdsem to makefile
8cdde28... reverse order of printf and push to make output more readable
bc36932... port asyncq to make use of new fdsem object
6ad165c... add abstracted file descriptor based semaphore object that is lock-free in the best cases
8836396... Store strings directly in strlst elements, other modernizations
98d36ef... fix some alignment issues and modernize file a little bit
929526d... Convert most snprintf() calls to pa_snprintf()
8e83838... Modernize things a little bith more
2a43bbf... Modernize things a little
2380ad9... add our own implementation for pa_snprintf() because NUL termination is apparently not guaranteed on windows and a couple of other libcs
9e9dc0b... Simplify implementation of pa_assert_se()
068f5d5... drop chunk argument from various drop() functions, since it doesn't make any sense if we want to guarantee always monotonously increasing read pointers; a couple of other fixes
9cc20b4... update static free list usage in asyncmsgq
e339d4b... update static free list usage in hashmap
f42e443... destruct freelists properly, by using gcc destructors. we do this only to make valgrind shut up, not because it would have any real value during runtime
279b1b3... wrap destructor gcc attribute in macro
a094923... change order of munmap and freeing of memblocks
c76d035... Fix a couple of typos in the resampler code
2a19c46... Fix typo in pa_memblock_release() call; s/assert/pa_assert/
65d54d6... s/assert/pa_assert/g; make use of static flist for memblock allocation where applicable; properly initialize length value in pa_memexport_put()
0e84f04... Minor clarification
f2c98d7... Make use of static flist for hashmap entry alllocation
69bfa35... Actually make the static flist static
3b912ac... Port module-sine to the new lock-free core
8442926... Reenable a couple of more modules
59faa5d... Remove a superfluous pa_memblock_release(); properly handle buf4 allocation
63c231e... Fix concurrency bug when turning memblock into a local memblock
481b425... Fix off-by-one in mixing code
ca5874d... Replace a couple of assert()s by pa_assert()s
ac1387d... Remove module-oss-mmap, since it is now merged into module-oss
a42c19e... Merge module-oss-mmap into module-oss and make suspending working properly
295e1c8... Make pa_sink_render_* and pa_source_post work only when in RUNNING state, to fix handling of monitor sources when their sink is suspended
0a095f6... Properly initialize all revents on EINTR
1a84664... Make sure pollfd[POLLFD_ASYNCQ].revents is properly initialized on signal
683fc4c... fix segfault when recording with module-oss.c
eec2fbe... Port module-oss to the new lock-free core
6312938... remove pa_memblockq_is_writable() (because it is stupid and not used anywhere anyway, and replace all assert()s with pa_assert()s
a482b9f... make sure we don't free the same connection twice
6776678... Limit silence buffer size for pa_sink_render()
de02c74... Track the 'missing' variable safely between the threads
d873731... rework the logic of pa_asyncq
77ebe70... Make sure the returned pa_msgobject object has a valid refcnt before returning it
099f3f2... Include assert.h, since we use assert() for our pa_assert() macro
a9fcd59... Fix length calculation in pa_silence_memblock_new() and make use of pa_assert() everywhere instead of assert()
fdd3ac9... Make use of dbus_watch_get_unix_fd() instead of dbus_watch_get_fd() because of deprecation of the latter
bb3ad9d... Update OSS driver for new lock-free core
013a55a... remove underrun condition in pa_sinks. Instead return silence in pa_sink_render() when necessary. This is required to guarantee that the time functions in connected sink inputs stays linear
780f736... don't handle underrun special
f061636... drop silence generation from sink drivers
fff9081... fix a typo and some minor optimizations
1c9bd20... minor cleanups and optimizations
e24c8de... Fix minor typo
deb523e... Port module-pipe-source to the new threaded design
94f6ab5... Fix another ugly typo, which made source outputs unusable
e279778... use pa_memblockq_push_align() instead of pa_memblockq_push() to deal with unaligned data coming from clients
1d7096b... Show memchunk length in debug output
1c62ce6... Fix a nasty typo in pa_asyncq_pop
572c77f... Remove anotify.[ch], since it is now entirely replaced by pa_asyncmsgq
5e72ac3... rework sink input/source output state machine
260dd1e... Make debug message more useful
1b99fd2... Move a few things between the threads
111dcd5... trivial cleanups
be4a882... A lot of more work to get the lock-free stuff in place
6911568... make untabify
590ae20... Add new untabify makefile target
a4fed0f... make eolspace
00da37f... Merge HUGE set of changes temporarily into a branch, to allow me to move them from one machine to another (lock-free and stuff)
6aeec56... add a new private branch
d664492... Create branch for lock free memblock implementation.
34e81ff... Handle Windows paths when normalizing authkey path.
29118f5... Make sure the caps header check can also be disabled.
1015ea4... Store previous reported time in order to assure a monotonic clock.
d429222... Accidental use of a swapped int.
11c6cac... buf is needed on Windows aswell.
abdf9b1... Add needed error code.
0a9abdd... Unfortunately Windows has two different values for EBADF depending on if it's a file or a socket. We'll have to deal with these as they show up.
ba06340... Add some required headers.
357ab88... Make sure socklen_t is defined.
5e5808a... Static libs bork the creation of dlls and AC_CHECK_LIB isn't very bright, so we have to do a test first to see if getopt_long() is included in the system libs.
ff4cc62... Move library checks to a separate section and make sure it's before function checks. It could miss functions because they are hidden in extra libs otherwise.
f5a2cf1... getopt_long resides in libiberty on many platforms.
76bc56c... Put inet_ntop() emulation in a seperate file.
d3cb144... Update comment for pa_lock_fd() to reflect that locks are mandatory on Windows.
160d886... Merge with trunk.
8258146... Generalise lstat fallback.
5fcbf04... Condense winsock includes and defines into one header.
9818d67... Make the tagstruct handling safe on machines with alignment restrictions.
8a32357... Make sure the data gets endianness conversion.
067c00f... Reversing incorrect commit.
72795fc... Use autoconf detected define for getgroups() type.
d5ce3ec... Ignore windows exe:s.
1b472f7... Solaris support.
6781628... The Windows sound interface module.
19d9fcb... Port to Windows. This is mostly glue layers for the poor POSIX support on Windows. A few notes
2f74bb9... Protect pthread.h with an ifdef.
bdc02f7... Protect sys/resource.h with an ifdef.
67833c2... Protect sched.h with ifdef.
57dccd2... Replace paths with defines.
2c4d42e... ctime_r() is not available everywhere.
e72bbdb... c was used before it was assigned.
010476f... Protect getuid() with an ifdef.
5ac2cb9... No regexp funtions are used in this file.
ecaf8d8... PATH_MAX is defined in limits.h.
983fdb3... Stub uses socket defines so include the header.
7aba34b... config.h should always be included so that necessary fixes can take effect.
2cf165d... ifdef-protect setpgid and setsid.
08bbfd2... Make it possible to disable caps support since it breaks fully static builds.
be2ba90... Add option to select which modules get linked in during static builds.
9550c8e... No need for conditional generation of symdef files.
971e370... Add possibility for linking semi-static executables (libtools definition of static).
e2495c7... We need explicit actions here.
268aebb... Protect sys/wait.h with an ifdef.
8f3c364... Make sure all socket headers are protected by ifdefs.
e28ce8c... Use pa_get_path_filename() instead of duplicating code.
29a5b85... Emulate poll() through select() where needed.
d3bc7b2... Fix test for mkfifo(). HAVE_MKFIFO is only generated as a config.h define by default.
5cd8703... Remove ftruncate test since we're not doing anything with the result.
a24102c... Fix indentation.
e9be6fa... Handle platforms that do not support the UNIX user/group database.
59aa6ca... There was a race condition here that caused latency calculation to fail miserably under some conditions.
ec87cb1... Fall back to signal() when sigaction isn't supported.
3ed983c... SIGQUIT is an optional signal.
b8859b4... Compiler warning about uninitialized variable.
3728854... Make sure the array is never too small.
b69d881... Fix printf string.
7192238... Old kernel headers didn't define the input_id structure. Therefore we cannot rely on it.
c5bee95... Fix correct type.
4deeaef... Don't include sys/socket.h in the header when we do not need to.
14474ae... Esound latency should not include buffer length. This added an extra second to esound already horrible latency calculations.
f0e8c65... Two variables with the same name causing corrupt strings.
4384d31... Fix warning.
ff49e63... inet_ntop can't be found on all platforms. Do a stupid emulation when not found.
456e256... Fix some compiler warnings about unused variables.
cd3691d... PIPE_BUF has nothing to do with the esound buffers.
13496bb... Handle when the platform doesn't have UNIX sockets.
3a3b4af... AF_UNIX and PF_UNIX is more portable than the _LOCAL equivalent.
dbad54a... Remove any warnings about incorrect type to setsockopt() (char* vs void*).
7dcf4e4... The standard declares some signals as optional. Make sure we handle this gracefully.
eacffc3... To access the new pa_gettimeofday() we need to include util.h.
8c5a75d... Syslog is not present on all platforms.
3996c5f... SIXCPU isn't present on all platforms. Replace cpulimit with dummy functions on those systems.
2ce05b2... Glob is not present on all systems.
70223ba... Fallbacks for systems that do not have getaddrinfo(). Does not handle IPv6 though.
3f2ac7e... We have a generic function for extracting the filename, let's use it.
f6b0f87... Remove unnecessary dependency on timeval definition.
687e2d7... Abstract the gettimeofday call into a utility function to ease porting.
70710e1... Check for OSS by looking for its header. Win32 isn't the only platform where OSS isn't supported.
11a4c67... Remove unused automake conditional.
e8c71ed... Since README is generated conditionally we must make sure there are no dependencies on it when it's not built.
1f11ee3... Big cleanup of the build structure.
22f6694... Creating branch for patches from Pierre Ossman
e1f008f... commit liboil porting changes
0c9873e... create a copy for liboil porting
-----------------------------------------------------------------------

Summary of changes:

-----------------------------------------------------------------------

commit e1f008f2a395422b0f1e0c931ea1550df853e6e4
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Sep 15 23:42:56 2005 +0000

    commit liboil porting changes
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/liboil-test@344 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/polyp/Makefile.am b/polyp/Makefile.am
index 009707c..18e1a2a 100644
--- a/polyp/Makefile.am
+++ b/polyp/Makefile.am
@@ -542,7 +542,7 @@ mainloop_test_SOURCES = mainloop-test.c
 mainloop_test_CFLAGS = $(AM_CFLAGS)
 mainloop_test_LDADD = $(AM_LDADD) libpolyp-mainloop- at PA_MAJORMINOR@.la libpolyp- at PA_MAJORMINOR@.la
 
-voltest_SOURCES = voltest.c sample.c
+voltest_SOURCES = voltest.c volume.c
 voltest_CFLAGS = $(AM_CFLAGS)
 voltest_LDADD = $(AM_LDADD)
 
diff --git a/polyp/channelmap.c b/polyp/channelmap.c
new file mode 100644
index 0000000..9787652
--- /dev/null
+++ b/polyp/channelmap.c
@@ -0,0 +1,140 @@
+/* $Id$ */
+
+/***
+  This file is part of polypaudio.
+ 
+  polypaudio 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.
+ 
+  polypaudio 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 polypaudio; 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 "channelmap.h"
+
+
+struct pa_channel_map* pa_channel_map_init(struct pa_channel_map *m) {
+    unsigned c;
+    assert(m);
+
+    for (c = 0; c < PA_CHANNELS_MAX; c++)
+        m->map[c] = PA_CHANNEL_POSITION_INVALID;
+
+    return m;
+}
+
+struct pa_channel_map* pa_channel_map_init_mono(struct pa_channel_map *m) {
+    assert(m);
+
+    pa_channel_map_init(m);
+    m->map[0] = PA_CHANNEL_POSITION_MONO;
+    return m;
+}
+
+struct pa_channel_map* pa_channel_map_init_stereo(struct pa_channel_map *m) {
+    assert(m);
+
+    pa_channel_map_init(m);
+    m->map[0] = PA_CHANNEL_POSITION_LEFT;
+    m->map[1] = PA_CHANNEL_POSITION_RIGHT;
+    return m;
+}
+
+struct pa_channel_map* pa_channel_map_init_auto(struct pa_channel_map *m, int channels) {
+    assert(m);
+    assert(channels > 0);
+
+    pa_channel_map_init(m);
+    
+    switch (channels) {
+        case 1:
+            m->map[0] = PA_CHANNEL_POSITION_MONO;
+            return m;
+
+        case 8:
+            m->mpa[6] = PA_CHANNEL_POSITION_SIDE_LEFT;
+            m->mpa[7] = PA_CHANNEL_POSITION_SIDE_RIGHT;
+            /* Fall through */
+            
+        case 6:
+            m->mpa[5] = PA_CHANNEL_POSITION_LFE;
+            /* Fall through */
+            
+        case 5:
+            m->map[4] = PA_CHANNEL_POSITION_FRONT_CENTER;
+            /* Fall through */
+            
+        case 4:
+            m->map[2] = PA_CHANNEL_POSITION_REAR_LEFT;
+            m->map[3] = PA_CHANNEL_POSITION_REAR_RIGHT;
+            /* Fall through */
+            
+        case 2:
+            m->map[0] = PA_CHANNEL_MAP_FRONT_LEFT;
+            m->map[1] = PA_CHANNEL_MAP_FRONT_RIGHT;
+            return m;
+            
+        default:
+            return NULL;
+    }
+}
+
+
+const char* pa_channel_position_to_string(pa_channel_position_t pos) {
+    const char *const 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] = "lfe",
+
+        [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"
+    };
+
+    if (pos < 0 || pos >= PA_CHANNEL_POSITION_MAX)
+        return NULL;
+
+    return table[pos];
+}
+
+int pa_channel_map_equal(struct pa_channel_map *a, struct pa_channel_map *b, int channels) {
+    char c;
+    
+    assert(a);
+    assert(b);
+    assert(channels > 0);
+
+    if (channels > PA_CHANNELS_MAX)
+        channels = PA_CHANNELS_MAX;
+
+    for (c = 0; c < channels; c++)
+        if (a->map[c] != b->map[c])
+            return 1;
+
+    return 0;
+}
diff --git a/polyp/channelmap.h b/polyp/channelmap.h
new file mode 100644
index 0000000..946247a
--- /dev/null
+++ b/polyp/channelmap.h
@@ -0,0 +1,75 @@
+#ifndef foochannelmaphfoo
+#define foochannelmaphfoo
+
+/* $Id$ */
+
+/***
+  This file is part of polypaudio.
+ 
+  polypaudio 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.
+ 
+  polypaudio 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 polypaudio; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+  USA.
+***/
+
+#include <polyp/sample.h>
+#include <polyp/cdecl.h>
+
+/** \file
+ * Constants and routines for channel mapping handling */
+
+PA_C_DECL_BEGIN
+
+typedef enum {
+    PA_CHANNEL_POSITION_INVALID = -1,
+    PA_CHANNEL_POSITION_MONO = 0,
+
+    PA_CHANNEL_POSITION_LEFT,
+    PA_CHANNEL_POSITION_RIGHT,
+
+    PA_CHANNEL_POSITION_FRONT_CENTER,
+    PA_CHANNEL_POSITION_FRONT_LEFT = PA_CHANNEL_POSITION_LEFT,
+    PA_CHANNEL_POSITION_FRONT_RIGHT = PA_CHANNEL_POSITION_RIGHT,
+
+    PA_CHANNEL_POSITION_REAR_CENTER,
+    PA_CHANNEL_POSITION_REAR_LEFT,
+    PA_CHANNEL_POSITION_REAR_RIGHT,
+    
+    PA_CHANNEL_POSITION_LFE,
+    PA_CHANNEL_POSITION_SUBWOOFER = PA_CHANNEL_LFE,
+    
+    PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER,
+    PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER,
+    
+    PA_CHANNEL_POSITION_SIDE_LEFT,
+    PA_CHANNEL_POSITION_SIDE_RIGHT,
+    
+    PA_CHANNEL_POSITION_MAX
+} pa_channel_position_t;
+
+struct {
+    pa_channel_position_t map[PA_CHANNELS_MAX];
+} pa_channel_map;
+
+struct pa_channel_map* pa_channel_map_init(struct pa_channel_map *m);
+struct pa_channel_map* pa_channel_map_init_mono(struct pa_channel_map *m);
+struct pa_channel_map* pa_channel_map_init_stereo(struct pa_channel_map *m);
+struct pa_channel_map* pa_channel_map_init_auto(struct pa_channel_map *m, int channels);
+
+const char* pa_channel_position_to_string(pa_channel_position_t pos);
+
+int pa_channel_map_equal(struct pa_channel_map *a, struct pa_channel_map *b, int channels)
+
+PA_C_DECL_END
+
+#endif
diff --git a/polyp/client.c b/polyp/client.c
index 8c7f480..dca7b52 100644
--- a/polyp/client.c
+++ b/polyp/client.c
@@ -33,16 +33,16 @@
 #include "subscribe.h"
 #include "log.h"
 
-struct pa_client *pa_client_new(struct pa_core *core, pa_typeid_t typeid, const char *name) {
+struct pa_client *pa_client_new(struct pa_core *core, const char *name, const char *driver) {
     struct pa_client *c;
     int r;
     assert(core);
 
     c = pa_xmalloc(sizeof(struct pa_client));
     c->name = pa_xstrdup(name);
+    c->driver = pa_xstrdup(driver);
     c->owner = NULL;
     c->core = core;
-    c->typeid = typeid;
 
     c->kill = NULL;
     c->userdata = NULL;
@@ -68,8 +68,8 @@ void pa_client_free(struct pa_client *c) {
     pa_log_info(__FILE__": freed %u \"%s\"\n", 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);
     pa_xfree(c);
-
 }
 
 void pa_client_kill(struct pa_client *c) {
diff --git a/polyp/client.h b/polyp/client.h
index 2a3a09e..082dc29 100644
--- a/polyp/client.h
+++ b/polyp/client.h
@@ -32,17 +32,16 @@
 
 struct pa_client {
     uint32_t index;
-    pa_typeid_t typeid;
 
     struct pa_module *owner;
-    char *name;
+    char *name, *driver;
     struct pa_core *core;
 
     void (*kill)(struct pa_client *c);
     void *userdata;
 };
 
-struct pa_client *pa_client_new(struct pa_core *c, pa_typeid_t typeid, const char *name);
+struct pa_client *pa_client_new(struct pa_core *c, const char *name, const char *driver);
 
 /* This function should be called only by the code that created the client */
 void pa_client_free(struct pa_client *c);
diff --git a/polyp/resampler.c b/polyp/resampler.c
index 28e4920..d3165c9 100644
--- a/polyp/resampler.c
+++ b/polyp/resampler.c
@@ -35,11 +35,12 @@
 
 struct pa_resampler {
     struct pa_sample_spec i_ss, o_ss;
+    struct pa_channel_map i_cm, o_cm;
     size_t i_fz, o_fz;
     struct pa_memblock_stat *memblock_stat;
     void *impl_data;
     int channels;
-    enum pa_resample_method resample_method;
+    pa_resample_method_t resample_method;
 
     void (*impl_free)(struct pa_resampler *r);
     void (*impl_set_input_rate)(struct pa_resampler *r, uint32_t rate);
@@ -62,7 +63,14 @@ struct impl_trivial {
 static int libsamplerate_init(struct pa_resampler*r);
 static int trivial_init(struct pa_resampler*r);
 
-struct pa_resampler* pa_resampler_new(const struct pa_sample_spec *a, const struct pa_sample_spec *b, struct pa_memblock_stat *s, enum pa_resample_method resample_method) {
+struct pa_resampler* pa_resampler_new(
+    const struct pa_sample_spec *a,
+    const struct pa_channel_map *am,
+    const struct pa_sample_spec *b,
+    const struct pa_channel_map *bm,
+    struct pa_memblock_stat *s,
+    pa_resample_method_t resample_method) {
+    
     struct pa_resampler *r = NULL;
     assert(a && b && pa_sample_spec_valid(a) && pa_sample_spec_valid(b) && resample_method != PA_RESAMPLER_INVALID);
 
@@ -82,6 +90,17 @@ struct pa_resampler* pa_resampler_new(const struct pa_sample_spec *a, const stru
     r->i_ss = *a;
     r->o_ss = *b;
 
+    if (am)
+        r->i_cm = *am;
+    else
+        pa_channel_map_init_auto(&r->i_cm, r->i_ss.channels);
+
+    if (bm)
+        r->o_cm = *bm;
+    else
+        pa_channel_map_init_auto(&r->o_cm, r->o_ss.channels);
+    
+
     r->i_fz = pa_frame_size(a);
     r->o_fz = pa_frame_size(b);
 
@@ -90,7 +109,7 @@ struct pa_resampler* pa_resampler_new(const struct pa_sample_spec *a, const stru
         r->channels = b->channels;
     
     /* Choose implementation */
-    if (a->channels != b->channels || a->format != b->format || resample_method != PA_RESAMPLER_TRIVIAL) {
+    if (a->channels != b->channels || a->format != b->format || resample_method != PA_RESAMPLER_TRIVIAL || !pa_channel_map_equal(&r->i_cm, &r->o_cm)) {
         /* Use the libsamplerate based resampler for the complicated cases */
         if (resample_method == PA_RESAMPLER_TRIVIAL)
             r->resample_method = PA_RESAMPLER_SRC_ZERO_ORDER_HOLD;
@@ -141,31 +160,11 @@ size_t pa_resampler_request(struct pa_resampler *r, size_t out_length) {
     return (((out_length / r->o_fz)*r->i_ss.rate)/r->o_ss.rate) * r->i_fz;
 }
 
-enum pa_resample_method pa_resampler_get_method(struct pa_resampler *r) {
+pa_resample_method_t pa_resampler_get_method(struct pa_resampler *r) {
     assert(r);
     return r->resample_method;
 }
 
-/* Parse a libsamplrate compatible resampling implementation */
-enum pa_resample_method pa_parse_resample_method(const char *string) {
-    assert(string);
-
-    if (!strcmp(string, "src-sinc-best-quality"))
-        return PA_RESAMPLER_SRC_SINC_BEST_QUALITY;
-    else if (!strcmp(string, "src-sinc-medium-quality"))
-        return PA_RESAMPLER_SRC_SINC_MEDIUM_QUALITY;
-    else if (!strcmp(string, "src-sinc-fastest"))
-        return PA_RESAMPLER_SRC_SINC_FASTEST;
-    else if (!strcmp(string, "src-zero-order-hold"))
-        return PA_RESAMPLER_SRC_ZERO_ORDER_HOLD;
-    else if (!strcmp(string, "src-linear"))
-        return PA_RESAMPLER_SRC_LINEAR;
-    else if (!strcmp(string, "trivial"))
-        return PA_RESAMPLER_TRIVIAL;
-    else
-        return PA_RESAMPLER_INVALID;
-}
-
 /*** libsamplerate based implementation ***/
 
 static void libsamplerate_free(struct pa_resampler *r) {
@@ -181,6 +180,70 @@ static void libsamplerate_free(struct pa_resampler *r) {
     pa_xfree(i);
 }
 
+static void calc_map_table(struct pa_resampler *r) {
+    struct impl_libsamplerate *u;
+    unsigned oc;
+    assert(r);
+    assert(r->impl_data);
+
+    u = r->impl_data;
+
+    if ((u->map_required = (!pa_channel_map_equal(&r->i_cm, r->o_cm) || r->i_ss.channels != r->o_ss.channels))) {
+
+        memset(u->map_table, -1, sizeof(u->map_table));
+
+        for (oc = 0; oc < r->o_iss.channels; oc++) {
+            unsigned i = 0, ic;
+
+            for (ic = 0; ic < r->i_ss.channels; ic++) {
+                pa_channel_position_t a, b;
+                
+                a = r->i_cm.map[ic];
+                b = r->o_cm.map[oc];
+                
+                if (a == b ||
+                    (a == PA_CHANNEL_POSITION_MONO && b == PA_CHANNEL_POSITION_LEFT) ||
+                    (a == PA_CHANNEL_POSITION_MONO && b == PA_CHANNEL_POSITION_RIGHT) ||
+                    (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;
+            }
+        }
+    }
+}
+
+
+static float *remap_to_float(struct pa_resampler *r, const struct pa_memchunk *in) {
+    unsigned nsamples;
+    struct impl_libsamplerate *u;
+    assert(r);
+    assert(r->impl_data);
+
+    u = r->impl_data;
+
+    nsamples = in->length / u->i_fz;
+
+    if () {
+
+        if (u->i_buf_samples < nsamples)
+            u->i_buf = pa_xrealloc(i->i_buf, sizeof(float) * (i->i_buf_samples = nsamples));
+
+        i->to_float32ne_func(ff_ins, (uint8_t*) in->memblock->data+in->index, i_nchannels, i->i_buf);
+
+    }
+
+    
+}
+
+
+static void libsamplerate_run(struct pa_resampler *r, const struct pa_memchunk *in, struct pa_memchunk *out) {
+
+    
+    
+}
+
+
 static void libsamplerate_run(struct pa_resampler *r, const struct pa_memchunk *in, struct pa_memchunk *out) {
     unsigned i_nchannels, o_nchannels, ins, ons, eff_ins, eff_ons;
     float *cbuf;
@@ -191,7 +254,8 @@ static void libsamplerate_run(struct pa_resampler *r, const struct pa_memchunk *
     /* How many input samples? */
     ins = in->length/r->i_fz;
 
-/*     pa_log("%u / %u = %u\n", in->length, r->i_fz, ins); */
+
+    /*     pa_log("%u / %u = %u\n", in->length, r->i_fz, ins); */
 
     /* How much space for output samples? */
     if (i->src_state)
@@ -395,7 +459,7 @@ static int trivial_init(struct pa_resampler*r) {
     return 0;
 }
 
-const char *pa_resample_method_to_string(enum pa_resample_method m) {
+const char *pa_resample_method_to_string(pa_resample_method_t m) {
     static const char * const resample_methods[] = {
         "src-sinc-best-quality",
         "src-sinc-medium-quality",
@@ -410,3 +474,23 @@ const char *pa_resample_method_to_string(enum pa_resample_method m) {
 
     return resample_methods[m];
 }
+
+pa_resample_method_t pa_parse_resample_method(const char *string) {
+    assert(string);
+
+    if (!strcmp(string, "src-sinc-best-quality"))
+        return PA_RESAMPLER_SRC_SINC_BEST_QUALITY;
+    else if (!strcmp(string, "src-sinc-medium-quality"))
+        return PA_RESAMPLER_SRC_SINC_MEDIUM_QUALITY;
+    else if (!strcmp(string, "src-sinc-fastest"))
+        return PA_RESAMPLER_SRC_SINC_FASTEST;
+    else if (!strcmp(string, "src-zero-order-hold"))
+        return PA_RESAMPLER_SRC_ZERO_ORDER_HOLD;
+    else if (!strcmp(string, "src-linear"))
+        return PA_RESAMPLER_SRC_LINEAR;
+    else if (!strcmp(string, "trivial"))
+        return PA_RESAMPLER_TRIVIAL;
+    else
+        return PA_RESAMPLER_INVALID;
+}
+
diff --git a/polyp/resampler.h b/polyp/resampler.h
index 0109e79..ec6a808 100644
--- a/polyp/resampler.h
+++ b/polyp/resampler.h
@@ -30,7 +30,7 @@
 
 struct pa_resampler;
 
-enum pa_resample_method {
+typedef enum {
     PA_RESAMPLER_INVALID                 = -1,
     PA_RESAMPLER_SRC_SINC_BEST_QUALITY   = SRC_SINC_BEST_QUALITY,
     PA_RESAMPLER_SRC_SINC_MEDIUM_QUALITY = SRC_SINC_MEDIUM_QUALITY,
@@ -39,9 +39,16 @@ enum pa_resample_method {
     PA_RESAMPLER_SRC_LINEAR              = SRC_LINEAR,
     PA_RESAMPLER_TRIVIAL,
     PA_RESAMPLER_MAX
-};
+} pa_resample_method_t;
+
+struct pa_resampler* pa_resampler_new(
+    const struct pa_sample_spec *a,
+    const struct pa_channel_map *am,
+    const struct pa_sample_spec *b,
+    const struct pa_channel_map *bm,
+    struct pa_memblock_stat *s,
+    pa_resample_method_t resample_method);
 
-struct pa_resampler* pa_resampler_new(const struct pa_sample_spec *a, const struct pa_sample_spec *b, struct pa_memblock_stat *s, int resample_method);
 void pa_resampler_free(struct pa_resampler *r);
 
 /* Returns the size of an input memory block which is required to return the specified amount of output data */
@@ -54,12 +61,12 @@ void pa_resampler_run(struct pa_resampler *r, const struct pa_memchunk *in, stru
 void pa_resampler_set_input_rate(struct pa_resampler *r, uint32_t rate);
 
 /* Return the resampling method of the resampler object */
-enum pa_resample_method pa_resampler_get_method(struct pa_resampler *r);
+pa_resample_method_t pa_resampler_get_method(struct pa_resampler *r);
 
 /* Try to parse the resampler method */
-enum pa_resample_method pa_parse_resample_method(const char *string);
+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(enum pa_resample_method m);
+const char *pa_resample_method_to_string(pa_resample_method_t m);
 
 #endif
diff --git a/polyp/sample-util.c b/polyp/sample-util.c
index d521afe..44cacfc 100644
--- a/polyp/sample-util.c
+++ b/polyp/sample-util.c
@@ -65,30 +65,37 @@ void pa_silence_memory(void *p, size_t length, const struct pa_sample_spec *spec
     memset(p, c, length);
 }
 
-size_t pa_mix(struct pa_mix_info channels[], unsigned nchannels, void *data, size_t length, const struct pa_sample_spec *spec, pa_volume_t volume) {
-    assert(channels && data && length && spec);
+size_t pa_mix(struct pa_mix_info streams[],
+              unsigned nstreams,
+              void *data,
+              size_t length,
+              const struct pa_sample_spec *spec,
+              const struct pa_cvolume *volume) {
+    
+    assert(streams && data && length && spec);
     
     if (spec->format == PA_SAMPLE_S16NE) {
         size_t d;
+        unsigned channel = 0;
         
         for (d = 0;; d += sizeof(int16_t)) {
-            unsigned c;
+            unsigned i;
             int32_t sum = 0;
             
             if (d >= length)
                 return d;
             
-            for (c = 0; c < nchannels; c++) {
+            for (i = 0; i < nstreams; i++) {
                 int32_t v;
-                pa_volume_t cvolume = channels[c].volume;
+                pa_volume_t cvolume = streams[i].volume.values[channel];
                 
-                if (d >= channels[c].chunk.length)
+                if (d >= streams[i].chunk.length)
                     return d;
                 
                 if (cvolume == PA_VOLUME_MUTED)
                     v = 0;
                 else {
-                    v = *((int16_t*) ((uint8_t*) channels[c].chunk.memblock->data + channels[c].chunk.index + d));
+                    v = *((int16_t*) ((uint8_t*) streams[i].chunk.memblock->data + streams[i].chunk.index + d));
                     
                     if (cvolume != PA_VOLUME_NORM) {
                         v *= cvolume;
@@ -111,28 +118,32 @@ size_t pa_mix(struct pa_mix_info channels[], unsigned nchannels, void *data, siz
             
             *((int16_t*) data) = sum;
             data = (uint8_t*) data + sizeof(int16_t);
+
+            if (++channel >= spec->channels)
+                channel = 0;
         }
     } else if (spec->format == PA_SAMPLE_U8) {
         size_t d;
+        unsigned channel = 0;
         
         for (d = 0;; d ++) {
             int32_t sum = 0;
-            unsigned c;
+            unsigned i;
             
             if (d >= length)
                 return d;
             
-            for (c = 0; c < nchannels; c++) {
+            for (i = 0; i < nstreams; i++) {
                 int32_t v;
-                pa_volume_t cvolume = channels[c].volume;
+                pa_volume_t cvolume = streams[i].volume.values[channel];
                 
-                if (d >= channels[c].chunk.length)
+                if (d >= streams[i].chunk.length)
                     return d;
                 
                 if (cvolume == PA_VOLUME_MUTED)
                     v = 0;
                 else {
-                    v = (int32_t) *((uint8_t*) channels[c].chunk.memblock->data + channels[c].chunk.index + d) - 0x80;
+                    v = (int32_t) *((uint8_t*) streams[i].chunk.memblock->data + streams[i].chunk.index + d) - 0x80;
                     
                     if (cvolume != PA_VOLUME_NORM) {
                         v *= cvolume;
@@ -155,29 +166,33 @@ size_t pa_mix(struct pa_mix_info channels[], unsigned nchannels, void *data, siz
             
             *((uint8_t*) data) = (uint8_t) (sum + 0x80);
             data = (uint8_t*) data + 1;
+
+            if (++channel >= spec->channels)
+                channel = 0;
         }
         
     } else if (spec->format == PA_SAMPLE_FLOAT32NE) {
         size_t d;
+        unsigned channel = 0;
         
         for (d = 0;; d += sizeof(float)) {
             float_t sum = 0;
-            unsigned c;
+            unsigned i;
             
             if (d >= length)
                 return d;
             
-            for (c = 0; c < nchannels; c++) {
+            for (i = 0; i < nstreams; i++) {
                 float v;
-                pa_volume_t cvolume = channels[c].volume;
+                pa_volume_t cvolume = streams[i].volume.values[channel];
                 
-                if (d >= channels[c].chunk.length)
+                if (d >= streams[i].chunk.length)
                     return d;
                 
                 if (cvolume == PA_VOLUME_MUTED)
                     v = 0;
                 else {
-                    v = *((float*) ((uint8_t*) channels[c].chunk.memblock->data + channels[c].chunk.index + d));
+                    v = *((float*) ((uint8_t*) streams[i].chunk.memblock->data + streams[i].chunk.index + d));
                     
                     if (cvolume != PA_VOLUME_NORM)
                         v = v*cvolume/PA_VOLUME_NORM;
@@ -196,6 +211,9 @@ size_t pa_mix(struct pa_mix_info channels[], unsigned nchannels, void *data, siz
             
             *((float*) data) = sum;
             data = (uint8_t*) data + sizeof(float);
+
+            if (++channel >= spec->channels)
+                channel = 0;
         }
     } else {
         abort();
@@ -203,13 +221,14 @@ size_t pa_mix(struct pa_mix_info channels[], unsigned nchannels, void *data, siz
 }
 
 
-void pa_volume_memchunk(struct pa_memchunk*c, const struct pa_sample_spec *spec, pa_volume_t volume) {
+void pa_volume_memchunk(struct pa_memchunk*c, const struct pa_sample_spec *spec, const struct pa_cvolume *volume) {
     assert(c && spec && (c->length % pa_frame_size(spec) == 0));
+    assert(volume);
 
-    if (volume == PA_VOLUME_NORM)
+    if (pa_cvolume_channels_equal_to(volume, spec->channels, PA_VOLUME_NORM))
         return;
 
-    if (volume == PA_VOLUME_MUTED) {
+    if (pa_cvolume_channels_equal_to(volume, spec->channels, PA_VOLUME_MUTED)) {
         pa_silence_memchunk(c, spec);
         return;
     }
@@ -217,26 +236,31 @@ void pa_volume_memchunk(struct pa_memchunk*c, const struct pa_sample_spec *spec,
     if (spec->format == PA_SAMPLE_S16NE) {
         int16_t *d;
         size_t n;
+        unsigned c = 0;
         
         for (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);
             
-            t *= volume;
+            t *= volume->values[c];
             t /= PA_VOLUME_NORM;
             
             if (t < -0x8000) t = -0x8000;
             if (t > 0x7FFF) t = 0x7FFF;
             
             *d = (int16_t) t;
+
+            if (++c >= spec->channels)
+                c = 0;
         }
     } else if (spec->format == PA_SAMPLE_U8) {
         uint8_t *d;
         size_t n;
+        unsigned c = 0;
 
         for (d = (uint8_t*) c->memblock->data + c->index, n = c->length; n > 0; d++, n--) {
             int32_t t = (int32_t) *d - 0x80;
 
-            t *= volume;
+            t *= volume->values[c];
             t /= PA_VOLUME_NORM;
 
             if (t < -0x80) t = -0x80;
@@ -244,21 +268,27 @@ void pa_volume_memchunk(struct pa_memchunk*c, const struct pa_sample_spec *spec,
 
             *d = (uint8_t) (t + 0x80);
             
+            if (++c >= spec->channels)
+                c = 0;
         }
     } else if (spec->format == PA_SAMPLE_FLOAT32NE) {
         float *d;
         size_t n;
+        unsigned c = 0;
 
         for (d = (float*) ((uint8_t*) c->memblock->data+c->index), n = c->length/sizeof(float); n > 0; d++, n--) {
             float t = *d;
 
-            t *= volume;
+            t *= volume->values[c];
             t /= PA_VOLUME_NORM;
 
             if (t < -1) t = -1;
             if (t > 1) t = 1;
 
             *d = t;
+
+            if (++c >= spec->channels)
+                c = 0;
         }
         
     } else {
diff --git a/polyp/sample-util.h b/polyp/sample-util.h
index aafdda6..f0c71b8 100644
--- a/polyp/sample-util.h
+++ b/polyp/sample-util.h
@@ -33,12 +33,19 @@ void pa_silence_memory(void *p, size_t length, const struct pa_sample_spec *spec
 
 struct pa_mix_info {
     struct pa_memchunk chunk;
-    pa_volume_t volume;
+    struct pa_cvolume cvolume;
     void *userdata;
 };
 
-size_t pa_mix(struct pa_mix_info channels[], unsigned nchannels, void *data, size_t length, const struct pa_sample_spec *spec, pa_volume_t volume);
+size_t pa_mix(const struct pa_mix_info channels[],
+              unsigned nchannels,
+              void *data,
+              size_t length,
+              const struct pa_sample_spec *spec,
+              const struct pa_cvolume *volume);
 
-void pa_volume_memchunk(struct pa_memchunk*c, const struct pa_sample_spec *spec, pa_volume_t volume);
+void pa_volume_memchunk(struct pa_memchunk*c,
+                        const struct pa_sample_spec *spec,
+                        const struct pa_cvolume *volume);
 
 #endif
diff --git a/polyp/sample.c b/polyp/sample.c
index f9d0c45..d38cc1b 100644
--- a/polyp/sample.c
+++ b/polyp/sample.c
@@ -69,10 +69,11 @@ pa_usec_t pa_bytes_to_usec(uint64_t length, const struct pa_sample_spec *spec) {
 int pa_sample_spec_valid(const struct pa_sample_spec *spec) {
     assert(spec);
 
-    if (spec->rate <= 0 || spec->channels <= 0)
-        return 0;
-
-    if (spec->format >= PA_SAMPLE_MAX || spec->format < 0)
+    if (spec->rate <= 0 ||
+        spec->channels <= 0 ||
+        spec->channels >= PA_CHANNELS_MAX ||
+        spec->format >= PA_SAMPLE_MAX ||
+        spec->format < 0)
         return 0;
 
     return 1;
@@ -86,13 +87,13 @@ int pa_sample_spec_equal(const struct pa_sample_spec*a, const struct pa_sample_s
 
 const char *pa_sample_format_to_string(enum pa_sample_format f) {
     static const char* const table[]= {
-        [PA_SAMPLE_U8] = "U8",
-        [PA_SAMPLE_ALAW] = "ALAW",
-        [PA_SAMPLE_ULAW] = "ULAW",
-        [PA_SAMPLE_S16LE] = "S16LE",
-        [PA_SAMPLE_S16BE] = "S16BE",
-        [PA_SAMPLE_FLOAT32LE] = "FLOAT32LE",
-        [PA_SAMPLE_FLOAT32BE] = "FLOAT32BE",
+        [PA_SAMPLE_U8] = "u8",
+        [PA_SAMPLE_ALAW] = "aLaw",
+        [PA_SAMPLE_ULAW] = "uLaw",
+        [PA_SAMPLE_S16LE] = "s16le",
+        [PA_SAMPLE_S16BE] = "s16be",
+        [PA_SAMPLE_FLOAT32LE] = "float32le",
+        [PA_SAMPLE_FLOAT32BE] = "float32be",
     };
 
     if (f >= PA_SAMPLE_MAX)
@@ -112,43 +113,6 @@ char *pa_sample_spec_snprint(char *s, size_t l, const struct pa_sample_spec *spe
     return s;
 }
 
-pa_volume_t pa_volume_multiply(pa_volume_t a, pa_volume_t b) {
-    uint64_t p = a;
-    p *= b;
-    p /= PA_VOLUME_NORM;
-
-    return (pa_volume_t) p;
-}
-
-pa_volume_t pa_volume_from_dB(double f) {
-    if (f <= PA_DECIBEL_MININFTY)
-        return PA_VOLUME_MUTED;
-
-    return (pa_volume_t) (pow(10, f/20)*PA_VOLUME_NORM);
-}
-
-double pa_volume_to_dB(pa_volume_t v) {
-    if (v == PA_VOLUME_MUTED)
-        return PA_DECIBEL_MININFTY;
-
-    return 20*log10((double) v/PA_VOLUME_NORM);
-}
-
-#define USER_DECIBEL_RANGE 30
-
-double pa_volume_to_user(pa_volume_t v) {
-    double dB = pa_volume_to_dB(v);
-
-    return dB < -USER_DECIBEL_RANGE ? 0 : dB/USER_DECIBEL_RANGE+1;
-}
-
-pa_volume_t pa_volume_from_user(double v) {
-
-    if (v <= 0)
-        return PA_VOLUME_MUTED;
-    
-    return pa_volume_from_dB((v-1)*USER_DECIBEL_RANGE);
-}
 
 void pa_bytes_snprint(char *s, size_t l, unsigned v) {
     if (v >= ((unsigned) 1024)*1024*1024)
diff --git a/polyp/sample.h b/polyp/sample.h
index 0494c7d..c4ccd3d 100644
--- a/polyp/sample.h
+++ b/polyp/sample.h
@@ -33,8 +33,11 @@
 
 PA_C_DECL_BEGIN
 
+/* Maximum allowed channels */
+#define PA_CHANNELS_MAX 16
+
 /** Sample format */
-enum pa_sample_format {
+typedef enum {
     PA_SAMPLE_U8,              /**< Unsigned 8 Bit PCM */
     PA_SAMPLE_ALAW,            /**< 8 Bit a-Law */
     PA_SAMPLE_ULAW,            /**< 8 Bit mu-Law */
@@ -44,7 +47,7 @@ enum pa_sample_format {
     PA_SAMPLE_FLOAT32BE,       /**< 32 Bit IEEE floating point, big endian, range -1..1 */
     PA_SAMPLE_MAX,             /**< Upper limit of valid sample types */
     PA_SAMPLE_INVALID = -1     /**< An invalid value */
-};
+} pa_sample_format_t;
 
 #ifdef WORDS_BIGENDIAN
 /** Signed 16 Bit PCM, native endian */
@@ -63,7 +66,7 @@ enum pa_sample_format {
 
 /** A sample format and attribute specification */
 struct pa_sample_spec {
-    enum pa_sample_format format;  /**< The sample format */
+    pa_sample_format_t format;     /**< The sample format */
     uint32_t rate;                 /**< The sample rate. (e.g. 44100) */
     uint8_t channels;              /**< Audio channels. (1 for mono, 2 for stereo, ...) */
 };
@@ -87,7 +90,10 @@ int pa_sample_spec_valid(const struct pa_sample_spec *spec);
 int pa_sample_spec_equal(const struct pa_sample_spec*a, const struct pa_sample_spec*b);
 
 /* Return a descriptive string for the specified sample format. \since 0.8 */
-const char *pa_sample_format_to_string(enum pa_sample_format f);
+const char *pa_sample_format_to_string(pa_sample_format_t f);
+
+/** Parse a sample format text. Inverse of pa_sample_format_to_string() */
+pa_sample_format_t pa_parse_sample_format(const char *format);
 
 /** Maximum required string length for pa_sample_spec_snprint() */
 #define PA_SAMPLE_SPEC_SNPRINT_MAX 32
@@ -95,43 +101,9 @@ const char *pa_sample_format_to_string(enum pa_sample_format f);
 /** Pretty print a sample type specification to a string */
 char* pa_sample_spec_snprint(char *s, size_t l, const struct pa_sample_spec *spec);
 
-/** Volume specification: 0: silence; < 256: diminished volume; 256: normal volume; > 256 amplified volume */
-typedef uint32_t pa_volume_t;
-
-/** Normal volume (100%) */
-#define PA_VOLUME_NORM (0x100)
-
-/** Muted volume (0%) */
-#define PA_VOLUME_MUTED (0)
-
-/** Multiply two volumes specifications, return the result. This uses PA_VOLUME_NORM as neutral element of multiplication. */
-pa_volume_t pa_volume_multiply(pa_volume_t a, pa_volume_t b);
-
-/** Convert volume from decibel to linear level. \since 0.4 */
-pa_volume_t pa_volume_from_dB(double f);
-
-/** Convert volume from linear level to decibel.  \since 0.4 */
-double pa_volume_to_dB(pa_volume_t v);
-
-/** Convert volume to scaled value understandable by the user (between 0 and 1). \since 0.6 */
-double pa_volume_to_user(pa_volume_t v);
-
-/** Convert user volume to polypaudio volume. \since 0.6 */
-pa_volume_t pa_volume_from_user(double v);
-
-#ifdef INFINITY
-#define PA_DECIBEL_MININFTY (-INFINITY)
-#else
-/** This value is used as minus infinity when using pa_volume_{to,from}_dB(). \since 0.4 */
-#define PA_DECIBEL_MININFTY (-200)
-#endif
-
 /** Pretty print a byte size value. (i.e. "2.5 MB") */
 void pa_bytes_snprint(char *s, size_t l, unsigned v);
 
-/** Parse a sample format text. Inverse of pa_sample_format_to_string() */
-enum pa_sample_format pa_parse_sample_format(const char *format);
-
 PA_C_DECL_END
 
 #endif
diff --git a/polyp/sink-input.c b/polyp/sink-input.c
index 3e7fdf7..40ee705 100644
--- a/polyp/sink-input.c
+++ b/polyp/sink-input.c
@@ -36,12 +36,23 @@
 
 #define CONVERT_BUFFER_LENGTH 4096
 
-struct pa_sink_input* pa_sink_input_new(struct pa_sink *s, pa_typeid_t typeid, const char *name, const struct pa_sample_spec *spec, int variable_rate, int resample_method) {
+struct pa_sink_input* pa_sink_input_new(
+    struct pa_sink *s,
+    const char *name,
+    const char *driver,
+    const struct pa_sample_spec *spec,
+    const struct pa_channel_map *map,
+    int variable_rate,
+    int resample_method) {
+    
     struct pa_sink_input *i;
     struct pa_resampler *resampler = NULL;
     int r;
     char st[256];
-    assert(s && spec && s->state == PA_SINK_RUNNING);
+
+    assert(s);
+    assert(spec);
+    assert(s->state == PA_SINK_RUNNING);
 
     if (pa_idxset_ncontents(s->inputs) >= PA_MAX_INPUTS_PER_SINK) {
         pa_log(__FILE__": Failed to create sink input: too many inputs per sink.\n");
@@ -52,18 +63,23 @@ struct pa_sink_input* pa_sink_input_new(struct pa_sink *s, pa_typeid_t typeid, c
         resample_method = s->core->resample_method;
     
     if (variable_rate || !pa_sample_spec_equal(spec, &s->sample_spec))
-        if (!(resampler = pa_resampler_new(spec, &s->sample_spec, s->core->memblock_stat, resample_method)))
+        if (!(resampler = pa_resampler_new(spec, map, &s->sample_spec, &s->channel_map, s->core->memblock_stat, resample_method)))
             return NULL;
     
     i = pa_xmalloc(sizeof(struct pa_sink_input));
     i->ref = 1;
     i->state = PA_SINK_INPUT_RUNNING;
     i->name = pa_xstrdup(name);
-    i->typeid = typeid;
+    i->driver = pa_xstrdup(driver);
     i->client = NULL;
     i->owner = NULL;
     i->sink = s;
+
     i->sample_spec = *spec;
+    if (map)
+        i->channel_map = *map;
+    else
+        pa_channel_map_init_auto(&i->channel_map, spec->channels);
 
     i->peek = NULL;
     i->drop = NULL;
@@ -72,7 +88,7 @@ struct pa_sink_input* pa_sink_input_new(struct pa_sink *s, pa_typeid_t typeid, c
     i->userdata = NULL;
     i->underrun = NULL;
 
-    i->volume = PA_VOLUME_NORM;
+    pa_cvolume_reset(&i->volume);
     i->playing = 0;
 
     i->resampled_chunk.memblock = NULL;
@@ -124,6 +140,7 @@ static void sink_input_free(struct pa_sink_input* i) {
         pa_resampler_free(i->resampler);
 
     pa_xfree(i->name);
+    pa_xfree(i->driver);
     pa_xfree(i);
 }
 
@@ -234,15 +251,22 @@ void pa_sink_input_drop(struct pa_sink_input *i, const struct pa_memchunk *chunk
     }
 }
 
-void pa_sink_input_set_volume(struct pa_sink_input *i, pa_volume_t volume) {
+void pa_sink_input_set_volume(struct pa_sink_input *i, const struct pa_cvolume *volume) {
     assert(i && i->sink && i->sink->core && i->ref >= 1);
 
-    if (i->volume != volume) {
-        i->volume = volume;
+    if (!pa_cvolume_equal(&i->volume, volume)) {
+        i->volume = *volume;
         pa_subscription_post(i->sink->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index);
     }
 }
 
+const struct pa_cvolume * pa_sink_input_get_volume(struct pa_sink_input *i) {
+    assert(i);
+    assert(i->ref >= 1);
+
+    return &i->volume;
+}
+
 void pa_sink_input_cork(struct pa_sink_input *i, int b) {
     int n;
     assert(i && i->ref >= 1);
diff --git a/polyp/sink-input.h b/polyp/sink-input.h
index 83abe53..90723c0 100644
--- a/polyp/sink-input.h
+++ b/polyp/sink-input.h
@@ -31,25 +31,25 @@
 #include "module.h"
 #include "client.h"
 
-enum pa_sink_input_state {
+typedef enum {
     PA_SINK_INPUT_RUNNING,
     PA_SINK_INPUT_CORKED,
     PA_SINK_INPUT_DISCONNECTED
-};
+} pa_sink_input_state_t;
 
 struct pa_sink_input {
     int ref;
-    enum pa_sink_input_state state;
-    
     uint32_t index;
-    pa_typeid_t typeid;
-
-    char *name;
+    pa_sink_input_state_t state;
+    
+    char *name, *driver;
     struct pa_module *owner;
     struct pa_client *client;
     struct pa_sink *sink;
+    
     struct pa_sample_spec sample_spec;
-    uint32_t volume;
+    struct pa_channel_map channel_map;
+    struct pa_cvolume volume;
     
     int (*peek) (struct pa_sink_input *i, struct pa_memchunk *chunk);
     void (*drop) (struct pa_sink_input *i, const struct pa_memchunk *chunk, size_t length);
@@ -65,7 +65,15 @@ struct pa_sink_input {
     struct pa_resampler *resampler;
 };
 
-struct pa_sink_input* pa_sink_input_new(struct pa_sink *s, pa_typeid_t typeid, const char *name, const struct pa_sample_spec *spec, int variable_rate, int resample_method);
+struct pa_sink_input* pa_sink_input_new(
+    struct pa_sink *s,
+    const char *name,
+    const char *driver,
+    const struct pa_sample_spec *spec,
+    const struct pa_channel_map *map,
+    int variable_rate,
+    int resample_method);
+
 void pa_sink_input_unref(struct pa_sink_input* i);
 struct pa_sink_input* pa_sink_input_ref(struct pa_sink_input* i);
 
@@ -80,7 +88,8 @@ pa_usec_t pa_sink_input_get_latency(struct pa_sink_input *i);
 int pa_sink_input_peek(struct pa_sink_input *i, struct pa_memchunk *chunk);
 void pa_sink_input_drop(struct pa_sink_input *i, const struct pa_memchunk *chunk, size_t length);
 
-void pa_sink_input_set_volume(struct pa_sink_input *i, pa_volume_t volume);
+void pa_sink_input_set_volume(struct pa_sink_input *i, const struct pa_cvolume *volume);
+const struct pa_cvolume *volume pa_sink_input_get_volume(struct pa_sink_input *i);
 
 void pa_sink_input_cork(struct pa_sink_input *i, int b);
 
diff --git a/polyp/sink.c b/polyp/sink.c
index 481e5cf..3b07472 100644
--- a/polyp/sink.c
+++ b/polyp/sink.c
@@ -39,12 +39,23 @@
 
 #define MAX_MIX_CHANNELS 32
 
-struct pa_sink* pa_sink_new(struct pa_core *core, pa_typeid_t typeid, const char *name, int fail, const struct pa_sample_spec *spec) {
+struct pa_sink* pa_sink_new(
+    struct pa_core *core,
+    const char *name,
+    const char *driver,
+    int fail,
+    const struct pa_sample_spec *spec,
+    const struct pa_channel_map *map) {
+    
     struct pa_sink *s;
     char *n = NULL;
     char st[256];
     int r;
-    assert(core && name && *name && spec);
+
+    assert(core);
+    assert(name);
+    assert(*name);
+    assert(spec);
 
     s = pa_xmalloc(sizeof(struct pa_sink));
 
@@ -53,31 +64,41 @@ struct pa_sink* pa_sink_new(struct pa_core *core, pa_typeid_t typeid, const char
         return NULL;
     }
 
-    s->name = pa_xstrdup(name);
-    s->description = NULL;
-    s->typeid = typeid;
-
     s->ref = 1;
+    s->core = core;
+
     s->state = PA_SINK_RUNNING;
-    
+    s->name = pa_xstrdup(name);
+    s->description = NULL;
+    s->driver = pa_xstrdup(driver);
     s->owner = NULL;
-    s->core = core;
+
     s->sample_spec = *spec;
+    if (map)
+        s->channel_map = *map;
+    else
+        pa_channel_map_init_auto(&s->channel_map, spec->channels);
+    
     s->inputs = pa_idxset_new(NULL, NULL);
 
     n = pa_sprintf_malloc("%s_monitor", name);
-    s->monitor_source = pa_source_new(core, typeid, n, 0, spec);
+    s->monitor_source = pa_source_new(core, n, driver, 0, spec, map);
     assert(s->monitor_source);
     pa_xfree(n);
     s->monitor_source->monitor_of = s;
     s->monitor_source->description = pa_sprintf_malloc("Monitor source of sink '%s'", s->name);
-    
-    s->volume = PA_VOLUME_NORM;
+
+    pa_cvolume_reset(&s->sw_volume);
+    pa_cvolume_reset(&s->hw_volume);
 
     s->notify = NULL;
     s->get_latency = NULL;
+    s->set_volume = NULL;
+    s->get_volume = NULL;
     s->userdata = NULL;
 
+    s->flags = 0;
+
     r = pa_idxset_put(core->sinks, s, &s->index);
     assert(s->index != PA_IDXSET_INVALID && r >= 0);
     
@@ -127,6 +148,7 @@ static void sink_free(struct pa_sink *s) {
 
     pa_xfree(s->name);
     pa_xfree(s->description);
+    pa_xfree(s->driver);
     pa_xfree(s);
 }
 
@@ -360,11 +382,38 @@ void pa_sink_set_owner(struct pa_sink *s, struct pa_module *m) {
         pa_source_set_owner(s->monitor_source, m);
 }
 
-void pa_sink_set_volume(struct pa_sink *s, pa_volume_t volume) {
-    assert(s && s->ref >= 1);
-    
-    if (s->volume != volume) {
-        s->volume = volume;
-        pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
-    }
+void pa_sink_set_volume(struct pa_sink *s, pa_mixer_t m, const struct pa_cvolume *volume) {
+    struct pa_cvolume *v;
+    assert(s);
+    assert(s->ref >= 1);
+    assert(volume);
+
+    if ((m == PA_MIXER_HARDWARE || m == PA_MIXER_AUTO) && s->set_volume)
+        v = &s->hw_volume;
+    else
+        v = &s->sw_volume;
+
+    if (pa_cvolume_equal(v, volume))
+        return;
+
+    *v = volume;
+    pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
+
+    if (v == &s->hw_volume)
+        s->set_volume(s);
+}
+
+const struct pa_cvolume *pa_sink_get_volume(struct pa_sink *sink, pa_mixer_t m) {
+    struct pa_cvolume *v;
+    assert(s);
+    assert(s->ref >= 1);
+
+    if ((m == PA_MIXER_HARDWARE || m == PA_MIXER_AUTO) && s->set_volume) {
+
+        if (s->get_volume)
+            s->get_volume(s);
+        
+        return &s->hw_volume;
+    } else
+        return &s->sw_volume;
 }
diff --git a/polyp/sink.h b/polyp/sink.h
index 844af96..a6d7efa 100644
--- a/polyp/sink.h
+++ b/polyp/sink.h
@@ -30,38 +30,51 @@ struct pa_sink;
 #include "sample.h"
 #include "idxset.h"
 #include "source.h"
-#include "typeid.h"
+#include "channelmap.h"
 
 #define PA_MAX_INPUTS_PER_SINK 6
 
-enum pa_sink_state {
+typedef enum {
     PA_SINK_RUNNING,
     PA_SINK_DISCONNECTED
-};
+} pa_sink_state_t;
+
+typedef enum {
+    PA_MIXER_AUTO,
+    PA_MIXER_SOFTWARE,
+    PA_MIXER_HARDWARE
+} pa_mixer_t;
 
 struct pa_sink {
     int ref;
-    enum pa_sink_state state;
-    
     uint32_t index;
-    pa_typeid_t typeid;
-
-    char *name, *description;
-    struct pa_module *owner;
     struct pa_core *core;
+    pa_sink_state_t state;
+
+    char *name, *description, *driver;
     struct pa_sample_spec sample_spec;
+    struct pa_channel_map channel_map;
     struct pa_idxset *inputs;
-
+    struct pa_module *owner;
     struct pa_source *monitor_source;
-
-    pa_volume_t volume;
+    struct pa_cvolume hw_volume, sw_volume;
 
     void (*notify)(struct pa_sink*sink);
     pa_usec_t (*get_latency)(struct pa_sink *s);
+    void (*set_volume)(struct pa_sink *s);
+    void (*get_volume)(struct pa_sink *s);
+    
     void *userdata;
 };
 
-struct pa_sink* pa_sink_new(struct pa_core *core, pa_typeid_t typeid, const char *name, int fail, const struct pa_sample_spec *spec);
+struct pa_sink* pa_sink_new(
+    struct pa_core *core,
+    const char *name,
+    const char *driver,
+    int fail,
+    const struct pa_sample_spec *spec,
+    const struct pa_channel_map *map);
+
 void pa_sink_disconnect(struct pa_sink* s);
 void pa_sink_unref(struct pa_sink*s);
 struct pa_sink* pa_sink_ref(struct pa_sink *s);
@@ -77,6 +90,7 @@ void pa_sink_notify(struct pa_sink*s);
 
 void pa_sink_set_owner(struct pa_sink *sink, struct pa_module *m);
 
-void pa_sink_set_volume(struct pa_sink *sink, pa_volume_t volume);
+void pa_sink_set_volume(struct pa_sink *sink, pa_mixer_t m, const struct pa_cvolume *volume);
+const struct pa_cvolume *pa_sink_get_volume(struct pa_sink *sink, pa_mixer_t m);
 
 #endif
diff --git a/polyp/source-output.c b/polyp/source-output.c
index f954c23..fa9f252 100644
--- a/polyp/source-output.c
+++ b/polyp/source-output.c
@@ -33,7 +33,14 @@
 #include "subscribe.h"
 #include "log.h"
 
-struct pa_source_output* pa_source_output_new(struct pa_source *s, pa_typeid_t typeid, const char *name, const struct pa_sample_spec *spec, int resample_method) {
+struct pa_source_output* pa_source_output_new(
+    struct pa_source *s,
+    const char *name,
+    const char *driver,
+    const struct pa_sample_spec *spec,
+    const struct pa_channel_map *map,
+    int resample_method) {
+    
     struct pa_source_output *o;
     struct pa_resampler *resampler = NULL;
     int r;
@@ -49,19 +56,24 @@ struct pa_source_output* pa_source_output_new(struct pa_source *s, pa_typeid_t t
         resample_method = s->core->resample_method;
 
     if (!pa_sample_spec_equal(&s->sample_spec, spec))
-        if (!(resampler = pa_resampler_new(&s->sample_spec, spec, s->core->memblock_stat, resample_method)))
+        if (!(resampler = pa_resampler_new(&s->sample_spec, &s->channel_map, spec, map, s->core->memblock_stat, resample_method)))
             return NULL;
     
     o = pa_xmalloc(sizeof(struct pa_source_output));
     o->ref = 1;
     o->state = PA_SOURCE_OUTPUT_RUNNING;
     o->name = pa_xstrdup(name);
-    o->typeid = typeid;
+    o->driver = pa_xstrdup(driver);
     
     o->client = NULL;
     o->owner = NULL;
     o->source = s;
+    
     o->sample_spec = *spec;
+    if (map)
+        c->channel_map = *map;
+    else
+        pa_channel_map_init_auto(&c->channel_map, spec->channels);
 
     o->push = NULL;
     o->kill = NULL;
@@ -96,7 +108,6 @@ void pa_source_output_disconnect(struct pa_source_output*o) {
     o->push = NULL;
     o->kill = NULL;
     
-    
     o->state = PA_SOURCE_OUTPUT_DISCONNECTED;
 }
 
@@ -112,6 +123,7 @@ static void source_output_free(struct pa_source_output* o) {
         pa_resampler_free(o->resampler);
 
     pa_xfree(o->name);
+    pa_xfree(o->driver);
     pa_xfree(o);
 }
 
diff --git a/polyp/source-output.h b/polyp/source-output.h
index f3187aa..f561e05 100644
--- a/polyp/source-output.h
+++ b/polyp/source-output.h
@@ -31,24 +31,24 @@
 #include "module.h"
 #include "client.h"
 
-enum pa_source_output_state {
+typedef enum {
     PA_SOURCE_OUTPUT_RUNNING,
     PA_SOURCE_OUTPUT_CORKED,
     PA_SOURCE_OUTPUT_DISCONNECTED
-};
+} pa_source_output_state_t;
 
 struct pa_source_output {
     int ref;
-    enum pa_source_output_state state;
-    
     uint32_t index;
-    pa_typeid_t typeid;
-
-    char *name;
+    pa_source_output_state_t state;
+    
+    char *name, *driver;
     struct pa_module *owner;
     struct pa_client *client;
     struct pa_source *source;
+
     struct pa_sample_spec sample_spec;
+    struct pa_channel_map channel_map;
     
     void (*push)(struct pa_source_output *o, const struct pa_memchunk *chunk);
     void (*kill)(struct pa_source_output* o);
@@ -59,7 +59,14 @@ struct pa_source_output {
     void *userdata;
 };
 
-struct pa_source_output* pa_source_output_new(struct pa_source *s, pa_typeid_t typeid, const char *name, const struct pa_sample_spec *spec, int resample_method);
+struct pa_source_output* pa_source_output_new(
+    struct pa_source *s,
+    const char *name,
+    const char *driver,
+    const struct pa_sample_spec *spec,
+    const struct pa_channel_map *map;
+    int resample_method);
+
 void pa_source_output_unref(struct pa_source_output* o);
 struct pa_source_output* pa_source_output_ref(struct pa_source_output *o);
 
diff --git a/polyp/source.c b/polyp/source.c
index fc73272..a80c6af 100644
--- a/polyp/source.c
+++ b/polyp/source.c
@@ -35,11 +35,22 @@
 #include "subscribe.h"
 #include "log.h"
 
-struct pa_source* pa_source_new(struct pa_core *core, pa_typeid_t typeid, const char *name, int fail, const struct pa_sample_spec *spec) {
+struct pa_source* pa_source_new(
+    struct pa_core *core,
+    const char *name,
+    const char *driver,
+    int fail,
+    const struct pa_sample_spec *spec,
+    const struct pa_channel_map *map) {
+    
     struct pa_source *s;
     char st[256];
     int r;
-    assert(core && spec && name && *name);
+    
+    assert(core);
+    assert(name);
+    assert(*name);
+    assert(spec);
 
     s = pa_xmalloc(sizeof(struct pa_source));
 
@@ -53,11 +64,16 @@ struct pa_source* pa_source_new(struct pa_core *core, pa_typeid_t typeid, const
     
     s->name = pa_xstrdup(name);
     s->description = NULL;
-    s->typeid = typeid; 
+    s->driver = pa_xstrdup(driver);
 
     s->owner = NULL;
     s->core = core;
     s->sample_spec = *spec;
+    if (map)
+        s->channel_map = *map;
+    else
+        pa_channel_map_init_auto(&s->channel_map, spec->channels);
+
     s->outputs = pa_idxset_new(NULL, NULL);
     s->monitor_of = NULL;
 
@@ -108,6 +124,7 @@ static void source_free(struct pa_source *s) {
 
     pa_xfree(s->name);
     pa_xfree(s->description);
+    pa_xfree(s->driver);
     pa_xfree(s);
 }
 
diff --git a/polyp/source.h b/polyp/source.h
index 0fac2b3..21ebda5 100644
--- a/polyp/source.h
+++ b/polyp/source.h
@@ -31,35 +31,42 @@ struct pa_source;
 #include "memblock.h"
 #include "memchunk.h"
 #include "sink.h"
-#include "typeid.h"
+#include "channelmap.h"
 
 #define PA_MAX_OUTPUTS_PER_SOURCE 16
 
-enum pa_source_state {
+typedef enum {
     PA_SOURCE_RUNNING,
     PA_SOURCE_DISCONNECTED
-};
+} pa_source_state_t;
 
 struct pa_source {
     int ref;
-    enum pa_source_state state;
-    
     uint32_t index;
-    pa_typeid_t typeid;
-    
-    char *name, *description;
-    struct pa_module *owner;
     struct pa_core *core;
+    pa_source_state_t state;
+    
+    char *name, *description, *driver;
     struct pa_sample_spec sample_spec;
+    struct pa_channel_map channel_map;
     struct pa_idxset *outputs;
     struct pa_sink *monitor_of;
+    struct pa_module *owner;
 
     void (*notify)(struct pa_source*source);
     pa_usec_t (*get_latency)(struct pa_source *s);
+    
     void *userdata;
 };
 
-struct pa_source* pa_source_new(struct pa_core *core, pa_typeid_t typeid, const char *name, int fail, const struct pa_sample_spec *spec);
+struct pa_source* pa_source_new(
+    struct pa_core *core,
+    const char *name,
+    const char *driver,
+    int fail,
+    const struct pa_sample_spec *spec,
+    const struct pa_channel_map *map);
+
 void pa_source_disconnect(struct pa_source *s);
 void pa_source_unref(struct pa_source *s);
 struct pa_source* pa_source_ref(struct pa_source *c);
diff --git a/polyp/tagstruct.h b/polyp/tagstruct.h
index 135825e..f867cfb 100644
--- a/polyp/tagstruct.h
+++ b/polyp/tagstruct.h
@@ -44,6 +44,8 @@ void pa_tagstruct_put_arbitrary(struct pa_tagstruct*t, const void *p, size_t len
 void pa_tagstruct_put_boolean(struct pa_tagstruct*t, int b);
 void pa_tagstruct_put_timeval(struct pa_tagstruct*t, const struct timeval *tv);
 void pa_tagstruct_put_usec(struct pa_tagstruct*t, pa_usec_t u);
+void pa_tagstruct_put_channel_map(struct pa_tagstruct *t, const struct pa_channel_map *map);
+void pa_tagstruct_put_cvolume(struct pa_tagstruct *t, const struct pa_cvolume *cvolume);
 
 int pa_tagstruct_gets(struct pa_tagstruct*t, const char **s);
 int pa_tagstruct_getu8(struct pa_tagstruct*t, uint8_t *c);
@@ -54,6 +56,8 @@ int pa_tagstruct_get_arbitrary(struct pa_tagstruct *t, const void **p, size_t le
 int pa_tagstruct_get_boolean(struct pa_tagstruct *t, int *b);
 int pa_tagstruct_get_timeval(struct pa_tagstruct*t, struct timeval *tv);
 int pa_tagstruct_get_usec(struct pa_tagstruct*t, pa_usec_t *u);
+int pa_tagstruct_get_channel_map(struct pa_tagstruct *t, struct pa_channel_map *map);
+int pa_tagstruct_get_cvolume(struct pa_tagstruct *t, struct pa_cvolume *v);
 
 int pa_tagstruct_eof(struct pa_tagstruct*t);
 const uint8_t* pa_tagstruct_data(struct pa_tagstruct*t, size_t *l);
diff --git a/polyp/voltest.c b/polyp/voltest.c
index d8d5c56..0c4e232 100644
--- a/polyp/voltest.c
+++ b/polyp/voltest.c
@@ -2,13 +2,18 @@
 
 #include <stdio.h>
 
-#include <polyp/sample.h>
+#include <polyp/volume.h>
 
 int main() {
-    int p;
-    for (p = 0; p <= 200; p++) {
-        pa_volume_t v = pa_volume_from_user((double) p/100);
-        double dB = pa_volume_to_dB(v);
-        printf("%3i%% = %u = %0.2f dB = %u = %3i%%\n", p, v, dB, pa_volume_from_dB(dB), (int) (pa_volume_to_user(v)*100));
+    pa_volume_t v;
+
+    for (v = PA_VOLUME_MUTED; v <= PA_VOLUME_NORM*2; v += 256) {
+
+        double dB = pa_sw_volume_to_dB(v);
+        double f = pa_sw_volume_to_linear(v);
+        
+        printf("Volume: %3i; percent: %i%%; decibel %0.2f; linear = %0.2f; volume(decibel): %3i; volume(linear): %3i\n",
+               v, (v*100)/PA_VOLUME_NORM, dB, f, pa_sw_volume_from_dB(dB), pa_sw_volume_from_linear(f));
+
     }
 }
diff --git a/polyp/volume.c b/polyp/volume.c
new file mode 100644
index 0000000..bb9d30d
--- /dev/null
+++ b/polyp/volume.c
@@ -0,0 +1,161 @@
+/* $Id$ */
+
+/***
+  This file is part of polypaudio.
+ 
+  polypaudio 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.
+ 
+  polypaudio 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 polypaudio; 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 "volume.h"
+
+int pa_cvolume_equal(const struct pa_cvolume *a, const struct pa_cvolume *b) {
+    int i;
+    assert(a);
+    assert(b);
+
+    if (a->channels != b->channels)
+        return 0;
+    
+    for (i = 0; i < a->channels; i++)
+        if (a->values[i] != b->values[i])
+            return 0;
+
+    return 1;
+}
+
+void pa_cvolume_set(struct pa_cvolume *a, pa_volume_t v) {
+    int i;
+    assert(a);
+
+    a->channels = PA_CHANNELS_MAX;
+
+    for (i = 0; i < a->channels; i++)
+        a->values[i] = v;
+}
+
+void pa_cvolume_reset(struct pa_cvolume *a) {
+    assert(a);
+    pa_cvolume_set(a, PA_VOLUME_NORM);
+}
+
+void pa_cvolume_mute(struct pa_cvolume *a) {
+    assert(a);
+    pa_cvolume_set(a, PA_VOLUME_MUTED);
+}
+
+pa_volume_t pa_cvolume_avg(const struct pa_cvolume *a) {
+    uint64_t sum = 0;
+    int i;
+    assert(a);
+
+    for (i = 0; i < a->channels; i++)
+        sum += a->values[i];
+
+    sum /= a->channels;
+
+    return (pa_volume_t) sum;
+}
+
+pa_volume_t pa_sw_volume_multiply(pa_volume_t a, pa_volume_t b) {
+    uint64_t p = a;
+    p *= b;
+    p /= PA_VOLUME_NORM;
+
+    return pa_sw_volume_from_linear(pa_sw_volume_to_linear(a)* pa_sw_volume_to_linear(b));
+}
+
+#define USER_DECIBEL_RANGE 30
+
+pa_volume_t pa_sw_volume_from_dB(double dB) {
+    if (dB <= -USER_DECIBEL_RANGE)
+        return PA_VOLUME_MUTED;
+
+    return (pa_volume_t) ((dB/USER_DECIBEL_RANGE+1)*PA_VOLUME_NORM);
+}
+
+double pa_sw_volume_to_dB(pa_volume_t v) {
+    if (v == PA_VOLUME_MUTED)
+        return PA_DECIBEL_MININFTY;
+
+    return ((double) v/PA_VOLUME_NORM-1)*USER_DECIBEL_RANGE;
+}
+
+pa_volume_t pa_sw_volume_from_linear(double v) {
+
+    if (v <= 0)
+        return PA_VOLUME_MUTED;
+
+    if (v == 1)
+        return PA_VOLUME_NORM;
+
+    return pa_sw_volume_from_dB(20*log10(v));
+}
+
+double pa_sw_volume_to_linear(pa_volume_t v) {
+
+    if (v == PA_VOLUME_MUTED)
+        return 0;
+
+    return pow(10, pa_sw_volume_to_dB(v)/20);
+    
+}
+
+char *pa_cvolume_snprintf(char *s, size_t l, const struct pa_cvolume *c, unsigned channels) {
+    unsigned c;
+    int first = 1;
+    
+    assert(s);
+    assert(l > 0);
+    assert(c);
+
+    if (channels > PA_CHANNELS_MAX || channels <= 0)
+        channels = PA_CHANNELS_MAX;
+
+    *s = 0;
+
+    for (c = 0; c < channels && l > 1; c++) {
+        l -= snprintf(s, l, "%s%u: %3u%%",
+                      first ? "" : " ",
+                      c,
+                      (c->channels[c]*100)/PA_VOLUME_NORM);
+
+        s = strchr(s, 0);
+    }
+
+    return s;
+}
+
+
+/** Return non-zero if the volume of all channels is equal to the specified value */
+int pa_cvolume_channels_equal_to(const struct pa_cvolume *a, uint8_t channels, pa_volume_t v) {
+    unsigned c;
+    assert(a);
+
+    if (channels > PA_CHANNELS_MAX)
+        channels = PA_CHANNELS_MAX;
+
+    for (c = 0; c < channels; c++)
+        if (a->map[c] != v)
+            return 0;
+
+    return 1;
+}
diff --git a/polyp/volume.h b/polyp/volume.h
new file mode 100644
index 0000000..c013ddd
--- /dev/null
+++ b/polyp/volume.h
@@ -0,0 +1,98 @@
+#ifndef foovolumehfoo
+#define foovolumehfoo
+
+/* $Id$ */
+
+/***
+  This file is part of polypaudio.
+ 
+  polypaudio 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.
+ 
+  polypaudio 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 polypaudio; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+  USA.
+***/
+
+#include <inttypes.h>
+#include <polyp/cdecl.h>
+#include <polyp/sample.h>
+
+/** \file
+ * Constants and routines for volume handling */
+
+PA_C_DECL_BEGIN
+
+/** Volume specification:
+ *  PA_VOLUME_MUTED: silence;
+ * < PA_VOLUME_NORM: decreased volume;
+ *   PA_VOLUME_NORM: normal volume;
+ * > PA_VOLUME_NORM: increased volume */
+typedef uint32_t pa_volume_t;
+
+/** Normal volume (100%) */
+#define PA_VOLUME_NORM (0x10000)
+
+/** Muted volume (0%) */
+#define PA_VOLUME_MUTED (0)
+
+/** A structure encapsulating a per-channel volume */
+struct pa_cvolume {
+    uint8_t channels;
+    pa_volume_t values[PA_CHANNELS_MAX];
+};
+
+/** Return non-zero when *a == *b */
+int pa_cvolume_equal(const struct pa_cvolume *a, const struct pa_cvolume *b);
+
+/** Set the volume of all channels to PA_VOLUME_NORM */
+void pa_cvolume_reset(struct pa_cvolume *a);
+
+/** Set the volume of all channels to PA_VOLUME_MUTED */
+void pa_cvolume_mute(struct pa_cvolume *a);
+
+/** Set the volume of all channels to the specified parameter */
+void pa_cvolume_set(struct pa_cvolume *a, pa_volume_t v);
+
+/** Pretty print a volume structure */
+char *pa_cvolume_snprintf(char *s, size_t l, const struct pa_cvolume *c, unsigned channels);
+
+/** Return the average volume of all channels */
+pa_volume_t pa_cvolume_avg(const struct pa_cvolume *a);
+
+/** Return non-zero if the volume of all channels is equal to the specified value */
+int pa_cvolume_channels_equal_to(const struct pa_cvolume *a, uint8_t channels, pa_volume_t v);
+
+/** Multiply two volumes specifications, return the result. This uses PA_VOLUME_NORM as neutral element of multiplication. */
+pa_volume_t pa_sw_volume_multiply(pa_volume_t a, pa_volume_t b);
+
+/** Convert a decibel value to a volume. \since 0.4 */
+pa_volume_t pa_sw_volume_from_dB(double f);
+
+/** Convert a volume to a decibel value.  \since 0.4 */
+double pa_sw_volume_to_dB(pa_volume_t v);
+
+/** Convert a linear factor to a volume. \since 0.8 */
+pa_volume_t pa_sw_volume_from_linear(double v);
+
+/** Convert a volume to a linear factor. \since 0.8 */
+double pa_sw_volume_to_linear(pa_volume_t v);
+
+#ifdef INFINITY
+#define PA_DECIBEL_MININFTY (-INFINITY)
+#else
+/** This value is used as minus infinity when using pa_volume_{to,from}_dB(). \since 0.4 */
+#define PA_DECIBEL_MININFTY (-200)
+#endif
+
+PA_C_DECL_END
+
+#endif

commit 1f11ee3c8b392a68685875478637ce875de85da2
Author: Pierre Ossman <ossman at cendio.se>
Date:   Thu Jan 5 13:07:00 2006 +0000

    Big cleanup of the build structure.
    
     * configure.ac is divided into distinct sections for programs, headers,
       optional components, etc.
    
     * polyp/Makefile.am is organised into several sections instead of a big mess.
    
     * Conditionals are only for adding things to the primaries, not around their
       build rules.
    
     * polypcore has been brought up to date in preparation for the Windows port.
       It is not possible to use the current tricks there.
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/ossman@362 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/Makefile.am b/Makefile.am
index 7935321..a6a012a 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -18,7 +18,7 @@
 # USA.
 
 EXTRA_DIST = bootstrap.sh README LICENSE doxygen/Makefile.am doxygen/Makefile.in doxygen/doxygen.conf.in libtool.m4 ltdl.m4
-SUBDIRS=polyp doc libltdl
+SUBDIRS=libltdl polyp doc
 
 MAINTAINERCLEANFILES=README
 noinst_DATA = README
@@ -49,8 +49,8 @@ homepage: all dist doxygen
 	cp -a doxygen/html/* $$HOME/homepage/private/projects/polypaudio/doxygen
 	cp $$HOME/homepage/private/projects/polypaudio/README.html $$HOME/homepage/private/projects/polypaudio/index.html
 
-distcleancheck:
-	@:
+#distcleancheck:
+#	@:
 
 doxygen:
 	$(MAKE) -C doxygen doxygen
diff --git a/acinclude.m4 b/acinclude.m4
index bedf51c..02f271b 100644
--- a/acinclude.m4
+++ b/acinclude.m4
@@ -197,3 +197,44 @@ else
 fi
 AC_LANG_RESTORE
 ])dnl ACX_PTHREAD
+
+AC_DEFUN([AC_CHECK_DEFINE],[
+AS_VAR_PUSHDEF([ac_var],[ac_cv_defined_$1])dnl
+AC_CACHE_CHECK([for $1 defined], ac_var,
+AC_TRY_COMPILE([#include <$2>],[
+  #ifdef $1
+  int ok;
+  #else
+  choke me
+  #endif
+],AS_VAR_SET(ac_var, yes),AS_VAR_SET(ac_var, no)))
+AS_IF([test AS_VAR_GET(ac_var) != "no"], [$3], [$4])dnl
+AS_VAR_POPDEF([ac_var])dnl
+])
+
+AC_DEFUN([ACX_LIBWRAP], [
+LIBWRAP_LIBS=
+saved_LIBS="$LIBS"
+LIBS="$LIBS -lwrap"
+AC_MSG_CHECKING([for tcpwrap library and headers])
+AC_LINK_IFELSE(
+AC_LANG_PROGRAM(
+[#include <tcpd.h>
+#include <syslog.h>
+int allow_severity = LOG_INFO;
+int deny_severity = LOG_WARNING;],
+[struct request_info *req; 
+return hosts_access (req);]),
+[AC_DEFINE(HAVE_LIBWRAP, [], [Have tcpwrap?])
+LIBWRAP_LIBS="-lwrap"
+AC_MSG_RESULT(yes)],
+[AC_MSG_RESULT(no)])
+LIBS="$saved_LIBS"
+])
+
+AC_DEFUN([ACX_LIRC], [
+LIRC_CFLAGS=
+LIRC_LIBS=
+AC_CHECK_HEADER(lirc/lirc_client.h,[AC_CHECK_LIB(lirc_client,lirc_init,[HAVE_LIRC=1
+LIRC_LIBS=-llirc_client],HAVE_LIRC=0)],HAVE_LIRC=0)
+])
diff --git a/configure.ac b/configure.ac
index 1254134..362077f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -35,18 +35,60 @@ if type -p stow > /dev/null && test -d /usr/local/stow ; then
    ac_default_prefix="/usr/local/stow/${PACKAGE_NAME}-${PACKAGE_VERSION}"
 fi
 
-# Checks for programs.
+#### Checks for programs. ####
+
+# CC
+
 AC_PROG_CC
+AC_PROG_GCC_TRADITIONAL
+
+# If using GCC specify some additional parameters
+if test "x$GCC" = "xyes" ; then
+   CFLAGS="$CFLAGS -pipe -W -Wall -pedantic"
+
+   AC_LANG_CONFTEST([int main() {}])
+   $CC -c conftest.c -std=gnu9x -Wno-unused-parameter $CFLAGS > /dev/null 2> /dev/null && CFLAGS="$CFLAGS -std=gnu9x -Wno-unused-parameter"
+   rm -f conftest.o
+fi
+
+# M4
 
-# libtool stuff
+AC_PATH_PROG([M4], [m4 gm4], [no])
+if test "x$M4" = xno ; then
+   AC_MSG_ERROR([m4 missing])
+fi
+
+# LYNX documentation generation
+AC_ARG_ENABLE(lynx,
+        AC_HELP_STRING(--disable-lynx,Turn off lynx usage for documentation generation),
+[case "${enableval}" in
+  yes) lynx=yes ;;
+  no)  lynx=no ;;
+  *) AC_MSG_ERROR(bad value ${enableval} for --disable-lynx) ;;
+esac],[lynx=yes])
+
+if test x$lynx = xyes ; then
+   AC_CHECK_PROG(have_lynx, lynx, yes, no)
+
+   if test x$have_lynx = xno ; then
+     AC_MSG_WARN([*** lynx not found, plain text README will not be built ***])
+   fi
+fi
+
+AM_CONDITIONAL([USE_LYNX], [test "x$have_lynx" = xyes])
+
+#### 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_CONFIG_SUBDIRS(libltdl)
 
-if test "x$ac_cv_lib_ltdl_lt_dlinit" = "xno" ; then
+if test "x$enable_ltdl_install" = "xno" && test "x$ac_cv_lib_ltdl_lt_dlinit" = "xno" ; then
     AC_MSG_ERROR([[
 
         *** Cannot find the libltdl development files.
@@ -54,93 +96,167 @@ if test "x$ac_cv_lib_ltdl_lt_dlinit" = "xno" ; then
         ]])
 fi
 
-# Checks for header files.
+#### Determine build environment ####
+
+os_is_win32=0
+
+case "$host_os" in
+	mingw*)
+        AC_DEFINE([OS_IS_WIN32], 1, [Build target is Windows.])
+        os_is_win32=1
+		;;
+	esac
+
+AM_CONDITIONAL(OS_IS_WIN32, test "x$os_is_win32" = "x1")
+
+###################################
+#   Basic environment checks      #
+###################################
+
+#### Checks for header files. ####
+
+# ISO
 AC_HEADER_STDC
-AC_CHECK_HEADERS([arpa/inet.h fcntl.h inttypes.h limits.h malloc.h netdb.h netinet/in.h stddef.h stdint.h stdlib.h string.h sys/ioctl.h sys/socket.h sys/time.h unistd.h syslog.h])
 
-ACX_PTHREAD
-AC_PATH_XTRA
+# POSIX
+AC_CHECK_HEADERS([glob.h grp.h netdb.h netinet/in.h netinet/tcp.h pwd.h \
+    sched.h sys/capability.h sys/resource.h sys/select.h sys/socket.h \
+    syslog.h])
+AC_CHECK_HEADERS([regex.h], [HAVE_REGEX=1], [HAVE_REGEX=0])
+AC_CHECK_HEADERS([sys/un.h], [HAVE_AF_UNIX=1], [HAVE_AF_UNIX=0])
 
-HAVE_X11=0
-test "x$no_x" != "xyes" && HAVE_X11=1
-AC_SUBST(HAVE_X11)
-AM_CONDITIONAL(HAVE_X11, test "x$no_x" != "xyes")
-if test "x$no_x" != "xyes" ; then
-   AC_DEFINE([HAVE_X11], 1, [Have X11])
-fi
+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])
+
+AM_CONDITIONAL([HAVE_EVDEV], [test "x$HAVE_EVDEV" = "x1"])
+
+# Windows
+AC_CHECK_HEADERS([winsock2.h ws2tcpip.h])
+
+# Other
+AC_CHECK_HEADERS([sys/ioctl.h])
+
+#### Typdefs, structures, etc. ####
 
-# Checks for typedefs, structures, and compiler characteristics.
 AC_C_CONST
+AC_C_BIGENDIAN
 AC_TYPE_PID_T
 AC_TYPE_SIZE_T
+AC_CHECK_TYPES(ssize_t, , [AC_DEFINE([ssize_t], [signed long],
+    [Define ssize_t if it is not done by the standard libs.])])
 AC_TYPE_OFF_T
-AC_HEADER_TIME
-
-# Checks for library functions.
-AC_FUNC_FORK
-AC_PROG_GCC_TRADITIONAL
-AC_FUNC_LSTAT
-AC_FUNC_LSTAT_FOLLOWS_SLASHED_SYMLINK
-AC_FUNC_MALLOC
-AC_FUNC_MEMCMP
-AC_FUNC_MMAP
-AC_FUNC_REALLOC
-AC_FUNC_SETPGRP
-AC_FUNC_VPRINTF
-AC_FUNC_CLOSEDIR_VOID
-AC_FUNC_SELECT_ARGTYPES
 AC_TYPE_SIGNAL
 AC_TYPE_UID_T
-AC_CHECK_FUNCS([gethostname gettimeofday memchr memmove memset mkdir mkfifo munmap rmdir socket strcspn strerror strrchr strspn strstr strtol strtoul strcasecmp putenv strchr strpbrk strdup getgrgid_r getpwuid_r regcomp ftruncate select])
-AC_CHECK_LIB(m, pow)
-AC_CHECK_FUNCS(pow)
-AC_FUNC_STAT
-AC_HEADER_SYS_WAIT
-AC_HEADER_DIRENT
 
-AC_C_BIGENDIAN
+AC_CHECK_DEFINE([SIGXCPU], [signal.h])
+AM_CONDITIONAL(HAVE_SIGXCPU, test "x$HAVE_SIGXCPU" = "x1")
+
+#### Check for functions ####
+
+# ISO
+AC_CHECK_LIB([m], [pow])
+
+# POSIX
+AC_FUNC_FORK
 AC_FUNC_GETGROUPS
+AC_FUNC_SELECT_ARGTYPES
+AC_CHECK_FUNCS([ftruncate getgrgid_r getpwuid_r gettimeofday getuid \
+    inet_ntop mkfifo nanosleep sigaction sleep])
 
-AC_CHECK_LIB(cap, cap_init, [CAP_LIBS='-lcap'], [CAP_LIBS=''])
-AC_SUBST(CAP_LIBS)
+AM_CONDITIONAL(HAVE_MKFIFO, test "x$HAVE_MKFIFO" = "x1")
 
-AC_CHECK_HEADERS(sys/capability.h)
+# X/OPEN
+AC_CHECK_FUNCS([readlink])
+
+# SUSv2
+AC_CHECK_FUNCS([ctime_r usleep])
+
+# Non-standard
 
 AC_CHECK_FUNCS(setresuid)
 AC_CHECK_FUNCS(setreuid)
 
+#### POSIX threads ####
+
+ACX_PTHREAD
+
+###################################
+#      External libraries         #
+###################################
+
+#### X11 (optional) ####
+
+HAVE_X11=0
+
+# The macro tests the host, not the build target
+if test "x$os_is_win32" != "x1" ; then
+    AC_PATH_XTRA
+    test "x$no_x" != "xyes" && HAVE_X11=1
+fi
+
+AC_SUBST(HAVE_X11)
+AM_CONDITIONAL(HAVE_X11, test "x$HAVE_X11" = "x1")
+if test "x$HAVE_X11" = "x1" ; then
+    AC_DEFINE([HAVE_X11], 1, [Have X11])
+fi
+
+#### Capabilities (optional) ####
+
+AC_CHECK_LIB(cap, cap_init, [CAP_LIBS='-lcap'], [CAP_LIBS=''])
+AC_SUBST(CAP_LIBS)
+
+#### 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 ])
 AC_SUBST(LIBSNDFILE_CFLAGS)
 AC_SUBST(LIBSNDFILE_LIBS)
 
+#### ALSA support (optional) ####
+
 PKG_CHECK_MODULES(ASOUNDLIB, [ alsa >= 1.0.0 ], [HAVE_ALSA=1], [HAVE_ALSA=0])
 AC_SUBST(ASOUNDLIB_CFLAGS)
 AC_SUBST(ASOUNDLIB_LIBS) 
 AC_SUBST(HAVE_ALSA)
 AM_CONDITIONAL([HAVE_ALSA], [test "x$HAVE_ALSA" = x1])
 
+#### GLib 2 support (optional) ####
+
 PKG_CHECK_MODULES(GLIB20, [ glib-2.0 >= 2.4.0 ], HAVE_GLIB20=1, HAVE_GLIB20=0)
 AC_SUBST(GLIB20_CFLAGS)
 AC_SUBST(GLIB20_LIBS)
 AC_SUBST(HAVE_GLIB20)
 AM_CONDITIONAL([HAVE_GLIB20], [test "x$HAVE_GLIB20" = x1])
 
+#### GLib 1 support (optional) ####
+
 PKG_CHECK_MODULES(GLIB12, [ glib >= 1.2.0 ], HAVE_GLIB12=1, HAVE_GLIB12=0)
 AC_SUBST(GLIB12_CFLAGS)
 AC_SUBST(GLIB12_LIBS)
 AC_SUBST(HAVE_GLIB12)
 AM_CONDITIONAL([HAVE_GLIB12], [test "x$HAVE_GLIB12" = x1])
 
+#### Howl support (optional) ####
+
 PKG_CHECK_MODULES(HOWL, [ howl >= 0.9.8 ], HAVE_HOWL=1, HAVE_HOWL=0)
 AC_SUBST(HOWL_CFLAGS)
 AC_SUBST(HOWL_LIBS)
 AC_SUBST(HAVE_HOWL)
 AM_CONDITIONAL([HAVE_HOWL], [test "x$HAVE_HOWL" = x1])
 
+#### Async DNS support (optional) ####
+
 PKG_CHECK_MODULES(LIBASYNCNS, [ libasyncns >= 0.1 ], HAVE_LIBASYNCNS=1, HAVE_LIBASYNCNS=0)
 AC_SUBST(LIBASYNCNS_CFLAGS)
 AC_SUBST(LIBASYNCNS_LIBS)
@@ -151,70 +267,42 @@ if test "x$HAVE_LIBASYNCNS" != "x0" ; then
    AC_DEFINE([HAVE_LIBASYNCNS], 1, [Have libasyncns?])
 fi
 
-AC_PATH_PROG([M4], [m4 gm4], [no])
-if test "x$M4" = xno ; then
-   AC_MSG_ERROR([m4 missing])
-fi
+#### TCP wrappers (optional) ####
 
-AC_MSG_CHECKING([for tcpwrap library and headers])
-LIBWRAP_LIBS=
-saved_LIBS="$LIBS"
-LIBS="$LIBS -lwrap"
-AC_LINK_IFELSE(
-AC_LANG_PROGRAM(
-[#include <tcpd.h>
-#include <syslog.h>
-int allow_severity = LOG_INFO;
-int deny_severity = LOG_WARNING;],
-[struct request_info *req; 
-return hosts_access (req);]),
-[AC_DEFINE(HAVE_LIBWRAP, [], [Have tcpwrap?])
-LIBWRAP_LIBS="-lwrap"
-AC_MSG_RESULT(yes)],
-[AC_MSG_RESULT(no)])
+ACX_LIBWRAP
 AC_SUBST(LIBWRAP_LIBS)
-LIBS="$saved_LIBS"
 
-LIRC_CFLAGS=
-LIRC_LIBS=
-AC_CHECK_HEADER(lirc/lirc_client.h,[AC_CHECK_LIB(lirc_client,lirc_init,[HAVE_LIRC=1
-LIRC_LIBS=-llirc_client],HAVE_LIRC=0)],HAVE_LIRC=0)
+#### LIRC support (optional) ####
+
+ACX_LIRC
 AC_SUBST(LIRC_CFLAGS)
 AC_SUBST(LIRC_LIBS)
 AM_CONDITIONAL([HAVE_LIRC], [test "x$HAVE_LIRC" = x1])
 
-AC_CHECK_HEADER(linux/input.h,HAVE_EVDEV=1,HAVE_EVDEV=0)
-AM_CONDITIONAL([HAVE_EVDEV], [test "x$HAVE_EVDEV" = x1])
-
-# If using GCC specify some additional parameters
-if test "x$GCC" = "xyes" ; then
-   CFLAGS="$CFLAGS -pipe -W -Wall -pedantic"
-
-   AC_LANG_CONFTEST([int main() {}])
-   $CC -c conftest.c -std=c99 -Wno-unused-parameter $CFLAGS > /dev/null 2> /dev/null && CFLAGS="$CFLAGS -std=c99 -Wno-unused-parameter"
-   rm -f conftest.o
-fi
-
-# LYNX documentation generation
-AC_ARG_ENABLE(lynx,
-        AC_HELP_STRING(--disable-lynx,Turn off lynx usage for documentation generation),
-[case "${enableval}" in
-  yes) lynx=yes ;;
-  no)  lynx=no ;;
-  *) AC_MSG_ERROR(bad value ${enableval} for --disable-lynx) ;;
-esac],[lynx=yes])
-
-if test x$lynx = xyes ; then
-   AC_CHECK_PROG(have_lynx, lynx, yes, no)
-
-   if test x$have_lynx = xno ; then
-     AC_MSG_WARN([*** lynx not found, plain text README will not be built ***])
-   fi
-fi
-
-AM_CONDITIONAL([USE_LYNX], [test "x$lynx" = xyes])
+###################################
+#            Output               #
+###################################
 
 AM_CONDITIONAL(BUILD_LIBPOLYPCORE, false)
 
-AC_CONFIG_FILES([Makefile polyp/Makefile polyplib.pc polyplib-simple.pc polyplib-mainloop.pc polyplib-browse.pc polyplib-error.pc polyplib-glib-mainloop.pc polyplib-glib12-mainloop.pc doc/Makefile doc/README.html doc/cli.html doc/daemon.html doc/modules.html doxygen/Makefile doxygen/doxygen.conf polyp/polyplib-version.h doc/FAQ.html])
+AC_CONFIG_FILES([
+Makefile
+polyp/Makefile
+polyplib.pc
+polyplib-simple.pc
+polyplib-mainloop.pc
+polyplib-browse.pc
+polyplib-error.pc
+polyplib-glib-mainloop.pc
+polyplib-glib12-mainloop.pc
+doc/Makefile
+doc/README.html
+doc/cli.html
+doc/daemon.html
+doc/modules.html
+doxygen/Makefile
+doxygen/doxygen.conf
+polyp/polyplib-version.h
+doc/FAQ.html
+])
 AC_OUTPUT
diff --git a/polyp/Makefile.am b/polyp/Makefile.am
index 389cb0d..847be9a 100644
--- a/polyp/Makefile.am
+++ b/polyp/Makefile.am
@@ -17,72 +17,440 @@
 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
 # USA.
 
+
+###################################
+#       Extra directories         #
+###################################
+
 polypincludedir=$(includedir)/polyp
 polypconfdir=$(sysconfdir)/polypaudio
 
 modlibdir=$(libdir)/polypaudio- at PA_MAJORMINOR@
 
-AM_CFLAGS=-D_GNU_SOURCE  -I$(top_srcdir) $(PTHREAD_CFLAGS) $(LIBSAMPLERATE_CFLAGS) $(LIBSNDFILE_CFLAGS)
-AM_CFLAGS+=-DDLSEARCHPATH=\"$(modlibdir)\"
-AM_CFLAGS+=-DDEFAULT_CONFIG_DIR=\"$(polypconfdir)\"
-AM_CFLAGS+=-DPOLYPAUDIO_BINARY=\"$(bindir)/polypaudio\"
+###################################
+#     Compiler/linker flags       #
+###################################
+
+AM_CFLAGS  = -D_GNU_SOURCE  -I$(top_srcdir)
+AM_CFLAGS += $(PTHREAD_CFLAGS) $(LTDLINCL)
+AM_CFLAGS += $(LIBSAMPLERATE_CFLAGS) $(LIBSNDFILE_CFLAGS)
+AM_CFLAGS += -DDLSEARCHPATH=\"$(modlibdir)\"
+AM_CFLAGS += -DDEFAULT_CONFIG_DIR=\"$(polypconfdir)\"
+AM_CFLAGS += -DPOLYPAUDIO_BINARY=\"$(bindir)/polypaudio$(EXEEXT)\"
 
 # This cool debug trap works on i386/gcc only
-AM_CFLAGS+='-DDEBUG_TRAP=__asm__("int $$3")'
+AM_CFLAGS += '-DDEBUG_TRAP=__asm__("int $$3")'
+
+AM_LIBADD = $(PTHREAD_LIBS)
+AM_LDADD = $(PTHREAD_LIBS)
+
+# Only required on some platforms but defined for all to avoid errors
+AM_LDFLAGS = -no-undefined
+
+if OS_IS_WIN32
+AM_LDFLAGS+=-Wl,--export-all-symbols
+WINSOCK_LIBS=-lwsock32 -lws2_32 -lwininet
+endif
+
+###################################
+#          Extra files            #
+###################################
 
-AM_LIBADD=$(PTHREAD_LIBS) -lm
-AM_LDADD=$(PTHREAD_LIBS) -lm
+EXTRA_DIST = \
+		client.conf.in \
+		daemon.conf.in \
+		default.pa.in \
+		depmod.py \
+		esdcompat.sh.in \
+		module-defs.h.m4
 
-EXTRA_DIST = default.pa.in daemon.conf.in client.conf.in depmod.py esdcompat.sh.in module-defs.h.m4
-bin_PROGRAMS = \
-		polypaudio \
+polypconf_DATA = default.pa daemon.conf client.conf
+
+BUILT_SOURCES = polyplib-version.h
+
+###################################
+#          Main daemon            #
+###################################
+
+bin_PROGRAMS = polypaudio
+
+polypaudio_SOURCES = \
+		caps.h caps.c \
+		cmdline.c cmdline.h \
+		cpulimit.c cpulimit.h \
+		conf-parser.h conf-parser.c \
+		daemon-conf.c daemon-conf.h \
+		dumpmodules.c dumpmodules.h \
+		gcc-printf.h \
+		main.c \
+		pid.c pid.h
+
+polypaudio_CFLAGS = $(AM_CFLAGS)
+polypaudio_CPPFLAGS = $(AM_CPPFLAGS)
+polypaudio_LDADD = $(AM_LDADD) libpolypcore.la $(LIBLTDL) \
+		$(LIBSAMPLERATE_LIBS) $(LIBSNDFILE_LIBS) $(CAP_LIBS)
+polypaudio_LDFLAGS= $(AM_LDFLAGS) -dlopen force 
+#q-static $(foreach f,$(modlib_LTLIBRARIES),-dlpreopen $(f))
+
+###################################
+#       Utility programs          #
+###################################
+
+bin_PROGRAMS += \
 		pacat \
 		pactl \
-		paplay \
-		pacmd
+		paplay
+
+if HAVE_AF_UNIX
+bin_PROGRAMS += pacmd
+endif
+
+if HAVE_X11
+bin_PROGRAMS += pax11publish
+endif
+
+if HAVE_HOWL
+bin_PROGRAMS += 	pabrowse
+endif
 
 bin_SCRIPTS = esdcompat.sh
 
+pacat_SOURCES = pacat.c
+pacat_LDADD = $(AM_LDADD) libpolyp- at PA_MAJORMINOR@.la libpolyp-error- at PA_MAJORMINOR@.la libpolyp-mainloop- at PA_MAJORMINOR@.la
+pacat_CFLAGS = $(AM_CFLAGS) 
+
+paplay_SOURCES = paplay.c
+paplay_LDADD = $(AM_LDADD) libpolyp- at PA_MAJORMINOR@.la libpolyp-error- at PA_MAJORMINOR@.la libpolyp-mainloop- at PA_MAJORMINOR@.la $(LIBSNDFILE_LIBS)
+paplay_CFLAGS = $(AM_CFLAGS) $(LIBSNDFILE_CFLAGS)
+
+pactl_SOURCES = pactl.c
+pactl_LDADD = $(AM_LDADD) libpolyp- at PA_MAJORMINOR@.la libpolyp-error- at PA_MAJORMINOR@.la libpolyp-mainloop- at PA_MAJORMINOR@.la $(LIBSNDFILE_LIBS)
+pactl_CFLAGS = $(AM_CFLAGS) $(LIBSNDFILE_CFLAGS)
+
+pacmd_SOURCES = pacmd.c util.c util.h xmalloc.c xmalloc.h log.c log.h pid.c pid.h
+pacmd_CFLAGS = $(AM_CFLAGS)
+pacmd_LDADD = $(AM_LDADD)
+
+pax11publish_SOURCES = pax11publish.c util.c util.h xmalloc.c xmalloc.h log.c log.h authkey.c authkey.h client-conf.c client-conf.h conf-parser.c conf-parser.h x11prop.c x11prop.h random.c random.h
+pax11publish_CFLAGS = $(AM_CFLAGS) $(X_CFLAGS)
+pax11publish_LDADD = $(AM_LDADD) $(X_PRE_LIBS) -lX11 $(X_LIBS) $(X_EXTRA_LIBS)
+
+pabrowse_SOURCES = pabrowse.c
+pabrowse_LDADD = $(AM_LDADD) libpolyp- at PA_MAJORMINOR@.la libpolyp-error- at PA_MAJORMINOR@.la libpolyp-mainloop- at PA_MAJORMINOR@.la libpolyp-browse- at PA_MAJORMINOR@.la
+pabrowse_CFLAGS = $(AM_CFLAGS)
+
+###################################
+#         Test programs           #
+###################################
+
 noinst_PROGRAMS = \
 		mainloop-test \
+		mcalign-test \
 		pacat-simple \
 		parec-simple \
-		cpulimit-test \
-		cpulimit-test2 \
-		voltest \
 		strlist-test \
-		mcalign-test
+		voltest
+
+if HAVE_SIGXCPU
+noinst_PROGRAMS += \
+		cpulimit-test \
+		cpulimit-test2
+endif
+
+if HAVE_GLIB20
+noinst_PROGRAMS += \
+		mainloop-test-glib
+endif
+
+if HAVE_GLIB12
+noinst_PROGRAMS += \
+		mainloop-test-glib12
+endif
+
+mainloop_test_SOURCES = mainloop-test.c
+mainloop_test_CFLAGS = $(AM_CFLAGS)
+mainloop_test_LDADD = $(AM_LDADD) libpolyp-mainloop- at PA_MAJORMINOR@.la libpolyp- at PA_MAJORMINOR@.la
+
+mcalign_test_SOURCES = mcalign-test.c util.c util.h xmalloc.c xmalloc.h log.c log.h mcalign.c mcalign.h memchunk.c memchunk.h memblock.c memblock.h
+mcalign_test_CFLAGS = $(AM_CFLAGS)
+mcalign_test_LDADD = $(AM_LDADD) $(WINSOCK_LIBS)
+
+pacat_simple_SOURCES = pacat-simple.c
+pacat_simple_LDADD = $(AM_LDADD) libpolyp- at PA_MAJORMINOR@.la libpolyp-simple- at PA_MAJORMINOR@.la libpolyp-error- at PA_MAJORMINOR@.la libpolyp-mainloop- at PA_MAJORMINOR@.la
+pacat_simple_CFLAGS = $(AM_CFLAGS)
+
+parec_simple_SOURCES = parec-simple.c
+parec_simple_LDADD = $(AM_LDADD) libpolyp- at PA_MAJORMINOR@.la libpolyp-simple- at PA_MAJORMINOR@.la libpolyp-error- at PA_MAJORMINOR@.la libpolyp-mainloop- at PA_MAJORMINOR@.la
+parec_simple_CFLAGS = $(AM_CFLAGS)
 
-polypconf_DATA=default.pa daemon.conf client.conf
+strlist_test_SOURCES = strlist-test.c strlist.c strlist.h strbuf.c strbuf.h util.c util.h xmalloc.c xmalloc.h log.c log.h
+strlist_test_CFLAGS = $(AM_CFLAGS)
+strlist_test_LDADD = $(AM_LDADD) $(WINSOCK_LIBS)
+
+voltest_SOURCES = voltest.c sample.c
+voltest_CFLAGS = $(AM_CFLAGS)
+voltest_LDADD = $(AM_LDADD)
+
+cpulimit_test_SOURCES = cpulimit-test.c cpulimit.c util.c log.c cpulimit.h util.h log.h
+cpulimit_test_CFLAGS = $(AM_CFLAGS)
+cpulimit_test_LDADD = $(AM_LDADD) libpolyp-mainloop- at PA_MAJORMINOR@.la
+
+cpulimit_test2_SOURCES = cpulimit-test.c cpulimit.c util.c log.c cpulimit.h util.h log.h
+cpulimit_test2_CFLAGS = $(AM_CFLAGS) -DTEST2
+cpulimit_test2_LDADD = $(AM_LDADD) libpolyp-mainloop- at PA_MAJORMINOR@.la
 
-BUILT_SOURCES=polyplib-version.h
+mainloop_test_glib_SOURCES = $(mainloop_test_SOURCES)
+mainloop_test_glib_CFLAGS = $(mainloop_test_CFLAGS) $(GLIB20_CFLAGS) -DGLIB_MAIN_LOOP
+mainloop_test_glib_LDADD = $(mainloop_test_LDADD) $(GLIB20_LIBS) libpolyp-mainloop-glib- at PA_MAJORMINOR@.la
+
+mainloop_test_glib12_SOURCES = $(mainloop_test_SOURCES)
+mainloop_test_glib12_CFLAGS = $(mainloop_test_CFLAGS) $(GLIB12_CFLAGS) -DGLIB_MAIN_LOOP
+mainloop_test_glib12_LDADD = $(mainloop_test_LDADD) $(GLIB12_LIBS) libpolyp-mainloop-glib12- at PA_MAJORMINOR@.la
 
-polypinclude_HEADERS= \
+###################################
+#         Client library          #
+###################################
+
+polypinclude_HEADERS = \
+		cdecl.h \
+		glib-mainloop.h \
+		mainloop.h \
+		mainloop-api.h \
+		mainloop-signal.h \
 		polyplib.h \
+		polyplib-context.h \
 		polyplib-def.h \
-		polyplib-simple.h \
 		polyplib-error.h \
-		polyplib-stream.h \
-		polyplib-context.h \
 		polyplib-introspect.h \
-		polyplib-subscribe.h \
 		polyplib-operation.h \
 		polyplib-scache.h \
+		polyplib-simple.h \
+		polyplib-stream.h \
+		polyplib-subscribe.h \
 		polyplib-version.h \
-		cdecl.h \
-		mainloop-api.h \
-		mainloop.h \
-		mainloop-signal.h \
 		sample.h \
-		glib-mainloop.h \
 		typeid.h
 
+if HAVE_HOWL
+polypinclude_HEADERS += \
+		polyplib-browser.h
+endif
+
+lib_LTLIBRARIES = \
+		libpolyp- at PA_MAJORMINOR@.la \
+		libpolyp-error- at PA_MAJORMINOR@.la \
+		libpolyp-mainloop- at PA_MAJORMINOR@.la \
+		libpolyp-simple- at PA_MAJORMINOR@.la
+
+if HAVE_HOWL
+lib_LTLIBRARIES += \
+		libpolyp-browse- at PA_MAJORMINOR@.la
+endif
+
+if HAVE_GLIB20
+lib_LTLIBRARIES += \
+		libpolyp-mainloop-glib- at PA_MAJORMINOR@.la
+endif
+
+if HAVE_GLIB12
+lib_LTLIBRARIES += \
+		libpolyp-mainloop-glib12- at PA_MAJORMINOR@.la
+endif
+
+libpolyp_ at PA_MAJORMINOR@_la_SOURCES = \
+		authkey.c authkey.h \
+		cdecl.h \
+		client-conf.c client-conf.h \
+		conf-parser.c conf-parser.h \
+		dynarray.c dynarray.h \
+		gcc-printf.h \
+		idxset.c idxset.h \
+		iochannel.c iochannel.h \
+		llist.h \
+		log.c log.h \
+		mainloop-api.c mainloop-api.h \
+		mcalign.c mcalign.h \
+		memblock.c memblock.h \
+		memchunk.c memchunk.h \
+		native-common.h \
+		packet.c packet.h \
+		parseaddr.c parseaddr.h \
+		pdispatch.c pdispatch.h \
+		polyplib.h \
+		polyplib-context.c polyplib-context.h \
+		polyplib-def.h \
+		polyplib-internal.h \
+		polyplib-introspect.c polyplib-introspect.h \
+		polyplib-operation.c polyplib-operation.h \
+		polyplib-scache.c polyplib-scache.h \
+		polyplib-stream.c polyplib-stream.h \
+		polyplib-subscribe.c polyplib-subscribe.h \
+		pstream.c pstream.h \
+		pstream-util.c pstream-util.h \
+		queue.c queue.h \
+		random.c random.h \
+		sample.c sample.h \
+		socket-client.c socket-client.h \
+		socket-util.c socket-util.h \
+		strbuf.c strbuf.h \
+		strlist.c strlist.h \
+		tagstruct.c tagstruct.h \
+		typeid.c typeid.h \
+		util.c util.h \
+		xmalloc.c xmalloc.h
+
+if HAVE_X11
+libpolyp_ at PA_MAJORMINOR@_la_SOURCES += \
+		client-conf-x11.c client-conf-x11.h \
+		x11prop.c x11prop.h
+endif
+
+libpolyp_ at PA_MAJORMINOR@_la_CFLAGS = $(AM_CFLAGS)
+libpolyp_ at PA_MAJORMINOR@_la_LDFLAGS = -version-info 0:0:0
+libpolyp_ at PA_MAJORMINOR@_la_LIBADD = $(AM_LIBADD) $(WINSOCK_LIBS)
+
+if HAVE_X11
+libpolyp_ at PA_MAJORMINOR@_la_CFLAGS += $(X_CFLAGS)
+libpolyp_ at PA_MAJORMINOR@_la_LDFLAGS += $(X_PRE_LIBS) -lX11 $(X_LIBS) $(X_EXTRA_LIBS)
+endif
+
+if HAVE_LIBASYNCNS
+libpolyp_ at PA_MAJORMINOR@_la_CFLAGS += $(LIBASYNCNS_CFLAGS)
+libpolyp_ at PA_MAJORMINOR@_la_LIBADD += $(LIBASYNCNS_LIBS)
+endif
+
+libpolyp_error_ at PA_MAJORMINOR@_la_SOURCES = polyplib-error.c polyplib-error.h
+libpolyp_error_ at PA_MAJORMINOR@_la_CFLAGS = $(AM_CFLAGS)
+libpolyp_error_ at PA_MAJORMINOR@_la_LIBADD = $(AM_LIBADD) libpolyp- at PA_MAJORMINOR@.la
+libpolyp_error_ at PA_MAJORMINOR@_la_LDFLAGS = -version-info 0:0:0
+
+libpolyp_mainloop_ at PA_MAJORMINOR@_la_SOURCES = \
+		mainloop.c mainloop.h \
+		mainloop-api.h mainloop-api.c \
+		mainloop-signal.c mainloop-signal.h
+libpolyp_mainloop_ at PA_MAJORMINOR@_la_CFLAGS = $(AM_CFLAGS)
+libpolyp_mainloop_ at PA_MAJORMINOR@_la_LIBADD = $(AM_LIBADD) libpolyp- at PA_MAJORMINOR@.la $(WINSOCK_LIBS)
+libpolyp_mainloop_ at PA_MAJORMINOR@_la_LDFLAGS = -version-info 0:0:0
+
+libpolyp_simple_ at PA_MAJORMINOR@_la_SOURCES = polyplib-simple.c polyplib-simple.h 
+libpolyp_simple_ at PA_MAJORMINOR@_la_CFLAGS = $(AM_CFLAGS)
+libpolyp_simple_ at PA_MAJORMINOR@_la_LIBADD = $(AM_LIBADD) libpolyp- at PA_MAJORMINOR@.la libpolyp-mainloop- at PA_MAJORMINOR@.la
+libpolyp_simple_ at PA_MAJORMINOR@_la_LDFLAGS = -version-info 0:0:0
+
+libpolyp_browse_ at PA_MAJORMINOR@_la_SOURCES = polyplib-browser.c polyplib-browser.h 
+libpolyp_browse_ at PA_MAJORMINOR@_la_CFLAGS = $(AM_CFLAGS) $(HOWL_CFLAGS)
+libpolyp_browse_ at PA_MAJORMINOR@_la_LIBADD = $(AM_LIBADD) libpolyp- at PA_MAJORMINOR@.la $(HOWL_LIBS)
+libpolyp_browse_ at PA_MAJORMINOR@_la_LDFLAGS = -version-info 0:0:0 
+
+libpolyp_mainloop_glib_ at PA_MAJORMINOR@_la_SOURCES = glib-mainloop.h glib-mainloop.c
+libpolyp_mainloop_glib_ at PA_MAJORMINOR@_la_CFLAGS = $(AM_CFLAGS) $(GLIB20_CFLAGS)
+libpolyp_mainloop_glib_ at PA_MAJORMINOR@_la_LIBADD = $(AM_LIBADD) libpolyp-mainloop- at PA_MAJORMINOR@.la $(GLIB20_LIBS)
+libpolyp_mainloop_glib_ at PA_MAJORMINOR@_la_LDFLAGS = -version-info 0:0:0
+
+libpolyp_mainloop_glib12_ at PA_MAJORMINOR@_la_SOURCES = glib-mainloop.h glib12-mainloop.c
+libpolyp_mainloop_glib12_ at PA_MAJORMINOR@_la_CFLAGS = $(AM_CFLAGS) $(GLIB12_CFLAGS)
+libpolyp_mainloop_glib12_ at PA_MAJORMINOR@_la_LIBADD = $(AM_LIBADD) libpolyp-mainloop- at PA_MAJORMINOR@.la $(GLIB12_LIBS)
+libpolyp_mainloop_glib12_ at PA_MAJORMINOR@_la_LDFLAGS = -version-info 0:0:0
+
+###################################
+#      Daemon core library        #
+###################################
+
+polypinclude_HEADERS += \
+		cli-command.h \
+		client.h \
+		core.h \
+		dynarray.h \
+		endianmacros.h \
+		hashmap.h \
+		idxset.h \
+		iochannel.h \
+		memblock.h \
+		memblockq.h \
+		memchunk.h \
+		modargs.h \
+		module.h \
+		namereg.h \
+		queue.h \
+		resampler.h \
+		sample-util.h \
+		sink.h \
+		sink-input.h \
+		sioman.h \
+		socket-server.h \
+		socket-client.h \
+		socket-util.h \
+		source.h \
+		source-output.h \
+		strbuf.h \
+		tokenizer.h \
+		tagstruct.h \
+		util.h
+
+lib_LTLIBRARIES += libpolypcore.la
+
+libpolypcore_la_SOURCES = \
+		autoload.c autoload.h \
+		cli-command.c cli-command.h \
+		cli-text.c cli-text.h \
+		client.c client.h \
+		core.c core.h \
+		dynarray.c dynarray.h \
+		endianmacros.h \
+		g711.c g711.h \
+		hashmap.c hashmap.h \
+		idxset.c idxset.h \
+		log.c log.h \
+		mainloop.c mainloop.h \
+		mainloop-api.c mainloop-api.h \
+		mainloop-signal.c mainloop-signal.h \
+		mcalign.c mcalign.h \
+		memblock.c memblock.h \
+		memblockq.c memblockq.h \
+		memchunk.c memchunk.h \
+		modargs.c modargs.h \
+		modinfo.c modinfo.h \
+		module.c module.h \
+		namereg.c namereg.h \
+		play-memchunk.c play-memchunk.h \
+		props.c props.h \
+		queue.c queue.h \
+		random.c random.h \
+		resampler.c resampler.h \
+		sample.c sample.h \
+		sample-util.c sample-util.h \
+		scache.c scache.h \
+		sconv.c sconv.h \
+		sconv-s16be.c sconv-s16be.h \
+		sconv-s16le.c sconv-s16le.h \
+		sink.c sink.h \
+		sink-input.c sink-input.h \
+		sioman.c sioman.h \
+		sound-file.c sound-file.h \
+		sound-file-stream.c sound-file-stream.h \
+		source.c source.h \
+		source-output.c source-output.h \
+		strbuf.c strbuf.h \
+		subscribe.c subscripe.h \
+		tokenizer.c tokenizer.h \
+		typeid.c typeid.h \
+		util.c util.h \
+		xmalloc.c xmalloc.h
+
+libpolypcore_la_CPPFLAGS = $(AM_CPPFLAGS)
+libpolypcore_la_LDFLAGS = -avoid-version
+libpolypcore_la_LIBADD = $(AM_LIBADD) $(LIBLTDL) $(LIBSAMPLERATE_LIBS) $(LIBSNDFILE_LIBS) $(WINSOCK_LIBS)
+
+###################################
+#   Plug-in support libraries     #
+###################################
+
 ### Warning! Due to an obscure bug in libtool/automake it is required
 ### that the libraries in modlib_LTLIBRARIES are specified in-order,
 ### i.e. libraries near the end of the list depend on libraries near
 ### the head, and not the other way!
 
-modlib_LTLIBRARIES= \
+modlib_LTLIBRARIES = \
 		libsocket-util.la \
 		libiochannel.la \
 		libsocket-server.la \
@@ -90,7 +458,6 @@ modlib_LTLIBRARIES= \
 		libparseaddr.la \
 		libpacket.la \
 		libpstream.la \
-		liboss-util.la \
 		libioline.la \
 		libcli.la \
 		libprotocol-cli.la \
@@ -103,163 +470,49 @@ modlib_LTLIBRARIES= \
 		libprotocol-simple.la \
 		libprotocol-esound.la \
 		libprotocol-native.la \
-		libprotocol-http.la \
-		module-cli.la \
-		module-cli-protocol-tcp.la \
-		module-cli-protocol-tcp6.la \
-		module-cli-protocol-unix.la \
-		module-pipe-sink.la \
-		module-pipe-source.la \
-		module-oss.la \
-		module-oss-mmap.la \
-		module-simple-protocol-tcp.la \
-		module-simple-protocol-tcp6.la \
-		module-simple-protocol-unix.la \
-		module-esound-protocol-tcp.la \
-		module-esound-protocol-tcp6.la \
-		module-esound-protocol-unix.la \
-		module-native-protocol-tcp.la \
-		module-native-protocol-tcp6.la \
-		module-native-protocol-unix.la \
-		module-native-protocol-fd.la \
-		module-sine.la \
-		module-combine.la \
-		module-esound-compat-spawnfd.la \
-		module-esound-compat-spawnpid.la \
-		module-match.la \
-		module-tunnel-sink.la \
-		module-tunnel-source.la \
-		module-null-sink.la \
-		module-esound-sink.la \
-		module-http-protocol-tcp.la \
-		module-http-protocol-tcp6.la \
-		module-http-protocol-unix.la
-
-SYMDEF_FILES= \
-		module-cli-symdef.h \
-		module-cli-protocol-tcp-symdef.h \
-		module-cli-protocol-tcp6-symdef.h \
-		module-cli-protocol-unix-symdef.h \
-		module-pipe-sink-symdef.h \
-		module-pipe-source-symdef.h \
-		module-oss-symdef.h \
-		module-oss-mmap-symdef.h \
-		module-simple-protocol-tcp-symdef.h \
-		module-simple-protocol-tcp6-symdef.h \
-		module-simple-protocol-unix-symdef.h \
-		module-esound-protocol-tcp-symdef.h \
-		module-esound-protocol-tcp6-symdef.h \
-		module-esound-protocol-unix-symdef.h \
-		module-native-protocol-tcp-symdef.h \
-		module-native-protocol-tcp6-symdef.h \
-		module-native-protocol-unix-symdef.h \
-		module-native-protocol-fd-symdef.h \
-		module-sine-symdef.h \
-		module-combine-symdef.h \
-		module-esound-compat-spawnfd-symdef.h \
-		module-esound-compat-spawnpid-symdef.h \
-		module-match-symdef.h \
-		module-tunnel-sink-symdef.h \
-		module-tunnel-source-symdef.h \
-		module-null-sink-symdef.h \
-		module-esound-sink-symdef.h \
-		module-zeroconf-publish-symdef.h \
-		module-lirc-symdef.h \
-		module-mmkbd-evdev-symdef.h \
-		module-http-protocol-tcp-symdef.h \
-		module-http-protocol-tcp6-symdef.h \
-		module-http-protocol-unix-symdef.h
+		libprotocol-http.la
 
-EXTRA_DIST+=$(SYMDEF_FILES)
-BUILT_SOURCES+=$(SYMDEF_FILES)
+if HAVE_X11
+modlib_LTLIBRARIES += \
+		libx11wrap.la \
+		libx11prop.la
+endif
 
-lib_LTLIBRARIES= \
-		libpolyp- at PA_MAJORMINOR@.la \
-		libpolyp-error- at PA_MAJORMINOR@.la \
-		libpolyp-mainloop- at PA_MAJORMINOR@.la \
-		libpolyp-simple- at PA_MAJORMINOR@.la
+if !OS_IS_WIN32
+modlib_LTLIBRARIES += \
+		liboss-util.la
+endif
 
-polypaudio_SOURCES = idxset.c idxset.h \
-		queue.c queue.h \
-		strbuf.c strbuf.h \
-		main.c \
-		mainloop.c mainloop.h \
-		memblock.c memblock.h \
-		sample.c sample.h \
-		sample-util.c sample-util.h \
-		memblockq.c memblockq.h \
-		client.c client.h \
-		core.c core.h \
-		source-output.c source-output.h \
-		sink-input.c sink-input.h \
-		source.c source.h \
-		sink.c sink.h \
-		module.c module.h \
-		mainloop-signal.c mainloop-signal.h \
-		mainloop-api.c mainloop-api.h \
-		util.c util.h \
-		hashmap.c hashmap.h \
-		namereg.c namereg.h \
-		sconv.c sconv.h \
-		resampler.c resampler.h \
-		endianmacros.h \
-		memchunk.c memchunk.h \
-		sconv-s16le.c sconv-s16le.h \
-		sconv-s16be.c sconv-s16be.h \
-		sioman.c sioman.h \
-		modargs.c modargs.h \
-		cmdline.c cmdline.h \
-		cli-command.c cli-command.h \
-		cli-text.c cli-text.h \
-		tokenizer.c tokenizer.h \
-		dynarray.c dynarray.h \
-		scache.c scache.h \
-		sound-file.c sound-file.h \
-		play-memchunk.c play-memchunk.h \
-		autoload.c autoload.h \
-		xmalloc.c xmalloc.h \
-		subscribe.h subscribe.c \
-		sound-file-stream.c sound-file-stream.h \
-		cpulimit.c cpulimit.h \
-		log.c log.h \
-		gcc-printf.h \
-		modinfo.c modinfo.h \
-		daemon-conf.c daemon-conf.h \
-		dumpmodules.c dumpmodules.h \
-		conf-parser.h conf-parser.c \
-		caps.h caps.c \
-		props.h props.c \
-		mcalign.c mcalign.h \
-		g711.c g711.h \
-		pid.c pid.h \
-		random.c random.h \
-		typeid.c typeid.h
+if HAVE_ALSA
+modlib_LTLIBRARIES += \
+		libalsa-util.la
+endif
 
-polypaudio_CFLAGS = $(AM_CFLAGS) $(LIBSAMPLERATE_CFLAGS) $(LIBSNDFILE_CFLAGS)
-polypaudio_CPPFLAGS = $(AM_CPPFLAGS) $(LTDLINCL)
-polypaudio_LDADD = $(AM_LDADD) $(LIBLTDL) $(LIBSAMPLERATE_LIBS) $(LIBSNDFILE_LIBS) $(CAP_LIBS)
-polypaudio_LDFLAGS= $(AM_LDFLAGS) -export-dynamic -dlopen force 
-#q-static $(foreach f,$(modlib_LTLIBRARIES),-dlpreopen $(f))
+if HAVE_HOWL
+modlib_LTLIBRARIES += \
+		libhowl-wrap.la
+endif
 
 libprotocol_simple_la_SOURCES = protocol-simple.c protocol-simple.h
 libprotocol_simple_la_LDFLAGS = -avoid-version
-libprotocol_simple_la_LIBADD = $(AM_LIBADD) libsocket-server.la libiochannel.la
+libprotocol_simple_la_LIBADD = $(AM_LIBADD) libpolypcore.la libsocket-server.la libiochannel.la
 
 libsocket_server_la_SOURCES = socket-server.c socket-server.h
 libsocket_server_la_LDFLAGS = -avoid-version
-libsocket_server_la_LIBADD = $(AM_LIBADD) libiochannel.la libsocket-util.la $(LIBWRAP_LIBS)
+libsocket_server_la_LIBADD = $(AM_LIBADD) libpolypcore.la libiochannel.la libsocket-util.la $(LIBWRAP_LIBS) $(WINSOCK_LIBS)
 
 libsocket_client_la_SOURCES = socket-client.c socket-client.h
 libsocket_client_la_LDFLAGS = -avoid-version
-libsocket_client_la_LIBADD = $(AM_LIBADD) libiochannel.la libsocket-util.la libparseaddr.la $(LIBASYNCNS_LIBS)
+libsocket_client_la_LIBADD = $(AM_LIBADD) libpolypcore.la libiochannel.la libsocket-util.la libparseaddr.la $(LIBASYNCNS_LIBS) $(WINSOCK_LIBS)
 libsocket_client_la_CFLAGS = $(AM_CFLAGS) $(LIBASYNCNS_CFLAGS)
 
 libparseaddr_la_SOURCES = parseaddr.c parseaddr.h
 libparseaddr_la_LDFLAGS = -avoid-version
+libparseaddr_la_LIBADD = $(AM_LIBADD) libpolypcore.la
 
 libpstream_la_SOURCES = pstream.c pstream.h
 libpstream_la_LDFLAGS = -avoid-version
-libpstream_la_LIBADD = $(AM_LIBADD) libpacket.la libiochannel.la
+libpstream_la_LIBADD = $(AM_LIBADD) libpolypcore.la libpacket.la libiochannel.la $(WINSOCK_LIBS)
 
 libpstream_util_la_SOURCES = pstream-util.c pstream-util.h
 libpstream_util_la_LDFLAGS = -avoid-version
@@ -267,326 +520,380 @@ libpstream_util_la_LIBADD = $(AM_LIBADD) libpacket.la libpstream.la libtagstruct
 
 libpdispatch_la_SOURCES = pdispatch.c pdispatch.h
 libpdispatch_la_LDFLAGS = -avoid-version
-libpdispatch_la_LIBADD = $(AM_LIBADD) libtagstruct.la
+libpdispatch_la_LIBADD = $(AM_LIBADD) libtagstruct.la libpolypcore.la
 
 libiochannel_la_SOURCES = iochannel.c iochannel.h
 libiochannel_la_LDFLAGS = -avoid-version
-libiochannel_la_LIBADD = $(AM_LIBADD) libsocket-util.la
+libiochannel_la_LIBADD = $(AM_LIBADD) libsocket-util.la libpolypcore.la
 
 libpacket_la_SOURCES = packet.c packet.h
 libpacket_la_LDFLAGS = -avoid-version
-
-liboss_util_la_SOURCES = oss-util.c oss-util.h
-liboss_util_la_LDFLAGS = -avoid-version
+libpacket_la_LIBADD = $(AM_LIBADD) libpolypcore.la
 
 libioline_la_SOURCES = ioline.c ioline.h
 libioline_la_LDFLAGS = -avoid-version
-libioline_la_LIBADD = $(AM_LIBADD) libiochannel.la
+libioline_la_LIBADD = $(AM_LIBADD) libiochannel.la libpolypcore.la
 
 libcli_la_SOURCES = cli.c cli.h
+libcli_la_CPPFLAGS = $(AM_CPPFLAGS)
 libcli_la_LDFLAGS = -avoid-version
-libcli_la_LIBADD = $(AM_LIBADD) libiochannel.la libioline.la
+libcli_la_LIBADD = $(AM_LIBADD) libiochannel.la libioline.la libpolypcore.la
 
 libstrlist_la_SOURCES = strlist.c strlist.h
 libstrlist_la_LDFLAGS = -avoid-version
-libstrlist_la_LIBADD = $(AM_LIBADD)
+libstrlist_la_LIBADD = $(AM_LIBADD) libpolypcore.la
 
 libprotocol_cli_la_SOURCES = protocol-cli.c protocol-cli.h
 libprotocol_cli_la_LDFLAGS = -avoid-version
-libprotocol_cli_la_LIBADD = $(AM_LIBADD) libsocket-server.la libiochannel.la libcli.la
+libprotocol_cli_la_LIBADD = $(AM_LIBADD) libsocket-server.la libiochannel.la libcli.la libpolypcore.la
 
 libprotocol_http_la_SOURCES = protocol-http.c protocol-http.h
 libprotocol_http_la_LDFLAGS = -avoid-version
-libprotocol_http_la_LIBADD = $(AM_LIBADD) libsocket-server.la libioline.la
+libprotocol_http_la_LIBADD = $(AM_LIBADD) libsocket-server.la libioline.la libpolypcore.la libiochannel.la
 
 libprotocol_native_la_SOURCES = protocol-native.c protocol-native.h native-common.h
 libprotocol_native_la_LDFLAGS = -avoid-version
-libprotocol_native_la_LIBADD = $(AM_LIBADD) libsocket-server.la libpstream.la libpstream-util.la libpdispatch.la libtagstruct.la libauthkey.la libauthkey-prop.la libstrlist.la
+libprotocol_native_la_LIBADD = $(AM_LIBADD) libsocket-server.la libpstream.la libpstream-util.la libpdispatch.la libtagstruct.la libauthkey.la libauthkey-prop.la libstrlist.la libpolypcore.la libiochannel.la
 
 libtagstruct_la_SOURCES = tagstruct.c tagstruct.h
 libtagstruct_la_LDFLAGS = -avoid-version
+libtagstruct_la_LIBADD = $(AM_LIBADD) libpolypcore.la $(WINSOCK_LIBS)
 
 libprotocol_esound_la_SOURCES = protocol-esound.c protocol-esound.h esound.h
 libprotocol_esound_la_LDFLAGS = -avoid-version
-libprotocol_esound_la_LIBADD = $(AM_LIBADD) libsocket-server.la libiochannel.la libauthkey.la
+libprotocol_esound_la_LIBADD = $(AM_LIBADD) libsocket-server.la libiochannel.la libauthkey.la libpolypcore.la
 
 libauthkey_la_SOURCES = authkey.c authkey.h
 libauthkey_la_LDFLAGS = -avoid-version
+libauthkey_la_LIBADD = $(AM_LIBADD) libpolypcore.la
 
 libauthkey_prop_la_SOURCES = authkey-prop.c authkey-prop.h
 libauthkey_prop_la_LDFLAGS = -avoid-version
+libauthkey_prop_la_LIBADD = $(AM_LIBADD) libpolypcore.la
 
 libsocket_util_la_SOURCES = socket-util.c socket-util.h
 libsocket_util_la_LDFLAGS = -avoid-version
+libsocket_util_la_LIBADD = $(AM_LIBADD) $(WINSOCK_LIBS)
+
+# X11
+
+libx11wrap_la_SOURCES = x11wrap.c x11wrap.h
+libx11wrap_la_LDFLAGS = -avoid-version
+libx11wrap_la_CFLAGS = $(AM_CFLAGS) $(X_CFLAGS)
+libx11wrap_la_LIBADD = $(AM_LIBADD) $(X_PRE_LIBS) -lX11 $(X_LIBS) $(X_EXTRA_LIBS)
+
+libx11prop_la_SOURCES = x11prop.c x11prop.h
+libx11prop_la_LDFLAGS = -avoid-version
+libx11prop_la_CFLAGS = $(AM_CFLAGS) $(X_CFLAGS)
+libx11prop_la_LIBADD = $(AM_LIBADD) $(X_PRE_LIBS) -lX11 $(X_LIBS) $(X_EXTRA_LIBS)
+
+# OSS
+
+liboss_util_la_SOURCES = oss-util.c oss-util.h
+liboss_util_la_LDFLAGS = -avoid-version
+
+# ALSA
+
+libalsa_util_la_SOURCES = alsa-util.c alsa-util.h
+libalsa_util_la_LDFLAGS = -avoid-version
+libalsa_util_la_LIBADD = $(AM_LIBADD) $(ASOUNDLIB_LIBS)
+libalsa_util_la_CFLAGS = $(AM_CFLAGS) $(ASOUNDLIB_CFLAGS)
+
+# HOWL
+
+libhowl_wrap_la_SOURCES = howl-wrap.c howl-wrap.h
+libhowl_wrap_la_LDFLAGS = -avoid-version
+libhowl_wrap_la_LIBADD = $(AM_LIBADD) $(HOWL_LIBS)
+libhowl_wrap_la_CFLAGS = $(AM_CFLAGS) $(HOWL_CFLAGS)
+
+###################################
+#        Plug-in libraries        #
+###################################
+
+modlib_LTLIBRARIES += \
+		module-cli.la \
+		module-cli-protocol-tcp.la \
+		module-cli-protocol-tcp6.la \
+		module-simple-protocol-tcp.la \
+		module-simple-protocol-tcp6.la \
+		module-esound-protocol-tcp.la \
+		module-esound-protocol-tcp6.la \
+		module-native-protocol-tcp.la \
+		module-native-protocol-tcp6.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-http-protocol-tcp6.la
+
+if HAVE_AF_UNIX
+modlib_LTLIBRARIES += \
+		module-cli-protocol-unix.la \
+		module-simple-protocol-unix.la \
+		module-esound-protocol-unix.la \
+		module-native-protocol-unix.la \
+		module-http-protocol-unix.la
+endif
+
+if HAVE_MKFIFO
+modlib_LTLIBRARIES += \
+		module-pipe-sink.la \
+		module-pipe-source.la
+endif
+
+if !OS_IS_WIN32
+modlib_LTLIBRARIES += \
+		module-esound-compat-spawnfd.la \
+		module-esound-compat-spawnpid.la
+endif
+
+if HAVE_REGEX
+modlib_LTLIBRARIES += \
+		module-match.la
+endif
+
+if HAVE_X11
+modlib_LTLIBRARIES += \
+		module-x11-bell.la \
+		module-x11-publish.la
+endif
+
+if !OS_IS_WIN32
+modlib_LTLIBRARIES += \
+		module-oss.la \
+		module-oss-mmap.la
+endif
+
+if HAVE_ALSA
+modlib_LTLIBRARIES += \
+		module-alsa-sink.la \
+		module-alsa-source.la
+endif
+
+if HAVE_HOWL
+modlib_LTLIBRARIES += \
+		module-zeroconf-publish.la
+endif
+
+if HAVE_LIRC
+modlib_LTLIBRARIES += \
+		module-lirc.la
+endif
+
+if HAVE_EVDEV
+modlib_LTLIBRARIES += \
+		module-mmkbd-evdev.la
+endif
+
+# These are generated by a M4 script
+
+SYMDEF_FILES = \
+		module-cli-symdef.h \
+		module-cli-protocol-tcp-symdef.h \
+		module-cli-protocol-tcp6-symdef.h \
+		module-cli-protocol-unix-symdef.h \
+		module-pipe-sink-symdef.h \
+		module-pipe-source-symdef.h \
+		module-simple-protocol-tcp-symdef.h \
+		module-simple-protocol-tcp6-symdef.h \
+		module-simple-protocol-unix-symdef.h \
+		module-esound-protocol-tcp-symdef.h \
+		module-esound-protocol-tcp6-symdef.h \
+		module-esound-protocol-unix-symdef.h \
+		module-native-protocol-tcp-symdef.h \
+		module-native-protocol-tcp6-symdef.h \
+		module-native-protocol-unix-symdef.h \
+		module-native-protocol-fd-symdef.h \
+		module-sine-symdef.h \
+		module-combine-symdef.h \
+		module-esound-compat-spawnfd-symdef.h \
+		module-esound-compat-spawnpid-symdef.h \
+		module-match-symdef.h \
+		module-tunnel-sink-symdef.h \
+		module-tunnel-source-symdef.h \
+		module-null-sink-symdef.h \
+		module-esound-sink-symdef.h \
+		module-zeroconf-publish-symdef.h \
+		module-lirc-symdef.h \
+		module-mmkbd-evdev-symdef.h \
+		module-http-protocol-tcp-symdef.h \
+		module-http-protocol-tcp6-symdef.h \
+		module-http-protocol-unix-symdef.h
+
+if HAVE_X11
+SYMDEF_FILES += \
+		module-x11-bell-symdef.h \
+		module-x11-publish-symdef.h
+endif
+
+if !OS_IS_WIN32
+SYMDEF_FILES += \
+		module-oss-symdef.h \
+		module-oss-mmap-symdef.h
+endif
+
+if HAVE_ALSA
+SYMDEF_FILES += \
+		module-alsa-sink-symdef.h \
+		module-alsa-source-symdef.h
+endif
+
+EXTRA_DIST += $(SYMDEF_FILES)
+BUILT_SOURCES += $(SYMDEF_FILES)
+
+$(SYMDEF_FILES): module-defs.h.m4
+	$(M4) -Dfname="$@" $< > $@
+
+# Simple protocol
 
 module_simple_protocol_tcp_la_SOURCES = module-protocol-stub.c
 module_simple_protocol_tcp_la_CFLAGS = -DUSE_TCP_SOCKETS -DUSE_PROTOCOL_SIMPLE $(AM_CFLAGS)
 module_simple_protocol_tcp_la_LDFLAGS = -module -avoid-version
-module_simple_protocol_tcp_la_LIBADD = $(AM_LIBADD) libprotocol-simple.la libsocket-server.la
+module_simple_protocol_tcp_la_LIBADD = $(AM_LIBADD) libpolypcore.la libprotocol-simple.la libsocket-server.la
 
 module_simple_protocol_tcp6_la_SOURCES = module-protocol-stub.c
 module_simple_protocol_tcp6_la_CFLAGS = -DUSE_TCP6_SOCKETS -DUSE_PROTOCOL_SIMPLE $(AM_CFLAGS)
 module_simple_protocol_tcp6_la_LDFLAGS = -module -avoid-version
-module_simple_protocol_tcp6_la_LIBADD = $(AM_LIBADD) libprotocol-simple.la libsocket-server.la
+module_simple_protocol_tcp6_la_LIBADD = $(AM_LIBADD) libpolypcore.la libprotocol-simple.la libsocket-server.la
 
 module_simple_protocol_unix_la_SOURCES = module-protocol-stub.c
 module_simple_protocol_unix_la_CFLAGS = -DUSE_UNIX_SOCKETS -DUSE_PROTOCOL_SIMPLE $(AM_CFLAGS)
 module_simple_protocol_unix_la_LDFLAGS = -module -avoid-version
-module_simple_protocol_unix_la_LIBADD = $(AM_LIBADD) libprotocol-simple.la libsocket-server.la libsocket-util.la
+module_simple_protocol_unix_la_LIBADD = $(AM_LIBADD) libpolypcore.la libprotocol-simple.la libsocket-server.la libsocket-util.la
+
+# CLI protocol
+
+module_cli_la_SOURCES = module-cli.c
+module_cli_la_LDFLAGS = -module -avoid-version
+module_cli_la_LIBADD = $(AM_LIBADD) libcli.la libiochannel.la libpolypcore.la
 
 module_cli_protocol_tcp_la_SOURCES = module-protocol-stub.c
 module_cli_protocol_tcp_la_CFLAGS = -DUSE_TCP_SOCKETS -DUSE_PROTOCOL_CLI $(AM_CFLAGS)
 module_cli_protocol_tcp_la_LDFLAGS = -module -avoid-version
-module_cli_protocol_tcp_la_LIBADD = $(AM_LIBADD) libprotocol-cli.la libsocket-server.la
+module_cli_protocol_tcp_la_LIBADD = $(AM_LIBADD) libpolypcore.la libprotocol-cli.la libsocket-server.la
 
 module_cli_protocol_tcp6_la_SOURCES = module-protocol-stub.c
 module_cli_protocol_tcp6_la_CFLAGS = -DUSE_TCP6_SOCKETS -DUSE_PROTOCOL_CLI $(AM_CFLAGS)
 module_cli_protocol_tcp6_la_LDFLAGS = -module -avoid-version
-module_cli_protocol_tcp6_la_LIBADD = $(AM_LIBADD) libprotocol-cli.la libsocket-server.la
+module_cli_protocol_tcp6_la_LIBADD = $(AM_LIBADD) libpolypcore.la libprotocol-cli.la libsocket-server.la
 
 module_cli_protocol_unix_la_SOURCES = module-protocol-stub.c
 module_cli_protocol_unix_la_CFLAGS = -DUSE_UNIX_SOCKETS -DUSE_PROTOCOL_CLI $(AM_CFLAGS)
 module_cli_protocol_unix_la_LDFLAGS = -module -avoid-version
-module_cli_protocol_unix_la_LIBADD = $(AM_LIBADD) libprotocol-cli.la libsocket-server.la libsocket-util.la
+module_cli_protocol_unix_la_LIBADD = $(AM_LIBADD) libpolypcore.la libprotocol-cli.la libsocket-server.la libsocket-util.la
+
+# HTTP protocol
 
 module_http_protocol_tcp_la_SOURCES = module-protocol-stub.c
 module_http_protocol_tcp_la_CFLAGS = -DUSE_TCP_SOCKETS -DUSE_PROTOCOL_HTTP $(AM_CFLAGS)
 module_http_protocol_tcp_la_LDFLAGS = -module -avoid-version
-module_http_protocol_tcp_la_LIBADD = $(AM_LIBADD) libprotocol-http.la libsocket-server.la
+module_http_protocol_tcp_la_LIBADD = $(AM_LIBADD) libpolypcore.la libprotocol-http.la libsocket-server.la
 
 module_http_protocol_tcp6_la_SOURCES = module-protocol-stub.c
 module_http_protocol_tcp6_la_CFLAGS = -DUSE_TCP6_SOCKETS -DUSE_PROTOCOL_HTTP $(AM_CFLAGS)
 module_http_protocol_tcp6_la_LDFLAGS = -module -avoid-version
-module_http_protocol_tcp6_la_LIBADD = $(AM_LIBADD) libprotocol-http.la libsocket-server.la
+module_http_protocol_tcp6_la_LIBADD = $(AM_LIBADD) libpolypcore.la libprotocol-http.la libsocket-server.la
 
 module_http_protocol_unix_la_SOURCES = module-protocol-stub.c
 module_http_protocol_unix_la_CFLAGS = -DUSE_UNIX_SOCKETS -DUSE_PROTOCOL_HTTP $(AM_CFLAGS)
 module_http_protocol_unix_la_LDFLAGS = -module -avoid-version
-module_http_protocol_unix_la_LIBADD = $(AM_LIBADD) libprotocol-http.la libsocket-server.la libsocket-util.la
+module_http_protocol_unix_la_LIBADD = $(AM_LIBADD) libpolypcore.la libprotocol-http.la libsocket-server.la libsocket-util.la
+
+# Native protocol
 
 module_native_protocol_tcp_la_SOURCES = module-protocol-stub.c
 module_native_protocol_tcp_la_CFLAGS = -DUSE_TCP_SOCKETS -DUSE_PROTOCOL_NATIVE $(AM_CFLAGS)
 module_native_protocol_tcp_la_LDFLAGS = -module -avoid-version
-module_native_protocol_tcp_la_LIBADD = $(AM_LIBADD) libprotocol-native.la libsocket-server.la
+module_native_protocol_tcp_la_LIBADD = $(AM_LIBADD) libpolypcore.la libprotocol-native.la libsocket-server.la
 
 module_native_protocol_tcp6_la_SOURCES = module-protocol-stub.c
 module_native_protocol_tcp6_la_CFLAGS = -DUSE_TCP6_SOCKETS -DUSE_PROTOCOL_NATIVE $(AM_CFLAGS)
 module_native_protocol_tcp6_la_LDFLAGS = -module -avoid-version
-module_native_protocol_tcp6_la_LIBADD = $(AM_LIBADD) libprotocol-native.la libsocket-server.la
+module_native_protocol_tcp6_la_LIBADD = $(AM_LIBADD) libpolypcore.la libprotocol-native.la libsocket-server.la
 
 module_native_protocol_unix_la_SOURCES = module-protocol-stub.c
 module_native_protocol_unix_la_CFLAGS = -DUSE_UNIX_SOCKETS -DUSE_PROTOCOL_NATIVE $(AM_CFLAGS)
 module_native_protocol_unix_la_LDFLAGS = -module -avoid-version
-module_native_protocol_unix_la_LIBADD = $(AM_LIBADD) libprotocol-native.la libsocket-server.la libsocket-util.la
+module_native_protocol_unix_la_LIBADD = $(AM_LIBADD) libpolypcore.la libprotocol-native.la libsocket-server.la libsocket-util.la
 
 module_native_protocol_fd_la_SOURCES = module-native-protocol-fd.c
 module_native_protocol_fd_la_CFLAGS = $(AM_CFLAGS)
 module_native_protocol_fd_la_LDFLAGS = -module -avoid-version
-module_native_protocol_fd_la_LIBADD = $(AM_LIBADD) libprotocol-native.la libsocket-server.la libsocket-util.la
+module_native_protocol_fd_la_LIBADD = $(AM_LIBADD) libpolypcore.la libprotocol-native.la libsocket-server.la libsocket-util.la libiochannel.la
+
+# EsounD protocol
 
 module_esound_protocol_tcp_la_SOURCES = module-protocol-stub.c
 module_esound_protocol_tcp_la_CFLAGS = -DUSE_TCP_SOCKETS -DUSE_PROTOCOL_ESOUND $(AM_CFLAGS)
 module_esound_protocol_tcp_la_LDFLAGS = -module -avoid-version
-module_esound_protocol_tcp_la_LIBADD = $(AM_LIBADD) libprotocol-esound.la libsocket-server.la
+module_esound_protocol_tcp_la_LIBADD = $(AM_LIBADD) libpolypcore.la libprotocol-esound.la libsocket-server.la
 
 module_esound_protocol_tcp6_la_SOURCES = module-protocol-stub.c
 module_esound_protocol_tcp6_la_CFLAGS = -DUSE_TCP6_SOCKETS -DUSE_PROTOCOL_ESOUND $(AM_CFLAGS)
 module_esound_protocol_tcp6_la_LDFLAGS = -module -avoid-version
-module_esound_protocol_tcp6_la_LIBADD = $(AM_LIBADD) libprotocol-esound.la libsocket-server.la
+module_esound_protocol_tcp6_la_LIBADD = $(AM_LIBADD) libpolypcore.la libprotocol-esound.la libsocket-server.la
 
 module_esound_protocol_unix_la_SOURCES = module-protocol-stub.c
 module_esound_protocol_unix_la_CFLAGS = -DUSE_UNIX_SOCKETS -DUSE_PROTOCOL_ESOUND $(AM_CFLAGS)
 module_esound_protocol_unix_la_LDFLAGS = -module -avoid-version
-module_esound_protocol_unix_la_LIBADD = $(AM_LIBADD) libprotocol-esound.la libsocket-server.la libsocket-util.la
+module_esound_protocol_unix_la_LIBADD = $(AM_LIBADD) libpolypcore.la libprotocol-esound.la libsocket-server.la libsocket-util.la
+
+module_esound_compat_spawnfd_la_SOURCES = module-esound-compat-spawnfd.c
+module_esound_compat_spawnfd_la_LDFLAGS = -module -avoid-version
+module_esound_compat_spawnfd_la_LIBADD = $(AM_LIBADD) libpolypcore.la
+
+module_esound_compat_spawnpid_la_SOURCES = module-esound-compat-spawnpid.c
+module_esound_compat_spawnpid_la_LDFLAGS = -module -avoid-version
+module_esound_compat_spawnpid_la_LIBADD = $(AM_LIBADD) libpolypcore.la
+
+module_esound_sink_la_SOURCES = module-esound-sink.c
+module_esound_sink_la_LDFLAGS = -module -avoid-version
+module_esound_sink_la_LIBADD = $(AM_LIBADD) libpolypcore.la libiochannel.la libsocket-client.la libauthkey.la
+
+# Pipes
 
 module_pipe_sink_la_SOURCES = module-pipe-sink.c
 module_pipe_sink_la_LDFLAGS = -module -avoid-version
-module_pipe_sink_la_LIBADD = $(AM_LIBADD) libiochannel.la
+module_pipe_sink_la_LIBADD = $(AM_LIBADD) libpolypcore.la libiochannel.la
 
 module_pipe_source_la_SOURCES = module-pipe-source.c
 module_pipe_source_la_LDFLAGS = -module -avoid-version
-module_pipe_source_la_LIBADD = $(AM_LIBADD) libiochannel.la
+module_pipe_source_la_LIBADD = $(AM_LIBADD) libpolypcore.la libiochannel.la
 
-module_oss_la_SOURCES = module-oss.c
-module_oss_la_LDFLAGS = -module -avoid-version
-module_oss_la_LIBADD = $(AM_LIBADD) libiochannel.la liboss-util.la
-
-module_oss_mmap_la_SOURCES = module-oss-mmap.c
-module_oss_mmap_la_LDFLAGS = -module -avoid-version
-module_oss_mmap_la_LIBADD = $(AM_LIBADD) liboss-util.la
-
-module_cli_la_SOURCES = module-cli.c
-module_cli_la_LDFLAGS = -module -avoid-version
-module_cli_la_LIBADD = $(AM_LIBADD) libcli.la libiochannel.la
+# Fake sources/sinks
 
 module_sine_la_SOURCES = module-sine.c
 module_sine_la_LDFLAGS = -module -avoid-version
-module_sine_la_LIBADD = $(AM_LIBADD)
-
-module_combine_la_SOURCES = module-combine.c
-module_combine_la_LDFLAGS = -module -avoid-version
-module_combine_la_LIBADD = $(AM_LIBADD)
+module_sine_la_LIBADD = $(AM_LIBADD) libpolypcore.la
 
 module_null_sink_la_SOURCES = module-null-sink.c
 module_null_sink_la_LDFLAGS = -module -avoid-version
-module_null_sink_la_LIBADD = $(AM_LIBADD)
+module_null_sink_la_LIBADD = $(AM_LIBADD) libpolypcore.la
+
+# Couplings
+
+module_combine_la_SOURCES = module-combine.c
+module_combine_la_LDFLAGS = -module -avoid-version
+module_combine_la_LIBADD = $(AM_LIBADD) libpolypcore.la
 
 module_match_la_SOURCES = module-match.c
 module_match_la_LDFLAGS = -module -avoid-version
-module_match_la_LIBADD = $(AM_LIBADD)
+module_match_la_LIBADD = $(AM_LIBADD) libpolypcore.la
 
 module_tunnel_sink_la_SOURCES = 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) 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_LIBADD = $(AM_LIBADD) libpolypcore.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 = module-tunnel.c
 module_tunnel_source_la_LDFLAGS = -module -avoid-version
-module_tunnel_source_la_LIBADD = $(AM_LIBADD) libsocket-client.la libpstream.la libpstream-util.la libpdispatch.la libtagstruct.la libauthkey.la libauthkey-prop.la libsocket-util.la libiochannel.la
-
-module_esound_compat_spawnfd_la_SOURCES = module-esound-compat-spawnfd.c
-module_esound_compat_spawnfd_la_LDFLAGS = -module -avoid-version
-module_esound_compat_spawnfd_la_LIBADD = $(AM_LIBADD)
-
-module_esound_compat_spawnpid_la_SOURCES = module-esound-compat-spawnpid.c
-module_esound_compat_spawnpid_la_LDFLAGS = -module -avoid-version
-module_esound_compat_spawnpid_la_LIBADD = $(AM_LIBADD)
-
-module_esound_sink_la_SOURCES = module-esound-sink.c
-module_esound_sink_la_LDFLAGS = -module -avoid-version
-module_esound_sink_la_LIBADD = $(AM_LIBADD) libsocket-client.la libauthkey.la
-
-libpolyp_ at PA_MAJORMINOR@_la_SOURCES = polyplib.h \
-		polyplib-def.h \
-		tagstruct.c tagstruct.h \
-		iochannel.c iochannel.h \
-		pstream.c pstream.h \
-		pstream-util.c pstream-util.h \
-		pdispatch.c pdispatch.h \
-		mainloop-api.c mainloop-api.h \
-		idxset.c idxset.h \
-		util.c util.h \
-		memblock.c memblock.h \
-		socket-client.c socket-client.h \
-		parseaddr.c parseaddr.h \
-		packet.c packet.h \
-		queue.c queue.h \
-		dynarray.c dynarray.h \
-		memchunk.c memchunk.h \
-		authkey.c authkey.h \
-		socket-util.c socket-util.h \
-		native-common.h \
-		sample.c sample.h \
-		xmalloc.c xmalloc.h \
-		polyplib-operation.c polyplib-operation.h \
-		polyplib-context.c polyplib-context.h \
-		polyplib-stream.c polyplib-stream.h \
-		polyplib-introspect.c polyplib-introspect.h \
-		polyplib-scache.c polyplib-scache.h \
-		polyplib-subscribe.c polyplib-subscribe.h \
-		polyplib-internal.h \
-		cdecl.h \
-		llist.h \
-		log.c log.h \
-		gcc-printf.h \
-		client-conf.c client-conf.h \
-		conf-parser.c conf-parser.h \
-		strlist.c strlist.h \
-		strbuf.c strbuf.h \
-		mcalign.c mcalign.h \
-		typeid.c typeid.h \
-		random.c random.h
-
-libpolyp_ at PA_MAJORMINOR@_la_CFLAGS = $(AM_CFLAGS)
-libpolyp_ at PA_MAJORMINOR@_la_LDFLAGS = -version-info 0:0:0
-libpolyp_ at PA_MAJORMINOR@_la_LIBADD = $(AM_LIBADD)
-
-libpolyp_mainloop_ at PA_MAJORMINOR@_la_SOURCES = mainloop-api.h mainloop-api.c \
-		mainloop.c mainloop.h \
-		mainloop-signal.c mainloop-signal.h
-libpolyp_mainloop_ at PA_MAJORMINOR@_la_CFLAGS = $(AM_CFLAGS)
-libpolyp_mainloop_ at PA_MAJORMINOR@_la_LIBADD = $(AM_LIBADD) libpolyp- at PA_MAJORMINOR@.la
-libpolyp_mainloop_ at PA_MAJORMINOR@_la_LDFLAGS = -version-info 0:0:0
-
-libpolyp_error_ at PA_MAJORMINOR@_la_SOURCES = polyplib-error.c polyplib-error.h
-libpolyp_error_ at PA_MAJORMINOR@_la_CFLAGS = $(AM_CFLAGS)
-libpolyp_error_ at PA_MAJORMINOR@_la_LIBADD = $(AM_LIBADD) libpolyp- at PA_MAJORMINOR@.la
-libpolyp_error_ at PA_MAJORMINOR@_la_LDFLAGS = -version-info 0:0:0
-
-libpolyp_simple_ at PA_MAJORMINOR@_la_SOURCES = polyplib-simple.c polyplib-simple.h 
-libpolyp_simple_ at PA_MAJORMINOR@_la_CFLAGS = $(AM_CFLAGS)
-libpolyp_simple_ at PA_MAJORMINOR@_la_LIBADD = $(AM_LIBADD) libpolyp- at PA_MAJORMINOR@.la libpolyp-mainloop- at PA_MAJORMINOR@.la
-libpolyp_simple_ at PA_MAJORMINOR@_la_LDFLAGS = -version-info 0:0:0
-
-pacat_SOURCES = pacat.c
-pacat_LDADD = $(AM_LDADD) libpolyp- at PA_MAJORMINOR@.la libpolyp-error- at PA_MAJORMINOR@.la libpolyp-mainloop- at PA_MAJORMINOR@.la
-pacat_CFLAGS = $(AM_CFLAGS) 
-
-paplay_SOURCES = paplay.c
-paplay_LDADD = $(AM_LDADD) libpolyp- at PA_MAJORMINOR@.la libpolyp-error- at PA_MAJORMINOR@.la libpolyp-mainloop- at PA_MAJORMINOR@.la $(LIBSNDFILE_LIBS)
-paplay_CFLAGS = $(AM_CFLAGS) $(LIBSNDFILE_CFLAGS)
+module_tunnel_source_la_LIBADD = $(AM_LIBADD) libpolypcore.la libsocket-client.la libpstream.la libpstream-util.la libpdispatch.la libtagstruct.la libauthkey.la libauthkey-prop.la libsocket-util.la libiochannel.la
 
-pactl_SOURCES = pactl.c
-pactl_LDADD = $(AM_LDADD) libpolyp- at PA_MAJORMINOR@.la libpolyp-error- at PA_MAJORMINOR@.la libpolyp-mainloop- at PA_MAJORMINOR@.la $(LIBSNDFILE_LIBS)
-pactl_CFLAGS = $(AM_CFLAGS) $(LIBSNDFILE_CFLAGS)
-
-pacat_simple_SOURCES = pacat-simple.c
-pacat_simple_LDADD = $(AM_LDADD) libpolyp- at PA_MAJORMINOR@.la libpolyp-simple- at PA_MAJORMINOR@.la libpolyp-error- at PA_MAJORMINOR@.la libpolyp-mainloop- at PA_MAJORMINOR@.la
-pacat_simple_CFLAGS = $(AM_CFLAGS)
-
-parec_simple_SOURCES = parec-simple.c
-parec_simple_LDADD = $(AM_LDADD) libpolyp- at PA_MAJORMINOR@.la libpolyp-simple- at PA_MAJORMINOR@.la libpolyp-error- at PA_MAJORMINOR@.la libpolyp-mainloop- at PA_MAJORMINOR@.la
-parec_simple_CFLAGS = $(AM_CFLAGS)
-
-mainloop_test_SOURCES = mainloop-test.c
-mainloop_test_CFLAGS = $(AM_CFLAGS)
-mainloop_test_LDADD = $(AM_LDADD) libpolyp-mainloop- at PA_MAJORMINOR@.la libpolyp- at PA_MAJORMINOR@.la
-
-voltest_SOURCES = voltest.c sample.c
-voltest_CFLAGS = $(AM_CFLAGS)
-voltest_LDADD = $(AM_LDADD)
-
-strlist_test_SOURCES = strlist-test.c strlist.c strlist.h strbuf.c strbuf.h util.c util.h xmalloc.c xmalloc.h log.c log.h
-strlist_test_CFLAGS = $(AM_CFLAGS)
-strlist_test_LDADD = $(AM_LDADD)
-
-mcalign_test_SOURCES = mcalign-test.c util.c util.h xmalloc.c xmalloc.h log.c log.h mcalign.c mcalign.h memchunk.c memchunk.h memblock.c memblock.h
-mcalign_test_CFLAGS = $(AM_CFLAGS)
-mcalign_test_LDADD = $(AM_LDADD)
-
-pacmd_SOURCES = pacmd.c util.c util.h xmalloc.c xmalloc.h log.c log.h pid.c pid.h
-pacmd_CFLAGS = $(AM_CFLAGS)
-pacmd_LDADD = $(AM_LDADD)
-
-cpulimit_test_SOURCES = cpulimit-test.c cpulimit.c util.c log.c cpulimit.h util.h log.h
-cpulimit_test_CFLAGS = $(AM_CFLAGS)
-cpulimit_test_LDADD = $(AM_LDADD) libpolyp-mainloop- at PA_MAJORMINOR@.la
-
-cpulimit_test2_SOURCES = cpulimit-test.c cpulimit.c util.c log.c cpulimit.h util.h log.h
-cpulimit_test2_CFLAGS = $(AM_CFLAGS) -DTEST2
-cpulimit_test2_LDADD = $(AM_LDADD) libpolyp-mainloop- at PA_MAJORMINOR@.la
-
-### X11 stuff
-
-if HAVE_X11
-modlib_LTLIBRARIES+= \
-		libx11wrap.la \
-		libx11prop.la \
-		module-x11-bell.la \
-		module-x11-publish.la
-SYMDEF_FILES += \
-		module-x11-bell-symdef.h \
-		module-x11-publish-symdef.h
-
-libx11wrap_la_SOURCES = x11wrap.c x11wrap.h
-libx11wrap_la_LDFLAGS = -avoid-version
-libx11wrap_la_CFLAGS = $(AM_CFLAGS) $(X_CFLAGS)
-libx11wrap_la_LIBADD = $(AM_LIBADD) $(X_PRE_LIBS) -lX11 $(X_LIBS) $(X_EXTRA_LIBS)
-
-libx11prop_la_SOURCES = x11prop.c x11prop.h
-libx11prop_la_LDFLAGS = -avoid-version
-libx11prop_la_CFLAGS = $(AM_CFLAGS) $(X_CFLAGS)
-libx11prop_la_LIBADD = $(AM_LIBADD) $(X_PRE_LIBS) -lX11 $(X_LIBS) $(X_EXTRA_LIBS)
+# X11
 
 module_x11_bell_la_SOURCES = module-x11-bell.c
 module_x11_bell_la_CFLAGS = $(AM_CFLAGS) $(X_CFLAGS)
@@ -598,41 +905,17 @@ 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
 
-bin_PROGRAMS+= \
-		pax11publish
+# OSS
 
-pax11publish_SOURCES = pax11publish.c util.c util.h xmalloc.c xmalloc.h log.c log.h authkey.c authkey.h client-conf.c client-conf.h conf-parser.c conf-parser.h x11prop.c x11prop.h random.c random.h
-pax11publish_CFLAGS = $(AM_CFLAGS) $(X_CFLAGS)
-pax11publish_LDADD = $(AM_LDADD) $(X_PRE_LIBS) -lX11 $(X_LIBS) $(X_EXTRA_LIBS)
-
-libpolyp_ at PA_MAJORMINOR@_la_CFLAGS += $(X_CFLAGS)
-libpolyp_ at PA_MAJORMINOR@_la_LDFLAGS += $(X_PRE_LIBS) -lX11 $(X_LIBS) $(X_EXTRA_LIBS)
-libpolyp_ at PA_MAJORMINOR@_la_SOURCES += x11prop.c x11prop.h client-conf-x11.c client-conf-x11.h
-
-endif
-
-### libasyncns stuff
-
-if HAVE_LIBASYNCNS
-libpolyp_ at PA_MAJORMINOR@_la_CFLAGS += $(LIBASYNCNS_CFLAGS)
-libpolyp_ at PA_MAJORMINOR@_la_LIBADD += $(LIBASYNCNS_LIBS)
-endif
-
-### ALSA modules
+module_oss_la_SOURCES = module-oss.c
+module_oss_la_LDFLAGS = -module -avoid-version
+module_oss_la_LIBADD = $(AM_LIBADD) libiochannel.la liboss-util.la
 
-if HAVE_ALSA
-modlib_LTLIBRARIES+= \
-		libalsa-util.la \
-		module-alsa-sink.la \
-		module-alsa-source.la
-SYMDEF_FILES += \
-		module-alsa-sink-symdef.h \
-		module-alsa-source-symdef.h
+module_oss_mmap_la_SOURCES = module-oss-mmap.c
+module_oss_mmap_la_LDFLAGS = -module -avoid-version
+module_oss_mmap_la_LIBADD = $(AM_LIBADD) liboss-util.la
 
-libalsa_util_la_SOURCES = alsa-util.c alsa-util.h
-libalsa_util_la_LDFLAGS = -avoid-version
-libalsa_util_la_LIBADD = $(AM_LIBADD) $(ASOUNDLIB_LIBS)
-libalsa_util_la_CFLAGS = $(AM_CFLAGS) $(ASOUNDLIB_CFLAGS)
+# ALSA
 
 module_alsa_sink_la_SOURCES = module-alsa-sink.c
 module_alsa_sink_la_LDFLAGS = -module -avoid-version
@@ -643,184 +926,31 @@ module_alsa_source_la_SOURCES = module-alsa-source.c
 module_alsa_source_la_LDFLAGS = -module -avoid-version
 module_alsa_source_la_LIBADD = $(AM_LIBADD) $(ASOUNDLIB_LIBS) libalsa-util.la
 module_alsa_source_la_CFLAGS = $(AM_CFLAGS) $(ASOUNDLIB_CFLAGS)
-endif
 
-### HOWL modules
-if HAVE_HOWL
-modlib_LTLIBRARIES+= \
-		libhowl-wrap.la \
-		module-zeroconf-publish.la
-
-libhowl_wrap_la_SOURCES = howl-wrap.c howl-wrap.h
-libhowl_wrap_la_LDFLAGS = -avoid-version
-libhowl_wrap_la_LIBADD = $(AM_LIBADD) $(HOWL_LIBS)
-libhowl_wrap_la_CFLAGS = $(AM_CFLAGS) $(HOWL_CFLAGS)
+# HOWL
 
 module_zeroconf_publish_la_SOURCES = module-zeroconf-publish.c
 module_zeroconf_publish_la_LDFLAGS = -module -avoid-version
 module_zeroconf_publish_la_LIBADD = $(AM_LIBADD) $(HOWL_LIBS) libhowl-wrap.la
 module_zeroconf_publish_la_CFLAGS = $(AM_CFLAGS) $(HOWL_CFLAGS)
 
-lib_LTLIBRARIES+= \
-		libpolyp-browse- at PA_MAJORMINOR@.la
-
-libpolyp_browse_ at PA_MAJORMINOR@_la_SOURCES = polyplib-browser.c polyplib-browser.h 
-libpolyp_browse_ at PA_MAJORMINOR@_la_CFLAGS = $(AM_CFLAGS) $(HOWL_CFLAGS)
-libpolyp_browse_ at PA_MAJORMINOR@_la_LIBADD = $(AM_LIBADD) libpolyp- at PA_MAJORMINOR@.la $(HOWL_LIBS)
-libpolyp_browse_ at PA_MAJORMINOR@_la_LDFLAGS = -version-info 0:0:0 
-
-bin_PROGRAMS += \
-		pabrowse
-
-pabrowse_SOURCES = pabrowse.c
-pabrowse_LDADD = $(AM_LDADD) libpolyp- at PA_MAJORMINOR@.la libpolyp-error- at PA_MAJORMINOR@.la libpolyp-mainloop- at PA_MAJORMINOR@.la libpolyp-browse- at PA_MAJORMINOR@.la
-pabrowse_CFLAGS = $(AM_CFLAGS)
-
-polypinclude_HEADERS+=polyplib-browser.h
-
-endif
-
-### GLIB 2.0 support
-
-if HAVE_GLIB20
-lib_LTLIBRARIES+= \
-		libpolyp-mainloop-glib- at PA_MAJORMINOR@.la
-
-noinst_PROGRAMS+= \
-		mainloop-test-glib
-
-libpolyp_mainloop_glib_ at PA_MAJORMINOR@_la_SOURCES = glib-mainloop.h glib-mainloop.c
-libpolyp_mainloop_glib_ at PA_MAJORMINOR@_la_CFLAGS = $(AM_CFLAGS) $(GLIB20_CFLAGS)
-libpolyp_mainloop_glib_ at PA_MAJORMINOR@_la_LIBADD = $(AM_LIBADD) libpolyp-mainloop- at PA_MAJORMINOR@.la $(GLIB20_LIBS)
-libpolyp_mainloop_glib_ at PA_MAJORMINOR@_la_LDFLAGS = -version-info 0:0:0
-
-mainloop_test_glib_SOURCES = $(mainloop_test_SOURCES)
-mainloop_test_glib_CFLAGS = $(mainloop_test_CFLAGS) $(GLIB20_CFLAGS) -DGLIB_MAIN_LOOP
-mainloop_test_glib_LDADD = $(mainloop_test_LDADD) $(GLIB20_LIBS) libpolyp-mainloop-glib- at PA_MAJORMINOR@.la
-endif
-
-### GLIB 1.2 support
-
-if HAVE_GLIB12
-
-lib_LTLIBRARIES+= \
-		libpolyp-mainloop-glib12- at PA_MAJORMINOR@.la
-
-noinst_PROGRAMS+= \
-		mainloop-test-glib12
-
-libpolyp_mainloop_glib12_ at PA_MAJORMINOR@_la_SOURCES = glib-mainloop.h glib12-mainloop.c
-libpolyp_mainloop_glib12_ at PA_MAJORMINOR@_la_CFLAGS = $(AM_CFLAGS) $(GLIB12_CFLAGS)
-libpolyp_mainloop_glib12_ at PA_MAJORMINOR@_la_LIBADD = $(AM_LIBADD) libpolyp-mainloop- at PA_MAJORMINOR@.la $(GLIB12_LIBS)
-libpolyp_mainloop_glib12_ at PA_MAJORMINOR@_la_LDFLAGS = -version-info 0:0:0
-
-mainloop_test_glib12_SOURCES = $(mainloop_test_SOURCES)
-mainloop_test_glib12_CFLAGS = $(mainloop_test_CFLAGS) $(GLIB12_CFLAGS) -DGLIB_MAIN_LOOP
-mainloop_test_glib12_LDADD = $(mainloop_test_LDADD) $(GLIB12_LIBS) libpolyp-mainloop-glib12- at PA_MAJORMINOR@.la
-
-endif
-
-### LIRC support
-
-if HAVE_LIRC
-
-modlib_LTLIBRARIES+= \
-		module-lirc.la
+# LIRC
 
 module_lirc_la_SOURCES = module-lirc.c
 module_lirc_la_LDFLAGS = -module -avoid-version
 module_lirc_la_LIBADD = $(AM_LIBADD) $(LIRC_LIBS) 
 module_lirc_la_CFLAGS = $(AM_CFLAGS) $(LIRC_CFLAGS)
 
-endif
-
-
-### Linux evdev
-
-if HAVE_EVDEV
-
-modlib_LTLIBRARIES+= \
-		module-mmkbd-evdev.la
+# Linux evdev
 
 module_mmkbd_evdev_la_SOURCES = module-mmkbd-evdev.c
 module_mmkbd_evdev_la_LDFLAGS = -module -avoid-version
 module_mmkbd_evdev_la_LIBADD = $(AM_LIBADD)
 module_mmkbd_evdev_la_CFLAGS = $(AM_CFLAGS)
 
-endif
-
-### libpolypcore (needs to be updated)
-
-if BUILD_LIBPOLYPCORE
-
-polypinclude_HEADERS+=cli-command.h\
-		client.h \
-		core.h \
-		dynarray.h \
-		endianmacros.h \
-		hashmap.h \
-		idxset.h \
-		iochannel.h \
-		memblock.h \
-		memblockq.h \
-		memchunk.h \
-		modargs.h \
-		module.h \
-		namereg.h \
-		queue.h \
-		resampler.h \
-		sample-util.h \
-		sink.h \
-		sink-input.h \
-		sioman.h \
-		socket-server.h \
-		socket-client.h \
-		socket-util.h \
-		source.h \
-		source-output.h \
-		strbuf.h \
-		tokenizer.h \
-		tagstruct.h \
-		util.h
-
-lib_LTLIBRARIES+= libpolypcore.la
-
-libpolypcore_la_SOURCES = idxset.c idxset.h \
-		queue.c queue.h \
-		strbuf.c strbuf.h \
-		mainloop.c mainloop.h \
-		memblock.c memblock.h \
-		sample.c sample.h \
-		sample-util.c sample-util.h \
-		memblockq.c memblockq.h \
-		client.c client.h \
-		core.c core.h \
-		source-output.c source-output.h \
-		sink-input.c sink-input.h \
-		source.c source.h \
-		sink.c sink.h \
-		module.c module.h \
-		mainloop-signal.c mainloop-signal.h \
-		mainloop-api.c mainloop-api.h \
-		util.c util.h \
-		hashmap.c hashmap.h \
-		namereg.c namereg.h \
-		sconv.c sconv.h \
-		resampler.c resampler.h \
-		endianmacros.h \
-		memchunk.c memchunk.h \
-		sconv-s16le.c sconv-s16le.h \
-		sconv-s16be.c sconv-s16be.h \
-		sioman.c sioman.h \
-		modargs.c modargs.h \
-		cli-command.c cli-command.h \
-		cli-text.c cli-text.h \
-		tokenizer.c tokenizer.h \
-		dynarray.c dynarray.h
-
-endif
-
-### Some minor stuff
+###################################
+#        Some minor stuff         #
+###################################
 
 suid: polypaudio
 	chown root $<
@@ -845,6 +975,3 @@ install-exec-hook:
 	chown root $(DESTDIR)$(bindir)/polypaudio ; true
 	chmod u+s $(DESTDIR)$(bindir)/polypaudio
 	ln -sf pacat $(DESTDIR)$(bindir)/parec
-
-$(SYMDEF_FILES): module-defs.h.m4
-	$(M4) -Dfname="$@" $< > $@

commit e8c71ed4c63a7ef123c122161b6a7cc3eafe7c85
Author: Pierre Ossman <ossman at cendio.se>
Date:   Thu Jan 5 13:14:21 2006 +0000

    Since README is generated conditionally we must make sure there are no
    dependencies on it when it's not built.
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/ossman@363 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/Makefile.am b/Makefile.am
index a6a012a..2cf93c7 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -17,11 +17,11 @@
 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
 # USA.
 
-EXTRA_DIST = bootstrap.sh README LICENSE doxygen/Makefile.am doxygen/Makefile.in doxygen/doxygen.conf.in libtool.m4 ltdl.m4
+EXTRA_DIST = bootstrap.sh LICENSE doxygen/Makefile.am doxygen/Makefile.in doxygen/doxygen.conf.in libtool.m4 ltdl.m4
 SUBDIRS=libltdl polyp doc
 
-MAINTAINERCLEANFILES=README
-noinst_DATA = README
+MAINTAINERCLEANFILES =
+noinst_DATA =
 
 pkgconfigdir = $(libdir)/pkgconfig
 pkgconfig_DATA = polyplib.pc polyplib-simple.pc polyplib-error.pc polyplib-mainloop.pc polyplib-browse.pc
@@ -36,10 +36,16 @@ pkgconfig_DATA += \
 	polyplib-glib12-mainloop.pc
 endif
 
+if USE_LYNX
+EXTRA_DIST += README
+MAINTAINERCLEANFILES += README
+noinst_DATA += README
+
 README:
 	rm -f README
 	$(MAKE) -C doc README
 	cd $(srcdir) && ln -s doc/README README
+endif
 
 homepage: all dist doxygen
 	test -d $$HOME/homepage/private
diff --git a/doc/Makefile.am b/doc/Makefile.am
index fff0655..c68c00f 100644
--- a/doc/Makefile.am
+++ b/doc/Makefile.am
@@ -16,7 +16,7 @@
 # along with polypaudio; if not, write to the Free Software Foundation,
 # Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
 
-noinst_DATA = README.html cli.html modules.html daemon.html README
+noinst_DATA = README.html cli.html modules.html daemon.html
 EXTRA_DIST = $(noinst_DATA) style.css README.html.in cli.html.in modules.html.in daemon.html.in todo FAQ.html.in
 
 MAINTAINERCLEANFILES = README.html cli.html modules.html daemon.html FAQ.html
@@ -26,6 +26,7 @@ if USE_LYNX
 README: README.html
 	lynx --dump $^ | sed 's,file://localhost/.*/doc/README.html,README,' > $@
 
+noinst_DATA += README
 CLEANFILES += README
 endif
 

commit 11a4c67a922c3af62c80500aca7f157430fdf926
Author: Pierre Ossman <ossman at cendio.se>
Date:   Thu Jan 5 13:15:38 2006 +0000

    Remove unused automake conditional.
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/ossman@364 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/configure.ac b/configure.ac
index 362077f..0027339 100644
--- a/configure.ac
+++ b/configure.ac
@@ -283,8 +283,6 @@ AM_CONDITIONAL([HAVE_LIRC], [test "x$HAVE_LIRC" = x1])
 #            Output               #
 ###################################
 
-AM_CONDITIONAL(BUILD_LIBPOLYPCORE, false)
-
 AC_CONFIG_FILES([
 Makefile
 polyp/Makefile

commit 70710e14d8f8bbab4f1a42db4993f27cb2ca7bc5
Author: Pierre Ossman <ossman at cendio.se>
Date:   Thu Jan 5 13:20:20 2006 +0000

    Check for OSS by looking for its header. Win32 isn't the only platform
    where OSS isn't supported.
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/ossman@365 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/configure.ac b/configure.ac
index 0027339..c851164 100644
--- a/configure.ac
+++ b/configure.ac
@@ -223,6 +223,12 @@ PKG_CHECK_MODULES(LIBSNDFILE, [ sndfile >= 1.0.10 ])
 AC_SUBST(LIBSNDFILE_CFLAGS)
 AC_SUBST(LIBSNDFILE_LIBS)
 
+#### OSS support (optional) ####
+
+AC_CHECK_HEADERS([sys/soundcard.h], [HAVE_OSS=1], [HAVE_OSS=0])
+AC_SUBST(HAVE_OSS)
+AM_CONDITIONAL([HAVE_OSS], [test "x$HAVE_OSS" = x1])
+
 #### ALSA support (optional) ####
 
 PKG_CHECK_MODULES(ASOUNDLIB, [ alsa >= 1.0.0 ], [HAVE_ALSA=1], [HAVE_ALSA=0])
diff --git a/polyp/Makefile.am b/polyp/Makefile.am
index 847be9a..2cd2a1f 100644
--- a/polyp/Makefile.am
+++ b/polyp/Makefile.am
@@ -478,7 +478,7 @@ modlib_LTLIBRARIES += \
 		libx11prop.la
 endif
 
-if !OS_IS_WIN32
+if HAVE_OSS
 modlib_LTLIBRARIES += \
 		liboss-util.la
 endif
@@ -662,7 +662,7 @@ modlib_LTLIBRARIES += \
 		module-x11-publish.la
 endif
 
-if !OS_IS_WIN32
+if HAVE_OSS
 modlib_LTLIBRARIES += \
 		module-oss.la \
 		module-oss-mmap.la

commit 687e2d7da5d55784bf0769774be7296254a08eba
Author: Pierre Ossman <ossman at cendio.se>
Date:   Thu Jan 5 16:38:09 2006 +0000

    Abstract the gettimeofday call into a utility function to ease porting.
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/ossman@366 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/polyp/core.c b/polyp/core.c
index e2bebec..539c677 100644
--- a/polyp/core.c
+++ b/polyp/core.c
@@ -144,7 +144,7 @@ void pa_core_check_quit(struct pa_core *c) {
 
     if (!c->quit_event && c->exit_idle_time >= 0 && pa_idxset_ncontents(c->clients) == 0) {
         struct timeval tv;
-        gettimeofday(&tv, NULL);
+        pa_gettimeofday(&tv);
         tv.tv_sec+= c->exit_idle_time;
         c->quit_event = c->mainloop->time_new(c->mainloop, &tv, quit_callback, c);
     } else if (c->quit_event && pa_idxset_ncontents(c->clients) > 0) {
diff --git a/polyp/glib-mainloop.c b/polyp/glib-mainloop.c
index 809c0b0..0f96a59 100644
--- a/polyp/glib-mainloop.c
+++ b/polyp/glib-mainloop.c
@@ -241,7 +241,7 @@ static void glib_time_restart(struct pa_time_event*e, const struct timeval *tv)
     struct timeval now;
     assert(e && e->mainloop && !e->dead);
 
-    gettimeofday(&now, NULL);
+    pa_gettimeofday(&now);
     if (e->source) {
         g_source_destroy(e->source);
         g_source_unref(e->source);
diff --git a/polyp/glib12-mainloop.c b/polyp/glib12-mainloop.c
index 5f03734..c328471 100644
--- a/polyp/glib12-mainloop.c
+++ b/polyp/glib12-mainloop.c
@@ -233,7 +233,7 @@ static void glib_time_restart(struct pa_time_event*e, const struct timeval *tv)
     struct timeval now;
     assert(e && e->mainloop && !e->dead);
 
-    gettimeofday(&now, NULL);
+    pa_gettimeofday(&now);
     if (e->source != (guint) -1)
         g_source_remove(e->source);
 
diff --git a/polyp/mainloop-test.c b/polyp/mainloop-test.c
index 0d40e76..dd8f813 100644
--- a/polyp/mainloop-test.c
+++ b/polyp/mainloop-test.c
@@ -111,7 +111,7 @@ int main(int argc, char *argv[]) {
     de = a->defer_new(a, dcb, NULL);
     assert(de);
 
-    gettimeofday(&tv, NULL);
+    pa_gettimeofday(&tv);
     tv.tv_sec += 10;
     te = a->time_new(a, &tv, tcb, NULL);
 
diff --git a/polyp/mainloop.c b/polyp/mainloop.c
index f6bb414..a0d2782 100644
--- a/polyp/mainloop.c
+++ b/polyp/mainloop.c
@@ -457,7 +457,7 @@ static int calc_next_timeout(struct pa_mainloop *m) {
 
         /* Let's save a system call */
         if (!got_time) {
-            gettimeofday(&now, NULL);
+            pa_gettimeofday(&now);
             got_time = 1;
         }
 
@@ -498,7 +498,7 @@ static int dispatch_timeout(struct pa_mainloop *m) {
 
         /* Let's save a system call */
         if (!got_time) {
-            gettimeofday(&now, NULL);
+            pa_gettimeofday(&now);
             got_time = 1;
         }
         
diff --git a/polyp/module-combine.c b/polyp/module-combine.c
index ca79d7d..7283c55 100644
--- a/polyp/module-combine.c
+++ b/polyp/module-combine.c
@@ -157,7 +157,7 @@ static void time_callback(struct pa_mainloop_api*a, struct pa_time_event* e, con
 
     adjust_rates(u);
 
-    gettimeofday(&n, NULL);
+    pa_gettimeofday(&n);
     n.tv_sec += u->adjust_time;
     u->sink->core->mainloop->time_restart(e, &n);
 }
@@ -363,7 +363,7 @@ int pa__init(struct pa_core *c, struct pa_module*m) {
         pa_log_warn(__FILE__": WARNING: no slave sinks specified.\n");
 
     if (u->adjust_time > 0) {
-        gettimeofday(&tv, NULL);
+        pa_gettimeofday(&tv);
         tv.tv_sec += u->adjust_time;
         u->time_event = c->mainloop->time_new(c->mainloop, &tv, time_callback, u);
     }
diff --git a/polyp/module-null-sink.c b/polyp/module-null-sink.c
index fcac1ea..6c7a44f 100644
--- a/polyp/module-null-sink.c
+++ b/polyp/module-null-sink.c
@@ -117,7 +117,7 @@ int pa__init(struct pa_core *c, struct pa_module*m) {
     pa_sink_set_owner(u->sink, m);
     u->sink->description = pa_sprintf_malloc("NULL sink");
 
-    gettimeofday(&tv, NULL);
+    pa_gettimeofday(&tv);
     u->time_event = c->mainloop->time_new(c->mainloop, &tv, time_callback, u);
 
     u->block_size = pa_bytes_per_second(&ss) / 10;
diff --git a/polyp/module-tunnel.c b/polyp/module-tunnel.c
index 9da87b3..749aebf 100644
--- a/polyp/module-tunnel.c
+++ b/polyp/module-tunnel.c
@@ -284,7 +284,7 @@ static void stream_get_latency_callback(struct pa_pdispatch *pd, uint32_t comman
         return;
     }
 
-    gettimeofday(&now, NULL);
+    pa_gettimeofday(&now);
 
     if (pa_timeval_cmp(&local, &remote) < 0 && pa_timeval_cmp(&remote, &now)) {
         /* local and remote seem to have synchronized clocks */
@@ -324,7 +324,7 @@ static void request_latency(struct userdata *u) {
     pa_tagstruct_putu32(t, tag = u->ctag++);
     pa_tagstruct_putu32(t, u->channel);
 
-    gettimeofday(&now, NULL);
+    pa_gettimeofday(&now);
     pa_tagstruct_put_timeval(t, &now);
     pa_tagstruct_putu64(t, 0);
     
@@ -536,7 +536,7 @@ static void timeout_callback(struct pa_mainloop_api *m, struct pa_time_event*e,
 
     request_latency(u);
     
-    gettimeofday(&ntv, NULL);
+    pa_gettimeofday(&ntv);
     ntv.tv_sec += LATENCY_INTERVAL;
     m->time_restart(e, &ntv);
 }
@@ -650,7 +650,7 @@ int pa__init(struct pa_core *c, struct pa_module*m) {
     pa_source_set_owner(u->source, m);
 #endif
     
-    gettimeofday(&ntv, NULL);
+    pa_gettimeofday(&ntv);
     ntv.tv_sec += LATENCY_INTERVAL;
     u->time_event = c->mainloop->time_new(c->mainloop, &ntv, timeout_callback, u);
 
diff --git a/polyp/module.c b/polyp/module.c
index aedaae0..0a3d569 100644
--- a/polyp/module.c
+++ b/polyp/module.c
@@ -47,7 +47,7 @@ static void timeout_callback(struct pa_mainloop_api *m, struct pa_time_event*e,
 
     pa_module_unload_unused(c);
 
-    gettimeofday(&ntv, NULL);
+    pa_gettimeofday(&ntv);
     ntv.tv_sec += UNLOAD_POLL_TIME;
     m->time_restart(e, &ntv);
 }
@@ -98,7 +98,7 @@ struct pa_module* pa_module_load(struct pa_core *c, const char *name, const char
 
     if (!c->module_auto_unload_event) {
         struct timeval ntv;
-        gettimeofday(&ntv, NULL);
+        pa_gettimeofday(&ntv);
         ntv.tv_sec += UNLOAD_POLL_TIME;
         c->module_auto_unload_event = c->mainloop->time_new(c->mainloop, &ntv, timeout_callback, c);
     }
diff --git a/polyp/pdispatch.c b/polyp/pdispatch.c
index 7a9e9c6..9e80875 100644
--- a/polyp/pdispatch.c
+++ b/polyp/pdispatch.c
@@ -245,7 +245,7 @@ void pa_pdispatch_register_reply(struct pa_pdispatch *pd, uint32_t tag, int time
     r->userdata = userdata;
     r->tag = tag;
     
-    gettimeofday(&tv, NULL);
+    pa_gettimeofday(&tv);
     tv.tv_sec += timeout;
 
     r->time_event = pd->mainloop->time_new(pd->mainloop, &tv, timeout_callback, r);
diff --git a/polyp/polyplib-stream.c b/polyp/polyplib-stream.c
index 440217e..d4480f8 100644
--- a/polyp/polyplib-stream.c
+++ b/polyp/polyplib-stream.c
@@ -217,7 +217,7 @@ static void ipol_callback(struct pa_mainloop_api *m, struct pa_time_event *e, co
         s->ipol_requested = 1;
     }
     
-    gettimeofday(&tv2, NULL);
+    pa_gettimeofday(&tv2);
     pa_timeval_add(&tv2, LATENCY_IPOL_INTERVAL_USEC);
     
     m->time_restart(e, &tv2);
@@ -256,7 +256,7 @@ void pa_create_stream_callback(struct pa_pdispatch *pd, uint32_t command, uint32
         struct timeval tv;
         pa_operation_unref(pa_stream_get_latency_info(s, NULL, NULL));
 
-        gettimeofday(&tv, NULL);
+        pa_gettimeofday(&tv);
         tv.tv_usec += LATENCY_IPOL_INTERVAL_USEC; /* every 100 ms */
 
         assert(!s->ipol_event);
@@ -412,7 +412,7 @@ static void stream_get_latency_info_callback(struct pa_pdispatch *pd, uint32_t c
         pa_context_fail(o->context, PA_ERROR_PROTOCOL);
         goto finish;
     } else {
-        gettimeofday(&now, NULL);
+        pa_gettimeofday(&now);
         
         if (pa_timeval_cmp(&local, &remote) < 0 && pa_timeval_cmp(&remote, &now)) {
             /* local and remote seem to have synchronized clocks */
@@ -470,7 +470,7 @@ struct pa_operation* pa_stream_get_latency_info(struct pa_stream *s, void (*cb)(
     pa_tagstruct_putu32(t, tag = s->context->ctag++);
     pa_tagstruct_putu32(t, s->channel);
 
-    gettimeofday(&now, NULL);
+    pa_gettimeofday(&now);
     pa_tagstruct_put_timeval(t, &now);
     pa_tagstruct_putu64(t, s->counter);
     
@@ -581,7 +581,7 @@ struct pa_operation* pa_stream_cork(struct pa_stream *s, int b, void (*cb) (stru
             s->ipol_usec = pa_stream_get_interpolated_time(s);
         else if (s->corked && !b)
             /* Unpausing */
-            gettimeofday(&s->ipol_timestamp, NULL);
+            pa_gettimeofday(&s->ipol_timestamp);
     }
 
     s->corked = b;
diff --git a/polyp/protocol-esound.c b/polyp/protocol-esound.c
index d99b721..2af3cc8 100644
--- a/polyp/protocol-esound.c
+++ b/polyp/protocol-esound.c
@@ -1099,7 +1099,7 @@ static void on_connection(struct pa_socket_server*s, struct pa_iochannel *io, vo
 
     if (!c->authorized) {
         struct timeval tv;
-        gettimeofday(&tv, NULL);
+        pa_gettimeofday(&tv);
         tv.tv_sec += AUTH_TIMEOUT;
         c->auth_timeout_event = p->core->mainloop->time_new(p->core->mainloop, &tv, auth_timeout, c);
     } else
diff --git a/polyp/protocol-native.c b/polyp/protocol-native.c
index 7e1a889..90dbdaf 100644
--- a/polyp/protocol-native.c
+++ b/polyp/protocol-native.c
@@ -928,7 +928,7 @@ static void command_get_playback_latency(struct pa_pdispatch *pd, uint32_t comma
     pa_tagstruct_put_boolean(reply, pa_memblockq_is_readable(s->memblockq));
     pa_tagstruct_putu32(reply, pa_memblockq_get_length(s->memblockq));
     pa_tagstruct_put_timeval(reply, &tv);
-    gettimeofday(&now, NULL);
+    pa_gettimeofday(&now);
     pa_tagstruct_put_timeval(reply, &now);
     pa_tagstruct_putu64(reply, counter);
     pa_pstream_send_tagstruct(c->pstream, reply);
@@ -971,7 +971,7 @@ static void command_get_record_latency(struct pa_pdispatch *pd, uint32_t command
     pa_tagstruct_put_boolean(reply, 0);
     pa_tagstruct_putu32(reply, pa_memblockq_get_length(s->memblockq));
     pa_tagstruct_put_timeval(reply, &tv);
-    gettimeofday(&now, NULL);
+    pa_gettimeofday(&now);
     pa_tagstruct_put_timeval(reply, &now);
     pa_tagstruct_putu64(reply, counter);
     pa_pstream_send_tagstruct(c->pstream, reply);
@@ -2024,7 +2024,7 @@ static void on_connection(struct pa_socket_server*s, struct pa_iochannel *io, vo
 
     if (!c->authorized) {
         struct timeval tv;
-        gettimeofday(&tv, NULL);
+        pa_gettimeofday(&tv);
         tv.tv_sec += AUTH_TIMEOUT;
         c->auth_timeout_event = p->core->mainloop->time_new(p->core->mainloop, &tv, auth_timeout, c);
     } else
diff --git a/polyp/scache.c b/polyp/scache.c
index ccdc718..143f974 100644
--- a/polyp/scache.c
+++ b/polyp/scache.c
@@ -55,7 +55,7 @@ static void timeout_callback(struct pa_mainloop_api *m, struct pa_time_event*e,
 
     pa_scache_unload_unused(c);
 
-    gettimeofday(&ntv, NULL);
+    pa_gettimeofday(&ntv);
     ntv.tv_sec += UNLOAD_POLL_TIME;
     m->time_restart(e, &ntv);
 }
@@ -165,7 +165,7 @@ int pa_scache_add_file_lazy(struct pa_core *c, const char *name, const char *fil
     
     if (!c->scache_auto_unload_event) {
         struct timeval ntv;
-        gettimeofday(&ntv, NULL);
+        pa_gettimeofday(&ntv);
         ntv.tv_sec += UNLOAD_POLL_TIME;
         c->scache_auto_unload_event = c->mainloop->time_new(c->mainloop, &ntv, timeout_callback, c);
     }
diff --git a/polyp/socket-client.c b/polyp/socket-client.c
index 21563d3..f02b74b 100644
--- a/polyp/socket-client.c
+++ b/polyp/socket-client.c
@@ -377,7 +377,7 @@ static void start_timeout(struct pa_socket_client *c) {
     assert(c);
     assert(!c->timeout_event);
 
-    gettimeofday(&tv, NULL);
+    pa_gettimeofday(&tv);
     pa_timeval_add(&tv, CONNECT_TIMEOUT * 1000000);
     c->timeout_event = c->mainloop->time_new(c->mainloop, &tv, timeout_cb, c);
 }
diff --git a/polyp/util.c b/polyp/util.c
index ee3fa87..699480a 100644
--- a/polyp/util.c
+++ b/polyp/util.c
@@ -302,6 +302,14 @@ char *pa_strlcpy(char *b, const char *s, size_t l) {
     return b;
 }
 
+int pa_gettimeofday(struct timeval *tv) {
+#ifdef HAVE_GETTIMEOFDAY
+    return gettimeofday(tv, NULL);
+#else
+#error "Platform lacks gettimeofday() or equivalent function."
+#endif
+}
+
 /* Calculate the difference between the two specfified timeval
  * timestamsps. */
 pa_usec_t pa_timeval_diff(const struct timeval *a, const struct timeval *b) {
@@ -351,7 +359,7 @@ 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);
-    gettimeofday(&now, NULL);
+    pa_gettimeofday(&now);
     return pa_timeval_diff(&now, tv);
 }
 
diff --git a/polyp/util.h b/polyp/util.h
index 2cfc5f6..745d8f0 100644
--- a/polyp/util.h
+++ b/polyp/util.h
@@ -53,6 +53,7 @@ char *pa_get_home_dir(char *s, size_t l);
 
 char *pa_path_get_filename(const char *p);
 
+int pa_gettimeofday(struct timeval *tv);
 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);
 pa_usec_t pa_timeval_age(const struct timeval *tv);

commit f6b0f87d0af87289204ee7b251bd9e23584ebc6b
Author: Pierre Ossman <ossman at cendio.se>
Date:   Thu Jan 5 16:42:00 2006 +0000

    Remove unnecessary dependency on timeval definition.
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/ossman@367 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/polyp/util.h b/polyp/util.h
index 745d8f0..d9e18dd 100644
--- a/polyp/util.h
+++ b/polyp/util.h
@@ -30,6 +30,8 @@
 #include "gcc-printf.h"
 #include "sample.h"
 
+struct timeval;
+
 void pa_make_nonblock_fd(int fd);
 
 int pa_make_secure_dir(const char* dir);

commit 3f2ac7eb8ce8db8947f1bfc195f845be0d409fde
Author: Pierre Ossman <ossman at cendio.se>
Date:   Thu Jan 5 17:14:51 2006 +0000

    We have a generic function for extracting the filename, let's use it.
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/ossman@368 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/polyp/scache.c b/polyp/scache.c
index 143f974..54563ba 100644
--- a/polyp/scache.c
+++ b/polyp/scache.c
@@ -303,10 +303,7 @@ static void add_file(struct pa_core *c, const char *pathname) {
     struct stat st;
     const char *e;
 
-    if (!(e = strrchr(pathname, '/')))
-        e = pathname;
-    else
-        e++;
+    e = pa_path_get_filename(pathname);
     
     if (stat(pathname, &st) < 0) {
         pa_log(__FILE__": stat('%s') failed: %s\n", pathname, strerror(errno));

commit 70223bac46f53f89041db61d2a06ea772968ce2d
Author: Pierre Ossman <ossman at cendio.se>
Date:   Thu Jan 5 17:43:06 2006 +0000

    Fallbacks for systems that do not have getaddrinfo(). Does not handle
    IPv6 though.
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/ossman@369 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/configure.ac b/configure.ac
index c851164..450f18a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -166,8 +166,8 @@ AC_CHECK_LIB([m], [pow])
 AC_FUNC_FORK
 AC_FUNC_GETGROUPS
 AC_FUNC_SELECT_ARGTYPES
-AC_CHECK_FUNCS([ftruncate getgrgid_r getpwuid_r gettimeofday getuid \
-    inet_ntop mkfifo nanosleep sigaction sleep])
+AC_CHECK_FUNCS([getaddrinfo ftruncate getgrgid_r getpwuid_r gettimeofday \
+    getuid inet_ntop mkfifo nanosleep sigaction sleep])
 
 AM_CONDITIONAL(HAVE_MKFIFO, test "x$HAVE_MKFIFO" = "x1")
 
diff --git a/polyp/socket-client.c b/polyp/socket-client.c
index f02b74b..40bbcc3 100644
--- a/polyp/socket-client.c
+++ b/polyp/socket-client.c
@@ -426,8 +426,9 @@ struct pa_socket_client* pa_socket_client_new_string(struct pa_mainloop_api *m,
                 assert(c->asyncns_query);
                 start_timeout(c);
             }
-#else
+#else /* HAVE_LIBASYNCNS */
             {
+#ifdef HAVE_GETADDRINFO
                 int ret;
                 struct addrinfo *res = NULL;
 
@@ -438,12 +439,37 @@ struct pa_socket_client* pa_socket_client_new_string(struct pa_mainloop_api *m,
 
                 if (res->ai_addr) {
                     if ((c = pa_socket_client_new_sockaddr(m, res->ai_addr, res->ai_addrlen)))
-                    	start_timeout(c);
+                        start_timeout(c);
 				}
                 
                 freeaddrinfo(res);
+#else /* HAVE_GETADDRINFO */
+                struct hostent *host = NULL;
+                struct sockaddr_in s;
+
+		/* FIXME: PF_INET6 support */
+                if (hints.ai_family != PF_INET)
+                    goto finish;
+
+                host = gethostbyname(a.path_or_host);
+                if (!host) {
+                    unsigned int addr = inet_addr(a.path_or_host);
+                    if (addr != INADDR_NONE)
+                        host = gethostbyaddr((char*)&addr, 4, AF_INET);
+                }
+
+                if (!host)
+                    goto finish;
+
+                s.sin_family = AF_INET;
+                memcpy(&s.sin_addr, host->h_addr, sizeof(struct in_addr));
+                s.sin_port = port;
+
+                if ((c = pa_socket_client_new_sockaddr(m, &s, sizeof(s))))
+                	start_timeout(c);
+#endif /* HAVE_GETADDRINFO */
             }
-#endif            
+#endif /* HAVE_LIBASYNCNS */
         }
     }
 
diff --git a/polyp/util.c b/polyp/util.c
index 699480a..2c4285f 100644
--- a/polyp/util.c
+++ b/polyp/util.c
@@ -831,11 +831,14 @@ size_t pa_parsehex(const char *p, uint8_t *d, size_t dlength) {
 /* Return the fully qualified domain name in *s */
 char *pa_get_fqdn(char *s, size_t l) {
     char hn[256];
+#ifdef HAVE_GETADDRINFO    
     struct addrinfo *a, hints;
+#endif
 
     if (!pa_get_host_name(hn, sizeof(hn)))
         return NULL;
 
+#ifdef HAVE_GETADDRINFO
     memset(&hints, 0, sizeof(hints));
     hints.ai_family = AF_UNSPEC;
     hints.ai_flags = AI_CANONNAME;
@@ -846,6 +849,9 @@ char *pa_get_fqdn(char *s, size_t l) {
     pa_strlcpy(s, a->ai_canonname, l);
     freeaddrinfo(a);
     return s;
+#else
+    return pa_strlcpy(s, hn, l);
+#endif
 }
 
 /* Returns nonzero when *s starts with *pfx */

commit 2ce05b2b4bda7933b419495e715c41909c3adf7e
Author: Pierre Ossman <ossman at cendio.se>
Date:   Thu Jan 5 17:49:45 2006 +0000

    Glob is not present on all systems.
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/ossman@370 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/polyp/scache.c b/polyp/scache.c
index 54563ba..0dec33c 100644
--- a/polyp/scache.c
+++ b/polyp/scache.c
@@ -32,7 +32,10 @@
 #include <sys/stat.h>
 #include <errno.h>
 #include <limits.h>
+
+#ifdef HAVE_GLOB_H
 #include <glob.h>
+#endif
 
 #include "scache.h"
 #include "sink-input.h"
@@ -320,6 +323,7 @@ int pa_scache_add_directory_lazy(struct pa_core *c, const char *pathname) {
 
     /* First try to open this as directory */
     if (!(dir = opendir(pathname))) {
+#ifdef HAVE_GLOB_H
         glob_t p;
         unsigned int i;
         /* If that fails, try to open it as shell glob */
@@ -333,6 +337,9 @@ int pa_scache_add_directory_lazy(struct pa_core *c, const char *pathname) {
             add_file(c, p.gl_pathv[i]);
         
         globfree(&p);
+#else
+        return -1;
+#endif
     } else {
         struct dirent *e;
 

commit 3996c5f0485fd5bfbf401da846f53cf32aa474a8
Author: Pierre Ossman <ossman at cendio.se>
Date:   Thu Jan 5 17:59:32 2006 +0000

    SIXCPU isn't present on all platforms. Replace cpulimit with dummy functions
    on those systems.
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/ossman@371 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/polyp/cpulimit.c b/polyp/cpulimit.c
index 0fab98a..f121123 100644
--- a/polyp/cpulimit.c
+++ b/polyp/cpulimit.c
@@ -23,6 +23,8 @@
 #include <config.h>
 #endif
 
+#ifdef HAVE_SIGXCPU
+
 #include <errno.h>
 #include <stdio.h>
 #include <string.h>
@@ -219,3 +221,16 @@ void pa_cpu_limit_done(void) {
         installed = 0;
     }
 }
+
+#else /* HAVE_SIGXCPU */
+
+struct pa_mainloop_api;
+
+int pa_cpu_limit_init(struct pa_mainloop_api *m) {
+    return 0;
+}
+
+void pa_cpu_limit_done(void) {
+}
+
+#endif

commit 8c5a75dfb2414aad449ad5de3354afdb48d556a7
Author: Pierre Ossman <ossman at cendio.se>
Date:   Thu Jan 5 18:00:39 2006 +0000

    Syslog is not present on all platforms.
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/ossman@372 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/polyp/log.c b/polyp/log.c
index 78736a4..2bbf2e8 100644
--- a/polyp/log.c
+++ b/polyp/log.c
@@ -25,9 +25,12 @@
 
 #include <assert.h>
 #include <stdarg.h>
-#include <syslog.h>
 #include <stdio.h>
 
+#ifdef HAVE_SYSLOG_H
+#include <syslog.h>
+#endif
+
 #include "log.h"
 #include "xmalloc.h"
 #include "util.h"
@@ -39,6 +42,7 @@ static enum pa_log_target log_target = PA_LOG_STDERR;
 static void (*user_log_func)(enum pa_log_level l, const char *s) = NULL;
 static enum pa_log_level maximal_level = PA_LOG_NOTICE;
 
+#ifdef HAVE_SYSLOG_H
 static const int level_to_syslog[] = {
     [PA_LOG_ERROR] = LOG_ERR,
     [PA_LOG_WARN] = LOG_WARNING,
@@ -46,6 +50,7 @@ static const int level_to_syslog[] = {
     [PA_LOG_INFO] = LOG_INFO,
     [PA_LOG_DEBUG] = LOG_DEBUG
 };
+#endif
 
 void pa_log_set_ident(const char *p) {
     if (log_ident)
@@ -79,13 +84,15 @@ void pa_log_levelv(enum pa_log_level level, const char *format, va_list ap) {
         case PA_LOG_STDERR:
             vfprintf(stderr, format, ap);
             break;
-            
+
+#ifdef HAVE_SYSLOG_H            
         case PA_LOG_SYSLOG:
             openlog(log_ident ? log_ident : "???", LOG_PID, LOG_USER);
             vsyslog(level_to_syslog[level], format, ap);
             closelog();
-            break;
-            
+            break;            
+#endif
+
         case PA_LOG_USER: {
             char *t = pa_vsprintf_malloc(format, ap);
             assert(user_log_func);
@@ -94,6 +101,7 @@ void pa_log_levelv(enum pa_log_level level, const char *format, va_list ap) {
         }
             
         case PA_LOG_NULL:
+        default:
             break;
     }
 

commit eacffc3e4d581f0fe57536e7ccfba7293623586c
Author: Pierre Ossman <ossman at cendio.se>
Date:   Thu Jan 5 18:01:51 2006 +0000

    To access the new pa_gettimeofday() we need to include util.h.
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/ossman@373 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/polyp/pdispatch.c b/polyp/pdispatch.c
index 9e80875..60dd911 100644
--- a/polyp/pdispatch.c
+++ b/polyp/pdispatch.c
@@ -32,6 +32,7 @@
 #include "xmalloc.h"
 #include "llist.h"
 #include "log.h"
+#include "util.h"
 
 /*#define DEBUG_OPCODES */
 

commit 7dcf4e45963b2aff840ea53bde4012e3c6cac9f8
Author: Pierre Ossman <ossman at cendio.se>
Date:   Thu Jan 5 18:09:46 2006 +0000

    The standard declares some signals as optional. Make sure we handle
    this gracefully.
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/ossman@374 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/polyp/core.c b/polyp/core.c
index 539c677..6043924 100644
--- a/polyp/core.c
+++ b/polyp/core.c
@@ -89,7 +89,9 @@ struct pa_core* pa_core_new(struct pa_mainloop_api *m) {
 
     pa_random(&c->cookie, sizeof(c->cookie));
     
+#ifdef SIGPIPE
     pa_check_signal_is_blocked(SIGPIPE);
+#endif
     return c;
 }
 
diff --git a/polyp/main.c b/polyp/main.c
index 26fa4a8..2e97e5c 100644
--- a/polyp/main.c
+++ b/polyp/main.c
@@ -70,20 +70,26 @@ static void signal_callback(struct pa_mainloop_api*m, struct pa_signal_event *e,
     pa_log_info(__FILE__": Got signal %s.\n", pa_strsignal(sig));
 
     switch (sig) {
+#ifdef SIGUSR1
         case SIGUSR1:
             pa_module_load(userdata, "module-cli", NULL);
             break;
+#endif
             
+#ifdef SIGUSR2
         case SIGUSR2:
             pa_module_load(userdata, "module-cli-protocol-unix", NULL);
             break;
+#endif
 
+#ifdef SIGHUP
         case SIGHUP: {
             char *c = pa_full_status_string(userdata);
             pa_log_notice(c);
             pa_xfree(c);
             return;
         }
+#endif
 
         case SIGINT:
         case SIGTERM:
@@ -263,9 +269,15 @@ int main(int argc, char *argv[]) {
         open("/dev/null", O_WRONLY);
         open("/dev/null", O_WRONLY);
         
+#ifdef SIGTTOU
         signal(SIGTTOU, SIG_IGN);
+#endif
+#ifdef SIGTTIN
         signal(SIGTTIN, SIG_IGN);
+#endif
+#ifdef SIGTSTP
         signal(SIGTSTP, SIG_IGN);
+#endif
         
         if ((tty_fd = open("/dev/tty", O_RDWR)) >= 0) {
             ioctl(tty_fd, TIOCNOTTY, (char*) 0);
@@ -292,16 +304,24 @@ int main(int argc, char *argv[]) {
     assert(r == 0);
     pa_signal_new(SIGINT, signal_callback, c);
     pa_signal_new(SIGTERM, signal_callback, c);
+#ifdef SIGPIPE
     signal(SIGPIPE, SIG_IGN);
+#endif
 
     c = pa_core_new(pa_mainloop_get_api(mainloop));
     assert(c);
     if (conf->daemonize)
         c->running_as_daemon = 1;
     
+#ifdef SIGUSR1
     pa_signal_new(SIGUSR1, signal_callback, c);
+#endif
+#ifdef SIGUSR2
     pa_signal_new(SIGUSR2, signal_callback, c);
+#endif
+#ifdef SIGHUP
     pa_signal_new(SIGHUP, signal_callback, c);
+#endif
 
     r = pa_cpu_limit_init(pa_mainloop_get_api(mainloop));
     assert(r == 0);
diff --git a/polyp/pacat.c b/polyp/pacat.c
index 5910d13..1bba2ee 100644
--- a/polyp/pacat.c
+++ b/polyp/pacat.c
@@ -480,8 +480,12 @@ int main(int argc, char *argv[]) {
     assert(r == 0);
     pa_signal_new(SIGINT, exit_signal_callback, NULL);
     pa_signal_new(SIGTERM, exit_signal_callback, NULL);
+#ifdef SIGUSR1
     pa_signal_new(SIGUSR1, sigusr1_signal_callback, NULL);
+#endif
+#ifdef SIGPIPE
     signal(SIGPIPE, SIG_IGN);
+#endif
     
     if (!(stdio_event = mainloop_api->io_new(mainloop_api,
                                              mode == PLAYBACK ? STDIN_FILENO : STDOUT_FILENO,
diff --git a/polyp/pactl.c b/polyp/pactl.c
index 423cce9..725b546 100644
--- a/polyp/pactl.c
+++ b/polyp/pactl.c
@@ -739,7 +739,9 @@ int main(int argc, char *argv[]) {
     r = pa_signal_init(mainloop_api);
     assert(r == 0);
     pa_signal_new(SIGINT, exit_signal_callback, NULL);
+#ifdef SIGPIPE
     signal(SIGPIPE, SIG_IGN);
+#endif
     
     if (!(context = pa_context_new(mainloop_api, client_name))) {
         fprintf(stderr, "pa_context_new() failed.\n");
diff --git a/polyp/paplay.c b/polyp/paplay.c
index 2eaf07c..4ace197 100644
--- a/polyp/paplay.c
+++ b/polyp/paplay.c
@@ -338,7 +338,9 @@ int main(int argc, char *argv[]) {
     r = pa_signal_init(mainloop_api);
     assert(r == 0);
     pa_signal_new(SIGINT, exit_signal_callback, NULL);
+#ifdef SIGPIPE
     signal(SIGPIPE, SIG_IGN);
+#endif
     
     /* Create a new connection context */
     if (!(context = pa_context_new(mainloop_api, client_name))) {
diff --git a/polyp/polyplib-context.c b/polyp/polyplib-context.c
index bca7d7e..f54cabb 100644
--- a/polyp/polyplib-context.c
+++ b/polyp/polyplib-context.c
@@ -110,8 +110,10 @@ struct pa_context *pa_context_new(struct pa_mainloop_api *mainloop, const char *
     c->autospawn_lock_fd = -1;
     memset(&c->spawn_api, 0, sizeof(c->spawn_api));
     c->do_autospawn = 0;
-    
+
+#ifdef SIGPIPE    
     pa_check_signal_is_blocked(SIGPIPE);
+#endif
 
     c->conf = pa_client_conf_new();
     pa_client_conf_load(c->conf, NULL);
diff --git a/polyp/util.c b/polyp/util.c
index 2c4285f..fdafe25 100644
--- a/polyp/util.c
+++ b/polyp/util.c
@@ -527,12 +527,24 @@ const char *pa_strsignal(int sig) {
     switch(sig) {
         case SIGINT: return "SIGINT";
         case SIGTERM: return "SIGTERM";
+#ifdef SIGUSR1
         case SIGUSR1: return "SIGUSR1";
+#endif
+#ifdef SIGUSR2
         case SIGUSR2: return "SIGUSR2";
+#endif
+#ifdef SIGXCPU
         case SIGXCPU: return "SIGXCPU";
+#endif
+#ifdef SIGPIPE
         case SIGPIPE: return "SIGPIPE";
+#endif
+#ifdef SIGCHLD
         case SIGCHLD: return "SIGCHLD";
+#endif
+#ifdef SIGHUP
         case SIGHUP: return "SIGHUP";
+#endif
         default: return "UNKNOWN SIGNAL";
     }
 }

commit dbad54a20bf323d35176b1faba4fdd4b425f9ad9
Author: Pierre Ossman <ossman at cendio.se>
Date:   Thu Jan 5 18:20:14 2006 +0000

    Remove any warnings about incorrect type to setsockopt() (char* vs void*).
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/ossman@375 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/polyp/socket-client.c b/polyp/socket-client.c
index 40bbcc3..3cd3e94 100644
--- a/polyp/socket-client.c
+++ b/polyp/socket-client.c
@@ -120,7 +120,7 @@ static void do_call(struct pa_socket_client *c) {
         goto finish;
     
     lerror = sizeof(error);
-    if (getsockopt(c->fd, SOL_SOCKET, SO_ERROR, &error, &lerror) < 0) {
+    if (getsockopt(c->fd, SOL_SOCKET, SO_ERROR, (void*)&error, &lerror) < 0) {
         pa_log(__FILE__": getsockopt(): %s\n", strerror(errno));
         goto finish;
     }
diff --git a/polyp/socket-server.c b/polyp/socket-server.c
index e67a9da..282f1eb 100644
--- a/polyp/socket-server.c
+++ b/polyp/socket-server.c
@@ -197,7 +197,7 @@ struct pa_socket_server* pa_socket_server_new_ipv4(struct pa_mainloop_api *m, ui
 
     pa_fd_set_cloexec(fd, 1);
 
-    if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0)
+    if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void*)&on, sizeof(on)) < 0)
         pa_log(__FILE__": setsockopt(): %s\n", strerror(errno));
 
     pa_socket_tcp_low_delay(fd);
@@ -246,7 +246,7 @@ struct pa_socket_server* pa_socket_server_new_ipv6(struct pa_mainloop_api *m, ui
 
     pa_fd_set_cloexec(fd, 1);
 
-    if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0)
+    if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void*)&on, sizeof(on)) < 0)
         pa_log(__FILE__": setsockopt(): %s\n", strerror(errno));
 
     pa_socket_tcp_low_delay(fd);
diff --git a/polyp/socket-util.c b/polyp/socket-util.c
index 495ee1b..7b32f4e 100644
--- a/polyp/socket-util.c
+++ b/polyp/socket-util.c
@@ -99,7 +99,7 @@ int pa_socket_low_delay(int fd) {
 
 #ifdef SO_PRIORITY
     priority = 7;
-    if (setsockopt(fd, SOL_SOCKET, SO_PRIORITY, &priority, sizeof(priority)) < 0)
+    if (setsockopt(fd, SOL_SOCKET, SO_PRIORITY, (void*)&priority, sizeof(priority)) < 0)
         return -1;
 #endif
 
@@ -117,9 +117,9 @@ int pa_socket_tcp_low_delay(int fd) {
 
 #if defined(SOL_TCP) || defined(IPPROTO_TCP)
 #if defined(SOL_TCP)
-    if (setsockopt(fd, SOL_TCP, TCP_NODELAY, &on, sizeof(on)) < 0)
+    if (setsockopt(fd, SOL_TCP, TCP_NODELAY, (void*)&on, sizeof(on)) < 0)
 #else
-    if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on)) < 0)
+    if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (void*)&on, sizeof(on)) < 0)
 #endif
         ret = -1;
 #endif
@@ -128,9 +128,9 @@ int pa_socket_tcp_low_delay(int fd) {
 	defined(IPPROTO_IP))
     tos = IPTOS_LOWDELAY;
 #ifdef SOL_IP
-    if (setsockopt(fd, SOL_IP, IP_TOS, &tos, sizeof(tos)) < 0)
+    if (setsockopt(fd, SOL_IP, IP_TOS, (void*)&tos, sizeof(tos)) < 0)
 #else
-    if (setsockopt(fd, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)) < 0)
+    if (setsockopt(fd, IPPROTO_IP, IP_TOS, (void*)&tos, sizeof(tos)) < 0)
 #endif
         ret = -1;
 #endif
@@ -142,7 +142,7 @@ int pa_socket_tcp_low_delay(int fd) {
 int pa_socket_set_rcvbuf(int fd, size_t l) {
     assert(fd >= 0);
 
-/*     if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &l, sizeof(l)) < 0) { */
+/*     if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, (void*)&l, sizeof(l)) < 0) { */
 /*         pa_log(__FILE__": SO_RCVBUF: %s\n", strerror(errno)); */
 /*         return -1; */
 /*     } */
@@ -153,7 +153,7 @@ int pa_socket_set_rcvbuf(int fd, size_t l) {
 int pa_socket_set_sndbuf(int fd, size_t l) {
     assert(fd >= 0);
 
-/*     if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &l, sizeof(l)) < 0) { */
+/*     if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (void*)&l, sizeof(l)) < 0) { */
 /*         pa_log(__FILE__": SO_SNDBUF: %s\n", strerror(errno)); */
 /*         return -1; */
 /*     } */

commit 3a3b4aff37397b786782d5a7e1f106b83d272abd
Author: Pierre Ossman <ossman at cendio.se>
Date:   Thu Jan 5 18:27:09 2006 +0000

    AF_UNIX and PF_UNIX is more portable than the _LOCAL equivalent.
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/ossman@376 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/polyp/socket-client.c b/polyp/socket-client.c
index 3cd3e94..2eecc34 100644
--- a/polyp/socket-client.c
+++ b/polyp/socket-client.c
@@ -203,7 +203,7 @@ struct pa_socket_client* pa_socket_client_new_unix(struct pa_mainloop_api *m, co
     assert(m && filename);
     
     memset(&sa, 0, sizeof(sa));
-    sa.sun_family = AF_LOCAL;
+    sa.sun_family = AF_UNIX;
     strncpy(sa.sun_path, filename, sizeof(sa.sun_path)-1);
     sa.sun_path[sizeof(sa.sun_path) - 1] = 0;
 
diff --git a/polyp/socket-server.c b/polyp/socket-server.c
index 282f1eb..7d6035c 100644
--- a/polyp/socket-server.c
+++ b/polyp/socket-server.c
@@ -144,14 +144,14 @@ struct pa_socket_server* pa_socket_server_new_unix(struct pa_mainloop_api *m, co
     
     assert(m && filename);
 
-    if ((fd = socket(PF_LOCAL, SOCK_STREAM, 0)) < 0) {
+    if ((fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) {
         pa_log(__FILE__": socket(): %s\n", strerror(errno));
         goto fail;
     }
 
     pa_fd_set_cloexec(fd, 1);
 
-    sa.sun_family = AF_LOCAL;
+    sa.sun_family = AF_UNIX;
     strncpy(sa.sun_path, filename, sizeof(sa.sun_path)-1);
     sa.sun_path[sizeof(sa.sun_path) - 1] = 0;
 
diff --git a/polyp/socket-util.c b/polyp/socket-util.c
index 7b32f4e..cd132d7 100644
--- a/polyp/socket-util.c
+++ b/polyp/socket-util.c
@@ -77,7 +77,7 @@ void pa_socket_peer_to_string(int fd, char *c, size_t l) {
                          ip & 0xFF,
                          ntohs(sa.in.sin_port));
                 return;
-            } else if (sa.sa.sa_family == AF_LOCAL) {
+            } else if (sa.sa.sa_family == AF_UNIX) {
                 snprintf(c, l, "UNIX socket client");
                 return;
             }
@@ -165,12 +165,12 @@ int pa_unix_socket_is_stale(const char *fn) {
     struct sockaddr_un sa;
     int fd = -1, ret = -1;
 
-    if ((fd = socket(PF_LOCAL, SOCK_STREAM, 0)) < 0) {
+    if ((fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) {
         pa_log(__FILE__": socket(): %s\n", strerror(errno));
         goto finish;
     }
 
-    sa.sun_family = AF_LOCAL;
+    sa.sun_family = AF_UNIX;
     strncpy(sa.sun_path, fn, sizeof(sa.sun_path)-1);
     sa.sun_path[sizeof(sa.sun_path) - 1] = 0;
 

commit 13496bb73ecd2a76a83bf528d9a180084c8c006d
Author: Pierre Ossman <ossman at cendio.se>
Date:   Thu Jan 5 18:43:10 2006 +0000

    Handle when the platform doesn't have UNIX sockets.
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/ossman@377 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/polyp/socket-client.c b/polyp/socket-client.c
index 2eecc34..a55fd4b 100644
--- a/polyp/socket-client.c
+++ b/polyp/socket-client.c
@@ -31,10 +31,14 @@
 #include <string.h>
 #include <assert.h>
 #include <stdlib.h>
-#include <sys/un.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
 #include <netdb.h>
+
+#ifdef HAVE_SYS_UN_H
+#include <sys/un.h>
+#endif
+
 #ifdef HAVE_LIBASYNCNS
 #include <asyncns.h>
 #endif
@@ -198,6 +202,8 @@ struct pa_socket_client* pa_socket_client_new_ipv4(struct pa_mainloop_api *m, ui
     return pa_socket_client_new_sockaddr(m, (struct sockaddr*) &sa, sizeof(sa));
 }
 
+#ifdef HAVE_SYS_UN_H
+
 struct pa_socket_client* pa_socket_client_new_unix(struct pa_mainloop_api *m, const char *filename) {
     struct sockaddr_un sa;
     assert(m && filename);
@@ -210,6 +216,14 @@ struct pa_socket_client* pa_socket_client_new_unix(struct pa_mainloop_api *m, co
     return pa_socket_client_new_sockaddr(m, (struct sockaddr*) &sa, sizeof(sa));
 }
 
+#else /* HAVE_SYS_UN_H */
+
+struct pa_socket_client* pa_socket_client_new_unix(struct pa_mainloop_api *m, const char *filename) {
+    return NULL;
+}
+
+#endif /* HAVE_SYS_UN_H */
+
 static int sockaddr_prepare(struct pa_socket_client *c, const struct sockaddr *sa, size_t salen) {
     assert(c);
     assert(sa);
diff --git a/polyp/socket-server.c b/polyp/socket-server.c
index 7d6035c..d46db6c 100644
--- a/polyp/socket-server.c
+++ b/polyp/socket-server.c
@@ -31,10 +31,13 @@
 #include <sys/socket.h>
 #include <stdio.h>
 #include <unistd.h>
-#include <sys/un.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
 
+#ifdef HAVE_SYS_UN_H
+#include <sys/un.h>
+#endif
+
 #ifdef HAVE_LIBWRAP
 #include <tcpd.h>
 #endif
@@ -137,6 +140,8 @@ struct pa_socket_server* pa_socket_server_ref(struct pa_socket_server *s) {
     return s;
 }
 
+#ifdef HAVE_SYS_UN_H
+
 struct pa_socket_server* pa_socket_server_new_unix(struct pa_mainloop_api *m, const char *filename) {
     int fd = -1;
     struct sockaddr_un sa;
@@ -182,6 +187,14 @@ fail:
     return NULL;
 }
 
+#else /* HAVE_SYS_UN_H */
+
+struct pa_socket_server* pa_socket_server_new_unix(struct pa_mainloop_api *m, const char *filename) {
+    return NULL;
+}
+
+#endif /* HAVE_SYS_UN_H */
+
 struct pa_socket_server* pa_socket_server_new_ipv4(struct pa_mainloop_api *m, uint32_t address, uint16_t port, const char *tcpwrap_service) {
     struct pa_socket_server *ss;
     int fd = -1;
diff --git a/polyp/socket-util.c b/polyp/socket-util.c
index cd132d7..4204ec9 100644
--- a/polyp/socket-util.c
+++ b/polyp/socket-util.c
@@ -31,7 +31,6 @@
 #include <string.h>
 #include <stdio.h>
 #include <sys/types.h>
-#include <sys/un.h>
 #include <netinet/in.h>
 #include <fcntl.h>
 #include <unistd.h>
@@ -42,6 +41,10 @@
 #include <sys/stat.h>
 #include <netdb.h>
 
+#ifdef HAVE_SYS_UN_H
+#include <sys/un.h>
+#endif
+
 #include "socket-util.h"
 #include "util.h"
 #include "xmalloc.h"
@@ -161,6 +164,8 @@ int pa_socket_set_sndbuf(int fd, size_t l) {
     return 0;
 }
 
+#ifdef HAVE_SYS_UN_H
+
 int pa_unix_socket_is_stale(const char *fn) {
     struct sockaddr_un sa;
     int fd = -1, ret = -1;
@@ -202,3 +207,15 @@ int pa_unix_socket_remove_stale(const char *fn) {
 
     return 0;
 }
+
+#else /* HAVE_SYS_UN_H */
+
+int pa_unix_socket_is_stale(const char *fn) {
+    return -1;
+}
+
+int pa_unix_socket_remove_stale(const char *fn) {
+    return -1;
+}
+
+#endif /* HAVE_SYS_UN_H */

commit cd3691dff79e18a288b7371bd0bed92d3abb5991
Author: Pierre Ossman <ossman at cendio.se>
Date:   Thu Jan 5 18:50:08 2006 +0000

    PIPE_BUF has nothing to do with the esound buffers.
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/ossman@378 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/polyp/module-esound-sink.c b/polyp/module-esound-sink.c
index 82c38cc..1910650 100644
--- a/polyp/module-esound-sink.c
+++ b/polyp/module-esound-sink.c
@@ -144,7 +144,7 @@ static int do_write(struct userdata *u) {
         pa_module_set_used(u->module, pa_idxset_ncontents(u->sink->inputs) + pa_idxset_ncontents(u->sink->monitor_source->outputs));
         
         if (!u->memchunk.length)
-            if (pa_sink_render(u->sink, PIPE_BUF, &u->memchunk) < 0)
+            if (pa_sink_render(u->sink, 8192, &u->memchunk) < 0)
                 return 0;
 
         assert(u->memchunk.memblock && u->memchunk.length);

commit 456e25634ce860d1576b6f09f11cdab8f9d8e685
Author: Pierre Ossman <ossman at cendio.se>
Date:   Thu Jan 5 18:51:46 2006 +0000

    Fix some compiler warnings about unused variables.
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/ossman@379 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/polyp/socket-util.c b/polyp/socket-util.c
index 4204ec9..eb6b424 100644
--- a/polyp/socket-util.c
+++ b/polyp/socket-util.c
@@ -97,10 +97,10 @@ void pa_socket_peer_to_string(int fd, char *c, size_t l) {
 }
 
 int pa_socket_low_delay(int fd) {
+#ifdef SO_PRIORITY
     int priority;
     assert(fd >= 0);
 
-#ifdef SO_PRIORITY
     priority = 7;
     if (setsockopt(fd, SOL_SOCKET, SO_PRIORITY, (void*)&priority, sizeof(priority)) < 0)
         return -1;
@@ -117,6 +117,7 @@ int pa_socket_tcp_low_delay(int fd) {
     ret = pa_socket_low_delay(fd);
     
     on = 1;
+    tos = 0;
 
 #if defined(SOL_TCP) || defined(IPPROTO_TCP)
 #if defined(SOL_TCP)

commit ff49e63b49dcd107e2680587b796c9c5998b1854
Author: Pierre Ossman <ossman at cendio.se>
Date:   Thu Jan 5 18:55:10 2006 +0000

    inet_ntop can't be found on all platforms. Do a stupid emulation when
    not found.
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/ossman@380 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/polyp/socket-server.c b/polyp/socket-server.c
index d46db6c..096d8a4 100644
--- a/polyp/socket-server.c
+++ b/polyp/socket-server.c
@@ -350,10 +350,22 @@ char *pa_socket_server_get_address(struct pa_socket_server *s, char *c, size_t l
             } else {
                 char ip[INET6_ADDRSTRLEN];
                 
+#ifdef HAVE_INET_NTOP
                 if (!inet_ntop(AF_INET6, &sa.sin6_addr, ip, sizeof(ip))) {
                     pa_log(__FILE__": inet_ntop() failed: %s\n", strerror(errno));
                     return NULL;
                 }
+#else
+                snprintf(ip, INET6_ADDRSTRLEN, "%x:%x:%x:%x:%x:%x:%x:%x",
+                    sa.sin6_addr.s6_addr[ 0] << 8 | sa.sin6_addr.s6_addr[ 1],
+                    sa.sin6_addr.s6_addr[ 2] << 8 | sa.sin6_addr.s6_addr[ 3],
+                    sa.sin6_addr.s6_addr[ 4] << 8 | sa.sin6_addr.s6_addr[ 5],
+                    sa.sin6_addr.s6_addr[ 6] << 8 | sa.sin6_addr.s6_addr[ 7],
+                    sa.sin6_addr.s6_addr[ 8] << 8 | sa.sin6_addr.s6_addr[ 9],
+                    sa.sin6_addr.s6_addr[10] << 8 | sa.sin6_addr.s6_addr[11],
+                    sa.sin6_addr.s6_addr[12] << 8 | sa.sin6_addr.s6_addr[13],
+                    sa.sin6_addr.s6_addr[14] << 8 | sa.sin6_addr.s6_addr[15]);
+#endif
                 
                 snprintf(c, l, "tcp6:[%s]:%u", ip, (unsigned) ntohs(sa.sin6_port));
             }
@@ -385,10 +397,25 @@ char *pa_socket_server_get_address(struct pa_socket_server *s, char *c, size_t l
             } else {
                 char ip[INET_ADDRSTRLEN];
 
+#ifdef HAVE_INET_NTOP
                 if (!inet_ntop(AF_INET, &sa.sin_addr, ip, sizeof(ip))) {
                     pa_log(__FILE__": inet_ntop() failed: %s\n", strerror(errno));
                     return NULL;
                 }
+#else /* HAVE_INET_NTOP */
+                snprintf(ip, INET_ADDRSTRLEN, "%d.%d.%d.%d",
+#ifdef WORDS_BIGENDIAN
+                    (int)(sa.sin_addr.s_addr >> 24) & 0xff,
+                    (int)(sa.sin_addr.s_addr >> 16) & 0xff,
+                    (int)(sa.sin_addr.s_addr >>  8) & 0xff,
+                    (int)(sa.sin_addr.s_addr >>  0) & 0xff);
+#else
+                    (int)(sa.sin_addr.s_addr >>  0) & 0xff,
+                    (int)(sa.sin_addr.s_addr >>  8) & 0xff,
+                    (int)(sa.sin_addr.s_addr >> 16) & 0xff,
+                    (int)(sa.sin_addr.s_addr >> 24) & 0xff);
+#endif
+#endif /* HAVE_INET_NTOP */
                 
                 snprintf(c, l, "tcp:[%s]:%u", ip, (unsigned) ntohs(sa.sin_port));
 

commit 4384d3126b362c3aa261f4f0c815221b2cc5c647
Author: Pierre Ossman <ossman at cendio.se>
Date:   Thu Jan 5 18:56:23 2006 +0000

    Fix warning.
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/ossman@381 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/polyp/socket-server.c b/polyp/socket-server.c
index 096d8a4..f200212 100644
--- a/polyp/socket-server.c
+++ b/polyp/socket-server.c
@@ -377,7 +377,7 @@ char *pa_socket_server_get_address(struct pa_socket_server *s, char *c, size_t l
             struct sockaddr_in sa;
             socklen_t l = sizeof(sa);
 
-            if (getsockname(s->fd, &sa, &l) < 0) {
+            if (getsockname(s->fd, (struct sockaddr*) &sa, &l) < 0) {
                 pa_log(__FILE__": getsockname() failed: %s\n", strerror(errno));
                 return NULL;
             }

commit f0e8c652397d512ed12939c3e2cbcbb4ec6cef75
Author: Pierre Ossman <ossman at cendio.se>
Date:   Thu Jan 5 18:57:19 2006 +0000

    Two variables with the same name causing corrupt strings.
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/ossman@382 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/polyp/socket-server.c b/polyp/socket-server.c
index f200212..ed86bc2 100644
--- a/polyp/socket-server.c
+++ b/polyp/socket-server.c
@@ -327,9 +327,9 @@ char *pa_socket_server_get_address(struct pa_socket_server *s, char *c, size_t l
     switch (s->type) {
         case SOCKET_SERVER_IPV6: {
             struct sockaddr_in6 sa;
-            socklen_t l = sizeof(sa);
+            socklen_t sa_len = sizeof(sa);
 
-            if (getsockname(s->fd, (struct sockaddr*) &sa, &l) < 0) {
+            if (getsockname(s->fd, (struct sockaddr*) &sa, &sa_len) < 0) {
                 pa_log(__FILE__": getsockname() failed: %s\n", strerror(errno));
                 return NULL;
             }
@@ -375,9 +375,9 @@ char *pa_socket_server_get_address(struct pa_socket_server *s, char *c, size_t l
 
         case SOCKET_SERVER_IPV4: {
             struct sockaddr_in sa;
-            socklen_t l = sizeof(sa);
+            socklen_t sa_len = sizeof(sa);
 
-            if (getsockname(s->fd, (struct sockaddr*) &sa, &l) < 0) {
+            if (getsockname(s->fd, (struct sockaddr*) &sa, &sa_len) < 0) {
                 pa_log(__FILE__": getsockname() failed: %s\n", strerror(errno));
                 return NULL;
             }

commit 14474ae4528456b6be243d75116a6080df50399e
Author: Pierre Ossman <ossman at cendio.se>
Date:   Thu Jan 5 18:59:24 2006 +0000

    Esound latency should not include buffer length. This added an extra second
    to esound already horrible latency calculations.
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/ossman@383 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/polyp/protocol-esound.c b/polyp/protocol-esound.c
index 2af3cc8..5705d3f 100644
--- a/polyp/protocol-esound.c
+++ b/polyp/protocol-esound.c
@@ -426,7 +426,6 @@ static int esd_proto_get_latency(struct connection *c, esd_proto_t request, cons
         latency = 0;
     else {
         double usec = pa_sink_get_latency(sink);
-        usec += PLAYBACK_BUFFER_SECONDS*1000000;          /* A better estimation would be a good idea! */
         latency = (int) ((usec*44100)/1000000);
     }
     

commit 4deeaefbe116f6374b3cdb7a4186bb1bf7afefe2
Author: Pierre Ossman <ossman at cendio.se>
Date:   Thu Jan 5 19:11:23 2006 +0000

    Don't include sys/socket.h in the header when we do not need to.
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/ossman@384 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/polyp/socket-client.c b/polyp/socket-client.c
index a55fd4b..58bc7e8 100644
--- a/polyp/socket-client.c
+++ b/polyp/socket-client.c
@@ -31,6 +31,7 @@
 #include <string.h>
 #include <assert.h>
 #include <stdlib.h>
+#include <sys/socket.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
 #include <netdb.h>
diff --git a/polyp/socket-client.h b/polyp/socket-client.h
index 9c3e0b3..b8c73ed 100644
--- a/polyp/socket-client.h
+++ b/polyp/socket-client.h
@@ -23,11 +23,12 @@
 ***/
 
 #include <inttypes.h>
-#include <sys/socket.h>
 
 #include "mainloop-api.h"
 #include "iochannel.h"
 
+struct sockaddr;
+
 struct pa_socket_client;
 
 struct pa_socket_client* pa_socket_client_new_ipv4(struct pa_mainloop_api *m, uint32_t address, uint16_t port);

commit c5bee95cdf30661b4090d86f4e0ab36109228fae
Author: Pierre Ossman <ossman at cendio.se>
Date:   Thu Jan 5 19:13:11 2006 +0000

    Fix correct type.
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/ossman@385 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/polyp/sample-util.c b/polyp/sample-util.c
index d521afe..bf8be34 100644
--- a/polyp/sample-util.c
+++ b/polyp/sample-util.c
@@ -161,7 +161,7 @@ size_t pa_mix(struct pa_mix_info channels[], unsigned nchannels, void *data, siz
         size_t d;
         
         for (d = 0;; d += sizeof(float)) {
-            float_t sum = 0;
+            pa_volume_t sum = 0;
             unsigned c;
             
             if (d >= length)

commit 719223825e56e580dd0c02e09d13f8a7be8c89a3
Author: Pierre Ossman <ossman at cendio.se>
Date:   Thu Jan 5 19:14:13 2006 +0000

    Old kernel headers didn't define the input_id structure. Therefore we cannot
    rely on it.
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/ossman@386 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/polyp/module-mmkbd-evdev.c b/polyp/module-mmkbd-evdev.c
index 758aaae..5368af5 100644
--- a/polyp/module-mmkbd-evdev.c
+++ b/polyp/module-mmkbd-evdev.c
@@ -49,6 +49,17 @@ PA_MODULE_USAGE("device=<evdev device> sink=<sink name>")
 
 #define DEFAULT_DEVICE "/dev/input/event0"
 
+/*
+ * This isn't defined in older kernel headers and there is no way of
+ * detecting it.
+ */
+struct _input_id {
+    __u16 bustype;
+    __u16 vendor;
+    __u16 product;
+    __u16 version;
+};
+
 static const char* const valid_modargs[] = {
     "device",
     "sink",
@@ -136,7 +147,7 @@ int pa__init(struct pa_core *c, struct pa_module*m) {
     struct pa_modargs *ma = NULL;
     struct userdata *u;
     int version;
-    struct input_id input_id;
+    struct _input_id input_id;
     char name[256];
     uint8_t evtype_bitmask[EV_MAX/8 + 1];
     assert(c && m);

commit b69d881eb2555f40795d5d930a84e4a7d7e4b598
Author: Pierre Ossman <ossman at cendio.se>
Date:   Thu Jan 5 19:14:58 2006 +0000

    Fix printf string.
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/ossman@387 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/polyp/mcalign-test.c b/polyp/mcalign-test.c
index e4a6a23..2ace6e5 100644
--- a/polyp/mcalign-test.c
+++ b/polyp/mcalign-test.c
@@ -66,7 +66,7 @@ int main(int argc, char *argv[]) {
 
         c.length = r;
         pa_mcalign_push(a, &c);
-        fprintf(stderr, "Read %u bytes\n", r);
+        fprintf(stderr, "Read %d bytes\n", r);
 
         c.index += r;
 

commit 3728854bc924ad4cfe72d9d83e040a888a715822
Author: Pierre Ossman <ossman at cendio.se>
Date:   Thu Jan 5 19:16:01 2006 +0000

    Make sure the array is never too small.
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/ossman@388 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/polyp/oss-util.c b/polyp/oss-util.c
index 8c83cbb..799bc40 100644
--- a/polyp/oss-util.c
+++ b/polyp/oss-util.c
@@ -92,7 +92,7 @@ fail:
 
 int pa_oss_auto_format(int fd, struct pa_sample_spec *ss) {
     int format, channels, speed, reqformat;
-    static const int format_trans[] = {
+    static const int format_trans[PA_SAMPLE_MAX] = {
         [PA_SAMPLE_U8] = AFMT_U8,
         [PA_SAMPLE_ALAW] = AFMT_A_LAW,
         [PA_SAMPLE_ULAW] = AFMT_MU_LAW,

commit b8859b4b60152403058884ee7d28f48d67a418a9
Author: Pierre Ossman <ossman at cendio.se>
Date:   Thu Jan 5 19:17:53 2006 +0000

    Compiler warning about uninitialized variable.
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/ossman@389 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/polyp/authkey.c b/polyp/authkey.c
index e16883d..35d97b7 100644
--- a/polyp/authkey.c
+++ b/polyp/authkey.c
@@ -63,7 +63,7 @@ static int generate(int fd, void *ret_data, size_t length) {
 static int load(const char *fn, void *data, size_t length) {
     int fd = -1;
     int writable = 1;
-    int unlock = 0, ret;
+    int unlock = 0, ret = -1;
     ssize_t r;
     assert(fn && data && length);
 

commit 3ed983c945f2bd6ad7503c969a5506bae41a823b
Author: Pierre Ossman <ossman at cendio.se>
Date:   Thu Jan 5 19:18:42 2006 +0000

    SIGQUIT is an optional signal.
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/ossman@390 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/polyp/xmalloc.c b/polyp/xmalloc.c
index 7ddefa9..f2751e5 100644
--- a/polyp/xmalloc.c
+++ b/polyp/xmalloc.c
@@ -45,7 +45,9 @@
 static void oom(void) {
     static const char e[] = "Not enough memory\n";
     pa_loop_write(STDERR_FILENO, e, sizeof(e)-1);
+#ifdef SIGQUIT
     raise(SIGQUIT);
+#endif
     _exit(1);
 }
 

commit ec87cb1571c293ff40b1191796c71275b6564694
Author: Pierre Ossman <ossman at cendio.se>
Date:   Thu Jan 5 19:25:21 2006 +0000

    Fall back to signal() when sigaction isn't supported.
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/ossman@391 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/polyp/mainloop-signal.c b/polyp/mainloop-signal.c
index 89f195e..eb3f5dd 100644
--- a/polyp/mainloop-signal.c
+++ b/polyp/mainloop-signal.c
@@ -30,6 +30,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
+#include <fcntl.h>
 
 #include "mainloop-signal.h"
 #include "util.h"
@@ -38,7 +39,11 @@
 
 struct pa_signal_event {
     int sig;
+#ifdef HAVE_SIGACTION
     struct sigaction saved_sigaction;
+#else
+    void (*saved_handler)(int sig);
+#endif
     void (*callback) (struct pa_mainloop_api*a, struct pa_signal_event *e, int signal, void *userdata);
     void *userdata;
     void (*destroy_callback) (struct pa_mainloop_api*a, struct pa_signal_event*e, void *userdata);
@@ -51,6 +56,9 @@ static struct pa_io_event* io_event = NULL;
 static struct pa_signal_event *signals = NULL;
 
 static void signal_handler(int sig) {
+#ifndef HAVE_SIGACTION
+    signal(sig, signal_handler);
+#endif
     write(signal_pipe[1], &sig, sizeof(sig));
 }
 
@@ -108,7 +116,7 @@ void pa_signal_done(void) {
         pa_signal_free(signals);
 
 
-        api->io_free(io_event);
+    api->io_free(io_event);
     io_event = NULL;
 
     close(signal_pipe[0]);
@@ -120,7 +128,11 @@ void pa_signal_done(void) {
 
 struct pa_signal_event* pa_signal_new(int sig, void (*callback) (struct pa_mainloop_api *api, struct pa_signal_event*e, int sig, void *userdata), void *userdata) {
     struct pa_signal_event *e = NULL;
+
+#ifdef HAVE_SIGACTION
     struct sigaction sa;
+#endif
+
     assert(sig > 0 && callback);
     
     for (e = signals; e; e = e->next)
@@ -133,12 +145,16 @@ struct pa_signal_event* pa_signal_new(int sig, void (*callback) (struct pa_mainl
     e->userdata = userdata;
     e->destroy_callback = NULL;
 
+#ifdef HAVE_SIGACTION
     memset(&sa, 0, sizeof(sa));
     sa.sa_handler = signal_handler;
     sigemptyset(&sa.sa_mask);
     sa.sa_flags = SA_RESTART;
     
     if (sigaction(sig, &sa, &e->saved_sigaction) < 0)
+#else
+    if ((e->saved_handler = signal(sig, signal_handler)) == SIG_ERR)
+#endif
         goto fail;
 
     e->previous = NULL;
@@ -162,7 +178,11 @@ void pa_signal_free(struct pa_signal_event *e) {
     else
         signals = e->next;
 
+#ifdef HAVE_SIGACTION
     sigaction(e->sig, &e->saved_sigaction, NULL);
+#else
+    signal(e->sig, e->saved_handler);
+#endif
 
     if (e->destroy_callback)
         e->destroy_callback(api, e, e->userdata);
diff --git a/polyp/util.c b/polyp/util.c
index fdafe25..a7dc3b1 100644
--- a/polyp/util.c
+++ b/polyp/util.c
@@ -153,6 +153,7 @@ ssize_t pa_loop_write(int fd, const void*data, size_t size) {
 /* Print a warning messages in case that the given signal is not
  * blocked or trapped */
 void pa_check_signal_is_blocked(int sig) {
+#ifdef HAVE_SIGACTION
     struct sigaction sa;
     sigset_t set;
 
@@ -185,6 +186,9 @@ void pa_check_signal_is_blocked(int sig) {
         return;
     
     pa_log(__FILE__": WARNING: %s is not trapped. This might cause malfunction!\n", pa_strsignal(sig));
+#else /* HAVE_SIGACTION */
+    pa_log(__FILE__": WARNING: %s might not be trapped. This might cause malfunction!\n", pa_strsignal(sig));
+#endif
 }
 
 /* The following function is based on an example from the GNU libc

commit 59aa6ca514101d50dea7bd56147a6984b8abb3bf
Author: Pierre Ossman <ossman at cendio.se>
Date:   Thu Jan 5 19:30:59 2006 +0000

    There was a race condition here that caused latency calculation to fail
    miserably under some conditions.
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/ossman@392 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/polyp/polyplib-internal.h b/polyp/polyplib-internal.h
index d1b3a27..9417430 100644
--- a/polyp/polyplib-internal.h
+++ b/polyp/polyplib-internal.h
@@ -92,7 +92,6 @@ struct pa_stream {
     enum pa_stream_direction direction;
     uint32_t requested_bytes;
     uint64_t counter;
-    pa_usec_t previous_time;
     enum pa_stream_state state;
     struct pa_mcalign *mcalign;
 
diff --git a/polyp/polyplib-stream.c b/polyp/polyplib-stream.c
index d4480f8..c7c40c0 100644
--- a/polyp/polyplib-stream.c
+++ b/polyp/polyplib-stream.c
@@ -65,7 +65,6 @@ struct pa_stream *pa_stream_new(struct pa_context *c, const char *name, const st
     s->mcalign = pa_mcalign_new(pa_frame_size(ss), c->memblock_stat);
 
     s->counter = 0;
-    s->previous_time = 0;
 
     s->corked = 0;
     s->interpolate = 0;
@@ -698,11 +697,6 @@ pa_usec_t pa_stream_get_time(struct pa_stream *s, const struct pa_latency_info *
         }
     }
 
-    if (usec < s->previous_time)
-        usec = s->previous_time;
-
-    s->previous_time = usec;
-    
     return usec;
 }
 
@@ -762,10 +756,6 @@ pa_usec_t pa_stream_get_interpolated_time(struct pa_stream *s) {
             usec = s->ipol_usec + pa_timeval_age(&s->ipol_timestamp);
     }
     
-    if (usec < s->previous_time)
-        usec = s->previous_time;
-
-    s->previous_time = usec;
     return usec;
 }
 

commit e9be6fa6d397a59ee4566d6674b9ed2cb3d04402
Author: Pierre Ossman <ossman at cendio.se>
Date:   Thu Jan 5 19:43:29 2006 +0000

    Handle platforms that do not support the UNIX user/group database.
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/ossman@393 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/polyp/util.c b/polyp/util.c
index a7dc3b1..2ac5540 100644
--- a/polyp/util.c
+++ b/polyp/util.c
@@ -34,7 +34,6 @@
 #include <unistd.h>
 #include <sys/types.h>
 #include <sys/stat.h>
-#include <pwd.h>
 #include <signal.h>
 #include <pthread.h>
 #include <sys/time.h>
@@ -42,11 +41,17 @@
 #include <sys/resource.h>
 #include <limits.h>
 #include <unistd.h>
-#include <grp.h>
 #include <netdb.h>
 
 #include <samplerate.h>
 
+#ifdef HAVE_PWD_H
+#include <pwd.h>
+#endif
+#ifdef HAVE_GRP_H
+#include <grp.h>
+#endif
+
 #include "util.h"
 #include "xmalloc.h"
 #include "log.h"
@@ -244,12 +249,17 @@ char *pa_vsprintf_malloc(const char *format, va_list ap) {
 
 /* Return the current username in the specified string buffer. */
 char *pa_get_user_name(char *s, size_t l) {
-    struct passwd pw, *r;
-    char buf[1024];
     char *p;
+
+#ifdef HAVE_PWD_H
+    char buf[1024];
+    struct passwd pw, *r;
+#endif
+
     assert(s && l > 0);
 
     if (!(p = getenv("USER")) && !(p = getenv("LOGNAME")) && !(p = getenv("USERNAME"))) {
+#ifdef HAVE_PWD_H
         
 #ifdef HAVE_GETPWUID_R
         if (getpwuid_r(getuid(), &pw, buf, sizeof(buf), &r) != 0 || !r) {
@@ -263,6 +273,9 @@ char *pa_get_user_name(char *s, size_t l) {
             }
             
             p = r->pw_name;
+#else /* HAVE_PWD_H */
+            return NULL;
+#endif /* HAVE_PWD_H */
         }
 
     return pa_strlcpy(s, p, l);
@@ -282,19 +295,34 @@ char *pa_get_host_name(char *s, size_t l) {
 /* Return the home directory of the current user */
 char *pa_get_home_dir(char *s, size_t l) {
     char *e;
+
+#ifdef HAVE_PWD_H
     char buf[1024];
     struct passwd pw, *r;
+#endif
+
     assert(s && l);
 
     if ((e = getenv("HOME")))
         return pa_strlcpy(s, e, l);
 
+#ifdef HAVE_PWD_H
+#ifdef HAVE_GETPWUID_R
     if (getpwuid_r(getuid(), &pw, buf, sizeof(buf), &r) != 0 || !r) {
         pa_log(__FILE__": getpwuid_r() failed\n");
+#else
+    /* XXX Not thread-safe, but needed on OSes (e.g. FreeBSD 4.X)
+        * that do not support getpwuid_r. */
+    if ((r = getpwuid(getuid())) == NULL) {
+        pa_log(__FILE__": getpwuid_r() failed\n");
+#endif
         return NULL;
     }
 
     return pa_strlcpy(s, r->pw_dir, l);
+#else /* HAVE_PWD_H */
+    return NULL;
+#endif
 }
 
 /* Similar to OpenBSD's strlcpy() function */
@@ -553,6 +581,7 @@ const char *pa_strsignal(int sig) {
     }
 }
 
+#ifdef HAVE_GRP_H
 
 /* Check whether the specified GID and the group name match */
 static int is_group(gid_t gid, const char *name) {
@@ -633,6 +662,14 @@ finish:
     return r;
 }
 
+#else /* HAVE_GRP_H */
+
+int pa_uid_in_group(const char *name, gid_t *gid) {
+    return -1;
+}
+
+#endif
+
 /* Lock or unlock a file entirely. (advisory) */
 int pa_lock_fd(int fd, int b) {
     struct flock flock;

commit a24102cda46ffdc0b3a6a0b82b13cf0ee80beb98
Author: Pierre Ossman <ossman at cendio.se>
Date:   Thu Jan 5 19:44:33 2006 +0000

    Fix indentation.
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/ossman@394 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/polyp/util.c b/polyp/util.c
index 2ac5540..9e8dc5e 100644
--- a/polyp/util.c
+++ b/polyp/util.c
@@ -264,22 +264,22 @@ char *pa_get_user_name(char *s, size_t l) {
 #ifdef HAVE_GETPWUID_R
         if (getpwuid_r(getuid(), &pw, buf, sizeof(buf), &r) != 0 || !r) {
 #else
-            /* XXX Not thread-safe, but needed on OSes (e.g. FreeBSD 4.X)
-             * that do not support getpwuid_r. */
-            if ((r = getpwuid(getuid())) == NULL) {
+        /* XXX Not thread-safe, but needed on OSes (e.g. FreeBSD 4.X)
+            * that do not support getpwuid_r. */
+        if ((r = getpwuid(getuid())) == NULL) {
 #endif
-                snprintf(s, l, "%lu", (unsigned long) getuid());
-                return s;
-            }
-            
-            p = r->pw_name;
+            snprintf(s, l, "%lu", (unsigned long) getuid());
+            return s;
+        }
+        
+        p = r->pw_name;
 #else /* HAVE_PWD_H */
-            return NULL;
+        return NULL;
 #endif /* HAVE_PWD_H */
-        }
+    }
 
     return pa_strlcpy(s, p, l);
-    }
+}
 
 /* Return the current hostname in the specified buffer. */
 char *pa_get_host_name(char *s, size_t l) {

commit 5cd8703f0de35ed38ddd79974b5a7e70af8203ce
Author: Pierre Ossman <ossman at cendio.se>
Date:   Thu Jan 5 20:25:05 2006 +0000

    Remove ftruncate test since we're not doing anything with the result.
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/ossman@395 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/configure.ac b/configure.ac
index 450f18a..eb4c941 100644
--- a/configure.ac
+++ b/configure.ac
@@ -166,8 +166,8 @@ AC_CHECK_LIB([m], [pow])
 AC_FUNC_FORK
 AC_FUNC_GETGROUPS
 AC_FUNC_SELECT_ARGTYPES
-AC_CHECK_FUNCS([getaddrinfo ftruncate getgrgid_r getpwuid_r gettimeofday \
-    getuid inet_ntop mkfifo nanosleep sigaction sleep])
+AC_CHECK_FUNCS([getaddrinfo getgrgid_r getpwuid_r gettimeofday getuid \
+    inet_ntop mkfifo nanosleep sigaction sleep])
 
 AM_CONDITIONAL(HAVE_MKFIFO, test "x$HAVE_MKFIFO" = "x1")
 

commit d3bc7b27b7b0da1a8d9de2cd93ac10096b6b0b17
Author: Pierre Ossman <ossman at cendio.se>
Date:   Thu Jan 5 20:31:48 2006 +0000

    Fix test for mkfifo(). HAVE_MKFIFO is only generated as a config.h define by
    default.
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/ossman@396 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/configure.ac b/configure.ac
index eb4c941..2d75332 100644
--- a/configure.ac
+++ b/configure.ac
@@ -167,7 +167,8 @@ AC_FUNC_FORK
 AC_FUNC_GETGROUPS
 AC_FUNC_SELECT_ARGTYPES
 AC_CHECK_FUNCS([getaddrinfo getgrgid_r getpwuid_r gettimeofday getuid \
-    inet_ntop mkfifo nanosleep sigaction sleep])
+    inet_ntop nanosleep sigaction sleep])
+AC_CHECK_FUNCS([mkfifo], [HAVE_MKFIFO=1], [HAVE_MKFIFO=0])
 
 AM_CONDITIONAL(HAVE_MKFIFO, test "x$HAVE_MKFIFO" = "x1")
 

commit 29a5b850a7d8e9c4fc878afae336e16cba0c6c25
Author: Pierre Ossman <ossman at cendio.se>
Date:   Thu Jan 5 20:56:17 2006 +0000

    Emulate poll() through select() where needed.
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/ossman@397 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/polyp/Makefile.am b/polyp/Makefile.am
index 2cd2a1f..6ec75d4 100644
--- a/polyp/Makefile.am
+++ b/polyp/Makefile.am
@@ -327,7 +327,8 @@ libpolyp_error_ at PA_MAJORMINOR@_la_LDFLAGS = -version-info 0:0:0
 libpolyp_mainloop_ at PA_MAJORMINOR@_la_SOURCES = \
 		mainloop.c mainloop.h \
 		mainloop-api.h mainloop-api.c \
-		mainloop-signal.c mainloop-signal.h
+		mainloop-signal.c mainloop-signal.h \
+		poll.c poll.h
 libpolyp_mainloop_ at PA_MAJORMINOR@_la_CFLAGS = $(AM_CFLAGS)
 libpolyp_mainloop_ at PA_MAJORMINOR@_la_LIBADD = $(AM_LIBADD) libpolyp- at PA_MAJORMINOR@.la $(WINSOCK_LIBS)
 libpolyp_mainloop_ at PA_MAJORMINOR@_la_LDFLAGS = -version-info 0:0:0
@@ -413,6 +414,7 @@ libpolypcore_la_SOURCES = \
 		module.c module.h \
 		namereg.c namereg.h \
 		play-memchunk.c play-memchunk.h \
+		poll.c poll.h \
 		props.c props.h \
 		queue.c queue.h \
 		random.c random.h \
diff --git a/polyp/mainloop.c b/polyp/mainloop.c
index a0d2782..90243bd 100644
--- a/polyp/mainloop.c
+++ b/polyp/mainloop.c
@@ -26,13 +26,18 @@
 #include <stdio.h>
 #include <signal.h>
 #include <unistd.h>
-#include <sys/poll.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>
+#else
+#include "poll.h"
+#endif
+
 #include "mainloop.h"
 #include "util.h"
 #include "idxset.h"
diff --git a/polyp/module-alsa-sink.c b/polyp/module-alsa-sink.c
index 69db287..dde5d8b 100644
--- a/polyp/module-alsa-sink.c
+++ b/polyp/module-alsa-sink.c
@@ -25,7 +25,12 @@
 
 #include <assert.h>
 #include <stdio.h>
+
+#ifdef HAVE_SYS_POLL_H
 #include <sys/poll.h>
+#else
+#include "poll.h"
+#endif
 
 #include <asoundlib.h>
 
diff --git a/polyp/module-alsa-source.c b/polyp/module-alsa-source.c
index 55abe8e..5b4076f 100644
--- a/polyp/module-alsa-source.c
+++ b/polyp/module-alsa-source.c
@@ -25,7 +25,12 @@
 
 #include <assert.h>
 #include <stdio.h>
+
+#ifdef HAVE_SYS_POLL_H
 #include <sys/poll.h>
+#else
+#include "poll.h"
+#endif
 
 #include <asoundlib.h>
 
diff --git a/polyp/poll.c b/polyp/poll.c
new file mode 100644
index 0000000..82ea3d8
--- /dev/null
+++ b/polyp/poll.c
@@ -0,0 +1,173 @@
+/* $Id: mainloop.c 302 2004-11-21 17:02:25Z lennart $ */
+
+/***
+   Copyright (C) 1994, 1996, 1997 Free Software Foundation, Inc.
+   Copyright (C) 2005, Cendio AB.
+   This file is part of polypaudio.
+   Based on work for the GNU C Library.
+
+   polypaudio is free software; you can redistribute it and/or modify it
+   under the terms of the GNU Library General Public License as published
+   by the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   polypaudio 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with polypaudio; If not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+   USA.
+***/
+
+/* Poll the file descriptors described by the NFDS structures starting at
+   FDS.  If TIMEOUT is nonzero and not -1, allow TIMEOUT milliseconds for
+   an event to occur; if TIMEOUT is -1, block until an event occurs.
+   Returns the number of file descriptors with events, zero if timed out,
+   or -1 for errors.  */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef HAVE_SYS_SELECT_H
+#include <sys/select.h>
+#endif
+
+#ifndef HAVE_SYS_POLL_H
+
+#include "util.h"
+#include "poll.h"
+
+int poll (struct pollfd *fds, unsigned long int nfds, int timeout) {
+    struct timeval tv;
+    fd_set rset, wset, xset;
+    struct pollfd *f;
+    int ready;
+    int maxfd = 0;
+    char data[64];
+
+    FD_ZERO (&rset);
+    FD_ZERO (&wset);
+    FD_ZERO (&xset);
+
+    if (nfds == 0) {
+        if (timeout >= 0) {
+            pa_msleep(timeout);
+            return 0;
+        }
+
+        return select(0, NULL, NULL, NULL, NULL);
+    }
+
+    for (f = fds; f < &fds[nfds]; ++f) {
+        if (f->fd != -1) {
+            if (f->events & POLLIN)
+                FD_SET (f->fd, &rset);
+            if (f->events & POLLOUT)
+                FD_SET (f->fd, &wset);
+            if (f->events & POLLPRI)
+                FD_SET (f->fd, &xset);
+            if (f->fd > maxfd && (f->events & (POLLIN|POLLOUT|POLLPRI)))
+                maxfd = f->fd;
+        }
+    }
+
+    tv.tv_sec = timeout / 1000;
+    tv.tv_usec = (timeout % 1000) * 1000;
+
+    ready = select ((SELECT_TYPE_ARG1) maxfd + 1, SELECT_TYPE_ARG234 &rset,
+                    SELECT_TYPE_ARG234 &wset, SELECT_TYPE_ARG234 &xset,
+                    SELECT_TYPE_ARG5 (timeout == -1 ? NULL : &tv));
+    if ((ready == -1) && (errno == EBADF)) {
+        ready = 0;
+
+        FD_ZERO (&rset);
+        FD_ZERO (&wset);
+        FD_ZERO (&xset);
+
+        maxfd = -1;
+
+        for (f = fds; f < &fds[nfds]; ++f) {
+            if (f->fd != -1) {
+                fd_set sngl_rset, sngl_wset, sngl_xset;
+
+                FD_ZERO (&sngl_rset);
+                FD_ZERO (&sngl_wset);
+                FD_ZERO (&sngl_xset);
+
+                if (f->events & POLLIN)
+                    FD_SET (f->fd, &sngl_rset);
+                if (f->events & POLLOUT)
+                    FD_SET (f->fd, &sngl_wset);
+                if (f->events & POLLPRI)
+                    FD_SET (f->fd, &sngl_xset);
+                if (f->events & (POLLIN|POLLOUT|POLLPRI)) {
+                    struct timeval singl_tv;
+
+                    singl_tv.tv_sec = 0;
+                    singl_tv.tv_usec = 0;
+
+                    if (select((SELECT_TYPE_ARG1) f->fd, SELECT_TYPE_ARG234 &rset,
+                               SELECT_TYPE_ARG234 &wset, SELECT_TYPE_ARG234 &xset,
+                               SELECT_TYPE_ARG5 &singl_tv) != -1) {
+                        if (f->events & POLLIN)
+                            FD_SET (f->fd, &rset);
+                        if (f->events & POLLOUT)
+                            FD_SET (f->fd, &wset);
+                        if (f->events & POLLPRI)
+                            FD_SET (f->fd, &xset);
+                        if (f->fd > maxfd && (f->events & (POLLIN|POLLOUT|POLLPRI)))
+                            maxfd = f->fd;
+                        ++ready;
+                    } else if (errno == EBADF)
+                        f->revents |= POLLNVAL;
+                }
+            }
+        }
+
+        if (ready) {
+        /* Linux alters the tv struct... but it shouldn't matter here ...
+         * as we're going to be a little bit out anyway as we've just eaten
+         * more than a couple of cpu cycles above */
+            ready = select ((SELECT_TYPE_ARG1) maxfd + 1, SELECT_TYPE_ARG234 &rset,
+                            SELECT_TYPE_ARG234 &wset, SELECT_TYPE_ARG234 &xset,
+                            SELECT_TYPE_ARG5 (timeout == -1 ? NULL : &tv));
+        }
+    }
+
+    if (ready > 0) {
+        ready = 0;
+        for (f = fds; f < &fds[nfds]; ++f) {
+            f->revents = 0;
+            if (f->fd != -1) {
+                if (FD_ISSET (f->fd, &rset)) {
+                    /* support for POLLHUP.  An hung up descriptor does not
+                       increase the return value! */
+                    if (recv (f->fd, data, 64, MSG_PEEK) == -1) {
+                        if (errno == ESHUTDOWN || errno == ECONNRESET ||
+                            errno == ECONNABORTED || errno == ENETRESET) {
+                            fprintf(stderr, "Hangup\n");
+                            f->revents |= POLLHUP;
+                        }
+                    }
+
+                    if (f->revents == 0)
+                        f->revents |= POLLIN;
+                }
+                if (FD_ISSET (f->fd, &wset))
+                    f->revents |= POLLOUT;
+                if (FD_ISSET (f->fd, &xset))
+                    f->revents |= POLLPRI;
+            }
+            if (f->revents)
+                ready++;
+        }
+    }
+
+    return ready;
+}
+
+#endif /* HAVE_SYS_POLL_H */
diff --git a/polyp/poll.h b/polyp/poll.h
new file mode 100644
index 0000000..573f90e
--- /dev/null
+++ b/polyp/poll.h
@@ -0,0 +1,57 @@
+/* $Id: mainloop.c 302 2004-11-21 17:02:25Z lennart $ */
+
+/***
+   Compatibility definitions for System V `poll' interface.
+   Copyright (C) 1994,96,97,98,99,2000,2001,2004 Free Software Foundation, Inc.
+   Copyright (C) 2005, Cendio AB.
+   This file is part of polypaudio.
+   Based on work for the GNU C Library.
+
+   polypaudio is free software; you can redistribute it and/or modify it
+   under the terms of the GNU Library General Public License as published
+   by the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   polypaudio 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with polypaudio; If not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+   USA.
+***/
+
+/* Event types that can be polled for.  These bits may be set in `events'
+   to indicate the interesting event types; they will appear in `revents'
+   to indicate the status of the file descriptor.  */
+#define POLLIN          0x001           /* There is data to read.  */
+#define POLLPRI         0x002           /* There is urgent data to read.  */
+#define POLLOUT         0x004           /* Writing now will not block.  */
+
+/* Event types always implicitly polled for.  These bits need not be set in
+   `events', but they will appear in `revents' to indicate the status of
+   the file descriptor.  */
+#define POLLERR         0x008           /* Error condition.  */
+#define POLLHUP         0x010           /* Hung up.  */
+#define POLLNVAL        0x020           /* Invalid polling request.  */
+
+
+/* Type used for the number of file descriptors.  */
+typedef unsigned long int nfds_t;
+
+/* Data structure describing a polling request.  */
+struct pollfd
+  {
+    int fd;                     /* File descriptor to poll.  */
+    short int events;           /* Types of events poller cares about.  */
+    short int revents;          /* Types of events that actually occurred.  */
+  };
+
+/* Poll the file descriptors described by the NFDS structures starting at
+   FDS.  If TIMEOUT is nonzero and not -1, allow TIMEOUT milliseconds for
+   an event to occur; if TIMEOUT is -1, block until an event occurs.
+   Returns the number of file descriptors with events, zero if timed out,
+   or -1 for errors.  */
+extern int poll (struct pollfd *__fds, nfds_t __nfds, int __timeout);

commit e28ce8c59f193f53f1c722f3d54238e6d35de731
Author: Pierre Ossman <ossman at cendio.se>
Date:   Thu Jan 5 21:01:52 2006 +0000

    Use pa_get_path_filename() instead of duplicating code.
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/ossman@398 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/polyp/dumpmodules.c b/polyp/dumpmodules.c
index 1dc14ed..5aaa108 100644
--- a/polyp/dumpmodules.c
+++ b/polyp/dumpmodules.c
@@ -31,6 +31,7 @@
 
 #include "dumpmodules.h"
 #include "modinfo.h"
+#include "util.h"
 
 #define PREFIX "module-"
 
@@ -80,10 +81,7 @@ static int callback(const char *path, lt_ptr data) {
     const char *e;
     struct pa_daemon_conf *c = (data);
 
-    if ((e = (const char*) strrchr(path, '/')))
-        e++;
-    else
-        e = path;
+    e = pa_path_get_filename(path);
 
     if (strlen(e) > sizeof(PREFIX)-1 && !strncmp(e, PREFIX, sizeof(PREFIX)-1))
         show_info(e, path, c->log_level >= PA_LOG_INFO ? long_info : short_info);

commit 8f3c364b4700c8e459269ff00dbe810503038639
Author: Pierre Ossman <ossman at cendio.se>
Date:   Thu Jan 5 21:15:09 2006 +0000

    Make sure all socket headers are protected by ifdefs.
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/ossman@399 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/configure.ac b/configure.ac
index 2d75332..8200383 100644
--- a/configure.ac
+++ b/configure.ac
@@ -119,9 +119,9 @@ AM_CONDITIONAL(OS_IS_WIN32, test "x$os_is_win32" = "x1")
 AC_HEADER_STDC
 
 # POSIX
-AC_CHECK_HEADERS([glob.h grp.h netdb.h netinet/in.h netinet/tcp.h pwd.h \
-    sched.h sys/capability.h sys/resource.h sys/select.h sys/socket.h \
-    syslog.h])
+AC_CHECK_HEADERS([arpa/inet.h glob.h grp.h netdb.h netinet/in.h \
+    netinet/in_systm.h netinet/ip.h netinet/tcp.h pwd.h sched.h \
+    sys/capability.h sys/resource.h sys/select.h sys/socket.h syslog.h])
 AC_CHECK_HEADERS([regex.h], [HAVE_REGEX=1], [HAVE_REGEX=0])
 AC_CHECK_HEADERS([sys/un.h], [HAVE_AF_UNIX=1], [HAVE_AF_UNIX=0])
 
diff --git a/polyp/module-protocol-stub.c b/polyp/module-protocol-stub.c
index 1569758..0b91c68 100644
--- a/polyp/module-protocol-stub.c
+++ b/polyp/module-protocol-stub.c
@@ -27,9 +27,14 @@
 #include <errno.h>
 #include <stdio.h>
 #include <assert.h>
-#include <arpa/inet.h>
 #include <unistd.h>
+
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+#ifdef HAVE_NETINET_IN_H
 #include <netinet/in.h>
+#endif
 
 #include "module.h"
 #include "socket-server.h"
diff --git a/polyp/polyplib-context.c b/polyp/polyplib-context.c
index f54cabb..f85c5a4 100644
--- a/polyp/polyplib-context.c
+++ b/polyp/polyplib-context.c
@@ -28,14 +28,19 @@
 #include <stdlib.h>
 #include <string.h>
 #include <sys/types.h>
-#include <sys/socket.h>
-#include <netdb.h>
 #include <unistd.h>
 #include <sys/stat.h>
 #include <errno.h>
 #include <sys/wait.h>
 #include <signal.h>
 
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+
 #include "polyplib-internal.h"
 #include "polyplib-context.h"
 #include "native-common.h"
diff --git a/polyp/pstream.c b/polyp/pstream.c
index c081c24..a64856d 100644
--- a/polyp/pstream.c
+++ b/polyp/pstream.c
@@ -27,7 +27,10 @@
 #include <stdlib.h>
 #include <assert.h>
 #include <unistd.h>
+
+#ifdef HAVE_NETINET_IN_H
 #include <netinet/in.h>
+#endif
 
 #include "pstream.h"
 #include "queue.h"
diff --git a/polyp/socket-client.c b/polyp/socket-client.c
index 58bc7e8..0d712fa 100644
--- a/polyp/socket-client.c
+++ b/polyp/socket-client.c
@@ -31,14 +31,22 @@
 #include <string.h>
 #include <assert.h>
 #include <stdlib.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <netdb.h>
 
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
 #ifdef HAVE_SYS_UN_H
 #include <sys/un.h>
 #endif
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
 
 #ifdef HAVE_LIBASYNCNS
 #include <asyncns.h>
diff --git a/polyp/socket-server.c b/polyp/socket-server.c
index ed86bc2..0cca4ae 100644
--- a/polyp/socket-server.c
+++ b/polyp/socket-server.c
@@ -28,15 +28,21 @@
 #include <errno.h>
 #include <string.h>
 #include <sys/types.h>
-#include <sys/socket.h>
 #include <stdio.h>
 #include <unistd.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
 
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
 #ifdef HAVE_SYS_UN_H
 #include <sys/un.h>
 #endif
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
 
 #ifdef HAVE_LIBWRAP
 #include <tcpd.h>
diff --git a/polyp/socket-util.c b/polyp/socket-util.c
index eb6b424..60f8d16 100644
--- a/polyp/socket-util.c
+++ b/polyp/socket-util.c
@@ -31,19 +31,31 @@
 #include <string.h>
 #include <stdio.h>
 #include <sys/types.h>
-#include <netinet/in.h>
 #include <fcntl.h>
 #include <unistd.h>
-#include <netinet/in_systm.h>
-#include <netinet/tcp.h>
-#include <netinet/ip.h>
-#include <sys/socket.h>
 #include <sys/stat.h>
-#include <netdb.h>
 
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
 #ifdef HAVE_SYS_UN_H
 #include <sys/un.h>
 #endif
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_NETINET_IN_SYSTM_H
+#include <netinet/in_systm.h>
+#endif
+#ifdef HAVE_NETINET_IP_H
+#include <netinet/ip.h>
+#endif
+#ifdef HAVE_NETINET_TCP_H
+#include <netinet/tcp.h>
+#endif
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
 
 #include "socket-util.h"
 #include "util.h"
diff --git a/polyp/tagstruct.c b/polyp/tagstruct.c
index a6dad86..a3bd7d9 100644
--- a/polyp/tagstruct.c
+++ b/polyp/tagstruct.c
@@ -27,9 +27,12 @@
 #include <string.h>
 #include <unistd.h>
 #include <sys/time.h>
-#include <netinet/in.h>
 #include <assert.h>
 
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+
 #include "tagstruct.h"
 #include "xmalloc.h"
 
diff --git a/polyp/util.c b/polyp/util.c
index 9e8dc5e..67eaeda 100644
--- a/polyp/util.c
+++ b/polyp/util.c
@@ -41,7 +41,10 @@
 #include <sys/resource.h>
 #include <limits.h>
 #include <unistd.h>
+
+#ifdef HAVE_NETDB_H
 #include <netdb.h>
+#endif
 
 #include <samplerate.h>
 

commit 268aebb2e44d772e3cff25d40403a720f80abd09
Author: Pierre Ossman <ossman at cendio.se>
Date:   Thu Jan 5 21:21:51 2006 +0000

    Protect sys/wait.h with an ifdef.
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/ossman@400 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/configure.ac b/configure.ac
index 8200383..981c74c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -121,7 +121,8 @@ AC_HEADER_STDC
 # POSIX
 AC_CHECK_HEADERS([arpa/inet.h glob.h grp.h netdb.h netinet/in.h \
     netinet/in_systm.h netinet/ip.h netinet/tcp.h pwd.h sched.h \
-    sys/capability.h sys/resource.h sys/select.h sys/socket.h syslog.h])
+    sys/capability.h sys/resource.h sys/select.h sys/socket.h sys/wait.h \
+    syslog.h])
 AC_CHECK_HEADERS([regex.h], [HAVE_REGEX=1], [HAVE_REGEX=0])
 AC_CHECK_HEADERS([sys/un.h], [HAVE_AF_UNIX=1], [HAVE_AF_UNIX=0])
 
diff --git a/polyp/polyplib-context.c b/polyp/polyplib-context.c
index f85c5a4..1b9d7de 100644
--- a/polyp/polyplib-context.c
+++ b/polyp/polyplib-context.c
@@ -31,9 +31,12 @@
 #include <unistd.h>
 #include <sys/stat.h>
 #include <errno.h>
-#include <sys/wait.h>
 #include <signal.h>
 
+#ifdef HAVE_SYS_WAIT_H
+#include <sys/wait.h>
+#endif
+
 #ifdef HAVE_SYS_SOCKET_H
 #include <sys/socket.h>
 #endif

commit e2495c7600f45cd3803cdc86fe0fe0cb11d6dfd5
Author: Pierre Ossman <ossman at cendio.se>
Date:   Thu Jan 5 21:24:39 2006 +0000

    We need explicit actions here.
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/ossman@401 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/configure.ac b/configure.ac
index 981c74c..5411296 100644
--- a/configure.ac
+++ b/configure.ac
@@ -155,7 +155,7 @@ AC_TYPE_OFF_T
 AC_TYPE_SIGNAL
 AC_TYPE_UID_T
 
-AC_CHECK_DEFINE([SIGXCPU], [signal.h])
+AC_CHECK_DEFINE([SIGXCPU], [signal.h], [HAVE_SIGXCPU=1], [HAVE_SIGXCPU=0])
 AM_CONDITIONAL(HAVE_SIGXCPU, test "x$HAVE_SIGXCPU" = "x1")
 
 #### Check for functions ####

commit 971e370a2fdc6496fab680844393955de8d3eed2
Author: Pierre Ossman <ossman at cendio.se>
Date:   Thu Jan 5 21:33:01 2006 +0000

    Add possibility for linking semi-static executables (libtools definition
    of static).
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/ossman@402 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/configure.ac b/configure.ac
index 5411296..08f7e2b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -291,6 +291,12 @@ AM_CONDITIONAL([HAVE_LIRC], [test "x$HAVE_LIRC" = x1])
 #            Output               #
 ###################################
 
+AC_ARG_ENABLE(
+        [static-bins],
+        AC_HELP_STRING([--enable-static-bins],[Statically link executables.]),
+        [STATIC_BINS=1], [STATIC_BINS=0])
+AM_CONDITIONAL([STATIC_BINS], [test "x$STATIC_BINS" = "x1"])
+
 AC_CONFIG_FILES([
 Makefile
 polyp/Makefile
diff --git a/polyp/Makefile.am b/polyp/Makefile.am
index 6ec75d4..2e8361c 100644
--- a/polyp/Makefile.am
+++ b/polyp/Makefile.am
@@ -47,6 +47,10 @@ AM_LDADD = $(PTHREAD_LIBS)
 # Only required on some platforms but defined for all to avoid errors
 AM_LDFLAGS = -no-undefined
 
+if STATIC_BINS
+BINLDFLAGS = -static
+endif
+
 if OS_IS_WIN32
 AM_LDFLAGS+=-Wl,--export-all-symbols
 WINSOCK_LIBS=-lwsock32 -lws2_32 -lwininet
@@ -89,7 +93,7 @@ polypaudio_CFLAGS = $(AM_CFLAGS)
 polypaudio_CPPFLAGS = $(AM_CPPFLAGS)
 polypaudio_LDADD = $(AM_LDADD) libpolypcore.la $(LIBLTDL) \
 		$(LIBSAMPLERATE_LIBS) $(LIBSNDFILE_LIBS) $(CAP_LIBS)
-polypaudio_LDFLAGS= $(AM_LDFLAGS) -dlopen force 
+polypaudio_LDFLAGS= $(AM_LDFLAGS) $(BINLDFLAGS) -dlopen force 
 #q-static $(foreach f,$(modlib_LTLIBRARIES),-dlpreopen $(f))
 
 ###################################
@@ -118,26 +122,32 @@ bin_SCRIPTS = esdcompat.sh
 pacat_SOURCES = pacat.c
 pacat_LDADD = $(AM_LDADD) libpolyp- at PA_MAJORMINOR@.la libpolyp-error- at PA_MAJORMINOR@.la libpolyp-mainloop- at PA_MAJORMINOR@.la
 pacat_CFLAGS = $(AM_CFLAGS) 
+pacat_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS)
 
 paplay_SOURCES = paplay.c
 paplay_LDADD = $(AM_LDADD) libpolyp- at PA_MAJORMINOR@.la libpolyp-error- at PA_MAJORMINOR@.la libpolyp-mainloop- at PA_MAJORMINOR@.la $(LIBSNDFILE_LIBS)
 paplay_CFLAGS = $(AM_CFLAGS) $(LIBSNDFILE_CFLAGS)
+paplay_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS)
 
 pactl_SOURCES = pactl.c
 pactl_LDADD = $(AM_LDADD) libpolyp- at PA_MAJORMINOR@.la libpolyp-error- at PA_MAJORMINOR@.la libpolyp-mainloop- at PA_MAJORMINOR@.la $(LIBSNDFILE_LIBS)
 pactl_CFLAGS = $(AM_CFLAGS) $(LIBSNDFILE_CFLAGS)
+pactl_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS)
 
 pacmd_SOURCES = pacmd.c util.c util.h xmalloc.c xmalloc.h log.c log.h pid.c pid.h
 pacmd_CFLAGS = $(AM_CFLAGS)
 pacmd_LDADD = $(AM_LDADD)
+pacmd_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS)
 
 pax11publish_SOURCES = pax11publish.c util.c util.h xmalloc.c xmalloc.h log.c log.h authkey.c authkey.h client-conf.c client-conf.h conf-parser.c conf-parser.h x11prop.c x11prop.h random.c random.h
 pax11publish_CFLAGS = $(AM_CFLAGS) $(X_CFLAGS)
 pax11publish_LDADD = $(AM_LDADD) $(X_PRE_LIBS) -lX11 $(X_LIBS) $(X_EXTRA_LIBS)
+pax11publish_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS)
 
 pabrowse_SOURCES = pabrowse.c
 pabrowse_LDADD = $(AM_LDADD) libpolyp- at PA_MAJORMINOR@.la libpolyp-error- at PA_MAJORMINOR@.la libpolyp-mainloop- at PA_MAJORMINOR@.la libpolyp-browse- at PA_MAJORMINOR@.la
 pabrowse_CFLAGS = $(AM_CFLAGS)
+pabrowse_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS)
 
 ###################################
 #         Test programs           #
@@ -170,42 +180,52 @@ endif
 mainloop_test_SOURCES = mainloop-test.c
 mainloop_test_CFLAGS = $(AM_CFLAGS)
 mainloop_test_LDADD = $(AM_LDADD) libpolyp-mainloop- at PA_MAJORMINOR@.la libpolyp- at PA_MAJORMINOR@.la
+mainloop_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS)
 
 mcalign_test_SOURCES = mcalign-test.c util.c util.h xmalloc.c xmalloc.h log.c log.h mcalign.c mcalign.h memchunk.c memchunk.h memblock.c memblock.h
 mcalign_test_CFLAGS = $(AM_CFLAGS)
 mcalign_test_LDADD = $(AM_LDADD) $(WINSOCK_LIBS)
+mcalign_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS)
 
 pacat_simple_SOURCES = pacat-simple.c
 pacat_simple_LDADD = $(AM_LDADD) libpolyp- at PA_MAJORMINOR@.la libpolyp-simple- at PA_MAJORMINOR@.la libpolyp-error- at PA_MAJORMINOR@.la libpolyp-mainloop- at PA_MAJORMINOR@.la
 pacat_simple_CFLAGS = $(AM_CFLAGS)
+pacat_simple_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS)
 
 parec_simple_SOURCES = parec-simple.c
 parec_simple_LDADD = $(AM_LDADD) libpolyp- at PA_MAJORMINOR@.la libpolyp-simple- at PA_MAJORMINOR@.la libpolyp-error- at PA_MAJORMINOR@.la libpolyp-mainloop- at PA_MAJORMINOR@.la
 parec_simple_CFLAGS = $(AM_CFLAGS)
+parec_simple_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS)
 
 strlist_test_SOURCES = strlist-test.c strlist.c strlist.h strbuf.c strbuf.h util.c util.h xmalloc.c xmalloc.h log.c log.h
 strlist_test_CFLAGS = $(AM_CFLAGS)
 strlist_test_LDADD = $(AM_LDADD) $(WINSOCK_LIBS)
+strlist_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS)
 
 voltest_SOURCES = voltest.c sample.c
 voltest_CFLAGS = $(AM_CFLAGS)
 voltest_LDADD = $(AM_LDADD)
+voltest_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS)
 
 cpulimit_test_SOURCES = cpulimit-test.c cpulimit.c util.c log.c cpulimit.h util.h log.h
 cpulimit_test_CFLAGS = $(AM_CFLAGS)
 cpulimit_test_LDADD = $(AM_LDADD) libpolyp-mainloop- at PA_MAJORMINOR@.la
+cpulimit_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS)
 
 cpulimit_test2_SOURCES = cpulimit-test.c cpulimit.c util.c log.c cpulimit.h util.h log.h
 cpulimit_test2_CFLAGS = $(AM_CFLAGS) -DTEST2
 cpulimit_test2_LDADD = $(AM_LDADD) libpolyp-mainloop- at PA_MAJORMINOR@.la
+cpulimit_test2_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS)
 
 mainloop_test_glib_SOURCES = $(mainloop_test_SOURCES)
 mainloop_test_glib_CFLAGS = $(mainloop_test_CFLAGS) $(GLIB20_CFLAGS) -DGLIB_MAIN_LOOP
 mainloop_test_glib_LDADD = $(mainloop_test_LDADD) $(GLIB20_LIBS) libpolyp-mainloop-glib- at PA_MAJORMINOR@.la
+mainloop_test_glib_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS)
 
 mainloop_test_glib12_SOURCES = $(mainloop_test_SOURCES)
 mainloop_test_glib12_CFLAGS = $(mainloop_test_CFLAGS) $(GLIB12_CFLAGS) -DGLIB_MAIN_LOOP
 mainloop_test_glib12_LDADD = $(mainloop_test_LDADD) $(GLIB12_LIBS) libpolyp-mainloop-glib12- at PA_MAJORMINOR@.la
+mainloop_test_glib12_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS)
 
 ###################################
 #         Client library          #

commit 9550c8ed80dee1aa7ced2d18144fd7b1a3b5a395
Author: Pierre Ossman <ossman at cendio.se>
Date:   Thu Jan 5 21:37:00 2006 +0000

    No need for conditional generation of symdef files.
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/ossman@403 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/polyp/Makefile.am b/polyp/Makefile.am
index 2e8361c..614a187 100644
--- a/polyp/Makefile.am
+++ b/polyp/Makefile.am
@@ -744,25 +744,13 @@ SYMDEF_FILES = \
 		module-mmkbd-evdev-symdef.h \
 		module-http-protocol-tcp-symdef.h \
 		module-http-protocol-tcp6-symdef.h \
-		module-http-protocol-unix-symdef.h
-
-if HAVE_X11
-SYMDEF_FILES += \
+		module-http-protocol-unix-symdef.h \
 		module-x11-bell-symdef.h \
-		module-x11-publish-symdef.h
-endif
-
-if !OS_IS_WIN32
-SYMDEF_FILES += \
+		module-x11-publish-symdef.h \
 		module-oss-symdef.h \
-		module-oss-mmap-symdef.h
-endif
-
-if HAVE_ALSA
-SYMDEF_FILES += \
+		module-oss-mmap-symdef.h \
 		module-alsa-sink-symdef.h \
 		module-alsa-source-symdef.h
-endif
 
 EXTRA_DIST += $(SYMDEF_FILES)
 BUILT_SOURCES += $(SYMDEF_FILES)

commit be2ba901751755f1673b0559a29fdcb9ca651405
Author: Pierre Ossman <ossman at cendio.se>
Date:   Thu Jan 5 21:39:49 2006 +0000

    Add option to select which modules get linked in during static builds.
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/ossman@404 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/configure.ac b/configure.ac
index 08f7e2b..941be8b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -297,6 +297,20 @@ AC_ARG_ENABLE(
         [STATIC_BINS=1], [STATIC_BINS=0])
 AM_CONDITIONAL([STATIC_BINS], [test "x$STATIC_BINS" = "x1"])
 
+AC_ARG_WITH(
+        [preopen-mods],
+        AC_HELP_STRING([--with-preopen-mods],[Modules to preopen in daemon (default: all).]),
+        [PREOPEN_MODS=$withval], [PREOPEN_MODS="all"])
+AM_CONDITIONAL([PREOPEN_MODS], [test "x$PREOPEN_MODS" != "xall"])
+if test "x$PREOPEN_MODS" != "xall" ; then
+    tmpLIBS=""
+    for mod in $PREOPEN_MODS; do
+        tmpLIBS="$tmpLIBS module-$mod.la"
+    done
+    PREOPEN_MODS="$tmpLIBS"
+    AC_SUBST(PREOPEN_MODS)
+fi
+
 AC_CONFIG_FILES([
 Makefile
 polyp/Makefile
diff --git a/polyp/Makefile.am b/polyp/Makefile.am
index 614a187..a066813 100644
--- a/polyp/Makefile.am
+++ b/polyp/Makefile.am
@@ -93,8 +93,13 @@ polypaudio_CFLAGS = $(AM_CFLAGS)
 polypaudio_CPPFLAGS = $(AM_CPPFLAGS)
 polypaudio_LDADD = $(AM_LDADD) libpolypcore.la $(LIBLTDL) \
 		$(LIBSAMPLERATE_LIBS) $(LIBSNDFILE_LIBS) $(CAP_LIBS)
-polypaudio_LDFLAGS= $(AM_LDFLAGS) $(BINLDFLAGS) -dlopen force 
-#q-static $(foreach f,$(modlib_LTLIBRARIES),-dlpreopen $(f))
+polypaudio_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) -dlopen force $(foreach f,$(PREOPEN_LIBS),-dlopen $(f))
+
+if PREOPEN_MODS
+PREOPEN_LIBS = $(PREOPEN_MODS)
+else
+PREOPEN_LIBS = $(modlib_LTLIBRARIES)
+endif
 
 ###################################
 #       Utility programs          #

commit 08bbfd2169ff81e37f0e5bd911490fc07b8f05f9
Author: Pierre Ossman <ossman at cendio.se>
Date:   Thu Jan 5 21:46:10 2006 +0000

    Make it possible to disable caps support since it breaks fully static
    builds.
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/ossman@405 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/configure.ac b/configure.ac
index 941be8b..5f8da07 100644
--- a/configure.ac
+++ b/configure.ac
@@ -210,7 +210,15 @@ fi
 
 #### Capabilities (optional) ####
 
-AC_CHECK_LIB(cap, cap_init, [CAP_LIBS='-lcap'], [CAP_LIBS=''])
+CAP_LIBS=''
+
+AC_ARG_WITH(
+        [caps],
+        AC_HELP_STRING([--without-caps],[Omit support for POSIX capabilities.]))
+
+if test "x${with_caps}" != "xno"; then
+    AC_CHECK_LIB(cap, cap_init, [CAP_LIBS='-lcap'], [CAP_LIBS=''])
+fi
 AC_SUBST(CAP_LIBS)
 
 #### Sample rate conversion ####

commit 2cf165db8bbcf43d9be3404f9566d523c8d6e323
Author: Pierre Ossman <ossman at cendio.se>
Date:   Thu Jan 5 21:49:22 2006 +0000

    ifdef-protect setpgid and setsid.
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/ossman@406 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/configure.ac b/configure.ac
index 5f8da07..1899e92 100644
--- a/configure.ac
+++ b/configure.ac
@@ -168,7 +168,7 @@ AC_FUNC_FORK
 AC_FUNC_GETGROUPS
 AC_FUNC_SELECT_ARGTYPES
 AC_CHECK_FUNCS([getaddrinfo getgrgid_r getpwuid_r gettimeofday getuid \
-    inet_ntop nanosleep sigaction sleep])
+    inet_ntop nanosleep setpgid setsid sigaction sleep])
 AC_CHECK_FUNCS([mkfifo], [HAVE_MKFIFO=1], [HAVE_MKFIFO=0])
 
 AM_CONDITIONAL(HAVE_MKFIFO, test "x$HAVE_MKFIFO" = "x1")
diff --git a/polyp/main.c b/polyp/main.c
index 2e97e5c..a56d2f1 100644
--- a/polyp/main.c
+++ b/polyp/main.c
@@ -258,8 +258,12 @@ int main(int argc, char *argv[]) {
         if (conf->auto_log_target)
             pa_log_set_target(PA_LOG_SYSLOG, NULL);
 
+#ifdef HAVE_SETSID
         setsid();
+#endif
+#ifdef HAVE_SETPGID
         setpgid(0,0);
+#endif
         
         close(0);
         close(1);

commit 7aba34bc4e3835dd84f13506555702993a3eeacc
Author: Pierre Ossman <ossman at cendio.se>
Date:   Thu Jan 5 21:56:33 2006 +0000

    config.h should always be included so that necessary fixes can take effect.
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/ossman@407 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/polyp/conf-parser.c b/polyp/conf-parser.c
index b25508e..8d2f2f6 100644
--- a/polyp/conf-parser.c
+++ b/polyp/conf-parser.c
@@ -19,6 +19,10 @@
   USA.
 ***/
 
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
 #include <assert.h>
 #include <string.h>
 #include <stdio.h>

commit 983fdb3238ec717208cd354fc4e487bd69bf1d30
Author: Pierre Ossman <ossman at cendio.se>
Date:   Thu Jan 5 22:05:20 2006 +0000

    Stub uses socket defines so include the header.
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/ossman@408 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/polyp/module-protocol-stub.c b/polyp/module-protocol-stub.c
index 0b91c68..37a17c8 100644
--- a/polyp/module-protocol-stub.c
+++ b/polyp/module-protocol-stub.c
@@ -29,6 +29,9 @@
 #include <assert.h>
 #include <unistd.h>
 
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
 #ifdef HAVE_ARPA_INET_H
 #include <arpa/inet.h>
 #endif

commit ecaf8d805e8d061d1f882132012cf0c1060d1b04
Author: Pierre Ossman <ossman at cendio.se>
Date:   Thu Jan 5 22:06:52 2006 +0000

    PATH_MAX is defined in limits.h.
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/ossman@409 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/polyp/module-protocol-stub.c b/polyp/module-protocol-stub.c
index 37a17c8..7cd5ed3 100644
--- a/polyp/module-protocol-stub.c
+++ b/polyp/module-protocol-stub.c
@@ -28,6 +28,7 @@
 #include <stdio.h>
 #include <assert.h>
 #include <unistd.h>
+#include <limits.h>
 
 #ifdef HAVE_SYS_SOCKET_H
 #include <sys/socket.h>

commit 5ac2cb90f73116f7c3ccadd4d89c26c01e3c6c0e
Author: Pierre Ossman <ossman at cendio.se>
Date:   Thu Jan 5 22:09:40 2006 +0000

    No regexp funtions are used in this file.
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/ossman@410 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/polyp/module-tunnel.c b/polyp/module-tunnel.c
index 749aebf..c6a35ca 100644
--- a/polyp/module-tunnel.c
+++ b/polyp/module-tunnel.c
@@ -28,7 +28,6 @@
 #include <string.h>
 #include <errno.h>
 #include <sys/types.h>
-#include <regex.h>
 #include <stdio.h>
 #include <stdlib.h>
 

commit 010476f226124292e05d26ddbb931827beccd39e
Author: Pierre Ossman <ossman at cendio.se>
Date:   Thu Jan 5 22:12:25 2006 +0000

    Protect getuid() with an ifdef.
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/ossman@411 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/polyp/caps.c b/polyp/caps.c
index 739e707..4ecb584 100644
--- a/polyp/caps.c
+++ b/polyp/caps.c
@@ -35,6 +35,8 @@
 #include "log.h"
 #include "caps.h"
 
+#ifdef HAVE_GETUID
+
 /* Drop root rights when called SUID root */
 void pa_drop_root(void) {
     uid_t uid = getuid();
@@ -54,6 +56,13 @@ void pa_drop_root(void) {
 #endif
 }
 
+#else
+
+void pa_drop_root(void) {
+}
+
+#endif
+
 #ifdef HAVE_SYS_CAPABILITY_H
 
 /* Limit capabilities set to CAPSYS_NICE */
diff --git a/polyp/main.c b/polyp/main.c
index a56d2f1..12b6b83 100644
--- a/polyp/main.c
+++ b/polyp/main.c
@@ -117,18 +117,25 @@ int main(int argc, char *argv[]) {
     char *s;
     int r, retval = 1, d = 0;
     int daemon_pipe[2] = { -1, -1 };
-    gid_t gid = (gid_t) -1;
     int suid_root;
     int valid_pid_file = 0;
 
+#ifdef HAVE_GETUID
+    gid_t gid = (gid_t) -1;
+#endif
+
     pa_limit_caps();
 
+#ifdef HAVE_GETUID
     suid_root = getuid() != 0 && geteuid() == 0;
     
     if (suid_root && (pa_uid_in_group("realtime", &gid) <= 0 || gid >= 1000)) {
         pa_log_warn(__FILE__": WARNING: called SUID root, but not in group 'realtime'.\n");
         pa_drop_root();
     }
+#else
+    suid_root = 0;
+#endif
     
     LTDL_SET_PRELOADED_SYMBOLS();
     

commit e72bbdb21744fe5c0ab3494126656518f4bcb524
Author: Pierre Ossman <ossman at cendio.se>
Date:   Thu Jan 5 22:14:22 2006 +0000

    c was used before it was assigned.
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/ossman@412 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/polyp/main.c b/polyp/main.c
index 12b6b83..3f9f359 100644
--- a/polyp/main.c
+++ b/polyp/main.c
@@ -311,6 +311,9 @@ int main(int argc, char *argv[]) {
     mainloop = pa_mainloop_new();
     assert(mainloop);
 
+    c = pa_core_new(pa_mainloop_get_api(mainloop));
+    assert(c);
+
     r = pa_signal_init(pa_mainloop_get_api(mainloop));
     assert(r == 0);
     pa_signal_new(SIGINT, signal_callback, c);
@@ -319,8 +322,6 @@ int main(int argc, char *argv[]) {
     signal(SIGPIPE, SIG_IGN);
 #endif
 
-    c = pa_core_new(pa_mainloop_get_api(mainloop));
-    assert(c);
     if (conf->daemonize)
         c->running_as_daemon = 1;
     

commit 2c4d42e7817d2bac20bcd71d603be1389b8d9337
Author: Pierre Ossman <ossman at cendio.se>
Date:   Thu Jan 5 22:27:14 2006 +0000

    ctime_r() is not available everywhere.
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/ossman@413 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/polyp/cli-command.c b/polyp/cli-command.c
index 0e8e09a..1244787 100644
--- a/polyp/cli-command.c
+++ b/polyp/cli-command.c
@@ -641,7 +641,11 @@ static int pa_cli_command_dump(struct pa_core *c, struct pa_tokenizer *t, struct
 
     time(&now);
 
+#ifdef HAVE_CTIME_R
     pa_strbuf_printf(buf, "### Configuration dump generated at %s\n", ctime_r(&now, txt));
+#else
+    pa_strbuf_printf(buf, "### Configuration dump generated at %s\n", ctime(&now));
+#endif
 
     
     for (m = pa_idxset_first(c->modules, &index); m; m = pa_idxset_next(c->modules, &index)) {

commit 57dccd259269003aace56bbb8a1a24dad42f10f2
Author: Pierre Ossman <ossman at cendio.se>
Date:   Thu Jan 5 22:32:00 2006 +0000

    Replace paths with defines.
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/ossman@414 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/polyp/Makefile.am b/polyp/Makefile.am
index a066813..beac830 100644
--- a/polyp/Makefile.am
+++ b/polyp/Makefile.am
@@ -28,6 +28,17 @@ polypconfdir=$(sysconfdir)/polypaudio
 modlibdir=$(libdir)/polypaudio- at PA_MAJORMINOR@
 
 ###################################
+#            Defines              #
+###################################
+
+POLYPAUDIO_BINARY=$(bindir)/polypaudio$(EXEEXT)
+if OS_IS_WIN32
+DEFAULT_CONFIG_DIR=%POLYP_ROOT%
+else
+DEFAULT_CONFIG_DIR=$(polypconfdir)
+endif
+
+###################################
 #     Compiler/linker flags       #
 ###################################
 
@@ -35,8 +46,8 @@ AM_CFLAGS  = -D_GNU_SOURCE  -I$(top_srcdir)
 AM_CFLAGS += $(PTHREAD_CFLAGS) $(LTDLINCL)
 AM_CFLAGS += $(LIBSAMPLERATE_CFLAGS) $(LIBSNDFILE_CFLAGS)
 AM_CFLAGS += -DDLSEARCHPATH=\"$(modlibdir)\"
-AM_CFLAGS += -DDEFAULT_CONFIG_DIR=\"$(polypconfdir)\"
-AM_CFLAGS += -DPOLYPAUDIO_BINARY=\"$(bindir)/polypaudio$(EXEEXT)\"
+AM_CFLAGS += -DDEFAULT_CONFIG_DIR=\"$(DEFAULT_CONFIG_DIR)\"
+AM_CFLAGS += -DPOLYPAUDIO_BINARY=\"$(POLYPAUDIO_BINARY)\"
 
 # This cool debug trap works on i386/gcc only
 AM_CFLAGS += '-DDEBUG_TRAP=__asm__("int $$3")'
@@ -974,17 +985,17 @@ suid: polypaudio
 esdcompat.sh: esdcompat.sh.in Makefile
 	sed -e 's, at PACKAGE_VERSION\@,$(PACKAGE_VERSION),g' \
 		-e 's, at PACKAGE_NAME\@,$(PACKAGE_NAME),g' \
-		-e 's, at POLYPAUDIO_BINARY\@,$(bindir)/polypaudio,g' < $< > $@
+		-e 's, at POLYPAUDIO_BINARY\@,$(POLYPAUDIO_BINARY),g' < $< > $@
 
 client.conf: client.conf.in Makefile
-	sed -e 's, at POLYPAUDIO_BINARY\@,$(bindir)/polypaudio,g' < $< > $@
+	sed -e 's, at POLYPAUDIO_BINARY\@,$(POLYPAUDIO_BINARY),g' < $< > $@
 
 default.pa: default.pa.in Makefile
-	sed -e 's, at POLYPAUDIO_BINARY\@,$(bindir)/polypaudio,g' < $< > $@
+	sed -e 's, at POLYPAUDIO_BINARY\@,$(POLYPAUDIO_BINARY),g' < $< > $@
 
 daemon.conf: daemon.conf.in Makefile
 	sed -e 's, at DLSEARCHPATH\@,$(modlibdir),g' \
-		-e 's, at DEFAULT_CONFIG_FILE\@,$(polypconfdir)/daemon.conf,g' < $< > $@
+		-e 's, at DEFAULT_CONFIG_FILE\@,$(DEFAULT_CONFIG_DIR),g' < $< > $@
 
 install-exec-hook:
 	chown root $(DESTDIR)$(bindir)/polypaudio ; true

commit 67833c2bcf1019f48df2cbabd654c67a6d4b7fef
Author: Pierre Ossman <ossman at cendio.se>
Date:   Thu Jan 5 22:40:45 2006 +0000

    Protect sched.h with ifdef.
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/ossman@415 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/polyp/util.c b/polyp/util.c
index 67eaeda..a05e601 100644
--- a/polyp/util.c
+++ b/polyp/util.c
@@ -37,11 +37,14 @@
 #include <signal.h>
 #include <pthread.h>
 #include <sys/time.h>
-#include <sched.h>
 #include <sys/resource.h>
 #include <limits.h>
 #include <unistd.h>
 
+#ifdef HAVE_SCHED_H
+#include <sched.h>
+#endif
+
 #ifdef HAVE_NETDB_H
 #include <netdb.h>
 #endif

commit bdc02f71f505b6a7b6874a7b3f6beff31355bb7c
Author: Pierre Ossman <ossman at cendio.se>
Date:   Thu Jan 5 22:42:26 2006 +0000

    Protect sys/resource.h with an ifdef.
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/ossman@416 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/polyp/cpulimit.c b/polyp/cpulimit.c
index f121123..53920f5 100644
--- a/polyp/cpulimit.c
+++ b/polyp/cpulimit.c
@@ -30,10 +30,13 @@
 #include <string.h>
 #include <assert.h>
 #include <sys/time.h>
-#include <sys/resource.h>
 #include <unistd.h>
 #include <signal.h>
 
+#ifdef HAVE_SYS_RESOURCE_H
+#include <sys/resource.h>
+#endif
+
 #include "cpulimit.h"
 #include "util.h"
 #include "log.h"
diff --git a/polyp/util.c b/polyp/util.c
index a05e601..cccb665 100644
--- a/polyp/util.c
+++ b/polyp/util.c
@@ -37,7 +37,6 @@
 #include <signal.h>
 #include <pthread.h>
 #include <sys/time.h>
-#include <sys/resource.h>
 #include <limits.h>
 #include <unistd.h>
 
@@ -45,6 +44,10 @@
 #include <sched.h>
 #endif
 
+#ifdef HAVE_SYS_RESOURCE_H
+#include <sys/resource.h>
+#endif
+
 #ifdef HAVE_NETDB_H
 #include <netdb.h>
 #endif

commit 2f74bb9d437fc165695e1d4bb7516ca979962a49
Author: Pierre Ossman <ossman at cendio.se>
Date:   Thu Jan 5 22:44:23 2006 +0000

    Protect pthread.h with an ifdef.
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/ossman@417 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/polyp/util.c b/polyp/util.c
index cccb665..acfa031 100644
--- a/polyp/util.c
+++ b/polyp/util.c
@@ -35,7 +35,6 @@
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <signal.h>
-#include <pthread.h>
 #include <sys/time.h>
 #include <limits.h>
 #include <unistd.h>
@@ -48,6 +47,10 @@
 #include <sys/resource.h>
 #endif
 
+#ifdef HAVE_PTHREAD
+#include <pthread.h>
+#endif
+
 #ifdef HAVE_NETDB_H
 #include <netdb.h>
 #endif

commit 19d9fcbda8637099854f2d8147b402b4420d19f5
Author: Pierre Ossman <ossman at cendio.se>
Date:   Thu Jan 5 22:51:37 2006 +0000

    Port to Windows. This is mostly glue layers for the poor POSIX support
    on Windows. A few notes
    
     * Only sockets behave somewhat like file descriptors in UNIX.
    
     * There are no fixed paths. Closes thing is environment variables that point
       to system directories. We also figure out where the binary/dll is
       located and use that as configuration directory.
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/ossman@418 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/configure.ac b/configure.ac
index 1899e92..5ff28a5 100644
--- a/configure.ac
+++ b/configure.ac
@@ -138,7 +138,7 @@ AC_CHECK_HEADERS([linux/input.h], [HAVE_EVDEV=1], [HAVE_EVDEV=0])
 AM_CONDITIONAL([HAVE_EVDEV], [test "x$HAVE_EVDEV" = "x1"])
 
 # Windows
-AC_CHECK_HEADERS([winsock2.h ws2tcpip.h])
+AC_CHECK_HEADERS([windows.h winsock2.h ws2tcpip.h])
 
 # Other
 AC_CHECK_HEADERS([sys/ioctl.h])
diff --git a/polyp/Makefile.am b/polyp/Makefile.am
index beac830..dcd3fc1 100644
--- a/polyp/Makefile.am
+++ b/polyp/Makefile.am
@@ -298,6 +298,7 @@ libpolyp_ at PA_MAJORMINOR@_la_SOURCES = \
 		cdecl.h \
 		client-conf.c client-conf.h \
 		conf-parser.c conf-parser.h \
+		dllmain.c \
 		dynarray.c dynarray.h \
 		gcc-printf.h \
 		idxset.c idxset.h \
@@ -432,6 +433,7 @@ libpolypcore_la_SOURCES = \
 		cli-text.c cli-text.h \
 		client.c client.h \
 		core.c core.h \
+		dllmain.c \
 		dynarray.c dynarray.h \
 		endianmacros.h \
 		g711.c g711.h \
@@ -562,7 +564,7 @@ libpdispatch_la_LIBADD = $(AM_LIBADD) libtagstruct.la libpolypcore.la
 
 libiochannel_la_SOURCES = iochannel.c iochannel.h
 libiochannel_la_LDFLAGS = -avoid-version
-libiochannel_la_LIBADD = $(AM_LIBADD) libsocket-util.la libpolypcore.la
+libiochannel_la_LIBADD = $(AM_LIBADD) libsocket-util.la libpolypcore.la $(WINSOCK_LIBS)
 
 libpacket_la_SOURCES = packet.c packet.h
 libpacket_la_LDFLAGS = -avoid-version
@@ -727,6 +729,11 @@ modlib_LTLIBRARIES += \
 		module-mmkbd-evdev.la
 endif
 
+if OS_IS_WIN32
+modlib_LTLIBRARIES += \
+		module-waveout.la
+endif
+
 # These are generated by a M4 script
 
 SYMDEF_FILES = \
@@ -766,7 +773,8 @@ SYMDEF_FILES = \
 		module-oss-symdef.h \
 		module-oss-mmap-symdef.h \
 		module-alsa-sink-symdef.h \
-		module-alsa-source-symdef.h
+		module-alsa-source-symdef.h \
+		module-waveout-symdef.h
 
 EXTRA_DIST += $(SYMDEF_FILES)
 BUILT_SOURCES += $(SYMDEF_FILES)
@@ -974,6 +982,13 @@ module_mmkbd_evdev_la_LDFLAGS = -module -avoid-version
 module_mmkbd_evdev_la_LIBADD = $(AM_LIBADD)
 module_mmkbd_evdev_la_CFLAGS = $(AM_CFLAGS)
 
+# Windows waveout
+
+module_waveout_la_SOURCES = module-waveout.c
+module_waveout_la_LDFLAGS = -module -avoid-version
+module_waveout_la_LIBADD = $(AM_LIBADD) libpolypcore.la -lwinmm
+module_waveout_la_CFLAGS = $(AM_CFLAGS)
+
 ###################################
 #        Some minor stuff         #
 ###################################
@@ -990,8 +1005,13 @@ esdcompat.sh: esdcompat.sh.in Makefile
 client.conf: client.conf.in Makefile
 	sed -e 's, at POLYPAUDIO_BINARY\@,$(POLYPAUDIO_BINARY),g' < $< > $@
 
+if OS_IS_WIN32    
+default.pa: default.pa.win32
+	cp $< $@
+else
 default.pa: default.pa.in Makefile
 	sed -e 's, at POLYPAUDIO_BINARY\@,$(POLYPAUDIO_BINARY),g' < $< > $@
+endif
 
 daemon.conf: daemon.conf.in Makefile
 	sed -e 's, at DLSEARCHPATH\@,$(modlibdir),g' \
diff --git a/polyp/client-conf.c b/polyp/client-conf.c
index 4906383..04c3d2e 100644
--- a/polyp/client-conf.c
+++ b/polyp/client-conf.c
@@ -19,6 +19,10 @@
   USA.
 ***/
 
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
 #include <stdlib.h>
 #include <assert.h>
 #include <unistd.h>
@@ -33,11 +37,21 @@
 #include "authkey.h"
 
 #ifndef DEFAULT_CONFIG_DIR
-#define DEFAULT_CONFIG_DIR "/etc/polypaudio"
+# ifndef OS_IS_WIN32
+#  define DEFAULT_CONFIG_DIR "/etc/polypaudio"
+# else
+#  define DEFAULT_CONFIG_DIR "%POLYP_ROOT%"
+# endif
+#endif
+
+#ifndef OS_IS_WIN32
+# define PATH_SEP "/"
+#else
+# define PATH_SEP "\\"
 #endif
 
-#define DEFAULT_CLIENT_CONFIG_FILE DEFAULT_CONFIG_DIR"/client.conf"
-#define DEFAULT_CLIENT_CONFIG_FILE_USER ".polypaudio/client.conf"
+#define DEFAULT_CLIENT_CONFIG_FILE DEFAULT_CONFIG_DIR PATH_SEP "client.conf"
+#define DEFAULT_CLIENT_CONFIG_FILE_USER ".polypaudio" PATH_SEP "client.conf"
 
 #define ENV_CLIENT_CONFIG_FILE "POLYP_CLIENTCONFIG"
 #define ENV_DEFAULT_SINK "POLYP_SINK"
diff --git a/polyp/daemon-conf.c b/polyp/daemon-conf.c
index a6afd05..780581b 100644
--- a/polyp/daemon-conf.c
+++ b/polyp/daemon-conf.c
@@ -37,13 +37,23 @@
 #include "resampler.h"
 
 #ifndef DEFAULT_CONFIG_DIR
-#define DEFAULT_CONFIG_DIR "/etc/polypaudio"
+# ifndef OS_IS_WIN32
+#  define DEFAULT_CONFIG_DIR "/etc/polypaudio"
+# else
+#  define DEFAULT_CONFIG_DIR "%POLYP_ROOT%"
+# endif
 #endif
 
-#define DEFAULT_SCRIPT_FILE DEFAULT_CONFIG_DIR"/default.pa"
-#define DEFAULT_SCRIPT_FILE_USER ".polypaudio/default.pa"
-#define DEFAULT_CONFIG_FILE DEFAULT_CONFIG_DIR"/daemon.conf"
-#define DEFAULT_CONFIG_FILE_USER ".polypaudio/daemon.conf"
+#ifndef OS_IS_WIN32
+# define PATH_SEP "/"
+#else
+# define PATH_SEP "\\"
+#endif
+
+#define DEFAULT_SCRIPT_FILE DEFAULT_CONFIG_DIR PATH_SEP "default.pa"
+#define DEFAULT_SCRIPT_FILE_USER ".polypaudio" PATH_SEP "default.pa"
+#define DEFAULT_CONFIG_FILE DEFAULT_CONFIG_DIR PATH_SEP "daemon.conf"
+#define DEFAULT_CONFIG_FILE_USER ".polypaudio" PATH_SEP "daemon.conf"
 
 #define ENV_SCRIPT_FILE "POLYP_SCRIPT"
 #define ENV_CONFIG_FILE "POLYP_CONFIG"
diff --git a/polyp/default.pa.win32 b/polyp/default.pa.win32
new file mode 100644
index 0000000..3478ada
--- /dev/null
+++ b/polyp/default.pa.win32
@@ -0,0 +1,43 @@
+#
+# This file is part of polypaudio.
+#
+# polypaudio 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.
+#
+# polypaudio 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 polypaudio; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+
+
+# Load audio drivers statically
+
+load-module module-waveout sink_name=output source_name=input
+load-module module-null-sink
+
+# Load audio drivers automatically on access
+
+#add-autoload-sink output module-waveout sink_name=output source_name=input
+#add-autoload-source input module-waveout sink_name=output source_name=input
+
+# Load several protocols
+#load-module module-esound-protocol-tcp
+#load-module module-native-protocol-tcp
+#load-module module-simple-protocol-tcp
+#load-module module-cli-protocol-tcp
+
+# Make some devices default
+set-default-sink output
+set-default-source input
+
+.nofail
+
+# Load something to the sample cache
+load-sample x11-bell %WINDIR%\Media\ding.wav
+load-sample-dir-lazy %WINDIR%\Media\*.wav
diff --git a/polyp/dllmain.c b/polyp/dllmain.c
new file mode 100644
index 0000000..34d0eed
--- /dev/null
+++ b/polyp/dllmain.c
@@ -0,0 +1,46 @@
+/* $Id: dllmain.c 317 2004-12-11 00:10:41Z lennart $ */
+
+/***
+  This file is part of polypaudio.
+
+  polypaudio 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.
+
+  polypaudio 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 polypaudio; 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 OS_IS_WIN32
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <windows.h>
+
+extern pa_set_root(HANDLE handle);
+
+BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) {
+    if (fdwReason != DLL_PROCESS_ATTACH)
+        return TRUE;
+
+    if (!pa_set_root(hinstDLL))
+        return FALSE;
+
+    return TRUE;
+}
+
+#endif /* OS_IS_WIN32 */
diff --git a/polyp/iochannel.c b/polyp/iochannel.c
index 0e7e8db..08a4e36 100644
--- a/polyp/iochannel.c
+++ b/polyp/iochannel.c
@@ -28,6 +28,10 @@
 #include <fcntl.h>
 #include <unistd.h>
 
+#ifdef HAVE_WINSOCK2_H
+#include <winsock2.h>
+#endif
+
 #include "iochannel.h"
 #include "util.h"
 #include "socket-util.h"
@@ -189,7 +193,19 @@ ssize_t pa_iochannel_write(struct pa_iochannel*io, const void*data, size_t l) {
     ssize_t r;
     assert(io && data && l && io->ofd >= 0);
 
-    if ((r = write(io->ofd, data, l)) >= 0) {
+#ifdef OS_IS_WIN32
+    r = send(io->ofd, data, l, 0);
+    if (r < 0) {
+        if (WSAGetLastError() != WSAENOTSOCK) {
+            errno = WSAGetLastError();
+            return r;
+        }
+    }
+
+    if (r < 0)
+#endif
+        r = write(io->ofd, data, l);
+    if (r >= 0) {
         io->writable = 0;
         enable_mainloop_sources(io);
     }
@@ -201,7 +217,19 @@ ssize_t pa_iochannel_read(struct pa_iochannel*io, void*data, size_t l) {
     ssize_t r;
     assert(io && data && io->ifd >= 0);
     
-    if ((r = read(io->ifd, data, l)) >= 0) {
+#ifdef OS_IS_WIN32
+    r = recv(io->ifd, data, l, 0);
+    if (r < 0) {
+        if (WSAGetLastError() != WSAENOTSOCK) {
+            errno = WSAGetLastError();
+            return r;
+        }
+    }
+
+    if (r < 0)
+#endif
+        r = read(io->ifd, data, l);
+    if (r >= 0) {
         io->readable = 0;
         enable_mainloop_sources(io);
     }
diff --git a/polyp/main.c b/polyp/main.c
index 3f9f359..437f0a4 100644
--- a/polyp/main.c
+++ b/polyp/main.c
@@ -35,7 +35,16 @@
 #include <memblock.h>
 #include <limits.h>
 #include <fcntl.h>
+#include <unistd.h>
+#include <sys/types.h>
+
+#ifdef HAVE_SYS_IOCTL_H
 #include <sys/ioctl.h>
+#endif
+
+#ifdef HAVE_WINSOCK2_H
+#include <winsock2.h>
+#endif
 
 #ifdef HAVE_LIBWRAP
 #include <syslog.h>
@@ -66,6 +75,23 @@ int allow_severity = LOG_INFO;
 int deny_severity = LOG_WARNING;
 #endif
 
+#ifdef OS_IS_WIN32
+
+static void message_cb(struct pa_mainloop_api*a, struct pa_defer_event *e, void *userdata) {
+    MSG msg;
+
+    while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
+        if (msg.message == WM_QUIT)
+            raise(SIGTERM);
+        else {
+            TranslateMessage(&msg);
+            DispatchMessage(&msg);
+        }
+    }
+}
+
+#endif
+
 static void signal_callback(struct pa_mainloop_api*m, struct pa_signal_event *e, int sig, void *userdata) {
     pa_log_info(__FILE__": Got signal %s.\n", pa_strsignal(sig));
 
@@ -124,6 +150,10 @@ int main(int argc, char *argv[]) {
     gid_t gid = (gid_t) -1;
 #endif
 
+#ifdef OS_IS_WIN32
+    struct pa_defer_event *defer;
+#endif
+
     pa_limit_caps();
 
 #ifdef HAVE_GETUID
@@ -142,6 +172,13 @@ int main(int argc, char *argv[]) {
     r = lt_dlinit();
     assert(r == 0);
 
+#ifdef OS_IS_WIN32
+    {
+        WSADATA data;
+        WSAStartup(MAKEWORD(2, 0), &data);
+    }
+#endif
+
     pa_log_set_ident("polypaudio");
     
     conf = pa_daemon_conf_new();
@@ -230,6 +267,7 @@ int main(int argc, char *argv[]) {
             goto finish;
         }
 
+#ifdef HAVE_FORK
         if (pipe(daemon_pipe) < 0) {
             pa_log(__FILE__": failed to create pipe.\n");
             goto finish;
@@ -261,6 +299,7 @@ int main(int argc, char *argv[]) {
 
         close(daemon_pipe[0]);
         daemon_pipe[0] = -1;
+#endif
 
         if (conf->auto_log_target)
             pa_log_set_target(PA_LOG_SYSLOG, NULL);
@@ -271,7 +310,8 @@ int main(int argc, char *argv[]) {
 #ifdef HAVE_SETPGID
         setpgid(0,0);
 #endif
-        
+
+#ifndef OS_IS_WIN32
         close(0);
         close(1);
         close(2);
@@ -279,7 +319,10 @@ int main(int argc, char *argv[]) {
         open("/dev/null", O_RDONLY);
         open("/dev/null", O_WRONLY);
         open("/dev/null", O_WRONLY);
-        
+#else
+        FreeConsole();
+#endif
+
 #ifdef SIGTTOU
         signal(SIGTTOU, SIG_IGN);
 #endif
@@ -290,18 +333,23 @@ int main(int argc, char *argv[]) {
         signal(SIGTSTP, SIG_IGN);
 #endif
         
+#ifdef TIOCNOTTY
         if ((tty_fd = open("/dev/tty", O_RDWR)) >= 0) {
             ioctl(tty_fd, TIOCNOTTY, (char*) 0);
             close(tty_fd);
         }
+#endif
     }
 
     chdir("/");
     
     if (conf->use_pid_file) {
         if (pa_pid_file_create() < 0) {
+            pa_log(__FILE__": pa_pid_file_create() failed.\n");
+#ifdef HAVE_FORK
             if (conf->daemonize)
                 pa_loop_write(daemon_pipe[1], &retval, sizeof(retval));
+#endif
             goto finish;
         }
 
@@ -322,9 +370,14 @@ int main(int argc, char *argv[]) {
     signal(SIGPIPE, SIG_IGN);
 #endif
 
+#ifdef OS_IS_WIN32
+    defer = pa_mainloop_get_api(mainloop)->defer_new(pa_mainloop_get_api(mainloop), message_cb, NULL);
+    assert(defer);
+#endif
+
     if (conf->daemonize)
         c->running_as_daemon = 1;
-    
+
 #ifdef SIGUSR1
     pa_signal_new(SIGUSR1, signal_callback, c);
 #endif
@@ -350,17 +403,23 @@ int main(int argc, char *argv[]) {
     
     if (r < 0 && conf->fail) {
         pa_log(__FILE__": failed to initialize daemon.\n");
+#ifdef HAVE_FORK
         if (conf->daemonize)
             pa_loop_write(daemon_pipe[1], &retval, sizeof(retval));
+#endif
     } else if (!c->modules || pa_idxset_ncontents(c->modules) == 0) {
         pa_log(__FILE__": daemon startup without any loaded modules, refusing to work.\n");
+#ifdef HAVE_FORK
         if (conf->daemonize)
             pa_loop_write(daemon_pipe[1], &retval, sizeof(retval));
+#endif
     } else {
 
         retval = 0;
+#ifdef HAVE_FORK
         if (conf->daemonize)
             pa_loop_write(daemon_pipe[1], &retval, sizeof(retval));
+#endif
 
         c->disallow_module_loading = conf->disallow_module_loading;
         c->exit_idle_time = conf->exit_idle_time;
@@ -378,7 +437,11 @@ int main(int argc, char *argv[]) {
             pa_log_info(__FILE__": Daemon shutdown initiated.\n");
         }
     }
-        
+
+#ifdef OS_IS_WIN32
+    pa_mainloop_get_api(mainloop)->defer_free(defer);
+#endif
+
     pa_core_free(c);
 
     pa_cpu_limit_done();
@@ -397,6 +460,10 @@ finish:
     
     close_pipe(daemon_pipe);
 
+#ifdef OS_IS_WIN32
+    WSACleanup();
+#endif
+
     lt_dlexit();
     
     return retval;
diff --git a/polyp/mainloop-signal.c b/polyp/mainloop-signal.c
index eb3f5dd..432498a 100644
--- a/polyp/mainloop-signal.c
+++ b/polyp/mainloop-signal.c
@@ -32,6 +32,10 @@
 #include <unistd.h>
 #include <fcntl.h>
 
+#ifdef HAVE_WINDOWS_H
+#include <windows.h>
+#endif
+
 #include "mainloop-signal.h"
 #include "util.h"
 #include "xmalloc.h"
@@ -53,19 +57,70 @@ struct pa_signal_event {
 static struct pa_mainloop_api *api = NULL;
 static int signal_pipe[2] = { -1, -1 };
 static struct pa_io_event* io_event = NULL;
+static struct pa_defer_event *defer_event = NULL;
 static struct pa_signal_event *signals = NULL;
 
+#ifdef OS_IS_WIN32
+static unsigned int waiting_signals = 0;
+static CRITICAL_SECTION crit;
+#endif
+
 static void signal_handler(int sig) {
 #ifndef HAVE_SIGACTION
     signal(sig, signal_handler);
 #endif
     write(signal_pipe[1], &sig, sizeof(sig));
+
+#ifdef OS_IS_WIN32
+    EnterCriticalSection(&crit);
+    waiting_signals++;
+    LeaveCriticalSection(&crit);
+#endif
+}
+
+static void dispatch(struct pa_mainloop_api*a, int sig) {
+    struct pa_signal_event*s;
+
+    for (s = signals; s; s = s->next) 
+        if (s->sig == sig) {
+            assert(s->callback);
+            s->callback(a, s, sig, s->userdata);
+            break;
+        }
+}
+
+static void defer(struct pa_mainloop_api*a, struct pa_defer_event*e, void *userdata) {
+    ssize_t r;
+    int sig;
+    unsigned int sigs;
+
+#ifdef OS_IS_WIN32
+    EnterCriticalSection(&crit);
+    sigs = waiting_signals;
+    waiting_signals = 0;
+    LeaveCriticalSection(&crit);
+#endif
+
+    while (sigs) {
+        if ((r = read(signal_pipe[0], &sig, sizeof(sig))) < 0) {
+            pa_log(__FILE__": read(): %s\n", strerror(errno));
+            return;
+        }
+        
+        if (r != sizeof(sig)) {
+            pa_log(__FILE__": short read()\n");
+            return;
+        }
+
+        dispatch(a, sig);
+
+        sigs--;
+    }
 }
 
 static void callback(struct pa_mainloop_api*a, struct pa_io_event*e, int fd, enum pa_io_event_flags f, void *userdata) {
     ssize_t r;
     int sig;
-    struct pa_signal_event*s;
     assert(a && e && f == PA_IO_EVENT_INPUT && e == io_event && fd == signal_pipe[0]);
 
         
@@ -81,19 +136,18 @@ static void callback(struct pa_mainloop_api*a, struct pa_io_event*e, int fd, enu
         pa_log(__FILE__": short read()\n");
         return;
     }
-    
-    for (s = signals; s; s = s->next) 
-        if (s->sig == sig) {
-            assert(s->callback);
-            s->callback(a, s, sig, s->userdata);
-            break;
-        }
+
+    dispatch(a, sig);
 }
 
 int pa_signal_init(struct pa_mainloop_api *a) {
-    assert(!api && a && signal_pipe[0] == -1 && signal_pipe[1] == -1 && !io_event);
-    
+    assert(!api && a && signal_pipe[0] == -1 && signal_pipe[1] == -1 && !io_event && !defer_event);
+
+#ifdef OS_IS_WIN32
+    if (_pipe(signal_pipe, 200, _O_BINARY) < 0) {
+#else
     if (pipe(signal_pipe) < 0) {
+#endif
         pa_log(__FILE__": pipe() failed: %s\n", strerror(errno));
         return -1;
     }
@@ -104,20 +158,36 @@ int pa_signal_init(struct pa_mainloop_api *a) {
     pa_fd_set_cloexec(signal_pipe[1], 1);
 
     api = a;
+
+#ifndef OS_IS_WIN32
     io_event = api->io_new(api, signal_pipe[0], PA_IO_EVENT_INPUT, callback, NULL);
     assert(io_event);
+#else
+    defer_event = api->defer_new(api, defer, NULL);
+    assert(defer_event);
+
+    InitializeCriticalSection(&crit);
+#endif
+
     return 0;
 }
 
 void pa_signal_done(void) {
-    assert(api && signal_pipe[0] >= 0 && signal_pipe[1] >= 0 && io_event);
+    assert(api && signal_pipe[0] >= 0 && signal_pipe[1] >= 0 && (io_event || defer_event));
 
     while (signals)
         pa_signal_free(signals);
 
 
+#ifndef OS_IS_WIN32
     api->io_free(io_event);
     io_event = NULL;
+#else
+    api->defer_free(defer_event);
+    defer_event = NULL;
+
+    DeleteCriticalSection(&crit);
+#endif
 
     close(signal_pipe[0]);
     close(signal_pipe[1]);
diff --git a/polyp/mainloop.c b/polyp/mainloop.c
index 90243bd..9cfd539 100644
--- a/polyp/mainloop.c
+++ b/polyp/mainloop.c
@@ -38,6 +38,10 @@
 #include "poll.h"
 #endif
 
+#ifdef HAVE_WINSOCK2_H
+#include <winsock2.h>
+#endif
+
 #include "mainloop.h"
 #include "util.h"
 #include "idxset.h"
@@ -108,6 +112,26 @@ static struct pa_io_event* mainloop_io_new(struct pa_mainloop_api*a, int fd, enu
     e->destroy_callback = NULL;
     e->pollfd = NULL;
 
+#ifdef OS_IS_WIN32
+    {
+        fd_set xset;
+        struct timeval tv;
+
+        tv.tv_sec = 0;
+        tv.tv_usec = 0;
+
+        FD_ZERO (&xset);
+        FD_SET (fd, &xset);
+
+        if ((select((SELECT_TYPE_ARG1) fd, NULL, NULL, SELECT_TYPE_ARG234 &xset,
+                    SELECT_TYPE_ARG5 &tv) == -1) &&
+             (WSAGetLastError() == WSAENOTSOCK)) {
+            pa_log_warn(__FILE__": WARNING: cannot monitor non-socket file descriptors.\n");
+            e->dead = 1;
+        }
+    }
+#endif
+
     pa_idxset_put(m->io_events, e, NULL);
     m->rebuild_pollfds = 1;
     return e;
diff --git a/polyp/module-protocol-stub.c b/polyp/module-protocol-stub.c
index 7cd5ed3..8c06a61 100644
--- a/polyp/module-protocol-stub.c
+++ b/polyp/module-protocol-stub.c
@@ -40,6 +40,13 @@
 #include <netinet/in.h>
 #endif
 
+#ifdef HAVE_WINSOCK2_H
+#include <winsock2.h>
+#endif
+#ifdef HAVE_WS2TCPIP_H
+#include <ws2tcpip.h>
+#endif
+
 #include "module.h"
 #include "socket-server.h"
 #include "socket-util.h"
diff --git a/polyp/pid.c b/polyp/pid.c
index 2fac687..ae3dc7f 100644
--- a/polyp/pid.c
+++ b/polyp/pid.c
@@ -35,6 +35,10 @@
 #include <limits.h>
 #include <signal.h>
 
+#ifdef HAVE_WINDOWS_H
+#include <windows.h>
+#endif
+
 #include "pid.h"
 #include "util.h"
 #include "log.h"
@@ -130,6 +134,10 @@ int pa_pid_file_create(void) {
     pid_t pid;
     size_t l;
 
+#ifdef OS_IS_WIN32
+    HANDLE process;
+#endif
+
     pa_runtime_path("pid", fn, sizeof(fn));
 
     if ((fd = open_pid_file(fn, O_CREAT|O_RDWR)) < 0)
@@ -138,7 +146,12 @@ int pa_pid_file_create(void) {
     if ((pid = read_pid(fn, fd)) == (pid_t) -1)
         pa_log(__FILE__": corrupt PID file, overwriting.\n");
     else if (pid > 0) {
+#ifdef OS_IS_WIN32
+        if ((process = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid)) != NULL) {
+            CloseHandle(process);
+#else
         if (kill(pid, 0) >= 0 || errno != ESRCH) {
+#endif
             pa_log(__FILE__": daemon already running.\n");
             goto fail;
         }
@@ -198,6 +211,12 @@ int pa_pid_file_remove(void) {
         goto fail;
     }
 
+#ifdef OS_IS_WIN32
+    pa_lock_fd(fd, 0);
+    close(fd);
+    fd = -1;
+#endif
+
     if (unlink(fn) < 0) {
         pa_log(__FILE__": failed to remove PID file '%s': %s\n", fn, strerror(errno));
         goto fail;
@@ -223,6 +242,8 @@ int pa_pid_file_check_running(pid_t *pid) {
     return pa_pid_file_kill(0, pid);
 }
 
+#ifndef OS_IS_WIN32
+
 /* Kill a current running daemon. Return non-zero on success, -1
  * otherwise. If successful *pid contains the PID of the daemon
  * process. */
@@ -242,7 +263,7 @@ int pa_pid_file_kill(int sig, pid_t *pid) {
     
     if ((*pid = read_pid(fn, fd)) == (pid_t) -1)
         goto fail;
-    
+
     ret = kill(*pid, sig);
     
 fail:
@@ -255,3 +276,11 @@ fail:
     return ret;
     
 }
+
+#else /* OS_IS_WIN32 */
+
+int pa_pid_file_kill(int sig, pid_t *pid) {
+    return -1;
+}
+
+#endif
diff --git a/polyp/poll.c b/polyp/poll.c
index 82ea3d8..7c25f34 100644
--- a/polyp/poll.c
+++ b/polyp/poll.c
@@ -36,6 +36,17 @@
 #include <sys/select.h>
 #endif
 
+#ifdef HAVE_WINSOCK2_H
+#include <winsock2.h>
+
+#define EBADF           WSAEBADF
+#define ESHUTDOWN       WSAESHUTDOWN
+#define ECONNRESET      WSAECONNRESET
+#define ECONNABORTED    WSAECONNABORTED
+#define ENETRESET       WSAENETRESET
+
+#endif /* HAVE_WINSOCK2_H */
+
 #ifndef HAVE_SYS_POLL_H
 
 #include "util.h"
@@ -59,7 +70,16 @@ int poll (struct pollfd *fds, unsigned long int nfds, int timeout) {
             return 0;
         }
 
+#ifdef OS_IS_WIN32
+        /*
+         * Windows does not support signals properly so waiting for them would
+         * mean a deadlock.
+         */
+        pa_msleep(100);
+        return 0;
+#else
         return select(0, NULL, NULL, NULL, NULL);
+#endif
     }
 
     for (f = fds; f < &fds[nfds]; ++f) {
@@ -138,6 +158,10 @@ int poll (struct pollfd *fds, unsigned long int nfds, int timeout) {
         }
     }
 
+#ifdef OS_IS_WIN32
+    errno = WSAGetLastError();
+#endif
+
     if (ready > 0) {
         ready = 0;
         for (f = fds; f < &fds[nfds]; ++f) {
diff --git a/polyp/polyplib-context.c b/polyp/polyplib-context.c
index 1b9d7de..da91995 100644
--- a/polyp/polyplib-context.c
+++ b/polyp/polyplib-context.c
@@ -32,6 +32,7 @@
 #include <sys/stat.h>
 #include <errno.h>
 #include <signal.h>
+#include <limits.h>
 
 #ifdef HAVE_SYS_WAIT_H
 #include <sys/wait.h>
@@ -44,6 +45,13 @@
 #include <netdb.h>
 #endif
 
+#ifdef HAVE_WINSOCK2_H
+#include <winsock2.h>
+#define ETIMEDOUT       WSAETIMEDOUT
+#define ECONNREFUSED    WSAECONNREFUSED
+#define EHOSTUNREACH    WSAEHOSTUNREACH
+#endif
+
 #include "polyplib-internal.h"
 #include "polyplib-context.h"
 #include "native-common.h"
@@ -382,6 +390,8 @@ finish:
 
 static void on_connection(struct pa_socket_client *client, struct pa_iochannel*io, void *userdata);
 
+#ifndef OS_IS_WIN32
+
 static int context_connect_spawn(struct pa_context *c) {
     pid_t pid;
     int status, r;
@@ -495,6 +505,8 @@ fail:
     return -1;
 }
 
+#endif /* OS_IS_WIN32 */
+
 static int try_next_connection(struct pa_context *c) {
     char *u = NULL;
     int r = -1;
@@ -509,10 +521,12 @@ static int try_next_connection(struct pa_context *c) {
         
         if (!u) {
 
+#ifndef OS_IS_WIN32
             if (c->do_autospawn) {
                 r = context_connect_spawn(c);
                 goto finish;
             }
+#endif
             
             pa_context_fail(c, PA_ERROR_CONNECTIONREFUSED);
             goto finish;
diff --git a/polyp/pstream.c b/polyp/pstream.c
index a64856d..607b0c1 100644
--- a/polyp/pstream.c
+++ b/polyp/pstream.c
@@ -32,6 +32,10 @@
 #include <netinet/in.h>
 #endif
 
+#ifdef HAVE_WINSOCK2_H
+#include <winsock2.h>
+#endif
+
 #include "pstream.h"
 #include "queue.h"
 #include "xmalloc.h"
diff --git a/polyp/random.c b/polyp/random.c
index 456954a..12f27bf 100644
--- a/polyp/random.c
+++ b/polyp/random.c
@@ -19,6 +19,10 @@
   USA.
 ***/
 
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
 #include <fcntl.h>
 #include <unistd.h>
 #include <errno.h>
@@ -31,13 +35,16 @@
 #include "util.h"
 #include "log.h"
 
+#ifndef OS_IS_WIN32
 #define RANDOM_DEVICE "/dev/urandom"
+#endif
 
 void pa_random(void *ret_data, size_t length) {
     int fd;
     ssize_t r = 0;
     assert(ret_data && length);
-    
+
+#ifdef RANDOM_DEVICE
     if ((fd = open(RANDOM_DEVICE, O_RDONLY)) >= 0) {
 
         if ((r = pa_loop_read(fd, ret_data, length)) < 0 || (size_t) r != length)
@@ -45,17 +52,20 @@ void pa_random(void *ret_data, size_t length) {
 
         close(fd);
     }
+#endif
 
     if ((size_t) r != length) {
         uint8_t *p;
         size_t l;
-        
+
+#ifdef RANDOM_DEVICE        
         pa_log_warn(__FILE__": WARNING: Failed to open entropy device '"RANDOM_DEVICE"': %s"
                     ", falling back to unsecure pseudo RNG.\n", strerror(errno));
+#endif
 
-        srandom(time(NULL));
+        srand(time(NULL));
         
         for (p = ret_data, l = length; l > 0; p++, l--)
-            *p = (uint8_t) random();
+            *p = (uint8_t) rand();
     }
 }
diff --git a/polyp/scache.c b/polyp/scache.c
index 0dec33c..2953145 100644
--- a/polyp/scache.c
+++ b/polyp/scache.c
@@ -37,6 +37,10 @@
 #include <glob.h>
 #endif
 
+#ifdef HAVE_WINDOWS_H
+#include <windows.h>
+#endif
+
 #include "scache.h"
 #include "sink-input.h"
 #include "mainloop.h"
@@ -147,6 +151,13 @@ int pa_scache_add_file(struct pa_core *c, const char *name, const char *filename
     struct pa_memchunk chunk;
     int r;
 
+#ifdef OS_IS_WIN32
+    char buf[MAX_PATH];
+
+    if (ExpandEnvironmentStrings(filename, buf, MAX_PATH))
+        filename = buf;
+#endif
+
     if (pa_sound_file_load(filename, &ss, &chunk, c->memblock_stat) < 0)
         return -1;
         
@@ -158,6 +169,14 @@ int pa_scache_add_file(struct pa_core *c, const char *name, const char *filename
 
 int pa_scache_add_file_lazy(struct pa_core *c, const char *name, const char *filename, uint32_t *index) {
     struct pa_scache_entry *e;
+
+#ifdef OS_IS_WIN32
+    char buf[MAX_PATH];
+
+    if (ExpandEnvironmentStrings(filename, buf, MAX_PATH))
+        filename = buf;
+#endif
+
     assert(c && name);
 
     if (!(e = scache_add_item(c, name)))
@@ -313,7 +332,9 @@ static void add_file(struct pa_core *c, const char *pathname) {
         return;
     }
 
+#if defined(S_ISREG) && defined(S_ISLNK)
     if (S_ISREG(st.st_mode) || S_ISLNK(st.st_mode))
+#endif
         pa_scache_add_file_lazy(c, e, pathname, NULL);
 }
 
diff --git a/polyp/socket-client.c b/polyp/socket-client.c
index 0d712fa..6d8cb2a 100644
--- a/polyp/socket-client.c
+++ b/polyp/socket-client.c
@@ -48,6 +48,15 @@
 #include <netdb.h>
 #endif
 
+#ifdef HAVE_WINSOCK2_H
+#include <winsock2.h>
+#define EINPROGRESS     WSAEINPROGRESS
+#define ETIMEDOUT       WSAETIMEDOUT
+#endif
+#ifdef HAVE_WS2TCPIP_H
+#include <ws2tcpip.h>
+#endif
+
 #ifdef HAVE_LIBASYNCNS
 #include <asyncns.h>
 #endif
diff --git a/polyp/socket-server.c b/polyp/socket-server.c
index 0cca4ae..b7e4fed 100644
--- a/polyp/socket-server.c
+++ b/polyp/socket-server.c
@@ -44,6 +44,13 @@
 #include <netinet/in.h>
 #endif
 
+#ifdef HAVE_WINSOCK2_H
+#include <winsock2.h>
+#endif
+#ifdef HAVE_WS2TCPIP_H
+#include <ws2tcpip.h>
+#endif
+
 #ifdef HAVE_LIBWRAP
 #include <tcpd.h>
 #endif
diff --git a/polyp/socket-util.c b/polyp/socket-util.c
index 60f8d16..699b28c 100644
--- a/polyp/socket-util.c
+++ b/polyp/socket-util.c
@@ -57,6 +57,11 @@
 #include <netdb.h>
 #endif
 
+#ifdef HAVE_WINSOCK2_H
+#include <winsock2.h>
+#define ETIMEDOUT       WSAETIMEDOUT
+#endif
+
 #include "socket-util.h"
 #include "util.h"
 #include "xmalloc.h"
@@ -72,6 +77,7 @@ void pa_socket_peer_to_string(int fd, char *c, size_t l) {
         return;
     }
 
+#ifndef OS_IS_WIN32
     if (S_ISSOCK(st.st_mode)) {
         union {
             struct sockaddr sa;
@@ -104,6 +110,7 @@ void pa_socket_peer_to_string(int fd, char *c, size_t l) {
         snprintf(c, l, "STDIN/STDOUT client");
         return;
     }
+#endif /* OS_IS_WIN32 */
 
     snprintf(c, l, "Unknown client");
 }
diff --git a/polyp/tagstruct.c b/polyp/tagstruct.c
index a3bd7d9..59178bf 100644
--- a/polyp/tagstruct.c
+++ b/polyp/tagstruct.c
@@ -33,6 +33,10 @@
 #include <netinet/in.h>
 #endif
 
+#ifdef HAVE_WINSOCK2_H
+#include <winsock2.h>
+#endif
+
 #include "tagstruct.h"
 #include "xmalloc.h"
 
diff --git a/polyp/util.c b/polyp/util.c
index acfa031..0495896 100644
--- a/polyp/util.c
+++ b/polyp/util.c
@@ -32,12 +32,12 @@
 #include <stdio.h>
 #include <fcntl.h>
 #include <unistd.h>
+#include <limits.h>
+#include <time.h>
+#include <ctype.h>
 #include <sys/types.h>
 #include <sys/stat.h>
-#include <signal.h>
 #include <sys/time.h>
-#include <limits.h>
-#include <unistd.h>
 
 #ifdef HAVE_SCHED_H
 #include <sched.h>
@@ -55,6 +55,17 @@
 #include <netdb.h>
 #endif
 
+#ifdef HAVE_WINDOWS_H
+#include <windows.h>
+#endif
+
+#ifdef HAVE_WINSOCK2_H
+#include <winsock2.h>
+#endif
+#ifdef HAVE_WS2TCPIP_H
+#include <ws2tcpip.h>
+#endif
+
 #include <samplerate.h>
 
 #ifdef HAVE_PWD_H
@@ -68,16 +79,56 @@
 #include "xmalloc.h"
 #include "log.h"
 
+#ifndef OS_IS_WIN32
 #define PA_RUNTIME_PATH_PREFIX "/tmp/polypaudio-"
+#define PATH_SEP '/'
+#else
+#define PA_RUNTIME_PATH_PREFIX "%TEMP%\\polypaudio-"
+#define PATH_SEP '\\'
+#endif
+
+#ifdef OS_IS_WIN32
+
+#define POLYP_ROOTENV "POLYP_ROOT"
+
+int pa_set_root(HANDLE handle) {
+    char library_path[MAX_PATH + sizeof(POLYP_ROOTENV) + 1], *sep;
+
+    strcpy(library_path, POLYP_ROOTENV "=");
+
+    if (!GetModuleFileName(handle, library_path + sizeof(POLYP_ROOTENV), MAX_PATH))
+        return 0;
+
+    sep = strrchr(library_path, '\\');
+    if (sep)
+        *sep = '\0';
+
+    if (_putenv(library_path) < 0)
+        return 0;
+
+    return 1;
+}
+
+#endif
 
 /** Make a file descriptor nonblock. Doesn't do any error checking */
 void pa_make_nonblock_fd(int fd) {
+#ifdef O_NONBLOCK
     int v;
     assert(fd >= 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(__FILE__": WARNING: Only sockets can be made non-blocking!\n");
+    }
+#else
+    pa_log_warn(__FILE__": WARNING: Non-blocking I/O not supported.!\n");
+#endif
 }
 
 /** Creates a directory securely */
@@ -85,15 +136,27 @@ int pa_make_secure_dir(const char* dir) {
     struct stat st;
     assert(dir);
 
-    if (mkdir(dir, 0700) < 0) 
+#ifdef OS_IS_WIN32
+    if (mkdir(dir) < 0)
+#else
+    if (mkdir(dir, 0700) < 0)
+#endif
         if (errno != EEXIST)
             return -1;
-    
-    if (lstat(dir, &st) < 0) 
+
+#ifdef OS_IS_WIN32
+    if (stat(dir, &st) < 0)
+#else
+    if (lstat(dir, &st) < 0)
+#endif
         goto fail;
-    
+
+#ifndef OS_IS_WIN32
     if (!S_ISDIR(st.st_mode) || (st.st_uid != getuid()) || ((st.st_mode & 0777) != 0700))
         goto fail;
+#else
+    fprintf(stderr, "FIXME: pa_make_secure_dir()\n");
+#endif
     
     return 0;
     
@@ -106,10 +169,11 @@ fail:
 int pa_make_secure_parent_dir(const char *fn) {
     int ret = -1;
     char *slash, *dir = pa_xstrdup(fn);
-    
-    if (!(slash = strrchr(dir, '/')))
+
+    slash = pa_path_get_filename(dir);
+    if (slash == fn)
         goto finish;
-    *slash = 0;
+    *(slash-1) = 0;
     
     if (pa_make_secure_dir(dir) < 0)
         goto finish;
@@ -285,6 +349,15 @@ char *pa_get_user_name(char *s, size_t l) {
         }
         
         p = r->pw_name;
+
+#elif defined(OS_IS_WIN32) /* HAVE_PWD_H */
+        DWORD size = sizeof(buf);
+
+        if (!GetUserName(buf, &size))
+            return NULL;
+
+        p = buf;
+
 #else /* HAVE_PWD_H */
         return NULL;
 #endif /* HAVE_PWD_H */
@@ -318,6 +391,9 @@ char *pa_get_home_dir(char *s, size_t l) {
     if ((e = getenv("HOME")))
         return pa_strlcpy(s, e, l);
 
+    if ((e = getenv("USERPROFILE")))
+        return pa_strlcpy(s, e, l);
+
 #ifdef HAVE_PWD_H
 #ifdef HAVE_GETPWUID_R
     if (getpwuid_r(getuid(), &pw, buf, sizeof(buf), &r) != 0 || !r) {
@@ -349,6 +425,34 @@ char *pa_strlcpy(char *b, const char *s, size_t l) {
 int pa_gettimeofday(struct timeval *tv) {
 #ifdef HAVE_GETTIMEOFDAY
     return gettimeofday(tv, NULL);
+#elif defined(OS_IS_WIN32)
+    /*
+     * Copied from implementation by Steven Edwards (LGPL).
+     * Found on wine mailing list.
+     */
+
+#if defined(_MSC_VER) || defined(__BORLANDC__)
+#define EPOCHFILETIME (116444736000000000i64)
+#else
+#define EPOCHFILETIME (116444736000000000LL)
+#endif
+
+    FILETIME        ft;
+    LARGE_INTEGER   li;
+    __int64         t;
+
+    if (tv) {
+        GetSystemTimeAsFileTime(&ft);
+        li.LowPart  = ft.dwLowDateTime;
+        li.HighPart = ft.dwHighDateTime;
+        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);
+    }
+
+    return 0;
 #else
 #error "Platform lacks gettimeofday() or equivalent function."
 #endif
@@ -432,10 +536,12 @@ sensible: set the nice level to -15 and enable realtime scheduling if
 supported.*/
 void pa_raise_priority(void) {
 
+#ifdef HAVE_SYS_RESOURCE_H
     if (setpriority(PRIO_PROCESS, 0, NICE_LEVEL) < 0)
         pa_log_warn(__FILE__": setpriority() failed: %s\n", strerror(errno));
     else 
         pa_log_info(__FILE__": Successfully gained nice level %i.\n", NICE_LEVEL); 
+#endif
     
 #ifdef _POSIX_PRIORITY_SCHEDULING
     {
@@ -455,10 +561,21 @@ void pa_raise_priority(void) {
         pa_log_info(__FILE__": Successfully enabled SCHED_FIFO scheduling.\n"); 
     }
 #endif
+
+#ifdef OS_IS_WIN32
+    if (!SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS))
+        pa_log_warn(__FILE__": SetPriorityClass() failed: 0x%08X\n", GetLastError());
+    else
+        pa_log_info(__FILE__": Successfully gained high priority class.\n"); 
+#endif
 }
 
 /* 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;
@@ -468,11 +585,15 @@ void pa_reset_priority(void) {
     }
 #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);
 
@@ -483,7 +604,8 @@ int pa_fd_set_cloexec(int fd, int b) {
     
     if (fcntl(fd, F_SETFD, v) < 0)
         return -1;
-    
+#endif    
+
     return 0;
 }
 
@@ -491,6 +613,8 @@ int pa_fd_set_cloexec(int fd, int b) {
  * only. This shoul be used for eyecandy only, don't rely on return
  * non-NULL! */
 char *pa_get_binary_name(char *s, size_t l) {
+
+#ifdef HAVE_READLINK
     char path[PATH_MAX];
     int i;
     assert(s && l);
@@ -503,6 +627,15 @@ char *pa_get_binary_name(char *s, size_t l) {
 
     s[i] = 0;
     return s;
+#elif defined(OS_IS_WIN32)
+    char path[PATH_MAX];
+    if (!GetModuleFileName(NULL, path, PATH_MAX))
+        return NULL;
+    pa_strlcpy(s, pa_path_get_filename(path), l);
+    return s;
+#else
+    return NULL;
+#endif
 }
 
 /* Return a pointer to the filename inside a path (which is the last
@@ -510,7 +643,7 @@ char *pa_get_binary_name(char *s, size_t l) {
 char *pa_path_get_filename(const char *p) {
     char *fn;
 
-    if ((fn = strrchr(p, '/')))
+    if ((fn = strrchr(p, PATH_SEP)))
         return fn+1;
 
     return (char*) p;
@@ -684,6 +817,7 @@ int pa_uid_in_group(const char *name, gid_t *gid) {
 
 /* Lock or unlock a file entirely. (advisory) */
 int pa_lock_fd(int fd, int b) {
+#ifdef F_SETLKW
     struct flock flock;
 
     /* Try a R/W lock first */
@@ -704,6 +838,19 @@ int pa_lock_fd(int fd, int b) {
     }
         
     pa_log(__FILE__": %slock failed: %s\n", !b ? "un" : "", strerror(errno));
+#endif
+
+#ifdef OS_IS_WIN32
+    HANDLE h = (HANDLE)_get_osfhandle(fd);
+
+    if (b && LockFile(h, 0, 0, 0xFFFFFFFF, 0xFFFFFFFF))
+        return 0;
+    if (!b && UnlockFile(h, 0, 0, 0xFFFFFFFF, 0xFFFFFFFF))
+        return 0;
+
+    pa_log(__FILE__": %slock failed: 0x%08X\n", !b ? "un" : "", GetLastError());
+#endif
+
     return -1;
 }
 
@@ -795,31 +942,51 @@ int pa_unlock_lockfile(const char *fn, int fd) {
  * allocated buffer containing the used configuration file is
  * stored there.*/
 FILE *pa_open_config_file(const char *global, const char *local, const char *env, char **result) {
-    const char *e;
+    const char *fn;
     char h[PATH_MAX];
 
-    if (env && (e = getenv(env))) {
+#ifdef OS_IS_WIN32
+    char buf[PATH_MAX];
+
+    if (!getenv(POLYP_ROOTENV))
+        pa_set_root(NULL);
+#endif
+
+    if (env && (fn = getenv(env))) {
+#ifdef OS_IS_WIN32
+        if (!ExpandEnvironmentStrings(fn, buf, PATH_MAX))
+            return NULL;
+        fn = buf;
+#endif
+
         if (result)
-            *result = pa_xstrdup(e);
-        return fopen(e, "r");
+            *result = pa_xstrdup(fn);
+
+        return fopen(fn, "r");
     }
 
     if (local && pa_get_home_dir(h, sizeof(h))) {
         FILE *f;
-        char *l;
+        char *lfn;
         
-        l = pa_sprintf_malloc("%s/%s", h, local);
-        f = fopen(l, "r");
+        lfn = pa_sprintf_malloc("%s/%s", h, local);
+
+#ifdef OS_IS_WIN32
+        if (!ExpandEnvironmentStrings(lfn, buf, PATH_MAX))
+            return NULL;
+        lfn = buf;
+#endif
+
+        f = fopen(lfn, "r");
 
         if (f || errno != ENOENT) {
             if (result)
-                *result = l;
-            else
-                pa_xfree(l);
+                *result = pa_xstrdup(lfn);
+            pa_xfree(lfn);
             return f;
         }
         
-        pa_xfree(l);
+        pa_xfree(lfn);
     }
 
     if (!global) {
@@ -829,6 +996,12 @@ FILE *pa_open_config_file(const char *global, const char *local, const char *env
         return NULL;
     }
 
+#ifdef OS_IS_WIN32
+    if (!ExpandEnvironmentStrings(global, buf, PATH_MAX))
+        return NULL;
+    global = buf;
+#endif
+
     if (result)
         *result = pa_xstrdup(global);
     
@@ -934,21 +1107,44 @@ int pa_startswith(const char *s, const char *pfx) {
 char *pa_runtime_path(const char *fn, char *s, size_t l) {
     char u[256];
 
+#ifndef OS_IS_WIN32
     if (fn && *fn == '/')
+#else
+    if (fn && strlen(fn) >= 3 && isalpha(fn[0]) && fn[1] == ':' && fn[2] == '\\')
+#endif
         return pa_strlcpy(s, fn, l);
-    
-    snprintf(s, l, PA_RUNTIME_PATH_PREFIX"%s%s%s", pa_get_user_name(u, sizeof(u)), fn ? "/" : "", fn ? fn : "");
+
+    if (fn)    
+        snprintf(s, l, "%s%s%c%s", PA_RUNTIME_PATH_PREFIX, pa_get_user_name(u, sizeof(u)), PATH_SEP, fn);
+    else
+        snprintf(s, l, "%s%s", PA_RUNTIME_PATH_PREFIX, pa_get_user_name(u, sizeof(u)));
+
+#ifdef OS_IS_WIN32
+    {
+        char buf[l];
+        strcpy(buf, s);
+        ExpandEnvironmentStrings(buf, s, l);
+    }
+#endif
+
     return s;
 }
 
 /* Wait t milliseconds */
 int pa_msleep(unsigned long t) {
+#ifdef OS_IS_WIN32
+    Sleep(t);
+    return 0;
+#elif defined(HAVE_NANOSLEEP)
     struct timespec ts;
 
     ts.tv_sec = t/1000;
     ts.tv_nsec = (t % 1000) * 1000000;
 
     return nanosleep(&ts, NULL);
+#else
+#error "Platform lacks a sleep function."
+#endif
 }
 
 /* Convert the string s to a signed integer in *ret_i */

commit 6781628ebd29423eb843b6acd71aaff5a744dd9c
Author: Pierre Ossman <ossman at cendio.se>
Date:   Thu Jan 5 22:58:01 2006 +0000

    The Windows sound interface module.
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/ossman@419 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/polyp/module-waveout.c b/polyp/module-waveout.c
new file mode 100644
index 0000000..4e01bc7
--- /dev/null
+++ b/polyp/module-waveout.c
@@ -0,0 +1,583 @@
+/* $Id: module-waveout.c 333 2005-01-08 21:36:53Z lennart $ */
+
+/***
+  This file is part of polypaudio.
+ 
+  polypaudio 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.
+ 
+  polypaudio 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 polypaudio; 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 <mmsystem.h>
+#include <assert.h>
+
+#include "sink.h"
+#include "source.h"
+#include "module.h"
+#include "mainloop-api.h"
+#include "modargs.h"
+#include "sample-util.h"
+#include "util.h"
+#include "log.h"
+#include "xmalloc.h"
+#include "module-waveout-symdef.h"
+
+PA_MODULE_AUTHOR("Pierre Ossman")
+PA_MODULE_DESCRIPTION("Windows waveOut Sink/Source")
+PA_MODULE_VERSION(PACKAGE_VERSION)
+PA_MODULE_USAGE("sink_name=<name for the sink> source_name=<name for the source> record=<enable source?> playback=<enable sink?> format=<sample format> channels=<number of channels> rate=<sample rate> fragments=<number of fragments> fragment_size=<fragment size>")
+
+#define PA_TYPEID_WAVEOUT PA_TYPEID_MAKE('W', 'A', 'V', 'E')
+
+#define DEFAULT_SINK_NAME "wave_output"
+#define DEFAULT_SOURCE_NAME "wave_input"
+
+struct userdata {
+    struct pa_sink *sink;
+    struct pa_source *source;
+    struct pa_core *core;
+    struct pa_time_event *event;
+    struct pa_defer_event *defer;
+    pa_usec_t poll_timeout;
+
+    uint32_t fragments, fragment_size;
+
+    uint32_t free_ofrags, free_ifrags;
+
+    DWORD written_bytes;
+
+    int cur_ohdr, cur_ihdr;
+    unsigned int oremain;
+    WAVEHDR *ohdrs, *ihdrs;
+    struct pa_memchunk silence;
+
+    HWAVEOUT hwo;
+    HWAVEIN hwi;
+    struct pa_module *module;
+
+    CRITICAL_SECTION crit;
+};
+
+static const char* const valid_modargs[] = {
+    "sink_name",
+    "source_name",
+    "record",
+    "playback",
+    "fragments",
+    "fragment_size",
+    "format",
+    "rate",
+    "channels",
+    NULL
+};
+
+static void update_usage(struct userdata *u) {
+   pa_module_set_used(u->module,
+                      (u->sink ? pa_idxset_ncontents(u->sink->inputs) : 0) +
+                      (u->sink ? pa_idxset_ncontents(u->sink->monitor_source->outputs) : 0) +
+                      (u->source ? pa_idxset_ncontents(u->source->outputs) : 0));
+}
+
+static void do_write(struct userdata *u)
+{
+    uint32_t free_frags, remain;
+    struct pa_memchunk memchunk, *cur_chunk;
+    WAVEHDR *hdr;
+    MMRESULT res;
+
+    if (!u->sink)
+        return;
+
+    EnterCriticalSection(&u->crit);
+
+    free_frags = u->free_ofrags;
+    u->free_ofrags = 0;
+
+    LeaveCriticalSection(&u->crit);
+
+    while (free_frags) {
+        hdr = &u->ohdrs[u->cur_ohdr];
+        if (hdr->dwFlags & WHDR_PREPARED)
+            waveOutUnprepareHeader(u->hwo, hdr, sizeof(WAVEHDR));
+
+        remain = u->oremain;
+        while (remain) {
+            cur_chunk = &memchunk;
+
+            if (pa_sink_render(u->sink, remain, cur_chunk) < 0) {
+                /*
+                 * Don't fill with silence unless we're getting close to
+                 * underflowing.
+                 */
+                if (free_frags > u->fragments/2)
+                    cur_chunk = &u->silence;
+                else {
+                    EnterCriticalSection(&u->crit);
+
+                    u->free_ofrags += free_frags;
+
+                    LeaveCriticalSection(&u->crit);
+
+                    u->oremain = remain;
+                    return;
+                }
+            }
+
+            assert(cur_chunk->memblock);
+            assert(cur_chunk->memblock->data);
+            assert(cur_chunk->length);
+
+            memcpy(hdr->lpData + u->fragment_size - remain,
+                (char*)cur_chunk->memblock->data + cur_chunk->index,
+                (cur_chunk->length < remain)?cur_chunk->length:remain);
+
+            remain -= (cur_chunk->length < remain)?cur_chunk->length:remain;
+
+            if (cur_chunk != &u->silence) {
+                pa_memblock_unref(cur_chunk->memblock);
+                cur_chunk->memblock = NULL;
+            }
+        }
+
+        res = waveOutPrepareHeader(u->hwo, hdr, sizeof(WAVEHDR));
+        if (res != MMSYSERR_NOERROR) {
+            pa_log_error(__FILE__ ": ERROR: Unable to prepare waveOut block: %d\n",
+                res);
+        }
+        res = waveOutWrite(u->hwo, hdr, sizeof(WAVEHDR));
+        if (res != MMSYSERR_NOERROR) {
+            pa_log_error(__FILE__ ": ERROR: Unable to write waveOut block: %d\n",
+                res);
+        }
+        
+        u->written_bytes += u->fragment_size;
+
+        free_frags--;
+        u->cur_ohdr++;
+        u->cur_ohdr %= u->fragments;
+        u->oremain = u->fragment_size;
+    }
+}
+
+static void do_read(struct userdata *u)
+{
+    uint32_t free_frags;
+    struct pa_memchunk memchunk;
+    WAVEHDR *hdr;
+    MMRESULT res;
+
+    if (!u->source)
+        return;
+
+    EnterCriticalSection(&u->crit);
+
+    free_frags = u->free_ifrags;
+    u->free_ifrags = 0;
+
+    LeaveCriticalSection(&u->crit);
+
+    while (free_frags) {
+        hdr = &u->ihdrs[u->cur_ihdr];
+        if (hdr->dwFlags & WHDR_PREPARED)
+            waveInUnprepareHeader(u->hwi, hdr, sizeof(WAVEHDR));
+
+        if (hdr->dwBytesRecorded) {
+            memchunk.memblock = pa_memblock_new(hdr->dwBytesRecorded, u->core->memblock_stat);
+            assert(memchunk.memblock);
+
+            memcpy((char*)memchunk.memblock->data, hdr->lpData, hdr->dwBytesRecorded);
+
+            memchunk.length = memchunk.memblock->length = hdr->dwBytesRecorded;
+            memchunk.index = 0;
+
+            pa_source_post(u->source, &memchunk);
+            pa_memblock_unref(memchunk.memblock);
+        }
+
+        res = waveInPrepareHeader(u->hwi, hdr, sizeof(WAVEHDR));
+        if (res != MMSYSERR_NOERROR) {
+            pa_log_error(__FILE__ ": ERROR: Unable to prepare waveIn block: %d\n",
+                res);
+        }
+        res = waveInAddBuffer(u->hwi, hdr, sizeof(WAVEHDR));
+        if (res != MMSYSERR_NOERROR) {
+            pa_log_error(__FILE__ ": ERROR: Unable to add waveIn block: %d\n",
+                res);
+        }
+        
+        free_frags--;
+        u->cur_ihdr++;
+        u->cur_ihdr %= u->fragments;
+    }
+}
+
+static void poll_cb(struct pa_mainloop_api*a, struct pa_time_event *e, const struct timeval *tv, void *userdata) {
+    struct userdata *u = userdata;
+    struct timeval ntv;
+
+    assert(u);
+
+    update_usage(u);
+
+    do_write(u);
+    do_read(u);
+
+    pa_gettimeofday(&ntv);
+    pa_timeval_add(&ntv, u->poll_timeout);
+
+    a->time_restart(e, &ntv);
+}
+
+static void defer_cb(struct pa_mainloop_api*a, struct pa_defer_event *e, void *userdata) {
+    struct userdata *u = userdata;
+
+    assert(u);
+
+    a->defer_enable(e, 0);
+
+    do_write(u);
+    do_read(u);
+}
+
+static void CALLBACK chunk_done_cb(HWAVEOUT hwo, UINT msg, DWORD_PTR inst, DWORD param1, DWORD param2) {
+    struct userdata *u = (struct userdata *)inst;
+
+    if (msg != WOM_DONE)
+        return;
+
+    EnterCriticalSection(&u->crit);
+
+    u->free_ofrags++;
+    assert(u->free_ofrags <= u->fragments);
+
+    LeaveCriticalSection(&u->crit);
+}
+
+static void CALLBACK chunk_ready_cb(HWAVEIN hwi, UINT msg, DWORD_PTR inst, DWORD param1, DWORD param2) {
+    struct userdata *u = (struct userdata *)inst;
+
+    if (msg != WIM_DATA)
+        return;
+
+    EnterCriticalSection(&u->crit);
+
+    u->free_ifrags++;
+    assert(u->free_ifrags <= u->fragments);
+
+    LeaveCriticalSection(&u->crit);
+}
+
+static pa_usec_t sink_get_latency_cb(struct pa_sink *s) {
+    struct userdata *u = s->userdata;
+    uint32_t free_frags;
+    MMTIME mmt;
+    assert(s && u && u->sink);
+
+    memset(&mmt, 0, sizeof(mmt));
+    mmt.wType = TIME_BYTES;
+    if (waveOutGetPosition(u->hwo, &mmt, sizeof(mmt)) == MMSYSERR_NOERROR)
+        return pa_bytes_to_usec(u->written_bytes - mmt.u.cb, &s->sample_spec);
+    else {
+        EnterCriticalSection(&u->crit);
+
+        free_frags = u->free_ofrags;
+
+        LeaveCriticalSection(&u->crit);
+
+        return pa_bytes_to_usec((u->fragments - free_frags) * u->fragment_size,
+                              &s->sample_spec);
+    }
+}
+
+static pa_usec_t source_get_latency_cb(struct pa_source *s) {
+    pa_usec_t r = 0;
+    struct userdata *u = s->userdata;
+    uint32_t free_frags;
+    assert(s && u && u->sink);
+
+    EnterCriticalSection(&u->crit);
+
+    free_frags = u->free_ifrags;
+
+    LeaveCriticalSection(&u->crit);
+
+    r += pa_bytes_to_usec((free_frags + 1) * u->fragment_size, &s->sample_spec);
+
+    fprintf(stderr, "Latency: %d us\n", (int)r);
+
+    return r;
+}
+
+static void notify_sink_cb(struct pa_sink *s) {
+    struct userdata *u = s->userdata;
+    assert(u);
+
+    u->core->mainloop->defer_enable(u->defer, 1);
+}
+
+static void notify_source_cb(struct pa_source *s) {
+    struct userdata *u = s->userdata;
+    assert(u);
+
+    u->core->mainloop->defer_enable(u->defer, 1);
+}
+
+static int ss_to_waveformat(struct pa_sample_spec *ss, LPWAVEFORMATEX wf) {
+    wf->wFormatTag = WAVE_FORMAT_PCM;
+
+    if (ss->channels > 2) {
+        pa_log_error(__FILE__": ERROR: More than two channels not supported.\n");
+        return -1;
+    }
+
+    wf->nChannels = ss->channels;
+
+    switch (ss->rate) {
+    case 8000:
+    case 11025:
+    case 22005:
+    case 44100:
+        break;
+    default:
+        pa_log_error(__FILE__": ERROR: Unsupported sample rate.\n");
+        return -1;
+    }
+
+    wf->nSamplesPerSec = ss->rate;
+
+    if (ss->format == PA_SAMPLE_U8)
+        wf->wBitsPerSample = 8;
+    else if (ss->format == PA_SAMPLE_S16NE)
+        wf->wBitsPerSample = 16;
+    else {
+        pa_log_error(__FILE__": ERROR: Unsupported sample format.\n");
+        return -1;
+    }
+
+    wf->nBlockAlign = wf->nChannels * wf->wBitsPerSample/8;
+    wf->nAvgBytesPerSec = wf->nSamplesPerSec * wf->nBlockAlign;
+
+    wf->cbSize = 0;
+
+    return 0;
+}
+
+int pa__init(struct pa_core *c, struct pa_module*m) {
+    struct userdata *u = NULL;
+    HWAVEOUT hwo = INVALID_HANDLE_VALUE;
+    HWAVEIN hwi = INVALID_HANDLE_VALUE;
+    WAVEFORMATEX wf;
+    int nfrags, frag_size;
+    int record = 1, playback = 1;
+    struct pa_sample_spec ss;
+    struct pa_modargs *ma = NULL;
+    unsigned int i;
+    struct timeval tv;
+
+    assert(c && m);
+
+    if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
+        pa_log(__FILE__": failed to parse module arguments.\n");
+        goto fail;
+    }
+
+    if (pa_modargs_get_value_boolean(ma, "record", &record) < 0 || pa_modargs_get_value_boolean(ma, "playback", &playback) < 0) {
+        pa_log(__FILE__": record= and playback= expect boolean argument.\n");
+        goto fail;
+    }
+
+    if (!playback && !record) {
+        pa_log(__FILE__": neither playback nor record enabled for device.\n");
+        goto fail;
+    }
+
+    nfrags = 20;
+    frag_size = 1024;
+    if (pa_modargs_get_value_s32(ma, "fragments", &nfrags) < 0 || pa_modargs_get_value_s32(ma, "fragment_size", &frag_size) < 0) {
+        pa_log(__FILE__": failed to parse fragments arguments\n");
+        goto fail;
+    }
+
+    ss = c->default_sample_spec;
+    if (pa_modargs_get_sample_spec(ma, &ss) < 0) {
+        pa_log(__FILE__": failed to parse sample specification\n");
+        goto fail;
+    }
+
+    if (ss_to_waveformat(&ss, &wf) < 0)
+        goto fail;
+
+    u = pa_xmalloc(sizeof(struct userdata));
+
+    if (record) {
+        if (waveInOpen(&hwi, WAVE_MAPPER, &wf, (DWORD_PTR)chunk_ready_cb, (DWORD_PTR)u, CALLBACK_FUNCTION) != MMSYSERR_NOERROR)
+            goto fail;
+        if (waveInStart(hwi) != MMSYSERR_NOERROR)
+            goto fail;
+        pa_log_debug(__FILE__": Opened waveIn subsystem.\n");
+    }
+
+    if (playback) {
+        if (waveOutOpen(&hwo, WAVE_MAPPER, &wf, (DWORD_PTR)chunk_done_cb, (DWORD_PTR)u, CALLBACK_FUNCTION) != MMSYSERR_NOERROR)
+            goto fail;
+        pa_log_debug(__FILE__": Opened waveOut subsystem.\n");
+    }
+
+    InitializeCriticalSection(&u->crit);
+
+    if (hwi != INVALID_HANDLE_VALUE) {
+        u->source = pa_source_new(c, PA_TYPEID_WAVEOUT, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME), 0, &ss);
+        assert(u->source);
+        u->source->userdata = u;
+        u->source->notify = notify_source_cb;
+        u->source->get_latency = source_get_latency_cb;
+        pa_source_set_owner(u->source, m);
+        u->source->description = pa_sprintf_malloc("Windows waveIn PCM");
+    } else
+        u->source = NULL;
+
+    if (hwo != INVALID_HANDLE_VALUE) {
+        u->sink = pa_sink_new(c, PA_TYPEID_WAVEOUT, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss);
+        assert(u->sink);
+        u->sink->notify = notify_sink_cb;
+        u->sink->get_latency = sink_get_latency_cb;
+        u->sink->userdata = u;
+        pa_sink_set_owner(u->sink, m);
+        u->sink->description = pa_sprintf_malloc("Windows waveOut PCM");
+    } else
+        u->sink = NULL;
+
+    assert(u->source || u->sink);
+
+    u->core = c;
+    u->hwi = hwi;
+    u->hwo = hwo;
+
+    u->fragments = nfrags;
+    u->free_ifrags = u->fragments;
+    u->free_ofrags = u->fragments;
+    u->fragment_size = frag_size - (frag_size % pa_frame_size(&ss));
+
+    u->written_bytes = 0;
+
+    u->oremain = u->fragment_size;
+
+    u->poll_timeout = pa_bytes_to_usec(u->fragments * u->fragment_size / 3, &ss);
+
+    pa_gettimeofday(&tv);
+    pa_timeval_add(&tv, u->poll_timeout);
+
+    u->event = c->mainloop->time_new(c->mainloop, &tv, poll_cb, u);
+    assert(u->event);
+
+    u->defer = c->mainloop->defer_new(c->mainloop, defer_cb, u);
+    assert(u->defer);
+    c->mainloop->defer_enable(u->defer, 0);
+
+    u->cur_ihdr = 0;
+    u->cur_ohdr = 0;
+    u->ihdrs = pa_xmalloc0(sizeof(WAVEHDR) * u->fragments);
+    assert(u->ihdrs);
+    u->ohdrs = pa_xmalloc0(sizeof(WAVEHDR) * u->fragments);
+    assert(u->ohdrs);
+    for (i = 0;i < u->fragments;i++) {
+        u->ihdrs[i].dwBufferLength = u->fragment_size;
+        u->ohdrs[i].dwBufferLength = u->fragment_size;
+        u->ihdrs[i].lpData = pa_xmalloc(u->fragment_size);
+        assert(u->ihdrs);
+        u->ohdrs[i].lpData = pa_xmalloc(u->fragment_size);
+        assert(u->ohdrs);
+    }
+    
+    u->silence.length = u->fragment_size;
+    u->silence.memblock = pa_memblock_new(u->silence.length, u->core->memblock_stat);
+    assert(u->silence.memblock);
+    pa_silence_memblock(u->silence.memblock, &ss);
+    u->silence.index = 0;
+
+    u->module = m;
+    m->userdata = u;
+
+    pa_modargs_free(ma);
+
+    return 0;
+
+fail:
+   if (hwi != INVALID_HANDLE_VALUE)
+        waveInClose(hwi);
+
+   if (hwo != INVALID_HANDLE_VALUE)
+        waveOutClose(hwo);
+
+    if (u)
+        pa_xfree(u);
+
+    if (ma)
+        pa_modargs_free(ma);
+    
+    return -1;
+}
+
+void pa__done(struct pa_core *c, struct pa_module*m) {
+    struct userdata *u;
+    unsigned int i;
+
+    assert(c && m);
+
+    if (!(u = m->userdata))
+        return;
+    
+    if (u->event)
+        c->mainloop->time_free(u->event);
+
+    if (u->defer)
+        c->mainloop->defer_free(u->defer);
+
+    if (u->sink) {
+        pa_sink_disconnect(u->sink);
+        pa_sink_unref(u->sink);
+    }
+    
+    if (u->source) {
+        pa_source_disconnect(u->source);
+        pa_source_unref(u->source);
+    }
+    
+    if (u->hwi != INVALID_HANDLE_VALUE) {
+        waveInReset(u->hwi);
+        waveInClose(u->hwi);
+    }
+
+    if (u->hwo != INVALID_HANDLE_VALUE) {
+        waveOutReset(u->hwo);
+        waveOutClose(u->hwo);
+    }
+
+    for (i = 0;i < u->fragments;i++) {
+        pa_xfree(u->ihdrs[i].lpData);
+        pa_xfree(u->ohdrs[i].lpData);
+    }
+
+    pa_xfree(u->ihdrs);
+    pa_xfree(u->ohdrs);
+
+    DeleteCriticalSection(&u->crit);
+    
+    pa_xfree(u);
+}

commit 1b472f76ec950e4337b9de1bc7617dbd89449e98
Author: Pierre Ossman <ossman at cendio.se>
Date:   Thu Jan 5 23:06:11 2006 +0000

    Solaris support.
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/ossman@420 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/configure.ac b/configure.ac
index 5ff28a5..7737d17 100644
--- a/configure.ac
+++ b/configure.ac
@@ -158,6 +158,10 @@ AC_TYPE_UID_T
 AC_CHECK_DEFINE([SIGXCPU], [signal.h], [HAVE_SIGXCPU=1], [HAVE_SIGXCPU=0])
 AM_CONDITIONAL(HAVE_SIGXCPU, test "x$HAVE_SIGXCPU" = "x1")
 
+# Solaris lacks this
+AC_CHECK_DEFINE([INADDR_NONE], [netinet/in.h], [],
+    [AC_DEFINE([INADDR_NONE],  [0xffffffff], [Define INADDR_NONE if not found in <netinet/in.h>])])
+
 #### Check for functions ####
 
 # ISO
@@ -167,6 +171,7 @@ AC_CHECK_LIB([m], [pow])
 AC_FUNC_FORK
 AC_FUNC_GETGROUPS
 AC_FUNC_SELECT_ARGTYPES
+AC_CHECK_LIB([rt], [sched_setscheduler])
 AC_CHECK_FUNCS([getaddrinfo getgrgid_r getpwuid_r gettimeofday getuid \
     inet_ntop nanosleep setpgid setsid sigaction sleep])
 AC_CHECK_FUNCS([mkfifo], [HAVE_MKFIFO=1], [HAVE_MKFIFO=0])
@@ -179,6 +184,9 @@ AC_CHECK_FUNCS([readlink])
 # SUSv2
 AC_CHECK_FUNCS([ctime_r usleep])
 
+# BSD
+AC_CHECK_LIB([socket], [connect])
+
 # Non-standard
 
 AC_CHECK_FUNCS(setresuid)
@@ -247,6 +255,12 @@ AC_SUBST(ASOUNDLIB_LIBS)
 AC_SUBST(HAVE_ALSA)
 AM_CONDITIONAL([HAVE_ALSA], [test "x$HAVE_ALSA" = x1])
 
+#### Solaris audio support (optional) ####
+
+AC_CHECK_HEADERS([sys/audio.h], [HAVE_SOLARIS=1], [HAVE_SOLARIS=0])
+AC_SUBST(HAVE_SOLARIS)
+AM_CONDITIONAL([HAVE_SOLARIS], [test "x$HAVE_SOLARIS" = x1])
+
 #### GLib 2 support (optional) ####
 
 PKG_CHECK_MODULES(GLIB20, [ glib-2.0 >= 2.4.0 ], HAVE_GLIB20=1, HAVE_GLIB20=0)
diff --git a/polyp/Makefile.am b/polyp/Makefile.am
index dcd3fc1..5f57142 100644
--- a/polyp/Makefile.am
+++ b/polyp/Makefile.am
@@ -43,7 +43,8 @@ endif
 ###################################
 
 AM_CFLAGS  = -D_GNU_SOURCE  -I$(top_srcdir)
-AM_CFLAGS += $(PTHREAD_CFLAGS) $(LTDLINCL)
+AM_CFLAGS += $(PTHREAD_CFLAGS) -D_POSIX_PTHREAD_SEMANTICS
+AM_CFLAGS += $(LTDLINCL)
 AM_CFLAGS += $(LIBSAMPLERATE_CFLAGS) $(LIBSNDFILE_CFLAGS)
 AM_CFLAGS += -DDLSEARCHPATH=\"$(modlibdir)\"
 AM_CFLAGS += -DDEFAULT_CONFIG_DIR=\"$(DEFAULT_CONFIG_DIR)\"
@@ -714,6 +715,11 @@ modlib_LTLIBRARIES += \
 		module-alsa-source.la
 endif
 
+if HAVE_SOLARIS
+modlib_LTLIBRARIES += \
+		module-solaris.la
+endif
+
 if HAVE_HOWL
 modlib_LTLIBRARIES += \
 		module-zeroconf-publish.la
@@ -774,6 +780,7 @@ SYMDEF_FILES = \
 		module-oss-mmap-symdef.h \
 		module-alsa-sink-symdef.h \
 		module-alsa-source-symdef.h \
+		module-solaris-symdef.h \
 		module-waveout-symdef.h
 
 EXTRA_DIST += $(SYMDEF_FILES)
@@ -961,6 +968,12 @@ module_alsa_source_la_LDFLAGS = -module -avoid-version
 module_alsa_source_la_LIBADD = $(AM_LIBADD) $(ASOUNDLIB_LIBS) libalsa-util.la
 module_alsa_source_la_CFLAGS = $(AM_CFLAGS) $(ASOUNDLIB_CFLAGS)
 
+# Solaris
+
+module_solaris_la_SOURCES = module-solaris.c
+module_solaris_la_LDFLAGS = -module -avoid-version
+module_solaris_la_LIBADD = $(AM_LIBADD) libiochannel.la
+
 # HOWL
 
 module_zeroconf_publish_la_SOURCES = module-zeroconf-publish.c
diff --git a/polyp/module-solaris.c b/polyp/module-solaris.c
new file mode 100644
index 0000000..3eb6646
--- /dev/null
+++ b/polyp/module-solaris.c
@@ -0,0 +1,436 @@
+/* $Id: module-oss.c 333 2005-01-08 21:36:53Z lennart $ */
+
+/***
+  This file is part of polypaudio.
+ 
+  polypaudio 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.
+ 
+  polypaudio 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 polypaudio; 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 <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 <sys/stat.h>
+#include <sys/types.h>
+
+#include <stropts.h>
+#include <sys/conf.h>
+#include <sys/audio.h>
+
+#include "iochannel.h"
+#include "sink.h"
+#include "source.h"
+#include "module.h"
+#include "sample-util.h"
+#include "util.h"
+#include "modargs.h"
+#include "xmalloc.h"
+#include "log.h"
+#include "module-solaris-symdef.h"
+
+PA_MODULE_AUTHOR("Pierre Ossman")
+PA_MODULE_DESCRIPTION("Solaris Sink/Source")
+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> buffer_size=<record buffer size>")
+
+#define PA_TYPEID_SOLARIS PA_TYPEID_MAKE('S', 'L', 'R', 'S')
+
+struct userdata {
+    struct pa_sink *sink;
+    struct pa_source *source;
+    struct pa_iochannel *io;
+    struct pa_core *core;
+
+    struct pa_memchunk memchunk, silence;
+
+    uint32_t sample_size;
+    unsigned int written_bytes, read_bytes;
+
+    int fd;
+    struct pa_module *module;
+};
+
+static const char* const valid_modargs[] = {
+    "sink_name",
+    "source_name",
+    "device",
+    "record",
+    "playback",
+    "buffer_size",
+    "format",
+    "rate",
+    "channels",
+    NULL
+};
+
+#define DEFAULT_SINK_NAME "solaris_output"
+#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_idxset_ncontents(u->sink->inputs) : 0) +
+                      (u->sink ? pa_idxset_ncontents(u->sink->monitor_source->outputs) : 0) +
+                      (u->source ? pa_idxset_ncontents(u->source->outputs) : 0));
+}
+
+static void do_write(struct userdata *u) {
+    struct pa_memchunk *memchunk;
+    ssize_t r;
+    
+    assert(u);
+
+    if (!u->sink || !pa_iochannel_is_writable(u->io))
+        return;
+
+    update_usage(u);
+
+    memchunk = &u->memchunk;
+    
+    if (!memchunk->length)
+        if (pa_sink_render(u->sink, CHUNK_SIZE, memchunk) < 0)
+            memchunk = &u->silence;
+    
+    assert(memchunk->memblock);
+    assert(memchunk->memblock->data);
+    assert(memchunk->length);
+    
+    if ((r = pa_iochannel_write(u->io, (uint8_t*) memchunk->memblock->data + memchunk->index, memchunk->length)) < 0) {
+        pa_log(__FILE__": write() failed: %s\n", strerror(errno));
+        return;
+    }
+    
+    if (memchunk == &u->silence)
+        assert(r % u->sample_size == 0);
+    else {
+        u->memchunk.index += r;
+        u->memchunk.length -= r;
+        
+        if (u->memchunk.length <= 0) {
+            pa_memblock_unref(u->memchunk.memblock);
+            u->memchunk.memblock = NULL;
+        }
+    }
+
+    u->written_bytes += r;
+}
+
+static void do_read(struct userdata *u) {
+    struct pa_memchunk memchunk;
+    int err, l;
+    ssize_t r;
+    assert(u);
+    
+    if (!u->source || !pa_iochannel_is_readable(u->io))
+        return;
+
+    update_usage(u);
+
+    err = ioctl(u->fd, I_NREAD, &l);
+    assert(err >= 0);
+
+    memchunk.memblock = pa_memblock_new(l, u->core->memblock_stat);
+    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(__FILE__": read() failed: %s\n", strerror(errno));
+        return;
+    }
+    
+    assert(r <= (ssize_t) memchunk.memblock->length);
+    memchunk.length = memchunk.memblock->length = r;
+    memchunk.index = 0;
+    
+    pa_source_post(u->source, &memchunk);
+    pa_memblock_unref(memchunk.memblock);
+
+    u->read_bytes += r;
+}
+
+static void io_callback(struct pa_iochannel *io, void*userdata) {
+    struct userdata *u = userdata;
+    assert(u);
+    do_write(u);
+    do_read(u);
+}
+
+static pa_usec_t sink_get_latency_cb(struct pa_sink *s) {
+    pa_usec_t r = 0;
+    audio_info_t info;
+    int err;
+    struct userdata *u = s->userdata;
+    assert(s && u && u->sink);
+
+    err = ioctl(u->fd, AUDIO_GETINFO, &info);
+    assert(err >= 0);
+
+    r += pa_bytes_to_usec(u->written_bytes, &s->sample_spec);
+    r -= pa_bytes_to_usec(info.play.samples * u->sample_size, &s->sample_spec);
+
+    if (u->memchunk.memblock)
+        r += pa_bytes_to_usec(u->memchunk.length, &s->sample_spec);
+
+    return r;
+}
+
+static pa_usec_t source_get_latency_cb(struct pa_source *s) {
+    pa_usec_t r = 0;
+    struct userdata *u = s->userdata;
+    audio_info_t info;
+    int err;
+    assert(s && u && u->source);
+
+    err = ioctl(u->fd, AUDIO_GETINFO, &info);
+    assert(err >= 0);
+
+    r += pa_bytes_to_usec(info.record.samples * u->sample_size, &s->sample_spec);
+    r -= pa_bytes_to_usec(u->read_bytes, &s->sample_spec);
+
+    return r;
+}
+
+static int pa_solaris_auto_format(int fd, int mode, struct pa_sample_spec *ss) {
+    audio_info_t info;
+
+    AUDIO_INITINFO(&info);
+
+    if (mode != O_RDONLY) {
+        info.play.sample_rate = ss->rate;
+        info.play.channels = ss->channels;
+        switch (ss->format) {
+        case PA_SAMPLE_U8:
+            info.play.precision = 8;
+            info.play.encoding = AUDIO_ENCODING_LINEAR;
+            break;
+        case PA_SAMPLE_ALAW:
+            info.play.precision = 8;
+            info.play.encoding = AUDIO_ENCODING_ALAW;
+            break;
+        case PA_SAMPLE_ULAW:
+            info.play.precision = 8;
+            info.play.encoding = AUDIO_ENCODING_ULAW;
+            break;
+        case PA_SAMPLE_S16NE:
+            info.play.precision = 16;
+            info.play.encoding = AUDIO_ENCODING_LINEAR;
+            break;
+        default:
+            return -1;
+        }
+    }
+
+    if (mode != O_WRONLY) {
+        info.record.sample_rate = ss->rate;
+        info.record.channels = ss->channels;
+        switch (ss->format) {
+        case PA_SAMPLE_U8:
+            info.record.precision = 8;
+            info.record.encoding = AUDIO_ENCODING_LINEAR;
+            break;
+        case PA_SAMPLE_ALAW:
+            info.record.precision = 8;
+            info.record.encoding = AUDIO_ENCODING_ALAW;
+            break;
+        case PA_SAMPLE_ULAW:
+            info.record.precision = 8;
+            info.record.encoding = AUDIO_ENCODING_ULAW;
+            break;
+        case PA_SAMPLE_S16NE:
+            info.record.precision = 16;
+            info.record.encoding = AUDIO_ENCODING_LINEAR;
+            break;
+        default:
+            return -1;
+        }
+    }
+
+    if (ioctl(fd, AUDIO_SETINFO, &info) < 0) {
+        if (errno == EINVAL)
+            pa_log(__FILE__": AUDIO_SETINFO: Unsupported sample format.\n");
+        else
+            pa_log(__FILE__": AUDIO_SETINFO: %s\n", strerror(errno));
+        return -1;
+    }
+
+    return 0;
+}
+
+static int pa_solaris_set_buffer(int fd, int buffer_size) {
+    audio_info_t info;
+
+    AUDIO_INITINFO(&info);
+
+    info.record.buffer_size = buffer_size;
+
+    if (ioctl(fd, AUDIO_SETINFO, &info) < 0) {
+        if (errno == EINVAL)
+            pa_log(__FILE__": AUDIO_SETINFO: Unsupported buffer size.\n");
+        else
+            pa_log(__FILE__": AUDIO_SETINFO: %s\n", strerror(errno));
+        return -1;
+    }
+
+    return 0;
+}
+
+int pa__init(struct pa_core *c, struct pa_module*m) {
+    struct userdata *u = NULL;
+    const char *p;
+    int fd = -1;
+    int buffer_size;
+    int mode;
+    int record = 1, playback = 1;
+    struct pa_sample_spec ss;
+    struct pa_modargs *ma = NULL;
+    assert(c && m);
+
+    if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
+        pa_log(__FILE__": failed to parse module arguments.\n");
+        goto fail;
+    }
+    
+    if (pa_modargs_get_value_boolean(ma, "record", &record) < 0 || pa_modargs_get_value_boolean(ma, "playback", &playback) < 0) {
+        pa_log(__FILE__": record= and playback= expect numeric argument.\n");
+        goto fail;
+    }
+
+    if (!playback && !record) {
+        pa_log(__FILE__": neither playback nor record enabled for device.\n");
+        goto fail;
+    }
+
+    mode = (playback&&record) ? O_RDWR : (playback ? O_WRONLY : (record ? O_RDONLY : 0));
+
+    buffer_size = -1;    
+    if (pa_modargs_get_value_s32(ma, "buffer_size", &buffer_size) < 0) {
+        pa_log(__FILE__": failed to parse buffer size argument\n");
+        goto fail;
+    }
+
+    ss = c->default_sample_spec;
+    if (pa_modargs_get_sample_spec(ma, &ss) < 0) {
+        pa_log(__FILE__": failed to parse sample specification\n");
+        goto fail;
+    }
+    
+    if ((fd = open(p = pa_modargs_get_value(ma, "device", DEFAULT_DEVICE), mode)) < 0)
+        goto fail;
+
+    pa_log_info(__FILE__": device opened in %s mode.\n", mode == O_WRONLY ? "O_WRONLY" : (mode == O_RDONLY ? "O_RDONLY" : "O_RDWR"));
+
+    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;
+
+    u = pa_xmalloc(sizeof(struct userdata));
+    u->core = c;
+
+    if (mode != O_WRONLY) {
+        u->source = pa_source_new(c, PA_TYPEID_SOLARIS, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME), 0, &ss);
+        assert(u->source);
+        u->source->userdata = u;
+        u->source->get_latency = source_get_latency_cb;
+        pa_source_set_owner(u->source, m);
+        u->source->description = pa_sprintf_malloc("Solaris PCM on '%s'", p);
+    } else
+        u->source = NULL;
+
+    if (mode != O_RDONLY) {
+        u->sink = pa_sink_new(c, PA_TYPEID_SOLARIS, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss);
+        assert(u->sink);
+        u->sink->get_latency = sink_get_latency_cb;
+        u->sink->userdata = u;
+        pa_sink_set_owner(u->sink, m);
+        u->sink->description = pa_sprintf_malloc("Solaris PCM on '%s'", p);
+    } 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;
+    u->sample_size = pa_frame_size(&ss);
+
+    u->silence.memblock = pa_memblock_new(u->silence.length = CHUNK_SIZE, u->core->memblock_stat);
+    assert(u->silence.memblock);
+    pa_silence_memblock(u->silence.memblock, &ss);
+    u->silence.index = 0;
+
+    u->written_bytes = 0;
+    u->read_bytes = 0;
+
+    u->module = m;
+    m->userdata = u;
+
+    pa_modargs_free(ma);
+
+    return 0;
+
+fail:
+    if (fd >= 0)
+        close(fd);
+
+    if (ma)
+        pa_modargs_free(ma);
+    
+    return -1;
+}
+
+void pa__done(struct pa_core *c, struct pa_module*m) {
+    struct userdata *u;
+    assert(c && m);
+
+    if (!(u = m->userdata))
+        return;
+    
+    if (u->memchunk.memblock)
+        pa_memblock_unref(u->memchunk.memblock);
+    if (u->silence.memblock)
+        pa_memblock_unref(u->silence.memblock);
+
+    if (u->sink) {
+        pa_sink_disconnect(u->sink);
+        pa_sink_unref(u->sink);
+    }
+    
+    if (u->source) {
+        pa_source_disconnect(u->source);
+        pa_source_unref(u->source);
+    }
+    
+    pa_iochannel_free(u->io);
+    pa_xfree(u);
+}
diff --git a/polyp/socket-server.c b/polyp/socket-server.c
index b7e4fed..c27979d 100644
--- a/polyp/socket-server.c
+++ b/polyp/socket-server.c
@@ -36,6 +36,10 @@
 #endif
 #ifdef HAVE_SYS_UN_H
 #include <sys/un.h>
+#ifndef SUN_LEN
+#define SUN_LEN(ptr) \
+    ((size_t)(((struct sockaddr_un *) 0)->sun_path) + strlen((ptr)->sun_path))
+#endif
 #endif
 #ifdef HAVE_ARPA_INET_H
 #include <arpa/inet.h>

commit 72795fcaa6778d3612ec04f9e5bde9a0eb2b1682
Author: Pierre Ossman <ossman at cendio.se>
Date:   Thu Jan 5 23:11:15 2006 +0000

    Use autoconf detected define for getgroups() type.
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/ossman@422 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/polyp/module-protocol-stub.c b/polyp/module-protocol-stub.c
index 8c06a61..b41515f 100644
--- a/polyp/module-protocol-stub.c
+++ b/polyp/module-protocol-stub.c
@@ -62,6 +62,10 @@
 #elif defined(USE_TCP6_SOCKETS)
 #define SOCKET_DESCRIPTION "(TCP/IPv6 sockets)"
 #define SOCKET_USAGE "port=<TCP port number> loopback=<listen on loopback device only?>"
+#ifdef OS_IS_WIN32
+static const struct in6_addr in6addr_any = {{ IN6ADDR_ANY_INIT }};
+static const struct in6_addr in6addr_loopback = {{ IN6ADDR_LOOPBACK_INIT }};
+#endif
 #else
 #define SOCKET_DESCRIPTION "(UNIX sockets)"
 #define SOCKET_USAGE "socket=<path to UNIX socket>"
diff --git a/polyp/polyplib-context.c b/polyp/polyplib-context.c
index da91995..fe5b306 100644
--- a/polyp/polyplib-context.c
+++ b/polyp/polyplib-context.c
@@ -367,12 +367,12 @@ static void setup_context(struct pa_context *c, struct pa_iochannel *io) {
     assert(!c->pdispatch);
     c->pdispatch = pa_pdispatch_new(c->mainloop, command_table, PA_COMMAND_MAX);
     assert(c->pdispatch);
-
+/*
     if (!c->conf->cookie_valid) {
         pa_context_fail(c, PA_ERROR_AUTHKEY);
         goto finish;
     }
-
+*/
     t = pa_tagstruct_new(NULL, 0);
     assert(t);
     pa_tagstruct_putu32(t, PA_COMMAND_AUTH);
diff --git a/polyp/socket-client.c b/polyp/socket-client.c
index 6d8cb2a..201733a 100644
--- a/polyp/socket-client.c
+++ b/polyp/socket-client.c
@@ -70,6 +70,10 @@
 
 #define CONNECT_TIMEOUT 5
 
+#ifdef OS_IS_WIN32
+static const struct in6_addr in6addr_loopback = {{ IN6ADDR_LOOPBACK_INIT }};
+#endif
+
 struct pa_socket_client {
     int ref;
     struct pa_mainloop_api *mainloop;
diff --git a/polyp/socket-server.c b/polyp/socket-server.c
index c27979d..2d5e5ac 100644
--- a/polyp/socket-server.c
+++ b/polyp/socket-server.c
@@ -65,6 +65,11 @@
 #include "util.h"
 #include "log.h"
 
+#ifdef OS_IS_WIN32
+static const struct in6_addr in6addr_any = {{ IN6ADDR_ANY_INIT }};
+static const struct in6_addr in6addr_loopback = {{ IN6ADDR_LOOPBACK_INIT }};
+#endif
+
 struct pa_socket_server {
     int ref;
     int fd;
diff --git a/polyp/util.c b/polyp/util.c
index 0495896..ff27430 100644
--- a/polyp/util.c
+++ b/polyp/util.c
@@ -773,7 +773,7 @@ finish:
 /* Check the current user is member of the specified group */
 int pa_uid_in_group(const char *name, gid_t *gid) {
     gid_t *gids, tgid;
-    long n = sysconf(_SC_NGROUPS_MAX);
+    GETGROUPS_T n = sysconf(_SC_NGROUPS_MAX);
     int r = -1, i;
 
     assert(n > 0);

commit 067c00ff5d3df79829a3b582bb6ac3079c3738de
Author: Pierre Ossman <ossman at cendio.se>
Date:   Thu Jan 5 23:13:54 2006 +0000

    Reversing incorrect commit.
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/ossman@423 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/polyp/module-protocol-stub.c b/polyp/module-protocol-stub.c
index b41515f..8c06a61 100644
--- a/polyp/module-protocol-stub.c
+++ b/polyp/module-protocol-stub.c
@@ -62,10 +62,6 @@
 #elif defined(USE_TCP6_SOCKETS)
 #define SOCKET_DESCRIPTION "(TCP/IPv6 sockets)"
 #define SOCKET_USAGE "port=<TCP port number> loopback=<listen on loopback device only?>"
-#ifdef OS_IS_WIN32
-static const struct in6_addr in6addr_any = {{ IN6ADDR_ANY_INIT }};
-static const struct in6_addr in6addr_loopback = {{ IN6ADDR_LOOPBACK_INIT }};
-#endif
 #else
 #define SOCKET_DESCRIPTION "(UNIX sockets)"
 #define SOCKET_USAGE "socket=<path to UNIX socket>"
diff --git a/polyp/polyplib-context.c b/polyp/polyplib-context.c
index fe5b306..da91995 100644
--- a/polyp/polyplib-context.c
+++ b/polyp/polyplib-context.c
@@ -367,12 +367,12 @@ static void setup_context(struct pa_context *c, struct pa_iochannel *io) {
     assert(!c->pdispatch);
     c->pdispatch = pa_pdispatch_new(c->mainloop, command_table, PA_COMMAND_MAX);
     assert(c->pdispatch);
-/*
+
     if (!c->conf->cookie_valid) {
         pa_context_fail(c, PA_ERROR_AUTHKEY);
         goto finish;
     }
-*/
+
     t = pa_tagstruct_new(NULL, 0);
     assert(t);
     pa_tagstruct_putu32(t, PA_COMMAND_AUTH);
diff --git a/polyp/socket-client.c b/polyp/socket-client.c
index 201733a..6d8cb2a 100644
--- a/polyp/socket-client.c
+++ b/polyp/socket-client.c
@@ -70,10 +70,6 @@
 
 #define CONNECT_TIMEOUT 5
 
-#ifdef OS_IS_WIN32
-static const struct in6_addr in6addr_loopback = {{ IN6ADDR_LOOPBACK_INIT }};
-#endif
-
 struct pa_socket_client {
     int ref;
     struct pa_mainloop_api *mainloop;
diff --git a/polyp/socket-server.c b/polyp/socket-server.c
index 2d5e5ac..c27979d 100644
--- a/polyp/socket-server.c
+++ b/polyp/socket-server.c
@@ -65,11 +65,6 @@
 #include "util.h"
 #include "log.h"
 
-#ifdef OS_IS_WIN32
-static const struct in6_addr in6addr_any = {{ IN6ADDR_ANY_INIT }};
-static const struct in6_addr in6addr_loopback = {{ IN6ADDR_LOOPBACK_INIT }};
-#endif
-
 struct pa_socket_server {
     int ref;
     int fd;

commit 8a323571a4fae25602133cc87656706ada9c0112
Author: Pierre Ossman <ossman at cendio.se>
Date:   Mon Jan 9 11:54:49 2006 +0000

    Make sure the data gets endianness conversion.
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/ossman@424 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/polyp/protocol-esound.c b/polyp/protocol-esound.c
index 5705d3f..18ecb0a 100644
--- a/polyp/protocol-esound.c
+++ b/polyp/protocol-esound.c
@@ -239,11 +239,14 @@ static void* connection_write(struct connection *c, size_t length) {
     return (uint8_t*) c->write_data+i;
 }
 
-static void format_esd2native(int format, struct pa_sample_spec *ss) {
+static void format_esd2native(int format, int swap_bytes, struct pa_sample_spec *ss) {
     assert(ss);
 
     ss->channels = ((format & ESD_MASK_CHAN) == ESD_STEREO) ? 2 : 1;
-    ss->format = ((format & ESD_MASK_BITS) == ESD_BITS16) ? PA_SAMPLE_S16NE : PA_SAMPLE_U8;
+    if ((format & ESD_MASK_BITS) == ESD_BITS16)
+        ss->format = swap_bytes ? PA_SAMPLE_S16RE : PA_SAMPLE_S16NE;
+    else
+        ss->format = PA_SAMPLE_U8;
 }
 
 static int format_native2esd(struct pa_sample_spec *ss) {
@@ -303,7 +306,7 @@ static int esd_proto_stream_play(struct connection *c, esd_proto_t request, cons
     rate = maybe_swap_endian_32(c->swap_byte_order, *((int*)data + 1));
 
     ss.rate = rate;
-    format_esd2native(format, &ss);
+    format_esd2native(format, c->swap_byte_order, &ss);
 
     if (!pa_sample_spec_valid(&ss)) {
         pa_log(__FILE__": invalid sample specification\n");
@@ -359,7 +362,7 @@ static int esd_proto_stream_record(struct connection *c, esd_proto_t request, co
     rate = maybe_swap_endian_32(c->swap_byte_order, *((int*)data + 1));
 
     ss.rate = rate;
-    format_esd2native(format, &ss);
+    format_esd2native(format, c->swap_byte_order, &ss);
 
     if (!pa_sample_spec_valid(&ss)) {
         pa_log(__FILE__": invalid sample specification.\n");
@@ -602,7 +605,7 @@ static int esd_proto_sample_cache(struct connection *c, esd_proto_t request, con
     rate = maybe_swap_endian_32(c->swap_byte_order, *((int*)data + 1));
     
     ss.rate = rate;
-    format_esd2native(format, &ss);
+    format_esd2native(format, c->swap_byte_order, &ss);
 
     sc_length = (size_t) maybe_swap_endian_32(c->swap_byte_order, (*((int*)data + 2)));
 
diff --git a/polyp/sample.h b/polyp/sample.h
index 0494c7d..82c1461 100644
--- a/polyp/sample.h
+++ b/polyp/sample.h
@@ -51,11 +51,19 @@ enum pa_sample_format {
 #define PA_SAMPLE_S16NE PA_SAMPLE_S16BE
 /** 32 Bit IEEE floating point, native endian */
 #define PA_SAMPLE_FLOAT32NE PA_SAMPLE_FLOAT32BE
+/** Signed 16 Bit PCM reverse endian */
+#define PA_SAMPLE_S16RE PA_SAMPLE_S16LE
+/** 32 Bit IEEE floating point, reverse endian */
+#define PA_SAMPLE_FLOAT32RE PA_SAMPLE_FLOAT32LE
 #else
 /** Signed 16 Bit PCM, native endian */
 #define PA_SAMPLE_S16NE PA_SAMPLE_S16LE
 /** 32 Bit IEEE floating point, native endian */
 #define PA_SAMPLE_FLOAT32NE PA_SAMPLE_FLOAT32LE
+/** Signed 16 Bit PCM reverse endian */
+#define PA_SAMPLE_S16RE PA_SAMPLE_S16BE
+/** 32 Bit IEEE floating point, reverse endian */
+#define PA_SAMPLE_FLOAT32RE PA_SAMPLE_FLOAT32BE
 #endif
 
 /** A Shortcut for PA_SAMPLE_FLOAT32NE */

commit 9818d67ec27bbc39feaf4c1a1f3d35a029484cc9
Author: Pierre Ossman <ossman at cendio.se>
Date:   Mon Jan 9 14:39:40 2006 +0000

    Make the tagstruct handling safe on machines with alignment restrictions.
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/ossman@427 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/polyp/tagstruct.c b/polyp/tagstruct.c
index 59178bf..ff444e3 100644
--- a/polyp/tagstruct.c
+++ b/polyp/tagstruct.c
@@ -125,7 +125,8 @@ void pa_tagstruct_putu32(struct pa_tagstruct*t, uint32_t i) {
     assert(t);
     extend(t, 5);
     t->data[t->length] = TAG_U32;
-    *((uint32_t*) (t->data+t->length+1)) = htonl(i);
+    i = htonl(i);
+    memcpy(t->data+t->length+1, &i, 4);
     t->length += 5;
 }
 
@@ -138,12 +139,14 @@ void pa_tagstruct_putu8(struct pa_tagstruct*t, uint8_t c) {
 }
 
 void pa_tagstruct_put_sample_spec(struct pa_tagstruct *t, const struct pa_sample_spec *ss) {
+    uint32_t rate;
     assert(t && ss);
     extend(t, 7);
     t->data[t->length] = TAG_SAMPLE_SPEC;
     t->data[t->length+1] = (uint8_t) ss->format;
     t->data[t->length+2] = ss->channels;
-    *(uint32_t*) (t->data+t->length+3) = htonl(ss->rate);
+    rate = htonl(ss->rate);
+    memcpy(t->data+t->length+3, &rate, 4);
     t->length += 7;
 }
 
@@ -152,9 +155,10 @@ void pa_tagstruct_put_arbitrary(struct pa_tagstruct *t, const void *p, size_t le
 
     extend(t, 5+length);
     t->data[t->length] = TAG_ARBITRARY;
-    *((uint32_t*) (t->data+t->length+1)) = htonl(length);
     if (length)
         memcpy(t->data+t->length+5, p, length);
+    length = htonl(length);
+    memcpy(t->data+t->length+1, &length, 4);
     t->length += 5+length;
 }
 
@@ -166,29 +170,38 @@ void pa_tagstruct_put_boolean(struct pa_tagstruct*t, int b) {
 }
 
 void pa_tagstruct_put_timeval(struct pa_tagstruct*t, const struct timeval *tv) {
+    uint32_t tmp;
     assert(t);
     extend(t, 9);
     t->data[t->length] = TAG_TIMEVAL;
-    *((uint32_t*) (t->data+t->length+1)) = htonl(tv->tv_sec);
-    *((uint32_t*) (t->data+t->length+5)) = htonl(tv->tv_usec);
+    tmp = htonl(tv->tv_sec);
+    memcpy(t->data+t->length+1, &tmp, 4);
+    tmp = htonl(tv->tv_usec);
+    memcpy(t->data+t->length+5, &tmp, 4);
     t->length += 9;
 }
 
 void pa_tagstruct_put_usec(struct pa_tagstruct*t, pa_usec_t u) {
+    uint32_t tmp;
     assert(t);
     extend(t, 9);
     t->data[t->length] = TAG_USEC;
-    *((uint32_t*) (t->data+t->length+1)) = htonl((uint32_t) (u >> 32));
-    *((uint32_t*) (t->data+t->length+5)) = htonl((uint32_t) u);
+    tmp = htonl((uint32_t) (u >> 32));
+    memcpy(t->data+t->length+1, &tmp, 4);
+    tmp = htonl((uint32_t) u);
+    memcpy(t->data+t->length+5, &tmp, 4);
     t->length += 9;
 }
 
 void pa_tagstruct_putu64(struct pa_tagstruct*t, uint64_t u) {
+    uint32_t tmp;
     assert(t);
     extend(t, 9);
     t->data[t->length] = TAG_U64;
-    *((uint32_t*) (t->data+t->length+1)) = htonl((uint32_t) (u >> 32));
-    *((uint32_t*) (t->data+t->length+5)) = htonl((uint32_t) u);
+    tmp = htonl((uint32_t) (u >> 32));
+    memcpy(t->data+t->length+1, &tmp, 4);
+    tmp = htonl((uint32_t) u);
+    memcpy(t->data+t->length+5, &tmp, 4);
     t->length += 9;
 }
 
@@ -237,8 +250,9 @@ int pa_tagstruct_getu32(struct pa_tagstruct*t, uint32_t *i) {
 
     if (t->data[t->rindex] != TAG_U32)
         return -1;
-    
-    *i = ntohl(*((uint32_t*) (t->data+t->rindex+1)));
+
+    memcpy(i, t->data+t->rindex+1, 4);
+    *i = ntohl(*i);
     t->rindex += 5;
     return 0;
 }
@@ -268,13 +282,15 @@ int pa_tagstruct_get_sample_spec(struct pa_tagstruct *t, struct pa_sample_spec *
     
     ss->format = t->data[t->rindex+1];
     ss->channels = t->data[t->rindex+2];
-    ss->rate = ntohl(*(uint32_t*) (t->data+t->rindex+3));
+    memcpy(&ss->rate, t->data+t->rindex+3, 4);
+    ss->rate = ntohl(ss->rate);
     
     t->rindex += 7;
     return 0;
 }
 
 int pa_tagstruct_get_arbitrary(struct pa_tagstruct *t, const void **p, size_t length) {
+    uint32_t len;
     assert(t && p);
     
     if (t->rindex+5+length > t->length)
@@ -283,7 +299,8 @@ int pa_tagstruct_get_arbitrary(struct pa_tagstruct *t, const void **p, size_t le
     if (t->data[t->rindex] != TAG_ARBITRARY)
         return -1;
 
-    if (ntohl(*((uint32_t*) (t->data+t->rindex+1))) != length)
+    memcpy(&len, t->data+t->rindex+1, 4);
+    if (ntohl(len) != length)
         return -1;
 
     *p = t->data+t->rindex+5;
@@ -326,15 +343,18 @@ int pa_tagstruct_get_timeval(struct pa_tagstruct*t, struct timeval *tv) {
 
     if (t->data[t->rindex] != TAG_TIMEVAL)
         return -1;
-    
-    tv->tv_sec = ntohl(*((uint32_t*) (t->data+t->rindex+1)));
-    tv->tv_usec = ntohl(*((uint32_t*) (t->data+t->rindex+5)));
+
+    memcpy(&tv->tv_sec, t->data+t->rindex+1, 4);
+    tv->tv_sec = ntohl(tv->tv_sec);
+    memcpy(&tv->tv_usec, t->data+t->rindex+5, 4);
+    tv->tv_usec = ntohl(tv->tv_usec);
     t->rindex += 9;
     return 0;
     
 }
 
 int pa_tagstruct_get_usec(struct pa_tagstruct*t, pa_usec_t *u) {
+    uint32_t tmp;
     assert(t && u);
 
     if (t->rindex+9 > t->length)
@@ -343,13 +363,16 @@ int pa_tagstruct_get_usec(struct pa_tagstruct*t, pa_usec_t *u) {
     if (t->data[t->rindex] != TAG_USEC)
         return -1;
 
-    *u = (pa_usec_t) ntohl(*((uint32_t*) (t->data+t->rindex+1))) << 32;
-    *u |= (pa_usec_t) ntohl(*((uint32_t*) (t->data+t->rindex+5)));
+    memcpy(&tmp, t->data+t->rindex+1, 4);
+    *u = (pa_usec_t) ntohl(tmp) << 32;
+    memcpy(&tmp, t->data+t->rindex+5, 4);
+    *u |= (pa_usec_t) ntohl(tmp);
     t->rindex +=9;
     return 0;
 }
 
 int pa_tagstruct_getu64(struct pa_tagstruct*t, uint64_t *u) {
+    uint32_t tmp;
     assert(t && u);
 
     if (t->rindex+9 > t->length)
@@ -358,8 +381,10 @@ int pa_tagstruct_getu64(struct pa_tagstruct*t, uint64_t *u) {
     if (t->data[t->rindex] != TAG_U64)
         return -1;
 
-    *u = (uint64_t) ntohl(*((uint32_t*) (t->data+t->rindex+1))) << 32;
-    *u |= (uint64_t) ntohl(*((uint32_t*) (t->data+t->rindex+5)));
+    memcpy(&tmp, t->data+t->rindex+1, 4);
+    *u = (pa_usec_t) ntohl(tmp) << 32;
+    memcpy(&tmp, t->data+t->rindex+5, 4);
+    *u |= (pa_usec_t) ntohl(tmp);
     t->rindex +=9;
     return 0;
 }

commit 5fcbf04f5b95cccc61b2986a6582fa475e4d9c8b
Author: Pierre Ossman <ossman at cendio.se>
Date:   Mon Jan 9 16:50:39 2006 +0000

    Condense winsock includes and defines into one header.
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/ossman@428 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/polyp/Makefile.am b/polyp/Makefile.am
index 5f57142..ab7dfe5 100644
--- a/polyp/Makefile.am
+++ b/polyp/Makefile.am
@@ -335,6 +335,7 @@ libpolyp_ at PA_MAJORMINOR@_la_SOURCES = \
 		tagstruct.c tagstruct.h \
 		typeid.c typeid.h \
 		util.c util.h \
+		winsock.h \
 		xmalloc.c xmalloc.h
 
 if HAVE_X11
@@ -476,6 +477,7 @@ libpolypcore_la_SOURCES = \
 		tokenizer.c tokenizer.h \
 		typeid.c typeid.h \
 		util.c util.h \
+		winsock.h \
 		xmalloc.c xmalloc.h
 
 libpolypcore_la_CPPFLAGS = $(AM_CPPFLAGS)
diff --git a/polyp/iochannel.c b/polyp/iochannel.c
index 08a4e36..1a0dbf9 100644
--- a/polyp/iochannel.c
+++ b/polyp/iochannel.c
@@ -28,9 +28,7 @@
 #include <fcntl.h>
 #include <unistd.h>
 
-#ifdef HAVE_WINSOCK2_H
-#include <winsock2.h>
-#endif
+#include "winsock.h"
 
 #include "iochannel.h"
 #include "util.h"
diff --git a/polyp/main.c b/polyp/main.c
index 437f0a4..e481fce 100644
--- a/polyp/main.c
+++ b/polyp/main.c
@@ -42,15 +42,13 @@
 #include <sys/ioctl.h>
 #endif
 
-#ifdef HAVE_WINSOCK2_H
-#include <winsock2.h>
-#endif
-
 #ifdef HAVE_LIBWRAP
 #include <syslog.h>
 #include <tcpd.h>
 #endif
 
+#include "winsock.h"
+
 #include "core.h"
 #include "mainloop.h"
 #include "module.h"
diff --git a/polyp/mainloop.c b/polyp/mainloop.c
index 9cfd539..ada74af 100644
--- a/polyp/mainloop.c
+++ b/polyp/mainloop.c
@@ -38,9 +38,7 @@
 #include "poll.h"
 #endif
 
-#ifdef HAVE_WINSOCK2_H
-#include <winsock2.h>
-#endif
+#include "winsock.h"
 
 #include "mainloop.h"
 #include "util.h"
diff --git a/polyp/module-protocol-stub.c b/polyp/module-protocol-stub.c
index 8c06a61..141eadd 100644
--- a/polyp/module-protocol-stub.c
+++ b/polyp/module-protocol-stub.c
@@ -40,12 +40,7 @@
 #include <netinet/in.h>
 #endif
 
-#ifdef HAVE_WINSOCK2_H
-#include <winsock2.h>
-#endif
-#ifdef HAVE_WS2TCPIP_H
-#include <ws2tcpip.h>
-#endif
+#include "winsock.h"
 
 #include "module.h"
 #include "socket-server.h"
diff --git a/polyp/poll.c b/polyp/poll.c
index 7c25f34..cb7e3e7 100644
--- a/polyp/poll.c
+++ b/polyp/poll.c
@@ -36,16 +36,7 @@
 #include <sys/select.h>
 #endif
 
-#ifdef HAVE_WINSOCK2_H
-#include <winsock2.h>
-
-#define EBADF           WSAEBADF
-#define ESHUTDOWN       WSAESHUTDOWN
-#define ECONNRESET      WSAECONNRESET
-#define ECONNABORTED    WSAECONNABORTED
-#define ENETRESET       WSAENETRESET
-
-#endif /* HAVE_WINSOCK2_H */
+#include "winsock.h"
 
 #ifndef HAVE_SYS_POLL_H
 
diff --git a/polyp/polyplib-context.c b/polyp/polyplib-context.c
index da91995..f97d9b8 100644
--- a/polyp/polyplib-context.c
+++ b/polyp/polyplib-context.c
@@ -45,12 +45,7 @@
 #include <netdb.h>
 #endif
 
-#ifdef HAVE_WINSOCK2_H
-#include <winsock2.h>
-#define ETIMEDOUT       WSAETIMEDOUT
-#define ECONNREFUSED    WSAECONNREFUSED
-#define EHOSTUNREACH    WSAEHOSTUNREACH
-#endif
+#include "winsock.h"
 
 #include "polyplib-internal.h"
 #include "polyplib-context.h"
diff --git a/polyp/pstream.c b/polyp/pstream.c
index 607b0c1..6f98328 100644
--- a/polyp/pstream.c
+++ b/polyp/pstream.c
@@ -32,9 +32,7 @@
 #include <netinet/in.h>
 #endif
 
-#ifdef HAVE_WINSOCK2_H
-#include <winsock2.h>
-#endif
+#include "winsock.h"
 
 #include "pstream.h"
 #include "queue.h"
diff --git a/polyp/socket-client.c b/polyp/socket-client.c
index 6d8cb2a..51134b8 100644
--- a/polyp/socket-client.c
+++ b/polyp/socket-client.c
@@ -48,19 +48,12 @@
 #include <netdb.h>
 #endif
 
-#ifdef HAVE_WINSOCK2_H
-#include <winsock2.h>
-#define EINPROGRESS     WSAEINPROGRESS
-#define ETIMEDOUT       WSAETIMEDOUT
-#endif
-#ifdef HAVE_WS2TCPIP_H
-#include <ws2tcpip.h>
-#endif
-
 #ifdef HAVE_LIBASYNCNS
 #include <asyncns.h>
 #endif
 
+#include "winsock.h"
+
 #include "socket-client.h"
 #include "socket-util.h"
 #include "util.h"
diff --git a/polyp/socket-server.c b/polyp/socket-server.c
index c27979d..18122f3 100644
--- a/polyp/socket-server.c
+++ b/polyp/socket-server.c
@@ -48,17 +48,12 @@
 #include <netinet/in.h>
 #endif
 
-#ifdef HAVE_WINSOCK2_H
-#include <winsock2.h>
-#endif
-#ifdef HAVE_WS2TCPIP_H
-#include <ws2tcpip.h>
-#endif
-
 #ifdef HAVE_LIBWRAP
 #include <tcpd.h>
 #endif
 
+#include "winsock.h"
+
 #include "socket-server.h"
 #include "socket-util.h"
 #include "xmalloc.h"
diff --git a/polyp/socket-util.c b/polyp/socket-util.c
index 699b28c..381502b 100644
--- a/polyp/socket-util.c
+++ b/polyp/socket-util.c
@@ -57,10 +57,7 @@
 #include <netdb.h>
 #endif
 
-#ifdef HAVE_WINSOCK2_H
-#include <winsock2.h>
-#define ETIMEDOUT       WSAETIMEDOUT
-#endif
+#include "winsock.h"
 
 #include "socket-util.h"
 #include "util.h"
diff --git a/polyp/tagstruct.c b/polyp/tagstruct.c
index ff444e3..1e44f8e 100644
--- a/polyp/tagstruct.c
+++ b/polyp/tagstruct.c
@@ -33,9 +33,7 @@
 #include <netinet/in.h>
 #endif
 
-#ifdef HAVE_WINSOCK2_H
-#include <winsock2.h>
-#endif
+#include "winsock.h"
 
 #include "tagstruct.h"
 #include "xmalloc.h"
diff --git a/polyp/util.c b/polyp/util.c
index ff27430..f1f4b2c 100644
--- a/polyp/util.c
+++ b/polyp/util.c
@@ -59,13 +59,6 @@
 #include <windows.h>
 #endif
 
-#ifdef HAVE_WINSOCK2_H
-#include <winsock2.h>
-#endif
-#ifdef HAVE_WS2TCPIP_H
-#include <ws2tcpip.h>
-#endif
-
 #include <samplerate.h>
 
 #ifdef HAVE_PWD_H
@@ -75,6 +68,8 @@
 #include <grp.h>
 #endif
 
+#include "winsock.h"
+
 #include "util.h"
 #include "xmalloc.h"
 #include "log.h"
diff --git a/polyp/winsock.h b/polyp/winsock.h
new file mode 100644
index 0000000..60fac87
--- /dev/null
+++ b/polyp/winsock.h
@@ -0,0 +1,23 @@
+#ifndef foowinsockhfoo
+#define foowinsockhfoo
+
+#ifdef HAVE_WINSOCK2_H
+#include <winsock2.h>
+
+#define EBADF           WSAEBADF
+#define ESHUTDOWN       WSAESHUTDOWN
+#define ECONNRESET      WSAECONNRESET
+#define ECONNABORTED    WSAECONNABORTED
+#define ENETRESET       WSAENETRESET
+#define EINPROGRESS     WSAEINPROGRESS
+#define ETIMEDOUT       WSAETIMEDOUT
+#define ECONNREFUSED    WSAECONNREFUSED
+#define EHOSTUNREACH    WSAEHOSTUNREACH
+
+#endif
+
+#ifdef HAVE_WS2TCPIP_H
+#include <ws2tcpip.h>
+#endif
+
+#endif

commit 8258146625050d242b9bc3dc5f175985feb5e2bd
Author: Pierre Ossman <ossman at cendio.se>
Date:   Mon Jan 9 16:56:41 2006 +0000

    Generalise lstat fallback.
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/ossman@429 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/configure.ac b/configure.ac
index 7737d17..8030e6a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -186,6 +186,7 @@ AC_CHECK_FUNCS([ctime_r usleep])
 
 # BSD
 AC_CHECK_LIB([socket], [connect])
+AC_CHECK_FUNCS([lstat])
 
 # Non-standard
 
diff --git a/polyp/util.c b/polyp/util.c
index f1f4b2c..b2f61d5 100644
--- a/polyp/util.c
+++ b/polyp/util.c
@@ -139,10 +139,10 @@ int pa_make_secure_dir(const char* dir) {
         if (errno != EEXIST)
             return -1;
 
-#ifdef OS_IS_WIN32
-    if (stat(dir, &st) < 0)
-#else
+#ifdef HAVE_LSTAT
     if (lstat(dir, &st) < 0)
+#else
+    if (stat(dir, &st) < 0)
 #endif
         goto fail;
 

commit 160d886c0d8f783765d06662d87c01a3603e1c4c
Author: Pierre Ossman <ossman at cendio.se>
Date:   Mon Jan 9 16:57:42 2006 +0000

    Merge with trunk.
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/ossman@430 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/polyp/polyplib-stream.c b/polyp/polyplib-stream.c
index c7c40c0..7058b54 100644
--- a/polyp/polyplib-stream.c
+++ b/polyp/polyplib-stream.c
@@ -413,7 +413,7 @@ static void stream_get_latency_info_callback(struct pa_pdispatch *pd, uint32_t c
     } else {
         pa_gettimeofday(&now);
         
-        if (pa_timeval_cmp(&local, &remote) < 0 && pa_timeval_cmp(&remote, &now)) {
+        if (pa_timeval_cmp(&local, &remote) <= 0 && pa_timeval_cmp(&remote, &now) <= 0) {
             /* local and remote seem to have synchronized clocks */
             
             if (o->stream->direction == PA_STREAM_PLAYBACK)

commit d3cb1448b4765705ed14aee5b40b87459a4e302d
Author: Pierre Ossman <ossman at cendio.se>
Date:   Mon Jan 9 16:59:12 2006 +0000

    Update comment for pa_lock_fd() to reflect that locks are mandatory
    on Windows.
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/ossman@431 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/polyp/util.c b/polyp/util.c
index b2f61d5..569412d 100644
--- a/polyp/util.c
+++ b/polyp/util.c
@@ -810,7 +810,8 @@ int pa_uid_in_group(const char *name, gid_t *gid) {
 
 #endif
 
-/* Lock or unlock a file entirely. (advisory) */
+/* Lock or unlock a file entirely.
+  (advisory on UNIX, mandatory on Windows) */
 int pa_lock_fd(int fd, int b) {
 #ifdef F_SETLKW
     struct flock flock;

commit 76bc56cf3b50e5d446046536f22a3dfd372f11c7
Author: Pierre Ossman <ossman at cendio.se>
Date:   Mon Jan 9 17:14:30 2006 +0000

    Put inet_ntop() emulation in a seperate file.
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/ossman@432 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/polyp/Makefile.am b/polyp/Makefile.am
index ab7dfe5..22e8da3 100644
--- a/polyp/Makefile.am
+++ b/polyp/Makefile.am
@@ -540,7 +540,9 @@ libprotocol_simple_la_SOURCES = protocol-simple.c protocol-simple.h
 libprotocol_simple_la_LDFLAGS = -avoid-version
 libprotocol_simple_la_LIBADD = $(AM_LIBADD) libpolypcore.la libsocket-server.la libiochannel.la
 
-libsocket_server_la_SOURCES = socket-server.c socket-server.h
+libsocket_server_la_SOURCES = \
+		inet_ntop.c inet_ntop.h \
+		socket-server.c socket-server.h
 libsocket_server_la_LDFLAGS = -avoid-version
 libsocket_server_la_LIBADD = $(AM_LIBADD) libpolypcore.la libiochannel.la libsocket-util.la $(LIBWRAP_LIBS) $(WINSOCK_LIBS)
 
diff --git a/polyp/inet_ntop.c b/polyp/inet_ntop.c
new file mode 100644
index 0000000..19f29f8
--- /dev/null
+++ b/polyp/inet_ntop.c
@@ -0,0 +1,78 @@
+/* $Id: inet_ntop.c 428 2006-01-09 16:50:39Z ossman $ */
+
+/***
+  This file is part of polypaudio.
+ 
+  polypaudio 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.
+ 
+  polypaudio 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 polypaudio; 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>
+
+#ifndef HAVE_INET_NTOP
+
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+
+#include "winsock.h"
+
+#include "inet_ntop.h"
+
+const char *inet_ntop(int af, const void *src, char *dst, socklen_t cnt) {
+    struct in_addr *in = (struct in_addr*)src;
+    struct in6_addr *in6 = (struct in6_addr*)src;
+
+    assert(src && dst);
+
+    switch (af) {
+    case AF_INET:
+        snprintf(dst, cnt, "%d.%d.%d.%d",
+#ifdef WORDS_BIGENDIAN
+            (int)(in->s_addr >> 24) & 0xff,
+            (int)(in->s_addr >> 16) & 0xff,
+            (int)(in->s_addr >>  8) & 0xff,
+            (int)(in->s_addr >>  0) & 0xff);
+#else
+            (int)(in->s_addr >>  0) & 0xff,
+            (int)(in->s_addr >>  8) & 0xff,
+            (int)(in->s_addr >> 16) & 0xff,
+            (int)(in->s_addr >> 24) & 0xff);
+#endif
+        break;
+    case AF_INET6:
+        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],
+            in6->s6_addr[ 6] << 8 | in6->s6_addr[ 7],
+            in6->s6_addr[ 8] << 8 | in6->s6_addr[ 9],
+            in6->s6_addr[10] << 8 | in6->s6_addr[11],
+            in6->s6_addr[12] << 8 | in6->s6_addr[13],
+            in6->s6_addr[14] << 8 | in6->s6_addr[15]);
+        break;
+    default:
+        errno = EAFNOSUPPORT;
+        return NULL;
+    }
+
+    return dst;
+}
+
+#endif /* INET_NTOP */
diff --git a/polyp/inet_ntop.h b/polyp/inet_ntop.h
new file mode 100644
index 0000000..11bc611
--- /dev/null
+++ b/polyp/inet_ntop.h
@@ -0,0 +1,6 @@
+#ifndef fooinet_ntophfoo
+#define fooinet_ntophfoo
+
+const char *inet_ntop(int af, const void *src, char *dst, socklen_t cnt);
+
+#endif
diff --git a/polyp/socket-server.c b/polyp/socket-server.c
index 18122f3..a78f04c 100644
--- a/polyp/socket-server.c
+++ b/polyp/socket-server.c
@@ -52,6 +52,10 @@
 #include <tcpd.h>
 #endif
 
+#ifndef HAVE_INET_NTOP
+#include "inet_ntop.h"
+#endif
+
 #include "winsock.h"
 
 #include "socket-server.h"
@@ -362,22 +366,10 @@ char *pa_socket_server_get_address(struct pa_socket_server *s, char *c, size_t l
             } else {
                 char ip[INET6_ADDRSTRLEN];
                 
-#ifdef HAVE_INET_NTOP
                 if (!inet_ntop(AF_INET6, &sa.sin6_addr, ip, sizeof(ip))) {
                     pa_log(__FILE__": inet_ntop() failed: %s\n", strerror(errno));
                     return NULL;
                 }
-#else
-                snprintf(ip, INET6_ADDRSTRLEN, "%x:%x:%x:%x:%x:%x:%x:%x",
-                    sa.sin6_addr.s6_addr[ 0] << 8 | sa.sin6_addr.s6_addr[ 1],
-                    sa.sin6_addr.s6_addr[ 2] << 8 | sa.sin6_addr.s6_addr[ 3],
-                    sa.sin6_addr.s6_addr[ 4] << 8 | sa.sin6_addr.s6_addr[ 5],
-                    sa.sin6_addr.s6_addr[ 6] << 8 | sa.sin6_addr.s6_addr[ 7],
-                    sa.sin6_addr.s6_addr[ 8] << 8 | sa.sin6_addr.s6_addr[ 9],
-                    sa.sin6_addr.s6_addr[10] << 8 | sa.sin6_addr.s6_addr[11],
-                    sa.sin6_addr.s6_addr[12] << 8 | sa.sin6_addr.s6_addr[13],
-                    sa.sin6_addr.s6_addr[14] << 8 | sa.sin6_addr.s6_addr[15]);
-#endif
                 
                 snprintf(c, l, "tcp6:[%s]:%u", ip, (unsigned) ntohs(sa.sin6_port));
             }
@@ -409,25 +401,10 @@ char *pa_socket_server_get_address(struct pa_socket_server *s, char *c, size_t l
             } else {
                 char ip[INET_ADDRSTRLEN];
 
-#ifdef HAVE_INET_NTOP
                 if (!inet_ntop(AF_INET, &sa.sin_addr, ip, sizeof(ip))) {
                     pa_log(__FILE__": inet_ntop() failed: %s\n", strerror(errno));
                     return NULL;
                 }
-#else /* HAVE_INET_NTOP */
-                snprintf(ip, INET_ADDRSTRLEN, "%d.%d.%d.%d",
-#ifdef WORDS_BIGENDIAN
-                    (int)(sa.sin_addr.s_addr >> 24) & 0xff,
-                    (int)(sa.sin_addr.s_addr >> 16) & 0xff,
-                    (int)(sa.sin_addr.s_addr >>  8) & 0xff,
-                    (int)(sa.sin_addr.s_addr >>  0) & 0xff);
-#else
-                    (int)(sa.sin_addr.s_addr >>  0) & 0xff,
-                    (int)(sa.sin_addr.s_addr >>  8) & 0xff,
-                    (int)(sa.sin_addr.s_addr >> 16) & 0xff,
-                    (int)(sa.sin_addr.s_addr >> 24) & 0xff);
-#endif
-#endif /* HAVE_INET_NTOP */
                 
                 snprintf(c, l, "tcp:[%s]:%u", ip, (unsigned) ntohs(sa.sin_port));
 

commit f5a2cf1e86c1b67c1bc8ae5e03f13b9b3d19eefb
Author: Pierre Ossman <ossman at cendio.se>
Date:   Tue Jan 10 07:50:50 2006 +0000

    getopt_long resides in libiberty on many platforms.
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/ossman@433 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/configure.ac b/configure.ac
index 8030e6a..815629f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -192,6 +192,7 @@ AC_CHECK_FUNCS([lstat])
 
 AC_CHECK_FUNCS(setresuid)
 AC_CHECK_FUNCS(setreuid)
+AC_CHECK_LIB([iberty], [getopt_long])
 
 #### POSIX threads ####
 

commit ff4cc6273d5db325433dbe01d4c7af242951c69e
Author: Pierre Ossman <ossman at cendio.se>
Date:   Tue Jan 10 08:35:14 2006 +0000

    Move library checks to a separate section and make sure it's before
    function checks. It could miss functions because they are hidden in
    extra libs otherwise.
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/ossman@434 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/configure.ac b/configure.ac
index 815629f..d450f4a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -162,16 +162,26 @@ AM_CONDITIONAL(HAVE_SIGXCPU, test "x$HAVE_SIGXCPU" = "x1")
 AC_CHECK_DEFINE([INADDR_NONE], [netinet/in.h], [],
     [AC_DEFINE([INADDR_NONE],  [0xffffffff], [Define INADDR_NONE if not found in <netinet/in.h>])])
 
-#### Check for functions ####
+#### Check for libs ####
 
 # ISO
 AC_CHECK_LIB([m], [pow])
 
 # POSIX
+AC_CHECK_LIB([rt], [sched_setscheduler])
+
+# BSD
+AC_CHECK_LIB([socket], [connect])
+
+# Non-standard
+AC_CHECK_LIB([iberty], [getopt_long])
+
+#### Check for functions ####
+
+# POSIX
 AC_FUNC_FORK
 AC_FUNC_GETGROUPS
 AC_FUNC_SELECT_ARGTYPES
-AC_CHECK_LIB([rt], [sched_setscheduler])
 AC_CHECK_FUNCS([getaddrinfo getgrgid_r getpwuid_r gettimeofday getuid \
     inet_ntop nanosleep setpgid setsid sigaction sleep])
 AC_CHECK_FUNCS([mkfifo], [HAVE_MKFIFO=1], [HAVE_MKFIFO=0])
@@ -185,14 +195,12 @@ AC_CHECK_FUNCS([readlink])
 AC_CHECK_FUNCS([ctime_r usleep])
 
 # BSD
-AC_CHECK_LIB([socket], [connect])
 AC_CHECK_FUNCS([lstat])
 
 # Non-standard
 
 AC_CHECK_FUNCS(setresuid)
 AC_CHECK_FUNCS(setreuid)
-AC_CHECK_LIB([iberty], [getopt_long])
 
 #### POSIX threads ####
 

commit 5e5808ab08cacb7bff8ab2df584f2d0f3af0fca9
Author: Pierre Ossman <ossman at cendio.se>
Date:   Tue Jan 10 09:13:48 2006 +0000

    Static libs bork the creation of dlls and AC_CHECK_LIB isn't very bright,
    so we have to do a test first to see if getopt_long() is included in the
    system libs.
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/ossman@435 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/configure.ac b/configure.ac
index d450f4a..1a002e5 100644
--- a/configure.ac
+++ b/configure.ac
@@ -174,7 +174,10 @@ AC_CHECK_LIB([rt], [sched_setscheduler])
 AC_CHECK_LIB([socket], [connect])
 
 # Non-standard
-AC_CHECK_LIB([iberty], [getopt_long])
+
+# This magic is needed so we do not needlessly add static libs to the win32
+# build, disabling its ability to make dlls.
+AC_CHECK_FUNCS([getopt_long], [], [AC_CHECK_LIB([iberty], [getopt_long])])
 
 #### Check for functions ####
 

commit 357ab88ab55ede0e5a1173ce7b7a727ba3204087
Author: Pierre Ossman <ossman at cendio.se>
Date:   Tue Jan 10 09:14:41 2006 +0000

    Make sure socklen_t is defined.
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/ossman@436 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/polyp/inet_ntop.h b/polyp/inet_ntop.h
index 11bc611..7fb67b4 100644
--- a/polyp/inet_ntop.h
+++ b/polyp/inet_ntop.h
@@ -1,6 +1,12 @@
 #ifndef fooinet_ntophfoo
 #define fooinet_ntophfoo
 
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+
+#include "winsock.h"
+
 const char *inet_ntop(int af, const void *src, char *dst, socklen_t cnt);
 
 #endif

commit ba06340ab8476733a0b84d0b97fa04a029cf2713
Author: Pierre Ossman <ossman at cendio.se>
Date:   Tue Jan 10 09:15:13 2006 +0000

    Add some required headers.
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/ossman@437 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/polyp/inet_ntop.c b/polyp/inet_ntop.c
index 19f29f8..ac2b529 100644
--- a/polyp/inet_ntop.c
+++ b/polyp/inet_ntop.c
@@ -24,6 +24,8 @@
 #endif
 
 #include <stdio.h>
+#include <errno.h>
+#include <assert.h>
 
 #ifndef HAVE_INET_NTOP
 
diff --git a/polyp/poll.c b/polyp/poll.c
index cb7e3e7..6a260da 100644
--- a/polyp/poll.c
+++ b/polyp/poll.c
@@ -32,6 +32,8 @@
 #include <config.h>
 #endif
 
+#include <errno.h>
+
 #ifdef HAVE_SYS_SELECT_H
 #include <sys/select.h>
 #endif

commit 0a9abdd9d141b12a475c43bf924eb7569debe9a5
Author: Pierre Ossman <ossman at cendio.se>
Date:   Tue Jan 10 09:15:56 2006 +0000

    Unfortunately Windows has two different values for EBADF depending on
    if it's a file or a socket. We'll have to deal with these as they show
    up.
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/ossman@438 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/polyp/winsock.h b/polyp/winsock.h
index 60fac87..89ef7ba 100644
--- a/polyp/winsock.h
+++ b/polyp/winsock.h
@@ -4,7 +4,6 @@
 #ifdef HAVE_WINSOCK2_H
 #include <winsock2.h>
 
-#define EBADF           WSAEBADF
 #define ESHUTDOWN       WSAESHUTDOWN
 #define ECONNRESET      WSAECONNRESET
 #define ECONNABORTED    WSAECONNABORTED

commit abdf9b1c3fb371637c73fa635d089178dea5d902
Author: Pierre Ossman <ossman at cendio.se>
Date:   Tue Jan 10 09:16:20 2006 +0000

    Add needed error code.
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/ossman@439 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/polyp/winsock.h b/polyp/winsock.h
index 89ef7ba..b1e0f7d 100644
--- a/polyp/winsock.h
+++ b/polyp/winsock.h
@@ -9,6 +9,7 @@
 #define ECONNABORTED    WSAECONNABORTED
 #define ENETRESET       WSAENETRESET
 #define EINPROGRESS     WSAEINPROGRESS
+#define EAFNOSUPPORT    WSAEAFNOSUPPORT
 #define ETIMEDOUT       WSAETIMEDOUT
 #define ECONNREFUSED    WSAECONNREFUSED
 #define EHOSTUNREACH    WSAEHOSTUNREACH

commit 11c6cac3241bf7bc647f3e8b7da751e0c88982ea
Author: Pierre Ossman <ossman at cendio.se>
Date:   Tue Jan 10 09:16:39 2006 +0000

    buf is needed on Windows aswell.
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/ossman@440 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/polyp/util.c b/polyp/util.c
index 569412d..26d7120 100644
--- a/polyp/util.c
+++ b/polyp/util.c
@@ -321,9 +321,9 @@ char *pa_vsprintf_malloc(const char *format, va_list ap) {
 /* Return the current username in the specified string buffer. */
 char *pa_get_user_name(char *s, size_t l) {
     char *p;
+    char buf[1024];
 
 #ifdef HAVE_PWD_H
-    char buf[1024];
     struct passwd pw, *r;
 #endif
 

commit d429222476ce224a86428f8d0527e61a672edf2b
Author: Pierre Ossman <ossman at cendio.se>
Date:   Tue Jan 10 12:37:41 2006 +0000

    Accidental use of a swapped int.
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/ossman@441 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/polyp/tagstruct.c b/polyp/tagstruct.c
index 1e44f8e..1ff09cd 100644
--- a/polyp/tagstruct.c
+++ b/polyp/tagstruct.c
@@ -149,14 +149,15 @@ void pa_tagstruct_put_sample_spec(struct pa_tagstruct *t, const struct pa_sample
 }
 
 void pa_tagstruct_put_arbitrary(struct pa_tagstruct *t, const void *p, size_t length) {
+    uint32_t tmp;
     assert(t && p);
 
     extend(t, 5+length);
     t->data[t->length] = TAG_ARBITRARY;
+    tmp = htonl(length);
+    memcpy(t->data+t->length+1, &tmp, 4);
     if (length)
         memcpy(t->data+t->length+5, p, length);
-    length = htonl(length);
-    memcpy(t->data+t->length+1, &length, 4);
     t->length += 5+length;
 }
 

commit 1015ea42413eb14b1a027a665df6af12344d097d
Author: Pierre Ossman <ossman at cendio.se>
Date:   Tue Jan 10 12:45:11 2006 +0000

    Store previous reported time in order to assure a monotonic clock.
    
    This is a resurrection of a feature previously removed. The new version
    is without the race condition of the original one.
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/ossman@442 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/polyp/polyplib-internal.h b/polyp/polyplib-internal.h
index 9417430..8677c81 100644
--- a/polyp/polyplib-internal.h
+++ b/polyp/polyplib-internal.h
@@ -92,6 +92,8 @@ struct pa_stream {
     enum pa_stream_direction direction;
     uint32_t requested_bytes;
     uint64_t counter;
+    pa_usec_t previous_time;
+    pa_usec_t previous_ipol_time;
     enum pa_stream_state state;
     struct pa_mcalign *mcalign;
 
diff --git a/polyp/polyplib-stream.c b/polyp/polyplib-stream.c
index 7058b54..b6a091b 100644
--- a/polyp/polyplib-stream.c
+++ b/polyp/polyplib-stream.c
@@ -65,6 +65,8 @@ struct pa_stream *pa_stream_new(struct pa_context *c, const char *name, const st
     s->mcalign = pa_mcalign_new(pa_frame_size(ss), c->memblock_stat);
 
     s->counter = 0;
+    s->previous_time = 0;
+    s->previous_ipol_time = 0;
 
     s->corked = 0;
     s->interpolate = 0;
@@ -697,6 +699,11 @@ pa_usec_t pa_stream_get_time(struct pa_stream *s, const struct pa_latency_info *
         }
     }
 
+    if (usec < s->previous_time)
+        usec = s->previous_time;
+
+    s->previous_time = usec;
+
     return usec;
 }
 
@@ -756,6 +763,11 @@ pa_usec_t pa_stream_get_interpolated_time(struct pa_stream *s) {
             usec = s->ipol_usec + pa_timeval_age(&s->ipol_timestamp);
     }
     
+    if (usec < s->previous_ipol_time)
+        usec = s->previous_ipol_time;
+
+    s->previous_ipol_time = usec;
+
     return usec;
 }
 

commit 29118f50cb848076c89aee54829f4da6d7b8df77
Author: Pierre Ossman <ossman at cendio.se>
Date:   Tue Jan 10 13:19:03 2006 +0000

    Make sure the caps header check can also be disabled.
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/ossman@443 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/configure.ac b/configure.ac
index 1a002e5..e5e03d0 100644
--- a/configure.ac
+++ b/configure.ac
@@ -121,7 +121,7 @@ AC_HEADER_STDC
 # POSIX
 AC_CHECK_HEADERS([arpa/inet.h glob.h grp.h netdb.h netinet/in.h \
     netinet/in_systm.h netinet/ip.h netinet/tcp.h pwd.h sched.h \
-    sys/capability.h sys/resource.h sys/select.h sys/socket.h sys/wait.h \
+    sys/resource.h sys/select.h sys/socket.h sys/wait.h \
     syslog.h])
 AC_CHECK_HEADERS([regex.h], [HAVE_REGEX=1], [HAVE_REGEX=0])
 AC_CHECK_HEADERS([sys/un.h], [HAVE_AF_UNIX=1], [HAVE_AF_UNIX=0])
@@ -239,6 +239,7 @@ AC_ARG_WITH(
 
 if test "x${with_caps}" != "xno"; then
     AC_CHECK_LIB(cap, cap_init, [CAP_LIBS='-lcap'], [CAP_LIBS=''])
+    AC_CHECK_HEADERS([sys/capability.h])
 fi
 AC_SUBST(CAP_LIBS)
 

commit 34e81ffb350540004b3aa9f5614f6b511ab96b37
Author: Pierre Ossman <ossman at cendio.se>
Date:   Tue Jan 10 16:56:59 2006 +0000

    Handle Windows paths when normalizing authkey path.
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/ossman@444 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/polyp/authkey.c b/polyp/authkey.c
index 35d97b7..969f09d 100644
--- a/polyp/authkey.c
+++ b/polyp/authkey.c
@@ -128,12 +128,20 @@ int pa_authkey_load(const char *path, void *data, size_t length) {
 static const char *normalize_path(const char *fn, char *s, size_t l) {
     assert(fn && s && l > 0);
 
+#ifndef OS_IS_WIN32
     if (fn[0] != '/') {
+#else
+    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);
+#else
+        snprintf(s, l, "%s\\%s", homedir, fn);
+#endif
         return s;
     }
 

commit 00da37f2c448096cdd54481b072db47b2f253141
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Jun 11 12:08:37 2007 +0000

    Merge HUGE set of changes temporarily into a branch, to allow me to move them from one machine to another (lock-free and stuff)
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1469 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/Makefile.am b/src/Makefile.am
index d90361f..eab465c 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -78,13 +78,15 @@ 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
 
 ###################################
@@ -219,7 +221,9 @@ noinst_PROGRAMS = \
 		hook-list-test \
 		memblock-test \
 		thread-test \
-		flist-test
+		flist-test \
+		asyncq-test \
+		asyncmsgq-test
 
 if HAVE_SIGXCPU
 noinst_PROGRAMS += \
@@ -274,13 +278,21 @@ 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 pulsecore/thread-posix.c pulsecore/thread.h pulsecore/asyncq.c pulsecore/asyncq.h pulsecore/core-util.c pulsecore/core-util.h pulse/xmalloc.c pulse/xmalloc.h pulsecore/log.h pulsecore/log.c pulsecore/core-error.h pulsecore/core-error.c pulsecore/once-posix.c pulsecore/once.h pulsecore/mutex-posix.c pulsecore/mutex.h pulse/utf8.c pulse/utf8.h pulse/util.h pulse/util.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 pulsecore/thread-posix.c pulsecore/thread.h pulsecore/asyncq.c pulsecore/asyncq.h pulsecore/asyncmsgq.c pulsecore/asyncmsgq.h pulsecore/core-util.c pulsecore/core-util.h pulse/xmalloc.c pulse/xmalloc.h pulsecore/log.h pulsecore/log.c pulsecore/core-error.h pulsecore/core-error.c pulsecore/once-posix.c pulsecore/once.h pulsecore/mutex-posix.c pulsecore/mutex.h pulse/utf8.c pulse/utf8.h pulse/util.h pulse/util.c pulsecore/semaphore.h pulsecore/semaphore-posix.c pulsecore/flist.h pulsecore/flist.c
+asyncmsgq_test_CFLAGS = $(AM_CFLAGS)
+asyncmsgq_test_LDADD = $(AM_LDADD) #libpulsecore.la
+asyncmsgq_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
@@ -455,6 +467,9 @@ 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 \
 		$(PA_THREAD_OBJS)
 
 if OS_IS_WIN32
@@ -567,6 +582,7 @@ pulsecoreinclude_HEADERS = \
 		pulsecore/refcnt.h \
 		pulsecore/mutex.h \
 		pulsecore/thread.h \
+		pulsecore/semaphore.h \
 		pulsecore/once.h
 
 lib_LTLIBRARIES += libpulsecore.la
@@ -636,6 +652,8 @@ 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/anotify.c pulsecore/anotify.h \
 		$(PA_THREAD_OBJS)
 
 if OS_IS_WIN32
@@ -851,34 +869,34 @@ 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-null-sink.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-esound-sink.la \
+#		module-http-protocol-tcp.la \
+#		module-detect.la \
+#		module-volume-restore.la \
+#		module-rescue-streams.la
 
 # See comment at librtp.la above
-if !OS_IS_WIN32
-modlibexec_LTLIBRARIES += \
-		module-rtp-send.la \
-		module-rtp-recv.la
-endif
+#if !OS_IS_WIN32
+#modlibexec_LTLIBRARIES += \
+#		module-rtp-send.la \
+#		module-rtp-recv.la
+#endif
 
 if HAVE_AF_UNIX
 modlibexec_LTLIBRARIES += \
 		module-cli-protocol-unix.la \
-		module-simple-protocol-unix.la \
-		module-esound-protocol-unix.la \
-		module-native-protocol-unix.la \
-		module-http-protocol-unix.la
+		module-simple-protocol-unix.la
+#		module-esound-protocol-unix.la \
+#		module-native-protocol-unix.la \
+#		module-http-protocol-unix.la
 endif
 
 if HAVE_MKFIFO
@@ -887,11 +905,11 @@ modlibexec_LTLIBRARIES += \
 		module-pipe-source.la
 endif
 
-if !OS_IS_WIN32
-modlibexec_LTLIBRARIES += \
-		module-esound-compat-spawnfd.la \
-		module-esound-compat-spawnpid.la
-endif
+#if !OS_IS_WIN32
+#modlibexec_LTLIBRARIES += \
+#		module-esound-compat-spawnfd.la \
+#		module-esound-compat-spawnpid.la
+#endif
 
 if HAVE_REGEX
 modlibexec_LTLIBRARIES += \
@@ -904,19 +922,19 @@ modlibexec_LTLIBRARIES += \
 		module-x11-publish.la
 endif
 
-if HAVE_OSS
-modlibexec_LTLIBRARIES += \
-		liboss-util.la \
-		module-oss.la \
-		module-oss-mmap.la
-endif
+#if HAVE_OSS
+#modlibexec_LTLIBRARIES += \
+#		liboss-util.la \
+#		module-oss.la \
+#		module-oss-mmap.la
+#endif
 
-if HAVE_ALSA
-modlibexec_LTLIBRARIES += \
-		libalsa-util.la \
-		module-alsa-sink.la \
-		module-alsa-source.la
-endif
+#if HAVE_ALSA
+#modlibexec_LTLIBRARIES += \
+#		libalsa-util.la \
+#		module-alsa-sink.la \
+#		module-alsa-source.la
+#endif
 
 if HAVE_SOLARIS
 modlibexec_LTLIBRARIES += \
@@ -938,11 +956,11 @@ modlibexec_LTLIBRARIES += \
 		module-mmkbd-evdev.la
 endif
 
-if HAVE_JACK
-modlibexec_LTLIBRARIES += \
-		module-jack-sink.la \
-		module-jack-source.la
-endif
+#if HAVE_JACK
+#modlibexec_LTLIBRARIES += \
+#		module-jack-sink.la \
+#		module-jack-source.la
+#endif
 
 if HAVE_GCONF
 modlibexec_LTLIBRARIES += \
diff --git a/src/modules/module-alsa-sink.c b/src/modules/module-alsa-sink.c
index 3d9f757..f9c4efd 100644
--- a/src/modules/module-alsa-sink.c
+++ b/src/modules/module-alsa-sink.c
@@ -174,6 +174,7 @@ static void do_write(struct userdata *u) {
     update_usage(u);
 
     for (;;) {
+        void *p;
         pa_memchunk *memchunk = NULL;
         snd_pcm_sframes_t frames;
 
@@ -185,14 +186,15 @@ static void do_write(struct userdata *u) {
             else
                 memchunk = &u->memchunk;
         }
-
         assert(memchunk->memblock);
-        assert(memchunk->memblock->data);
         assert(memchunk->length);
-        assert(memchunk->memblock->length);
         assert((memchunk->length % u->frame_size) == 0);
 
-        if ((frames = snd_pcm_writei(u->pcm_handle, (uint8_t*) memchunk->memblock->data + memchunk->index, memchunk->length / u->frame_size)) < 0) {
+        p = pa_memblock_acquire(memchunk->memblock);
+
+        if ((frames = snd_pcm_writei(u->pcm_handle, (uint8_t*) p + memchunk->index, memchunk->length / u->frame_size)) < 0) {
+            pa_memblock_release(memchunk->memblock);
+
             if (frames == -EAGAIN)
                 return;
 
@@ -217,6 +219,8 @@ static void do_write(struct userdata *u) {
             return;
         }
 
+        pa_memblock_release(memchunk->memblock);
+
         if (memchunk == &u->memchunk) {
             size_t l = frames * u->frame_size;
             memchunk->index += l;
diff --git a/src/modules/module-alsa-source.c b/src/modules/module-alsa-source.c
index 4061d66..6d7e09e 100644
--- a/src/modules/module-alsa-source.c
+++ b/src/modules/module-alsa-source.c
@@ -180,6 +180,7 @@ static void do_read(struct userdata *u) {
         pa_memchunk post_memchunk;
         snd_pcm_sframes_t frames;
         size_t l;
+        void *p;
 
         if (!u->memchunk.memblock) {
             u->memchunk.memblock = pa_memblock_new(u->source->core->mempool, u->memchunk.length = u->fragment_size);
@@ -188,11 +189,13 @@ static void do_read(struct userdata *u) {
 
         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 ((frames = snd_pcm_readi(u->pcm_handle, (uint8_t*) u->memchunk.memblock->data + u->memchunk.index, u->memchunk.length / u->frame_size)) < 0) {
+        p = pa_memblock_acquire(u->memchunk.memblock);
+
+        if ((frames = snd_pcm_readi(u->pcm_handle, (uint8_t*) p + u->memchunk.index, u->memchunk.length / u->frame_size)) < 0) {
+            pa_memblock_release(u->memchunk.memblock);
+
             if (frames == -EAGAIN)
                 return;
 
@@ -216,6 +219,7 @@ static void do_read(struct userdata *u) {
             pa_module_unload_request(u->module);
             return;
         }
+        pa_memblock_release(u->memchunk.memblock);
 
         l = frames * u->frame_size;
 
diff --git a/src/modules/module-esound-sink.c b/src/modules/module-esound-sink.c
index 26638d9..39886d0 100644
--- a/src/modules/module-esound-sink.c
+++ b/src/modules/module-esound-sink.c
@@ -144,18 +144,25 @@ static int do_write(struct userdata *u) {
             u->write_index = u->write_length = 0;
         }
     } else if (u->state == STATE_RUNNING) {
+        void *p;
+
         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;
 
-        assert(u->memchunk.memblock && u->memchunk.length);
+        assert(u->memchunk.memblock);
+        assert(u->memchunk.length);
+
+        p = pa_memblock_acquire(u->memchunk.memblock);
 
-        if ((r = pa_iochannel_write(u->io, (uint8_t*) u->memchunk.memblock->data + u->memchunk.index, u->memchunk.length)) < 0) {
+        if ((r = pa_iochannel_write(u->io, (uint8_t*) p + u->memchunk.index, u->memchunk.length)) < 0) {
+            pa_memblock_release(u->memchunk.memblock);
             pa_log("write() failed: %s", pa_cstrerror(errno));
             return -1;
         }
+        pa_memblock_release(u->memchunk.memblock);
 
         u->memchunk.index += r;
         u->memchunk.length -= r;
diff --git a/src/modules/module-jack-sink.c b/src/modules/module-jack-sink.c
index c6a7e33..1092aed 100644
--- a/src/modules/module-jack-sink.c
+++ b/src/modules/module-jack-sink.c
@@ -137,22 +137,25 @@ static void io_event_cb(pa_mainloop_api *m, pa_io_event *e, int fd, pa_io_event_
         unsigned fs;
         jack_nframes_t frame_idx;
         pa_memchunk chunk;
+        void *p;
 
         fs = pa_frame_size(&u->sink->sample_spec);
 
         pa_sink_render_full(u->sink, u->frames_requested * fs, &chunk);
+        p = pa_memblock_acquire(chunk.memblock);
 
         for (frame_idx = 0; frame_idx < u->frames_requested; frame_idx ++) {
             unsigned c;
 
             for (c = 0; c < u->channels; c++) {
-                float *s = ((float*) ((uint8_t*) chunk.memblock->data + chunk.index)) + (frame_idx * u->channels) + c;
+                float *s = ((float*) ((uint8_t*) p + chunk.index)) + (frame_idx * u->channels) + c;
                 float *d = ((float*) u->buffer[c]) + frame_idx;
 
                 *d = *s;
             }
         }
 
+        pa_memblock_release(chunk.memblock);
         pa_memblock_unref(chunk.memblock);
 
         u->frames_requested = 0;
diff --git a/src/modules/module-jack-source.c b/src/modules/module-jack-source.c
index 8ca2403..e19b218 100644
--- a/src/modules/module-jack-source.c
+++ b/src/modules/module-jack-source.c
@@ -136,23 +136,28 @@ static void io_event_cb(pa_mainloop_api *m, pa_io_event *e, int fd, pa_io_event_
         unsigned fs;
         jack_nframes_t frame_idx;
         pa_memchunk chunk;
+        void *p;
 
         fs = pa_frame_size(&u->source->sample_spec);
 
         chunk.memblock = pa_memblock_new(u->core->mempool, chunk.length = u->frames_posted * fs);
         chunk.index = 0;
 
+        p = pa_memblock_acquire(chunk.memblock);
+
         for (frame_idx = 0; frame_idx < u->frames_posted; frame_idx ++) {
             unsigned c;
 
             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;
+                float *d = ((float*) ((uint8_t*) p + chunk.index)) + (frame_idx * u->channels) + c;
 
                 *d = *s;
             }
         }
 
+        pa_memblock_release(chunk.memblock);
+
         pa_source_post(u->source, &chunk);
         pa_memblock_unref(chunk.memblock);
 
diff --git a/src/modules/module-null-sink.c b/src/modules/module-null-sink.c
index 54a8e89..8cf961b 100644
--- a/src/modules/module-null-sink.c
+++ b/src/modules/module-null-sink.c
@@ -28,7 +28,6 @@
 #include <stdlib.h>
 #include <sys/stat.h>
 #include <stdio.h>
-#include <assert.h>
 #include <errno.h>
 #include <string.h>
 #include <fcntl.h>
@@ -38,6 +37,7 @@
 #include <pulse/timeval.h>
 #include <pulse/xmalloc.h>
 
+#include <pulsecore/macro.h>
 #include <pulsecore/iochannel.h>
 #include <pulsecore/sink.h>
 #include <pulsecore/module.h>
@@ -64,11 +64,9 @@ struct userdata {
     pa_core *core;
     pa_module *module;
     pa_sink *sink;
-    pa_time_event *time_event;
+    pa_thread *thread;
     size_t block_size;
-
-    uint64_t n_bytes;
-    struct timeval start_time;
+    struct timeval timestamp;
 };
 
 static const char* const valid_modargs[] = {
@@ -81,35 +79,131 @@ static const char* const valid_modargs[] = {
     NULL
 };
 
-static void time_callback(pa_mainloop_api *m, pa_time_event*e, const struct timeval *tv, void *userdata) {
+static void thread_func(void *userdata) {
     struct userdata *u = userdata;
-    pa_memchunk chunk;
-    struct timeval ntv = *tv;
-    size_t l;
-
-    assert(u);
-
-    if (pa_sink_render(u->sink, u->block_size, &chunk) >= 0) {
-        l = chunk.length;
-        pa_memblock_unref(chunk.memblock);
-    } else
-        l = u->block_size;
-
-    pa_timeval_add(&ntv, pa_bytes_to_usec(l, &u->sink->sample_spec));
-    m->time_restart(e, &ntv);
-
-    u->n_bytes += l;
-}
-
-static pa_usec_t get_latency(pa_sink *s) {
-    struct userdata *u = s->userdata;
-    pa_usec_t a, b;
-    struct timeval now;
+    int quit = 0;
+    struct pollfd pollfd;
+    int running = 1;
+
+    pa_assert(u);
+
+    pa_log_debug("Thread starting up");
+
+    memset(&pollfd, 0, sizeof(pollfd));
+    pollfd.fd = pa_asyncmsgq_get_fd(u->sink->asyncmsgq, PA_ASYNCQ_POP);
+    pollfd.events = POLLIN;
+
+    pa_gettimeofday(u->timestamp);
+    
+    for (;;) {
+        int code;
+        void *data, *object;
+        int r, timeout;
+        struct timeval now;
+
+        /* Check whether there is a message for us to process */
+        if (pa_asyncmsgq_get(u->sink->asyncmsgq, &object, &code, &data) == 0) {
+
+
+            /* Now process these messages our own way */
+            if (!object) {
+
+                switch (code) {
+                    case PA_MESSAGE_SHUTDOWN:
+                        goto finish;
+
+                    default:
+                        pa_sink_process_msg(u->sink->asyncmsgq, object, code, data);
+
+                }
+                
+            } else if (object == u->sink) {
+
+                switch (code) {
+                    case PA_SINK_MESSAGE_STOP:
+                        pa_assert(running);
+                        running = 0;
+                        break;
+                        
+                    case PA_SINK_MESSAGE_START:
+                        pa_assert(!running);
+                        running = 1;
+                        
+                        pa_gettimeofday(u->timestamp);
+                        break;
+                        
+                    case PA_SINK_MESSAGE_GET_LATENCY:
+                        
+                        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;
+                        
+                        /* ... */
+
+                    default:
+                        pa_sink_process_msg(u->sink->asyncmsgq, object, code, data);
+                }
+            }
+            
+            pa_asyncmsgq_done(u->sink->asyncmsgq);
+            continue;
+        }
+
+        /* Render some data and drop it immediately */
+
+        if (running) {
+            pa_gettimeofday(&now);
+            
+            if (pa_timeval_cmp(u->timestamp, &now) <= 0) {
+                pa_memchunk chunk;
+                size_t l;
+                
+                if (pa_sink_render(u->sink, u->block_size, &chunk) >= 0) {
+                    l = chunk.length;
+                    pa_memblock_unref(chunk.memblock);
+                } else
+                    l = u->block_size;
+                
+                pa_timeval_add(&u->timestamp, pa_bytes_to_usec(l, &u->sink->sample_spec));
+                continue;
+            }
+
+            timeout = pa_timeval_diff(&u->timestamp, &now)/1000;
+            
+            if (timeout < 1)
+                timeout = 1;
+        } else
+            timeout = -1;
+
+        /* Hmm, nothing to do. Let's sleep */
+        
+        if (pa_asyncmsgq_before_poll(u->sink->asyncmsgq) < 0)
+            continue;
+
+        r = poll(&pollfd, 1, timeout);
+        pa_asyncmsgq_after_poll(u->sink->asyncmsgq);
+
+        if (r < 0) {
+            if (errno == EINTR)
+                continue;
+
+            pa_log("poll() failed: %s", pa_cstrerror(errno));
+            goto fail;
+        }
+        
+        pa_assert(r == 0 || pollfd.revents == POLLIN);
+    }
 
-    a = pa_timeval_diff(pa_gettimeofday(&now), &u->start_time);
-    b = pa_bytes_to_usec(u->n_bytes, &s->sample_spec);
+fail:
+    /* We have to continue processing messages until we receive the
+     * SHUTDOWN message */
+    pa_asyncmsgq_post(u->core->asyncmsgq, u->core, PA_CORE_MESSAGE_UNLOAD_MODULE, pa_module_ref(u->module), NULL, pa_module_unref);
+    pa_asyncmsgq_wait_for(PA_MESSAGE_SHUTDOWN);
 
-    return b > a ? b - a : 0;
+finish:
+    pa_log_debug("Thread shutting down");
 }
 
 int pa__init(pa_core *c, pa_module*m) {
@@ -118,17 +212,17 @@ int pa__init(pa_core *c, pa_module*m) {
     pa_channel_map map;
     pa_modargs *ma = NULL;
 
-    assert(c);
-    assert(m);
+    pa_assert(c);
+    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;
     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;
     }
 
@@ -138,22 +232,24 @@ int pa__init(pa_core *c, pa_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.");
+        pa_log("Failed to create sink.");
         goto fail;
     }
 
-    u->sink->get_latency = get_latency;
     u->sink->userdata = u;
     pa_sink_set_owner(u->sink, m);
     pa_sink_set_description(u->sink, pa_modargs_get_value(ma, "description", "NULL sink"));
 
-    u->n_bytes = 0;
-    pa_gettimeofday(&u->start_time);
-
-    u->time_event = c->mainloop->time_new(c->mainloop, &u->start_time, time_callback, u);
-
-    u->block_size = pa_bytes_per_second(&ss) / 10;
+    u->block_size = pa_bytes_per_second(&ss) / 20; /* 50 ms */
+    
+    if (u->block_size <= 0)
+        u->block_size = pa_frame_size(&ss);
 
+    if (!(u->thread = pa_thread_new(thread_func, u))) {
+        pa_log("Failed to create thread.");
+        goto fail;
+    }
+    
     pa_modargs_free(ma);
 
     return 0;
@@ -169,15 +265,21 @@ fail:
 
 void pa__done(pa_core *c, pa_module*m) {
     struct userdata *u;
-    assert(c && m);
+    
+    pa_assert(c);
+    pa_assert(m);
 
     if (!(u = m->userdata))
         return;
 
     pa_sink_disconnect(u->sink);
-    pa_sink_unref(u->sink);
 
-    u->core->mainloop->time_free(u->time_event);
+    if (u->thread) {
+        pa_asyncmsgq_send(u->sink->asyncmsgq, PA_SINK_MESSAGE_SHUTDOWN, NULL);
+        pa_thread_free(u->thread);
+    }
+    
+    pa_sink_unref(u->sink);
 
     pa_xfree(u);
 }
diff --git a/src/modules/module-oss-mmap.c b/src/modules/module-oss-mmap.c
index 16c9b31..567230e 100644
--- a/src/modules/module-oss-mmap.c
+++ b/src/modules/module-oss-mmap.c
@@ -173,7 +173,7 @@ static void out_fill_memblocks(struct userdata *u, unsigned n) {
                     u->out_fragment_size,
                     1);
         assert(chunk.memblock);
-        chunk.length = chunk.memblock->length;
+        chunk.length = pa_memblock_get_length(chunk.memblock);
         chunk.index = 0;
 
         pa_sink_render_into_full(u->sink, &chunk);
@@ -217,7 +217,7 @@ static void in_post_memblocks(struct userdata *u, unsigned n) {
 
         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.length = pa_memblock_get_length(chunk.memblock);
             chunk.index = 0;
 
             pa_source_post(u->source, &chunk);
diff --git a/src/modules/module-oss.c b/src/modules/module-oss.c
index 9d4d0ea..9061e11 100644
--- a/src/modules/module-oss.c
+++ b/src/modules/module-oss.c
@@ -158,6 +158,7 @@ static void do_write(struct userdata *u) {
     }
 
     do {
+        void *p;
         memchunk = &u->memchunk;
 
         if (!memchunk->length)
@@ -165,10 +166,11 @@ static void do_write(struct userdata *u) {
                 memchunk = &u->silence;
 
         assert(memchunk->memblock);
-        assert(memchunk->memblock->data);
         assert(memchunk->length);
 
-        if ((r = pa_iochannel_write(u->io, (uint8_t*) memchunk->memblock->data + memchunk->index, memchunk->length)) < 0) {
+        p = pa_memblock_acquire(memchunk->memblock);
+        if ((r = pa_iochannel_write(u->io, (uint8_t*) p + memchunk->index, memchunk->length)) < 0) {
+            pa_memblock_release(memchunk->memblock);
 
             if (errno != EAGAIN) {
                 pa_log("write() failed: %s", pa_cstrerror(errno));
@@ -180,6 +182,8 @@ static void do_write(struct userdata *u) {
             break;
         }
 
+        pa_memblock_release(memchunk->memblock);
+
         if (memchunk == &u->silence)
             assert(r % u->sample_size == 0);
         else {
@@ -224,9 +228,13 @@ static void do_read(struct userdata *u) {
     }
 
     do {
+        void *p;
         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) {
+
+        p = pa_memblock_acquire(memchunk.memblock);
+
+        if ((r = pa_iochannel_read(u->io, p, pa_memblock_get_length(memchunk.memblock))) < 0) {
+            pa_memblock_release(memchunk.memblock);
             pa_memblock_unref(memchunk.memblock);
 
             if (errno != EAGAIN) {
@@ -239,8 +247,10 @@ static void do_read(struct userdata *u) {
             break;
         }
 
-        assert(r <= (ssize_t) memchunk.memblock->length);
-        memchunk.length = memchunk.memblock->length = r;
+        pa_memblock_release(memchunk.memblock);
+
+        assert(r <= (ssize_t) pa_memblock_get_length(memchunk.memblock));
+        memchunk.length = r;
         memchunk.index = 0;
 
         pa_source_post(u->source, &memchunk);
diff --git a/src/modules/module-pipe-sink.c b/src/modules/module-pipe-sink.c
index 170b046..61672ed 100644
--- a/src/modules/module-pipe-sink.c
+++ b/src/modules/module-pipe-sink.c
@@ -58,20 +58,16 @@ 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;
-
-    char *filename;
-
-    pa_sink *sink;
-    pa_iochannel *io;
-    pa_defer_event *defer_event;
-
-    pa_memchunk memchunk;
     pa_module *module;
+    pa_sink *sink;
+    char *filename;
+    int fd;
+    pa_thread *thread;
 };
 
 static const char* const valid_modargs[] = {
@@ -84,97 +80,203 @@ static const char* const valid_modargs[] = {
     NULL
 };
 
-static void do_write(struct userdata *u) {
-    ssize_t r;
-    assert(u);
-
-    u->core->mainloop->defer_enable(u->defer_event, 0);
-
-    if (!pa_iochannel_is_writable(u->io))
-        return;
-
-    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;
-
-    assert(u->memchunk.memblock && u->memchunk.length);
-
-    if ((r = pa_iochannel_write(u->io, (uint8_t*) u->memchunk.memblock->data + u->memchunk.index, u->memchunk.length)) < 0) {
-        pa_log("write(): %s", pa_cstrerror(errno));
-        return;
-    }
+enum {
+    POLLFD_ASYNCQ,
+    POLLFD_FIFO,
+    POLLFD_MAX,
+};
 
-    u->memchunk.index += r;
-    u->memchunk.length -= r;
+static void thread_func(void *userdata) {
+    struct userdata *u = userdata;
+    int quit = 0;
+    struct pollfd pollfd[POLLFD_MAX];
+    int running = 1, underrun = 0;
+    pa_memchunk memchunk;
 
-    if (u->memchunk.length <= 0) {
-        pa_memblock_unref(u->memchunk.memblock);
-        u->memchunk.memblock = NULL;
+    pa_assert(u);
+
+    pa_log_debug("Thread starting up");
+
+    memset(&pollfd, 0, sizeof(pollfd));
+    pollfd[POLLFD_ASYNCQ].fd = pa_asyncmsgq_get_fd(u->sink->asyncmsgq, PA_ASYNCQ_POP);
+    pollfd[POLLFD_ASYNCQ].events = POLLIN;
+
+    pollfd[POLLFD_FIFO].fd = u->fd;
+
+    memset(&memchunk, 0, sizeof(memchunk));
+
+    for (;;) {
+        int code;
+        void *object, *data;
+        int r;
+        struct timeval now;
+
+        /* Check whether there is a message for us to process */
+        if (pa_asyncmsgq_get(u->sink->asyncmsgq, &object, &code, &data) == 0) {
+
+
+            /* Now process these messages our own way */
+            if (!object) {
+                switch (code) {
+                    case PA_SINK_MESSAGE_SHUTDOWN:
+                        goto finish;
+
+                    default:
+                        pa_sink_process_msg(u->sink->asyncmsgq, object, code, data);
+                }
+                
+            } else if (object == u->sink) {
+                        
+                case PA_SINK_MESSAGE_STOP:
+                    pa_assert(running);
+                    running = 0;
+                    break;
+
+                case PA_SINK_MESSAGE_START:
+                    pa_assert(!running);
+                    running = 1;
+                    break;
+
+                case PA_SINK_MESSAGE_GET_LATENCY: {
+                    size_t n = 0;
+                    int l;
+
+                    if (ioctl(u->fd, TIOCINQ, &l) >= 0 && l > 0)
+                        n = (size_t) l;
+
+                    n += memchunk.length;
+
+                    *((pa_usec_t*) data) pa_bytes_to_usec(n, &u->sink->sample_spec);
+                    break;
+                }
+
+                /* ... */
+
+                default:
+                    pa_sink_process_msg(u->sink->asyncmsgq, object, code, data);
+            }
+            
+            pa_asyncmsgq_done(u->sink->asyncmsgq);
+            continue;
+        }
+
+        /* Render some data and write it to the fifo */
+
+        if (running && (pollfd[POLLFD_FIFO].revents || underrun)) {
+
+            if (chunk.length <= 0)
+                pa_sink_render(u->fd, PIPE_BUF, &chunk);
+
+            underrun = chunk.length <= 0;
+
+            if (!underrun) {
+                ssize_t l;
+                
+                p = pa_memblock_acquire(u->memchunk.memblock);
+                l = pa_write(u->fd, (uint8_t*) p + u->memchunk.index, u->memchunk.length);
+                pa_memblock_release(p);
+                    
+                if (l < 0) {
+
+                    if (errno != EINTR && 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);
+                        u->memchunk.memblock = NULL;
+                    }
+                }
+
+                pollfd[POLLFD_FIFO].revents = 0;
+                continue;
+            }
+        }
+
+        pollfd[POLLFD_FIFO].events = running && !underrun ? POLLOUT : 0;
+
+        /* Hmm, nothing to do. Let's sleep */
+        
+        if (pa_asyncmsgq_before_poll(u->sink->asyncmsgq) < 0)
+            continue;
+
+        r = poll(&pollfd, 1, 0);
+        pa_asyncmsgq_after_poll(u->sink->asyncmsgq);
+
+        if (r < 0) {
+            if (errno == EINTR)
+                continue;
+
+            pa_log("poll() failed: %s", pa_cstrerror(errno));
+            goto fail;
+        }
+
+        if (pollfd[POLLFD_FIFO].revents & ~POLLIN) {
+            pa_log("FIFO shutdown.");
+            goto fail;
+        }
+        
+        pa_assert(pollfd[POLLFD_ASYNCQ].revents & ~POLLIN == 0);
     }
-}
-
-static void notify_cb(pa_sink*s) {
-    struct userdata *u = s->userdata;
-    assert(s && u);
-
-    if (pa_iochannel_is_writable(u->io))
-        u->core->mainloop->defer_enable(u->defer_event, 1);
-}
-
-static pa_usec_t get_latency_cb(pa_sink *s) {
-    struct userdata *u = s->userdata;
-    assert(s && u);
-
-    return u->memchunk.memblock ? pa_bytes_to_usec(u->memchunk.length, &s->sample_spec) : 0;
-}
-
-static void defer_callback(PA_GCC_UNUSED pa_mainloop_api *m, PA_GCC_UNUSED pa_defer_event*e, void *userdata) {
-    struct userdata *u = userdata;
-    assert(u);
-    do_write(u);
-}
+    
+fail:
+    /* We have to continue processing messages until we receive the
+     * SHUTDOWN message */
+    pa_asyncmsgq_post(u->core->asyncmsgq, u->core, PA_CORE_MESSAGE_UNLOAD_MODULE, pa_module_ref(u->module), pa_module_unref);
+    pa_asyncmsgq_wait_for(PA_SINK_MESSAGE_SHUTDOWN);
 
-static void io_callback(PA_GCC_UNUSED pa_iochannel *io, void*userdata) {
-    struct userdata *u = userdata;
-    assert(u);
-    do_write(u);
+finish:
+    pa_log_debug("Thread shutting down");
 }
 
 int pa__init(pa_core *c, pa_module*m) {
     struct userdata *u = NULL;
     struct stat st;
-    const char *p;
-    int fd = -1;
     pa_sample_spec ss;
     pa_channel_map map;
     pa_modargs *ma = NULL;
     char *t;
 
-    assert(c && m);
+    pa_assert(c);
+    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;
     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");
         goto fail;
     }
 
-    mkfifo(p = pa_modargs_get_value(ma, "file", DEFAULT_FIFO_NAME), 0777);
-
-    if ((fd = open(p, O_RDWR)) < 0) {
+    u = pa_xnew0(struct userdata, 1);
+    u->core = c;
+    u->module = m;
+    u->filename = pa_xstrdup(pa_modargs_get_value(ma, "file", DEFAULT_FIFO_NAME));
+    u->fd = fd;
+    u->memchunk.memblock = NULL;
+    u->memchunk.length = 0;
+    m->userdata = u;
+    
+    mkfifo(u->filename, 0666);
+    
+    if ((u->fd = open(u->filename, O_RDWR)) < 0) {
         pa_log("open('%s'): %s", p, pa_cstrerror(errno));
         goto fail;
     }
 
-    pa_fd_set_cloexec(fd, 1);
+    pa_fd_set_cloexec(u->fd, 1);
+    pa_make_nonblock_fd(u->fd);
 
-    if (fstat(fd, &st) < 0) {
+    if (fstat(u->fd, &st) < 0) {
         pa_log("fstat('%s'): %s", p, pa_cstrerror(errno));
         goto fail;
     }
@@ -184,34 +286,21 @@ int pa__init(pa_core *c, pa_module*m) {
         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.");
+        pa_log("Failed to create sink.");
         goto fail;
     }
-    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("Unix FIFO sink '%s'", p));
     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->memchunk.memblock = NULL;
-    u->memchunk.length = 0;
-
-    u->defer_event = c->mainloop->defer_new(c->mainloop, defer_callback, u);
-    assert(u->defer_event);
-    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_modargs_free(ma);
 
     return 0;
@@ -220,9 +309,6 @@ fail:
     if (ma)
         pa_modargs_free(ma);
 
-    if (fd >= 0)
-        close(fd);
-
     pa__done(c, m);
 
     return -1;
@@ -230,22 +316,31 @@ fail:
 
 void pa__done(pa_core *c, pa_module*m) {
     struct userdata *u;
-    assert(c && m);
+    pa_assert(c);
+    pa_assert(m);
 
     if (!(u = m->userdata))
         return;
 
-    if (u->memchunk.memblock)
-        pa_memblock_unref(u->memchunk.memblock);
-
     pa_sink_disconnect(u->sink);
+
+    if (u->thread) {
+        pa_asyncmsgq_send(u->sink->asyncmsgq, PA_SINK_MESSAGE_SHUTDOWN, NULL);
+        pa_thread_free(u->thread);
+    }
+    
     pa_sink_unref(u->sink);
-    pa_iochannel_free(u->io);
-    u->core->mainloop->defer_free(u->defer_event);
 
-    assert(u->filename);
-    unlink(u->filename);
-    pa_xfree(u->filename);
+    if (u->memchunk.memblock)
+       pa_memblock_unref(u->memchunk.memblock);
+
+    if (u->filename) {
+        unlink(u->filename);
+        pa_xfree(u->filename);
+    }
+
+    if (u->fd >= 0)
+        close(u->fd);
 
     pa_xfree(u);
 }
diff --git a/src/modules/module-pipe-source.c b/src/modules/module-pipe-source.c
index 56c721b..f275c5d 100644
--- a/src/modules/module-pipe-source.c
+++ b/src/modules/module-pipe-source.c
@@ -84,7 +84,9 @@ static const char* const valid_modargs[] = {
 
 static void do_read(struct userdata *u) {
     ssize_t r;
+    void *p;
     pa_memchunk chunk;
+
     assert(u);
 
     if (!pa_iochannel_is_readable(u->io))
@@ -97,17 +99,22 @@ static void do_read(struct userdata *u) {
         u->chunk.index = chunk.length = 0;
     }
 
-    assert(u->chunk.memblock && u->chunk.memblock->length > u->chunk.index);
-    if ((r = pa_iochannel_read(u->io, (uint8_t*) u->chunk.memblock->data + u->chunk.index, u->chunk.memblock->length - u->chunk.index)) <= 0) {
+    assert(u->chunk.memblock);
+    assert(pa_memblock_get_length(u->chunk.memblock) > u->chunk.index);
+
+    p = pa_memblock_acquire(u->chunk.memblock);
+    if ((r = pa_iochannel_read(u->io, (uint8_t*) p + u->chunk.index, pa_memblock_get_length(u->chunk.memblock) - u->chunk.index)) <= 0) {
+        pa_memblock_release(u->chunk.memblock);
         pa_log("read(): %s", pa_cstrerror(errno));
         return;
     }
+    pa_memblock_release(u->chunk.memblock);
 
     u->chunk.length = r;
     pa_source_post(u->source, &u->chunk);
     u->chunk.index += r;
 
-    if (u->chunk.index >= u->chunk.memblock->length) {
+    if (u->chunk.index >= pa_memblock_get_length(u->chunk.memblock)) {
         u->chunk.index = u->chunk.length = 0;
         pa_memblock_unref(u->chunk.memblock);
         u->chunk.memblock = NULL;
diff --git a/src/modules/module-sine.c b/src/modules/module-sine.c
index 661455b..baf3734 100644
--- a/src/modules/module-sine.c
+++ b/src/modules/module-sine.c
@@ -65,7 +65,7 @@ static int sink_input_peek(pa_sink_input *i, pa_memchunk *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;
 }
 
@@ -74,11 +74,12 @@ static void sink_input_drop(pa_sink_input *i, const pa_memchunk *chunk, size_t l
     assert(i && chunk && length && i->userdata);
     u = i->userdata;
 
-    assert(chunk->memblock == u->memblock && length <= u->memblock->length-u->peek_index);
+    assert(chunk->memblock == u->memblock);
+    assert(length <= pa_memblock_get_length(u->memblock)-u->peek_index);
 
     u->peek_index += length;
 
-    if (u->peek_index >= u->memblock->length)
+    if (u->peek_index >= pa_memblock_get_length(u->memblock))
         u->peek_index = 0;
 }
 
@@ -111,6 +112,7 @@ int pa__init(pa_core *c, pa_module*m) {
     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))) {
@@ -142,7 +144,9 @@ int pa__init(pa_core *c, pa_module*m) {
     }
 
     u->memblock = pa_memblock_new(c->mempool, pa_bytes_per_second(&ss));
-    calc_sine(u->memblock->data, u->memblock->length, frequency);
+    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);
 
diff --git a/src/modules/rtp/rtp.c b/src/modules/rtp/rtp.c
index 03a0141..f0ab7d8 100644
--- a/src/modules/rtp/rtp.c
+++ b/src/modules/rtp/rtp.c
@@ -81,7 +81,7 @@ int pa_rtp_send(pa_rtp_context *c, size_t size, pa_memblockq *q) {
             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_base = (void*)((uint8_t*) pa_memblock_acquire(chunk.memblock) + chunk.index);
                 iov[iov_idx].iov_len = k;
                 mb[iov_idx] = chunk.memblock;
                 iov_idx ++;
@@ -116,8 +116,10 @@ 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
@@ -174,7 +176,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;
@@ -195,9 +197,9 @@ int pa_rtp_recv(pa_rtp_context *c, pa_memchunk *chunk, pa_mempool *pool) {
         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);
@@ -238,8 +240,10 @@ int pa_rtp_recv(pa_rtp_context *c, pa_memchunk *chunk, pa_mempool *pool) {
     return 0;
 
 fail:
-    if (chunk->memblock)
+    if (chunk->memblock) {
+        pa_memblock_release(chunk->memblock);
         pa_memblock_unref(chunk->memblock);
+    }
 
     return -1;
 }
diff --git a/src/pulse/internal.h b/src/pulse/internal.h
index 52354fd..e5c9ef1 100644
--- a/src/pulse/internal.h
+++ b/src/pulse/internal.h
@@ -116,6 +116,7 @@ struct pa_stream {
     uint32_t requested_bytes;
 
     pa_memchunk peek_memchunk;
+    void *peek_data;
     pa_memblockq *record_memblockq;
 
     int corked;
diff --git a/src/pulse/stream.c b/src/pulse/stream.c
index f20c17a..44fce52 100644
--- a/src/pulse/stream.c
+++ b/src/pulse/stream.c
@@ -91,6 +91,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;
 
@@ -125,8 +126,11 @@ static void stream_free(pa_stream *s) {
         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);
@@ -608,8 +612,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;
@@ -675,9 +682,12 @@ 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;
+    assert(s->peek_data);
+    *data = (uint8_t*) s->peek_data + s->peek_memchunk.index;
     *length = s->peek_memchunk.length;
     return 0;
 }
@@ -696,6 +706,8 @@ int pa_stream_drop(pa_stream *s) {
     if (s->timing_info_valid && !s->timing_info.read_index_corrupt)
         s->timing_info.read_index += s->peek_memchunk.length;
 
+    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;
diff --git a/src/pulse/xmalloc.h b/src/pulse/xmalloc.h
index 2f6399c..62a450d 100644
--- a/src/pulse/xmalloc.h
+++ b/src/pulse/xmalloc.h
@@ -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/asyncmsgq.c b/src/pulsecore/asyncmsgq.c
new file mode 100644
index 0000000..31e27e7
--- /dev/null
+++ b/src/pulsecore/asyncmsgq.c
@@ -0,0 +1,235 @@
+/* $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);
+
+struct asyncmsgq_item {
+    int code;
+    pa_msgobject *object;
+    void *userdata;
+    pa_free_cb_t free_cb;
+    pa_memchunk memchunk;
+    pa_semaphore *semaphore;
+};
+
+struct pa_asyncmsgq {
+    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_assert_se(a->asyncq = pa_asyncq_new(size));
+    pa_assert_se(a->mutex = pa_mutex_new(0));
+    a->current = NULL;
+    
+    return a;
+}
+
+void pa_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->object);
+        
+        if (i->userdata_free_cb)
+            i->userdata_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);
+}
+
+void pa_asyncmsgq_post(pa_asyncmsgq *a, pa_msgobject *object, int code, const void *userdata, const pa_memchunk *chunk, pa_free_cb_t free_cb) {
+    struct asyncmsgq_item *i;
+    pa_assert(a);
+
+    if (!(i = pa_flist_pop(PA_STATIC_FLIST_GET(asyncmsgq))))
+        i = pa_xnew(struct asyncmsgq_item, 1);
+
+    i->code = code;
+    i->object = pa_msgobject_ref(object);
+    i->userdata = (void*) userdata;
+    i->free_cb = free_cb;
+    if (chunk) {
+        pa_assert(chunk->memblock);
+        i->memchunk = *chunk;
+        pa_memblock_ref(i->memchunk.memblock);
+    } else
+        pa_memchunk_reset(&i->memchunk);
+    i->semaphore = NULL;
+
+    /* 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);
+}
+
+int pa_asyncmsgq_send(pa_asyncmsgq *a, pa_msgobject *object, int code, const void *userdata, const pa_memchunk *chunk) {
+    struct asyncmsgq_item i;
+    pa_assert(a);
+
+    i.code = code;
+    i.object = object;
+    i.userdata = (void*) userdata;
+    i.free_cb = NULL;
+    i.ret = -1;
+    if (chunk) {
+        pa_assert(chunk->memblock);
+        i->memchunk = *chunk;
+    } else
+        pa_memchunk_reset(&i->memchunk);
+    pa_assert_se(i.semaphore = pa_semaphore_new(0));
+
+    /* 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);
+    pa_semaphore_free(i.semaphore);
+
+    return i.ret;
+}
+
+int pa_asyncmsgq_get(pa_asyncmsgq *a, pa_msgobject **object, int *code, void **userdata, pa_memchunk *chunk, int wait) {
+    pa_assert(a);
+    pa_assert(code);
+    pa_assert(!a->current);
+
+    if (!(a->current = pa_asyncq_pop(a->asyncq, wait)))
+        return -1;
+
+    *code = a->current->code;
+    if (userdata)
+        *userdata = a->current->userdata;
+    if (object)
+        *object = a->current->object;
+    if (chunk)
+        *chunk = a->chunk;
+    
+    return 0;
+}
+
+void pa_asyncmsgq_done(pa_asyncmsgq *a, int ret) {
+    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(a);
+    
+    do {
+        
+        if (pa_asyncmsgq_get(a, NULL, &c, NULL, 1) < 0)
+            return -1;
+
+        pa_asyncmsgq_done(a);
+        
+    } while (c != code);
+
+    return 0;
+}
+
+int pa_asyncmsgq_get_fd(pa_asyncmsgq *a) {
+    pa_assert(a);
+
+    return pa_asyncq_get_fd(a->asyncq);
+}
+
+int pa_asyncmsgq_before_poll(pa_asyncmsgq *a) {
+    pa_assert(a);
+
+    return pa_asyncq_before_poll(a->asyncq);
+}
+
+void pa_asyncmsgq_after_poll(pa_asyncmsgq *a) {
+    pa_assert(a);
+
+    pa_asyncq_after_poll(a->asyncq);
+}
+
+int pa_asyncmsgq_dispatch(pa_msgobject *object, int code, void *userdata, pa_memchunk *memchunk) {
+    pa_assert(q);
+
+    if (object)
+        return object->msg_process(object, code, userdata, memchunk);
+
+    return 0;
+}
diff --git a/src/pulsecore/asyncmsgq.h b/src/pulsecore/asyncmsgq.h
new file mode 100644
index 0000000..17b37e4
--- /dev/null
+++ b/src/pulsecore/asyncmsgq.h
@@ -0,0 +1,73 @@
+#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 fromer just enqueues the message asynchronously, the
+ * latter waits for completion, synchronously. */
+
+enum {
+    PA_MESSAGE_SHUTDOWN /* A generic message to inform the handler of this queue to quit */
+};
+
+typedef struct pa_asyncmsgq pa_asyncmsgq;
+
+pa_asyncmsgq* pa_asyncmsgq_new(size_t size);
+void pa_asyncmsgq_free(pa_asyncmsgq* q);
+
+void pa_asyncmsgq_post(pa_asyncmsgq *q, pa_msgobject *object, int code, const void *userdata, 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, const pa_memchunk *memchunk);
+
+int pa_asyncmsgq_get(pa_asyncmsgq *q, pa_msgobject **object, int *code, void **userdata, pa_memchunk *memchunk, int wait);
+int pa_asyncmsgq_dispatch(pa_msgobject *object, int code, void *userdata, pa_memchunk *memchunk);
+void pa_asyncmsgq_done(pa_asyncmsgq *q, int ret);
+int pa_asyncmsgq_wait_for(pa_asyncmsgq *a, int code);
+
+/* 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
index 0000000..779cd47
--- /dev/null
+++ b/src/pulsecore/asyncq.c
@@ -0,0 +1,271 @@
+/* $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"
+
+#define ASYNCQ_SIZE 128
+
+/* For debugging purposes we can define _Y to put and extra thread
+ * yield between each operation. */
+
+#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_atomic_int_t read_waiting;
+    pa_atomic_int_t write_waiting;
+    int read_fds[2], write_fds[2];
+};
+
+#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;
+    pa_atomic_store(&l->read_waiting, 0);
+    pa_atomic_store(&l->write_waiting, 0);
+
+    if (pipe(l->read_fds) < 0) {
+        pa_xfree(l);
+        return NULL;
+    }
+    
+    if (pipe(l->write_fds) < 0) {
+        pa_close(l->read_fds[0]);
+        pa_close(l->read_fds[1]);
+        pa_xfree(l);
+        return NULL;
+    }
+
+    pa_make_nonblock_fd(l->read_fds[1]);
+    pa_make_nonblock_fd(l->write_fds[1]);
+
+    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_close(l->read_fds[0]);
+    pa_close(l->read_fds[1]);
+    pa_close(l->write_fds[0]);
+    pa_close(l->write_fds[1]);
+    
+    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)) {
+        
+        /* First try failed. Let's wait for changes. */
+
+        if (!wait)
+            return -1;
+
+        _Y;
+
+        pa_atomic_inc(&l->write_waiting);
+
+        for (;;) {
+            char x[20];
+            
+            _Y;
+
+            if (pa_atomic_ptr_cmpxchg(&cells[idx], NULL, p))
+                break;
+
+            _Y;
+
+            if (read(l->write_fds[0], x, sizeof(x)) < 0 && errno != EINTR) {
+                pa_atomic_dec(&l->write_waiting);
+                return -1;
+            }
+        }
+        
+        _Y;
+
+        pa_atomic_dec(&l->write_waiting);
+    }
+    
+    _Y;
+    l->write_idx++;
+    
+    if (pa_atomic_load(&l->read_waiting)) {
+        char x = 'x';
+        _Y;
+        write(l->read_fds[1], &x, sizeof(x));
+    }
+    
+    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]))) {
+
+        /* First try failed. Let's wait for changes. */
+    
+        if (!wait)
+            return NULL;
+
+        _Y;
+
+        pa_atomic_inc(&l->read_waiting);
+
+        for (;;) {
+            char x[20];
+
+            _Y;
+
+            if ((ret = pa_atomic_ptr_load(&cells[idx])))
+                break;
+
+            _Y;
+
+            if (read(l->read_fds[0], x, sizeof(x)) < 0 && errno != EINTR) {
+                pa_atomic_dec(&l->read_waiting);
+                return NULL;
+            }
+        }
+
+        _Y;
+
+        pa_atomic_dec(&l->read_waiting);
+    }
+
+    /* Guaranteed if we only have a single reader */
+    pa_assert_se(pa_atomic_ptr_cmpxchg(&cells[idx], ret, NULL));
+
+    _Y;
+    l->read_idx++;
+
+    if (pa_atomic_load(&l->write_waiting)) {
+        char x = 'x';
+        _Y;
+        write(l->write_fds[1], &x, sizeof(x));
+    }
+            
+    return ret;
+}
+
+int pa_asyncq_get_fd(pa_asyncq *q) {
+    pa_assert(q);
+
+    return q->read_fds[0];
+}
+
+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);
+
+    if (pa_atomic_ptr_load(&cells[idx]))
+        return -1;
+
+    pa_atomic_inc(&l->read_waiting);
+    
+    if (pa_atomic_ptr_load(&cells[idx])) {
+        pa_atomic_dec(&l->read_waiting);
+        return -1;
+    }
+
+    return 0;
+}
+
+int pa_asyncq_after_poll(pa_asyncq *l) {
+    pa_assert(l);
+
+    pa_assert(pa_atomic_load(&l->read_waiting) > 0);
+
+    pa_atomic_dec(&l->read_waiting);
+}
diff --git a/src/pulsecore/asyncq.h b/src/pulsecore/asyncq.h
new file mode 100644
index 0000000..aac45b1
--- /dev/null
+++ b/src/pulsecore/asyncq.h
@@ -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(size_t 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);
+int pa_asyncq_after_poll(pa_asyncq *a);
+
+#endif
diff --git a/src/pulsecore/atomic.h b/src/pulsecore/atomic.h
index 013e8c2..9a024f9 100644
--- a/src/pulsecore/atomic.h
+++ b/src/pulsecore/atomic.h
@@ -31,9 +31,9 @@
  * It is not guaranteed however, that sizeof(AO_t) == sizeof(size_t).
  * however very likely. */
 
-typedef struct pa_atomic_int {
+typedef struct pa_atomic {
     volatile AO_t value;
-} pa_atomic_int_t;
+} pa_atomic_t;
 
 #define PA_ATOMIC_INIT(v) { .value = (v) }
 
@@ -41,31 +41,31 @@ typedef struct pa_atomic_int {
  * 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_int_t *a) {
+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 +73,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);
 }
diff --git a/src/pulsecore/cli-command.c b/src/pulsecore/cli-command.c
index 6989069..36c85d6 100644
--- a/src/pulsecore/cli-command.c
+++ b/src/pulsecore/cli-command.c
@@ -95,6 +95,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);
@@ -130,12 +131,13 @@ 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},
+    { "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},
     { "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-sink-input-mute",     pa_cli_command_sink_input_mute,    "Set the mute switch of a sink input (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-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},
@@ -392,7 +394,7 @@ 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;
 }
 
@@ -460,7 +462,7 @@ 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;
 }
 
@@ -489,7 +491,7 @@ 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;
 }
 
@@ -518,7 +520,42 @@ 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_input_mute(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_GCC_UNUSED int *fail) {
+    const char *n, *v;
+    pa_sink_input *si;
+    uint32_t idx;
+    int mute;
+
+    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;
 }
 
@@ -900,7 +937,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 +945,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 +958,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));
     }
 
 
diff --git a/src/pulsecore/cli-text.c b/src/pulsecore/cli-text.c
index 413f933..05d681e 100644
--- a/src/pulsecore/cli-text.c
+++ b/src/pulsecore/cli-text.c
@@ -93,6 +93,12 @@ char *pa_sink_list_to_string(pa_core *c) {
     pa_strbuf *s;
     pa_sink *sink;
     uint32_t idx = PA_IDXSET_INVALID;
+    static const char* const state_table[] = {
+        [PA_SINK_RUNNING] = "RUNNING",
+        [PA_SINK_SUSPENDED] = "SUSPENDED",
+        [PA_SINK_IDLE] = "IDLE",
+        [PA_SINK_DISCONNECTED] = "DISCONNECTED"
+    };
     assert(c);
 
     s = pa_strbuf_new();
@@ -108,22 +114,29 @@ char *pa_sink_list_to_string(pa_core *c) {
             "  %c index: %u\n"
             "\tname: <%s>\n"
             "\tdriver: <%s>\n"
+            "\tis_hardware: <%i>\n"
+            "\tstate: %s\n"
             "\tvolume: <%s>\n"
+            "\tmute: <%i>\n"
             "\tlatency: <%0.0f usec>\n"
             "\tmonitor_source: <%u>\n"
             "\tsample spec: <%s>\n"
             "\tchannel map: <%s>\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->is_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));
 
-        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,6 +148,12 @@ char *pa_source_list_to_string(pa_core *c) {
     pa_strbuf *s;
     pa_source *source;
     uint32_t idx = PA_IDXSET_INVALID;
+    static const char* const state_table[] = {
+        [PA_SOURCE_RUNNING] = "RUNNING",
+        [PA_SOURCE_SUSPENDED] = "SUSPENDED",
+        [PA_SOURCE_IDLE] = "IDLE",
+        [PA_SOURCE_DISCONNECTED] = "DISCONNECTED"
+    };
     assert(c);
 
     s = pa_strbuf_new();
@@ -143,7 +162,7 @@ char *pa_source_list_to_string(pa_core *c) {
     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,6 +170,10 @@ char *pa_source_list_to_string(pa_core *c) {
             "  %c index: %u\n"
             "\tname: <%s>\n"
             "\tdriver: <%s>\n"
+            "\tis_hardware: <%i>\n"
+            "\tstate: %s\n"
+            "\tvolume: <%s>\n"
+            "\tmute: <%u>\n"
             "\tlatency: <%0.0f usec>\n"
             "\tsample spec: <%s>\n"
             "\tchannel map: <%s>\n",
@@ -158,14 +181,18 @@ char *pa_source_list_to_string(pa_core *c) {
             source->index,
             source->name,
             source->driver,
+            !!source->is_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));
 
         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,9 +206,9 @@ 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_DISCONNECTED] = "DISCONNECTED"
     };
     assert(c);
 
@@ -202,14 +229,16 @@ char *pa_source_output_list_to_string(pa_core *c) {
             "\tdriver: <%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],
+            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,9 +256,10 @@ 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_DISCONNECTED] = "DISCONNECTED"
     };
 
     assert(c);
@@ -251,6 +281,7 @@ char *pa_sink_input_list_to_string(pa_core *c) {
             "\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 +289,17 @@ char *pa_sink_input_list_to_string(pa_core *c) {
             i->index,
             i->name,
             i->driver,
-            state_table[i->state],
+            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);
     }
diff --git a/src/pulsecore/core-def.h b/src/pulsecore/core-def.h
index 10a3be4..4bc0513 100644
--- a/src/pulsecore/core-def.h
+++ b/src/pulsecore/core-def.h
@@ -24,9 +24,6 @@
   USA.
 ***/
 
-typedef enum pa_mixer {
-    PA_MIXER_SOFTWARE,
-    PA_MIXER_HARDWARE
-} pa_mixer_t;
+/* FIXME: Remove this shit */
 
 #endif
diff --git a/src/pulsecore/core.c b/src/pulsecore/core.c
index 31b6c18..c80caf1 100644
--- a/src/pulsecore/core.c
+++ b/src/pulsecore/core.c
@@ -45,13 +45,59 @@
 #include <pulsecore/props.h>
 #include <pulsecore/random.h>
 #include <pulsecore/log.h>
+#include <pulsecore/macro.h>
 
 #include "core.h"
 
+static int core_process_msg(pa_msgobject *o, int code, void *userdata, 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 asyncmsgq_cb(pa_mainloop_api*api, pa_io_event* e, int fd, pa_io_event_flags_t events, void *userdata) {
+    pa_core *c = userdata;
+    
+    pa_assert(pa_asyncmsgq_get_fd(c->asyncmsgq) == fd);
+    pa_assert(events == PA_IO_EVENT_INPUT);
+
+    pa_asyncmsgq_after_poll(c->asyncmsgq);
+
+    for (;;) {
+        pa_msgobject *object;
+        int code;
+        void *data;
+        pa_memchunk chunk;
+
+        /* Check whether there is a message for us to process */
+        while (pa_asyncmsgq_get(c->asyncmsgq, &object, &code, &data, &chunk, 0) == 0) {
+            pa_asyncmsgq_dispatch(object, code, data, &chunk);
+            pa_asyncmsgq_done(c->asyncmsgq, 0);
+        }
+        
+        if (pa_asyncmsgq_before_poll(c->asyncmsgq) == 0)
+            break;
+    }
+}
+
+static void core_free(pa_object *o);
+
 pa_core* pa_core_new(pa_mainloop_api *m, int shared) {
     pa_core* c;
     pa_mempool *pool;
 
+    pa_assert(m);
+    
     if (shared) {
         if (!(pool = pa_mempool_new(shared))) {
             pa_log_warn("failed to allocate shared memory pool. Falling back to a normal memory pool.");
@@ -66,7 +112,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);
@@ -123,11 +171,17 @@ pa_core* pa_core_new(pa_mainloop_api *m, int shared) {
 #ifdef SIGPIPE
     pa_check_signal_is_blocked(SIGPIPE);
 #endif
+
+    pa_assert_se(c->asyncmsgq = pa_asyncmsgq_new(0));
+    pa_assert_se(pa_asyncmsgq_before_poll(c->asyncmsgq) == 0);
+    pa_assert_se(c->asyncmsgq_event = c->mainloop->io_new(c->mainloop, pa_asyncmsgq_get_fd(c->asyncmsgq), PA_IO_EVENT_INPUT, asyncmsgq_cb, c));
+            
     return c;
 }
 
-void pa_core_free(pa_core *c) {
-    assert(c);
+static void core_free(pa_object *o) {
+    pa_core *c = PA_CORE(o);
+    pa_core_assert_ref(c);
 
     pa_module_unload_all(c);
     assert(!c->modules);
@@ -162,6 +216,10 @@ void pa_core_free(pa_core *c) {
 
     pa_property_cleanup(c);
 
+    c->mainloop->io_free(c->asyncmsgq_event);
+    pa_asyncmsgq_after_poll(c->asyncmsgq);
+    pa_asyncmsgq_free(c->asyncmsgq);
+
     pa_hook_free(&c->hook_sink_input_new);
     pa_hook_free(&c->hook_sink_disconnect);
     pa_hook_free(&c->hook_source_output_new);
diff --git a/src/pulsecore/core.h b/src/pulsecore/core.h
index 51a18b6..dc2ebb4 100644
--- a/src/pulsecore/core.h
+++ b/src/pulsecore/core.h
@@ -34,17 +34,21 @@
 #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>
 
 /* 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;
@@ -88,10 +92,20 @@ struct pa_core {
         hook_sink_disconnect,
         hook_source_output_new,
         hook_source_disconnect;
+
+    pa_asyncmsgq *asyncmsgq;
+    pa_io_event *asyncmsgq_event;
+};
+
+PA_DECLARE_CLASS(pa_core);
+#define PA_CORE(o) ((pa_core*) 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);
diff --git a/src/pulsecore/flist.c b/src/pulsecore/flist.c
index 00567ab..3805e1d 100644
--- a/src/pulsecore/flist.c
+++ b/src/pulsecore/flist.c
@@ -30,6 +30,7 @@
 #include <pulsecore/atomic.h>
 #include <pulsecore/log.h>
 #include <pulsecore/thread.h>
+#include <pulsecore/macro.h>
 #include <pulse/xmalloc.h>
 
 #include "flist.h"
@@ -90,18 +91,19 @@ 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;
 };
 
+#define PA_FLIST_CELLS(x) ((struct cell*) ((uint8_t*) (x) + PA_ALIGN(sizeof(struct pa_flist))))
+
 static int is_power_of_two(unsigned size) {
     return !(size & (size - 1));
 }
@@ -114,10 +116,9 @@ pa_flist *pa_flist_new(unsigned size) {
 
     assert(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);
@@ -134,30 +135,35 @@ void pa_flist_free(pa_flist *l, pa_free_cb_t free_cb) {
     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;
 
     assert(l);
     assert(p);
 
+    cells = PA_FLIST_CELLS(l);
+    
     n = len = (int) l->size - pa_atomic_load(&l->length) + N_EXTRA_SCAN;
     _Y;
     idx = reduce(l, pa_atomic_load(&l->write_idx));
@@ -165,13 +171,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;
@@ -191,9 +197,12 @@ int pa_flist_push(pa_flist*l, void *p) {
 
 void* pa_flist_pop(pa_flist*l) {
     int idx, len, n;
+    struct cell *cells;
 
     assert(l);
 
+    cells = PA_FLIST_CELLS(l);
+
     n = len = pa_atomic_load(&l->length) + N_EXTRA_SCAN;
     _Y;
     idx = reduce(l, pa_atomic_load(&l->read_idx));
@@ -201,14 +210,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);
diff --git a/src/pulsecore/flist.h b/src/pulsecore/flist.h
index bf702bf..80fd86c 100644
--- a/src/pulsecore/flist.h
+++ b/src/pulsecore/flist.h
@@ -26,6 +26,8 @@
 
 #include <pulse/def.h>
 
+#include <pulsecore/once.h>
+
 /* A multiple-reader multipler-write lock-free free list implementation */
 
 typedef struct pa_flist pa_flist;
@@ -38,4 +40,22 @@ 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);
 
+#define PA_STATIC_FLIST_DECLARE(name, size)                     \
+    struct {                                                    \
+        pa_flist *flist;                                        \
+        pa_once_t once;                                         \
+    } name##_static_flist = { NULL, PA_ONCE_INIT };             \
+                                                                \
+    static void name##_init(void) {                             \
+        name##_static_flist.flist = pa_flist_new(size);         \
+    }                                                           \
+                                                                \
+    static inline pa_flist* name##_get(void) {                  \
+        pa_once(&name##_static_flist.once, name##_init);        \
+        return name##_static_flist.flist;                       \
+    } \
+    struct __stupid_useless_struct_to_allow_trailing_semicolon
+
+#define PA_STATIC_FLIST_GET(name) (name##_get())
+
 #endif
diff --git a/src/pulsecore/hashmap.h b/src/pulsecore/hashmap.h
index 3ca2a47..98df450 100644
--- a/src/pulsecore/hashmap.h
+++ b/src/pulsecore/hashmap.h
@@ -32,11 +32,13 @@
 
 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);
diff --git a/src/pulsecore/idxset.c b/src/pulsecore/idxset.c
index 70ef7ba..e683ead 100644
--- a/src/pulsecore/idxset.c
+++ b/src/pulsecore/idxset.c
@@ -32,6 +32,7 @@
 #include <string.h>
 
 #include <pulse/xmalloc.h>
+#include <pulsecore/macro.h>
 
 #include "idxset.h"
 
diff --git a/src/pulsecore/idxset.h b/src/pulsecore/idxset.h
index 17a70f4..5b55cec 100644
--- a/src/pulsecore/idxset.h
+++ b/src/pulsecore/idxset.h
@@ -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);
 
diff --git a/src/pulsecore/macro.h b/src/pulsecore/macro.h
new file mode 100644
index 0000000..215c5c0
--- /dev/null
+++ b/src/pulsecore/macro.h
@@ -0,0 +1,80 @@
+#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 <pulsecore/log.h>
+
+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))
+
+#define PA_ELEMENTSOF(x) (sizeof(x)/sizeof((x)[0]))
+
+#define SA_MAX(a, b) ((a) > (b) ? (a) : (b))
+#define SA_MIN(a, b) ((a) < (b) ? (a) : (b))
+
+#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 */
+#define pa_assert_se(x) do {                  \
+        int _r = !!(x);                       \
+        pa_assert(_r);                        \
+    } while(0)
+
+#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)
+
+#endif
diff --git a/src/pulsecore/mcalign.c b/src/pulsecore/mcalign.c
index dd1d71f..9761643 100644
--- a/src/pulsecore/mcalign.c
+++ b/src/pulsecore/mcalign.c
@@ -91,6 +91,7 @@ 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);
@@ -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);
+            assert(m->leftover.length <= m->base);
+            assert(m->leftover.length <= pa_memblock_get_length(m->leftover.memblock));
 
             if (c->length > l) {
                 /* Save the remainder of the memory block */
diff --git a/src/pulsecore/memblock.c b/src/pulsecore/memblock.c
index 6f09a90..71b576a 100644
--- a/src/pulsecore/memblock.c
+++ b/src/pulsecore/memblock.c
@@ -33,10 +33,14 @@
 #include <unistd.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 "memblock.h"
 
@@ -48,6 +52,32 @@
 #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 +85,8 @@ struct pa_memimport_segment {
 };
 
 struct pa_memimport {
+    pa_mutex *mutex;
+
     pa_mempool *pool;
     pa_hashmap *segments;
     pa_hashmap *blocks;
@@ -73,9 +105,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,21 +129,27 @@ 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);
 
+/* No lock necessary */
 static void stat_add(pa_memblock*b) {
     assert(b);
     assert(b->pool);
@@ -129,6 +169,7 @@ 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);
@@ -152,6 +193,7 @@ 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;
 
@@ -164,56 +206,70 @@ 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);
 
-    b = pa_xmalloc(sizeof(pa_memblock) + length);
+    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);
 
-    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);
 
     return (uint8_t*) slot + 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);
 
     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,6 +279,7 @@ 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;
@@ -237,7 +294,7 @@ pa_memblock *pa_memblock_new_pool(pa_mempool *p, size_t length) {
 
         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 + sizeof(pa_memblock));
 
     } else if (p->block_size - sizeof(struct mempool_slot) >= length) {
 
@@ -246,22 +303,26 @@ pa_memblock *pa_memblock_new_pool(pa_mempool *p, size_t length) {
 
         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_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;
 
@@ -270,17 +331,20 @@ pa_memblock *pa_memblock_new_fixed(pa_mempool *p, void *d, size_t length, int re
     assert(length > 0);
 
     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;
 
@@ -290,18 +354,68 @@ pa_memblock *pa_memblock_new_user(pa_mempool *p, void *d, size_t length, void (*
     assert(free_cb);
 
     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) {
+    assert(b);
+    assert(PA_REFCNT_VALUE(b) > 0);
+
+    return b->read_only && PA_REFCNT_VALUE(b) == 1;
+}
+
+/* No lock necessary */
+void* pa_memblock_acquire(pa_memblock *b) {
+    assert(b);
+    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;
+    assert(b);
+    assert(PA_REFCNT_VALUE(b) > 0);
+
+    r = pa_atomic_dec(&b->n_acquired);
+    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) {
+    assert(b);
+    assert(PA_REFCNT_VALUE(b) > 0);
+
+    return b->length;
+}
+
+pa_mempool* pa_memblock_get_pool(pa_memblock *b) {
+    assert(b);
+    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);
@@ -310,19 +424,17 @@ pa_memblock* pa_memblock_ref(pa_memblock*b) {
     return b;
 }
 
-void pa_memblock_unref(pa_memblock*b) {
+static void memblock_free(pa_memblock *b) {
     assert(b);
-    assert(PA_REFCNT_VALUE(b) > 0);
 
-    if (PA_REFCNT_DEC(b) > 0)
-        return;
+    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);
+            b->per_type.user.free_cb(pa_atomic_ptr_load(&b->data));
 
             /* Fall through */
 
@@ -333,17 +445,24 @@ void pa_memblock_unref(pa_memblock*b) {
 
         case PA_MEMBLOCK_IMPORTED : {
             pa_memimport_segment *segment;
+            pa_memimport *import;
+
+            /* FIXME! This should be implemented lock-free */
 
             segment = b->per_type.imported.segment;
             assert(segment);
-            assert(segment->import);
-
-            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);
+            import = segment->import;
+            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_mutex_unlock(import->mutex);
+
+            import->release_cb(import, b->per_type.imported.id, import->userdata);
+
             pa_xfree(b);
             break;
         }
@@ -351,13 +470,20 @@ void pa_memblock_unref(pa_memblock*b) {
         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);
+            slot = mempool_slot_by_ptr(b->pool, pa_atomic_ptr_load(&b->data));
             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)
+            /* 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)
                 pa_xfree(b);
 
             break;
@@ -369,6 +495,36 @@ void pa_memblock_unref(pa_memblock*b) {
     }
 }
 
+/* No lock necessary */
+void pa_memblock_unref(pa_memblock*b) {
+    assert(b);
+    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) {
+    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);
 
@@ -381,38 +537,43 @@ static void memblock_make_local(pa_memblock *b) {
             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);
 
-    if (PA_REFCNT_VALUE(b) > 1)
+    if (PA_REFCNT_DEC(b) > 0)
         memblock_make_local(b);
-
-    pa_memblock_unref(b);
+    else
+        memblock_free(b);
 }
 
+/* Self-locked. This function is not multiple-caller safe */
 static void memblock_replace_import(pa_memblock *b) {
     pa_memimport_segment *seg;
 
@@ -428,6 +589,8 @@ static void memblock_replace_import(pa_memblock *b) {
     assert(seg);
     assert(seg->import);
 
+    pa_mutex_lock(seg->import->mutex);
+
     pa_hashmap_remove(
             seg->import->blocks,
             PA_UINT32_TO_PTR(b->per_type.imported.id));
@@ -436,6 +599,8 @@ static void memblock_replace_import(pa_memblock *b) {
 
     if (-- seg->n_blocks <= 0)
         segment_detach(seg);
+
+    pa_mutex_unlock(seg->import->mutex);
 }
 
 pa_mempool* pa_mempool_new(int shared) {
@@ -444,12 +609,15 @@ pa_mempool* pa_mempool_new(int shared) {
 
     p = pa_xnew(pa_mempool, 1);
 
+    p->mutex = pa_mutex_new(1);
+    p->semaphore = pa_semaphore_new(0);
+
 #ifdef HAVE_SYSCONF
     ps = (size_t) sysconf(_SC_PAGESIZE);
 #elif defined(PAGE_SIZE)
-	ps = (size_t) PAGE_SIZE;
+    ps = (size_t) PAGE_SIZE;
 #else
-	ps = 4096; /* Let's hope it's like x86. */
+    ps = 4096; /* Let's hope it's like x86. */
 #endif
 
     p->block_size = (PA_MEMPOOL_SLOT_SIZE/ps)*ps;
@@ -466,13 +634,13 @@ pa_mempool* pa_mempool_new(int shared) {
         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;
 }
@@ -480,34 +648,61 @@ pa_mempool* pa_mempool_new(int shared) {
 void pa_mempool_free(pa_mempool *p) {
     assert(p);
 
+    pa_mutex_lock(p->mutex);
+
     while (p->imports)
         pa_memimport_free(p->imports);
 
     while (p->exports)
         pa_memexport_free(p->exports);
 
+    pa_mutex_unlock(p->mutex);
+
     if (pa_atomic_load(&p->stat.n_allocated) > 0)
         pa_log_warn("WARNING! Memory pool destroyed but not all memory blocks freed!");
 
+    pa_flist_free(p->free_slots, NULL);
     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);
 
     return &p->stat;
 }
 
+/* No lock necessary */
 void pa_mempool_vacuum(pa_mempool *p) {
     struct mempool_slot *slot;
+    pa_flist *list;
 
     assert(p);
 
-    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));
+    list = pa_flist_new(p->n_blocks*2);
+
+    while ((slot = pa_flist_pop(p->free_slots)))
+        while (pa_flist_push(list, slot) < 0)
+            ;
+
+    while ((slot = pa_flist_pop(list))) {
+        pa_shm_punch(&p->memory,
+                     (uint8_t*) slot - (uint8_t*) p->memory.ptr + sizeof(struct mempool_slot),
+                     p->block_size - 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);
 
@@ -519,6 +714,7 @@ 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);
 
@@ -533,18 +729,23 @@ pa_memimport* pa_memimport_new(pa_mempool *p, pa_memimport_release_cb_t cb, void
     assert(cb);
 
     i = pa_xnew(pa_memimport, 1);
+    i->mutex = pa_mutex_new(0);
     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,6 +766,7 @@ 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);
 
@@ -573,51 +775,68 @@ static void segment_detach(pa_memimport_segment *seg) {
     pa_xfree(seg);
 }
 
+/* Self-locked. Not multiple-caller safe */
 void pa_memimport_free(pa_memimport *i) {
     pa_memexport *e;
     pa_memblock *b;
 
     assert(i);
 
-    /* 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);
+    pa_mutex_lock(i->mutex);
 
     while ((b = pa_hashmap_get_first(i->blocks)))
         memblock_replace_import(b);
 
     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);
+
+    PA_LLIST_REMOVE(pa_memimport, i->pool->imports, i);
+
+    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_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);
+    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 +844,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;
@@ -634,10 +857,15 @@ int pa_memimport_process_revoke(pa_memimport *i, uint32_t id) {
     pa_memblock *b;
     assert(i);
 
+    pa_mutex_lock(i->mutex);
+
     if (!(b = pa_hashmap_get(i->blocks, PA_UINT32_TO_PTR(id))))
         return -1;
 
     memblock_replace_import(b);
+
+    pa_mutex_unlock(i->mutex);
+
     return 0;
 }
 
@@ -652,6 +880,7 @@ pa_memexport* pa_memexport_new(pa_mempool *p, pa_memexport_revoke_cb_t cb, void
         return NULL;
 
     e = pa_xnew(pa_memexport, 1);
+    e->mutex = pa_mutex_new(1);
     e->pool = p;
     PA_LLIST_HEAD_INIT(struct memexport_slot, e->free_slots);
     PA_LLIST_HEAD_INIT(struct memexport_slot, e->used_slots);
@@ -659,51 +888,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_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_xfree(e);
 }
 
+/* Self-locked */
 int pa_memexport_process_release(pa_memexport *e, uint32_t id) {
+    pa_memblock *b;
+
     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);
+    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_memblock_unref(e->slots[id].block);
-    e->slots[id].block = NULL;
+    pa_atomic_sub(&e->pool->stat.exported_size, b->length);
 
-    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_mutex_lock(e->mutex);
+
     for (slot = e->used_slots; slot; slot = next) {
         uint32_t idx;
         next = slot->next;
@@ -716,8 +969,11 @@ 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;
 
@@ -734,13 +990,16 @@ static pa_memblock *memblock_shared_copy(pa_mempool *p, pa_memblock *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;
+    size_t length;
 
     assert(e);
     assert(b);
@@ -753,12 +1012,15 @@ int pa_memexport_put(pa_memexport *e, pa_memblock *b, uint32_t *block_id, uint32
     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,8 +1029,11 @@ 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);
         memory = &b->per_type.imported.segment->memory;
@@ -778,15 +1043,17 @@ int pa_memexport_put(pa_memexport *e, pa_memblock *b, uint32_t *block_id, uint32
         memory = &b->pool->memory;
     }
 
-    assert(b->data >= memory->ptr);
-    assert((uint8_t*) b->data + b->length <= (uint8_t*) memory->ptr + memory->size);
+    assert(data >= memory->ptr);
+    assert((uint8_t*) data + length <= (uint8_t*) memory->ptr + memory->size);
 
     *shm_id = memory->id;
-    *offset = (uint8_t*) b->data - (uint8_t*) memory->ptr;
-    *size = b->length;
+    *offset = (uint8_t*) data - (uint8_t*) memory->ptr;
+    *size = length;
+
+    pa_memblock_release(b);
 
     pa_atomic_inc(&e->pool->stat.n_exported);
-    pa_atomic_add(&e->pool->stat.exported_size, b->length);
+    pa_atomic_add(&e->pool->stat.exported_size, length);
 
     return 0;
 }
diff --git a/src/pulsecore/memblock.h b/src/pulsecore/memblock.h
index fe4773d..6f8bbef 100644
--- a/src/pulsecore/memblock.h
+++ b/src/pulsecore/memblock.h
@@ -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,17 @@ 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);
+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);
+
 /* The memory block manager */
 pa_mempool* pa_mempool_new(int shared);
 void pa_mempool_free(pa_mempool *p);
diff --git a/src/pulsecore/memblockq.c b/src/pulsecore/memblockq.c
index e31fb6d..a80df33 100644
--- a/src/pulsecore/memblockq.c
+++ b/src/pulsecore/memblockq.c
@@ -178,7 +178,7 @@ int pa_memblockq_push(pa_memblockq* bq, const pa_memchunk *uchunk) {
     assert(uchunk);
     assert(uchunk->memblock);
     assert(uchunk->length > 0);
-    assert(uchunk->index + uchunk->length <= uchunk->memblock->length);
+    assert(uchunk->index + uchunk->length <= pa_memblock_get_length(uchunk->memblock));
 
     if (uchunk->length % bq->base)
         return -1;
@@ -362,8 +362,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 {
@@ -415,8 +415,8 @@ void pa_memblockq_drop(pa_memblockq *bq, const pa_memchunk *chunk, size_t length
 
             if (bq->silence) {
 
-                if (!l || l > bq->silence->length)
-                    l = bq->silence->length;
+                if (!l || l > pa_memblock_get_length(bq->silence))
+                    l = pa_memblock_get_length(bq->silence);
 
             }
 
diff --git a/src/pulsecore/memchunk.c b/src/pulsecore/memchunk.c
index 7111e1e..f00cc9e 100644
--- a/src/pulsecore/memchunk.c
+++ b/src/pulsecore/memchunk.c
@@ -37,22 +37,25 @@
 void 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);
 
-    if (PA_REFCNT_VALUE(c->memblock) == 1 &&
-        !c->memblock->read_only &&
-        c->memblock->length >= c->index+min)
+    if (pa_memblock_is_read_only(c->memblock) &&
+        pa_memblock_get_length(c->memblock) >= c->index+min)
         return;
 
     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;
diff --git a/src/pulsecore/msgobject.c b/src/pulsecore/msgobject.c
new file mode 100644
index 0000000..ea404cc
--- /dev/null
+++ b/src/pulsecore/msgobject.c
@@ -0,0 +1,40 @@
+/* $Id$ */
+
+/***
+  This file is part of PulseAudio.
+
+  Copyright 2004-2006 Lennart Poettering
+  Copyright 2006 Pierre Ossman <ossman at 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_msgobject *pa_msgobject_new_internal(size_t size, const char *type_name) {
+    pa_msgobject *o;
+    
+    pa_assert(size > sizeof(pa_msgobject));
+    pa_assert(type_name);
+
+    o = PA_MSGOBJECT(pa_object_new_internal(size, type_name));
+    o->process_msg = NULL;
+    return o;
+}
diff --git a/src/pulsecore/msgobject.h b/src/pulsecore/msgobject.h
new file mode 100644
index 0000000..317ebd2
--- /dev/null
+++ b/src/pulsecore/msgobject.h
@@ -0,0 +1,52 @@
+#ifndef foopulsemsgobjecthfoo
+#define foopulsemsgobjecthfoo
+
+/* $Id$ */
+
+/***
+  This file is part of PulseAudio.
+
+  Copyright 2004-2006 Lennart Poettering
+  Copyright 2006 Pierre Ossman <ossman at 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, pa_memchunk *chunk);
+};
+
+pa_msgobject *pa_msgobject_new_internal(size_t size, const char *type_name);
+
+#define pa_msgobject_new(type) ((type*) pa_msgobject_new_internal(sizeof(type), #type))
+#define pa_msgobject_free ((void (*) (pa_msgobject* o)) pa_object_free)
+
+#define PA_MSGOBJECT(o) ((pa_msgobject*) (o))
+
+PA_DECLARE_CLASS(pa_msgobject);
+
+#endif
diff --git a/src/pulsecore/mutex-posix.c b/src/pulsecore/mutex-posix.c
index 52e731b..a66950e 100644
--- a/src/pulsecore/mutex-posix.c
+++ b/src/pulsecore/mutex-posix.c
@@ -28,8 +28,6 @@
 #include <assert.h>
 #include <pthread.h>
 
-#include <atomic_ops.h>
-
 #include <pulse/xmalloc.h>
 
 #include "mutex.h"
diff --git a/src/pulsecore/object.c b/src/pulsecore/object.c
new file mode 100644
index 0000000..de7d5ad
--- /dev/null
+++ b/src/pulsecore/object.c
@@ -0,0 +1,61 @@
+/* $Id$ */
+
+/***
+  This file is part of PulseAudio.
+
+  Copyright 2004-2006 Lennart Poettering
+  Copyright 2006 Pierre Ossman <ossman at 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) {
+    pa_object *o;
+    
+    pa_assert(size > sizeof(pa_object));
+    pa_assert(type_name);
+
+    o = pa_xmalloc(size);
+    PA_REFCNT_INIT(o);
+    o->type_name = type_name;
+    o->free = pa_object_free;
+
+    return o;
+}
+
+pa_object *pa_object_ref(pa_object *o) {
+    pa_assert(o);
+    pa_assert(PA_REFCNT_VALUE(o) >= 1);
+
+    PA_REFCNT_INC(o);
+    return o;
+}
+
+void pa_object_unref(pa_object *o) {
+    pa_assert(o);
+    pa_assert(PA_REFCNT_VALUE(o) >= 1);
+
+    if (PA_REFCNT_DEC(o) <= 0) {
+        pa_assert(o->free);
+        o->free(o);
+    }
+}
diff --git a/src/pulsecore/object.h b/src/pulsecore/object.h
new file mode 100644
index 0000000..8fccf19
--- /dev/null
+++ b/src/pulsecore/object.h
@@ -0,0 +1,72 @@
+#ifndef foopulseobjecthfoo
+#define foopulseobjecthfoo
+
+/* $Id$ */
+
+/***
+  This file is part of PulseAudio.
+
+  Copyright 2004-2006 Lennart Poettering
+  Copyright 2006 Pierre Ossman <ossman at 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>
+
+typedef struct pa_object pa_object;
+
+struct pa_object {
+    PA_REFCNT_DECLARE;
+    const char *type_name;
+    void (*free)(pa_object *o);
+};
+
+pa_object *pa_object_new_internal(size_t size, const char *type_name);
+#define pa_object_new(type) ((type*) pa_object_new_internal(sizeof(type), #type))
+
+#define pa_object_free ((void (*) (pa_object* o)) pa_xfree)
+
+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;
+}
+
+#define pa_object_assert_ref(o) pa_assert(pa_object_refcnt(o))
+
+#define PA_OBJECT(o) ((pa_object*) (o))
+
+#define PA_DECLARE_CLASS(c) \
+    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
+        
+#endif
diff --git a/src/pulsecore/once-posix.c b/src/pulsecore/once-posix.c
index 4af7b36..7ccd08e 100644
--- a/src/pulsecore/once-posix.c
+++ b/src/pulsecore/once-posix.c
@@ -26,44 +26,56 @@
 #endif
 
 #include <pthread.h>
-#include <assert.h>
 
+#include <pulsecore/macro.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);
-}
-
+/* Not reentrant -- how could it be? */
 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 *m;
+    
+    pa_assert(control);
+    pa_assert(func);
+
+    if (pa_atomic_load(&control->done))
+        return;
+    
+    pa_atomic_inc(&control->ref);
+        
+    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_mutex_unlock(m);
+            break;
+        }
+
+        pa_assert_se(m = pa_mutex_new(0));
+        pa_mutex_lock(m);
+        
+        if (pa_atomic_ptr_cmpxchg(&control->mutex, NULL, m)) {
+            func();
+            pa_atomic_store(&control->done, 1);
+            pa_mutex_unlock(m);
+
+            break;
+        }
+
+        pa_mutex_unlock(m);
+        pa_mutex_free(m);
+    }
+
+    pa_assert(pa_atomic_load(&control->done));
+    
+    if (pa_atomic_dec(&control->ref) <= 1) {
+        pa_assert(pa_atomic_ptr_cmpxchg(&control->mutex, m, NULL));
+        pa_mutex_free(m);
     }
-    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
diff --git a/src/pulsecore/once.h b/src/pulsecore/once.h
index c20fc0b..b260212 100644
--- a/src/pulsecore/once.h
+++ b/src/pulsecore/once.h
@@ -25,13 +25,19 @@
 ***/
 
 #include <pulsecore/mutex.h>
+#include <pulsecore/atomic.h>
 
 typedef struct pa_once {
-    unsigned int once_value;
-    pa_mutex *mutex;
+    pa_atomic_ptr_t mutex;
+    pa_atomic_t ref, done;
 } pa_once_t;
 
-#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);
 
diff --git a/src/pulsecore/play-memblockq.c b/src/pulsecore/play-memblockq.c
index 76edd27..9c5945a 100644
--- a/src/pulsecore/play-memblockq.c
+++ b/src/pulsecore/play-memblockq.c
@@ -122,7 +122,5 @@ int pa_play_memblockq(
 
     si->userdata = q;
 
-    pa_sink_notify(si->sink);
-
     return 0;
 }
diff --git a/src/pulsecore/play-memchunk.c b/src/pulsecore/play-memchunk.c
index 9132e29..65b6e82 100644
--- a/src/pulsecore/play-memchunk.c
+++ b/src/pulsecore/play-memchunk.c
@@ -57,7 +57,7 @@ static int sink_input_peek(pa_sink_input *i, pa_memchunk *chunk) {
     if (c->length <= 0)
         return -1;
 
-    assert(c->memblock && c->memblock->length);
+    assert(c->memblock);
     *chunk = *c;
     pa_memblock_ref(c->memblock);
 
@@ -122,7 +122,5 @@ int pa_play_memchunk(
 
     pa_memblock_ref(chunk->memblock);
 
-    pa_sink_notify(si->sink);
-
     return 0;
 }
diff --git a/src/pulsecore/protocol-esound.c b/src/pulsecore/protocol-esound.c
index 49a78d4..6a5c612 100644
--- a/src/pulsecore/protocol-esound.c
+++ b/src/pulsecore/protocol-esound.c
@@ -894,14 +894,22 @@ 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);
+        assert(c->scache.memchunk.memblock);
+        assert(c->scache.name);
+        assert(c->scache.memchunk.index < c->scache.memchunk.length);
 
-        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) {
+        p = pa_memblock_acquire(c->scache.memchunk.memblock);
+
+        if ((r = pa_iochannel_read(c->io, (uint8_t*) p+c->scache.memchunk.index, c->scache.memchunk.length-c->scache.memchunk.index)) <= 0) {
+            pa_memblock_release(c->scache.memchunk.memblock);
             pa_log_debug("read(): %s", r < 0 ? pa_cstrerror(errno) : "EOF");
             return -1;
         }
 
+        pa_memblock_release(c->scache.memchunk.memblock);
+
         c->scache.memchunk.index += r;
         assert(c->scache.memchunk.index <= c->scache.memchunk.length);
 
@@ -928,6 +936,7 @@ static int do_read(struct connection *c) {
         pa_memchunk chunk;
         ssize_t r;
         size_t l;
+        void *p;
 
         assert(c->input_memblockq);
 
@@ -940,7 +949,7 @@ static int do_read(struct connection *c) {
             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;
@@ -948,14 +957,19 @@ static int do_read(struct connection *c) {
 
         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);
+            assert(c->playback.current_memblock);
+            assert(pa_memblock_get_length(c->playback.current_memblock) >= 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);
+
+        if ((r = pa_iochannel_read(c->io, (uint8_t*) p+c->playback.memblock_index, l)) <= 0) {
+            pa_memblock_release(c->playback.current_memblock);
             pa_log_debug("read(): %s", r < 0 ? pa_cstrerror(errno) : "EOF");
             return -1;
         }
+        pa_memblock_release(c->playback.current_memblock);
 
         chunk.memblock = c->playback.current_memblock;
         chunk.index = c->playback.memblock_index;
@@ -993,19 +1007,26 @@ 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);
+        assert(chunk.memblock);
+        assert(chunk.length);
+
+        p = pa_memblock_acquire(chunk.memblock);
 
-        if ((r = pa_iochannel_write(c->io, (uint8_t*) chunk.memblock->data+chunk.index, chunk.length)) < 0) {
+        if ((r = pa_iochannel_write(c->io, (uint8_t*) p+chunk.index, chunk.length)) < 0) {
+            pa_memblock_release(chunk.memblock);
             pa_memblock_unref(chunk.memblock);
             pa_log("write(): %s", pa_cstrerror(errno));
             return -1;
         }
 
+        pa_memblock_release(chunk.memblock);
+
         pa_memblockq_drop(c->output_memblockq, &chunk, r);
         pa_memblock_unref(chunk.memblock);
 
diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c
index dd41b3d..8645569 100644
--- a/src/pulsecore/protocol-native.c
+++ b/src/pulsecore/protocol-native.c
@@ -2278,6 +2278,7 @@ static void pstream_memblock_callback(pa_pstream *p, uint32_t channel, int64_t o
     } else {
         struct upload_stream *u = (struct upload_stream*) stream;
         size_t l;
+
         assert(u->type == UPLOAD_STREAM);
 
         if (!u->memchunk.memblock) {
@@ -2297,9 +2298,18 @@ static void pstream_memblock_callback(pa_pstream *p, uint32_t channel, int64_t o
         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;
         }
diff --git a/src/pulsecore/protocol-simple.c b/src/pulsecore/protocol-simple.c
index 31ad6dd..288cf87 100644
--- a/src/pulsecore/protocol-simple.c
+++ b/src/pulsecore/protocol-simple.c
@@ -25,7 +25,6 @@
 #include <config.h>
 #endif
 
-#include <assert.h>
 #include <stdlib.h>
 #include <limits.h>
 #include <stdio.h>
@@ -54,13 +53,13 @@ struct connection {
     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_int missing;
     } playback;
 };
 
@@ -69,35 +68,52 @@ struct pa_protocol_simple {
     pa_core *core;
     pa_socket_server*server;
     pa_idxset *connections;
+
+    pa_asyncmsgq *asyncmsgq;
+
     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 */
+};
+
+enum {
+    MESSAGE_REQUEST_DATA,   /* data from source output to main loop */ 
+    MESSAGE_POST_DATA       /* data from source output to main loop */
+};
+
+    
 #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);
+    pa_assert(c);
 
     pa_idxset_remove_by_data(c->protocol->connections, c, NULL);
 
-    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_unref(c->sink_input);
     }
+    
     if (c->source_output) {
         pa_source_output_disconnect(c->source_output);
         pa_source_output_unref(c->source_output);
     }
+    
+    if (c->playback.current_memblock)
+        pa_memblock_unref(c->playback.current_memblock);
+    
     if (c->client)
         pa_client_free(c->client);
     if (c->io)
@@ -106,8 +122,7 @@ static void connection_free(struct connection *c) {
         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);
 }
 
@@ -115,27 +130,37 @@ static int do_read(struct connection *c) {
     pa_memchunk chunk;
     ssize_t r;
     size_t l;
+    void *p;
 
-    if (!c->sink_input || !(l = pa_memblockq_missing(c->input_memblockq)))
+    pa_assert(c);
+    
+    if (!c->sink_input || !(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, 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 (errno == EINTR || errno == EAGAIN)
+            return 0;
+        
         pa_log_debug("read(): %s", r == 0 ? "EOF" : pa_cstrerror(errno));
         return -1;
     }
@@ -143,14 +168,10 @@ 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->protocol->asyncmsgq, c, MESSAGE_POST_DATA, NULL, &chunk, NULL, NULL);
 
     return 0;
 }
@@ -158,35 +179,41 @@ static int do_read(struct connection *c) {
 static int do_write(struct connection *c) {
     pa_memchunk chunk;
     ssize_t r;
+    void *p;
+
+    p_assert(c);
 
     if (!c->source_output)
         return 0;
 
-    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 (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);
-
+    
     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);
+    pa_assert(c);
 
     if (c->dead)
         return;
@@ -207,103 +234,148 @@ 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);
     } else
         connection_free(c);
 }
 
 /*** sink_input callbacks ***/
 
-static int sink_input_peek_cb(pa_sink_input *i, pa_memchunk *chunk) {
+/* Called from thread context */
+static int sink_input_process_msg(pa_sink_input *i, int code, void *userdata, const pa_memchunk *chunk) {
     struct connection*c;
-    assert(i && i->userdata && chunk);
+    
+    pa_assert(i);
     c = i->userdata;
+    pa_assert(c);
 
-    if (pa_memblockq_peek(c->input_memblockq, chunk) < 0) {
+    switch (code) {
 
-        if (c->dead)
-            connection_free(c);
+        case SINK_INPUT_MESSAGE_POST_DATA: {
+            pa_assert(chunk);
 
-        return -1;
+            /* New data from the main loop */
+            pa_memblockq_push_align(c->input_memblockq, chunk);
+            return 0;
+        }
+        
+        case PA_SINK_INPUT_MESSAGE_GET_LATENCY: {
+            pa_usec_t *r = userdata;
+            
+            *r = pa_bytes_to_usec(pa_memblockq_get_length(c->input_memblockq), &c->sink_input->sample_spec);
+
+            /* Fall through, the default handler will add in the extra
+             * latency added by the resampler */
+        }
+
+        default:
+            return pa_sink_input_process_msg(i, code, userdata);
     }
+}
 
-    return 0;
+/* Called from thread context */
+static int sink_input_peek_cb(pa_sink_input *i, pa_memchunk *chunk) {
+    struct connection*c;
+    
+    pa_assert(i);
+    c = i->userdata;
+    pa_assert(c);
+    pa_assert(chunk);
+
+    r = pa_memblockq_peek(c->input_memblockq, chunk);
+
+    if (c->dead && r < 0)
+        connection_free(c);
+
+    return r;
 }
 
+/* Called from thread context */
 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);
+    size_t old, new;
+    
+    pa_assert(i);
+    pa_assert(c);
+    pa_assert(length);
 
+    old = pa_memblockq_missing(c->input_memblockq);
     pa_memblockq_drop(c->input_memblockq, chunk, length);
+    new = pa_memblockq_missing(c->input_memblockq);
 
-    /* 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_atomic_store(&c->playback.missing, &new);
+
+    if (new > old)
+        pa_asyncmsgq_post(c->protocol->asyncmsgq, c, MESSAGE_REQUEST_DATA, NULL, NULL, NULL, NULL);
 }
 
+/* Called from main context */
 static void sink_input_kill_cb(pa_sink_input *i) {
-    assert(i && i->userdata);
+    pa_assert(i);
+    pa_assert(i->userdata);
+    
     connection_free((struct connection *) i->userdata);
 }
 
-
-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);
-}
-
 /*** source_output callbacks ***/
 
 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);
+    struct connection *c;
+    
+    pa_assert(o);
+    c = 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(c->protocol->asyncmsgq, c, MESSAGE_REQUEST_DATA, NULL, chunk, NULL, NULL);
 }
 
 static void source_output_kill_cb(pa_source_output *o) {
-    assert(o && o->userdata);
-    connection_free((struct connection *) o->userdata);
+    struct connection*c;
+
+    pa_assert(o);
+    c = o->userdata;
+    pa_assert(c);
+    
+    connection_free(c);
 }
 
 static pa_usec_t source_output_get_latency_cb(pa_source_output *o) {
-    struct connection*c = o->userdata;
-    assert(o && c);
+    struct connection*c;
+    
+    pa_assert(o);
+    c = 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) {
+    struct connection*c;
+    
+    pa_assert(client);
+    c = client->userdata;
+    pa_assert(c);
+
+    connection_free(client);
 }
 
 /*** 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 ***/
-
-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);
+    pa_assert(io);
+    pa_assert(c);
 
     do_work(c);
 }
@@ -314,7 +386,10 @@ static void on_connection(pa_socket_server*s, pa_iochannel *io, void *userdata)
     pa_protocol_simple *p = userdata;
     struct 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,25 +397,25 @@ 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->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;
 
+    
     if (p->mode & PLAYBACK) {
         pa_sink_input_new_data data;
         size_t l;
@@ -372,11 +447,13 @@ 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_assert(c->input_memblockq);
         pa_iochannel_socket_set_rcvbuf(io, l/PLAYBACK_BUFFER_FRAGMENTS*5);
         c->playback.fragment_size = l/10;
 
-        pa_sink_notify(c->sink_input->sink);
+        pa_atomic_store(&c->playback.missing, pa_memblockq_missing(c->input_memblockq));
+
+        pa_sink_input_put(c->sink_input);
     }
 
     if (p->mode & RECORD) {
@@ -409,16 +486,14 @@ 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:
@@ -426,16 +501,60 @@ fail:
         connection_free(c);
 }
 
+static void asyncmsgq_cb(pa_mainloop_api*api, pa_io_event* e, int fd, pa_io_event_flags_t events, void *userdata) {
+    pa_protocol_simple *p = userdata;
+    int do_some_work = 0;
+    
+    pa_assert(pa_asyncmsgq_get_fd(p->asyncmsgq) == fd);
+    pa_assert(events == PA_IO_EVENT_INPUT);
+
+    pa_asyncmsgq_after_poll(p->asyncmsgq);
+
+    for (;;) {
+        int code;
+        void *object, *data;
+
+        /* Check whether there is a message for us to process */
+        while (pa_asyncmsgq_get(p->asyncmsgq, &object, &code, &data) == 0) {
+
+            connection *c = object;
+
+            pa_assert(c);
+            
+            switch (code) {
+
+                case MESSAGE_REQUEST_DATA:
+                    do_work(c);
+                    break;
+
+                case MESSAGE_POST_DATA:
+                    pa_memblockq_push(c->output_memblockq, chunk);
+                    do_work(c);
+                    break;
+            }
+
+            pa_asyncmsgq_done(p->asyncmsgq);
+        }
+        
+        if (pa_asyncmsgq_before_poll(p->asyncmsgq) == 0)
+            break;
+    }
+}
+
 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);
+    
+    pa_assert(core);
+    pa_assert(server);
+    pa_assert(ma);
 
-    p = pa_xmalloc0(sizeof(pa_protocol_simple));
+    p = pa_xnew0(pa_protocol_simple, 1);
     p->module = m;
     p->core = core;
     p->server = server;
     p->connections = pa_idxset_new(NULL, NULL);
+    pa_assert_se(p->asyncmsgq = pa_asyncmsgq_new(0));
 
     p->sample_spec = core->default_sample_spec;
     if (pa_modargs_get_sample_spec(ma, &p->sample_spec) < 0) {
@@ -467,18 +586,22 @@ pa_protocol_simple* pa_protocol_simple_new(pa_core *core, pa_socket_server *serv
 
     pa_socket_server_set_callback(p->server, on_connection, p);
 
+    pa_assert_se(pa_asyncmsgq_before_poll(p->asyncmsgq) == 0);
+    pa_assert_se(p->asyncmsgq_event = core->mainloop->io_event_new(core->mainloop, pa_asyncmsgq_get_fd(p->asyncmsgq), PA_IO_EVENT_INPUT, p));
+    
     return p;
 
 fail:
     if (p)
         pa_protocol_simple_free(p);
+    
     return NULL;
 }
 
 
 void pa_protocol_simple_free(pa_protocol_simple *p) {
     struct connection *c;
-    assert(p);
+    pa_assert(p);
 
     if (p->connections) {
         while((c = pa_idxset_first(p->connections, NULL)))
@@ -489,6 +612,13 @@ void pa_protocol_simple_free(pa_protocol_simple *p) {
 
     if (p->server)
         pa_socket_server_unref(p->server);
+
+    if (p->asyncmsgq) {
+        c->mainloop->io_event_free(c->asyncmsgq_event);
+        pa_asyncmsgq_after_poll(c->asyncmsgq);
+        pa_asyncmsgq_free(p->asyncmsgq);
+    }
+    
     pa_xfree(p);
 }
 
diff --git a/src/pulsecore/pstream.c b/src/pulsecore/pstream.c
index fdb1a66..f4aab1c 100644
--- a/src/pulsecore/pstream.c
+++ b/src/pulsecore/pstream.c
@@ -49,7 +49,6 @@
 #include <pulsecore/log.h>
 #include <pulsecore/core-scache.h>
 #include <pulsecore/creds.h>
-#include <pulsecore/mutex.h>
 #include <pulsecore/refcnt.h>
 
 #include "pstream.h"
@@ -118,8 +117,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 +128,7 @@ struct pa_pstream {
         uint32_t shm_info[PA_PSTREAM_SHM_MAX];
         void *data;
         size_t index;
+        pa_memchunk memchunk;
     } write;
 
     struct {
@@ -173,8 +173,6 @@ static void do_something(pa_pstream *p) {
 
     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,8 +186,6 @@ static void do_something(pa_pstream *p) {
             goto fail;
     }
 
-    pa_mutex_unlock(p->mutex);
-
     pa_pstream_unref(p);
     return;
 
@@ -200,8 +196,6 @@ fail:
     if (p->die_callback)
         p->die_callback(p, p->die_callback_userdata);
 
-    pa_mutex_unlock(p->mutex);
-
     pa_pstream_unref(p);
 }
 
@@ -214,16 +208,6 @@ static void io_callback(pa_iochannel*io, void *userdata) {
     do_something(p);
 }
 
-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);
-
-    do_something(p);
-}
-
 static void memimport_release_cb(pa_memimport *i, uint32_t block_id, void *userdata);
 
 pa_pstream *pa_pstream_new(pa_mainloop_api *m, pa_iochannel *io, pa_mempool *pool) {
@@ -239,17 +223,14 @@ 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;
@@ -312,8 +293,8 @@ static void pstream_free(pa_pstream *p) {
     if (p->read.packet)
         pa_packet_unref(p->read.packet);
 
-    if (p->mutex)
-        pa_mutex_free(p->mutex);
+    if (p->write.memchunk.memblock)
+        pa_memblock_unref(p->write.memchunk.memblock);
 
     pa_xfree(p);
 }
@@ -325,10 +306,8 @@ void pa_pstream_send_packet(pa_pstream*p, pa_packet *packet, const pa_creds *cre
     assert(PA_REFCNT_VALUE(p) > 0);
     assert(packet);
 
-    pa_mutex_lock(p->mutex);
-
     if (p->dead)
-        goto finish;
+        return;
 
     i = pa_xnew(struct item_info, 1);
     i->type = PA_PSTREAM_ITEM_PACKET;
@@ -340,11 +319,6 @@ 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);
 }
 
 void pa_pstream_send_memblock(pa_pstream*p, uint32_t channel, int64_t offset, pa_seek_mode_t seek_mode, const pa_memchunk *chunk) {
@@ -355,12 +329,9 @@ void pa_pstream_send_memblock(pa_pstream*p, uint32_t channel, int64_t offset, pa
     assert(channel != (uint32_t) -1);
     assert(chunk);
 
-    pa_mutex_lock(p->mutex);
-
     if (p->dead)
-        goto finish;
+        return;
 
-    length = chunk->length;
     idx = 0;
 
     while (length > 0) {
@@ -389,10 +360,6 @@ 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) {
@@ -402,10 +369,8 @@ static void memimport_release_cb(pa_memimport *i, uint32_t block_id, void *userd
     assert(p);
     assert(PA_REFCNT_VALUE(p) > 0);
 
-    pa_mutex_lock(p->mutex);
-
     if (p->dead)
-        goto finish;
+        return;
 
 /*     pa_log("Releasing block %u", block_id); */
 
@@ -417,11 +382,6 @@ static void memimport_release_cb(pa_memimport *i, uint32_t block_id, void *userd
 #endif
 
     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) {
@@ -431,11 +391,8 @@ static void memexport_revoke_cb(pa_memexport *e, uint32_t block_id, void *userda
     assert(p);
     assert(PA_REFCNT_VALUE(p) > 0);
 
-    pa_mutex_lock(p->mutex);
-
     if (p->dead)
-        goto finish;
-
+        return;
 /*     pa_log("Revoking block %u", block_id); */
 
     item = pa_xnew(struct item_info, 1);
@@ -446,22 +403,20 @@ static void memexport_revoke_cb(pa_memexport *e, uint32_t block_id, void *userda
 #endif
 
     pa_queue_push(p->send_queue, item);
-    p->mainloop->defer_enable(p->defer_event, 1);
-
-finish:
-
-    pa_mutex_unlock(p->mutex);
 }
 
 static void prepare_next_write_item(pa_pstream *p) {
     assert(p);
     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);
@@ -528,7 +483,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,6 +501,7 @@ 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);
@@ -558,9 +516,16 @@ 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);
+        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);
     }
 
@@ -570,14 +535,17 @@ static int do_write(pa_pstream *p) {
     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;
 
@@ -591,13 +559,20 @@ static int do_write(pa_pstream *p) {
     }
 
     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;
-
+    pa_memblock *release_memblock = NULL;
     assert(p);
     assert(PA_REFCNT_VALUE(p) > 0);
 
@@ -605,8 +580,16 @@ static int do_read(pa_pstream *p) {
         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;
+        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);
     }
 
@@ -615,15 +598,18 @@ static int do_read(pa_pstream *p) {
         int 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) {
@@ -704,7 +690,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.");
@@ -791,7 +777,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,52 +805,51 @@ 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_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_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_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_mutex_lock(p->mutex);
     p->recieve_memblock_callback = cb;
     p->recieve_memblock_callback_userdata = userdata;
-    pa_mutex_unlock(p->mutex);
 }
 
 int pa_pstream_is_pending(pa_pstream *p) {
@@ -873,15 +858,11 @@ int pa_pstream_is_pending(pa_pstream *p) {
     assert(p);
     assert(PA_REFCNT_VALUE(p) > 0);
 
-    pa_mutex_lock(p->mutex);
-
     if (p->dead)
         b = 0;
     else
         b = p->write.current || !pa_queue_is_empty(p->send_queue);
 
-    pa_mutex_unlock(p->mutex);
-
     return b;
 }
 
@@ -904,8 +885,6 @@ pa_pstream* pa_pstream_ref(pa_pstream*p) {
 void pa_pstream_close(pa_pstream *p) {
     assert(p);
 
-    pa_mutex_lock(p->mutex);
-
     p->dead = 1;
 
     if (p->import) {
@@ -923,25 +902,16 @@ void pa_pstream_close(pa_pstream *p) {
         p->io = NULL;
     }
 
-    if (p->defer_event) {
-        p->mainloop->defer_free(p->defer_event);
-        p->defer_event = NULL;
-    }
-
     p->die_callback = NULL;
     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);
-
     p->use_shm = enable;
 
     if (enable) {
@@ -956,6 +926,4 @@ void pa_pstream_use_shm(pa_pstream *p, int enable) {
             p->export = NULL;
         }
     }
-
-    pa_mutex_unlock(p->mutex);
 }
diff --git a/src/pulsecore/refcnt.h b/src/pulsecore/refcnt.h
index 43433ff..64271ab 100644
--- a/src/pulsecore/refcnt.h
+++ b/src/pulsecore/refcnt.h
@@ -27,18 +27,18 @@
 #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
diff --git a/src/pulsecore/resampler.c b/src/pulsecore/resampler.c
index 3827ff9..248d733 100644
--- a/src/pulsecore/resampler.c
+++ b/src/pulsecore/resampler.c
@@ -53,8 +53,7 @@ struct pa_resampler {
 };
 
 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;
@@ -226,14 +225,14 @@ static void libsamplerate_free(pa_resampler *r) {
     if (u->src_state)
         src_delete(u->src_state);
 
-    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);
+    if (u->buf1.memblock)
+        pa_memblock_unref(u->buf1.memblock);
+    if (u->buf2.memblock)
+        pa_memblock_unref(u->buf2.memblock);
+    if (u->buf3.memblock)
+        pa_memblock_unref(u->buf3.memblock);
+    if (u->buf4.memblock)
+        pa_memblock_unref(u->buf4.memblock);
     pa_xfree(u);
 }
 
@@ -272,64 +271,80 @@ static void calc_map_table(pa_resampler *r) {
     }
 }
 
-static float * convert_to_float(pa_resampler *r, void *input, unsigned n_frames) {
+static pa_memchunk* convert_to_float(pa_resampler *r, pa_memchunk *input) {
     struct impl_libsamplerate *u;
     unsigned n_samples;
+    void *src, *dst;
 
     assert(r);
     assert(input);
+    assert(input->memblock);
+
     assert(r->impl_data);
     u = r->impl_data;
 
     /* Convert the incoming sample into floats and place them in buf1 */
 
-    if (!u->to_float32ne_func)
+    if (!u->to_float32ne_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);
+    if (!u->buf1.memblock || u->buf1_samples < n_samples) {
+        if (u->buf1.memblock)
+            pa_memblock_unref(u->buf1.memblock);
 
         u->buf1_samples = n_samples;
-        u->buf1_block = pa_memblock_new(r->mempool, sizeof(float) * n_samples);
-        u->buf1 = u->buf1_block->data;
+        u->buf1.memblock = pa_memblock_new(r->mempool, u->buf1.length = sizeof(float) * n_samples);
+        u->buf1.index = 0;
     }
 
-    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(u->buf1.memblock);
+    u->to_float32ne_func(n_samples, src, dst);
+    pa_memblock_release(input->memblock);
+    pa_memblock_release(u->buf1.memblock);
+
+    u->buf1.length = sizeof(float) * n_samples;
 
-    return u->buf1;
+    return &u->buf1;
 }
 
-static float *remap_channels(pa_resampler *r, float *input, unsigned n_frames) {
+static pa_memchunk *remap_channels(pa_resampler *r, pa_memchunk *input) {
     struct impl_libsamplerate *u;
-    unsigned n_samples;
+    unsigned n_samples, n_frames;
     int i_skip, o_skip;
     unsigned oc;
+    float *src, *dst;
 
     assert(r);
     assert(input);
+    assert(input->memblock);
+
     assert(r->impl_data);
     u = r->impl_data;
 
     /* Remap channels and place the result int buf2 */
 
-    if (!u->map_required)
+    if (!u->map_required || !input->length)
         return input;
 
-    n_samples = n_frames * r->o_ss.channels;
+    n_samples = input->length / sizeof(float);
+    n_frames = n_samples / r->o_ss.channels;
 
-    if (u->buf2_samples < n_samples) {
-        if (u->buf2_block)
-            pa_memblock_unref(u->buf2_block);
+    if (!u->buf2.memblock || u->buf2_samples < n_samples) {
+        if (u->buf2.memblock)
+            pa_memblock_unref(u->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;
+        u->buf2.memblock = pa_memblock_new(r->mempool, u->buf2.length = sizeof(float) * n_samples);
+        u->buf2.index = 0;
     }
 
-    memset(u->buf2, 0, n_samples * sizeof(float));
+    src = (float*) ((uint8_t*) pa_memblock_acquire(input->memblock) + input->index);
+    dst = (float*) pa_memblock_acquire(u->buf2.memblock);
+
+    memset(dst, 0, n_samples * sizeof(float));
 
     o_skip = sizeof(float) * r->o_ss.channels;
     i_skip = sizeof(float) * r->i_ss.channels;
@@ -340,49 +355,57 @@ static float *remap_channels(pa_resampler *r, float *input, unsigned n_frames) {
 
         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,
+                dst + oc, o_skip,
+                dst + oc, o_skip,
+                src + u->map_table[oc][i], i_skip,
                 n_frames,
                 &one, &one);
     }
 
-    return u->buf2;
+    pa_memblock_release(input->memblock);
+    pa_memblock_release(u->buf2.memblock);
+
+    u->buf2.length = n_frames * sizeof(float) * r->o_ss.channels;
+
+    return &u->buf2;
 }
 
-static float *resample(pa_resampler *r, float *input, unsigned *n_frames) {
+static pa_memchunk *resample(pa_resampler *r, pa_memchunk *input) {
     struct impl_libsamplerate *u;
     SRC_DATA data;
+    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;
 
     /* Resample the data and place the result in buf3 */
 
-    if (!u->src_state)
+    if (!u->src_state || !input->length)
         return input;
 
-    out_n_frames = (*n_frames*r->o_ss.rate/r->i_ss.rate)+1024;
+    in_n_samples = input->length / sizeof(float);
+    in_n_frames = in_n_samples * r->o_ss.channels;
+
+    out_n_frames = (in_n_frames*r->o_ss.rate/r->i_ss.rate)+1024;
     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);
+    if (!u->buf3.memblock || u->buf3_samples < out_n_samples) {
+        if (u->buf3.memblock)
+            pa_memblock_unref(u->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;
+        u->buf3.memblock = pa_memblock_new(r->mempool, u->buf3.length = sizeof(float) * out_n_samples);
+        u->buf3.index = 0;
     }
 
-    data.data_in = input;
-    data.input_frames = *n_frames;
+    data.data_in = (float*) ((uint8_t*) pa_memblock_acquire(input->memblock) + input->index);
+    data.input_frames = in_n_frames;
 
-    data.data_out = u->buf3;
+    data.data_out = (float*) pa_memblock_acquire(u->buf3.memblock);
     data.output_frames = out_n_frames;
 
     data.src_ratio = (double) r->o_ss.rate / r->i_ss.rate;
@@ -390,16 +413,20 @@ static float *resample(pa_resampler *r, float *input, unsigned *n_frames) {
 
     ret = src_process(u->src_state, &data);
     assert(ret == 0);
-    assert((unsigned) data.input_frames_used == *n_frames);
+    assert((unsigned) data.input_frames_used == in_n_frames);
 
-    *n_frames = data.output_frames_gen;
+    pa_memblock_release(input->memblock);
+    pa_memblock_release(u->buf3.memblock);
 
-    return u->buf3;
+    u->buf3.length = data.output_frames_gen * sizeof(float) * r->o_ss.channels;
+
+    return &u->buf3;
 }
 
-static void *convert_from_float(pa_resampler *r, float *input, unsigned n_frames) {
+static pa_memchunk *convert_from_float(pa_resampler *r, pa_memchunk *input) {
     struct impl_libsamplerate *u;
-    unsigned n_samples;
+    unsigned n_samples, n_frames;
+    void *src, *dst;
 
     assert(r);
     assert(input);
@@ -408,30 +435,35 @@ static void *convert_from_float(pa_resampler *r, float *input, unsigned n_frames
 
     /* Convert the data into the correct sample type and place the result in buf4 */
 
-    if (!u->from_float32ne_func)
+    if (!u->from_float32ne_func || !input->length)
         return input;
 
+    n_frames = input->length / sizeof(float) / r->o_ss.channels;
     n_samples = n_frames * r->o_ss.channels;
 
     if (u->buf4_samples < n_samples) {
-        if (u->buf4_block)
-            pa_memblock_unref(u->buf4_block);
+        if (u->buf4.memblock)
+            pa_memblock_unref(u->buf4.memblock);
 
         u->buf4_samples = n_samples;
-        u->buf4_block = pa_memblock_new(r->mempool, sizeof(float) * n_samples);
-        u->buf4 = u->buf4_block->data;
+        u->buf4.memblock = pa_memblock_new(r->mempool, u->buf4.length = r->o_fz * n_frames);
+        u->buf4.index = 0;
     }
 
-    u->from_float32ne_func(n_samples, input, u->buf4);
+    src = (uint8_t*) pa_memblock_acquire(input->memblock) + input->length;
+    dst = pa_memblock_acquire(u->buf4.memblock);
+    u->from_float32ne_func(n_samples, src, dst);
+    pa_memblock_release(input->memblock);
+    pa_memblock_release(u->buf4.memblock);
 
-    return u->buf4;
+    u->buf4.length = r->o_fz * n_frames;
+
+    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;
+    pa_memchunk *buf;
 
     assert(r);
     assert(in);
@@ -443,55 +475,23 @@ static void libsamplerate_run(pa_resampler *r, const pa_memchunk *in, pa_memchun
 
     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;
-            }
-
-            assert(out->memblock);
-        }
-    } else {
-        out->memblock = NULL;
-        out->index = out->length = 0;
-    }
+    buf = convert_to_float(r, (pa_memchunk*) in);
+    buf = remap_channels(r, buf);
+    buf = resample(r, buf);
+
+    if (buf->length) {
+        buf = convert_from_float(r, buf);
+        *out = *buf;
+
+        if (buf == in)
+            pa_memblock_ref(buf->memblock);
+        else
+            pa_memchunk_reset(buf);
+    } else
+        pa_memchunk_reset(out);
+
+    pa_memblock_release(in->memblock);
+
 }
 
 static void libsamplerate_update_input_rate(pa_resampler *r, uint32_t rate) {
@@ -518,8 +518,10 @@ static int libsamplerate_init(pa_resampler *r) {
 
     r->impl_data = u = pa_xnew(struct impl_libsamplerate, 1);
 
-    u->buf1 = u->buf2 = u->buf3 = u->buf4 = NULL;
-    u->buf1_block = u->buf2_block = u->buf3_block = u->buf4_block = NULL;
+    pa_memchunk_reset(&u->buf1);
+    pa_memchunk_reset(&u->buf2);
+    pa_memchunk_reset(&u->buf3);
+    pa_memchunk_reset(&u->buf4);
     u->buf1_samples = u->buf2_samples = u->buf3_samples = u->buf4_samples = 0;
 
     if (r->i_ss.format == PA_SAMPLE_FLOAT32NE)
@@ -580,6 +582,7 @@ static void trivial_run(pa_resampler *r, const pa_memchunk *in, pa_memchunk *out
         /* Do real resampling */
         size_t l;
         unsigned o_index;
+        void *src, *dst;
 
         /* The length of the new memory block rounded up */
         l = ((((n_frames+1) * r->o_ss.rate) / r->i_ss.rate) + 1) * fz;
@@ -587,6 +590,9 @@ static void trivial_run(pa_resampler *r, const pa_memchunk *in, pa_memchunk *out
         out->index = 0;
         out->memblock = pa_memblock_new(r->mempool, l);
 
+        src = (uint8_t*) pa_memblock_acquire(in->memblock) + in->index;
+        dst = pa_memblock_acquire(out->memblock);
+
         for (o_index = 0;; o_index++, u->o_counter++) {
             unsigned j;
 
@@ -596,13 +602,16 @@ static void trivial_run(pa_resampler *r, const pa_memchunk *in, pa_memchunk *out
             if (j >= n_frames)
                 break;
 
-            assert(o_index*fz < out->memblock->length);
+            assert(o_index*fz < pa_memblock_get_length(out->memblock));
 
-            memcpy((uint8_t*) out->memblock->data + fz*o_index,
-                   (uint8_t*) in->memblock->data + in->index + fz*j, fz);
+            memcpy((uint8_t*) dst + fz*o_index,
+                   (uint8_t*) src + fz*j, fz);
 
         }
 
+        pa_memblock_release(in->memblock);
+        pa_memblock_release(out->memblock);
+
         out->length = o_index*fz;
     }
 
diff --git a/src/pulsecore/sample-util.c b/src/pulsecore/sample-util.c
index a997140..2e51427 100644
--- a/src/pulsecore/sample-util.c
+++ b/src/pulsecore/sample-util.c
@@ -61,15 +61,27 @@ pa_memblock *pa_silence_memblock_new(pa_mempool *pool, const pa_sample_spec *spe
 }
 
 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;
+
+    assert(b);
+    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);
+    assert(c);
+    assert(c->memblock);
+    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) {
@@ -98,26 +110,38 @@ void pa_silence_memory(void *p, size_t length, const pa_sample_spec *spec) {
 }
 
 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;
+
+    assert(streams);
+    assert(data);
+    assert(length);
+    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 +151,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));
@@ -155,17 +179,18 @@ size_t pa_mix(
                 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 +200,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 = 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));
@@ -203,17 +228,18 @@ size_t pa_mix(
                 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 +249,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));
@@ -251,17 +277,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 +298,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,17 +322,34 @@ 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));
+void pa_volume_memchunk(
+        pa_memchunk*c,
+        const pa_sample_spec *spec,
+        const pa_cvolume *volume) {
+
+    void *ptr;
+
+    assert(c);
+    assert(spec);
+    assert(c->length % pa_frame_size(spec) == 0);
     assert(volume);
 
     if (pa_cvolume_channels_equal_to(volume, PA_VOLUME_NORM))
@@ -316,6 +360,8 @@ 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;
@@ -326,7 +372,7 @@ void pa_volume_memchunk(pa_memchunk*c, const pa_sample_spec *spec, const pa_cvol
             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--) {
+            for (channel = 0, d = (int16_t*) ((uint8_t*) ptr + c->index), n = c->length/sizeof(int16_t); n > 0; d++, n--) {
                 int32_t t = (int32_t)(*d);
 
                 t = (int32_t) (t * linear[channel]);
@@ -351,7 +397,7 @@ void pa_volume_memchunk(pa_memchunk*c, const pa_sample_spec *spec, const pa_cvol
             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--) {
+            for (channel = 0, d = (int16_t*) ((uint8_t*) ptr + c->index), n = c->length/sizeof(int16_t); n > 0; d++, n--) {
                 int32_t t = (int32_t)(INT16_SWAP(*d));
 
                 t = (int32_t) (t * linear[channel]);
@@ -373,7 +419,7 @@ void pa_volume_memchunk(pa_memchunk*c, const pa_sample_spec *spec, const pa_cvol
             size_t n;
             unsigned channel = 0;
 
-            for (d = (uint8_t*) c->memblock->data + c->index, n = c->length; n > 0; d++, n--) {
+            for (d = (uint8_t*) ptr + c->index, n = c->length; n > 0; d++, n--) {
                 int32_t t = (int32_t) *d - 0x80;
 
                 t = (int32_t) (t * pa_sw_volume_to_linear(volume->values[channel]));
@@ -395,7 +441,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;
 
@@ -418,5 +464,7 @@ void pa_volume_memchunk(pa_memchunk*c, const pa_sample_spec *spec, const pa_cvol
                 pa_sample_format_to_string(spec->format));
             abort();
     }
+
+    pa_memblock_release(c->memblock);
 }
 
diff --git a/src/pulsecore/sample-util.h b/src/pulsecore/sample-util.h
index 3ff065a..2b11ad3 100644
--- a/src/pulsecore/sample-util.h
+++ b/src/pulsecore/sample-util.h
@@ -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,
diff --git a/src/pulsecore/semaphore-posix.c b/src/pulsecore/semaphore-posix.c
new file mode 100644
index 0000000..71ec57a
--- /dev/null
+++ b/src/pulsecore/semaphore-posix.c
@@ -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.h b/src/pulsecore/semaphore.h
new file mode 100644
index 0000000..c394e0f
--- /dev/null
+++ b/src/pulsecore/semaphore.h
@@ -0,0 +1,35 @@
+#ifndef foopulsesemaphorehfoo
+#define foopulsesemaphorehfoo
+
+/* $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.
+***/
+
+typedef struct pa_semaphore pa_semaphore;
+
+pa_semaphore* pa_semaphore_new(unsigned value);
+void pa_semaphore_free(pa_semaphore *m);
+
+void pa_semaphore_post(pa_semaphore *m);
+void pa_semaphore_wait(pa_semaphore *m);
+
+#endif
diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c
index 3ddd743..da7b58b 100644
--- a/src/pulsecore/sink-input.c
+++ b/src/pulsecore/sink-input.c
@@ -27,7 +27,6 @@
 #endif
 
 #include <stdio.h>
-#include <assert.h>
 #include <stdlib.h>
 #include <string.h>
 
@@ -46,41 +45,45 @@
 #define MOVE_BUFFER_LENGTH (1024*1024)
 #define SILENCE_BUFFER_LENGTH (64*1024)
 
-#define CHECK_VALIDITY_RETURN_NULL(condition) \
-do {\
-if (!(condition)) \
-    return NULL; \
-} while (0)
+static void sink_input_free(pa_msgobject *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, int mute) {
+    pa_assert(data);
+
+    data->muted_is_set = 1;
+    data->muted = !!mute;
+}
+
 pa_sink_input* pa_sink_input_new(
         pa_core *core,
         pa_sink_input_new_data *data,
@@ -88,46 +91,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;
 
-    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_DISCONNECTED);
 
     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,7 +145,7 @@ 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,
@@ -147,20 +156,31 @@ pa_sink_input* pa_sink_input_new(
             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;
+    pa_atomic_load(&i->state, PA_SINK_INPUT_DRAINED);
     i->flags = flags;
     i->name = pa_xstrdup(data->name);
     i->driver = pa_xstrdup(data->driver);
     i->module = data->module;
     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->volume = data->volume;
+    i->muted = data->muted;
+    
+    i->process_msg = NULL;
     i->peek = NULL;
     i->drop = NULL;
     i->kill = NULL;
@@ -168,94 +188,87 @@ pa_sink_input* pa_sink_input_new(
     i->underrun = NULL;
     i->userdata = NULL;
 
-    i->move_silence = 0;
+    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.soft_volume = i->volume;
+    i->thread_info.soft_muted = i->muted;
 
-    pa_memchunk_reset(&i->resampled_chunk);
-    i->resampler = resampler;
-    i->resample_method = data->resample_method;
-    i->silence_memblock = NULL;
+    pa_assert_se(pa_idxset_put(core->sink_inputs, i, &i->index) == 0);
+    pa_assert_se(pa_idxset_put(i->sink->inputs, i, NULL) == 0);
 
-    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",
+    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);
+    pa_assert(i);
+    pa_return_if_fail(pa_sink_input_get_state(i) != PA_SINK_INPUT_DISCONNECTED);
 
+    pa_asyncmsgq_send(i->sink->asyncmsgq, i->sink, PA_SINK_MESSAGE_REMOVE_INPUT, i, NULL);
+    
     pa_idxset_remove_by_data(i->sink->core->sink_inputs, i, NULL);
     pa_idxset_remove_by_data(i->sink->inputs, i, NULL);
 
     pa_subscription_post(i->sink->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_REMOVE, i->index);
     i->sink = NULL;
 
+    i->process_msg = NULL;
     i->peek = NULL;
     i->drop = NULL;
     i->kill = NULL;
     i->get_latency = NULL;
     i->underrun = NULL;
 
-    i->state = PA_SINK_INPUT_DISCONNECTED;
+    pa_atomic_load(&i->state, PA_SINK_INPUT_DISCONNECTED);
 }
 
-static void sink_input_free(pa_sink_input* i) {
-    assert(i);
+static void sink_input_free(pa_msgobject *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_sink_input_disconnect(i);
 
-    pa_log_info("freed %u \"%s\"", i->index, i->name);
+    pa_log_info("Freeing output %u \"%s\"", i->index, i->name);
 
     if (i->resampled_chunk.memblock)
         pa_memblock_unref(i->resampled_chunk.memblock);
 
-    if (i->resampler)
-        pa_resampler_free(i->resampler);
+    if (i->thread_info.resampler)
+        pa_resampler_free(i->thread_info.resampler);
 
-    if (i->silence_memblock)
-        pa_memblock_unref(i->silence_memblock);
+    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);
-}
+    i->thread_info.volume = i->volume;
+    i->thread_info.muted = i->muted;
 
-pa_sink_input* pa_sink_input_ref(pa_sink_input *i) {
-    assert(i);
-    assert(i->ref >= 1);
+    pa_asyncmsgq_post(i->sink->asyncmsgq, i->sink, PA_SINK_MESSAGE_ADD_INPUT, i, NULL, pa_sink_unref, pa_sink_input_unref);
+    pa_sink_update_status(i->sink);
 
-    i->ref++;
-    return i;
+    pa_subscription_post(core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_NEW, i->index);
 }
 
 void pa_sink_input_kill(pa_sink_input*i) {
-    assert(i);
-    assert(i->ref >= 1);
+    pa_sink_input_assert_ref(i);
 
     if (i->kill)
         i->kill(i);
@@ -264,18 +277,14 @@ 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);
 
+    if (pa_asyncmsgq_send(i->sink->asyncmsgq, i->sink, PA_SINK_INPUT_MESSAGE_GET_LATENCY, &r, 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;
 }
 
@@ -283,35 +292,40 @@ int pa_sink_input_peek(pa_sink_input *i, pa_memchunk *chunk, pa_cvolume *volume)
     int ret = -1;
     int do_volume_adj_here;
     int volume_is_norm;
+    pa_sink_input_state_t state;
+    
+    pa_sink_input_assert_ref(i);
+    pa_assert(chunk);
+    pa_assert(volume);
 
-    assert(i);
-    assert(i->ref >= 1);
-    assert(chunk);
-    assert(volume);
+    state = pa_sink_input_get_state(i);
 
-    pa_sink_input_ref(i);
+    if (state == PA_SINK_INPUT_DISCONNECTED)
+        return -1;
 
-    if (!i->peek || !i->drop || i->state == PA_SINK_INPUT_CORKED)
+    if (!i->peek || !i->drop || state == PA_SINK_INPUT_CORKED)
         goto finish;
 
-    assert(i->state == PA_SINK_INPUT_RUNNING || i->state == PA_SINK_INPUT_DRAINED);
+    pa_assert(state == PA_SINK_INPUT_RUNNING || state == PA_SINK_INPUT_DRAINED);
 
-    if (i->move_silence > 0) {
+/*     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 */
+/*         /\* 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, SILENCE_BUFFER_LENGTH); */
 
-        chunk->memblock = pa_memblock_ref(i->silence_memblock);
-        chunk->index = 0;
-        chunk->length = i->move_silence < chunk->memblock->length ? i->move_silence : chunk->memblock->length;
+/*         chunk->memblock = pa_memblock_ref(i->thread_info.silence_memblock); */
+/*         chunk->index = 0; */
+/*         l = pa_memblock_get_length(chunk->memblock); */
+/*         chunk->length = i->move_silence < l ? i->move_silence : l; */
 
-        ret = 0;
-        do_volume_adj_here = 1;
-        goto finish;
-    }
+/*         ret = 0; */
+/*         do_volume_adj_here = 1; */
+/*         goto finish; */
+/*     } */
 
     if (!i->resampler) {
         do_volume_adj_here = 0;
@@ -320,16 +334,16 @@ int pa_sink_input_peek(pa_sink_input *i, pa_memchunk *chunk, pa_cvolume *volume)
     }
 
     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.soft_volume) && !i->thread_info.soft_muted;
 
-    while (!i->resampled_chunk.memblock) {
+    while (!i->thread_info.resampled_chunk.memblock) {
         pa_memchunk tchunk;
         size_t l;
 
         if ((ret = i->peek(i, &tchunk)) < 0)
             goto finish;
 
-        assert(tchunk.length);
+        pa_assert(tchunk.length);
 
         l = pa_resampler_request(i->resampler, CONVERT_BUFFER_LENGTH);
 
@@ -342,30 +356,30 @@ int pa_sink_input_peek(pa_sink_input *i, pa_memchunk *chunk, pa_cvolume *volume)
         /* 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);
+            pa_volume_memchunk(&tchunk, &i->sample_spec, &i->thread_info.soft_volume);
         }
 
-        pa_resampler_run(i->resampler, &tchunk, &i->resampled_chunk);
+        pa_resampler_run(i->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);
 
-    *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)
+    if (ret < 0 && state == PA_SINK_INPUT_RUNNING && i->underrun)
         i->underrun(i);
 
     if (ret >= 0)
-        i->state = PA_SINK_INPUT_RUNNING;
+        pa_atomic_cmpxchg(&i->state, state, PA_SINK_INPUT_RUNNING);
     else if (ret < 0 && i->state == PA_SINK_INPUT_RUNNING)
-        i->state = PA_SINK_INPUT_DRAINED;
+        pa_atomic_cmpxchg(&i->state, state, PA_SINK_INPUT_DRAINED);
 
     if (ret >= 0) {
         /* Let's see if we had to apply the volume adjustment
@@ -376,42 +390,42 @@ finish:
             pa_cvolume_reset(volume, i->sink->sample_spec.channels);
         else
             /* We've both the same channel map, so let's have the sink do the adjustment for us*/
-            *volume = i->volume;
+            *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);
+    pa_sink_input_assert_ref(i);
+    pa_assert(length > 0);
 
-    if (i->move_silence > 0) {
+/*     if (i->move_silence > 0) { */
 
-        if (chunk) {
+/*         if (chunk) { */
+/*             size_t l; */
 
-            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;
+/*             l = pa_memblock_get_length(i->silence_memblock); */
 
-        }
+/*             if (chunk->memblock != i->silence_memblock || */
+/*                 chunk->index != 0 || */
+/*                 (chunk->memblock && (chunk->length != (l < i->move_silence ? l : i->move_silence)))) */
+/*                 return; */
 
-        assert(i->move_silence >= length);
+/*         } */
 
-        i->move_silence -= length;
+/*         pa_assert(i->move_silence >= length); */
 
-        if (i->move_silence <= 0) {
-            assert(i->silence_memblock);
-            pa_memblock_unref(i->silence_memblock);
-            i->silence_memblock = NULL;
-        }
+/*         i->move_silence -= length; */
 
-        return;
-    }
+/*         if (i->move_silence <= 0) { */
+/*             pa_assert(i->silence_memblock); */
+/*             pa_memblock_unref(i->silence_memblock); */
+/*             i->silence_memblock = NULL; */
+/*         } */
+
+/*         return; */
+/*     } */
 
     if (!i->resampler) {
         if (i->drop)
@@ -419,75 +433,88 @@ void pa_sink_input_drop(pa_sink_input *i, const pa_memchunk *chunk, size_t lengt
         return;
     }
 
-    assert(i->resampled_chunk.memblock);
-    assert(i->resampled_chunk.length >= length);
+    pa_assert(i->thread_info.resampled_chunk.memblock);
+    pa_assert(i->thread_info.resampled_chunk.length >= length);
 
-    i->resampled_chunk.index += length;
-    i->resampled_chunk.length -= length;
+    i->thread_info.resampled_chunk.index += length;
+    i->thread_info.resampled_chunk.length -= length;
 
-    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;
+    if (i->thread_info.resampled_chunk.length <= 0) {
+        pa_memblock_unref(i->thread_info.resampled_chunk.memblock);
+        i->thread_info.resampled_chunk.memblock = NULL;
+        i->thread_info.resampled_chunk.index = i->thread_info.resampled_chunk.length = 0;
     }
 }
 
 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);
 
     if (pa_cvolume_equal(&i->volume, volume))
         return;
 
     i->volume = *volume;
+
+    pa_asyncmsgq_post(s->asyncmsgq, pa_sink_input_ref(i), PA_SINK_INPUT_MESSAGE_SET_VOLUME, pa_xnewdup(struct pa_cvolume, volume, 1), pa_sink_input_unref, 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);
 
     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, int mute) {
+    pa_assert(i);
+    pa_sink_input_assert_ref(i);
+
+    if (!i->muted == !mute)
+        return;
+
+    i->muted = mute;
+
+    pa_asyncmsgq_post(s->asyncmsgq, pa_sink_input_ref(i), PA_SINK_INPUT_MESSAGE_SET_MUTE, PA_UINT_TO_PTR(mute), pa_sink_input_unref, NULL);
+    pa_subscription_post(i->sink->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index);
+}
 
-    assert(i);
-    assert(i->ref >= 1);
+int pa_sink_input_get_mute(pa_sink_input *i) {
+    pa_sink_input_assert_ref(i);
 
-    assert(i->state != PA_SINK_INPUT_DISCONNECTED);
+    return !!i->mute;
+}
+
+void pa_sink_input_cork(pa_sink_input *i, int b) {
+    int n;
+    pa_sink_input_state_t state;
 
-    n = i->state == PA_SINK_INPUT_CORKED && !b;
+    pa_sink_input_assert_ref(i);
 
-    if (b)
-        i->state = PA_SINK_INPUT_CORKED;
-    else if (i->state == PA_SINK_INPUT_CORKED)
-        i->state = PA_SINK_INPUT_DRAINED;
+    state = pa_sink_input_get_state(i);
+    pa_assert(state != PA_SINK_INPUT_DISCONNECTED);
 
-    if (n)
-        pa_sink_notify(i->sink);
+    if (b && state != PA_SINK_INPUT_CORKED)
+        pa_atomic_store(i->state, PA_SINK_INPUT_CORKED);
+    else if (!b && state == PA_SINK_INPUT_CORKED)
+        pa_atomic_cmpxchg(i->state, state, PA_SINK_INPUT_DRAINED);
 }
 
-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_return_val_if_fail(u->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(s->asyncmsgq, pa_sink_input_ref(i), PA_SINK_INPUT_MESSAGE_SET_RATE, PA_UINT_TO_PTR(rate), NULL, pa_sink_input_unref, 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;
@@ -502,13 +529,9 @@ void pa_sink_input_set_name(pa_sink_input *i, const char *name) {
 }
 
 pa_resample_method_t pa_sink_input_get_resample_method(pa_sink_input *i) {
-    assert(i);
-    assert(i->ref >= 1);
-
-    if (!i->resampler)
-        return i->resample_method;
+    pa_sink_input_assert_ref(i);
 
-    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) {
@@ -516,156 +539,196 @@ int pa_sink_input_move_to(pa_sink_input *i, pa_sink *dest, int immediately) {
     pa_memblockq *buffer = NULL;
     pa_sink *origin;
 
-    assert(i);
-    assert(dest);
+    pa_sink_input_assert_ref(i);
+    pa_sink_assert_ref(dest);
 
-    origin = i->sink;
+    return -1;
+    
+/*     origin = i->sink; */
 
-    if (dest == origin)
-        return 0;
+/*     if (dest == origin) */
+/*         return 0; */
 
-    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 (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 &&
-        pa_sample_spec_equal(&origin->sample_spec, &dest->sample_spec) &&
-        pa_channel_map_equal(&origin->channel_map, &dest->channel_map))
+/*     if (i->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;
+/*         /\* Try to reuse the old resampler if possible *\/ */
+/*         new_resampler = i->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)) {
+/*     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)) { */
 
-        /* Okey, we need a new resampler for the new sink */
+/*         /\* Okey, we need a new resampler for the new sink *\/ */
 
-        if (!(new_resampler = pa_resampler_new(
-                      dest->core->mempool,
-                      &i->sample_spec, &i->channel_map,
-                      &dest->sample_spec, &dest->channel_map,
-                      i->resample_method))) {
-            pa_log_warn("Unsupported resampling operation.");
-            return -1;
-        }
-    }
+/*         if (!(new_resampler = pa_resampler_new( */
+/*                       dest->core->mempool, */
+/*                       &i->sample_spec, &i->channel_map, */
+/*                       &dest->sample_spec, &dest->channel_map, */
+/*                       i->resample_method))) { */
+/*             pa_log_warn("Unsupported resampling operation."); */
+/*             return -1; */
+/*         } */
+/*     } */
 
-    if (!immediately) {
-        pa_usec_t old_latency, new_latency;
-        pa_usec_t silence_usec = 0;
+/*     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);
+/*         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 */
+/*         /\* Let's do a little bit of Voodoo for compensating latency */
+/*          * differences *\/ */
 
-        old_latency = pa_sink_get_latency(origin);
-        new_latency = pa_sink_get_latency(dest);
+/*         old_latency = pa_sink_get_latency(origin); */
+/*         new_latency = pa_sink_get_latency(dest); */
 
-        /* The already resampled data should go to the old sink */
+/*         /\* The already resampled data should go to the old sink *\/ */
 
-        if (old_latency >= new_latency) {
+/*         if (old_latency >= new_latency) { */
 
-            /* The latency of the old sink is larger than the latency
-             * of the new sink. Therefore to compensate for the
-             * difference we to play silence on the new one for a
-             * while */
+/*             /\* The latency of the old sink is larger than the latency */
+/*              * of the new sink. Therefore to compensate for the */
+/*              * difference we to play silence on the new one for a */
+/*              * while *\/ */
 
-            silence_usec = old_latency - new_latency;
+/*             silence_usec = old_latency - new_latency; */
 
-        } else {
-            size_t l;
-            int volume_is_norm;
+/*         } 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
-             * and make sure that this is still played on the old
-             * sink, until we can play the first sample on the new
-             * sink.*/
+/*             /\* The latency of new sink is larger than the latency of */
+/*              * the old sink. Therefore we have to precompute a little */
+/*              * and make sure that this is still played on the old */
+/*              * sink, until we can play the first sample on the new */
+/*              * sink.*\/ */
 
-            l = pa_usec_to_bytes(new_latency - old_latency, &origin->sample_spec);
+/*             l = pa_usec_to_bytes(new_latency - old_latency, &origin->sample_spec); */
 
-            volume_is_norm = pa_cvolume_is_norm(&i->volume);
+/*             volume_is_norm = pa_cvolume_is_norm(&i->volume); */
 
-            while (l > 0) {
-                pa_memchunk chunk;
-                pa_cvolume volume;
-                size_t n;
+/*             while (l > 0) { */
+/*                 pa_memchunk chunk; */
+/*                 pa_cvolume volume; */
+/*                 size_t n; */
 
-                if (pa_sink_input_peek(i, &chunk, &volume) < 0)
-                    break;
+/*                 if (pa_sink_input_peek(i, &chunk, &volume) < 0) */
+/*                     break; */
 
-                n = chunk.length > l ? l : chunk.length;
-                pa_sink_input_drop(i, &chunk, n);
-                chunk.length = n;
+/*                 n = chunk.length > l ? l : chunk.length; */
+/*                 pa_sink_input_drop(i, &chunk, n); */
+/*                 chunk.length = n; */
 
-                if (!volume_is_norm) {
-                    pa_memchunk_make_writable(&chunk, 0);
-                    pa_volume_memchunk(&chunk, &origin->sample_spec, &volume);
-                }
+/*                 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;
-                }
+/*                 if (pa_memblockq_push(buffer, &chunk) < 0) { */
+/*                     pa_memblock_unref(chunk.memblock); */
+/*                     break; */
+/*                 } */
 
-                pa_memblock_unref(chunk.memblock);
-                l -= n;
-            }
-        }
+/*                 pa_memblock_unref(chunk.memblock); */
+/*                 l -= n; */
+/*             } */
+/*         } */
 
-        if (i->resampled_chunk.memblock) {
+/*         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 */
+/*             /\* 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_memblockq_push(buffer, &i->resampled_chunk);
-            silence_usec += pa_bytes_to_usec(i->resampled_chunk.length, &origin->sample_spec);
-        }
+/*             pa_memblockq_push(buffer, &i->resampled_chunk); */
+/*             silence_usec += pa_bytes_to_usec(i->resampled_chunk.length, &origin->sample_spec); */
+/*         } */
 
-        /* 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);
-    }
+/*         /\* 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); */
+/*     } */
 
-    /* Okey, let's move it */
-    pa_idxset_remove_by_data(origin->inputs, i, NULL);
-    pa_idxset_put(dest->inputs, i, NULL);
-    i->sink = dest;
-
-    /* Replace resampler */
-    if (new_resampler != i->resampler) {
-        if (i->resampler)
-            pa_resampler_free(i->resampler);
-        i->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;
-        }
-    }
+/*     /\* Okey, let's move it *\/ */
+/*     pa_idxset_remove_by_data(origin->inputs, i, NULL); */
+/*     pa_idxset_put(dest->inputs, i, NULL); */
+/*     i->sink = dest; */
 
-    /* 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;
-    }
+/*     /\* Replace resampler *\/ */
+/*     if (new_resampler != i->resampler) { */
+/*         if (i->resampler) */
+/*             pa_resampler_free(i->resampler); */
+/*         i->resampler = new_resampler; */
 
-    /* Notify everyone */
-    pa_subscription_post(i->sink->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index);
-    pa_sink_notify(i->sink);
+/*         /\* 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; */
+/*         } */
+/*     } */
+
+/*     /\* 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; */
+/*     } */
 
-    /* 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);
+/*     /\* 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, now 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; */
+}
+
+int pa_sink_input_process_msg(pa_msgobject *o, int code, void *userdata, pa_memchunk *chunk) {
+    pa_sink_input *i = PA_SINK_INPUT(o);
+    
+    pa_sink_input_assert_ref(i);
+
+    switch (code) {
+        case PA_SINK_INPUT_MESSAGE_SET_VOLUME:
+            s->thread_info.soft_volume = *((pa_cvolume*) userdata);
+            return 0;
+            
+        case PA_SINK_INPUT_MESSAGE_SET_MUTE:
+            s->thread_info.soft_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->resampled_chunk.length, &i->sink->sample_spec);
+
+/*             if (i->move_silence) */
+/*                 r += pa_bytes_to_usec(i->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->resampler, PA_PTR_TO_UINT(userdata));
+
+            return 0;
+        }
+    }
 
-    return 0;
+    return -1;
 }
diff --git a/src/pulsecore/sink-input.h b/src/pulsecore/sink-input.h
index 51d9ec7..64a7a73 100644
--- a/src/pulsecore/sink-input.h
+++ b/src/pulsecore/sink-input.h
@@ -1,5 +1,5 @@
-#ifndef foosinkinputhfoo
-#define foosinkinputhfoo
+#ifndef foopulsesinkinputhfoo
+#define foopulsesinkinputhfoo
 
 /* $Id$ */
 
@@ -51,9 +51,11 @@ typedef enum pa_sink_input_flags {
 } pa_sink_input_flags_t;
 
 struct pa_sink_input {
-    int ref;
+    pa_msgobject parent;
+    
     uint32_t index;
-    pa_sink_input_state_t state;
+    pa_core *core;
+    pa_atomic_t state;
     pa_sink_input_flags_t flags;
 
     char *name, *driver;                /* may be NULL */
@@ -64,27 +66,47 @@ struct pa_sink_input {
 
     pa_sample_spec sample_spec;
     pa_channel_map channel_map;
+    
     pa_cvolume volume;
+    int muted;
 
-    /* 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;
-
+    int (*process_msg)(pa_sink_input *i, int code, void *userdata); 
     int (*peek) (pa_sink_input *i, pa_memchunk *chunk);
     void (*drop) (pa_sink_input *i, const pa_memchunk *chunk, size_t length);
     void (*kill) (pa_sink_input *i);             /* may be NULL */
     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_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_cvolume volume;
+        int muted;
+    } thread_info;
+    
+    void *userdata;
+};
 
-    pa_resample_method_t resample_method;
+PA_DECLARE_CLASS(pa_sink_input);
+#define PA_SINK_INPUT(o) ((pa_sink_input*) (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_MAX
 };
 
 typedef struct pa_sink_input_new_data {
@@ -100,6 +122,8 @@ typedef struct pa_sink_input_new_data {
     int channel_map_is_set;
     pa_cvolume volume;
     int volume_is_set;
+    int muted;
+    int muted_is_set;
 
     pa_resample_method_t resample_method;
 } pa_sink_input_new_data;
@@ -108,37 +132,46 @@ 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, int 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);
-
-/* To be called by the implementing module only */
+void pa_sink_input_put(pa_sink_input *i);
 void pa_sink_input_disconnect(pa_sink_input* i);
 
-/* External code may request disconnection with this funcion */
+void pa_sink_input_set_name(pa_sink_input *i, const char *name);
+
+/* 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, int 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_set_rate(pa_sink_input *i, uint32_t rate);
 
-void pa_sink_input_set_name(pa_sink_input *i, const char *name);
-
 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);
 
+#define pa_sink_input_get_state(i) ((pa_sink_input_state_t) pa_atomic_load(&i->state))
+
+/* To be used exclusively by the sink driver thread */
+
+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);
+int pa_sink_input_process_msg(pa_msgobject *o, int code, void *userdata, pa_memchunk *chunk);
+
 #endif
diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c
index 9588c2c..3620559 100644
--- a/src/pulsecore/sink.c
+++ b/src/pulsecore/sink.c
@@ -41,16 +41,13 @@
 #include <pulsecore/sample-util.h>
 #include <pulsecore/core-subscribe.h>
 #include <pulsecore/log.h>
+#include <pulsecore/macro.h>
 
 #include "sink.h"
 
 #define MAX_MIX_CHANNELS 32
 
-#define CHECK_VALIDITY_RETURN_NULL(condition) \
-do {\
-if (!(condition)) \
-    return NULL; \
-} while (0)
+static void sink_free(pa_object *s);
 
 pa_sink* pa_sink_new(
         pa_core *core,
@@ -66,60 +63,64 @@ pa_sink* pa_sink_new(
     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;
+    pa_atomic_store(&s->state, PA_SINK_IDLE);
     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);
 
-    pa_cvolume_reset(&s->sw_volume, spec->channels);
-    pa_cvolume_reset(&s->hw_volume, spec->channels);
-    s->sw_muted = 0;
-    s->hw_muted = 0;
+    pa_cvolume_reset(&s->volume, spec->channels);
+    s->muted = 0;
+    s->refresh_volume = s->refresh_mute = 0;
 
     s->is_hardware = 0;
 
     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->start = NULL;
+    s->stop = NULL;
     s->userdata = NULL;
 
+    pa_assert_se(s->asyncmsgq = pa_asyncmsgq_new(0));
+    
     r = pa_idxset_put(core->sinks, s, &s->index);
-    assert(s->index != PA_IDXSET_INVALID && r >= 0);
+    pa_assert(s->index != PA_IDXSET_INVALID && r >= 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);
 
@@ -135,24 +136,64 @@ pa_sink* pa_sink_new(
 
     pa_xfree(n);
 
+    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;
+    
     pa_subscription_post(core, PA_SUBSCRIPTION_EVENT_SINK | PA_SUBSCRIPTION_EVENT_NEW, s->index);
 
     return s;
 }
 
+static void sink_start(pa_sink *s) {
+    pa_sink_state_t state;
+    pa_assert(s);
+
+    state = pa_sink_get_state(s);
+    pa_return_if_fail(state == PA_SINK_IDLE || state == PA_SINK_SUSPENDED);
+
+    pa_atomic_store(&s->state, PA_SINK_RUNNING);
+
+    if (s->start)
+        s->start(s);
+    else
+        pa_asyncmsgq_post(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_START, NULL, NULL, NULL);
+}
+
+static void sink_stop(pa_sink *s) {
+    pa_sink_state_t state;
+    int stop;
+    
+    pa_assert(s);
+    state = pa_sink_get_state(s);
+    pa_return_if_fail(state == PA_SINK_RUNNING || state == PA_SINK_SUSPENDED);
+
+    stop = state == PA_SINK_RUNNING;
+    pa_atomic_store(&s->state, PA_SINK_IDLE);
+
+    if (stop) {
+        if (s->stop)
+            s->stop(s);
+        else
+            pa_asyncmsgq_post(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_STOP, NULL, NULL, NULL);
+    }
+}
+
 void pa_sink_disconnect(pa_sink* s) {
     pa_sink_input *i, *j = NULL;
 
-    assert(s);
-    assert(s->state == PA_SINK_RUNNING);
+    pa_assert(s);
+    pa_return_if_fail(pa_sink_get_state(s) != PA_SINK_DISCONNECTED);
 
-    s->state = PA_SINK_DISCONNECTED;
+    sink_stop(s);
+
+    pa_atomic_store(&s->state, PA_SINK_DISCONNECTED);
     pa_namereg_unregister(s->core, s->name);
 
     pa_hook_fire(&s->core->hook_sink_disconnect, s);
 
     while ((i = pa_idxset_first(s->inputs, NULL))) {
-        assert(i != j);
+        pa_assert(i != j);
         pa_sink_input_kill(i);
         j = i;
     }
@@ -163,23 +204,25 @@ void pa_sink_disconnect(pa_sink* s) {
     pa_idxset_remove_by_data(s->core->sinks, s, NULL);
 
     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->start = NULL;
+    s->stop = NULL;
 
     pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK | PA_SUBSCRIPTION_EVENT_REMOVE, s->index);
 }
 
-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_assert(s);
+    pa_assert(pa_sink_refcnt(s) == 0);
 
-    if (s->state != PA_SINK_DISCONNECTED)
-        pa_sink_disconnect(s);
+    pa_sink_disconnect(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);
@@ -187,47 +230,66 @@ static void sink_free(pa_sink *s) {
     }
 
     pa_idxset_free(s->inputs, NULL, NULL);
+    
+    pa_hashmap_free(s->thread_info.inputs, (pa_free2_cb_t) pa_sink_input_unref, NULL);
 
+    pa_asyncmsgq_free(s->asyncmsgq);
+    
     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_update_status(pa_sink*s) {
+    pa_sink_assert_ref(s);
 
-    if (!(--s->ref))
-        sink_free(s);
+    if (pa_sink_get_state(s) == PA_SINK_SUSPENDED)
+        return;
+    
+    if (pa_sink_used_by(s) > 0)
+        sink_start(s);
+    else
+        sink_stop(s);
 }
 
-pa_sink* pa_sink_ref(pa_sink *s) {
-    assert(s);
-    assert(s->ref >= 1);
+void pa_sink_suspend(pa_sink *s, int suspend) {
+    pa_sink_state_t state;
 
-    s->ref++;
-    return s;
-}
+    pa_sink_assert_ref(s);
 
-void pa_sink_notify(pa_sink*s) {
-    assert(s);
-    assert(s->ref >= 1);
+    state = pa_sink_get_state(s);
+    pa_return_if_fail(suspend && (state == PA_SINK_RUNNING || state == PA_SINK_IDLE));
+    pa_return_if_fail(!suspend && (state == PA_SINK_SUSPENDED));
 
-    if (s->notify)
-        s->notify(s);
+
+    if (suspend) {
+        pa_atomic_store(&s->state, PA_SINK_SUSPENDED);
+
+        if (s->stop)
+            s->stop(s);
+        else
+            pa_asyncmsgq_post(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_STOP, NULL, NULL, NULL);
+        
+    } else {
+        pa_atomic_store(&s->state, PA_SINK_RUNNING);
+
+        if (s->start)
+            s->start(s);
+        else
+            pa_asyncmsgq_post(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_START, NULL, NULL, NULL);
+    }
 }
 
 static unsigned fill_mix_info(pa_sink *s, pa_mix_info *info, unsigned maxinfo) {
-    uint32_t idx = PA_IDXSET_INVALID;
     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)) {
+    while ((i = pa_hashmap_iterate(s->thread_info.inputs, &state, NULL))) {
         /* Increase ref counter, to make sure that this input doesn't
          * vanish while we still need it */
         pa_sink_input_ref(i);
@@ -239,9 +301,8 @@ static unsigned fill_mix_info(pa_sink *s, pa_mix_info *info, unsigned maxinfo) {
 
         info->userdata = i;
 
-        assert(info->chunk.memblock);
-        assert(info->chunk.memblock->data);
-        assert(info->chunk.length);
+        pa_assert(info->chunk.memblock);
+        pa_assert(info->chunk.length);
 
         info++;
         maxinfo--;
@@ -252,15 +313,14 @@ static unsigned fill_mix_info(pa_sink *s, pa_mix_info *info, unsigned maxinfo) {
 }
 
 static void inputs_drop(pa_sink *s, pa_mix_info *info, unsigned maxinfo, size_t length) {
-    assert(s);
-    assert(s->ref >= 1);
-    assert(info);
+    pa_sink_assert_ref(s);
+    pa_assert(info);
 
     for (; maxinfo > 0; maxinfo--, info++) {
         pa_sink_input *i = info->userdata;
 
-        assert(i);
-        assert(info->chunk.memblock);
+        pa_assert(i);
+        pa_assert(info->chunk.memblock);
 
         /* Drop read data */
         pa_sink_input_drop(i, &info->chunk, length);
@@ -277,10 +337,9 @@ int pa_sink_render(pa_sink*s, size_t length, pa_memchunk *result) {
     unsigned n;
     int r = -1;
 
-    assert(s);
-    assert(s->ref >= 1);
-    assert(length);
-    assert(result);
+    pa_sink_assert_ref(s);
+    pa_assert(length);
+    pa_assert(result);
 
     pa_sink_ref(s);
 
@@ -298,23 +357,23 @@ 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;
     }
 
@@ -336,12 +395,10 @@ int pa_sink_render_into(pa_sink*s, pa_memchunk *target) {
     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(target);
+    pa_assert(target->memblock);
+    pa_assert(target->length);
 
     pa_sink_ref(s);
 
@@ -350,30 +407,48 @@ int pa_sink_render_into(pa_sink*s, pa_memchunk *target) {
     if (n <= 0)
         goto finish;
 
-    if (n == 1) {
-        pa_cvolume volume;
 
+    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);
-
-        pa_sw_cvolume_multiply(&volume, &s->sw_volume, &info[0].volume);
-
-        if (s->sw_muted)
+        if (s->thread_info.soft_muted)
             pa_silence_memchunk(target, &s->sample_spec);
-        else if (!pa_cvolume_is_norm(&volume))
-            pa_volume_memchunk(target, &s->sample_spec, &volume);
-    } else
+        else {
+            void *src, *ptr;
+            pa_cvolume 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);
+        
         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);
+    
+        pa_memblock_release(target->memblock);
+    }
+    
     inputs_drop(s, info, n, target->length);
 
     if (s->monitor_source)
@@ -391,12 +466,10 @@ 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(target);
+    pa_assert(target->memblock);
+    pa_assert(target->length);
 
     pa_sink_ref(s);
 
@@ -425,10 +498,9 @@ void pa_sink_render_into_full(pa_sink *s, pa_memchunk *target) {
 }
 
 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(length);
+    pa_assert(result);
 
     /*** This needs optimization ***/
 
@@ -439,108 +511,109 @@ void pa_sink_render_full(pa_sink *s, size_t length, pa_memchunk *result) {
 }
 
 pa_usec_t pa_sink_get_latency(pa_sink *s) {
-    assert(s);
-    assert(s->ref >= 1);
-
-    if (!s->get_latency)
+    pa_usec_t usec = 0;
+    
+    pa_sink_assert_ref(s);
+
+    if (s->get_latency)
+        return s->get_latency(s);
+    
+    if (pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_GET_LATENCY, &usec, 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(volume);
 
-    s->owner = m;
+    changed = !pa_cvolume_equal(volume, &s->volume);
+    s->volume = *volume;
+    
+    if (s->set_volume && s->set_volume(s) < 0)
+        s->set_volume = NULL;
 
-    if (s->monitor_source)
-        pa_source_set_owner(s->monitor_source, m);
+    if (!s->set_volume)
+        pa_asyncmsgq_post(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_SET_VOLUME, pa_xnewdup(struct pa_cvolume, volume, 1), NULL, pa_xfree);
 
-    pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
+    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;
-
-    assert(s);
-    assert(s->ref >= 1);
-    assert(volume);
-
-    if (m == PA_MIXER_HARDWARE && s->set_hw_volume)
-        v = &s->hw_volume;
-    else
-        v = &s->sw_volume;
+const pa_cvolume *pa_sink_get_volume(pa_sink *s) {
+    struct pa_cvolume old_volume;
 
-    if (pa_cvolume_equal(v, volume))
-        return;
+    pa_sink_assert_ref(s);
 
-    *v = *volume;
+    old_volume = s->volume;
+    
+    if (s->get_volume && s->get_volume(s) < 0)
+        s->get_volume = NULL;
 
-    if (v == &s->hw_volume)
-        if (s->set_hw_volume(s) < 0)
-            s->sw_volume =  *volume;
+    if (!s->get_volume && s->refresh_volume)
+        pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_GET_VOLUME, &s->volume, NULL);
 
-    pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
+    if (!pa_cvolume_equal(&old_volume, &s->volume))
+        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, int mute) {
+    int changed;
+    
+    pa_sink_assert_ref(s);
 
-    if (m == PA_MIXER_HARDWARE && s->set_hw_volume) {
+    changed = 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), NULL, NULL);
 
-void pa_sink_set_mute(pa_sink *s, pa_mixer_t m, int mute) {
-    int *t;
-
-    assert(s);
-    assert(s->ref >= 1);
-
-    if (m == PA_MIXER_HARDWARE && s->set_hw_mute)
-        t = &s->hw_muted;
-    else
-        t = &s->sw_muted;
+    if (changed)
+        pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
+}
 
-    if (!!*t == !!mute)
-        return;
+int pa_sink_get_mute(pa_sink *s) {
+    int old_muted;
+    
+    pa_sink_assert_ref(s);
 
-    *t = !!mute;
+    old_muted = s->muted;
+    
+    if (s->get_mute && s->get_mute(s) < 0)
+        s->get_mute = NULL;
 
-    if (t == &s->hw_muted)
-        if (s->set_hw_mute(s) < 0)
-            s->sw_muted = !!mute;
+    if (!s->get_mute && s->refresh_mute)
+        pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_GET_MUTE, &s->muted, NULL);
 
-    pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
+    if (old_muted != s->muted)
+        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;
 
-        if (s->get_hw_mute)
-            s->get_hw_mute(s);
+    s->module = m;
 
-        return s->hw_muted;
-    } else
-        return s->sw_muted;
+    if (s->monitor_source)
+        pa_source_set_module(s->monitor_source, m);
+
+    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;
@@ -565,8 +638,7 @@ void pa_sink_set_description(pa_sink *s, const char *description) {
 unsigned pa_sink_used_by(pa_sink *s) {
     unsigned ret;
 
-    assert(s);
-    assert(s->ref >= 1);
+    pa_sink_assert_ref(s);
 
     ret = pa_idxset_size(s->inputs);
 
@@ -575,3 +647,41 @@ unsigned pa_sink_used_by(pa_sink *s) {
 
     return ret;
 }
+
+int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, pa_memchunk *chunk) {
+    pa_sink *s = PA_SINK(o);
+    pa_sink_assert_ref(s);
+
+    switch (code) {
+        case PA_SINK_MESSAGE_ADD_INPUT: {
+            pa_sink_input *i = userdata;
+            pa_hashmap_put(s->thread_info.inputs, PA_UINT32_TO_PTR(i->index), pa_sink_input_ref(i));
+            return 0;
+        }
+            
+        case PA_SINK_MESSAGE_REMOVE_INPUT: {
+            pa_sink_input *i = userdata;
+            pa_hashmap_remove(s->thread_info.inputs, PA_UINT32_TO_PTR(i->index));
+            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:
+            *((int*) userdata) = s->thread_info.soft_muted;
+            return 0;
+            
+        default:
+            return -1;
+    }
+}
diff --git a/src/pulsecore/sink.h b/src/pulsecore/sink.h
index ef73f67..2939cc4 100644
--- a/src/pulsecore/sink.h
+++ b/src/pulsecore/sink.h
@@ -1,5 +1,5 @@
-#ifndef foosinkhfoo
-#define foosinkhfoo
+#ifndef foopulsesinkhfoo
+#define foopulsesinkhfoo
 
 /* $Id$ */
 
@@ -25,37 +25,43 @@
   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>
 
 #define PA_MAX_INPUTS_PER_SINK 32
 
 typedef enum pa_sink_state {
     PA_SINK_RUNNING,
+    PA_SINK_SUSPENDED,
+    PA_SINK_IDLE,
     PA_SINK_DISCONNECTED
 } pa_sink_state_t;
 
 struct pa_sink {
-    int ref;
+    pa_msgobject parent;
+
     uint32_t index;
     pa_core *core;
-    pa_sink_state_t state;
+    pa_atomic_t state;
 
     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;
@@ -63,49 +69,85 @@ struct pa_sink {
     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 */
+    pa_cvolume volume;
+    int muted;
+    int refresh_volume;
+    int refresh_mute;
+
+    int (*start)(pa_sink *s);
+    int (*stop)(pa_sink *s);
+    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;
+
+    /* Contains copies of the above data so that the real-time worker
+     * thread can work without access locking */
+    struct {
+        pa_hashmap *inputs;
+        pa_cvolume soft_volume;
+        int soft_muted;
+    } thread_info;
 
     void *userdata;
 };
 
+PA_DECLARE_CLASS(pa_sink);
+#define PA_SINK(s) ((pa_sink*) (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_START,
+    PA_SINK_MESSAGE_STOP,
+    PA_SINK_MESSAGE_MAX
+} pa_sink_message_t;
+
+/* To be used exclusively by the sink driver */
+
 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);
+        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);
+void pa_sink_set_module(pa_sink *sink, pa_module *m);
+void pa_sink_set_description(pa_sink *s, const char *description);
+
+/* Usable by everyone */
 
 pa_usec_t pa_sink_get_latency(pa_sink *s);
 
-void pa_sink_notify(pa_sink*s);
+void pa_sink_update_status(pa_sink*s);
+void pa_sink_suspend(pa_sink *s, int suspend);
 
-void pa_sink_set_owner(pa_sink *sink, pa_module *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, int mute);
+int pa_sink_get_mute(pa_sink *sink);
 
-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);
+unsigned pa_sink_used_by(pa_sink *s);
+#define pa_sink_get_state(s) ((pa_sink_state_t) pa_atomic_load(&(s)->state))
 
-void pa_sink_set_description(pa_sink *s, const char *description);
+/* To be used exclusively by the sink driver thread */
 
-unsigned pa_sink_used_by(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);
+
+int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, pa_memchunk *chunk);
 
 #endif
diff --git a/src/pulsecore/sound-file-stream.c b/src/pulsecore/sound-file-stream.c
index 7a43c74..a682ee6 100644
--- a/src/pulsecore/sound-file-stream.c
+++ b/src/pulsecore/sound-file-stream.c
@@ -76,21 +76,25 @@ static int sink_input_peek(pa_sink_input *i, pa_memchunk *chunk) {
     if (!u->memchunk.memblock) {
         uint32_t fs = pa_frame_size(&i->sample_spec);
         sf_count_t n;
+        void *p;
 
         u->memchunk.memblock = pa_memblock_new(i->sink->core->mempool, BUF_SIZE);
         u->memchunk.index = 0;
 
+        p = pa_memblock_acquire(u->memchunk.memblock);
+
         if (u->readf_function) {
-            if ((n = u->readf_function(u->sndfile, u->memchunk.memblock->data, BUF_SIZE/fs)) <= 0)
+            if ((n = u->readf_function(u->sndfile, p, BUF_SIZE/fs)) <= 0)
                 n = 0;
 
             u->memchunk.length = n * fs;
         } else {
-            if ((n = sf_read_raw(u->sndfile, u->memchunk.memblock->data, BUF_SIZE)) <= 0)
+            if ((n = sf_read_raw(u->sndfile, p, BUF_SIZE)) <= 0)
                 n = 0;
 
             u->memchunk.length = n;
         }
+        pa_memblock_release(u->memchunk.memblock);
 
         if (!u->memchunk.length) {
             free_userdata(u);
diff --git a/src/pulsecore/sound-file.c b/src/pulsecore/sound-file.c
index 69b543a..6e93f8a 100644
--- a/src/pulsecore/sound-file.c
+++ b/src/pulsecore/sound-file.c
@@ -42,7 +42,11 @@ int pa_sound_file_load(pa_mempool *pool, const char *fname, pa_sample_spec *ss,
     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;
+
+    assert(fname);
+    assert(ss);
+    assert(chunk);
 
     chunk->memblock = NULL;
     chunk->index = chunk->length = 0;
@@ -99,8 +103,10 @@ int pa_sound_file_load(pa_mempool *pool, const char *fname, pa_sample_spec *ss,
     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) != l)) {
         pa_log("Premature file end");
         goto finish;
     }
@@ -112,6 +118,9 @@ finish:
     if (sf)
         sf_close(sf);
 
+    if (ptr)
+        pa_memblock_release(chunk->memblock);
+
     if (ret != 0 && chunk->memblock)
         pa_memblock_unref(chunk->memblock);
 
diff --git a/src/pulsecore/source-output.c b/src/pulsecore/source-output.c
index c7a9858..c1aa339 100644
--- a/src/pulsecore/source-output.c
+++ b/src/pulsecore/source-output.c
@@ -26,7 +26,6 @@
 #endif
 
 #include <stdio.h>
-#include <assert.h>
 #include <stdlib.h>
 #include <string.h>
 
@@ -39,14 +38,8 @@
 
 #include "source-output.h"
 
-#define CHECK_VALIDITY_RETURN_NULL(condition) \
-do {\
-if (!(condition)) \
-    return NULL; \
-} while (0)
-
 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 +47,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,48 +67,53 @@ 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;
 
-    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_DISCONNECTED);
 
     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,
@@ -125,115 +123,133 @@ pa_source_output* pa_source_output_new(
             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_source_output_new(pa_source_output);
+    
+    o->parent.parent.free = source_output_free;
+    o->parent.process_msg = pa_source_output_process_msg;
+    
+    o->core = core;
+    pa_atomic_load(&o->state, PA_SOURCE_OUTPUT_RUNNING);
+    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->process_msg = NULL;
     o->push = NULL;
     o->kill = NULL;
     o->get_latency = NULL;
     o->userdata = NULL;
 
-    o->resampler = resampler;
-    o->resample_method = data->resample_method;
+    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, 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);
+    pa_assert(o);
+    pa_return_if_fail(pa_source_output_get_state(i) != PA_SOURCE_OUTPUT_DISCONNECTED);
+    pa_assert(o->source);
+    pa_assert(o->source->core);
 
+    pa_asyncmsgq_send(i->sink->asyncmsgq, i->sink, PA_SOURCE_MESSAGE_REMOVE_OUTPUT, o, NULL);
+    
     pa_idxset_remove_by_data(o->source->core->source_outputs, o, NULL);
     pa_idxset_remove_by_data(o->source->outputs, o, NULL);
 
     pa_subscription_post(o->source->core, PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_REMOVE, o->index);
     o->source = NULL;
 
+    o->process_msg = NULL;
     o->push = NULL;
     o->kill = NULL;
     o->get_latency = NULL;
 
-    o->state = PA_SOURCE_OUTPUT_DISCONNECTED;
+    pa_atomic_load(&i->state, PA_SOURCE_OUTPUT_DISCONNECTED);
 }
 
-static void source_output_free(pa_source_output* o) {
-    assert(o);
+static void source_output_free(pa_msgobject* mo) {
+    pa_source_output *o = PA_SOURCE_OUTPUT(mo);
+    
+    pa_assert(pa_source_output_refcnt(o) == 0);
 
-    if (o->state != PA_SOURCE_OUTPUT_DISCONNECTED)
-        pa_source_output_disconnect(o);
+    pa_source_output_disconnect(o);
 
-    pa_log_info("freed %u \"%s\"", o->index, o->name);
+    pa_log_info("Freeing output %u \"%s\"", o->index, o->name);
 
-    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);
+    
+    pa_asyncmsgq_post(o->source->asyncmsgq, o->source, PA_SOURCE_MESSAGE_ADD_OUTPUT, o, NULL, pa_source_unref, pa_source_output_unref);
+    pa_source_update_status(o->source);
 
-    if (!(--o->ref))
-        source_output_free(o);
-}
-
-pa_source_output* pa_source_output_ref(pa_source_output *o) {
-    assert(o);
-    assert(o->ref >= 1);
-
-    o->ref++;
-    return o;
+    pa_subscription_post(core, PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_NEW, o->index);
 }
 
 void pa_source_output_kill(pa_source_output*o) {
-    assert(o);
-    assert(o->ref >= 1);
+    pa_source_output_assert_ref(o);
 
     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);
+
+    if (pa_asyncmsgq_send(o->source->asyncmsgq, i->source, PA_SOURCE_OUTPUT_MESSAGE_GET_LATENCY, &r, NULL) < 0)
+        r = 0;
+    
+    if (o->get_latency)
+        r += o->get_latency(o);
+
+    return r;
+}
+
 void pa_source_output_push(pa_source_output *o, const pa_memchunk *chunk) {
     pa_memchunk rchunk;
+    pa_source_output_state_t state;
 
-    assert(o);
-    assert(chunk);
-    assert(chunk->length);
-    assert(o->push);
+    pa_source_output_assert_ref(o);
+    pa_assert(chunk);
+    pa_assert(chunk->length);
 
-    if (o->state == PA_SOURCE_OUTPUT_CORKED)
+    state = pa_source_output_get_state(o);
+    
+    if (!o->push || state == PA_SOURCE_OUTPUT_DISCONNECTED || state == PA_SOURCE_OUTPUT_CORKED)
         return;
 
+    pa_assert(state = PA_SOURCE_OUTPUT_RUNNING);
+    
     if (!o->resampler) {
         o->push(o, chunk);
         return;
@@ -243,119 +259,137 @@ void pa_source_output_push(pa_source_output *o, const pa_memchunk *chunk) {
     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, int b) {
+    int n;
+    pa_source_output_state_t state;
 
-    if (o->name && name && !strcmp(o->name, name))
-        return;
+    pa_source_output_assert_ref(o);
 
-    pa_xfree(o->name);
-    o->name = pa_xstrdup(name);
+    state = pa_source_output_get_state(o);
+    pa_assert(state != PA_SOURCE_OUTPUT_DISCONNECTED);
 
-    pa_subscription_post(o->source->core, PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_CHANGE, o->index);
+    if (b && state != PA_SOURCE_OUTPUT_CORKED)
+        pa_atomic_store(o->state, PA_SOURCE_OUTPUT_CORKED);
+    else if (!b && state == PA_SOURCE_OUTPUT_CORKED)
+        pa_atomic_cmpxchg(o->state, state, PA_SOURCE_OUTPUT_RUNNING);
 }
 
-pa_usec_t pa_source_output_get_latency(pa_source_output *o) {
-    assert(o);
-    assert(o->ref >= 1);
+int pa_source_output_set_rate(pa_source_output *o, uint32_t rate) {
+    pa_source_output_assert_ref(o);
+    pa_return_val_if_fail(o->thread_info.resampler, -1);
 
-    if (o->get_latency)
-        return o->get_latency(o);
+    if (i->sample_spec.rate == rate)
+        return 0;
+
+    i->sample_spec.rate = rate;
 
+    pa_asyncmsgq_post(s->asyncmsgq, pa_source_output_ref(i), PA_SOURCE_OUTPUT_MESSAGE_SET_RATE, PA_UINT_TO_PTR(rate), NULL, pa_source_output_unref, NULL);
+    
+    pa_subscription_post(o->source->core, PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT!|PA_SUBSCRIPTION_EVENT_CHANGE, i->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);
+    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_source_assert_ref(dest);
 
-    origin = o->source;
+    return -1;
+    
+/*     origin = o->source; */
 
-    if (dest == origin)
-        return 0;
+/*     if (dest == origin) */
+/*         return 0; */
 
-    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 (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 &&
-        pa_sample_spec_equal(&origin->sample_spec, &dest->sample_spec) &&
-        pa_channel_map_equal(&origin->channel_map, &dest->channel_map))
+/*     if (o->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;
+/*         /\* Try to reuse the old resampler if possible *\/ */
+/*         new_resampler = o->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 (!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 sink *\/ */
 
-        if (!(new_resampler = pa_resampler_new(
-                      dest->core->mempool,
-                      &dest->sample_spec, &dest->channel_map,
-                      &o->sample_spec, &o->channel_map,
-                      o->resample_method))) {
-            pa_log_warn("Unsupported resampling operation.");
-            return -1;
-        }
-    }
+/*         if (!(new_resampler = pa_resampler_new( */
+/*                       dest->core->mempool, */
+/*                       &dest->sample_spec, &dest->channel_map, */
+/*                       &o->sample_spec, &o->channel_map, */
+/*                       o->resample_method))) { */
+/*             pa_log_warn("Unsupported resampling operation."); */
+/*             return -1; */
+/*         } */
+/*     } */
 
-    /* Okey, let's move it */
-    pa_idxset_remove_by_data(origin->outputs, o, NULL);
-    pa_idxset_put(dest->outputs, o, NULL);
-    o->source = dest;
+/*     /\* Okey, let's move it *\/ */
+/*     pa_idxset_remove_by_data(origin->outputs, o, NULL); */
+/*     pa_idxset_put(dest->outputs, o, NULL); */
+/*     o->source = dest; */
 
-    /* Replace resampler */
-    if (new_resampler != o->resampler) {
-        if (o->resampler)
-            pa_resampler_free(o->resampler);
-        o->resampler = new_resampler;
-    }
+/*     /\* Replace resampler *\/ */
+/*     if (new_resampler != o->resampler) { */
+/*         if (o->resampler) */
+/*             pa_resampler_free(o->resampler); */
+/*         o->resampler = new_resampler; */
+/*     } */
 
-    /* Notify everyone */
-    pa_subscription_post(o->source->core, PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_CHANGE, o->index);
-    pa_source_notify(o->source);
+/*     /\* 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;
+/*     return 0; */
+}
+
+int pa_source_output_process_msg(pa_msgobject *mo, int code, void *userdata, pa_memchunk* chunk) {
+    pa_source_output *o = PA_SOURCE_OUTPUT(o);
+    
+    pa_source_output_assert_ref(i);
+
+    switch (code) {
+
+        case PA_SOURCE_OUTPUT_MESSAGE_SET_RATE: {
+            
+            i->thread_info.sample_spec.rate = PA_PTR_TO_UINT(userdata);
+            pa_resampler_set_output_rate(i->resampler, PA_PTR_TO_UINT(userdata));
+
+            return 0;
+        }
+    }
+
+    return -1;
 }
diff --git a/src/pulsecore/source-output.h b/src/pulsecore/source-output.h
index 3da6caa..0f9c3ba 100644
--- a/src/pulsecore/source-output.h
+++ b/src/pulsecore/source-output.h
@@ -1,5 +1,5 @@
-#ifndef foosourceoutputhfoo
-#define foosourceoutputhfoo
+#ifndef foopulsesourceoutputhfoo
+#define foopulsesourceoutputhfoo
 
 /* $Id$ */
 
@@ -35,40 +35,59 @@ 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_RUNNING,
     PA_SOURCE_OUTPUT_CORKED,
     PA_SOURCE_OUTPUT_DISCONNECTED
 } pa_source_output_state_t;
 
 typedef enum pa_source_output_flags {
-    PA_SOURCE_OUTPUT_NO_HOOKS = 1
+    PA_SOURCE_OUTPUT_NO_HOOKS = 1,
+    PA_SOURCE_OUTPUT_VARIABLE_RATE = 2
 } pa_source_output_flags_t;
 
 struct pa_source_output {
-    int ref;
+    pa_msgobject parent;
+    
     uint32_t index;
-    pa_source_output_state_t state;
+    pa_core *core;
+    pa_atomic_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;
 
+    int (*process_msg)(pa_sink_input *i, int code, void *userdata);
     void (*push)(pa_source_output *o, const pa_memchunk *chunk);
     void (*kill)(pa_source_output* o);              /* may be NULL */
     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_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*) (o))
+
+enum {
+    PA_SOURCE_OUTPUT_MESSAGE_GET_LATENCY,
+    PA_SOURCE_OUTPUT_MESSAGE_SET_RATE,
+    PA_SOURCE_OUTPUT_MESSAGE_MAX
+};
+
 typedef struct pa_source_output_new_data {
     const char *name, *driver;
     pa_module *module;
@@ -89,30 +108,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);
-
-/* To be called by the implementing module only */
+void pa_source_output_put(pa_source_output *o);
 void pa_source_output_disconnect(pa_source_output*o);
 
-/* External code may request disconnection with this funcion */
-void pa_source_output_kill(pa_source_output*o);
+void pa_source_output_set_name(pa_source_output *i, const char *name);
 
-void pa_source_output_push(pa_source_output *o, const pa_memchunk *chunk);
+/* Callable by everyone */
 
-void pa_source_output_set_name(pa_source_output *i, const char *name);
+/* External code may request disconnection with this funcion */
+void pa_source_output_kill(pa_source_output*o);
 
 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_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) ((pa_source_output_state_t) pa_atomic_load(&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, pa_memchunk *chunk);
+
 #endif
diff --git a/src/pulsecore/source.c b/src/pulsecore/source.c
index 9bb2d34..fd3c85d 100644
--- a/src/pulsecore/source.c
+++ b/src/pulsecore/source.c
@@ -42,12 +42,6 @@
 
 #include "source.h"
 
-#define CHECK_VALIDITY_RETURN_NULL(condition) \
-do {\
-if (!(condition)) \
-    return NULL; \
-} while (0)
-
 pa_source* pa_source_new(
         pa_core *core,
         const char *driver,
@@ -65,30 +59,32 @@ pa_source* pa_source_new(
     assert(name);
     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;
+    pa_atomic_store(&s->state, PA_SOURCE_IDLE);
     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;
@@ -96,45 +92,87 @@ pa_source* pa_source_new(
     s->outputs = pa_idxset_new(NULL, NULL);
     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;
+    pa_cvolume_reset(&s->volume, spec->channels);
+    s->muted = 0;
+    s->refresh_volume = s->refresh_mute = 0;
 
     s->is_hardware = 0;
 
     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->start = NULL;
+    s->stop = NULL;
     s->userdata = NULL;
 
+    pa_assert_se(s->asyncmsgq = pa_asyncmsgq_new(0));
+    
     r = pa_idxset_put(core->sources, s, &s->index);
     assert(s->index != PA_IDXSET_INVALID && r >= 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);
 
+    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;
+    
     pa_subscription_post(core, PA_SUBSCRIPTION_EVENT_SOURCE | PA_SUBSCRIPTION_EVENT_NEW, s->index);
 
     return s;
 }
 
+static void source_start(pa_source *s) {
+    pa_source_state_t state;
+    pa_assert(s);
+
+    state = pa_source_get_state(s);
+    pa_return_if_fail(state == PA_SOURCE_IDLE || state == PA_SOURCE_SUSPENDED);
+
+    pa_atomic_store(&s->state, PA_SOURCE_RUNNING);
+
+    if (s->start)
+        s->start(s);
+    else
+        pa_asyncmsgq_post(s->asyncmsgq, s, PA_SOURCE_MESSAGE_START, NULL, NULL, pa_source_unref, NULL);
+}
+
+static void source_stop(pa_source *s) {
+    pa_source_state_t state;
+    int stop;
+    
+    pa_assert(s);
+    state = pa_source_get_state(s);
+    pa_return_if_fail(state == PA_SOURCE_RUNNING || state == PA_SOURCE_SUSPENDED);
+
+    stop = state == PA_SOURCE_RUNNING;
+    pa_atomic_store(&s->state, PA_SOURCE_IDLE);
+
+    if (stop) {
+        if (s->stop)
+            s->stop(s);
+        else
+            pa_asyncmsgq_post(s->asyncmsgq, s, PA_SOURCE_MESSAGE_STOP, NULL, NULL, pa_source_unref, NULL);
+    }
+}
+
 void pa_source_disconnect(pa_source *s) {
     pa_source_output *o, *j = NULL;
 
-    assert(s);
-    assert(s->state == PA_SOURCE_RUNNING);
+    pa_assert(s);
+    pa_return_if_fail(pa_sink_get_state(s) != PA_SINK_DISCONNECT);
 
-    s->state = PA_SOURCE_DISCONNECTED;
+    source_stop(s);
+    
+    pa_atomic_store(&s->state, PA_SOURCE_DISCONNECTED);
     pa_namereg_unregister(s->core, s->name);
 
     pa_hook_fire(&s->core->hook_source_disconnect, s);
 
     while ((o = pa_idxset_first(s->outputs, NULL))) {
-        assert(o != j);
+        pa_assert(o != j);
         pa_source_output_kill(o);
         j = o;
     }
@@ -142,190 +180,206 @@ void pa_source_disconnect(pa_source *s) {
     pa_idxset_remove_by_data(s->core->sources, s, NULL);
 
     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->start = NULL;
+    s->stop = NULL;
 
     pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE | PA_SUBSCRIPTION_EVENT_REMOVE, s->index);
 }
 
-static void source_free(pa_source *s) {
-    assert(s);
-    assert(!s->ref);
+static void source_free(pa_msgobject *o) {
+    pa_source *s = PA_SOURCE(o);
+    
+    pa_assert(s);
+    pa_assert(pa_source_refcnt(s) == 0);
 
-    if (s->state != PA_SOURCE_DISCONNECTED)
-        pa_source_disconnect(s);
+    pa_source_disconnect(s);
 
-    pa_log_info("freed %u \"%s\"", s->index, s->name);
+    pa_log_info("Freeing source %u \"%s\"", s->index, s->name);
 
     pa_idxset_free(s->outputs, NULL, NULL);
+    pa_hashmap_free(s->thread_info.outputs, pa_sink_output_unref, NULL);
 
+    pa_asyncmsgq_free(s->asyncmsgq);
+    
     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);
+void pa_source_update_status(pa_source*s) {
+    pa_source_assert_ref(s);
 
-    if (!(--s->ref))
-        source_free(s);
+    if (pa_source_get_state(s) == PA_SOURCE_STATE_SUSPENDED)
+        return;
+    
+    if (pa_source_used_by(s) > 0)
+        source_start(s);
+    else
+        source_stop(s);
 }
 
-pa_source* pa_source_ref(pa_source *s) {
-    assert(s);
-    assert(s->ref >= 1);
+void pa_source_suspend(pa_source *s, int suspend) {
+    pa_source_state_t state;
 
-    s->ref++;
-    return s;
-}
+    pa_source_assert_ref(s);
 
-void pa_source_notify(pa_source*s) {
-    assert(s);
-    assert(s->ref >= 1);
+    state = pa_source_get_state(s);
+    pa_return_if_fail(suspend && (s->state == PA_SOURCE_RUNNING || s->state == PA_SOURCE_IDLE));
+    pa_return_if_fail(!suspend && (s->state == PA_SOURCE_SUSPENDED));
 
-    if (s->notify)
-        s->notify(s);
-}
 
-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;
+    if (suspend) {
+        pa_atomic_store(&s->state, PA_SOURCE_SUSPENDED);
 
-    assert(o);
-    assert(chunk);
+        if (s->stop)
+            s->stop(s);
+        else
+            pa_asyncmsgq_post(s->asyncmsgq, s, PA_SOURCE_MESSAGE_STOP, NULL, NULL, pa_source_unref, NULL);
+        
+    } else {
+        pa_atomic_store(&s->state, PA_SOURCE_RUNNING);
 
-    pa_source_output_push(o, chunk);
-    return 0;
+        if (s->start)
+            s->start(s);
+        else
+            pa_asyncmsgq_post(s->asyncmsgq, s, PA_SOURCE_MESSAGE_START, NULL, NULL, pa_source_unref, NULL);
+    }
 }
 
 void pa_source_post(pa_source*s, const pa_memchunk *chunk) {
-    assert(s);
-    assert(s->ref >= 1);
-    assert(chunk);
-
-    pa_source_ref(s);
+    pa_source_output *o;
+    void *state = NULL;
+    
+    pa_source_assert_ref(s);
+    pa_assert(chunk);
 
     if (s->sw_muted || !pa_cvolume_is_norm(&s->sw_volume)) {
         pa_memchunk vchunk = *chunk;
 
         pa_memblock_ref(vchunk.memblock);
         pa_memchunk_make_writable(&vchunk, 0);
-        if (s->sw_muted)
+        
+        if (s->thread_info.muted || pa_cvolume_is_muted(s->thread_info.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.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 {
+        
+        while ((o = pa_hashmap_iterate(s->thread_info.outputs, &state, NULL)))
+            pa_source_output_push(o, chunk);
 
-    pa_source_unref(s);
+    }
 }
 
-void pa_source_set_owner(pa_source *s, pa_module *m) {
-    assert(s);
-    assert(s->ref >= 1);
-
-    if (m == s->owner)
-        return;
+pa_usec_t pa_source_get_latency(pa_source *s) {
+    pa_usec_t usec;
 
-    s->owner = m;
-    pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
-}
+    pa_source_assert_ref(s);
 
-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, s, PA_SOURCE_MESSAGE_GET_LATENCY, &usec, 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) {
+void pa_source_set_volume(pa_source *s, const pa_cvolume *volume) {
     pa_cvolume *v;
 
-    assert(s);
-    assert(s->ref >= 1);
-    assert(volume);
-
-    if (m == PA_MIXER_HARDWARE && s->set_hw_volume)
-        v = &s->hw_volume;
-    else
-        v = &s->sw_volume;
-
-    if (pa_cvolume_equal(v, volume))
-        return;
+    pa_source_assert_ref(s);
+    pa_assert(volume);
 
-    *v = *volume;
+    changed = !pa_cvolume_equal(volume, s->volume);
+    s->volume = *volume;
+    
+    if (s->set_volume && s->set_volume(s) < 0)
+        s->set_volume = NULL;
 
-    if (v == &s->hw_volume)
-        if (s->set_hw_volume(s) < 0)
-            s->sw_volume =  *volume;
+    if (!s->set_volume)
+        pa_asyncmsgq_post(s->asyncmsgq, pa_source_ref(s), PA_SOURCE_MESSAGE_SET_VOLUME, pa_xnewdup(struct pa_cvolume, volume, 1), pa_source_unref, pa_xfree);
 
-    pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
+    if (changed)
+        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_mixer_t m) {
-    assert(s);
-    assert(s->ref >= 1);
+const pa_cvolume *pa_source_get_volume(pa_source *s) {
+    pa_source_assert_ref(s);
 
-    if (m == PA_MIXER_HARDWARE && s->set_hw_volume) {
+    old_volume = s->volume;
+    
+    if (s->get_volume && s->get_volume(s) < 0)
+        s->get_volume = NULL;
 
-        if (s->get_hw_volume)
-            s->get_hw_volume(s);
+    if (!s->get_volume && s->refresh_volume)
+        pa_asyncmsgq_send(s->asyncmsgq, s, PA_SOURCE_MESSAGE_GET_VOLUME, &s->volume);
 
-        return &s->hw_volume;
-    } else
-        return &s->sw_volume;
+    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;
 }
 
 void pa_source_set_mute(pa_source *s, pa_mixer_t m, int mute) {
-    int *t;
+    int changed;
+    
+    pa_source_assert_ref(s);
 
-    assert(s);
-    assert(s->ref >= 1);
+    changed = s->muted != mute;
 
-    if (m == PA_MIXER_HARDWARE && s->set_hw_mute)
-        t = &s->hw_muted;
-    else
-        t = &s->sw_muted;
-
-    if (!!*t == !!mute)
-        return;
+    if (s->set_mute && s->set_mute(s) < 0)
+        s->set_mute = NULL;
 
-    *t = !!mute;
+    if (!s->set_mute)
+        pa_asyncmsgq_post(s->asyncmsgq, pa_source_ref(s), PA_SOURCE_MESSAGE_SET_MUTE, PA_UINT_TO_PTR(mute), pa_source_unref, NULL);
 
-    if (t == &s->hw_muted)
-        if (s->set_hw_mute(s) < 0)
-            s->sw_muted = !!mute;
-
-    pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
+    if (changed)
+        pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
 }
 
 int pa_source_get_mute(pa_source *s, pa_mixer_t m) {
-    assert(s);
-    assert(s->ref >= 1);
+    int old_muted;
+    
+    pa_source_assert_ref(s);
+
+    old_muted = s->muted;
+    
+    if (s->get_mute && s->get_mute(s) < 0)
+        s->get_mute = NULL;
+
+    if (!s->get_mute && s->refresh_mute)
+        pa_asyncmsgq_send(s->asyncmsgq, s, PA_SOURCE_MESSAGE_GET_MUTE, &s->muted);
+
+    if (old_muted != s->muted)
+        pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
+    
+    return s->muted;
+}
 
-    if (m == PA_MIXER_HARDWARE && s->set_hw_mute) {
+void pa_source_set_module(pa_source *s, pa_module *m) {
+    pa_source_assert_ref(s);
 
-        if (s->get_hw_mute)
-            s->get_hw_mute(s);
+    if (m == s->module)
+        return;
 
-        return s->hw_muted;
-    } else
-        return s->sw_muted;
+    s->module = m;
+    
+    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;
@@ -340,8 +394,45 @@ void pa_source_set_description(pa_source *s, const char *description) {
 }
 
 unsigned pa_source_used_by(pa_source *s) {
-    assert(s);
-    assert(s->ref >= 1);
+    pa_source_assert_ref(s);
 
     return pa_idxset_size(s->outputs);
 }
+
+int pa_source_process_msg(pa_msgobject *o, void *object, int code, pa_memchunk *chunk, void *userdata) {
+    pa_source *s = PA_SOURCE(o);
+    pa_source_assert_ref(s);
+
+    switch (code) {
+        case PA_SOURCE_MESSAGE_ADD_OUTPUT: {
+            pa_source_output *i = userdata;
+            pa_hashmap_put(s->thread_info.outputs, PA_UINT32_TO_PTR(i->index), pa_source_output_ref(i));
+            return 0;
+        }
+            
+        case PA_SOURCE_MESSAGE_REMOVE_INPUT: {
+            pa_source_input *i = userdata;
+            pa_hashmap_remove(s->thread_info.outputs, PA_UINT32_TO_PTR(i->index), pa_source_output_ref(i));
+            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:
+            *((int*) userdata) = s->thread_info.soft_muted;
+            return 0;
+            
+        default:
+            return -1;
+    }
+}
diff --git a/src/pulsecore/source.h b/src/pulsecore/source.h
index 5a28cf4..1e20c6e 100644
--- a/src/pulsecore/source.h
+++ b/src/pulsecore/source.h
@@ -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,24 +40,30 @@ 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>
 
-#define PA_MAX_OUTPUTS_PER_SOURCE 16
+#define PA_MAX_OUTPUTS_PER_SOURCE 32
 
 typedef enum pa_source_state {
     PA_SOURCE_RUNNING,
+    PA_SOURCE_SUSPENDED,
+    PA_SOURCE_IDLE,
     PA_SOURCE_DISCONNECTED
 } pa_source_state_t;
 
 struct pa_source {
-    int ref;
+    pa_msgobject parent;
+    
     uint32_t index;
     pa_core *core;
-    pa_source_state_t state;
+    pa_atomic_t state;
 
     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;
@@ -64,48 +71,79 @@ struct pa_source {
     pa_idxset *outputs;
     pa_sink *monitor_of;                     /* may be NULL */
 
-    pa_cvolume hw_volume, sw_volume;
-    int hw_muted, sw_muted;
-
-    int is_hardware;
-
-    void (*notify)(pa_source*source);        /* may be NULL */
+    pa_cvolume volume;
+    int muted;
+    int refresh_volume;
+    int referesh_mute;
+
+    void (*start)(pa_source*source);         /* may be NULL */
+    void (*stop)(pa_source*source);          /* 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;
+
+    struct {
+        pa_hashmap *outputs;
+        pa_cvolume soft_volume;
+        int soft_muted;
+    } thread_info;
+    
     void *userdata;
 };
 
+PA_DECLARE_CLASS(pa_source);
+#define PA_SOURCE(s) ((pa_source*) (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_START,
+    PA_SOURCE_MESSAGE_STOP,
+    PA_SOURCE_MESSAGE_MAX
+} pa_source_message_t;
+
+/* To be used exclusively by the source driver */
+
 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);
+        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);
-
-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_owner(pa_source *s, pa_module *m);
+/* Callable by everyone */
 
 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);
+void pa_source_update_status(pa_source*s);
+void pa_source_suspend(pa_source *s);
 
-void pa_source_set_description(pa_source *s, const char *description);
+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, int mute);
+int pa_source_get_mute(pa_source *source);
 
 unsigned pa_source_used_by(pa_source *s);
+#define pa_source_get_state(s) ((pa_source_state_t) pa_atomic_load(&(s)->state))
+
+/* To be used exclusively by the source driver thread */
+
+void pa_source_post(pa_source*s, const pa_memchunk *b);
+void pa_source_process_msg(pa_msgobject *o, int code, void *userdata, pa_memchunk *chunk);
+
 #endif
diff --git a/src/pulsecore/thread-posix.c b/src/pulsecore/thread-posix.c
index 4271fa4..6ad5ac4 100644
--- a/src/pulsecore/thread-posix.c
+++ b/src/pulsecore/thread-posix.c
@@ -26,7 +26,6 @@
 #include <config.h>
 #endif
 
-#include <assert.h>
 #include <pthread.h>
 #include <sched.h>
 #include <errno.h>
@@ -35,56 +34,50 @@
 #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 pthread_key_t thread_key;
+static pthread_once_t thread_once = PTHREAD_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);
+static void thread_once_func(void) {
+    pa_assert_se(pthread_key_create(&thread_key, thread_free_cb) == 0);
 }
 
 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);
+    pthread_once(&thread_once, thread_once_func);
+    pthread_setspecific(thread_key, 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 +85,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 +103,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 +130,9 @@ 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);
+    pthread_once(&thread_once, thread_once_func);
 
-    if ((t = pa_tls_get(thread_tls)))
+    if ((t = pthread_getspecific(thread_key)))
         return t;
 
     /* This is a foreign thread, let's create a pthread structure to
@@ -151,19 +144,19 @@ pa_thread* pa_thread_self(void) {
     t->userdata = NULL;
     pa_atomic_store(&t->running, 2);
 
-    pa_tls_set(thread_tls, t);
+    pthread_setspecific(thread_key, 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 +165,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 +183,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 +199,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;
 }
 
diff --git a/src/tests/asyncmsgq-test.c b/src/tests/asyncmsgq-test.c
new file mode 100644
index 0000000..8a0f5a3
--- /dev/null
+++ b/src/tests/asyncmsgq-test.c
@@ -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, 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);
+
+    } 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, NULL, NULL);
+
+    pa_thread_yield();
+
+    printf("Operation B post\n");
+    pa_asyncmsgq_post(q, NULL, OPERATION_B, NULL, NULL, NULL);
+
+    pa_thread_yield();
+
+    printf("Operation C send\n");
+    pa_asyncmsgq_send(q, NULL, OPERATION_C, NULL);
+
+    pa_thread_yield();
+
+    printf("Quit post\n");
+    pa_asyncmsgq_post(q, NULL, QUIT, NULL, NULL, NULL);
+
+    pa_thread_free(t);
+
+    pa_asyncmsgq_free(q);
+
+    return 0;
+}
diff --git a/src/tests/asyncq-test.c b/src/tests/asyncq-test.c
new file mode 100644
index 0000000..10566db
--- /dev/null
+++ b/src/tests/asyncq-test.c
@@ -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++) {
+        pa_asyncq_push(q, (void*) (i+1), 1);
+        printf("pushed %i\n", i);
+    }
+
+    pa_asyncq_push(q, (void*) -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 == (void*) -1)
+            break;
+
+        pa_assert(p == (void *) (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;
+}
diff --git a/src/tests/mcalign-test.c b/src/tests/mcalign-test.c
index db76712..d101311 100644
--- a/src/tests/mcalign-test.c
+++ b/src/tests/mcalign-test.c
@@ -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);
diff --git a/src/tests/memblock-test.c b/src/tests/memblock-test.c
index 8d25ba3..1f63499 100644
--- a/src/tests/memblock-test.c
+++ b/src/tests/memblock-test.c
@@ -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!";
 
@@ -90,10 +91,17 @@ int main(int argc, char *argv[]) {
     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[1]);
+
     blocks[3] = pa_memblock_new_malloced(pool_a, pa_xstrdup(txt), sizeof(txt));
     blocks[4] = NULL;
 
@@ -130,14 +138,18 @@ int main(int argc, char *argv[]) {
 
         mb_c = pa_memimport_get(import_c, id, shm_id, offset, size);
         assert(mb_c);
-        printf("1 data=%s\n", (char*) mb_c->data);
+        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);
diff --git a/src/tests/memblockq-test.c b/src/tests/memblockq-test.c
index 1c0b7fe..7ad3b2f 100644
--- a/src/tests/memblockq-test.c
+++ b/src/tests/memblockq-test.c
@@ -131,8 +131,10 @@ 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);

commit a4fed0fbb568dc57762906fb7e48fc945925d2ca
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Jun 11 12:17:40 2007 +0000

    make eolspace
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1470 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-null-sink.c b/src/modules/module-null-sink.c
index 8cf961b..ce3b29b 100644
--- a/src/modules/module-null-sink.c
+++ b/src/modules/module-null-sink.c
@@ -94,7 +94,7 @@ static void thread_func(void *userdata) {
     pollfd.events = POLLIN;
 
     pa_gettimeofday(u->timestamp);
-    
+
     for (;;) {
         int code;
         void *data, *object;
@@ -116,7 +116,7 @@ static void thread_func(void *userdata) {
                         pa_sink_process_msg(u->sink->asyncmsgq, object, code, data);
 
                 }
-                
+
             } else if (object == u->sink) {
 
                 switch (code) {
@@ -124,29 +124,29 @@ static void thread_func(void *userdata) {
                         pa_assert(running);
                         running = 0;
                         break;
-                        
+
                     case PA_SINK_MESSAGE_START:
                         pa_assert(!running);
                         running = 1;
-                        
+
                         pa_gettimeofday(u->timestamp);
                         break;
-                        
+
                     case PA_SINK_MESSAGE_GET_LATENCY:
-                        
+
                         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;
-                        
+
                         /* ... */
 
                     default:
                         pa_sink_process_msg(u->sink->asyncmsgq, object, code, data);
                 }
             }
-            
+
             pa_asyncmsgq_done(u->sink->asyncmsgq);
             continue;
         }
@@ -155,30 +155,30 @@ static void thread_func(void *userdata) {
 
         if (running) {
             pa_gettimeofday(&now);
-            
+
             if (pa_timeval_cmp(u->timestamp, &now) <= 0) {
                 pa_memchunk chunk;
                 size_t l;
-                
+
                 if (pa_sink_render(u->sink, u->block_size, &chunk) >= 0) {
                     l = chunk.length;
                     pa_memblock_unref(chunk.memblock);
                 } else
                     l = u->block_size;
-                
+
                 pa_timeval_add(&u->timestamp, pa_bytes_to_usec(l, &u->sink->sample_spec));
                 continue;
             }
 
             timeout = pa_timeval_diff(&u->timestamp, &now)/1000;
-            
+
             if (timeout < 1)
                 timeout = 1;
         } else
             timeout = -1;
 
         /* Hmm, nothing to do. Let's sleep */
-        
+
         if (pa_asyncmsgq_before_poll(u->sink->asyncmsgq) < 0)
             continue;
 
@@ -192,7 +192,7 @@ static void thread_func(void *userdata) {
             pa_log("poll() failed: %s", pa_cstrerror(errno));
             goto fail;
         }
-        
+
         pa_assert(r == 0 || pollfd.revents == POLLIN);
     }
 
@@ -241,7 +241,7 @@ int pa__init(pa_core *c, pa_module*m) {
     pa_sink_set_description(u->sink, pa_modargs_get_value(ma, "description", "NULL sink"));
 
     u->block_size = pa_bytes_per_second(&ss) / 20; /* 50 ms */
-    
+
     if (u->block_size <= 0)
         u->block_size = pa_frame_size(&ss);
 
@@ -249,7 +249,7 @@ int pa__init(pa_core *c, pa_module*m) {
         pa_log("Failed to create thread.");
         goto fail;
     }
-    
+
     pa_modargs_free(ma);
 
     return 0;
@@ -265,7 +265,7 @@ fail:
 
 void pa__done(pa_core *c, pa_module*m) {
     struct userdata *u;
-    
+
     pa_assert(c);
     pa_assert(m);
 
@@ -278,7 +278,7 @@ void pa__done(pa_core *c, pa_module*m) {
         pa_asyncmsgq_send(u->sink->asyncmsgq, PA_SINK_MESSAGE_SHUTDOWN, NULL);
         pa_thread_free(u->thread);
     }
-    
+
     pa_sink_unref(u->sink);
 
     pa_xfree(u);
diff --git a/src/modules/module-pipe-sink.c b/src/modules/module-pipe-sink.c
index 61672ed..e4735f6 100644
--- a/src/modules/module-pipe-sink.c
+++ b/src/modules/module-pipe-sink.c
@@ -124,9 +124,9 @@ static void thread_func(void *userdata) {
                     default:
                         pa_sink_process_msg(u->sink->asyncmsgq, object, code, data);
                 }
-                
+
             } else if (object == u->sink) {
-                        
+
                 case PA_SINK_MESSAGE_STOP:
                     pa_assert(running);
                     running = 0;
@@ -155,7 +155,7 @@ static void thread_func(void *userdata) {
                 default:
                     pa_sink_process_msg(u->sink->asyncmsgq, object, code, data);
             }
-            
+
             pa_asyncmsgq_done(u->sink->asyncmsgq);
             continue;
         }
@@ -171,20 +171,20 @@ static void thread_func(void *userdata) {
 
             if (!underrun) {
                 ssize_t l;
-                
+
                 p = pa_memblock_acquire(u->memchunk.memblock);
                 l = pa_write(u->fd, (uint8_t*) p + u->memchunk.index, u->memchunk.length);
                 pa_memblock_release(p);
-                    
+
                 if (l < 0) {
 
                     if (errno != EINTR && 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;
 
@@ -202,7 +202,7 @@ static void thread_func(void *userdata) {
         pollfd[POLLFD_FIFO].events = running && !underrun ? POLLOUT : 0;
 
         /* Hmm, nothing to do. Let's sleep */
-        
+
         if (pa_asyncmsgq_before_poll(u->sink->asyncmsgq) < 0)
             continue;
 
@@ -221,10 +221,10 @@ static void thread_func(void *userdata) {
             pa_log("FIFO shutdown.");
             goto fail;
         }
-        
+
         pa_assert(pollfd[POLLFD_ASYNCQ].revents & ~POLLIN == 0);
     }
-    
+
 fail:
     /* We have to continue processing messages until we receive the
      * SHUTDOWN message */
@@ -265,9 +265,9 @@ int pa__init(pa_core *c, pa_module*m) {
     u->memchunk.memblock = NULL;
     u->memchunk.length = 0;
     m->userdata = u;
-    
+
     mkfifo(u->filename, 0666);
-    
+
     if ((u->fd = open(u->filename, O_RDWR)) < 0) {
         pa_log("open('%s'): %s", p, pa_cstrerror(errno));
         goto fail;
@@ -290,7 +290,7 @@ int pa__init(pa_core *c, pa_module*m) {
         pa_log("Failed to create sink.");
         goto fail;
     }
-    
+
     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));
@@ -300,7 +300,7 @@ int pa__init(pa_core *c, pa_module*m) {
         pa_log("Failed to create thread.");
         goto fail;
     }
-    
+
     pa_modargs_free(ma);
 
     return 0;
@@ -328,7 +328,7 @@ void pa__done(pa_core *c, pa_module*m) {
         pa_asyncmsgq_send(u->sink->asyncmsgq, PA_SINK_MESSAGE_SHUTDOWN, NULL);
         pa_thread_free(u->thread);
     }
-    
+
     pa_sink_unref(u->sink);
 
     if (u->memchunk.memblock)
diff --git a/src/pulsecore/asyncmsgq.c b/src/pulsecore/asyncmsgq.c
index 31e27e7..de5b2f9 100644
--- a/src/pulsecore/asyncmsgq.c
+++ b/src/pulsecore/asyncmsgq.c
@@ -65,7 +65,7 @@ pa_asyncmsgq *pa_asyncmsgq_new(unsigned size) {
     pa_assert_se(a->asyncq = pa_asyncq_new(size));
     pa_assert_se(a->mutex = pa_mutex_new(0));
     a->current = NULL;
-    
+
     return a;
 }
 
@@ -82,10 +82,10 @@ void pa_asyncmsgq_free(pa_asyncmsgq *a) {
 
         if (i->memchunk.memblock)
             pa_memblock_unref(i->object);
-        
+
         if (i->userdata_free_cb)
             i->userdata_free_cb(i->userdata);
-        
+
         if (pa_flist_push(PA_STATIC_FLIST_GET(asyncmsgq), i) < 0)
             pa_xfree(i);
     }
@@ -162,7 +162,7 @@ int pa_asyncmsgq_get(pa_asyncmsgq *a, pa_msgobject **object, int *code, void **u
         *object = a->current->object;
     if (chunk)
         *chunk = a->chunk;
-    
+
     return 0;
 }
 
@@ -183,7 +183,7 @@ void pa_asyncmsgq_done(pa_asyncmsgq *a, int ret) {
 
         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);
     }
@@ -194,14 +194,14 @@ void pa_asyncmsgq_done(pa_asyncmsgq *a, int ret) {
 int pa_asyncmsgq_wait_for(pa_asyncmsgq *a, int code) {
     int c;
     pa_assert(a);
-    
+
     do {
-        
+
         if (pa_asyncmsgq_get(a, NULL, &c, NULL, 1) < 0)
             return -1;
 
         pa_asyncmsgq_done(a);
-        
+
     } while (c != code);
 
     return 0;
diff --git a/src/pulsecore/asyncq.c b/src/pulsecore/asyncq.c
index 779cd47..54d36dc 100644
--- a/src/pulsecore/asyncq.c
+++ b/src/pulsecore/asyncq.c
@@ -85,7 +85,7 @@ pa_asyncq *pa_asyncq_new(unsigned size) {
         pa_xfree(l);
         return NULL;
     }
-    
+
     if (pipe(l->write_fds) < 0) {
         pa_close(l->read_fds[0]);
         pa_close(l->read_fds[1]);
@@ -104,7 +104,7 @@ void pa_asyncq_free(pa_asyncq *l, pa_free_cb_t free_cb) {
 
     if (free_cb) {
         void *p;
-        
+
         while ((p = pa_asyncq_pop(l, 0)))
             free_cb(p);
     }
@@ -113,7 +113,7 @@ void pa_asyncq_free(pa_asyncq *l, pa_free_cb_t free_cb) {
     pa_close(l->read_fds[1]);
     pa_close(l->write_fds[0]);
     pa_close(l->write_fds[1]);
-    
+
     pa_xfree(l);
 }
 
@@ -125,12 +125,12 @@ int pa_asyncq_push(pa_asyncq*l, void *p, int wait) {
     pa_assert(p);
 
     cells = PA_ASYNCQ_CELLS(l);
-    
+
     _Y;
     idx = reduce(l, l->write_idx);
 
     if (!pa_atomic_ptr_cmpxchg(&cells[idx], NULL, p)) {
-        
+
         /* First try failed. Let's wait for changes. */
 
         if (!wait)
@@ -142,7 +142,7 @@ int pa_asyncq_push(pa_asyncq*l, void *p, int wait) {
 
         for (;;) {
             char x[20];
-            
+
             _Y;
 
             if (pa_atomic_ptr_cmpxchg(&cells[idx], NULL, p))
@@ -155,21 +155,21 @@ int pa_asyncq_push(pa_asyncq*l, void *p, int wait) {
                 return -1;
             }
         }
-        
+
         _Y;
 
         pa_atomic_dec(&l->write_waiting);
     }
-    
+
     _Y;
     l->write_idx++;
-    
+
     if (pa_atomic_load(&l->read_waiting)) {
         char x = 'x';
         _Y;
         write(l->read_fds[1], &x, sizeof(x));
     }
-    
+
     return 0;
 }
 
@@ -188,7 +188,7 @@ void* pa_asyncq_pop(pa_asyncq*l, int wait) {
     if (!(ret = pa_atomic_ptr_load(&cells[idx]))) {
 
         /* First try failed. Let's wait for changes. */
-    
+
         if (!wait)
             return NULL;
 
@@ -228,7 +228,7 @@ void* pa_asyncq_pop(pa_asyncq*l, int wait) {
         _Y;
         write(l->write_fds[1], &x, sizeof(x));
     }
-            
+
     return ret;
 }
 
@@ -253,7 +253,7 @@ int pa_asyncq_before_poll(pa_asyncq *l) {
         return -1;
 
     pa_atomic_inc(&l->read_waiting);
-    
+
     if (pa_atomic_ptr_load(&cells[idx])) {
         pa_atomic_dec(&l->read_waiting);
         return -1;
diff --git a/src/pulsecore/core.c b/src/pulsecore/core.c
index c80caf1..99ac74e 100644
--- a/src/pulsecore/core.c
+++ b/src/pulsecore/core.c
@@ -53,9 +53,9 @@ static int core_process_msg(pa_msgobject *o, int code, void *userdata, pa_memchu
     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;
@@ -67,7 +67,7 @@ static int core_process_msg(pa_msgobject *o, int code, void *userdata, pa_memchu
 
 static void asyncmsgq_cb(pa_mainloop_api*api, pa_io_event* e, int fd, pa_io_event_flags_t events, void *userdata) {
     pa_core *c = userdata;
-    
+
     pa_assert(pa_asyncmsgq_get_fd(c->asyncmsgq) == fd);
     pa_assert(events == PA_IO_EVENT_INPUT);
 
@@ -84,7 +84,7 @@ static void asyncmsgq_cb(pa_mainloop_api*api, pa_io_event* e, int fd, pa_io_even
             pa_asyncmsgq_dispatch(object, code, data, &chunk);
             pa_asyncmsgq_done(c->asyncmsgq, 0);
         }
-        
+
         if (pa_asyncmsgq_before_poll(c->asyncmsgq) == 0)
             break;
     }
@@ -97,7 +97,7 @@ pa_core* pa_core_new(pa_mainloop_api *m, int shared) {
     pa_mempool *pool;
 
     pa_assert(m);
-    
+
     if (shared) {
         if (!(pool = pa_mempool_new(shared))) {
             pa_log_warn("failed to allocate shared memory pool. Falling back to a normal memory pool.");
@@ -175,7 +175,7 @@ pa_core* pa_core_new(pa_mainloop_api *m, int shared) {
     pa_assert_se(c->asyncmsgq = pa_asyncmsgq_new(0));
     pa_assert_se(pa_asyncmsgq_before_poll(c->asyncmsgq) == 0);
     pa_assert_se(c->asyncmsgq_event = c->mainloop->io_new(c->mainloop, pa_asyncmsgq_get_fd(c->asyncmsgq), PA_IO_EVENT_INPUT, asyncmsgq_cb, c));
-            
+
     return c;
 }
 
diff --git a/src/pulsecore/core.h b/src/pulsecore/core.h
index dc2ebb4..86660b7 100644
--- a/src/pulsecore/core.h
+++ b/src/pulsecore/core.h
@@ -48,7 +48,7 @@ typedef struct pa_core pa_core;
 
 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;
diff --git a/src/pulsecore/flist.c b/src/pulsecore/flist.c
index 3805e1d..022010b 100644
--- a/src/pulsecore/flist.c
+++ b/src/pulsecore/flist.c
@@ -163,7 +163,7 @@ int pa_flist_push(pa_flist*l, void *p) {
     assert(p);
 
     cells = PA_FLIST_CELLS(l);
-    
+
     n = len = (int) l->size - pa_atomic_load(&l->length) + N_EXTRA_SCAN;
     _Y;
     idx = reduce(l, pa_atomic_load(&l->write_idx));
diff --git a/src/pulsecore/msgobject.c b/src/pulsecore/msgobject.c
index ea404cc..ce9f22f 100644
--- a/src/pulsecore/msgobject.c
+++ b/src/pulsecore/msgobject.c
@@ -30,7 +30,7 @@
 
 pa_msgobject *pa_msgobject_new_internal(size_t size, const char *type_name) {
     pa_msgobject *o;
-    
+
     pa_assert(size > sizeof(pa_msgobject));
     pa_assert(type_name);
 
diff --git a/src/pulsecore/object.c b/src/pulsecore/object.c
index de7d5ad..e6ed53b 100644
--- a/src/pulsecore/object.c
+++ b/src/pulsecore/object.c
@@ -30,7 +30,7 @@
 
 pa_object *pa_object_new_internal(size_t size, const char *type_name) {
     pa_object *o;
-    
+
     pa_assert(size > sizeof(pa_object));
     pa_assert(type_name);
 
diff --git a/src/pulsecore/object.h b/src/pulsecore/object.h
index 8fccf19..e195a35 100644
--- a/src/pulsecore/object.h
+++ b/src/pulsecore/object.h
@@ -68,5 +68,5 @@ static inline int pa_object_refcnt(pa_object *o) {
         pa_object_assert_ref(PA_OBJECT(o));                     \
     }                                                           \
     struct __stupid_useless_struct_to_allow_trailing_semicolon
-        
+
 #endif
diff --git a/src/pulsecore/once-posix.c b/src/pulsecore/once-posix.c
index 7ccd08e..25ccb03 100644
--- a/src/pulsecore/once-posix.c
+++ b/src/pulsecore/once-posix.c
@@ -35,17 +35,17 @@
 /* Not reentrant -- how could it be? */
 void pa_once(pa_once_t *control, pa_once_func_t func) {
     pa_mutex *m;
-    
+
     pa_assert(control);
     pa_assert(func);
 
     if (pa_atomic_load(&control->done))
         return;
-    
+
     pa_atomic_inc(&control->ref);
-        
+
     for (;;) {
-        
+
         if ((m = pa_atomic_ptr_load(&control->mutex))) {
 
             /* The mutex is stored in locked state, hence let's just
@@ -57,7 +57,7 @@ void pa_once(pa_once_t *control, pa_once_func_t func) {
 
         pa_assert_se(m = pa_mutex_new(0));
         pa_mutex_lock(m);
-        
+
         if (pa_atomic_ptr_cmpxchg(&control->mutex, NULL, m)) {
             func();
             pa_atomic_store(&control->done, 1);
@@ -71,7 +71,7 @@ void pa_once(pa_once_t *control, pa_once_func_t func) {
     }
 
     pa_assert(pa_atomic_load(&control->done));
-    
+
     if (pa_atomic_dec(&control->ref) <= 1) {
         pa_assert(pa_atomic_ptr_cmpxchg(&control->mutex, m, NULL));
         pa_mutex_free(m);
diff --git a/src/pulsecore/protocol-simple.c b/src/pulsecore/protocol-simple.c
index 288cf87..b7a4cc7 100644
--- a/src/pulsecore/protocol-simple.c
+++ b/src/pulsecore/protocol-simple.c
@@ -86,11 +86,11 @@ enum {
 };
 
 enum {
-    MESSAGE_REQUEST_DATA,   /* data from source output to main loop */ 
+    MESSAGE_REQUEST_DATA,   /* data from source output to main loop */
     MESSAGE_POST_DATA       /* data from source output to main loop */
 };
 
-    
+
 #define PLAYBACK_BUFFER_SECONDS (.5)
 #define PLAYBACK_BUFFER_FRAGMENTS (10)
 #define RECORD_BUFFER_SECONDS (5)
@@ -105,15 +105,15 @@ static void connection_free(struct connection *c) {
         pa_sink_input_disconnect(c->sink_input);
         pa_sink_input_unref(c->sink_input);
     }
-    
+
     if (c->source_output) {
         pa_source_output_disconnect(c->source_output);
         pa_source_output_unref(c->source_output);
     }
-    
+
     if (c->playback.current_memblock)
         pa_memblock_unref(c->playback.current_memblock);
-    
+
     if (c->client)
         pa_client_free(c->client);
     if (c->io)
@@ -122,7 +122,7 @@ static void connection_free(struct connection *c) {
         pa_memblockq_free(c->input_memblockq);
     if (c->output_memblockq)
         pa_memblockq_free(c->output_memblockq);
-    
+
     pa_xfree(c);
 }
 
@@ -133,7 +133,7 @@ static int do_read(struct connection *c) {
     void *p;
 
     pa_assert(c);
-    
+
     if (!c->sink_input || !(l = pa_atomic_load(&c->playback.missing)))
         return 0;
 
@@ -155,12 +155,12 @@ static int do_read(struct connection *c) {
     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 (errno == EINTR || errno == EAGAIN)
             return 0;
-        
+
         pa_log_debug("read(): %s", r == 0 ? "EOF" : pa_cstrerror(errno));
         return -1;
     }
@@ -195,7 +195,7 @@ static int do_write(struct connection *c) {
     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) {
@@ -208,7 +208,7 @@ static int do_write(struct connection *c) {
     }
 
     pa_memblockq_drop(c->output_memblockq, &chunk, r);
-    
+
     return 0;
 }
 
@@ -251,7 +251,7 @@ fail:
 /* Called from thread context */
 static int sink_input_process_msg(pa_sink_input *i, int code, void *userdata, const pa_memchunk *chunk) {
     struct connection*c;
-    
+
     pa_assert(i);
     c = i->userdata;
     pa_assert(c);
@@ -265,10 +265,10 @@ static int sink_input_process_msg(pa_sink_input *i, int code, void *userdata, co
             pa_memblockq_push_align(c->input_memblockq, chunk);
             return 0;
         }
-        
+
         case PA_SINK_INPUT_MESSAGE_GET_LATENCY: {
             pa_usec_t *r = userdata;
-            
+
             *r = pa_bytes_to_usec(pa_memblockq_get_length(c->input_memblockq), &c->sink_input->sample_spec);
 
             /* Fall through, the default handler will add in the extra
@@ -283,7 +283,7 @@ static int sink_input_process_msg(pa_sink_input *i, int code, void *userdata, co
 /* Called from thread context */
 static int sink_input_peek_cb(pa_sink_input *i, pa_memchunk *chunk) {
     struct connection*c;
-    
+
     pa_assert(i);
     c = i->userdata;
     pa_assert(c);
@@ -301,7 +301,7 @@ 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) {
     struct connection*c = i->userdata;
     size_t old, new;
-    
+
     pa_assert(i);
     pa_assert(c);
     pa_assert(length);
@@ -320,7 +320,7 @@ static void sink_input_drop_cb(pa_sink_input *i, const pa_memchunk *chunk, size_
 static void sink_input_kill_cb(pa_sink_input *i) {
     pa_assert(i);
     pa_assert(i->userdata);
-    
+
     connection_free((struct connection *) i->userdata);
 }
 
@@ -328,7 +328,7 @@ static void sink_input_kill_cb(pa_sink_input *i) {
 
 static void source_output_push_cb(pa_source_output *o, const pa_memchunk *chunk) {
     struct connection *c;
-    
+
     pa_assert(o);
     c = o->userdata;
     pa_assert(c);
@@ -343,17 +343,17 @@ static void source_output_kill_cb(pa_source_output *o) {
     pa_assert(o);
     c = o->userdata;
     pa_assert(c);
-    
+
     connection_free(c);
 }
 
 static pa_usec_t source_output_get_latency_cb(pa_source_output *o) {
     struct connection*c;
-    
+
     pa_assert(o);
     c = o->userdata;
     pa_assert(c);
-    
+
     return pa_bytes_to_usec(pa_memblockq_get_length(c->output_memblockq), &c->source_output->sample_spec);
 }
 
@@ -361,7 +361,7 @@ static pa_usec_t source_output_get_latency_cb(pa_source_output *o) {
 
 static void client_kill_cb(pa_client *client) {
     struct connection*c;
-    
+
     pa_assert(client);
     c = client->userdata;
     pa_assert(c);
@@ -386,7 +386,7 @@ static void on_connection(pa_socket_server*s, pa_iochannel *io, void *userdata)
     pa_protocol_simple *p = userdata;
     struct connection *c = NULL;
     char cname[256];
-    
+
     pa_assert(s);
     pa_assert(io);
     pa_assert(p);
@@ -415,7 +415,7 @@ static void on_connection(pa_socket_server*s, pa_iochannel *io, void *userdata)
     c->client->kill = client_kill_cb;
     c->client->userdata = c;
 
-    
+
     if (p->mode & PLAYBACK) {
         pa_sink_input_new_data data;
         size_t l;
@@ -493,7 +493,7 @@ static void on_connection(pa_socket_server*s, pa_iochannel *io, void *userdata)
 
     pa_iochannel_set_callback(c->io, io_callback, c);
     pa_idxset_put(p->connections, c, NULL);
-    
+
     return;
 
 fail:
@@ -504,7 +504,7 @@ fail:
 static void asyncmsgq_cb(pa_mainloop_api*api, pa_io_event* e, int fd, pa_io_event_flags_t events, void *userdata) {
     pa_protocol_simple *p = userdata;
     int do_some_work = 0;
-    
+
     pa_assert(pa_asyncmsgq_get_fd(p->asyncmsgq) == fd);
     pa_assert(events == PA_IO_EVENT_INPUT);
 
@@ -520,7 +520,7 @@ static void asyncmsgq_cb(pa_mainloop_api*api, pa_io_event* e, int fd, pa_io_even
             connection *c = object;
 
             pa_assert(c);
-            
+
             switch (code) {
 
                 case MESSAGE_REQUEST_DATA:
@@ -535,7 +535,7 @@ static void asyncmsgq_cb(pa_mainloop_api*api, pa_io_event* e, int fd, pa_io_even
 
             pa_asyncmsgq_done(p->asyncmsgq);
         }
-        
+
         if (pa_asyncmsgq_before_poll(p->asyncmsgq) == 0)
             break;
     }
@@ -544,7 +544,7 @@ static void asyncmsgq_cb(pa_mainloop_api*api, pa_io_event* e, int fd, pa_io_even
 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;
-    
+
     pa_assert(core);
     pa_assert(server);
     pa_assert(ma);
@@ -588,13 +588,13 @@ pa_protocol_simple* pa_protocol_simple_new(pa_core *core, pa_socket_server *serv
 
     pa_assert_se(pa_asyncmsgq_before_poll(p->asyncmsgq) == 0);
     pa_assert_se(p->asyncmsgq_event = core->mainloop->io_event_new(core->mainloop, pa_asyncmsgq_get_fd(p->asyncmsgq), PA_IO_EVENT_INPUT, p));
-    
+
     return p;
 
 fail:
     if (p)
         pa_protocol_simple_free(p);
-    
+
     return NULL;
 }
 
@@ -618,7 +618,7 @@ void pa_protocol_simple_free(pa_protocol_simple *p) {
         pa_asyncmsgq_after_poll(c->asyncmsgq);
         pa_asyncmsgq_free(p->asyncmsgq);
     }
-    
+
     pa_xfree(p);
 }
 
diff --git a/src/pulsecore/semaphore-posix.c b/src/pulsecore/semaphore-posix.c
index 71ec57a..750c2af 100644
--- a/src/pulsecore/semaphore-posix.c
+++ b/src/pulsecore/semaphore-posix.c
@@ -60,7 +60,7 @@ void pa_semaphore_post(pa_semaphore *s) {
 void pa_semaphore_wait(pa_semaphore *s) {
     int ret;
     pa_assert(s);
-    
+
     do {
         ret = sem_wait(&s->sem);
     } while (ret < 0 && errno == EINTR);
diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c
index da7b58b..00b82d2 100644
--- a/src/pulsecore/sink-input.c
+++ b/src/pulsecore/sink-input.c
@@ -52,7 +52,7 @@ pa_sink_input_new_data* pa_sink_input_new_data_init(pa_sink_input_new_data *data
 
     memset(data, 0, sizeof(*data));
     data->resample_method = PA_RESAMPLER_INVALID;
-    
+
     return data;
 }
 
@@ -117,7 +117,7 @@ pa_sink_input* pa_sink_input_new(
     if (!data->channel_map_is_set) {
         if (data->sink->channel_map.channels == data->sample_spec.channels)
             data->channel_map = data->sink->channel_map;
-        else 
+        else
             pa_channel_map_init_auto(&data->channel_map, data->sample_spec.channels, PA_CHANNEL_MAP_DEFAULT);
     }
 
@@ -132,7 +132,7 @@ pa_sink_input* pa_sink_input_new(
 
     if (!data->muted_is_set)
         data->muted = 0;
-    
+
     if (data->resample_method == PA_RESAMPLER_INVALID)
         data->resample_method = core->resample_method;
 
@@ -163,7 +163,7 @@ pa_sink_input* pa_sink_input_new(
 
     i->parent.parent.free = sink_input_free;
     i->parent.process_msg = pa_sink_input_process_msg;
-    
+
     i->core = core;
     pa_atomic_load(&i->state, PA_SINK_INPUT_DRAINED);
     i->flags = flags;
@@ -172,14 +172,14 @@ pa_sink_input* pa_sink_input_new(
     i->module = data->module;
     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;
-    
+
     i->process_msg = NULL;
     i->peek = NULL;
     i->drop = NULL;
@@ -214,7 +214,7 @@ void pa_sink_input_disconnect(pa_sink_input *i) {
     pa_return_if_fail(pa_sink_input_get_state(i) != PA_SINK_INPUT_DISCONNECTED);
 
     pa_asyncmsgq_send(i->sink->asyncmsgq, i->sink, PA_SINK_MESSAGE_REMOVE_INPUT, i, NULL);
-    
+
     pa_idxset_remove_by_data(i->sink->core->sink_inputs, i, NULL);
     pa_idxset_remove_by_data(i->sink->inputs, i, NULL);
 
@@ -236,7 +236,7 @@ static void sink_input_free(pa_msgobject *o) {
 
     pa_assert(i);
     pa_assert(pa_sink_input_refcnt(i) == 0);
-    
+
     pa_sink_input_disconnect(i);
 
     pa_log_info("Freeing output %u \"%s\"", i->index, i->name);
@@ -281,7 +281,7 @@ pa_usec_t pa_sink_input_get_latency(pa_sink_input *i) {
 
     if (pa_asyncmsgq_send(i->sink->asyncmsgq, i->sink, PA_SINK_INPUT_MESSAGE_GET_LATENCY, &r, NULL) < 0)
         r = 0;
-    
+
     if (i->get_latency)
         r += i->get_latency(i);
 
@@ -293,7 +293,7 @@ int pa_sink_input_peek(pa_sink_input *i, pa_memchunk *chunk, pa_cvolume *volume)
     int do_volume_adj_here;
     int volume_is_norm;
     pa_sink_input_state_t state;
-    
+
     pa_sink_input_assert_ref(i);
     pa_assert(chunk);
     pa_assert(volume);
@@ -508,7 +508,7 @@ int pa_sink_input_set_rate(pa_sink_input *i, uint32_t rate) {
     i->sample_spec.rate = rate;
 
     pa_asyncmsgq_post(s->asyncmsgq, pa_sink_input_ref(i), PA_SINK_INPUT_MESSAGE_SET_RATE, PA_UINT_TO_PTR(rate), NULL, pa_sink_input_unref, NULL);
-    
+
     pa_subscription_post(i->sink->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index);
     return 0
 }
@@ -543,7 +543,7 @@ int pa_sink_input_move_to(pa_sink_input *i, pa_sink *dest, int immediately) {
     pa_sink_assert_ref(dest);
 
     return -1;
-    
+
 /*     origin = i->sink; */
 
 /*     if (dest == origin) */
@@ -697,32 +697,32 @@ int pa_sink_input_move_to(pa_sink_input *i, pa_sink *dest, int immediately) {
 
 int pa_sink_input_process_msg(pa_msgobject *o, int code, void *userdata, pa_memchunk *chunk) {
     pa_sink_input *i = PA_SINK_INPUT(o);
-    
+
     pa_sink_input_assert_ref(i);
 
     switch (code) {
         case PA_SINK_INPUT_MESSAGE_SET_VOLUME:
             s->thread_info.soft_volume = *((pa_cvolume*) userdata);
             return 0;
-            
+
         case PA_SINK_INPUT_MESSAGE_SET_MUTE:
             s->thread_info.soft_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->resampled_chunk.length, &i->sink->sample_spec);
 
 /*             if (i->move_silence) */
 /*                 r += pa_bytes_to_usec(i->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->resampler, PA_PTR_TO_UINT(userdata));
 
diff --git a/src/pulsecore/sink-input.h b/src/pulsecore/sink-input.h
index 64a7a73..338d696 100644
--- a/src/pulsecore/sink-input.h
+++ b/src/pulsecore/sink-input.h
@@ -52,7 +52,7 @@ typedef enum pa_sink_input_flags {
 
 struct pa_sink_input {
     pa_msgobject parent;
-    
+
     uint32_t index;
     pa_core *core;
     pa_atomic_t state;
@@ -66,11 +66,11 @@ struct pa_sink_input {
 
     pa_sample_spec sample_spec;
     pa_channel_map channel_map;
-    
+
     pa_cvolume volume;
     int muted;
 
-    int (*process_msg)(pa_sink_input *i, int code, void *userdata); 
+    int (*process_msg)(pa_sink_input *i, int code, void *userdata);
     int (*peek) (pa_sink_input *i, pa_memchunk *chunk);
     void (*drop) (pa_sink_input *i, const pa_memchunk *chunk, size_t length);
     void (*kill) (pa_sink_input *i);             /* may be NULL */
@@ -81,10 +81,10 @@ struct pa_sink_input {
 
     struct {
         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. */
@@ -94,7 +94,7 @@ struct pa_sink_input {
         pa_cvolume volume;
         int muted;
     } thread_info;
-    
+
     void *userdata;
 };
 
diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c
index 3620559..0e022d9 100644
--- a/src/pulsecore/sink.c
+++ b/src/pulsecore/sink.c
@@ -86,7 +86,7 @@ pa_sink* pa_sink_new(
 
     s->parent.parent.free = sink_free;
     s->parent.process_msg = pa_sink_process_msg;
-    
+
     s->core = core;
     pa_atomic_store(&s->state, PA_SINK_IDLE);
     s->name = pa_xstrdup(name);
@@ -115,7 +115,7 @@ pa_sink* pa_sink_new(
     s->userdata = NULL;
 
     pa_assert_se(s->asyncmsgq = pa_asyncmsgq_new(0));
-    
+
     r = pa_idxset_put(core->sinks, s, &s->index);
     pa_assert(s->index != PA_IDXSET_INVALID && r >= 0);
 
@@ -139,7 +139,7 @@ pa_sink* pa_sink_new(
     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;
-    
+
     pa_subscription_post(core, PA_SUBSCRIPTION_EVENT_SINK | PA_SUBSCRIPTION_EVENT_NEW, s->index);
 
     return s;
@@ -163,7 +163,7 @@ static void sink_start(pa_sink *s) {
 static void sink_stop(pa_sink *s) {
     pa_sink_state_t state;
     int stop;
-    
+
     pa_assert(s);
     state = pa_sink_get_state(s);
     pa_return_if_fail(state == PA_SINK_RUNNING || state == PA_SINK_SUSPENDED);
@@ -216,7 +216,7 @@ void pa_sink_disconnect(pa_sink* s) {
 
 static void sink_free(pa_object *o) {
     pa_sink *s = PA_SINK(o);
-            
+
     pa_assert(s);
     pa_assert(pa_sink_refcnt(s) == 0);
 
@@ -230,11 +230,11 @@ static void sink_free(pa_object *o) {
     }
 
     pa_idxset_free(s->inputs, NULL, NULL);
-    
+
     pa_hashmap_free(s->thread_info.inputs, (pa_free2_cb_t) pa_sink_input_unref, NULL);
 
     pa_asyncmsgq_free(s->asyncmsgq);
-    
+
     pa_xfree(s->name);
     pa_xfree(s->description);
     pa_xfree(s->driver);
@@ -246,7 +246,7 @@ void pa_sink_update_status(pa_sink*s) {
 
     if (pa_sink_get_state(s) == PA_SINK_SUSPENDED)
         return;
-    
+
     if (pa_sink_used_by(s) > 0)
         sink_start(s);
     else
@@ -270,7 +270,7 @@ void pa_sink_suspend(pa_sink *s, int suspend) {
             s->stop(s);
         else
             pa_asyncmsgq_post(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_STOP, NULL, NULL, NULL);
-        
+
     } else {
         pa_atomic_store(&s->state, PA_SINK_RUNNING);
 
@@ -417,38 +417,38 @@ int pa_sink_render_into(pa_sink*s, pa_memchunk *target) {
         else {
             void *src, *ptr;
             pa_cvolume 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);
-        
+
         target->length = pa_mix(info, n,
                                 (uint8_t*) ptr + target->index,
                                 target->length,
                                 &s->sample_spec,
                                 &s->thread_info.soft_volume,
                                 s->thread_info.soft_muted);
-    
+
         pa_memblock_release(target->memblock);
     }
-    
+
     inputs_drop(s, info, n, target->length);
 
     if (s->monitor_source)
@@ -512,12 +512,12 @@ void pa_sink_render_full(pa_sink *s, size_t length, pa_memchunk *result) {
 
 pa_usec_t pa_sink_get_latency(pa_sink *s) {
     pa_usec_t usec = 0;
-    
+
     pa_sink_assert_ref(s);
 
     if (s->get_latency)
         return s->get_latency(s);
-    
+
     if (pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_GET_LATENCY, &usec, NULL) < 0)
         return 0;
 
@@ -532,7 +532,7 @@ void pa_sink_set_volume(pa_sink *s, const pa_cvolume *volume) {
 
     changed = !pa_cvolume_equal(volume, &s->volume);
     s->volume = *volume;
-    
+
     if (s->set_volume && s->set_volume(s) < 0)
         s->set_volume = NULL;
 
@@ -549,7 +549,7 @@ const pa_cvolume *pa_sink_get_volume(pa_sink *s) {
     pa_sink_assert_ref(s);
 
     old_volume = s->volume;
-    
+
     if (s->get_volume && s->get_volume(s) < 0)
         s->get_volume = NULL;
 
@@ -558,13 +558,13 @@ const pa_cvolume *pa_sink_get_volume(pa_sink *s) {
 
     if (!pa_cvolume_equal(&old_volume, &s->volume))
         pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
-    
+
     return &s->volume;
 }
 
 void pa_sink_set_mute(pa_sink *s, int mute) {
     int changed;
-    
+
     pa_sink_assert_ref(s);
 
     changed = s->muted != mute;
@@ -581,11 +581,11 @@ void pa_sink_set_mute(pa_sink *s, int mute) {
 
 int pa_sink_get_mute(pa_sink *s) {
     int old_muted;
-    
+
     pa_sink_assert_ref(s);
 
     old_muted = s->muted;
-    
+
     if (s->get_mute && s->get_mute(s) < 0)
         s->get_mute = NULL;
 
@@ -594,7 +594,7 @@ int pa_sink_get_mute(pa_sink *s) {
 
     if (old_muted != s->muted)
         pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
-    
+
     return s->muted;
 }
 
@@ -658,29 +658,29 @@ int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, pa_memchunk *
             pa_hashmap_put(s->thread_info.inputs, PA_UINT32_TO_PTR(i->index), pa_sink_input_ref(i));
             return 0;
         }
-            
+
         case PA_SINK_MESSAGE_REMOVE_INPUT: {
             pa_sink_input *i = userdata;
             pa_hashmap_remove(s->thread_info.inputs, PA_UINT32_TO_PTR(i->index));
             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:
             *((int*) userdata) = s->thread_info.soft_muted;
             return 0;
-            
+
         default:
             return -1;
     }
diff --git a/src/pulsecore/source-output.c b/src/pulsecore/source-output.c
index c1aa339..517c033 100644
--- a/src/pulsecore/source-output.c
+++ b/src/pulsecore/source-output.c
@@ -113,7 +113,7 @@ pa_source_output* pa_source_output_new(
     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,
@@ -127,10 +127,10 @@ pa_source_output* pa_source_output_new(
     }
 
     o = pa_source_output_new(pa_source_output);
-    
+
     o->parent.parent.free = source_output_free;
     o->parent.process_msg = pa_source_output_process_msg;
-    
+
     o->core = core;
     pa_atomic_load(&o->state, PA_SOURCE_OUTPUT_RUNNING);
     o->flags = flags;
@@ -173,7 +173,7 @@ void pa_source_output_disconnect(pa_source_output*o) {
     pa_assert(o->source->core);
 
     pa_asyncmsgq_send(i->sink->asyncmsgq, i->sink, PA_SOURCE_MESSAGE_REMOVE_OUTPUT, o, NULL);
-    
+
     pa_idxset_remove_by_data(o->source->core->source_outputs, o, NULL);
     pa_idxset_remove_by_data(o->source->outputs, o, NULL);
 
@@ -190,7 +190,7 @@ void pa_source_output_disconnect(pa_source_output*o) {
 
 static void source_output_free(pa_msgobject* mo) {
     pa_source_output *o = PA_SOURCE_OUTPUT(mo);
-    
+
     pa_assert(pa_source_output_refcnt(o) == 0);
 
     pa_source_output_disconnect(o);
@@ -207,7 +207,7 @@ static void source_output_free(pa_msgobject* mo) {
 
 void pa_source_output_put(pa_source_output *o) {
     pa_source_output_assert_ref(o);
-    
+
     pa_asyncmsgq_post(o->source->asyncmsgq, o->source, PA_SOURCE_MESSAGE_ADD_OUTPUT, o, NULL, pa_source_unref, pa_source_output_unref);
     pa_source_update_status(o->source);
 
@@ -228,7 +228,7 @@ pa_usec_t pa_source_output_get_latency(pa_source_output *o) {
 
     if (pa_asyncmsgq_send(o->source->asyncmsgq, i->source, PA_SOURCE_OUTPUT_MESSAGE_GET_LATENCY, &r, NULL) < 0)
         r = 0;
-    
+
     if (o->get_latency)
         r += o->get_latency(o);
 
@@ -244,12 +244,12 @@ void pa_source_output_push(pa_source_output *o, const pa_memchunk *chunk) {
     pa_assert(chunk->length);
 
     state = pa_source_output_get_state(o);
-    
+
     if (!o->push || state == PA_SOURCE_OUTPUT_DISCONNECTED || state == PA_SOURCE_OUTPUT_CORKED)
         return;
 
     pa_assert(state = PA_SOURCE_OUTPUT_RUNNING);
-    
+
     if (!o->resampler) {
         o->push(o, chunk);
         return;
@@ -289,7 +289,7 @@ int pa_source_output_set_rate(pa_source_output *o, uint32_t rate) {
     i->sample_spec.rate = rate;
 
     pa_asyncmsgq_post(s->asyncmsgq, pa_source_output_ref(i), PA_SOURCE_OUTPUT_MESSAGE_SET_RATE, PA_UINT_TO_PTR(rate), NULL, pa_source_output_unref, NULL);
-    
+
     pa_subscription_post(o->source->core, PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT!|PA_SUBSCRIPTION_EVENT_CHANGE, i->index);
     return 0;
 }
@@ -312,7 +312,7 @@ void pa_source_output_set_name(pa_source_output *o, const char *name) {
 pa_resample_method_t pa_source_output_get_resample_method(pa_source_output *o) {
     pa_source_output_assert_ref(o);
 
-    return o->resample_method; 
+    return o->resample_method;
 }
 
 int pa_source_output_move_to(pa_source_output *o, pa_source *dest) {
@@ -323,7 +323,7 @@ int pa_source_output_move_to(pa_source_output *o, pa_source *dest) {
     pa_source_assert_ref(dest);
 
     return -1;
-    
+
 /*     origin = o->source; */
 
 /*     if (dest == origin) */
@@ -377,13 +377,13 @@ int pa_source_output_move_to(pa_source_output *o, pa_source *dest) {
 
 int pa_source_output_process_msg(pa_msgobject *mo, int code, void *userdata, pa_memchunk* chunk) {
     pa_source_output *o = PA_SOURCE_OUTPUT(o);
-    
+
     pa_source_output_assert_ref(i);
 
     switch (code) {
 
         case PA_SOURCE_OUTPUT_MESSAGE_SET_RATE: {
-            
+
             i->thread_info.sample_spec.rate = PA_PTR_TO_UINT(userdata);
             pa_resampler_set_output_rate(i->resampler, PA_PTR_TO_UINT(userdata));
 
diff --git a/src/pulsecore/source-output.h b/src/pulsecore/source-output.h
index 0f9c3ba..e7c2c13 100644
--- a/src/pulsecore/source-output.h
+++ b/src/pulsecore/source-output.h
@@ -48,7 +48,7 @@ typedef enum pa_source_output_flags {
 
 struct pa_source_output {
     pa_msgobject parent;
-    
+
     uint32_t index;
     pa_core *core;
     pa_atomic_t state;
@@ -72,10 +72,10 @@ struct pa_source_output {
 
     struct {
         pa_sample_spec sample_spec;
-        
+
         pa_resampler* resampler;              /* may be NULL */
     } thread_info;
-        
+
     void *userdata;
 };
 
diff --git a/src/pulsecore/source.c b/src/pulsecore/source.c
index fd3c85d..7d01338 100644
--- a/src/pulsecore/source.c
+++ b/src/pulsecore/source.c
@@ -78,7 +78,7 @@ pa_source* pa_source_new(
 
     s->parent.parent.free = source_free;
     s->parent.process_msg = pa_source_process_msg;
-    
+
     s->core = core;
     pa_atomic_store(&s->state, PA_SOURCE_IDLE);
     s->name = pa_xstrdup(name);
@@ -108,7 +108,7 @@ pa_source* pa_source_new(
     s->userdata = NULL;
 
     pa_assert_se(s->asyncmsgq = pa_asyncmsgq_new(0));
-    
+
     r = pa_idxset_put(core->sources, s, &s->index);
     assert(s->index != PA_IDXSET_INVALID && r >= 0);
 
@@ -118,7 +118,7 @@ pa_source* pa_source_new(
     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;
-    
+
     pa_subscription_post(core, PA_SUBSCRIPTION_EVENT_SOURCE | PA_SUBSCRIPTION_EVENT_NEW, s->index);
 
     return s;
@@ -142,7 +142,7 @@ static void source_start(pa_source *s) {
 static void source_stop(pa_source *s) {
     pa_source_state_t state;
     int stop;
-    
+
     pa_assert(s);
     state = pa_source_get_state(s);
     pa_return_if_fail(state == PA_SOURCE_RUNNING || state == PA_SOURCE_SUSPENDED);
@@ -165,7 +165,7 @@ void pa_source_disconnect(pa_source *s) {
     pa_return_if_fail(pa_sink_get_state(s) != PA_SINK_DISCONNECT);
 
     source_stop(s);
-    
+
     pa_atomic_store(&s->state, PA_SOURCE_DISCONNECTED);
     pa_namereg_unregister(s->core, s->name);
 
@@ -192,7 +192,7 @@ void pa_source_disconnect(pa_source *s) {
 
 static void source_free(pa_msgobject *o) {
     pa_source *s = PA_SOURCE(o);
-    
+
     pa_assert(s);
     pa_assert(pa_source_refcnt(s) == 0);
 
@@ -204,7 +204,7 @@ static void source_free(pa_msgobject *o) {
     pa_hashmap_free(s->thread_info.outputs, pa_sink_output_unref, NULL);
 
     pa_asyncmsgq_free(s->asyncmsgq);
-    
+
     pa_xfree(s->name);
     pa_xfree(s->description);
     pa_xfree(s->driver);
@@ -216,7 +216,7 @@ void pa_source_update_status(pa_source*s) {
 
     if (pa_source_get_state(s) == PA_SOURCE_STATE_SUSPENDED)
         return;
-    
+
     if (pa_source_used_by(s) > 0)
         source_start(s);
     else
@@ -240,7 +240,7 @@ void pa_source_suspend(pa_source *s, int suspend) {
             s->stop(s);
         else
             pa_asyncmsgq_post(s->asyncmsgq, s, PA_SOURCE_MESSAGE_STOP, NULL, NULL, pa_source_unref, NULL);
-        
+
     } else {
         pa_atomic_store(&s->state, PA_SOURCE_RUNNING);
 
@@ -254,7 +254,7 @@ void pa_source_suspend(pa_source *s, int suspend) {
 void pa_source_post(pa_source*s, const pa_memchunk *chunk) {
     pa_source_output *o;
     void *state = NULL;
-    
+
     pa_source_assert_ref(s);
     pa_assert(chunk);
 
@@ -263,7 +263,7 @@ void pa_source_post(pa_source*s, const pa_memchunk *chunk) {
 
         pa_memblock_ref(vchunk.memblock);
         pa_memchunk_make_writable(&vchunk, 0);
-        
+
         if (s->thread_info.muted || pa_cvolume_is_muted(s->thread_info.volume))
             pa_silence_memchunk(&vchunk, &s->sample_spec);
         else
@@ -271,10 +271,10 @@ void pa_source_post(pa_source*s, const pa_memchunk *chunk) {
 
         while ((o = pa_hashmap_iterate(s->thread_info.outputs, &state, NULL)))
             pa_source_output_push(o, &vchunk);
-            
+
         pa_memblock_unref(vchunk.memblock);
     } else {
-        
+
         while ((o = pa_hashmap_iterate(s->thread_info.outputs, &state, NULL)))
             pa_source_output_push(o, chunk);
 
@@ -303,7 +303,7 @@ void pa_source_set_volume(pa_source *s, const pa_cvolume *volume) {
 
     changed = !pa_cvolume_equal(volume, s->volume);
     s->volume = *volume;
-    
+
     if (s->set_volume && s->set_volume(s) < 0)
         s->set_volume = NULL;
 
@@ -318,7 +318,7 @@ const pa_cvolume *pa_source_get_volume(pa_source *s) {
     pa_source_assert_ref(s);
 
     old_volume = s->volume;
-    
+
     if (s->get_volume && s->get_volume(s) < 0)
         s->get_volume = NULL;
 
@@ -327,13 +327,13 @@ const pa_cvolume *pa_source_get_volume(pa_source *s) {
 
     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;
 }
 
 void pa_source_set_mute(pa_source *s, pa_mixer_t m, int mute) {
     int changed;
-    
+
     pa_source_assert_ref(s);
 
     changed = s->muted != mute;
@@ -350,11 +350,11 @@ void pa_source_set_mute(pa_source *s, pa_mixer_t m, int mute) {
 
 int pa_source_get_mute(pa_source *s, pa_mixer_t m) {
     int old_muted;
-    
+
     pa_source_assert_ref(s);
 
     old_muted = s->muted;
-    
+
     if (s->get_mute && s->get_mute(s) < 0)
         s->get_mute = NULL;
 
@@ -363,7 +363,7 @@ int pa_source_get_mute(pa_source *s, pa_mixer_t m) {
 
     if (old_muted != s->muted)
         pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
-    
+
     return s->muted;
 }
 
@@ -374,7 +374,7 @@ void pa_source_set_module(pa_source *s, pa_module *m) {
         return;
 
     s->module = m;
-    
+
     pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
 }
 
@@ -409,29 +409,29 @@ int pa_source_process_msg(pa_msgobject *o, void *object, int code, pa_memchunk *
             pa_hashmap_put(s->thread_info.outputs, PA_UINT32_TO_PTR(i->index), pa_source_output_ref(i));
             return 0;
         }
-            
+
         case PA_SOURCE_MESSAGE_REMOVE_INPUT: {
             pa_source_input *i = userdata;
             pa_hashmap_remove(s->thread_info.outputs, PA_UINT32_TO_PTR(i->index), pa_source_output_ref(i));
             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:
             *((int*) userdata) = s->thread_info.soft_muted;
             return 0;
-            
+
         default:
             return -1;
     }
diff --git a/src/pulsecore/source.h b/src/pulsecore/source.h
index 1e20c6e..b41b1bc 100644
--- a/src/pulsecore/source.h
+++ b/src/pulsecore/source.h
@@ -54,7 +54,7 @@ typedef enum pa_source_state {
 
 struct pa_source {
     pa_msgobject parent;
-    
+
     uint32_t index;
     pa_core *core;
     pa_atomic_t state;
@@ -91,7 +91,7 @@ struct pa_source {
         pa_cvolume soft_volume;
         int soft_muted;
     } thread_info;
-    
+
     void *userdata;
 };
 
diff --git a/src/tests/asyncmsgq-test.c b/src/tests/asyncmsgq-test.c
index 8a0f5a3..d10b512 100644
--- a/src/tests/asyncmsgq-test.c
+++ b/src/tests/asyncmsgq-test.c
@@ -48,11 +48,11 @@ static void the_thread(void *_q) {
 
     do {
         int code = 0;
-        
+
         pa_assert_se(pa_asyncmsgq_get(q, NULL, &code, NULL, 1) == 0);
 
         switch (code) {
-            
+
             case OPERATION_A:
                 printf("Operation A\n");
                 break;
@@ -64,7 +64,7 @@ static void the_thread(void *_q) {
             case OPERATION_C:
                 printf("Operation C\n");
                 break;
-                
+
             case QUIT:
                 printf("quit\n");
                 quit = 1;
@@ -79,7 +79,7 @@ static void the_thread(void *_q) {
 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));
diff --git a/src/tests/asyncq-test.c b/src/tests/asyncq-test.c
index 10566db..600d9d0 100644
--- a/src/tests/asyncq-test.c
+++ b/src/tests/asyncq-test.c
@@ -38,7 +38,7 @@
 static void producer(void *_q) {
     pa_asyncq *q = _q;
     int i;
-    
+
     for (i = 0; i < 1000; i++) {
         pa_asyncq_push(q, (void*) (i+1), 1);
         printf("pushed %i\n", i);
@@ -54,7 +54,7 @@ static void consumer(void *_q) {
     int i;
 
     sleep(1);
-    
+
     for (i = 0;; i++) {
         p = pa_asyncq_pop(q, 1);
 
@@ -62,7 +62,7 @@ static void consumer(void *_q) {
             break;
 
         pa_assert(p == (void *) (i+1));
-        
+
         printf("popped %i\n", i);
     }
 
@@ -72,7 +72,7 @@ static void consumer(void *_q) {
 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));

commit 590ae20d4de57d94ff276b62a0c726ec7b2f8154
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Jun 11 13:53:16 2007 +0000

    Add new untabify makefile target
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1471 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/Makefile.am b/Makefile.am
index abc3d77..0fd4ccc 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -48,4 +48,7 @@ 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;' \{\} \;
+
 .PHONY: homepage distcleancheck doxygen

commit 69115687ad1604ddfa9fa7cd86eb286e6bb5ea9a
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Jun 11 13:53:31 2007 +0000

    make untabify
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1472 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/daemon/main.c b/src/daemon/main.c
index 91cc3a2..2424efa 100644
--- a/src/daemon/main.c
+++ b/src/daemon/main.c
@@ -568,7 +568,7 @@ int main(int argc, char *argv[]) {
     assert(mainloop);
 
     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;
     }
 
diff --git a/src/modules/alsa-util.c b/src/modules/alsa-util.c
index 40be531..0a51802 100644
--- a/src/modules/alsa-util.c
+++ b/src/modules/alsa-util.c
@@ -326,7 +326,7 @@ int pa_alsa_set_hw_params(snd_pcm_t *pcm_handle, pa_sample_spec *ss, uint32_t *p
     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)
+            (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)
diff --git a/src/modules/module-detect.c b/src/modules/module-detect.c
index 41b68ac..29d6fc2 100644
--- a/src/modules/module-detect.c
+++ b/src/modules/module-detect.c
@@ -139,7 +139,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;
         }
 
@@ -155,13 +155,13 @@ static int detect_oss(pa_core *c, int just_one) {
             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);
 
             if (!pa_module_load(c, "module-oss", args))
                 continue;
-	}
+        }
 
         n++;
 
diff --git a/src/modules/oss-util.c b/src/modules/oss-util.c
index fb53146..4be71e2 100644
--- a/src/modules/oss-util.c
+++ b/src/modules/oss-util.c
@@ -99,7 +99,7 @@ success:
 #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" : "",
diff --git a/src/pulse/utf8.c b/src/pulse/utf8.c
index 2ac2d10..923e021 100644
--- a/src/pulse/utf8.c
+++ b/src/pulse/utf8.c
@@ -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
diff --git a/src/pulsecore/g711.c b/src/pulsecore/g711.c
index 8c2bbf0..aa2d703 100644
--- a/src/pulsecore/g711.c
+++ b/src/pulsecore/g711.c
@@ -43,30 +43,30 @@
 
 #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
diff --git a/src/pulsecore/pipe.c b/src/pulsecore/pipe.c
index 7f6bb2e..e614c9c 100644
--- a/src/pulsecore/pipe.c
+++ b/src/pulsecore/pipe.c
@@ -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 */
diff --git a/src/pulsecore/shm.c b/src/pulsecore/shm.c
index 444d401..8c7fb4d 100644
--- a/src/pulsecore/shm.c
+++ b/src/pulsecore/shm.c
@@ -113,7 +113,7 @@ int pa_shm_create_rw(pa_shm *m, size_t size, int shared, mode_t mode) {
         close(fd);
         m->do_unlink = 1;
 #else
-		return -1;
+                return -1;
 #endif
     }
 
@@ -139,36 +139,36 @@ void pa_shm_free(pa_shm *m) {
     assert(m->size > 0);
 
 #ifdef MAP_FAILED
-	assert(m->ptr != MAP_FAILED);
+        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);
 
                     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 */
+                assert(0);
 #endif
-	}
+        }
 
     memset(m, 0, sizeof(*m));
 }
@@ -182,7 +182,7 @@ void pa_shm_punch(pa_shm *m, size_t offset, size_t size) {
     assert(offset+size <= m->size);
 
 #ifdef MAP_FAILED
-	assert(m->ptr != MAP_FAILED);
+        assert(m->ptr != MAP_FAILED);
 #endif
 
     /* You're welcome to implement this as NOOP on systems that don't
@@ -270,7 +270,7 @@ fail:
 #else /* HAVE_SHM_OPEN */
 
 int pa_shm_attach_ro(pa_shm *m, unsigned id) {
-	return -1;
+        return -1;
 }
 
 #endif /* HAVE_SHM_OPEN */
diff --git a/src/pulsecore/socket-client.c b/src/pulsecore/socket-client.c
index b99c802..b83bfea 100644
--- a/src/pulsecore/socket-client.c
+++ b/src/pulsecore/socket-client.c
@@ -435,7 +435,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 */
@@ -479,7 +479,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 +507,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 */
diff --git a/src/pulsecore/socket-util.c b/src/pulsecore/socket-util.c
index 673058e..05cb336 100644
--- a/src/pulsecore/socket-util.c
+++ b/src/pulsecore/socket-util.c
@@ -177,7 +177,7 @@ int pa_socket_tcp_low_delay(int fd) {
 #endif
 
 #if defined(IPTOS_LOWDELAY) && defined(IP_TOS) && (defined(SOL_IP) || \
-	defined(IPPROTO_IP))
+        defined(IPPROTO_IP))
     tos = IPTOS_LOWDELAY;
 #ifdef SOL_IP
     if (setsockopt(fd, SOL_IP, IP_TOS, (void*)&tos, sizeof(tos)) < 0)
diff --git a/src/utils/padsp.c b/src/utils/padsp.c
index 9a2bad4..041115e 100644
--- a/src/utils/padsp.c
+++ b/src/utils/padsp.c
@@ -259,9 +259,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 +421,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 +1395,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;
@@ -1446,7 +1446,7 @@ int open(const char *filename, int flags, ...) {
     va_start(args, flags);
     if (flags & O_CREAT) {
       if (sizeof(mode_t) < sizeof(int))
-	mode = va_arg(args, int);
+        mode = va_arg(args, int);
       else
         mode = va_arg(args, mode_t);
     }
@@ -2023,9 +2023,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: {
@@ -2279,8 +2279,8 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno)
 
         case SNDCTL_DSP_SETDUPLEX:
             debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_SETDUPLEX\n");
-	    /* this is a no-op */
-	    break;
+            /* this is a no-op */
+            break;
 
         default:
             debug(DEBUG_LEVEL_NORMAL, __FILE__": unknown ioctl 0x%08lx\n", request);

commit be4a8828360b3607414c3ebfd836494e6490267d
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Jun 13 22:08:14 2007 +0000

    A lot of more work to get the lock-free stuff in place
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1474 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/Makefile.am b/src/Makefile.am
index eab465c..0a5d529 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -283,14 +283,14 @@ 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 pulsecore/thread-posix.c pulsecore/thread.h pulsecore/asyncq.c pulsecore/asyncq.h pulsecore/core-util.c pulsecore/core-util.h pulse/xmalloc.c pulse/xmalloc.h pulsecore/log.h pulsecore/log.c pulsecore/core-error.h pulsecore/core-error.c pulsecore/once-posix.c pulsecore/once.h pulsecore/mutex-posix.c pulsecore/mutex.h pulse/utf8.c pulse/utf8.h pulse/util.h pulse/util.c
+asyncq_test_SOURCES = tests/asyncq-test.c
 asyncq_test_CFLAGS = $(AM_CFLAGS)
-asyncq_test_LDADD = $(AM_LDADD) #libpulsecore.la
+asyncq_test_LDADD = $(AM_LDADD) libpulsecore.la
 asyncq_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS)
 
-asyncmsgq_test_SOURCES = tests/asyncmsgq-test.c pulsecore/thread-posix.c pulsecore/thread.h pulsecore/asyncq.c pulsecore/asyncq.h pulsecore/asyncmsgq.c pulsecore/asyncmsgq.h pulsecore/core-util.c pulsecore/core-util.h pulse/xmalloc.c pulse/xmalloc.h pulsecore/log.h pulsecore/log.c pulsecore/core-error.h pulsecore/core-error.c pulsecore/once-posix.c pulsecore/once.h pulsecore/mutex-posix.c pulsecore/mutex.h pulse/utf8.c pulse/utf8.h pulse/util.h pulse/util.c pulsecore/semaphore.h pulsecore/semaphore-posix.c pulsecore/flist.h pulsecore/flist.c
+asyncmsgq_test_SOURCES = tests/asyncmsgq-test.c
 asyncmsgq_test_CFLAGS = $(AM_CFLAGS)
-asyncmsgq_test_LDADD = $(AM_LDADD) #libpulsecore.la
+asyncmsgq_test_LDADD = $(AM_LDADD) libpulsecore.la
 asyncmsgq_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS)
 
 mcalign_test_SOURCES = tests/mcalign-test.c
@@ -653,7 +653,10 @@ libpulsecore_la_SOURCES += \
 		pulsecore/hook-list.c pulsecore/hook-list.h \
 		pulsecore/shm.c pulsecore/shm.h \
 		pulsecore/flist.c pulsecore/flist.h \
-		pulsecore/anotify.c pulsecore/anotify.h \
+		pulsecore/asyncmsgq.c pulsecore/asyncmsgqq.h \
+		pulsecore/asyncq.c pulsecore/asyncq.h \
+		pulsecore/object.c pulsecore/object.h \
+		pulsecore/msgobject.c pulsecore/msgobject.h \
 		$(PA_THREAD_OBJS)
 
 if OS_IS_WIN32
@@ -718,9 +721,10 @@ modlibexec_LTLIBRARIES = \
 		libauthkey-prop.la \
 		libstrlist.la \
 		libprotocol-simple.la \
-		libprotocol-esound.la \
-		libprotocol-native.la \
-		libprotocol-http.la
+		libprotocol-http.la 
+
+#		libprotocol-esound.la
+#		libprotocol-native.la
 
 # We need to emulate sendmsg/recvmsg to support this on Win32
 if !OS_IS_WIN32
@@ -870,6 +874,11 @@ modlibexec_LTLIBRARIES += \
 		module-cli-protocol-tcp.la \
 		module-simple-protocol-tcp.la \
 		module-null-sink.la
+		module-detect.la \
+		module-volume-restore.la \
+		module-rescue-streams.la \
+		module-http-protocol-tcp.la 
+
 #		module-esound-protocol-tcp.la \
 #		module-native-protocol-tcp.la \
 #		module-native-protocol-fd.la \
@@ -877,11 +886,7 @@ modlibexec_LTLIBRARIES += \
 #		module-combine.la \
 #		module-tunnel-sink.la \
 #		module-tunnel-source.la \
-#		module-esound-sink.la \
-#		module-http-protocol-tcp.la \
-#		module-detect.la \
-#		module-volume-restore.la \
-#		module-rescue-streams.la
+#		module-esound-sink.la
 
 # See comment at librtp.la above
 #if !OS_IS_WIN32
@@ -894,9 +899,9 @@ if HAVE_AF_UNIX
 modlibexec_LTLIBRARIES += \
 		module-cli-protocol-unix.la \
 		module-simple-protocol-unix.la
+		module-http-protocol-unix.la
 #		module-esound-protocol-unix.la \
-#		module-native-protocol-unix.la \
-#		module-http-protocol-unix.la
+#		module-native-protocol-unix.la
 endif
 
 if HAVE_MKFIFO
@@ -1079,44 +1084,44 @@ module_http_protocol_unix_la_LIBADD = $(AM_LIBADD) libpulsecore.la libprotocol-h
 
 # Native protocol
 
-module_native_protocol_tcp_la_SOURCES = modules/module-protocol-stub.c
-module_native_protocol_tcp_la_CFLAGS = -DUSE_TCP_SOCKETS -DUSE_PROTOCOL_NATIVE $(AM_CFLAGS)
-module_native_protocol_tcp_la_LDFLAGS = -module -avoid-version
-module_native_protocol_tcp_la_LIBADD = $(AM_LIBADD) libpulsecore.la libprotocol-native.la libsocket-server.la
+#module_native_protocol_tcp_la_SOURCES = modules/module-protocol-stub.c
+#module_native_protocol_tcp_la_CFLAGS = -DUSE_TCP_SOCKETS -DUSE_PROTOCOL_NATIVE $(AM_CFLAGS)
+#module_native_protocol_tcp_la_LDFLAGS = -module -avoid-version
+#module_native_protocol_tcp_la_LIBADD = $(AM_LIBADD) libpulsecore.la libprotocol-native.la libsocket-server.la
 
-module_native_protocol_unix_la_SOURCES = modules/module-protocol-stub.c
-module_native_protocol_unix_la_CFLAGS = -DUSE_UNIX_SOCKETS -DUSE_PROTOCOL_NATIVE $(AM_CFLAGS)
-module_native_protocol_unix_la_LDFLAGS = -module -avoid-version
-module_native_protocol_unix_la_LIBADD = $(AM_LIBADD) libpulsecore.la libprotocol-native.la libsocket-server.la libsocket-util.la
+#module_native_protocol_unix_la_SOURCES = modules/module-protocol-stub.c
+#module_native_protocol_unix_la_CFLAGS = -DUSE_UNIX_SOCKETS -DUSE_PROTOCOL_NATIVE $(AM_CFLAGS)
+#module_native_protocol_unix_la_LDFLAGS = -module -avoid-version
+#module_native_protocol_unix_la_LIBADD = $(AM_LIBADD) libpulsecore.la libprotocol-native.la libsocket-server.la libsocket-util.la
 
-module_native_protocol_fd_la_SOURCES = modules/module-native-protocol-fd.c
-module_native_protocol_fd_la_CFLAGS = $(AM_CFLAGS)
-module_native_protocol_fd_la_LDFLAGS = -module -avoid-version
-module_native_protocol_fd_la_LIBADD = $(AM_LIBADD) libpulsecore.la libprotocol-native.la libsocket-server.la libsocket-util.la libiochannel.la
+#module_native_protocol_fd_la_SOURCES = modules/module-native-protocol-fd.c
+#module_native_protocol_fd_la_CFLAGS = $(AM_CFLAGS)
+#module_native_protocol_fd_la_LDFLAGS = -module -avoid-version
+#module_native_protocol_fd_la_LIBADD = $(AM_LIBADD) libpulsecore.la libprotocol-native.la libsocket-server.la libsocket-util.la libiochannel.la
 
 # EsounD protocol
 
-module_esound_protocol_tcp_la_SOURCES = modules/module-protocol-stub.c
-module_esound_protocol_tcp_la_CFLAGS = -DUSE_TCP_SOCKETS -DUSE_PROTOCOL_ESOUND $(AM_CFLAGS)
-module_esound_protocol_tcp_la_LDFLAGS = -module -avoid-version
-module_esound_protocol_tcp_la_LIBADD = $(AM_LIBADD) libpulsecore.la libprotocol-esound.la libsocket-server.la
+#module_esound_protocol_tcp_la_SOURCES = modules/module-protocol-stub.c
+#module_esound_protocol_tcp_la_CFLAGS = -DUSE_TCP_SOCKETS -DUSE_PROTOCOL_ESOUND $(AM_CFLAGS)
+#module_esound_protocol_tcp_la_LDFLAGS = -module -avoid-version
+#module_esound_protocol_tcp_la_LIBADD = $(AM_LIBADD) libpulsecore.la libprotocol-esound.la libsocket-server.la
 
-module_esound_protocol_unix_la_SOURCES = modules/module-protocol-stub.c
-module_esound_protocol_unix_la_CFLAGS = -DUSE_UNIX_SOCKETS -DUSE_PROTOCOL_ESOUND $(AM_CFLAGS)
-module_esound_protocol_unix_la_LDFLAGS = -module -avoid-version
-module_esound_protocol_unix_la_LIBADD = $(AM_LIBADD) libpulsecore.la libprotocol-esound.la libsocket-server.la libsocket-util.la
+#module_esound_protocol_unix_la_SOURCES = modules/module-protocol-stub.c
+#module_esound_protocol_unix_la_CFLAGS = -DUSE_UNIX_SOCKETS -DUSE_PROTOCOL_ESOUND $(AM_CFLAGS)
+#module_esound_protocol_unix_la_LDFLAGS = -module -avoid-version
+#module_esound_protocol_unix_la_LIBADD = $(AM_LIBADD) libpulsecore.la libprotocol-esound.la libsocket-server.la libsocket-util.la
 
-module_esound_compat_spawnfd_la_SOURCES = modules/module-esound-compat-spawnfd.c
-module_esound_compat_spawnfd_la_LDFLAGS = -module -avoid-version
-module_esound_compat_spawnfd_la_LIBADD = $(AM_LIBADD) libpulsecore.la
+#module_esound_compat_spawnfd_la_SOURCES = modules/module-esound-compat-spawnfd.c
+#module_esound_compat_spawnfd_la_LDFLAGS = -module -avoid-version
+#module_esound_compat_spawnfd_la_LIBADD = $(AM_LIBADD) libpulsecore.la
 
-module_esound_compat_spawnpid_la_SOURCES = modules/module-esound-compat-spawnpid.c
-module_esound_compat_spawnpid_la_LDFLAGS = -module -avoid-version
-module_esound_compat_spawnpid_la_LIBADD = $(AM_LIBADD) libpulsecore.la
+#module_esound_compat_spawnpid_la_SOURCES = modules/module-esound-compat-spawnpid.c
+#module_esound_compat_spawnpid_la_LDFLAGS = -module -avoid-version
+#module_esound_compat_spawnpid_la_LIBADD = $(AM_LIBADD) libpulsecore.la
 
-module_esound_sink_la_SOURCES = modules/module-esound-sink.c
-module_esound_sink_la_LDFLAGS = -module -avoid-version
-module_esound_sink_la_LIBADD = $(AM_LIBADD) libpulsecore.la libiochannel.la libsocket-client.la libauthkey.la
+#module_esound_sink_la_SOURCES = modules/module-esound-sink.c
+#module_esound_sink_la_LDFLAGS = -module -avoid-version
+#module_esound_sink_la_LIBADD = $(AM_LIBADD) libpulsecore.la libiochannel.la libsocket-client.la libauthkey.la
 
 # Pipes
 
@@ -1140,22 +1145,22 @@ module_null_sink_la_LIBADD = $(AM_LIBADD) libpulsecore.la
 
 # Couplings
 
-module_combine_la_SOURCES = modules/module-combine.c
-module_combine_la_LDFLAGS = -module -avoid-version
-module_combine_la_LIBADD = $(AM_LIBADD) libpulsecore.la
+#module_combine_la_SOURCES = modules/module-combine.c
+#module_combine_la_LDFLAGS = -module -avoid-version
+#module_combine_la_LIBADD = $(AM_LIBADD) 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
 
@@ -1171,34 +1176,34 @@ module_x11_publish_la_LIBADD = $(AM_LIBADD) $(X_PRE_LIBS) -lX11 $(X_LIBS) $(X_EX
 
 # OSS
 
-liboss_util_la_SOURCES = modules/oss-util.c modules/oss-util.h
-liboss_util_la_LDFLAGS = -avoid-version
-liboss_util_la_LIBADD = libpulsecore.la
+#liboss_util_la_SOURCES = modules/oss-util.c modules/oss-util.h
+#liboss_util_la_LDFLAGS = -avoid-version
+#liboss_util_la_LIBADD = libpulsecore.la
 
-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
+#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
 
-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
+#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
-libalsa_util_la_LDFLAGS = -avoid-version
-libalsa_util_la_LIBADD = $(AM_LIBADD) $(ASOUNDLIB_LIBS) libpulsecore.la
-libalsa_util_la_CFLAGS = $(AM_CFLAGS) $(ASOUNDLIB_CFLAGS)
+#libalsa_util_la_SOURCES = modules/alsa-util.c modules/alsa-util.h
+#libalsa_util_la_LDFLAGS = -avoid-version
+#libalsa_util_la_LIBADD = $(AM_LIBADD) $(ASOUNDLIB_LIBS) libpulsecore.la
+#libalsa_util_la_CFLAGS = $(AM_CFLAGS) $(ASOUNDLIB_CFLAGS)
 
-module_alsa_sink_la_SOURCES = modules/module-alsa-sink.c
-module_alsa_sink_la_LDFLAGS = -module -avoid-version
-module_alsa_sink_la_LIBADD = $(AM_LIBADD) $(ASOUNDLIB_LIBS) libalsa-util.la libpulsecore.la
-module_alsa_sink_la_CFLAGS = $(AM_CFLAGS) $(ASOUNDLIB_CFLAGS)
+#module_alsa_sink_la_SOURCES = modules/module-alsa-sink.c
+#module_alsa_sink_la_LDFLAGS = -module -avoid-version
+#module_alsa_sink_la_LIBADD = $(AM_LIBADD) $(ASOUNDLIB_LIBS) libalsa-util.la libpulsecore.la
+#module_alsa_sink_la_CFLAGS = $(AM_CFLAGS) $(ASOUNDLIB_CFLAGS)
 
-module_alsa_source_la_SOURCES = modules/module-alsa-source.c
-module_alsa_source_la_LDFLAGS = -module -avoid-version
-module_alsa_source_la_LIBADD = $(AM_LIBADD) $(ASOUNDLIB_LIBS) libalsa-util.la libpulsecore.la
-module_alsa_source_la_CFLAGS = $(AM_CFLAGS) $(ASOUNDLIB_CFLAGS)
+#module_alsa_source_la_SOURCES = modules/module-alsa-source.c
+#module_alsa_source_la_LDFLAGS = -module -avoid-version
+#module_alsa_source_la_LIBADD = $(AM_LIBADD) $(ASOUNDLIB_LIBS) libalsa-util.la libpulsecore.la
+#module_alsa_source_la_CFLAGS = $(AM_CFLAGS) $(ASOUNDLIB_CFLAGS)
 
 # Solaris
 
@@ -1265,15 +1270,15 @@ module_rtp_recv_la_CFLAGS = $(AM_CFLAGS)
 
 # JACK
 
-module_jack_sink_la_SOURCES = modules/module-jack-sink.c
-module_jack_sink_la_LDFLAGS = -module -avoid-version
-module_jack_sink_la_LIBADD = $(AM_LIBADD) libpulsecore.la $(JACK_LIBS)
-module_jack_sink_la_CFLAGS = $(AM_LIBADD) $(JACK_CFLAGS)
+#module_jack_sink_la_SOURCES = modules/module-jack-sink.c
+#module_jack_sink_la_LDFLAGS = -module -avoid-version
+#module_jack_sink_la_LIBADD = $(AM_LIBADD) libpulsecore.la $(JACK_LIBS)
+#module_jack_sink_la_CFLAGS = $(AM_LIBADD) $(JACK_CFLAGS)
 
-module_jack_source_la_SOURCES = modules/module-jack-source.c
-module_jack_source_la_LDFLAGS = -module -avoid-version
-module_jack_source_la_LIBADD = $(AM_LIBADD) libpulsecore.la $(JACK_LIBS)
-module_jack_source_la_CFLAGS = $(AM_LIBADD) $(JACK_CFLAGS)
+#module_jack_source_la_SOURCES = modules/module-jack-source.c
+#module_jack_source_la_LDFLAGS = -module -avoid-version
+#module_jack_source_la_LIBADD = $(AM_LIBADD) libpulsecore.la $(JACK_LIBS)
+#module_jack_source_la_CFLAGS = $(AM_LIBADD) $(JACK_CFLAGS)
 
 # HAL
 libdbus_util_la_SOURCES = modules/dbus-util.c modules/dbus-util.h
diff --git a/src/daemon/main.c b/src/daemon/main.c
index 2424efa..a1926fe 100644
--- a/src/daemon/main.c
+++ b/src/daemon/main.c
@@ -656,7 +656,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();
diff --git a/src/modules/module-lirc.c b/src/modules/module-lirc.c
index c8adbc8..452fa1f 100644
--- a/src/modules/module-lirc.c
+++ b/src/modules/module-lirc.c
@@ -121,7 +121,7 @@ static void io_callback(pa_mainloop_api *io, PA_GCC_UNUSED pa_io_event *e, PA_GC
                     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 +134,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 +145,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:
diff --git a/src/modules/module-mmkbd-evdev.c b/src/modules/module-mmkbd-evdev.c
index b7433ac..919b399 100644
--- a/src/modules/module-mmkbd-evdev.c
+++ b/src/modules/module-mmkbd-evdev.c
@@ -114,7 +114,7 @@ static void io_callback(pa_mainloop_api *io, PA_GCC_UNUSED pa_io_event *e, PA_GC
                     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:
diff --git a/src/modules/module-null-sink.c b/src/modules/module-null-sink.c
index ce3b29b..afe130d 100644
--- a/src/modules/module-null-sink.c
+++ b/src/modules/module-null-sink.c
@@ -33,17 +33,19 @@
 #include <fcntl.h>
 #include <unistd.h>
 #include <limits.h>
+#include <sys/poll.h>
 
 #include <pulse/timeval.h>
 #include <pulse/xmalloc.h>
 
 #include <pulsecore/macro.h>
-#include <pulsecore/iochannel.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 "module-null-sink-symdef.h"
 
@@ -65,7 +67,9 @@ struct userdata {
     pa_module *module;
     pa_sink *sink;
     pa_thread *thread;
+    pa_asyncmsgq *asyncmsgq;
     size_t block_size;
+    
     struct timeval timestamp;
 };
 
@@ -79,85 +83,74 @@ static const char* const valid_modargs[] = {
     NULL
 };
 
+static int sink_process_msg(pa_msgobject *o, int code, void *data, pa_memchunk *chunk) {
+    struct userdata *u = PA_SINK(o)->userdata;
+
+    switch (code) {
+        case PA_SINK_MESSAGE_SET_STATE:
+
+            if (PA_PTR_TO_UINT(data) == PA_SINK_RUNNING)
+                pa_gettimeofday(&u->timestamp);
+            
+            break;
+            
+        case PA_SINK_MESSAGE_GET_LATENCY: {
+            struct timeval now;
+    
+            pa_gettimeofday(&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, chunk);
+}
+
 static void thread_func(void *userdata) {
     struct userdata *u = userdata;
-    int quit = 0;
     struct pollfd pollfd;
-    int running = 1;
 
     pa_assert(u);
 
     pa_log_debug("Thread starting up");
 
+    pa_gettimeofday(&u->timestamp);
+
     memset(&pollfd, 0, sizeof(pollfd));
-    pollfd.fd = pa_asyncmsgq_get_fd(u->sink->asyncmsgq, PA_ASYNCQ_POP);
+    pollfd.fd = pa_asyncmsgq_get_fd(u->asyncmsgq);
     pollfd.events = POLLIN;
 
-    pa_gettimeofday(u->timestamp);
-
     for (;;) {
+        pa_msgobject *object;
         int code;
-        void *data, *object;
+        void *data;
+        pa_memchunk chunk;
         int r, timeout;
         struct timeval now;
 
         /* Check whether there is a message for us to process */
-        if (pa_asyncmsgq_get(u->sink->asyncmsgq, &object, &code, &data) == 0) {
-
-
-            /* Now process these messages our own way */
-            if (!object) {
-
-                switch (code) {
-                    case PA_MESSAGE_SHUTDOWN:
-                        goto finish;
-
-                    default:
-                        pa_sink_process_msg(u->sink->asyncmsgq, object, code, data);
-
-                }
+        if (pa_asyncmsgq_get(u->asyncmsgq, &object, &code, &data, &chunk, 0) == 0) {
+            int ret;
 
-            } else if (object == u->sink) {
-
-                switch (code) {
-                    case PA_SINK_MESSAGE_STOP:
-                        pa_assert(running);
-                        running = 0;
-                        break;
-
-                    case PA_SINK_MESSAGE_START:
-                        pa_assert(!running);
-                        running = 1;
-
-                        pa_gettimeofday(u->timestamp);
-                        break;
-
-                    case PA_SINK_MESSAGE_GET_LATENCY:
-
-                        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;
-
-                        /* ... */
-
-                    default:
-                        pa_sink_process_msg(u->sink->asyncmsgq, object, code, data);
-                }
+            if (!object && code == PA_MESSAGE_SHUTDOWN) {
+                pa_asyncmsgq_done(u->asyncmsgq, 0);
+                goto finish;
             }
-
-            pa_asyncmsgq_done(u->sink->asyncmsgq);
+                    
+            ret = pa_asyncmsgq_dispatch(object, code, data, &chunk);
+            pa_asyncmsgq_done(u->asyncmsgq, ret);
             continue;
         }
 
         /* Render some data and drop it immediately */
-
-        if (running) {
+        if (u->sink->thread_info.state == PA_SINK_RUNNING) {
             pa_gettimeofday(&now);
 
-            if (pa_timeval_cmp(u->timestamp, &now) <= 0) {
-                pa_memchunk chunk;
+            if (pa_timeval_cmp(&u->timestamp, &now) <= 0) {
                 size_t l;
 
                 if (pa_sink_render(u->sink, u->block_size, &chunk) >= 0) {
@@ -179,11 +172,11 @@ static void thread_func(void *userdata) {
 
         /* Hmm, nothing to do. Let's sleep */
 
-        if (pa_asyncmsgq_before_poll(u->sink->asyncmsgq) < 0)
+        if (pa_asyncmsgq_before_poll(u->asyncmsgq) < 0)
             continue;
 
         r = poll(&pollfd, 1, timeout);
-        pa_asyncmsgq_after_poll(u->sink->asyncmsgq);
+        pa_asyncmsgq_after_poll(u->asyncmsgq);
 
         if (r < 0) {
             if (errno == EINTR)
@@ -199,8 +192,8 @@ static void thread_func(void *userdata) {
 fail:
     /* We have to continue processing messages until we receive the
      * SHUTDOWN message */
-    pa_asyncmsgq_post(u->core->asyncmsgq, u->core, PA_CORE_MESSAGE_UNLOAD_MODULE, pa_module_ref(u->module), NULL, pa_module_unref);
-    pa_asyncmsgq_wait_for(PA_MESSAGE_SHUTDOWN);
+    pa_asyncmsgq_post(u->core->asyncmsgq, PA_MSGOBJECT(u->core), PA_CORE_MESSAGE_UNLOAD_MODULE, u->module, NULL, NULL);
+    pa_asyncmsgq_wait_for(u->asyncmsgq, PA_MESSAGE_SHUTDOWN);
 
 finish:
     pa_log_debug("Thread shutting down");
@@ -231,20 +224,24 @@ int pa__init(pa_core *c, pa_module*m) {
     u->module = m;
     m->userdata = u;
 
+    pa_assert_se(u->asyncmsgq = pa_asyncmsgq_new(0));
+    
     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.");
         goto fail;
     }
 
+    u->sink->parent.process_msg = sink_process_msg;
     u->sink->userdata = u;
-    pa_sink_set_owner(u->sink, m);
+
+    pa_sink_set_module(u->sink, m);
+    pa_sink_set_asyncmsgq(u->sink, u->asyncmsgq);
     pa_sink_set_description(u->sink, pa_modargs_get_value(ma, "description", "NULL sink"));
 
     u->block_size = pa_bytes_per_second(&ss) / 20; /* 50 ms */
-
     if (u->block_size <= 0)
         u->block_size = pa_frame_size(&ss);
-
+    
     if (!(u->thread = pa_thread_new(thread_func, u))) {
         pa_log("Failed to create thread.");
         goto fail;
@@ -272,14 +269,19 @@ void pa__done(pa_core *c, pa_module*m) {
     if (!(u = m->userdata))
         return;
 
-    pa_sink_disconnect(u->sink);
+    if (u->sink)
+        pa_sink_disconnect(u->sink);
 
     if (u->thread) {
-        pa_asyncmsgq_send(u->sink->asyncmsgq, PA_SINK_MESSAGE_SHUTDOWN, NULL);
+        pa_asyncmsgq_send(u->asyncmsgq, NULL, PA_MESSAGE_SHUTDOWN, NULL, NULL);
         pa_thread_free(u->thread);
     }
 
-    pa_sink_unref(u->sink);
+    if (u->asyncmsgq)
+        pa_asyncmsgq_free(u->asyncmsgq);
+
+    if (u->sink)
+        pa_sink_unref(u->sink);
 
     pa_xfree(u);
 }
diff --git a/src/modules/module-pipe-sink.c b/src/modules/module-pipe-sink.c
index e4735f6..da9124a 100644
--- a/src/modules/module-pipe-sink.c
+++ b/src/modules/module-pipe-sink.c
@@ -34,6 +34,8 @@
 #include <fcntl.h>
 #include <unistd.h>
 #include <limits.h>
+#include <sys/ioctl.h>
+#include <sys/poll.h>
 
 #include <pulse/xmalloc.h>
 
@@ -44,6 +46,7 @@
 #include <pulsecore/core-util.h>
 #include <pulsecore/modargs.h>
 #include <pulsecore/log.h>
+#include <pulsecore/thread.h>
 
 #include "module-pipe-sink-symdef.h"
 
@@ -65,9 +68,12 @@ struct userdata {
     pa_core *core;
     pa_module *module;
     pa_sink *sink;
+    pa_thread *thread;
+    pa_asyncmsgq *asyncmsgq;
     char *filename;
     int fd;
-    pa_thread *thread;
+
+    pa_memchunk memchunk;
 };
 
 static const char* const valid_modargs[] = {
@@ -80,109 +86,99 @@ static const char* const valid_modargs[] = {
     NULL
 };
 
-enum {
-    POLLFD_ASYNCQ,
-    POLLFD_FIFO,
-    POLLFD_MAX,
-};
+static int sink_process_msg(pa_msgobject *o, int code, void *data, pa_memchunk *chunk) {
+    struct userdata *u = PA_SINK(o)->userdata;
+
+    switch (code) {
+            
+        case PA_SINK_MESSAGE_GET_LATENCY: {
+            size_t n = 0;
+            int l;
+            
+            if (ioctl(u->fd, TIOCINQ, &l) >= 0 && l > 0)
+                n = (size_t) l;
+            
+            n += u->memchunk.length;
+            
+            *((pa_usec_t*) data) = pa_bytes_to_usec(n, &u->sink->sample_spec);
+            break;
+        }
+    }
+    
+    return pa_sink_process_msg(o, code, data, chunk);
+}
 
 static void thread_func(void *userdata) {
+    enum {
+        POLLFD_ASYNCQ,
+        POLLFD_FIFO,
+        POLLFD_MAX,
+    };
+    
     struct userdata *u = userdata;
-    int quit = 0;
     struct pollfd pollfd[POLLFD_MAX];
-    int running = 1, underrun = 0;
-    pa_memchunk memchunk;
+    int underrun = 0;
+    int write_type = 0;
 
     pa_assert(u);
 
     pa_log_debug("Thread starting up");
 
+    pa_memchunk_reset(&u->memchunk);
+    
     memset(&pollfd, 0, sizeof(pollfd));
-    pollfd[POLLFD_ASYNCQ].fd = pa_asyncmsgq_get_fd(u->sink->asyncmsgq, PA_ASYNCQ_POP);
+    
+    pollfd[POLLFD_ASYNCQ].fd = pa_asyncmsgq_get_fd(u->asyncmsgq);
     pollfd[POLLFD_ASYNCQ].events = POLLIN;
-
     pollfd[POLLFD_FIFO].fd = u->fd;
 
-    memset(&memchunk, 0, sizeof(memchunk));
-
     for (;;) {
+        pa_msgobject *object;
         int code;
-        void *object, *data;
+        void *data;
+        pa_memchunk chunk;
         int r;
-        struct timeval now;
 
         /* Check whether there is a message for us to process */
-        if (pa_asyncmsgq_get(u->sink->asyncmsgq, &object, &code, &data) == 0) {
-
-
-            /* Now process these messages our own way */
-            if (!object) {
-                switch (code) {
-                    case PA_SINK_MESSAGE_SHUTDOWN:
-                        goto finish;
-
-                    default:
-                        pa_sink_process_msg(u->sink->asyncmsgq, object, code, data);
-                }
+        if (pa_asyncmsgq_get(u->asyncmsgq, &object, &code, &data, &chunk, 0) == 0) {
+            int ret;
 
-            } else if (object == u->sink) {
-
-                case PA_SINK_MESSAGE_STOP:
-                    pa_assert(running);
-                    running = 0;
-                    break;
-
-                case PA_SINK_MESSAGE_START:
-                    pa_assert(!running);
-                    running = 1;
-                    break;
-
-                case PA_SINK_MESSAGE_GET_LATENCY: {
-                    size_t n = 0;
-                    int l;
-
-                    if (ioctl(u->fd, TIOCINQ, &l) >= 0 && l > 0)
-                        n = (size_t) l;
-
-                    n += memchunk.length;
-
-                    *((pa_usec_t*) data) pa_bytes_to_usec(n, &u->sink->sample_spec);
-                    break;
-                }
-
-                /* ... */
-
-                default:
-                    pa_sink_process_msg(u->sink->asyncmsgq, object, code, data);
+            if (!object && code == PA_MESSAGE_SHUTDOWN) {
+                pa_asyncmsgq_done(u->asyncmsgq, 0);
+                goto finish;
             }
 
-            pa_asyncmsgq_done(u->sink->asyncmsgq);
+            ret = pa_asyncmsgq_dispatch(object, code, data, &chunk);
+            pa_asyncmsgq_done(u->asyncmsgq, ret);
             continue;
         }
 
         /* Render some data and write it to the fifo */
 
-        if (running && (pollfd[POLLFD_FIFO].revents || underrun)) {
+        if (u->sink->thread_info.state == PA_SINK_RUNNING && (pollfd[POLLFD_FIFO].revents || underrun)) {
 
-            if (chunk.length <= 0)
-                pa_sink_render(u->fd, PIPE_BUF, &chunk);
+            if (u->memchunk.length <= 0)
+                pa_sink_render(u->sink, PIPE_BUF, &u->memchunk);
 
-            underrun = chunk.length <= 0;
+            underrun = u->memchunk.length <= 0;
 
             if (!underrun) {
                 ssize_t l;
+                void *p;
 
                 p = pa_memblock_acquire(u->memchunk.memblock);
-                l = pa_write(u->fd, (uint8_t*) p + u->memchunk.index, u->memchunk.length);
-                pa_memblock_release(p);
+                l = pa_write(u->fd, (uint8_t*) p + u->memchunk.index, u->memchunk.length, &write_type);
+                pa_memblock_release(u->memchunk.memblock);
 
                 if (l < 0) {
 
-                    if (errno != EINTR && errno != EAGAIN) {
+                    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;
@@ -190,24 +186,24 @@ static void thread_func(void *userdata) {
 
                     if (u->memchunk.length <= 0) {
                         pa_memblock_unref(u->memchunk.memblock);
-                        u->memchunk.memblock = NULL;
+                        pa_memchunk_reset(&u->memchunk);
                     }
-                }
 
-                pollfd[POLLFD_FIFO].revents = 0;
-                continue;
+                    pollfd[POLLFD_FIFO].revents = 0;
+                    continue;
+                }
             }
         }
 
-        pollfd[POLLFD_FIFO].events = running && !underrun ? POLLOUT : 0;
+        pollfd[POLLFD_FIFO].events = (u->sink->thread_info.state == PA_SINK_RUNNING && !underrun) ? POLLOUT : 0;
 
         /* Hmm, nothing to do. Let's sleep */
 
-        if (pa_asyncmsgq_before_poll(u->sink->asyncmsgq) < 0)
+        if (pa_asyncmsgq_before_poll(u->asyncmsgq) < 0)
             continue;
 
-        r = poll(&pollfd, 1, 0);
-        pa_asyncmsgq_after_poll(u->sink->asyncmsgq);
+        r = poll(pollfd, POLLFD_MAX, -1);
+        pa_asyncmsgq_after_poll(u->asyncmsgq);
 
         if (r < 0) {
             if (errno == EINTR)
@@ -217,19 +213,19 @@ static void thread_func(void *userdata) {
             goto fail;
         }
 
-        if (pollfd[POLLFD_FIFO].revents & ~POLLIN) {
+        if (pollfd[POLLFD_FIFO].revents & ~POLLOUT) {
             pa_log("FIFO shutdown.");
             goto fail;
         }
 
-        pa_assert(pollfd[POLLFD_ASYNCQ].revents & ~POLLIN == 0);
+        pa_assert((pollfd[POLLFD_ASYNCQ].revents & ~POLLIN) == 0);
     }
 
 fail:
     /* We have to continue processing messages until we receive the
      * SHUTDOWN message */
-    pa_asyncmsgq_post(u->core->asyncmsgq, u->core, PA_CORE_MESSAGE_UNLOAD_MODULE, pa_module_ref(u->module), pa_module_unref);
-    pa_asyncmsgq_wait_for(PA_SINK_MESSAGE_SHUTDOWN);
+    pa_asyncmsgq_post(u->core->asyncmsgq, PA_MSGOBJECT(u->core), PA_CORE_MESSAGE_UNLOAD_MODULE, u->module, NULL, NULL);
+    pa_asyncmsgq_wait_for(u->asyncmsgq, PA_MESSAGE_SHUTDOWN);
 
 finish:
     pa_log_debug("Thread shutting down");
@@ -253,23 +249,22 @@ int pa__init(pa_core *c, pa_module*m) {
 
     ss = c->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;
     }
 
     u = pa_xnew0(struct userdata, 1);
     u->core = c;
     u->module = m;
-    u->filename = pa_xstrdup(pa_modargs_get_value(ma, "file", DEFAULT_FIFO_NAME));
-    u->fd = fd;
-    u->memchunk.memblock = NULL;
-    u->memchunk.length = 0;
     m->userdata = u;
 
-    mkfifo(u->filename, 0666);
+    pa_assert_se(u->asyncmsgq = pa_asyncmsgq_new(0));
+    
+    u->filename = pa_xstrdup(pa_modargs_get_value(ma, "file", DEFAULT_FILE_NAME));
 
-    if ((u->fd = open(u->filename, 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;
     }
 
@@ -277,12 +272,12 @@ int pa__init(pa_core *c, pa_module*m) {
     pa_make_nonblock_fd(u->fd);
 
     if (fstat(u->fd, &st) < 0) {
-        pa_log("fstat('%s'): %s", p, pa_cstrerror(errno));
+        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;
     }
 
@@ -291,9 +286,12 @@ int pa__init(pa_core *c, pa_module*m) {
         goto fail;
     }
 
+    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));
+    
+    pa_sink_set_module(u->sink, m);
+    pa_sink_set_asyncmsgq(u->sink, u->asyncmsgq);
+    pa_sink_set_description(u->sink, t = pa_sprintf_malloc("Unix FIFO sink '%s'", u->filename));
     pa_xfree(t);
 
     if (!(u->thread = pa_thread_new(thread_func, u))) {
@@ -316,20 +314,26 @@ fail:
 
 void pa__done(pa_core *c, pa_module*m) {
     struct userdata *u;
+    
     pa_assert(c);
     pa_assert(m);
 
     if (!(u = m->userdata))
         return;
 
-    pa_sink_disconnect(u->sink);
+    if (u->sink)
+        pa_sink_disconnect(u->sink);
 
     if (u->thread) {
-        pa_asyncmsgq_send(u->sink->asyncmsgq, PA_SINK_MESSAGE_SHUTDOWN, NULL);
+        pa_asyncmsgq_send(u->asyncmsgq, NULL, PA_MESSAGE_SHUTDOWN, NULL, NULL);
         pa_thread_free(u->thread);
     }
 
-    pa_sink_unref(u->sink);
+    if (u->asyncmsgq)
+        pa_asyncmsgq_free(u->asyncmsgq);
+    
+    if (u->sink)
+        pa_sink_unref(u->sink);
 
     if (u->memchunk.memblock)
        pa_memblock_unref(u->memchunk.memblock);
diff --git a/src/modules/module-pipe-source.c b/src/modules/module-pipe-source.c
index f275c5d..ac2bef7 100644
--- a/src/modules/module-pipe-source.c
+++ b/src/modules/module-pipe-source.c
@@ -179,7 +179,7 @@ int pa__init(pa_core *c, pa_module*m) {
         goto fail;
     }
     u->source->userdata = u;
-    pa_source_set_owner(u->source, m);
+    pa_source_set_module(u->source, m);
     pa_source_set_description(u->source, t = pa_sprintf_malloc("Unix FIFO source '%s'", p));
     pa_xfree(t);
 
diff --git a/src/pulsecore/asyncmsgq.c b/src/pulsecore/asyncmsgq.c
index de5b2f9..6becb62 100644
--- a/src/pulsecore/asyncmsgq.c
+++ b/src/pulsecore/asyncmsgq.c
@@ -48,6 +48,7 @@ struct asyncmsgq_item {
     pa_free_cb_t free_cb;
     pa_memchunk memchunk;
     pa_semaphore *semaphore;
+    int ret;
 };
 
 struct pa_asyncmsgq {
@@ -81,10 +82,10 @@ void pa_asyncmsgq_free(pa_asyncmsgq *a) {
             pa_msgobject_unref(i->object);
 
         if (i->memchunk.memblock)
-            pa_memblock_unref(i->object);
+            pa_memblock_unref(i->memchunk.memblock);
 
-        if (i->userdata_free_cb)
-            i->userdata_free_cb(i->userdata);
+        if (i->free_cb)
+            i->free_cb(i->userdata);
 
         if (pa_flist_push(PA_STATIC_FLIST_GET(asyncmsgq), i) < 0)
             pa_xfree(i);
@@ -103,7 +104,7 @@ void pa_asyncmsgq_post(pa_asyncmsgq *a, pa_msgobject *object, int code, const vo
         i = pa_xnew(struct asyncmsgq_item, 1);
 
     i->code = code;
-    i->object = pa_msgobject_ref(object);
+    i->object = object ? pa_msgobject_ref(object) : NULL;
     i->userdata = (void*) userdata;
     i->free_cb = free_cb;
     if (chunk) {
@@ -131,9 +132,9 @@ int pa_asyncmsgq_send(pa_asyncmsgq *a, pa_msgobject *object, int code, const voi
     i.ret = -1;
     if (chunk) {
         pa_assert(chunk->memblock);
-        i->memchunk = *chunk;
+        i.memchunk = *chunk;
     } else
-        pa_memchunk_reset(&i->memchunk);
+        pa_memchunk_reset(&i.memchunk);
     pa_assert_se(i.semaphore = pa_semaphore_new(0));
 
     /* Thus mutex makes the queue multiple-writer safe. This lock is only used on the writing side */
@@ -161,8 +162,10 @@ int pa_asyncmsgq_get(pa_asyncmsgq *a, pa_msgobject **object, int *code, void **u
     if (object)
         *object = a->current->object;
     if (chunk)
-        *chunk = a->chunk;
+        *chunk = a->current->memchunk;
 
+    pa_log_debug("q=%p object=%p code=%i data=%p", a, a->current->object, a->current->code, a->current->userdata);
+    
     return 0;
 }
 
@@ -196,11 +199,16 @@ int pa_asyncmsgq_wait_for(pa_asyncmsgq *a, int code) {
     pa_assert(a);
 
     do {
+        pa_msgobject *o;
+        void *data;
+        pa_memchunk chunk;
+        int ret;
 
-        if (pa_asyncmsgq_get(a, NULL, &c, NULL, 1) < 0)
+        if (pa_asyncmsgq_get(a, &o, &c, &data, &chunk, 1) < 0)
             return -1;
 
-        pa_asyncmsgq_done(a);
+        ret = pa_asyncmsgq_dispatch(o, c, data, &chunk);
+        pa_asyncmsgq_done(a, ret);
 
     } while (c != code);
 
@@ -226,10 +234,9 @@ void pa_asyncmsgq_after_poll(pa_asyncmsgq *a) {
 }
 
 int pa_asyncmsgq_dispatch(pa_msgobject *object, int code, void *userdata, pa_memchunk *memchunk) {
-    pa_assert(q);
 
     if (object)
-        return object->msg_process(object, code, userdata, memchunk);
+        return object->process_msg(object, code, userdata, memchunk);
 
     return 0;
 }
diff --git a/src/pulsecore/asyncq.c b/src/pulsecore/asyncq.c
index 54d36dc..da1f16f 100644
--- a/src/pulsecore/asyncq.c
+++ b/src/pulsecore/asyncq.c
@@ -52,8 +52,8 @@ struct pa_asyncq {
     unsigned size;
     unsigned read_idx;
     unsigned write_idx;
-    pa_atomic_int_t read_waiting;
-    pa_atomic_int_t write_waiting;
+    pa_atomic_t read_waiting, n_read;
+    pa_atomic_t write_waiting, n_written;
     int read_fds[2], write_fds[2];
 };
 
@@ -80,6 +80,8 @@ pa_asyncq *pa_asyncq_new(unsigned size) {
     l->size = size;
     pa_atomic_store(&l->read_waiting, 0);
     pa_atomic_store(&l->write_waiting, 0);
+    pa_atomic_store(&l->n_written, 0);
+    pa_atomic_store(&l->n_read, 0);
 
     if (pipe(l->read_fds) < 0) {
         pa_xfree(l);
@@ -131,10 +133,26 @@ int pa_asyncq_push(pa_asyncq*l, void *p, int wait) {
 
     if (!pa_atomic_ptr_cmpxchg(&cells[idx], NULL, p)) {
 
-        /* First try failed. Let's wait for changes. */
-
-        if (!wait)
+        if (!wait) {
+            /* Let's empty the FIFO from old notifications, before we return */
+            
+            while (pa_atomic_load(&l->n_read) > 0) {
+                ssize_t r;
+                int x[20];
+                
+                errno = 0;
+                if ((r = read(l->write_fds[0], x, sizeof(x))) <= 0 && errno != EINTR)
+                    return -1;
+                
+                if (r > 0)
+                    if (pa_atomic_sub(&l->n_read, r) <= r)
+                        break;
+            }
+            
             return -1;
+        }
+
+        /* First try failed. Let's wait for changes. */
 
         _Y;
 
@@ -142,6 +160,7 @@ int pa_asyncq_push(pa_asyncq*l, void *p, int wait) {
 
         for (;;) {
             char x[20];
+            ssize_t r;
 
             _Y;
 
@@ -150,10 +169,13 @@ int pa_asyncq_push(pa_asyncq*l, void *p, int wait) {
 
             _Y;
 
-            if (read(l->write_fds[0], x, sizeof(x)) < 0 && errno != EINTR) {
+            if ((r = read(l->write_fds[0], x, sizeof(x))) < 0 && errno != EINTR) {
                 pa_atomic_dec(&l->write_waiting);
                 return -1;
             }
+
+            if (r > 0)
+                pa_atomic_sub(&l->n_read, r);
         }
 
         _Y;
@@ -167,7 +189,8 @@ int pa_asyncq_push(pa_asyncq*l, void *p, int wait) {
     if (pa_atomic_load(&l->read_waiting)) {
         char x = 'x';
         _Y;
-        write(l->read_fds[1], &x, sizeof(x));
+        if (write(l->read_fds[1], &x, sizeof(x)) > 0)
+            pa_atomic_inc(&l->n_written);
     }
 
     return 0;
@@ -189,8 +212,24 @@ void* pa_asyncq_pop(pa_asyncq*l, int wait) {
 
         /* First try failed. Let's wait for changes. */
 
-        if (!wait)
+        if (!wait) {
+            /* Let's empty the FIFO from old notifications, before we return */
+            
+            while (pa_atomic_load(&l->n_written) > 0) {
+                ssize_t r;
+                int x[20];
+                
+                errno = 0;
+                if ((r = read(l->read_fds[0], x, sizeof(x))) <= 0 && errno != EINTR)
+                    return NULL;
+                
+                if (r > 0)
+                    if (pa_atomic_sub(&l->n_written, r) <= r)
+                        break;
+            }
+            
             return NULL;
+        }
 
         _Y;
 
@@ -198,6 +237,7 @@ void* pa_asyncq_pop(pa_asyncq*l, int wait) {
 
         for (;;) {
             char x[20];
+            ssize_t r;
 
             _Y;
 
@@ -206,10 +246,13 @@ void* pa_asyncq_pop(pa_asyncq*l, int wait) {
 
             _Y;
 
-            if (read(l->read_fds[0], x, sizeof(x)) < 0 && errno != EINTR) {
+            if ((r = read(l->read_fds[0], x, sizeof(x)) < 0) && errno != EINTR) {
                 pa_atomic_dec(&l->read_waiting);
                 return NULL;
             }
+
+            if (r > 0)
+                pa_atomic_sub(&l->n_written, r);
         }
 
         _Y;
@@ -226,7 +269,8 @@ void* pa_asyncq_pop(pa_asyncq*l, int wait) {
     if (pa_atomic_load(&l->write_waiting)) {
         char x = 'x';
         _Y;
-        write(l->write_fds[1], &x, sizeof(x));
+        if (write(l->write_fds[1], &x, sizeof(x)) >= 0)
+            pa_atomic_inc(&l->n_read);
     }
 
     return ret;
@@ -262,10 +306,13 @@ int pa_asyncq_before_poll(pa_asyncq *l) {
     return 0;
 }
 
-int pa_asyncq_after_poll(pa_asyncq *l) {
+void pa_asyncq_after_poll(pa_asyncq *l) {
     pa_assert(l);
 
     pa_assert(pa_atomic_load(&l->read_waiting) > 0);
 
     pa_atomic_dec(&l->read_waiting);
+
+
+    
 }
diff --git a/src/pulsecore/asyncq.h b/src/pulsecore/asyncq.h
index aac45b1..729ec46 100644
--- a/src/pulsecore/asyncq.h
+++ b/src/pulsecore/asyncq.h
@@ -51,6 +51,6 @@ 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);
-int pa_asyncq_after_poll(pa_asyncq *a);
+void pa_asyncq_after_poll(pa_asyncq *a);
 
 #endif
diff --git a/src/pulsecore/cli-command.c b/src/pulsecore/cli-command.c
index 36c85d6..d761353 100644
--- a/src/pulsecore/cli-command.c
+++ b/src/pulsecore/cli-command.c
@@ -115,6 +115,8 @@ 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);
 
 /* A method table for all available commands */
 
@@ -134,11 +136,11 @@ static const struct command commands[] = {
     { "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},
+    { "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-sink-input-mute",     pa_cli_command_sink_input_mute,    "Set the mute switch of a sink input (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},
@@ -161,6 +163,8 @@ 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},
     { NULL, NULL, NULL, 0 }
 };
 
@@ -899,6 +903,64 @@ static int pa_cli_command_move_source_output(pa_core *c, pa_tokenizer *t, pa_str
     return 0;
 }
 
+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;
+
+    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;
+
+    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_dump(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_GCC_UNUSED int *fail) {
     pa_module *m;
     pa_sink *sink;
@@ -1162,3 +1224,4 @@ int pa_cli_command_execute(pa_core *c, const char *s, pa_strbuf *buf, int *fail)
 
     return 0;
 }
+
diff --git a/src/pulsecore/cli-text.c b/src/pulsecore/cli-text.c
index 05d681e..c919e46 100644
--- a/src/pulsecore/cli-text.c
+++ b/src/pulsecore/cli-text.c
@@ -114,14 +114,15 @@ char *pa_sink_list_to_string(pa_core *c) {
             "  %c index: %u\n"
             "\tname: <%s>\n"
             "\tdriver: <%s>\n"
-            "\tis_hardware: <%i>\n"
+            "\tis hardware: <%i>\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", 
             c->default_sink_name && !strcmp(sink->name, c->default_sink_name) ? '*' : ' ',
             sink->index,
             sink->name,
@@ -133,7 +134,8 @@ char *pa_sink_list_to_string(pa_core *c) {
             (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));
 
         if (sink->module)
             pa_strbuf_printf(s, "\tmodule: <%u>\n", sink->module->index);
@@ -170,13 +172,14 @@ char *pa_source_list_to_string(pa_core *c) {
             "  %c index: %u\n"
             "\tname: <%s>\n"
             "\tdriver: <%s>\n"
-            "\tis_hardware: <%i>\n"
+            "\tis hardware: <%i>\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",
             c->default_source_name && !strcmp(source->name, c->default_source_name) ? '*' : ' ',
             source->index,
             source->name,
@@ -187,7 +190,8 @@ char *pa_source_list_to_string(pa_core *c) {
             !!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));
 
         if (source->monitor_of)
             pa_strbuf_printf(s, "\tmonitor_of: <%u>\n", source->monitor_of->index);
diff --git a/src/pulsecore/core-subscribe.c b/src/pulsecore/core-subscribe.c
index 6608d57..288d107 100644
--- a/src/pulsecore/core-subscribe.c
+++ b/src/pulsecore/core-subscribe.c
@@ -207,7 +207,7 @@ static void sched_event(pa_core *c) {
 }
 
 /* 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);
 
@@ -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;
diff --git a/src/pulsecore/core.c b/src/pulsecore/core.c
index 99ac74e..a940bfc 100644
--- a/src/pulsecore/core.c
+++ b/src/pulsecore/core.c
@@ -49,6 +49,8 @@
 
 #include "core.h"
 
+static PA_DEFINE_CHECK_TYPE(pa_core, core_check_type, pa_msgobject_check_type);
+
 static int core_process_msg(pa_msgobject *o, int code, void *userdata, pa_memchunk *chunk) {
     pa_core *c = PA_CORE(o);
 
@@ -81,8 +83,10 @@ static void asyncmsgq_cb(pa_mainloop_api*api, pa_io_event* e, int fd, pa_io_even
 
         /* Check whether there is a message for us to process */
         while (pa_asyncmsgq_get(c->asyncmsgq, &object, &code, &data, &chunk, 0) == 0) {
-            pa_asyncmsgq_dispatch(object, code, data, &chunk);
-            pa_asyncmsgq_done(c->asyncmsgq, 0);
+            int ret;
+
+            ret = pa_asyncmsgq_dispatch(object, code, data, &chunk);
+            pa_asyncmsgq_done(c->asyncmsgq, ret);
         }
 
         if (pa_asyncmsgq_before_poll(c->asyncmsgq) == 0)
@@ -112,7 +116,7 @@ pa_core* pa_core_new(pa_mainloop_api *m, int shared) {
         }
     }
 
-    c = pa_msgobject_new(pa_core);
+    c = pa_msgobject_new(pa_core, core_check_type);
     c->parent.parent.free = core_free;
     c->parent.process_msg = core_process_msg;
 
@@ -181,7 +185,7 @@ pa_core* pa_core_new(pa_mainloop_api *m, int shared) {
 
 static void core_free(pa_object *o) {
     pa_core *c = PA_CORE(o);
-    pa_core_assert_ref(c);
+    pa_assert(c);
 
     pa_module_unload_all(c);
     assert(!c->modules);
@@ -212,13 +216,14 @@ static void core_free(pa_object *o) {
     pa_xfree(c->default_source_name);
     pa_xfree(c->default_sink_name);
 
+    pa_asyncmsgq_after_poll(c->asyncmsgq);
+    pa_asyncmsgq_free(c->asyncmsgq);
+
     pa_mempool_free(c->mempool);
 
     pa_property_cleanup(c);
 
     c->mainloop->io_free(c->asyncmsgq_event);
-    pa_asyncmsgq_after_poll(c->asyncmsgq);
-    pa_asyncmsgq_free(c->asyncmsgq);
 
     pa_hook_free(&c->hook_sink_input_new);
     pa_hook_free(&c->hook_sink_disconnect);
diff --git a/src/pulsecore/core.h b/src/pulsecore/core.h
index 86660b7..a64f217 100644
--- a/src/pulsecore/core.h
+++ b/src/pulsecore/core.h
@@ -98,7 +98,7 @@ struct pa_core {
 };
 
 PA_DECLARE_CLASS(pa_core);
-#define PA_CORE(o) ((pa_core*) o)
+#define PA_CORE(o) pa_core_cast(o)
 
 enum {
     PA_CORE_MESSAGE_UNLOAD_MODULE,
diff --git a/src/pulsecore/log.c b/src/pulsecore/log.c
index 0033adb..a1197eb 100644
--- a/src/pulsecore/log.c
+++ b/src/pulsecore/log.c
@@ -71,14 +71,11 @@ 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);
 }
 
diff --git a/src/pulsecore/msgobject.c b/src/pulsecore/msgobject.c
index ce9f22f..6db630c 100644
--- a/src/pulsecore/msgobject.c
+++ b/src/pulsecore/msgobject.c
@@ -28,13 +28,15 @@
 
 #include "msgobject.h"
 
-pa_msgobject *pa_msgobject_new_internal(size_t size, const char *type_name) {
+PA_DEFINE_CHECK_TYPE(pa_msgobject, pa_msgobject_check_type, pa_object_check_type);
+
+pa_msgobject *pa_msgobject_new_internal(size_t size, const char *type_name, int (*check_type)(pa_object *o, const char *type_name)) {
     pa_msgobject *o;
 
     pa_assert(size > sizeof(pa_msgobject));
     pa_assert(type_name);
 
-    o = PA_MSGOBJECT(pa_object_new_internal(size, type_name));
+    o = PA_MSGOBJECT(pa_object_new_internal(size, type_name, check_type ? check_type : pa_msgobject_check_type));
     o->process_msg = NULL;
     return o;
 }
diff --git a/src/pulsecore/msgobject.h b/src/pulsecore/msgobject.h
index 317ebd2..65761ae 100644
--- a/src/pulsecore/msgobject.h
+++ b/src/pulsecore/msgobject.h
@@ -40,12 +40,14 @@ struct pa_msgobject {
     int (*process_msg)(pa_msgobject *o, int code, void *userdata, pa_memchunk *chunk);
 };
 
-pa_msgobject *pa_msgobject_new_internal(size_t size, const char *type_name);
+pa_msgobject *pa_msgobject_new_internal(size_t size, const char *type_name, int (*check_type)(pa_object *o, const char *type_name));
 
-#define pa_msgobject_new(type) ((type*) pa_msgobject_new_internal(sizeof(type), #type))
+int pa_msgobject_check_type(pa_object *o, const char *type);
+
+#define pa_msgobject_new(type, check_type) ((type*) pa_msgobject_new_internal(sizeof(type), #type, check_type))
 #define pa_msgobject_free ((void (*) (pa_msgobject* o)) pa_object_free)
 
-#define PA_MSGOBJECT(o) ((pa_msgobject*) (o))
+#define PA_MSGOBJECT(o) pa_msgobject_cast(o)
 
 PA_DECLARE_CLASS(pa_msgobject);
 
diff --git a/src/pulsecore/object.c b/src/pulsecore/object.c
index e6ed53b..a983c5a 100644
--- a/src/pulsecore/object.c
+++ b/src/pulsecore/object.c
@@ -28,7 +28,7 @@
 
 #include "object.h"
 
-pa_object *pa_object_new_internal(size_t size, const char *type_name) {
+pa_object *pa_object_new_internal(size_t size, const char *type_name, int (*check_type)(pa_object *o, const char *type_name)) {
     pa_object *o;
 
     pa_assert(size > sizeof(pa_object));
@@ -38,24 +38,30 @@ pa_object *pa_object_new_internal(size_t size, const char *type_name) {
     PA_REFCNT_INIT(o);
     o->type_name = type_name;
     o->free = pa_object_free;
+    o->check_type = check_type ? check_type : pa_object_check_type;
 
     return o;
 }
 
 pa_object *pa_object_ref(pa_object *o) {
-    pa_assert(o);
-    pa_assert(PA_REFCNT_VALUE(o) >= 1);
+    pa_object_assert_ref(o);
 
     PA_REFCNT_INC(o);
     return o;
 }
 
 void pa_object_unref(pa_object *o) {
-    pa_assert(o);
-    pa_assert(PA_REFCNT_VALUE(o) >= 1);
+    pa_object_assert_ref(o);
 
     if (PA_REFCNT_DEC(o) <= 0) {
         pa_assert(o->free);
         o->free(o);
     }
 }
+
+int pa_object_check_type(pa_object *o, const char *type_name) {
+    pa_assert(o);
+    pa_assert(type_name);
+    
+    return type_name == "pa_object" || strcmp(type_name, "pa_object") == 0;
+}
diff --git a/src/pulsecore/object.h b/src/pulsecore/object.h
index e195a35..270f289 100644
--- a/src/pulsecore/object.h
+++ b/src/pulsecore/object.h
@@ -25,7 +25,9 @@
   USA.
 ***/
 
+#include <string.h>
 #include <sys/types.h>
+
 #include <pulse/xmalloc.h>
 #include <pulsecore/refcnt.h>
 #include <pulsecore/macro.h>
@@ -36,13 +38,22 @@ struct pa_object {
     PA_REFCNT_DECLARE;
     const char *type_name;
     void (*free)(pa_object *o);
+    int (*check_type)(pa_object *o, const char *type_name);
 };
 
-pa_object *pa_object_new_internal(size_t size, const char *type_name);
-#define pa_object_new(type) ((type*) pa_object_new_internal(sizeof(type), #type))
+pa_object *pa_object_new_internal(size_t size, const char *type_name, int (*check_type)(pa_object *o, const char *type_name));
+#define pa_object_new(type, check_type) ((type*) pa_object_new_internal(sizeof(type), #type, check_type)
 
 #define pa_object_free ((void (*) (pa_object* o)) pa_xfree)
 
+int pa_object_check_type(pa_object *o, const char *type);
+
+static inline int pa_object_isinstance(void *o) {
+    pa_object *obj = (pa_object*) o;
+    pa_assert(obj);
+    return obj->check_type(obj, "pa_object");
+}
+
 pa_object *pa_object_ref(pa_object *o);
 void pa_object_unref(pa_object *o);
 
@@ -50,23 +61,50 @@ 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->check_type(obj, "pa_object"));
+    return obj;
+}
+
 #define pa_object_assert_ref(o) pa_assert(pa_object_refcnt(o))
 
-#define PA_OBJECT(o) ((pa_object*) (o))
-
-#define PA_DECLARE_CLASS(c) \
-    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));                     \
-    }                                                           \
+#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;                                \
+        pa_assert(obj);                                                 \
+        return obj->check_type(obj, #c);                                \
+    }                                                                   \
+    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, func, parent)                           \
+    int func(pa_object *o, const char *type) {                          \
+        pa_assert(o);                                                   \
+        pa_assert(type);                                                \
+        if (type == #c ||                                               \
+            strcmp(type, #c) == 0)                                      \
+            return 1;                                                   \
+        return parent(o, type);                                         \
+    }                                                                   \
     struct __stupid_useless_struct_to_allow_trailing_semicolon
 
+
 #endif
diff --git a/src/pulsecore/protocol-simple.c b/src/pulsecore/protocol-simple.c
index b7a4cc7..67741bd 100644
--- a/src/pulsecore/protocol-simple.c
+++ b/src/pulsecore/protocol-simple.c
@@ -40,13 +40,15 @@
 #include <pulsecore/namereg.h>
 #include <pulsecore/log.h>
 #include <pulsecore/core-error.h>
+#include <pulsecore/atomic.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;
@@ -59,18 +61,21 @@ struct connection {
     struct {
         pa_memblock *current_memblock;
         size_t memblock_index, fragment_size;
-        pa_atomic_int missing;
+        pa_atomic_t missing;
     } playback;
-};
+} connection;
+
+PA_DECLARE_CLASS(connection);
+#define CONNECTION(o) (connection_cast(o))
 
+static PA_DEFINE_CHECK_TYPE(connection, connection_check_type, pa_msgobject_check_type);
+                     
 struct pa_protocol_simple {
     pa_module *module;
     pa_core *core;
     pa_socket_server*server;
     pa_idxset *connections;
 
-    pa_asyncmsgq *asyncmsgq;
-
     enum {
         RECORD = 1,
         PLAYBACK = 2,
@@ -86,8 +91,9 @@ enum {
 };
 
 enum {
-    MESSAGE_REQUEST_DATA,   /* data from source output to main loop */
-    MESSAGE_POST_DATA       /* data from source output to main loop */
+    MESSAGE_REQUEST_DATA,      /* data requested from sink input from the main loop */
+    MESSAGE_POST_DATA,         /* data from source output to main loop */
+    MESSAGE_DROP_CONNECTION    /* Please drop a aconnection now */
 };
 
 
@@ -96,37 +102,49 @@ enum {
 #define RECORD_BUFFER_SECONDS (5)
 #define RECORD_BUFFER_FRAGMENTS (100)
 
-static void connection_free(struct connection *c) {
+static void connection_free(pa_object *o) {
+    connection *c = CONNECTION(o);
     pa_assert(c);
 
+    if (c->playback.current_memblock)
+        pa_memblock_unref(c->playback.current_memblock);
+
+    if (c->io)
+        pa_iochannel_free(c->io);
+    if (c->input_memblockq)
+        pa_memblockq_free(c->input_memblockq);
+    if (c->output_memblockq)
+        pa_memblockq_free(c->output_memblockq);
+
+    pa_xfree(c);
+}
+
+static void connection_drop(connection *c) {
+    pa_assert(c);
+    
     pa_idxset_remove_by_data(c->protocol->connections, c, NULL);
 
     if (c->sink_input) {
         pa_sink_input_disconnect(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_unref(c->source_output);
+        c->source_output = NULL;
     }
 
-    if (c->playback.current_memblock)
-        pa_memblock_unref(c->playback.current_memblock);
-
-    if (c->client)
+    if (c->client) {
         pa_client_free(c->client);
-    if (c->io)
-        pa_iochannel_free(c->io);
-    if (c->input_memblockq)
-        pa_memblockq_free(c->input_memblockq);
-    if (c->output_memblockq)
-        pa_memblockq_free(c->output_memblockq);
+        c->client = NULL;
+    }
 
-    pa_xfree(c);
+    connection_unref(c);
 }
 
-static int do_read(struct connection *c) {
+static int do_read(connection *c) {
     pa_memchunk chunk;
     ssize_t r;
     size_t l;
@@ -171,17 +189,17 @@ static int do_read(struct connection *c) {
 
     c->playback.memblock_index += r;
 
-    pa_asyncmsgq_post(c->protocol->asyncmsgq, c, MESSAGE_POST_DATA, NULL, &chunk, NULL, NULL);
+    pa_asyncmsgq_post(c->protocol->core->asyncmsgq, PA_MSGOBJECT(c->sink_input), SINK_INPUT_MESSAGE_POST_DATA, NULL, &chunk, NULL);
 
     return 0;
 }
 
-static int do_write(struct connection *c) {
+static int do_write(connection *c) {
     pa_memchunk chunk;
     ssize_t r;
     void *p;
 
-    p_assert(c);
+    pa_assert(c);
 
     if (!c->source_output)
         return 0;
@@ -212,7 +230,7 @@ static int do_write(struct connection *c) {
     return 0;
 }
 
-static void do_work(struct connection *c) {
+static void do_work(connection *c) {
     pa_assert(c);
 
     if (c->dead)
@@ -243,14 +261,39 @@ fail:
 
         pa_memblockq_prebuf_disable(c->input_memblockq);
     } else
-        connection_free(c);
+        connection_drop(c);
+}
+
+static int connection_process_msg(pa_msgobject *o, int code, void*userdata, pa_memchunk *chunk) {
+    connection *c = CONNECTION(o);
+    
+    connection_assert_ref(c);
+
+    switch (code) {
+        case MESSAGE_REQUEST_DATA:
+            do_work(c);
+            break;
+            
+        case MESSAGE_POST_DATA:
+            pa_memblockq_push(c->output_memblockq, chunk);
+            do_work(c);
+            break;
+
+        case MESSAGE_DROP_CONNECTION:
+            connection_drop(c);
+            break;
+
+    }
+
+    return 0;
 }
 
 /*** sink_input callbacks ***/
 
 /* Called from thread context */
-static int sink_input_process_msg(pa_sink_input *i, int code, void *userdata, const pa_memchunk *chunk) {
-    struct connection*c;
+static int sink_input_process_msg(pa_msgobject *o, int code, void *userdata, pa_memchunk *chunk) {
+    pa_sink_input *i = PA_SINK_INPUT(o);
+    connection*c;
 
     pa_assert(i);
     c = i->userdata;
@@ -263,6 +306,8 @@ static int sink_input_process_msg(pa_sink_input *i, int code, void *userdata, co
 
             /* New data from the main loop */
             pa_memblockq_push_align(c->input_memblockq, chunk);
+            pa_atomic_store(&c->playback.missing, pa_memblockq_missing(c->input_memblockq));
+            
             return 0;
         }
 
@@ -276,13 +321,14 @@ static int sink_input_process_msg(pa_sink_input *i, int code, void *userdata, co
         }
 
         default:
-            return pa_sink_input_process_msg(i, code, userdata);
+            return pa_sink_input_process_msg(o, code, userdata, chunk);
     }
 }
 
 /* Called from thread context */
 static int sink_input_peek_cb(pa_sink_input *i, pa_memchunk *chunk) {
-    struct connection*c;
+    connection*c;
+    int r;
 
     pa_assert(i);
     c = i->userdata;
@@ -292,14 +338,14 @@ static int sink_input_peek_cb(pa_sink_input *i, pa_memchunk *chunk) {
     r = pa_memblockq_peek(c->input_memblockq, chunk);
 
     if (c->dead && r < 0)
-        connection_free(c);
+        pa_asyncmsgq_post(c->protocol->core->asyncmsgq, PA_MSGOBJECT(c), MESSAGE_DROP_CONNECTION, c, NULL, NULL);
 
     return r;
 }
 
 /* Called from thread context */
 static void sink_input_drop_cb(pa_sink_input *i, const pa_memchunk *chunk, size_t length) {
-    struct connection*c = i->userdata;
+    connection*c = i->userdata;
     size_t old, new;
 
     pa_assert(i);
@@ -310,10 +356,10 @@ static void sink_input_drop_cb(pa_sink_input *i, const pa_memchunk *chunk, size_
     pa_memblockq_drop(c->input_memblockq, chunk, length);
     new = pa_memblockq_missing(c->input_memblockq);
 
-    pa_atomic_store(&c->playback.missing, &new);
+    pa_atomic_store(&c->playback.missing, new);
 
     if (new > old)
-        pa_asyncmsgq_post(c->protocol->asyncmsgq, c, MESSAGE_REQUEST_DATA, NULL, NULL, NULL, NULL);
+        pa_asyncmsgq_post(c->protocol->core->asyncmsgq, PA_MSGOBJECT(c), MESSAGE_REQUEST_DATA, NULL, NULL, NULL);
 }
 
 /* Called from main context */
@@ -321,34 +367,34 @@ static void sink_input_kill_cb(pa_sink_input *i) {
     pa_assert(i);
     pa_assert(i->userdata);
 
-    connection_free((struct connection *) i->userdata);
+    connection_drop((connection *) i->userdata);
 }
 
 /*** source_output callbacks ***/
 
 static void source_output_push_cb(pa_source_output *o, const pa_memchunk *chunk) {
-    struct connection *c;
+    connection *c;
 
     pa_assert(o);
     c = o->userdata;
     pa_assert(c);
     pa_assert(chunk);
 
-    pa_asyncmsgq_post(c->protocol->asyncmsgq, c, MESSAGE_REQUEST_DATA, NULL, chunk, NULL, NULL);
+    pa_asyncmsgq_post(c->protocol->core->asyncmsgq, PA_MSGOBJECT(c), MESSAGE_POST_DATA, NULL, chunk, NULL);
 }
 
 static void source_output_kill_cb(pa_source_output *o) {
-    struct connection*c;
+    connection*c;
 
     pa_assert(o);
     c = o->userdata;
     pa_assert(c);
 
-    connection_free(c);
+    connection_drop(c);
 }
 
 static pa_usec_t source_output_get_latency_cb(pa_source_output *o) {
-    struct connection*c;
+    connection*c;
 
     pa_assert(o);
     c = o->userdata;
@@ -360,19 +406,19 @@ static pa_usec_t source_output_get_latency_cb(pa_source_output *o) {
 /*** client callbacks ***/
 
 static void client_kill_cb(pa_client *client) {
-    struct connection*c;
+    connection*c;
 
     pa_assert(client);
     c = client->userdata;
     pa_assert(c);
 
-    connection_free(client);
+    connection_drop(c);
 }
 
 /*** pa_iochannel callbacks ***/
 
 static void io_callback(pa_iochannel*io, void *userdata) {
-    struct connection *c = userdata;
+    connection *c = userdata;
 
     pa_assert(io);
     pa_assert(c);
@@ -384,7 +430,7 @@ static void io_callback(pa_iochannel*io, 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];
 
     pa_assert(s);
@@ -397,7 +443,9 @@ 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, connection_check_type);
+    c->parent.parent.free = connection_free;
+    c->parent.process_msg = connection_process_msg;
     c->io = io;
     c->sink_input = NULL;
     c->source_output = NULL;
@@ -415,7 +463,6 @@ static void on_connection(pa_socket_server*s, pa_iochannel *io, void *userdata)
     c->client->kill = client_kill_cb;
     c->client->userdata = c;
 
-
     if (p->mode & PLAYBACK) {
         pa_sink_input_new_data data;
         size_t l;
@@ -432,10 +479,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);
@@ -449,7 +496,7 @@ static void on_connection(pa_socket_server*s, pa_iochannel *io, void *userdata)
                 NULL);
         pa_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));
 
@@ -498,47 +545,7 @@ static void on_connection(pa_socket_server*s, pa_iochannel *io, void *userdata)
 
 fail:
     if (c)
-        connection_free(c);
-}
-
-static void asyncmsgq_cb(pa_mainloop_api*api, pa_io_event* e, int fd, pa_io_event_flags_t events, void *userdata) {
-    pa_protocol_simple *p = userdata;
-    int do_some_work = 0;
-
-    pa_assert(pa_asyncmsgq_get_fd(p->asyncmsgq) == fd);
-    pa_assert(events == PA_IO_EVENT_INPUT);
-
-    pa_asyncmsgq_after_poll(p->asyncmsgq);
-
-    for (;;) {
-        int code;
-        void *object, *data;
-
-        /* Check whether there is a message for us to process */
-        while (pa_asyncmsgq_get(p->asyncmsgq, &object, &code, &data) == 0) {
-
-            connection *c = object;
-
-            pa_assert(c);
-
-            switch (code) {
-
-                case MESSAGE_REQUEST_DATA:
-                    do_work(c);
-                    break;
-
-                case MESSAGE_POST_DATA:
-                    pa_memblockq_push(c->output_memblockq, chunk);
-                    do_work(c);
-                    break;
-            }
-
-            pa_asyncmsgq_done(p->asyncmsgq);
-        }
-
-        if (pa_asyncmsgq_before_poll(p->asyncmsgq) == 0)
-            break;
-    }
+        connection_drop(c);
 }
 
 pa_protocol_simple* pa_protocol_simple_new(pa_core *core, pa_socket_server *server, pa_module *m, pa_modargs *ma) {
@@ -554,7 +561,6 @@ pa_protocol_simple* pa_protocol_simple_new(pa_core *core, pa_socket_server *serv
     p->core = core;
     p->server = server;
     p->connections = pa_idxset_new(NULL, NULL);
-    pa_assert_se(p->asyncmsgq = pa_asyncmsgq_new(0));
 
     p->sample_spec = core->default_sample_spec;
     if (pa_modargs_get_sample_spec(ma, &p->sample_spec) < 0) {
@@ -586,9 +592,6 @@ pa_protocol_simple* pa_protocol_simple_new(pa_core *core, pa_socket_server *serv
 
     pa_socket_server_set_callback(p->server, on_connection, p);
 
-    pa_assert_se(pa_asyncmsgq_before_poll(p->asyncmsgq) == 0);
-    pa_assert_se(p->asyncmsgq_event = core->mainloop->io_event_new(core->mainloop, pa_asyncmsgq_get_fd(p->asyncmsgq), PA_IO_EVENT_INPUT, p));
-
     return p;
 
 fail:
@@ -600,12 +603,12 @@ fail:
 
 
 void pa_protocol_simple_free(pa_protocol_simple *p) {
-    struct connection *c;
+    connection *c;
     pa_assert(p);
 
     if (p->connections) {
         while((c = pa_idxset_first(p->connections, NULL)))
-            connection_free(c);
+            connection_drop(c);
 
         pa_idxset_free(p->connections, NULL, NULL);
     }
@@ -613,12 +616,6 @@ void pa_protocol_simple_free(pa_protocol_simple *p) {
     if (p->server)
         pa_socket_server_unref(p->server);
 
-    if (p->asyncmsgq) {
-        c->mainloop->io_event_free(c->asyncmsgq_event);
-        pa_asyncmsgq_after_poll(c->asyncmsgq);
-        pa_asyncmsgq_free(p->asyncmsgq);
-    }
-
     pa_xfree(p);
 }
 
diff --git a/src/pulsecore/resampler.c b/src/pulsecore/resampler.c
index 248d733..a43c7c7 100644
--- a/src/pulsecore/resampler.c
+++ b/src/pulsecore/resampler.c
@@ -48,6 +48,7 @@ struct pa_resampler {
 
     void (*impl_free)(pa_resampler *r);
     void (*impl_update_input_rate)(pa_resampler *r, uint32_t rate);
+    void (*impl_update_output_rate)(pa_resampler *r, uint32_t rate);
     void (*impl_run)(pa_resampler *r, const pa_memchunk *in, pa_memchunk *out);
     void *impl_data;
 };
@@ -165,6 +166,19 @@ void pa_resampler_set_input_rate(pa_resampler *r, uint32_t rate) {
         r->impl_update_input_rate(r, rate);
 }
 
+void pa_resampler_set_output_rate(pa_resampler *r, uint32_t rate) {
+    assert(r);
+    assert(rate > 0);
+
+    if (r->o_ss.rate == rate)
+        return;
+
+    r->o_ss.rate = rate;
+
+    if (r->impl_update_output_rate)
+        r->impl_update_output_rate(r, rate);
+}
+
 void pa_resampler_run(pa_resampler *r, const pa_memchunk *in, pa_memchunk *out) {
     assert(r && in && out && r->impl_run);
 
@@ -512,6 +526,25 @@ static void libsamplerate_update_input_rate(pa_resampler *r, uint32_t rate) {
     }
 }
 
+
+static void libsamplerate_update_output_rate(pa_resampler *r, uint32_t rate) {
+    struct impl_libsamplerate *u;
+
+    assert(r);
+    assert(rate > 0);
+    assert(r->impl_data);
+    u = r->impl_data;
+
+    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) rate / r->i_ss.rate);
+        assert(ret == 0);
+    }
+}
+
 static int libsamplerate_init(pa_resampler *r) {
     struct impl_libsamplerate *u = NULL;
     int err;
@@ -541,6 +574,7 @@ static int libsamplerate_init(pa_resampler *r) {
 
     r->impl_free = libsamplerate_free;
     r->impl_update_input_rate = libsamplerate_update_input_rate;
+    r->impl_update_output_rate = libsamplerate_update_output_rate;
     r->impl_run = libsamplerate_run;
 
     calc_map_table(r);
@@ -631,7 +665,7 @@ static void trivial_free(pa_resampler *r) {
     pa_xfree(r->impl_data);
 }
 
-static void trivial_update_input_rate(pa_resampler *r, uint32_t rate) {
+static void trivial_update_rate(pa_resampler *r, uint32_t rate) {
     struct impl_trivial *u;
 
     assert(r);
@@ -655,7 +689,8 @@ static int trivial_init(pa_resampler*r) {
 
     r->impl_run = trivial_run;
     r->impl_free = trivial_free;
-    r->impl_update_input_rate = trivial_update_input_rate;
+    r->impl_update_input_rate = trivial_update_rate;
+    r->impl_update_output_rate = trivial_update_rate;
 
     return 0;
 }
diff --git a/src/pulsecore/resampler.h b/src/pulsecore/resampler.h
index c283593..ada293e 100644
--- a/src/pulsecore/resampler.h
+++ b/src/pulsecore/resampler.h
@@ -63,6 +63,9 @@ 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);
 
diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c
index 00b82d2..2c6b356 100644
--- a/src/pulsecore/sink-input.c
+++ b/src/pulsecore/sink-input.c
@@ -45,7 +45,9 @@
 #define MOVE_BUFFER_LENGTH (1024*1024)
 #define SILENCE_BUFFER_LENGTH (64*1024)
 
-static void sink_input_free(pa_msgobject *o);
+static PA_DEFINE_CHECK_TYPE(pa_sink_input, sink_input_check_type, pa_msgobject_check_type);
+
+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) {
     pa_assert(data);
@@ -159,13 +161,12 @@ pa_sink_input* pa_sink_input_new(
         data->resample_method = pa_resampler_get_method(resampler);
     }
 
-    i = pa_msgobject_new(pa_sink_input);
-
+    i = pa_msgobject_new(pa_sink_input, sink_input_check_type);
     i->parent.parent.free = sink_input_free;
     i->parent.process_msg = pa_sink_input_process_msg;
 
     i->core = core;
-    pa_atomic_load(&i->state, PA_SINK_INPUT_DRAINED);
+    pa_atomic_store(&i->state, PA_SINK_INPUT_DRAINED);
     i->flags = flags;
     i->name = pa_xstrdup(data->name);
     i->driver = pa_xstrdup(data->driver);
@@ -189,11 +190,11 @@ pa_sink_input* pa_sink_input_new(
     i->userdata = NULL;
 
     i->thread_info.silence_memblock = NULL;
-    i->thread_info.move_silence = 0;
+/*     i->thread_info.move_silence = 0; */
     pa_memchunk_reset(&i->thread_info.resampled_chunk);
     i->thread_info.resampler = resampler;
-    i->thread_info.soft_volume = i->volume;
-    i->thread_info.soft_muted = i->muted;
+    i->thread_info.volume = i->volume;
+    i->thread_info.muted = i->muted;
 
     pa_assert_se(pa_idxset_put(core->sink_inputs, i, &i->index) == 0);
     pa_assert_se(pa_idxset_put(i->sink->inputs, i, NULL) == 0);
@@ -213,14 +214,16 @@ void pa_sink_input_disconnect(pa_sink_input *i) {
     pa_assert(i);
     pa_return_if_fail(pa_sink_input_get_state(i) != PA_SINK_INPUT_DISCONNECTED);
 
-    pa_asyncmsgq_send(i->sink->asyncmsgq, i->sink, PA_SINK_MESSAGE_REMOVE_INPUT, i, NULL);
+    pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i->sink), PA_SINK_MESSAGE_REMOVE_INPUT, i, NULL);
 
     pa_idxset_remove_by_data(i->sink->core->sink_inputs, i, NULL);
     pa_idxset_remove_by_data(i->sink->inputs, i, NULL);
 
     pa_subscription_post(i->sink->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_REMOVE, i->index);
-    i->sink = NULL;
 
+    pa_sink_update_status(i->sink);
+
+    i->sink = NULL;
     i->process_msg = NULL;
     i->peek = NULL;
     i->drop = NULL;
@@ -228,10 +231,10 @@ void pa_sink_input_disconnect(pa_sink_input *i) {
     i->get_latency = NULL;
     i->underrun = NULL;
 
-    pa_atomic_load(&i->state, PA_SINK_INPUT_DISCONNECTED);
+    pa_atomic_store(&i->state, PA_SINK_INPUT_DISCONNECTED);
 }
 
-static void sink_input_free(pa_msgobject *o) {
+static void sink_input_free(pa_object *o) {
     pa_sink_input* i = PA_SINK_INPUT(o);
 
     pa_assert(i);
@@ -241,8 +244,8 @@ static void sink_input_free(pa_msgobject *o) {
 
     pa_log_info("Freeing output %u \"%s\"", i->index, i->name);
 
-    if (i->resampled_chunk.memblock)
-        pa_memblock_unref(i->resampled_chunk.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);
@@ -261,10 +264,10 @@ void pa_sink_input_put(pa_sink_input *i) {
     i->thread_info.volume = i->volume;
     i->thread_info.muted = i->muted;
 
-    pa_asyncmsgq_post(i->sink->asyncmsgq, i->sink, PA_SINK_MESSAGE_ADD_INPUT, i, NULL, pa_sink_unref, pa_sink_input_unref);
+    pa_asyncmsgq_post(i->sink->asyncmsgq, PA_MSGOBJECT(i->sink), PA_SINK_MESSAGE_ADD_INPUT, pa_sink_input_ref(i), NULL, (pa_free_cb_t) pa_sink_input_unref);
     pa_sink_update_status(i->sink);
 
-    pa_subscription_post(core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_NEW, i->index);
+    pa_subscription_post(i->sink->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_NEW, i->index);
 }
 
 void pa_sink_input_kill(pa_sink_input*i) {
@@ -279,7 +282,7 @@ pa_usec_t pa_sink_input_get_latency(pa_sink_input *i) {
 
     pa_sink_input_assert_ref(i);
 
-    if (pa_asyncmsgq_send(i->sink->asyncmsgq, i->sink, PA_SINK_INPUT_MESSAGE_GET_LATENCY, &r, NULL) < 0)
+    if (pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_GET_LATENCY, &r, NULL) < 0)
         r = 0;
 
     if (i->get_latency)
@@ -327,14 +330,14 @@ int pa_sink_input_peek(pa_sink_input *i, pa_memchunk *chunk, pa_cvolume *volume)
 /*         goto finish; */
 /*     } */
 
-    if (!i->resampler) {
+    if (!i->thread_info.resampler) {
         do_volume_adj_here = 0;
         ret = i->peek(i, 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->thread_info.soft_volume) && !i->thread_info.soft_muted;
+    volume_is_norm = pa_cvolume_is_norm(&i->thread_info.volume) && !i->thread_info.muted;
 
     while (!i->thread_info.resampled_chunk.memblock) {
         pa_memchunk tchunk;
@@ -345,7 +348,7 @@ int pa_sink_input_peek(pa_sink_input *i, pa_memchunk *chunk, pa_cvolume *volume)
 
         pa_assert(tchunk.length);
 
-        l = pa_resampler_request(i->resampler, CONVERT_BUFFER_LENGTH);
+        l = pa_resampler_request(i->thread_info.resampler, CONVERT_BUFFER_LENGTH);
 
         if (l > tchunk.length)
             l = tchunk.length;
@@ -356,10 +359,10 @@ int pa_sink_input_peek(pa_sink_input *i, pa_memchunk *chunk, pa_cvolume *volume)
         /* 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->thread_info.soft_volume);
+            pa_volume_memchunk(&tchunk, &i->sample_spec, &i->thread_info.volume);
         }
 
-        pa_resampler_run(i->resampler, &tchunk, &i->thread_info.resampled_chunk);
+        pa_resampler_run(i->thread_info.resampler, &tchunk, &i->thread_info.resampled_chunk);
         pa_memblock_unref(tchunk.memblock);
     }
 
@@ -378,7 +381,7 @@ finish:
 
     if (ret >= 0)
         pa_atomic_cmpxchg(&i->state, state, PA_SINK_INPUT_RUNNING);
-    else if (ret < 0 && i->state == PA_SINK_INPUT_RUNNING)
+    else if (ret < 0 && state == PA_SINK_INPUT_RUNNING)
         pa_atomic_cmpxchg(&i->state, state, PA_SINK_INPUT_DRAINED);
 
     if (ret >= 0) {
@@ -427,7 +430,7 @@ void pa_sink_input_drop(pa_sink_input *i, const pa_memchunk *chunk, size_t lengt
 /*         return; */
 /*     } */
 
-    if (!i->resampler) {
+    if (!i->thread_info.resampler) {
         if (i->drop)
             i->drop(i, chunk, length);
         return;
@@ -454,7 +457,7 @@ void pa_sink_input_set_volume(pa_sink_input *i, const pa_cvolume *volume) {
 
     i->volume = *volume;
 
-    pa_asyncmsgq_post(s->asyncmsgq, pa_sink_input_ref(i), PA_SINK_INPUT_MESSAGE_SET_VOLUME, pa_xnewdup(struct pa_cvolume, volume, 1), pa_sink_input_unref, pa_xfree);
+    pa_asyncmsgq_post(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_SET_VOLUME, pa_xnewdup(struct pa_cvolume, volume, 1), NULL, pa_xfree);
     pa_subscription_post(i->sink->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index);
 }
 
@@ -473,18 +476,17 @@ void pa_sink_input_set_mute(pa_sink_input *i, int mute) {
 
     i->muted = mute;
 
-    pa_asyncmsgq_post(s->asyncmsgq, pa_sink_input_ref(i), PA_SINK_INPUT_MESSAGE_SET_MUTE, PA_UINT_TO_PTR(mute), pa_sink_input_unref, NULL);
+    pa_asyncmsgq_post(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_SET_MUTE, PA_UINT_TO_PTR(mute), 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);
 
-    return !!i->mute;
+    return !!i->muted;
 }
 
 void pa_sink_input_cork(pa_sink_input *i, int b) {
-    int n;
     pa_sink_input_state_t state;
 
     pa_sink_input_assert_ref(i);
@@ -493,24 +495,24 @@ void pa_sink_input_cork(pa_sink_input *i, int b) {
     pa_assert(state != PA_SINK_INPUT_DISCONNECTED);
 
     if (b && state != PA_SINK_INPUT_CORKED)
-        pa_atomic_store(i->state, PA_SINK_INPUT_CORKED);
+        pa_atomic_store(&i->state, PA_SINK_INPUT_CORKED);
     else if (!b && state == PA_SINK_INPUT_CORKED)
-        pa_atomic_cmpxchg(i->state, state, PA_SINK_INPUT_DRAINED);
+        pa_atomic_cmpxchg(&i->state, state, PA_SINK_INPUT_DRAINED);
 }
 
 int pa_sink_input_set_rate(pa_sink_input *i, uint32_t rate) {
     pa_sink_input_assert_ref(i);
-    pa_return_val_if_fail(u->thread_info.resampler, -1);
+    pa_return_val_if_fail(i->thread_info.resampler, -1);
 
     if (i->sample_spec.rate == rate)
         return 0;
 
     i->sample_spec.rate = rate;
 
-    pa_asyncmsgq_post(s->asyncmsgq, pa_sink_input_ref(i), PA_SINK_INPUT_MESSAGE_SET_RATE, PA_UINT_TO_PTR(rate), NULL, pa_sink_input_unref, NULL);
+    pa_asyncmsgq_post(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_SET_RATE, PA_UINT_TO_PTR(rate), NULL, NULL);
 
     pa_subscription_post(i->sink->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index);
-    return 0
+    return 0;
 }
 
 void pa_sink_input_set_name(pa_sink_input *i, const char *name) {
@@ -535,9 +537,9 @@ 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_resampler *new_resampler = NULL;
-    pa_memblockq *buffer = NULL;
-    pa_sink *origin;
+/*     pa_resampler *new_resampler = NULL; */
+/*     pa_memblockq *buffer = NULL; */
+/*     pa_sink *origin; */
 
     pa_sink_input_assert_ref(i);
     pa_sink_assert_ref(dest);
@@ -702,18 +704,18 @@ int pa_sink_input_process_msg(pa_msgobject *o, int code, void *userdata, pa_memc
 
     switch (code) {
         case PA_SINK_INPUT_MESSAGE_SET_VOLUME:
-            s->thread_info.soft_volume = *((pa_cvolume*) userdata);
+            i->thread_info.volume = *((pa_cvolume*) userdata);
             return 0;
 
         case PA_SINK_INPUT_MESSAGE_SET_MUTE:
-            s->thread_info.soft_muted = PA_PTR_TO_UINT(userdata);
+            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->resampled_chunk.length, &i->sink->sample_spec);
+                *r += pa_bytes_to_usec(i->thread_info.resampled_chunk.length, &i->sink->sample_spec);
 
 /*             if (i->move_silence) */
 /*                 r += pa_bytes_to_usec(i->move_silence, &i->sink->sample_spec); */
@@ -724,7 +726,7 @@ int pa_sink_input_process_msg(pa_msgobject *o, int code, void *userdata, pa_memc
         case PA_SINK_INPUT_MESSAGE_SET_RATE: {
 
             i->thread_info.sample_spec.rate = PA_PTR_TO_UINT(userdata);
-            pa_resampler_set_input_rate(i->resampler, PA_PTR_TO_UINT(userdata));
+            pa_resampler_set_input_rate(i->thread_info.resampler, PA_PTR_TO_UINT(userdata));
 
             return 0;
         }
diff --git a/src/pulsecore/sink-input.h b/src/pulsecore/sink-input.h
index 338d696..a8c05b8 100644
--- a/src/pulsecore/sink-input.h
+++ b/src/pulsecore/sink-input.h
@@ -99,7 +99,7 @@ struct pa_sink_input {
 };
 
 PA_DECLARE_CLASS(pa_sink_input);
-#define PA_SINK_INPUT(o) ((pa_sink_input*) (o))
+#define PA_SINK_INPUT(o) pa_sink_input_cast(o)
 
 enum {
     PA_SINK_INPUT_MESSAGE_SET_VOLUME,
@@ -160,7 +160,7 @@ 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_set_rate(pa_sink_input *i, uint32_t rate);
+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);
 
diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c
index 0e022d9..7f00904 100644
--- a/src/pulsecore/sink.c
+++ b/src/pulsecore/sink.c
@@ -47,6 +47,8 @@
 
 #define MAX_MIX_CHANNELS 32
 
+static PA_DEFINE_CHECK_TYPE(pa_sink, sink_check_type, pa_msgobject_check_type);
+
 static void sink_free(pa_object *s);
 
 pa_sink* pa_sink_new(
@@ -77,7 +79,7 @@ pa_sink* pa_sink_new(
     pa_return_null_if_fail(!driver || pa_utf8_valid(driver));
     pa_return_null_if_fail(name && pa_utf8_valid(name) && *name);
 
-    s = pa_msgobject_new(pa_sink);
+    s = pa_msgobject_new(pa_sink, sink_check_type);
 
     if (!(name = pa_namereg_register(core, name, PA_NAMEREG_SINK, s, fail))) {
         pa_xfree(s);
@@ -88,7 +90,7 @@ pa_sink* pa_sink_new(
     s->parent.process_msg = pa_sink_process_msg;
 
     s->core = core;
-    pa_atomic_store(&s->state, PA_SINK_IDLE);
+    s->state = PA_SINK_IDLE;
     s->name = pa_xstrdup(name);
     s->description = NULL;
     s->driver = pa_xstrdup(driver);
@@ -110,11 +112,10 @@ pa_sink* pa_sink_new(
     s->get_volume = NULL;
     s->set_mute = NULL;
     s->get_mute = NULL;
-    s->start = NULL;
-    s->stop = NULL;
+    s->set_state = NULL;
     s->userdata = NULL;
 
-    pa_assert_se(s->asyncmsgq = pa_asyncmsgq_new(0));
+    s->asyncmsgq = NULL;
 
     r = pa_idxset_put(core->sinks, s, &s->index);
     pa_assert(s->index != PA_IDXSET_INVALID && r >= 0);
@@ -139,56 +140,40 @@ pa_sink* pa_sink_new(
     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;
 
     pa_subscription_post(core, PA_SUBSCRIPTION_EVENT_SINK | PA_SUBSCRIPTION_EVENT_NEW, s->index);
 
     return s;
 }
 
-static void sink_start(pa_sink *s) {
-    pa_sink_state_t state;
+static int sink_set_state(pa_sink *s, pa_sink_state_t state) {
+    int ret;
+    
     pa_assert(s);
 
-    state = pa_sink_get_state(s);
-    pa_return_if_fail(state == PA_SINK_IDLE || state == PA_SINK_SUSPENDED);
-
-    pa_atomic_store(&s->state, PA_SINK_RUNNING);
-
-    if (s->start)
-        s->start(s);
-    else
-        pa_asyncmsgq_post(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_START, NULL, NULL, NULL);
-}
-
-static void sink_stop(pa_sink *s) {
-    pa_sink_state_t state;
-    int stop;
+    if (s->state == state)
+        return 0;
 
-    pa_assert(s);
-    state = pa_sink_get_state(s);
-    pa_return_if_fail(state == PA_SINK_RUNNING || state == PA_SINK_SUSPENDED);
+    if (s->set_state)
+        if ((ret = s->set_state(s, state)) < 0)
+            return -1;
 
-    stop = state == PA_SINK_RUNNING;
-    pa_atomic_store(&s->state, PA_SINK_IDLE);
+    if (pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_SET_STATE, PA_UINT_TO_PTR(state), NULL) < 0)
+        return -1;
 
-    if (stop) {
-        if (s->stop)
-            s->stop(s);
-        else
-            pa_asyncmsgq_post(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_STOP, NULL, NULL, NULL);
-    }
+    s->state = state;
+    return 0;
 }
 
 void pa_sink_disconnect(pa_sink* s) {
     pa_sink_input *i, *j = NULL;
 
     pa_assert(s);
-    pa_return_if_fail(pa_sink_get_state(s) != PA_SINK_DISCONNECTED);
-
-    sink_stop(s);
+    pa_return_if_fail(s->state != PA_SINK_DISCONNECTED);
 
-    pa_atomic_store(&s->state, PA_SINK_DISCONNECTED);
     pa_namereg_unregister(s->core, s->name);
+    pa_idxset_remove_by_data(s->core->sinks, s, NULL);
 
     pa_hook_fire(&s->core->hook_sink_disconnect, s);
 
@@ -201,26 +186,27 @@ void pa_sink_disconnect(pa_sink* s) {
     if (s->monitor_source)
         pa_source_disconnect(s->monitor_source);
 
-    pa_idxset_remove_by_data(s->core->sinks, s, NULL);
+    sink_set_state(s, PA_SINK_DISCONNECTED);
 
     s->get_latency = NULL;
     s->get_volume = NULL;
     s->set_volume = NULL;
     s->set_mute = NULL;
     s->get_mute = NULL;
-    s->start = NULL;
-    s->stop = NULL;
+    s->set_state = NULL;
 
     pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK | PA_SUBSCRIPTION_EVENT_REMOVE, s->index);
 }
 
 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);
 
-    pa_sink_disconnect(s);
+    if (s->state != PA_SINK_DISCONNECTED)
+        pa_sink_disconnect(s);
 
     pa_log_info("Freeing sink %u \"%s\"", s->index, s->name);
 
@@ -231,9 +217,10 @@ static void sink_free(pa_object *o) {
 
     pa_idxset_free(s->inputs, NULL, NULL);
 
-    pa_hashmap_free(s->thread_info.inputs, (pa_free2_cb_t) pa_sink_input_unref, NULL);
-
-    pa_asyncmsgq_free(s->asyncmsgq);
+    while ((i = pa_hashmap_steal_first(s->thread_info.inputs)))
+        pa_sink_input_unref(i);
+    
+    pa_hashmap_free(s->thread_info.inputs, NULL, NULL);
 
     pa_xfree(s->name);
     pa_xfree(s->description);
@@ -241,44 +228,38 @@ static void sink_free(pa_object *o) {
     pa_xfree(s);
 }
 
-void pa_sink_update_status(pa_sink*s) {
+void pa_sink_set_asyncmsgq(pa_sink *s, pa_asyncmsgq *q) {
     pa_sink_assert_ref(s);
+    pa_assert(q);
 
-    if (pa_sink_get_state(s) == PA_SINK_SUSPENDED)
-        return;
+    s->asyncmsgq = q;
 
-    if (pa_sink_used_by(s) > 0)
-        sink_start(s);
-    else
-        sink_stop(s);
+    if (s->monitor_source)
+        pa_source_set_asyncmsgq(s->monitor_source, q);
 }
 
-void pa_sink_suspend(pa_sink *s, int suspend) {
-    pa_sink_state_t state;
-
+int pa_sink_update_status(pa_sink*s) {
     pa_sink_assert_ref(s);
 
-    state = pa_sink_get_state(s);
-    pa_return_if_fail(suspend && (state == PA_SINK_RUNNING || state == PA_SINK_IDLE));
-    pa_return_if_fail(!suspend && (state == PA_SINK_SUSPENDED));
+    if (s->state == PA_SINK_SUSPENDED)
+        return 0;
 
+    return sink_set_state(s, pa_sink_used_by(s) ? PA_SINK_RUNNING : PA_SINK_IDLE);
+}
 
-    if (suspend) {
-        pa_atomic_store(&s->state, PA_SINK_SUSPENDED);
+int pa_sink_suspend(pa_sink *s, int suspend) {
+    pa_sink_assert_ref(s);
 
-        if (s->stop)
-            s->stop(s);
-        else
-            pa_asyncmsgq_post(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_STOP, NULL, NULL, NULL);
+    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);
+}
 
-    } else {
-        pa_atomic_store(&s->state, PA_SINK_RUNNING);
+void pa_sink_ping(pa_sink *s) {
+    pa_sink_assert_ref(s);
 
-        if (s->start)
-            s->start(s);
-        else
-            pa_asyncmsgq_post(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_START, NULL, NULL, NULL);
-    }
+    pa_asyncmsgq_post(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_PING, NULL, NULL, NULL);
 }
 
 static unsigned fill_mix_info(pa_sink *s, pa_mix_info *info, unsigned maxinfo) {
@@ -652,7 +633,7 @@ int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, pa_memchunk *
     pa_sink *s = PA_SINK(o);
     pa_sink_assert_ref(s);
 
-    switch (code) {
+    switch ((pa_sink_message_t) code) {
         case PA_SINK_MESSAGE_ADD_INPUT: {
             pa_sink_input *i = userdata;
             pa_hashmap_put(s->thread_info.inputs, PA_UINT32_TO_PTR(i->index), pa_sink_input_ref(i));
@@ -681,7 +662,17 @@ int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, pa_memchunk *
             *((int*) userdata) = s->thread_info.soft_muted;
             return 0;
 
-        default:
-            return -1;
+        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_GET_LATENCY:
+        case PA_SINK_MESSAGE_MAX:
+            ;
     }
+
+    return -1;
 }
diff --git a/src/pulsecore/sink.h b/src/pulsecore/sink.h
index 2939cc4..0b308e5 100644
--- a/src/pulsecore/sink.h
+++ b/src/pulsecore/sink.h
@@ -55,7 +55,7 @@ struct pa_sink {
 
     uint32_t index;
     pa_core *core;
-    pa_atomic_t state;
+    pa_sink_state_t state;
 
     char *name;
     char *description, *driver;            /* may be NULL */
@@ -74,8 +74,7 @@ struct pa_sink {
     int refresh_volume;
     int refresh_mute;
 
-    int (*start)(pa_sink *s);
-    int (*stop)(pa_sink *s);
+    int (*set_state)(pa_sink *s, pa_sink_state_t state);
     int (*set_volume)(pa_sink *s);      /* dito */
     int (*get_volume)(pa_sink *s);      /* dito */
     int (*get_mute)(pa_sink *s);        /* dito */
@@ -87,6 +86,7 @@ struct pa_sink {
     /* 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;
         int soft_muted;
@@ -96,7 +96,7 @@ struct pa_sink {
 };
 
 PA_DECLARE_CLASS(pa_sink);
-#define PA_SINK(s) ((pa_sink*) (s))
+#define PA_SINK(s) (pa_sink_cast(s))
 
 typedef enum pa_sink_message {
     PA_SINK_MESSAGE_ADD_INPUT,
@@ -106,8 +106,8 @@ typedef enum pa_sink_message {
     PA_SINK_MESSAGE_GET_MUTE,
     PA_SINK_MESSAGE_SET_MUTE,
     PA_SINK_MESSAGE_GET_LATENCY,
-    PA_SINK_MESSAGE_START,
-    PA_SINK_MESSAGE_STOP,
+    PA_SINK_MESSAGE_SET_STATE,
+    PA_SINK_MESSAGE_PING,
     PA_SINK_MESSAGE_MAX
 } pa_sink_message_t;
 
@@ -125,13 +125,19 @@ void pa_sink_disconnect(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);
 
 /* Usable by everyone */
 
 pa_usec_t pa_sink_get_latency(pa_sink *s);
 
-void pa_sink_update_status(pa_sink*s);
-void pa_sink_suspend(pa_sink *s, int suspend);
+int pa_sink_update_status(pa_sink*s);
+int pa_sink_suspend(pa_sink *s, int suspend);
+
+/* 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, const pa_cvolume *volume);
 const pa_cvolume *pa_sink_get_volume(pa_sink *sink);
@@ -139,7 +145,7 @@ void pa_sink_set_mute(pa_sink *sink, int mute);
 int pa_sink_get_mute(pa_sink *sink);
 
 unsigned pa_sink_used_by(pa_sink *s);
-#define pa_sink_get_state(s) ((pa_sink_state_t) pa_atomic_load(&(s)->state))
+#define pa_sink_get_state(s) ((s)->state)
 
 /* To be used exclusively by the sink driver thread */
 
@@ -149,5 +155,5 @@ int pa_sink_render_into(pa_sink*s, pa_memchunk *target);
 void pa_sink_render_into_full(pa_sink *s, pa_memchunk *target);
 
 int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, pa_memchunk *chunk);
-
+    
 #endif
diff --git a/src/pulsecore/sound-file-stream.c b/src/pulsecore/sound-file-stream.c
index a682ee6..974c053 100644
--- a/src/pulsecore/sound-file-stream.c
+++ b/src/pulsecore/sound-file-stream.c
@@ -200,7 +200,7 @@ int pa_play_file(
     u->sink_input->kill = sink_input_kill;
     u->sink_input->userdata = u;
 
-    pa_sink_notify(u->sink_input->sink);
+/*     pa_sink_notify(u->sink_input->sink); */
 
     return 0;
 
diff --git a/src/pulsecore/source-output.c b/src/pulsecore/source-output.c
index 517c033..2211f25 100644
--- a/src/pulsecore/source-output.c
+++ b/src/pulsecore/source-output.c
@@ -38,6 +38,10 @@
 
 #include "source-output.h"
 
+static PA_DEFINE_CHECK_TYPE(pa_source_output, source_output_check_type, pa_msgobject_check_type);
+
+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) {
     pa_assert(data);
 
@@ -126,13 +130,12 @@ pa_source_output* pa_source_output_new(
         data->resample_method = pa_resampler_get_method(resampler);
     }
 
-    o = pa_source_output_new(pa_source_output);
-
+    o = pa_msgobject_new(pa_source_output, source_output_check_type);
     o->parent.parent.free = source_output_free;
     o->parent.process_msg = pa_source_output_process_msg;
 
     o->core = core;
-    pa_atomic_load(&o->state, PA_SOURCE_OUTPUT_RUNNING);
+    pa_atomic_store(&o->state, PA_SOURCE_OUTPUT_RUNNING);
     o->flags = flags;
     o->name = pa_xstrdup(data->name);
     o->driver = pa_xstrdup(data->driver);
@@ -168,27 +171,29 @@ pa_source_output* pa_source_output_new(
 
 void pa_source_output_disconnect(pa_source_output*o) {
     pa_assert(o);
-    pa_return_if_fail(pa_source_output_get_state(i) != PA_SOURCE_OUTPUT_DISCONNECTED);
+    pa_return_if_fail(pa_source_output_get_state(o) != PA_SOURCE_OUTPUT_DISCONNECTED);
     pa_assert(o->source);
     pa_assert(o->source->core);
 
-    pa_asyncmsgq_send(i->sink->asyncmsgq, i->sink, PA_SOURCE_MESSAGE_REMOVE_OUTPUT, o, NULL);
+    pa_asyncmsgq_send(o->source->asyncmsgq, PA_MSGOBJECT(o->source), PA_SOURCE_MESSAGE_REMOVE_OUTPUT, o, NULL);
 
     pa_idxset_remove_by_data(o->source->core->source_outputs, o, NULL);
     pa_idxset_remove_by_data(o->source->outputs, o, NULL);
 
     pa_subscription_post(o->source->core, PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_REMOVE, o->index);
-    o->source = NULL;
 
+    pa_source_update_status(o->source);
+
+    o->source = NULL;
     o->process_msg = NULL;
     o->push = NULL;
     o->kill = NULL;
     o->get_latency = NULL;
 
-    pa_atomic_load(&i->state, PA_SOURCE_OUTPUT_DISCONNECTED);
+    pa_atomic_store(&o->state, PA_SOURCE_OUTPUT_DISCONNECTED);
 }
 
-static void source_output_free(pa_msgobject* mo) {
+static void source_output_free(pa_object* mo) {
     pa_source_output *o = PA_SOURCE_OUTPUT(mo);
 
     pa_assert(pa_source_output_refcnt(o) == 0);
@@ -208,10 +213,10 @@ static void source_output_free(pa_msgobject* mo) {
 void pa_source_output_put(pa_source_output *o) {
     pa_source_output_assert_ref(o);
 
-    pa_asyncmsgq_post(o->source->asyncmsgq, o->source, PA_SOURCE_MESSAGE_ADD_OUTPUT, o, NULL, pa_source_unref, pa_source_output_unref);
+    pa_asyncmsgq_post(o->source->asyncmsgq, PA_MSGOBJECT(o->source), PA_SOURCE_MESSAGE_ADD_OUTPUT, pa_source_output_ref(o), NULL, (pa_free_cb_t) pa_source_output_unref);
     pa_source_update_status(o->source);
 
-    pa_subscription_post(core, PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_NEW, o->index);
+    pa_subscription_post(o->source->core, PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_NEW, o->index);
 }
 
 void pa_source_output_kill(pa_source_output*o) {
@@ -226,7 +231,7 @@ pa_usec_t pa_source_output_get_latency(pa_source_output *o) {
 
     pa_source_output_assert_ref(o);
 
-    if (pa_asyncmsgq_send(o->source->asyncmsgq, i->source, PA_SOURCE_OUTPUT_MESSAGE_GET_LATENCY, &r, NULL) < 0)
+    if (pa_asyncmsgq_send(o->source->asyncmsgq, PA_MSGOBJECT(o), PA_SOURCE_OUTPUT_MESSAGE_GET_LATENCY, &r, NULL) < 0)
         r = 0;
 
     if (o->get_latency)
@@ -250,12 +255,12 @@ void pa_source_output_push(pa_source_output *o, const pa_memchunk *chunk) {
 
     pa_assert(state = PA_SOURCE_OUTPUT_RUNNING);
 
-    if (!o->resampler) {
+    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;
 
@@ -265,7 +270,6 @@ void pa_source_output_push(pa_source_output *o, const pa_memchunk *chunk) {
 }
 
 void pa_source_output_cork(pa_source_output *o, int b) {
-    int n;
     pa_source_output_state_t state;
 
     pa_source_output_assert_ref(o);
@@ -274,23 +278,23 @@ void pa_source_output_cork(pa_source_output *o, int b) {
     pa_assert(state != PA_SOURCE_OUTPUT_DISCONNECTED);
 
     if (b && state != PA_SOURCE_OUTPUT_CORKED)
-        pa_atomic_store(o->state, PA_SOURCE_OUTPUT_CORKED);
+        pa_atomic_store(&o->state, PA_SOURCE_OUTPUT_CORKED);
     else if (!b && state == PA_SOURCE_OUTPUT_CORKED)
-        pa_atomic_cmpxchg(o->state, state, PA_SOURCE_OUTPUT_RUNNING);
+        pa_atomic_cmpxchg(&o->state, state, PA_SOURCE_OUTPUT_RUNNING);
 }
 
 int pa_source_output_set_rate(pa_source_output *o, uint32_t rate) {
     pa_source_output_assert_ref(o);
     pa_return_val_if_fail(o->thread_info.resampler, -1);
 
-    if (i->sample_spec.rate == rate)
+    if (o->sample_spec.rate == rate)
         return 0;
 
-    i->sample_spec.rate = rate;
+    o->sample_spec.rate = rate;
 
-    pa_asyncmsgq_post(s->asyncmsgq, pa_source_output_ref(i), PA_SOURCE_OUTPUT_MESSAGE_SET_RATE, PA_UINT_TO_PTR(rate), NULL, pa_source_output_unref, NULL);
+    pa_asyncmsgq_post(o->source->asyncmsgq, PA_MSGOBJECT(o), PA_SOURCE_OUTPUT_MESSAGE_SET_RATE, PA_UINT_TO_PTR(rate), NULL, NULL);
 
-    pa_subscription_post(o->source->core, PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT!|PA_SUBSCRIPTION_EVENT_CHANGE, i->index);
+    pa_subscription_post(o->source->core, PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_CHANGE, o->index);
     return 0;
 }
 
@@ -316,8 +320,8 @@ 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) {
-    pa_source *origin;
-    pa_resampler *new_resampler = NULL;
+/*     pa_source *origin; */
+/*     pa_resampler *new_resampler = NULL; */
 
     pa_source_output_assert_ref(o);
     pa_source_assert_ref(dest);
@@ -344,7 +348,7 @@ int pa_source_output_move_to(pa_source_output *o, pa_source *dest) {
 /*     else if (!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, */
@@ -376,16 +380,16 @@ int pa_source_output_move_to(pa_source_output *o, pa_source *dest) {
 }
 
 int pa_source_output_process_msg(pa_msgobject *mo, int code, void *userdata, pa_memchunk* chunk) {
-    pa_source_output *o = PA_SOURCE_OUTPUT(o);
+    pa_source_output *o = PA_SOURCE_OUTPUT(mo);
 
-    pa_source_output_assert_ref(i);
+    pa_source_output_assert_ref(o);
 
     switch (code) {
 
         case PA_SOURCE_OUTPUT_MESSAGE_SET_RATE: {
 
-            i->thread_info.sample_spec.rate = PA_PTR_TO_UINT(userdata);
-            pa_resampler_set_output_rate(i->resampler, PA_PTR_TO_UINT(userdata));
+            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;
         }
diff --git a/src/pulsecore/source-output.h b/src/pulsecore/source-output.h
index e7c2c13..d3bc0bc 100644
--- a/src/pulsecore/source-output.h
+++ b/src/pulsecore/source-output.h
@@ -80,7 +80,7 @@ struct pa_source_output {
 };
 
 PA_DECLARE_CLASS(pa_source_output);
-#define PA_SOURCE_OUTPUT(o) ((pa_source_output*) (o))
+#define PA_SOURCE_OUTPUT(o) pa_source_output_cast(o)
 
 enum {
     PA_SOURCE_OUTPUT_MESSAGE_GET_LATENCY,
@@ -129,7 +129,7 @@ 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_set_rate(pa_source_output *o, uint32_t rate);
+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);
 
diff --git a/src/pulsecore/source.c b/src/pulsecore/source.c
index 7d01338..f0a898f 100644
--- a/src/pulsecore/source.c
+++ b/src/pulsecore/source.c
@@ -42,6 +42,10 @@
 
 #include "source.h"
 
+static PA_DEFINE_CHECK_TYPE(pa_source, source_check_type, pa_msgobject_check_type);
+
+static void source_free(pa_object *o);
+
 pa_source* pa_source_new(
         pa_core *core,
         const char *driver,
@@ -69,7 +73,7 @@ pa_source* pa_source_new(
     pa_return_null_if_fail(!driver || pa_utf8_valid(driver));
     pa_return_null_if_fail(pa_utf8_valid(name) && *name);
 
-    s = pa_msgobject_new(pa_source);
+    s = pa_msgobject_new(pa_source, source_check_type);
 
     if (!(name = pa_namereg_register(core, name, PA_NAMEREG_SOURCE, s, fail))) {
         pa_xfree(s);
@@ -80,7 +84,7 @@ pa_source* pa_source_new(
     s->parent.process_msg = pa_source_process_msg;
 
     s->core = core;
-    pa_atomic_store(&s->state, PA_SOURCE_IDLE);
+    s->state = PA_SOURCE_IDLE;
     s->name = pa_xstrdup(name);
     s->description = NULL;
     s->driver = pa_xstrdup(driver);
@@ -94,7 +98,7 @@ pa_source* pa_source_new(
 
     pa_cvolume_reset(&s->volume, spec->channels);
     s->muted = 0;
-    s->refresh_volume = s->refresh_mute = 0;
+    s->refresh_volume = s->refresh_muted = 0;
 
     s->is_hardware = 0;
 
@@ -103,11 +107,10 @@ pa_source* pa_source_new(
     s->get_volume = NULL;
     s->set_mute = NULL;
     s->get_mute = NULL;
-    s->start = NULL;
-    s->stop = NULL;
+    s->set_state = NULL;
     s->userdata = NULL;
 
-    pa_assert_se(s->asyncmsgq = pa_asyncmsgq_new(0));
+    s->asyncmsgq = NULL;
 
     r = pa_idxset_put(core->sources, s, &s->index);
     assert(s->index != PA_IDXSET_INVALID && r >= 0);
@@ -118,56 +121,40 @@ pa_source* pa_source_new(
     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;
 
     pa_subscription_post(core, PA_SUBSCRIPTION_EVENT_SOURCE | PA_SUBSCRIPTION_EVENT_NEW, s->index);
 
     return s;
 }
 
-static void source_start(pa_source *s) {
-    pa_source_state_t state;
+static int source_set_state(pa_source *s, pa_source_state_t state) {
+    int ret;
+    
     pa_assert(s);
 
-    state = pa_source_get_state(s);
-    pa_return_if_fail(state == PA_SOURCE_IDLE || state == PA_SOURCE_SUSPENDED);
-
-    pa_atomic_store(&s->state, PA_SOURCE_RUNNING);
-
-    if (s->start)
-        s->start(s);
-    else
-        pa_asyncmsgq_post(s->asyncmsgq, s, PA_SOURCE_MESSAGE_START, NULL, NULL, pa_source_unref, NULL);
-}
-
-static void source_stop(pa_source *s) {
-    pa_source_state_t state;
-    int stop;
+    if (s->state == state)
+        return 0;
 
-    pa_assert(s);
-    state = pa_source_get_state(s);
-    pa_return_if_fail(state == PA_SOURCE_RUNNING || state == PA_SOURCE_SUSPENDED);
+    if (s->set_state)
+        if ((ret = s->set_state(s, state)) < 0)
+            return -1;
 
-    stop = state == PA_SOURCE_RUNNING;
-    pa_atomic_store(&s->state, PA_SOURCE_IDLE);
+    if (pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_SET_STATE, PA_UINT_TO_PTR(state), NULL) < 0)
+        return -1;
 
-    if (stop) {
-        if (s->stop)
-            s->stop(s);
-        else
-            pa_asyncmsgq_post(s->asyncmsgq, s, PA_SOURCE_MESSAGE_STOP, NULL, NULL, pa_source_unref, NULL);
-    }
+    s->state = state;
+    return 0;
 }
 
 void pa_source_disconnect(pa_source *s) {
     pa_source_output *o, *j = NULL;
 
     pa_assert(s);
-    pa_return_if_fail(pa_sink_get_state(s) != PA_SINK_DISCONNECT);
-
-    source_stop(s);
+    pa_return_if_fail(s->state != PA_SOURCE_DISCONNECTED);
 
-    pa_atomic_store(&s->state, PA_SOURCE_DISCONNECTED);
     pa_namereg_unregister(s->core, s->name);
+    pa_idxset_remove_by_data(s->core->sources, s, NULL);
 
     pa_hook_fire(&s->core->hook_source_disconnect, s);
 
@@ -177,33 +164,36 @@ void pa_source_disconnect(pa_source *s) {
         j = o;
     }
 
-    pa_idxset_remove_by_data(s->core->sources, s, NULL);
+    source_set_state(s, PA_SOURCE_DISCONNECTED);
 
     s->get_latency = NULL;
     s->get_volume = NULL;
     s->set_volume = NULL;
     s->set_mute = NULL;
     s->get_mute = NULL;
-    s->start = NULL;
-    s->stop = NULL;
+    s->set_state = NULL;
 
     pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE | PA_SUBSCRIPTION_EVENT_REMOVE, s->index);
 }
 
-static void source_free(pa_msgobject *o) {
+static void source_free(pa_object *o) {
+    pa_source_output *so;
     pa_source *s = PA_SOURCE(o);
 
     pa_assert(s);
     pa_assert(pa_source_refcnt(s) == 0);
 
-    pa_source_disconnect(s);
+    if (s->state != PA_SOURCE_DISCONNECTED)
+        pa_source_disconnect(s);
 
     pa_log_info("Freeing source %u \"%s\"", s->index, s->name);
 
     pa_idxset_free(s->outputs, NULL, NULL);
-    pa_hashmap_free(s->thread_info.outputs, pa_sink_output_unref, NULL);
 
-    pa_asyncmsgq_free(s->asyncmsgq);
+    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);
@@ -211,44 +201,28 @@ static void source_free(pa_msgobject *o) {
     pa_xfree(s);
 }
 
-void pa_source_update_status(pa_source*s) {
+int pa_source_update_status(pa_source*s) {
     pa_source_assert_ref(s);
 
-    if (pa_source_get_state(s) == PA_SOURCE_STATE_SUSPENDED)
-        return;
+    if (s->state == PA_SOURCE_SUSPENDED)
+        return 0;
 
-    if (pa_source_used_by(s) > 0)
-        source_start(s);
-    else
-        source_stop(s);
+    return source_set_state(s, pa_source_used_by(s) ? PA_SOURCE_RUNNING : PA_SOURCE_IDLE);
 }
 
-void pa_source_suspend(pa_source *s, int suspend) {
-    pa_source_state_t state;
-
+int pa_source_suspend(pa_source *s, int suspend) {
     pa_source_assert_ref(s);
 
-    state = pa_source_get_state(s);
-    pa_return_if_fail(suspend && (s->state == PA_SOURCE_RUNNING || s->state == PA_SOURCE_IDLE));
-    pa_return_if_fail(!suspend && (s->state == PA_SOURCE_SUSPENDED));
-
-
-    if (suspend) {
-        pa_atomic_store(&s->state, PA_SOURCE_SUSPENDED);
-
-        if (s->stop)
-            s->stop(s);
-        else
-            pa_asyncmsgq_post(s->asyncmsgq, s, PA_SOURCE_MESSAGE_STOP, NULL, NULL, pa_source_unref, NULL);
+    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);
+}
 
-    } else {
-        pa_atomic_store(&s->state, PA_SOURCE_RUNNING);
+void pa_source_ping(pa_source *s) {
+    pa_source_assert_ref(s);
 
-        if (s->start)
-            s->start(s);
-        else
-            pa_asyncmsgq_post(s->asyncmsgq, s, PA_SOURCE_MESSAGE_START, NULL, NULL, pa_source_unref, NULL);
-    }
+    pa_asyncmsgq_post(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_PING, NULL, NULL, NULL);
 }
 
 void pa_source_post(pa_source*s, const pa_memchunk *chunk) {
@@ -258,16 +232,16 @@ void pa_source_post(pa_source*s, const pa_memchunk *chunk) {
     pa_source_assert_ref(s);
     pa_assert(chunk);
 
-    if (s->sw_muted || !pa_cvolume_is_norm(&s->sw_volume)) {
+    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->thread_info.muted || pa_cvolume_is_muted(s->thread_info.volume))
+        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->thread_info.volume);
+            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);
@@ -289,32 +263,33 @@ pa_usec_t pa_source_get_latency(pa_source *s) {
     if (s->get_latency)
         return s->get_latency(s);
 
-    if (pa_asyncmsgq_send(s->asyncmsgq, s, PA_SOURCE_MESSAGE_GET_LATENCY, &usec, NULL) < 0)
+    if (pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_GET_LATENCY, &usec, NULL) < 0)
         return 0;
 
     return usec;
 }
 
 void pa_source_set_volume(pa_source *s, const pa_cvolume *volume) {
-    pa_cvolume *v;
+    int changed;
 
     pa_source_assert_ref(s);
     pa_assert(volume);
 
-    changed = !pa_cvolume_equal(volume, s->volume);
+    changed = !pa_cvolume_equal(volume, &s->volume);
     s->volume = *volume;
 
     if (s->set_volume && s->set_volume(s) < 0)
         s->set_volume = NULL;
 
     if (!s->set_volume)
-        pa_asyncmsgq_post(s->asyncmsgq, pa_source_ref(s), PA_SOURCE_MESSAGE_SET_VOLUME, pa_xnewdup(struct pa_cvolume, volume, 1), pa_source_unref, pa_xfree);
+        pa_asyncmsgq_post(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_SET_VOLUME, pa_xnewdup(struct pa_cvolume, volume, 1), NULL, pa_xfree);
 
     if (changed)
         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);
 
     old_volume = s->volume;
@@ -323,7 +298,7 @@ const pa_cvolume *pa_source_get_volume(pa_source *s) {
         s->get_volume = NULL;
 
     if (!s->get_volume && s->refresh_volume)
-        pa_asyncmsgq_send(s->asyncmsgq, s, PA_SOURCE_MESSAGE_GET_VOLUME, &s->volume);
+        pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_GET_VOLUME, &s->volume, NULL);
 
     if (!pa_cvolume_equal(&old_volume, &s->volume))
         pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
@@ -331,7 +306,7 @@ const pa_cvolume *pa_source_get_volume(pa_source *s) {
     return &s->volume;
 }
 
-void pa_source_set_mute(pa_source *s, pa_mixer_t m, int mute) {
+void pa_source_set_mute(pa_source *s, int mute) {
     int changed;
 
     pa_source_assert_ref(s);
@@ -342,13 +317,13 @@ void pa_source_set_mute(pa_source *s, pa_mixer_t m, int mute) {
         s->set_mute = NULL;
 
     if (!s->set_mute)
-        pa_asyncmsgq_post(s->asyncmsgq, pa_source_ref(s), PA_SOURCE_MESSAGE_SET_MUTE, PA_UINT_TO_PTR(mute), pa_source_unref, NULL);
+        pa_asyncmsgq_post(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_SET_MUTE, PA_UINT_TO_PTR(mute), NULL, NULL);
 
     if (changed)
         pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
 }
 
-int pa_source_get_mute(pa_source *s, pa_mixer_t m) {
+int pa_source_get_mute(pa_source *s) {
     int old_muted;
 
     pa_source_assert_ref(s);
@@ -358,8 +333,8 @@ int pa_source_get_mute(pa_source *s, pa_mixer_t m) {
     if (s->get_mute && s->get_mute(s) < 0)
         s->get_mute = NULL;
 
-    if (!s->get_mute && s->refresh_mute)
-        pa_asyncmsgq_send(s->asyncmsgq, s, PA_SOURCE_MESSAGE_GET_MUTE, &s->muted);
+    if (!s->get_mute && s->refresh_muted)
+        pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_GET_MUTE, &s->muted, NULL);
 
     if (old_muted != s->muted)
         pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
@@ -393,26 +368,33 @@ void pa_source_set_description(pa_source *s, const char *description) {
     pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
 }
 
+void pa_source_set_asyncmsgq(pa_source *s, pa_asyncmsgq *q) {
+    pa_source_assert_ref(s);
+    pa_assert(q);
+
+    s->asyncmsgq = q;
+}
+
 unsigned pa_source_used_by(pa_source *s) {
     pa_source_assert_ref(s);
 
     return pa_idxset_size(s->outputs);
 }
 
-int pa_source_process_msg(pa_msgobject *o, void *object, int code, pa_memchunk *chunk, void *userdata) {
+int pa_source_process_msg(pa_msgobject *o, int code, void *userdata, pa_memchunk *chunk) {
     pa_source *s = PA_SOURCE(o);
     pa_source_assert_ref(s);
 
-    switch (code) {
+    switch ((pa_source_message_t) code) {
         case PA_SOURCE_MESSAGE_ADD_OUTPUT: {
             pa_source_output *i = userdata;
             pa_hashmap_put(s->thread_info.outputs, PA_UINT32_TO_PTR(i->index), pa_source_output_ref(i));
             return 0;
         }
 
-        case PA_SOURCE_MESSAGE_REMOVE_INPUT: {
-            pa_source_input *i = userdata;
-            pa_hashmap_remove(s->thread_info.outputs, PA_UINT32_TO_PTR(i->index), pa_source_output_ref(i));
+        case PA_SOURCE_MESSAGE_REMOVE_OUTPUT: {
+            pa_source_output *i = userdata;
+            pa_hashmap_remove(s->thread_info.outputs, PA_UINT32_TO_PTR(i->index));
             return 0;
         }
 
@@ -432,7 +414,17 @@ int pa_source_process_msg(pa_msgobject *o, void *object, int code, pa_memchunk *
             *((int*) userdata) = s->thread_info.soft_muted;
             return 0;
 
-        default:
-            return -1;
+        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_GET_LATENCY:
+        case PA_SOURCE_MESSAGE_MAX:
+            ;
     }
+
+    return -1;
 }
diff --git a/src/pulsecore/source.h b/src/pulsecore/source.h
index b41b1bc..4db2ded 100644
--- a/src/pulsecore/source.h
+++ b/src/pulsecore/source.h
@@ -57,7 +57,7 @@ struct pa_source {
 
     uint32_t index;
     pa_core *core;
-    pa_atomic_t state;
+    pa_source_state_t state;
 
     char *name;
     char *description, *driver;              /* may be NULL */
@@ -74,10 +74,9 @@ struct pa_source {
     pa_cvolume volume;
     int muted;
     int refresh_volume;
-    int referesh_mute;
+    int refresh_muted;
 
-    void (*start)(pa_source*source);         /* may be NULL */
-    void (*stop)(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 */
@@ -87,6 +86,7 @@ struct pa_source {
     pa_asyncmsgq *asyncmsgq;
 
     struct {
+        pa_source_state_t state;
         pa_hashmap *outputs;
         pa_cvolume soft_volume;
         int soft_muted;
@@ -96,7 +96,7 @@ struct pa_source {
 };
 
 PA_DECLARE_CLASS(pa_source);
-#define PA_SOURCE(s) ((pa_source*) (s))
+#define PA_SOURCE(s) pa_source_cast(s)
 
 typedef enum pa_source_message {
     PA_SOURCE_MESSAGE_ADD_OUTPUT,
@@ -106,8 +106,8 @@ typedef enum pa_source_message {
     PA_SOURCE_MESSAGE_GET_MUTE,
     PA_SOURCE_MESSAGE_SET_MUTE,
     PA_SOURCE_MESSAGE_GET_LATENCY,
-    PA_SOURCE_MESSAGE_START,
-    PA_SOURCE_MESSAGE_STOP,
+    PA_SOURCE_MESSAGE_SET_STATE,
+    PA_SOURCE_MESSAGE_PING,
     PA_SOURCE_MESSAGE_MAX
 } pa_source_message_t;
 
@@ -125,13 +125,15 @@ void pa_source_disconnect(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);
 
 /* Callable by everyone */
 
 pa_usec_t pa_source_get_latency(pa_source *s);
 
-void pa_source_update_status(pa_source*s);
-void pa_source_suspend(pa_source *s);
+int pa_source_update_status(pa_source*s);
+int pa_source_suspend(pa_source *s, int suspend);
+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);
@@ -139,11 +141,11 @@ void pa_source_set_mute(pa_source *source, int mute);
 int pa_source_get_mute(pa_source *source);
 
 unsigned pa_source_used_by(pa_source *s);
-#define pa_source_get_state(s) ((pa_source_state_t) pa_atomic_load(&(s)->state))
+#define pa_source_get_state(s) ((pa_source_state_t) (s)->state)
 
 /* To be used exclusively by the source driver thread */
 
 void pa_source_post(pa_source*s, const pa_memchunk *b);
-void pa_source_process_msg(pa_msgobject *o, int code, void *userdata, pa_memchunk *chunk);
+int pa_source_process_msg(pa_msgobject *o, int code, void *userdata, pa_memchunk *chunk);
 
 #endif
diff --git a/src/tests/asyncmsgq-test.c b/src/tests/asyncmsgq-test.c
index d10b512..847d5be 100644
--- a/src/tests/asyncmsgq-test.c
+++ b/src/tests/asyncmsgq-test.c
@@ -49,7 +49,7 @@ static void the_thread(void *_q) {
     do {
         int code = 0;
 
-        pa_assert_se(pa_asyncmsgq_get(q, NULL, &code, NULL, 1) == 0);
+        pa_assert_se(pa_asyncmsgq_get(q, NULL, &code, NULL, NULL, 1) == 0);
 
         switch (code) {
 
@@ -71,7 +71,7 @@ static void the_thread(void *_q) {
                 break;
         }
 
-        pa_asyncmsgq_done(q);
+        pa_asyncmsgq_done(q, 0);
 
     } while (!quit);
 }
@@ -91,11 +91,11 @@ int main(int argc, char *argv[]) {
 
     printf("Operation B post\n");
     pa_asyncmsgq_post(q, NULL, OPERATION_B, NULL, NULL, NULL);
-
+    
     pa_thread_yield();
 
     printf("Operation C send\n");
-    pa_asyncmsgq_send(q, NULL, OPERATION_C, NULL);
+    pa_asyncmsgq_send(q, NULL, OPERATION_C, NULL, NULL);
 
     pa_thread_yield();
 

commit 111dcd5e34434324adafd9f43c656592f3a02d60
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Jun 14 16:53:40 2007 +0000

    trivial cleanups
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1475 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-pipe-sink.c b/src/modules/module-pipe-sink.c
index da9124a..216e42a 100644
--- a/src/modules/module-pipe-sink.c
+++ b/src/modules/module-pipe-sink.c
@@ -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>
@@ -40,7 +39,6 @@
 #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>
@@ -170,6 +168,8 @@ static void thread_func(void *userdata) {
                 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)
@@ -202,7 +202,10 @@ static void thread_func(void *userdata) {
         if (pa_asyncmsgq_before_poll(u->asyncmsgq) < 0)
             continue;
 
+/*         pa_log("polling for %u (underrun=%i)", pollfd[POLLFD_FIFO].events, underrun);  */
         r = poll(pollfd, POLLFD_MAX, -1);
+/*         pa_log("polling got %u", r > 0 ? pollfd[POLLFD_FIFO].revents : 0);  */
+
         pa_asyncmsgq_after_poll(u->asyncmsgq);
 
         if (r < 0) {
@@ -232,11 +235,11 @@ finish:
 }
 
 int pa__init(pa_core *c, pa_module*m) {
-    struct userdata *u = NULL;
+    struct userdata *u;
     struct stat st;
     pa_sample_spec ss;
     pa_channel_map map;
-    pa_modargs *ma = NULL;
+    pa_modargs *ma;
     char *t;
 
     pa_assert(c);

commit 1b99fd2fc4c80ab581b08e1fb03ed8543dc763ec
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Jun 14 17:01:01 2007 +0000

    Move a few things between the threads
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1476 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/protocol-simple.c b/src/pulsecore/protocol-simple.c
index 67741bd..288c1c0 100644
--- a/src/pulsecore/protocol-simple.c
+++ b/src/pulsecore/protocol-simple.c
@@ -88,6 +88,7 @@ struct pa_protocol_simple {
 
 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 {
@@ -189,7 +190,7 @@ static int do_read(connection *c) {
 
     c->playback.memblock_index += r;
 
-    pa_asyncmsgq_post(c->protocol->core->asyncmsgq, PA_MSGOBJECT(c->sink_input), SINK_INPUT_MESSAGE_POST_DATA, NULL, &chunk, NULL);
+    pa_asyncmsgq_post(c->sink_input->sink->asyncmsgq, PA_MSGOBJECT(c->sink_input), SINK_INPUT_MESSAGE_POST_DATA, NULL, &chunk, NULL);
 
     return 0;
 }
@@ -259,7 +260,7 @@ fail:
         pa_iochannel_free(c->io);
         c->io = NULL;
 
-        pa_memblockq_prebuf_disable(c->input_memblockq);
+        pa_asyncmsgq_post(c->sink_input->sink->asyncmsgq, PA_MSGOBJECT(c->sink_input), SINK_INPUT_MESSAGE_DISABLE_PREBUF, NULL, NULL, NULL);
     } else
         connection_drop(c);
 }
@@ -282,7 +283,6 @@ static int connection_process_msg(pa_msgobject *o, int code, void*userdata, pa_m
         case MESSAGE_DROP_CONNECTION:
             connection_drop(c);
             break;
-
     }
 
     return 0;
@@ -307,10 +307,17 @@ static int sink_input_process_msg(pa_msgobject *o, int code, void *userdata, pa_
             /* New data from the main loop */
             pa_memblockq_push_align(c->input_memblockq, chunk);
             pa_atomic_store(&c->playback.missing, pa_memblockq_missing(c->input_memblockq));
+
+/*             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;
 
@@ -337,6 +344,8 @@ static int sink_input_peek_cb(pa_sink_input *i, pa_memchunk *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(c->protocol->core->asyncmsgq, PA_MSGOBJECT(c), MESSAGE_DROP_CONNECTION, c, NULL, NULL);
 

commit 260dd1e886dcc99147c48293c67b1910374b76ad
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Jun 14 17:06:11 2007 +0000

    Make debug message more useful
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1477 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/asyncmsgq.c b/src/pulsecore/asyncmsgq.c
index 6becb62..a46f038 100644
--- a/src/pulsecore/asyncmsgq.c
+++ b/src/pulsecore/asyncmsgq.c
@@ -164,7 +164,7 @@ int pa_asyncmsgq_get(pa_asyncmsgq *a, pa_msgobject **object, int *code, void **u
     if (chunk)
         *chunk = a->current->memchunk;
 
-    pa_log_debug("q=%p object=%p code=%i data=%p", a, a->current->object, a->current->code, a->current->userdata);
+    pa_log_debug("q=%p object=%p (%s) code=%i data=%p", (void*) a, (void*) a->current->object, a->current->object ? a->current->object->parent.type_name : NULL, a->current->code, (void*) a->current->userdata);
     
     return 0;
 }

commit 5e72ac353ed6f81ee1efc1691f725a2c8d67ac40
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Jun 14 17:12:40 2007 +0000

    rework sink input/source output state machine
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1478 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c
index 2c6b356..d27f00f 100644
--- a/src/pulsecore/sink-input.c
+++ b/src/pulsecore/sink-input.c
@@ -166,7 +166,7 @@ pa_sink_input* pa_sink_input_new(
     i->parent.process_msg = pa_sink_input_process_msg;
 
     i->core = core;
-    pa_atomic_store(&i->state, PA_SINK_INPUT_DRAINED);
+    i->state = PA_SINK_INPUT_RUNNING;
     i->flags = flags;
     i->name = pa_xstrdup(data->name);
     i->driver = pa_xstrdup(data->driver);
@@ -181,7 +181,6 @@ pa_sink_input* pa_sink_input_new(
     i->volume = data->volume;
     i->muted = data->muted;
 
-    i->process_msg = NULL;
     i->peek = NULL;
     i->drop = NULL;
     i->kill = NULL;
@@ -189,6 +188,9 @@ pa_sink_input* pa_sink_input_new(
     i->underrun = NULL;
     i->userdata = NULL;
 
+    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);
@@ -210,28 +212,41 @@ pa_sink_input* pa_sink_input_new(
     return i;
 }
 
+static int sink_input_set_state(pa_sink_input *i, pa_sink_input_state_t state) {
+    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), NULL) < 0)
+        return -1;
+
+    i->state = state;
+    return 0;
+}
+
 void pa_sink_input_disconnect(pa_sink_input *i) {
     pa_assert(i);
-    pa_return_if_fail(pa_sink_input_get_state(i) != PA_SINK_INPUT_DISCONNECTED);
+    pa_return_if_fail(i->state != PA_SINK_INPUT_DISCONNECTED);
 
     pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i->sink), PA_SINK_MESSAGE_REMOVE_INPUT, i, NULL);
-
     pa_idxset_remove_by_data(i->sink->core->sink_inputs, i, NULL);
     pa_idxset_remove_by_data(i->sink->inputs, i, NULL);
 
     pa_subscription_post(i->sink->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_REMOVE, i->index);
 
+    sink_input_set_state(i, PA_SINK_INPUT_DISCONNECTED);
     pa_sink_update_status(i->sink);
-
+    
     i->sink = NULL;
-    i->process_msg = NULL;
     i->peek = NULL;
     i->drop = NULL;
     i->kill = NULL;
     i->get_latency = NULL;
     i->underrun = NULL;
-
-    pa_atomic_store(&i->state, PA_SINK_INPUT_DISCONNECTED);
 }
 
 static void sink_input_free(pa_object *o) {
@@ -240,7 +255,8 @@ static void sink_input_free(pa_object *o) {
     pa_assert(i);
     pa_assert(pa_sink_input_refcnt(i) == 0);
 
-    pa_sink_input_disconnect(i);
+    if (i->state != PA_SINK_INPUT_DISCONNECTED)
+        pa_sink_input_disconnect(i);
 
     pa_log_info("Freeing output %u \"%s\"", i->index, i->name);
 
@@ -295,21 +311,15 @@ int pa_sink_input_peek(pa_sink_input *i, pa_memchunk *chunk, pa_cvolume *volume)
     int ret = -1;
     int do_volume_adj_here;
     int volume_is_norm;
-    pa_sink_input_state_t state;
 
     pa_sink_input_assert_ref(i);
     pa_assert(chunk);
     pa_assert(volume);
 
-    state = pa_sink_input_get_state(i);
-
-    if (state == PA_SINK_INPUT_DISCONNECTED)
-        return -1;
-
-    if (!i->peek || !i->drop || state == PA_SINK_INPUT_CORKED)
+    if (!i->peek || !i->drop || i->thread_info.state == PA_SINK_INPUT_DISCONNECTED || i->thread_info.state == PA_SINK_INPUT_CORKED)
         goto finish;
 
-    pa_assert(state == PA_SINK_INPUT_RUNNING || 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->thread_info.move_silence > 0) { */
 /*         size_t l; */
@@ -359,7 +369,7 @@ int pa_sink_input_peek(pa_sink_input *i, pa_memchunk *chunk, pa_cvolume *volume)
         /* 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->thread_info.volume);
+            pa_volume_memchunk(&tchunk, &i->thread_info.sample_spec, &i->thread_info.volume);
         }
 
         pa_resampler_run(i->thread_info.resampler, &tchunk, &i->thread_info.resampled_chunk);
@@ -376,13 +386,13 @@ int pa_sink_input_peek(pa_sink_input *i, pa_memchunk *chunk, pa_cvolume *volume)
 
 finish:
 
-    if (ret < 0 && state == PA_SINK_INPUT_RUNNING && i->underrun)
+    if (ret < 0 && !pa_atomic_load(&i->thread_info.drained) && i->underrun)
         i->underrun(i);
 
     if (ret >= 0)
-        pa_atomic_cmpxchg(&i->state, state, PA_SINK_INPUT_RUNNING);
-    else if (ret < 0 && state == PA_SINK_INPUT_RUNNING)
-        pa_atomic_cmpxchg(&i->state, 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
@@ -487,17 +497,9 @@ int pa_sink_input_get_mute(pa_sink_input *i) {
 }
 
 void pa_sink_input_cork(pa_sink_input *i, int b) {
-    pa_sink_input_state_t state;
-
     pa_sink_input_assert_ref(i);
 
-    state = pa_sink_input_get_state(i);
-    pa_assert(state != PA_SINK_INPUT_DISCONNECTED);
-
-    if (b && state != PA_SINK_INPUT_CORKED)
-        pa_atomic_store(&i->state, PA_SINK_INPUT_CORKED);
-    else if (!b && state == PA_SINK_INPUT_CORKED)
-        pa_atomic_cmpxchg(&i->state, state, PA_SINK_INPUT_DRAINED);
+    sink_input_set_state(i, b ? PA_SINK_INPUT_CORKED : PA_SINK_INPUT_RUNNING);
 }
 
 int pa_sink_input_set_rate(pa_sink_input *i, uint32_t rate) {
@@ -730,7 +732,26 @@ int pa_sink_input_process_msg(pa_msgobject *o, int code, void *userdata, pa_memc
 
             return 0;
         }
+
+        case PA_SINK_INPUT_MESSAGE_SET_STATE: {
+            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);
+
+            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;
+}
diff --git a/src/pulsecore/sink-input.h b/src/pulsecore/sink-input.h
index a8c05b8..426e48c 100644
--- a/src/pulsecore/sink-input.h
+++ b/src/pulsecore/sink-input.h
@@ -39,8 +39,8 @@ 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_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_state_t;
@@ -55,7 +55,11 @@ struct pa_sink_input {
 
     uint32_t index;
     pa_core *core;
-    pa_atomic_t state;
+
+    /* 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;
 
     char *name, *driver;                /* may be NULL */
@@ -70,7 +74,6 @@ struct pa_sink_input {
     pa_cvolume volume;
     int muted;
 
-    int (*process_msg)(pa_sink_input *i, int code, void *userdata);
     int (*peek) (pa_sink_input *i, pa_memchunk *chunk);
     void (*drop) (pa_sink_input *i, const pa_memchunk *chunk, size_t length);
     void (*kill) (pa_sink_input *i);             /* may be NULL */
@@ -80,6 +83,9 @@ struct pa_sink_input {
     pa_resample_method_t resample_method;
 
     struct {
+        pa_sink_input_state_t state;
+        pa_atomic_t drained;
+        
         pa_sample_spec sample_spec;
 
         pa_memchunk resampled_chunk;
@@ -106,6 +112,7 @@ enum {
     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
 };
 
@@ -166,7 +173,7 @@ 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);
 
-#define pa_sink_input_get_state(i) ((pa_sink_input_state_t) pa_atomic_load(&i->state))
+pa_sink_input_state_t pa_sink_input_get_state(pa_sink_input *i);
 
 /* To be used exclusively by the sink driver thread */
 
diff --git a/src/pulsecore/source-output.c b/src/pulsecore/source-output.c
index 2211f25..1b93c06 100644
--- a/src/pulsecore/source-output.c
+++ b/src/pulsecore/source-output.c
@@ -135,7 +135,7 @@ pa_source_output* pa_source_output_new(
     o->parent.process_msg = pa_source_output_process_msg;
 
     o->core = core;
-    pa_atomic_store(&o->state, PA_SOURCE_OUTPUT_RUNNING);
+    o->state = PA_SOURCE_OUTPUT_RUNNING;
     o->flags = flags;
     o->name = pa_xstrdup(data->name);
     o->driver = pa_xstrdup(data->driver);
@@ -147,12 +147,13 @@ pa_source_output* pa_source_output_new(
     o->sample_spec = data->sample_spec;
     o->channel_map = data->channel_map;
 
-    o->process_msg = NULL;
     o->push = NULL;
     o->kill = NULL;
     o->get_latency = NULL;
     o->userdata = NULL;
 
+    o->thread_info.state = o->state;
+    o->thread_info.sample_spec = o->sample_spec;
     o->thread_info.resampler = resampler;
 
     pa_assert_se(pa_idxset_put(core->source_outputs, o, &o->index) == 0);
@@ -169,11 +170,22 @@ pa_source_output* pa_source_output_new(
     return o;
 }
 
+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), NULL) < 0)
+        return -1;
+
+    o->state = state;
+    return 0;
+}
+
 void pa_source_output_disconnect(pa_source_output*o) {
     pa_assert(o);
-    pa_return_if_fail(pa_source_output_get_state(o) != PA_SOURCE_OUTPUT_DISCONNECTED);
-    pa_assert(o->source);
-    pa_assert(o->source->core);
+    pa_return_if_fail(o->state != PA_SOURCE_OUTPUT_DISCONNECTED);
 
     pa_asyncmsgq_send(o->source->asyncmsgq, PA_MSGOBJECT(o->source), PA_SOURCE_MESSAGE_REMOVE_OUTPUT, o, NULL);
 
@@ -182,15 +194,13 @@ void pa_source_output_disconnect(pa_source_output*o) {
 
     pa_subscription_post(o->source->core, PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_REMOVE, o->index);
 
+    source_output_set_state(o, PA_SOURCE_OUTPUT_DISCONNECTED);
     pa_source_update_status(o->source);
 
     o->source = NULL;
-    o->process_msg = NULL;
     o->push = NULL;
     o->kill = NULL;
     o->get_latency = NULL;
-
-    pa_atomic_store(&o->state, PA_SOURCE_OUTPUT_DISCONNECTED);
 }
 
 static void source_output_free(pa_object* mo) {
@@ -198,7 +208,8 @@ static void source_output_free(pa_object* mo) {
 
     pa_assert(pa_source_output_refcnt(o) == 0);
 
-    pa_source_output_disconnect(o);
+    if (o->state != PA_SOURCE_OUTPUT_DISCONNECTED)
+        pa_source_output_disconnect(o);
 
     pa_log_info("Freeing output %u \"%s\"", o->index, o->name);
 
@@ -242,18 +253,15 @@ pa_usec_t pa_source_output_get_latency(pa_source_output *o) {
 
 void pa_source_output_push(pa_source_output *o, const pa_memchunk *chunk) {
     pa_memchunk rchunk;
-    pa_source_output_state_t state;
 
     pa_source_output_assert_ref(o);
     pa_assert(chunk);
     pa_assert(chunk->length);
 
-    state = pa_source_output_get_state(o);
-
-    if (!o->push || state == PA_SOURCE_OUTPUT_DISCONNECTED || state == PA_SOURCE_OUTPUT_CORKED)
+    if (!o->push || o->state == PA_SOURCE_OUTPUT_DISCONNECTED || o->state == PA_SOURCE_OUTPUT_CORKED)
         return;
 
-    pa_assert(state = PA_SOURCE_OUTPUT_RUNNING);
+    pa_assert(o->state = PA_SOURCE_OUTPUT_RUNNING);
 
     if (!o->thread_info.resampler) {
         o->push(o, chunk);
@@ -270,17 +278,9 @@ void pa_source_output_push(pa_source_output *o, const pa_memchunk *chunk) {
 }
 
 void pa_source_output_cork(pa_source_output *o, int b) {
-    pa_source_output_state_t state;
-
     pa_source_output_assert_ref(o);
 
-    state = pa_source_output_get_state(o);
-    pa_assert(state != PA_SOURCE_OUTPUT_DISCONNECTED);
-
-    if (b && state != PA_SOURCE_OUTPUT_CORKED)
-        pa_atomic_store(&o->state, PA_SOURCE_OUTPUT_CORKED);
-    else if (!b && state == PA_SOURCE_OUTPUT_CORKED)
-        pa_atomic_cmpxchg(&o->state, state, PA_SOURCE_OUTPUT_RUNNING);
+    source_output_set_state(o, b ? PA_SOURCE_OUTPUT_CORKED : PA_SOURCE_OUTPUT_RUNNING);
 }
 
 int pa_source_output_set_rate(pa_source_output *o, uint32_t rate) {
@@ -393,6 +393,13 @@ int pa_source_output_process_msg(pa_msgobject *mo, int code, void *userdata, pa_
 
             return 0;
         }
+
+        case PA_SOURCE_OUTPUT_MESSAGE_SET_STATE: {
+            o->thread_info.state = PA_PTR_TO_UINT(userdata);
+
+            return 0;
+        }
+            
     }
 
     return -1;
diff --git a/src/pulsecore/source-output.h b/src/pulsecore/source-output.h
index d3bc0bc..7b6afe8 100644
--- a/src/pulsecore/source-output.h
+++ b/src/pulsecore/source-output.h
@@ -51,7 +51,7 @@ struct pa_source_output {
 
     uint32_t index;
     pa_core *core;
-    pa_atomic_t state;
+    pa_source_output_state_t state;
     pa_source_output_flags_t flags;
 
     char *name, *driver;                  /* may be NULL */
@@ -63,7 +63,6 @@ struct pa_source_output {
     pa_sample_spec sample_spec;
     pa_channel_map channel_map;
 
-    int (*process_msg)(pa_sink_input *i, int code, void *userdata);
     void (*push)(pa_source_output *o, const pa_memchunk *chunk);
     void (*kill)(pa_source_output* o);              /* may be NULL */
     pa_usec_t (*get_latency) (pa_source_output *o); /* may be NULL */
@@ -71,6 +70,8 @@ struct pa_source_output {
     pa_resample_method_t resample_method;
 
     struct {
+        pa_source_output_state_t state;
+        
         pa_sample_spec sample_spec;
 
         pa_resampler* resampler;              /* may be NULL */
@@ -85,6 +86,7 @@ PA_DECLARE_CLASS(pa_source_output);
 enum {
     PA_SOURCE_OUTPUT_MESSAGE_GET_LATENCY,
     PA_SOURCE_OUTPUT_MESSAGE_SET_RATE,
+    PA_SOURCE_OUTPUT_MESSAGE_SET_STATE,
     PA_SOURCE_OUTPUT_MESSAGE_MAX
 };
 
@@ -135,7 +137,7 @@ 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) ((pa_source_output_state_t) pa_atomic_load(&o->state))
+#define pa_source_output_get_state(o) ((o)->state)
 
 /* To be used exclusively by the source driver thread */
 

commit 572c77f41822be193db603dd3c2d6f0f3ca9fa92
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Jun 14 18:48:40 2007 +0000

    Remove anotify.[ch], since it is now entirely replaced by pa_asyncmsgq
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1479 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/anotify.c b/src/pulsecore/anotify.c
deleted file mode 100644
index 25c5fe7..0000000
--- a/src/pulsecore/anotify.c
+++ /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/anotify.h b/src/pulsecore/anotify.h
deleted file mode 100644
index b3f75b7..0000000
--- a/src/pulsecore/anotify.h
+++ /dev/null
@@ -1,40 +0,0 @@
-#ifndef foopulseanotifyhfoo
-#define foopulseanotifyhfoo
-
-/* $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.
-***/
-
-/* Asynchronous thread-safe notification of mainloops */
-
-
-#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);
-
-#endif

commit 1c62ce6f860804cfb87aaef591d48f07dc36bbd2
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Jun 14 20:11:46 2007 +0000

    Fix a nasty typo in pa_asyncq_pop
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1480 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/asyncq.c b/src/pulsecore/asyncq.c
index da1f16f..c966e7d 100644
--- a/src/pulsecore/asyncq.c
+++ b/src/pulsecore/asyncq.c
@@ -141,8 +141,10 @@ int pa_asyncq_push(pa_asyncq*l, void *p, int wait) {
                 int x[20];
                 
                 errno = 0;
-                if ((r = read(l->write_fds[0], x, sizeof(x))) <= 0 && errno != EINTR)
+                if ((r = read(l->write_fds[0], x, sizeof(x))) < 0 && errno != EINTR)
                     return -1;
+
+                pa_assert(r != 0);
                 
                 if (r > 0)
                     if (pa_atomic_sub(&l->n_read, r) <= r)
@@ -174,6 +176,8 @@ int pa_asyncq_push(pa_asyncq*l, void *p, int wait) {
                 return -1;
             }
 
+            pa_assert(r != 0);
+
             if (r > 0)
                 pa_atomic_sub(&l->n_read, r);
         }
@@ -220,8 +224,10 @@ void* pa_asyncq_pop(pa_asyncq*l, int wait) {
                 int x[20];
                 
                 errno = 0;
-                if ((r = read(l->read_fds[0], x, sizeof(x))) <= 0 && errno != EINTR)
+                if ((r = read(l->read_fds[0], x, sizeof(x))) < 0 && errno != EINTR)
                     return NULL;
+
+                pa_assert(r != 0);
                 
                 if (r > 0)
                     if (pa_atomic_sub(&l->n_written, r) <= r)
@@ -246,11 +252,13 @@ void* pa_asyncq_pop(pa_asyncq*l, int wait) {
 
             _Y;
 
-            if ((r = read(l->read_fds[0], x, sizeof(x)) < 0) && errno != EINTR) {
+            if ((r = read(l->read_fds[0], x, sizeof(x))) < 0 && errno != EINTR) {
                 pa_atomic_dec(&l->read_waiting);
                 return NULL;
             }
 
+            pa_assert(r != 0);
+
             if (r > 0)
                 pa_atomic_sub(&l->n_written, r);
         }
@@ -312,7 +320,4 @@ void pa_asyncq_after_poll(pa_asyncq *l) {
     pa_assert(pa_atomic_load(&l->read_waiting) > 0);
 
     pa_atomic_dec(&l->read_waiting);
-
-
-    
 }

commit 1d7096b19e0671ecc2824fda96cdd94b125eb80b
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Jun 14 20:12:26 2007 +0000

    Show memchunk length in debug output
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1481 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/asyncmsgq.c b/src/pulsecore/asyncmsgq.c
index a46f038..d650989 100644
--- a/src/pulsecore/asyncmsgq.c
+++ b/src/pulsecore/asyncmsgq.c
@@ -164,7 +164,7 @@ int pa_asyncmsgq_get(pa_asyncmsgq *a, pa_msgobject **object, int *code, void **u
     if (chunk)
         *chunk = a->current->memchunk;
 
-    pa_log_debug("q=%p object=%p (%s) code=%i data=%p", (void*) a, (void*) a->current->object, a->current->object ? a->current->object->parent.type_name : NULL, a->current->code, (void*) a->current->userdata);
+    pa_log_debug("q=%p object=%p (%s) code=%i data=%p chunk.length=%u", (void*) a, (void*) a->current->object, a->current->object ? a->current->object->parent.type_name : NULL, a->current->code, (void*) a->current->userdata, a->current->memchunk.length);
     
     return 0;
 }

commit e279778848f07c4c6ebb7b02555eea83d57430d5
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Jun 14 20:13:44 2007 +0000

    use pa_memblockq_push_align() instead of pa_memblockq_push() to deal with unaligned data coming from clients
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1482 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/protocol-simple.c b/src/pulsecore/protocol-simple.c
index 288c1c0..0e978c6 100644
--- a/src/pulsecore/protocol-simple.c
+++ b/src/pulsecore/protocol-simple.c
@@ -205,8 +205,10 @@ static int do_write(connection *c) {
     if (!c->source_output)
         return 0;
 
-    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);
@@ -276,7 +278,8 @@ static int connection_process_msg(pa_msgobject *o, int code, void*userdata, pa_m
             break;
             
         case MESSAGE_POST_DATA:
-            pa_memblockq_push(c->output_memblockq, chunk);
+/*             pa_log("got data %u", chunk->length); */
+            pa_memblockq_push_align(c->output_memblockq, chunk);
             do_work(c);
             break;
 

commit 94f6ab5fba54db12a5373ab840ee973fb49bae9a
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Jun 14 20:14:33 2007 +0000

    Fix another ugly typo, which made source outputs unusable
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1483 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/source-output.c b/src/pulsecore/source-output.c
index 1b93c06..defb779 100644
--- a/src/pulsecore/source-output.c
+++ b/src/pulsecore/source-output.c
@@ -261,7 +261,7 @@ void pa_source_output_push(pa_source_output *o, const pa_memchunk *chunk) {
     if (!o->push || o->state == PA_SOURCE_OUTPUT_DISCONNECTED || o->state == PA_SOURCE_OUTPUT_CORKED)
         return;
 
-    pa_assert(o->state = PA_SOURCE_OUTPUT_RUNNING);
+    pa_assert(o->state == PA_SOURCE_OUTPUT_RUNNING);
 
     if (!o->thread_info.resampler) {
         o->push(o, chunk);

commit deb523e0e8cf44bbb074b277a0a54cf9442c510e
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Jun 14 20:15:06 2007 +0000

    Port module-pipe-source to the new threaded design
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1484 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-pipe-source.c b/src/modules/module-pipe-source.c
index ac2bef7..42224d5 100644
--- a/src/modules/module-pipe-source.c
+++ b/src/modules/module-pipe-source.c
@@ -28,22 +28,22 @@
 #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 "module-pipe-source-symdef.h"
 
@@ -58,18 +58,20 @@ 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_asyncmsgq *asyncmsgq;
+    
     char *filename;
+    int fd;
 
-    pa_source *source;
-    pa_iochannel *io;
-    pa_module *module;
-    pa_memchunk chunk;
+    pa_memchunk memchunk;
 };
 
 static const char* const valid_modargs[] = {
@@ -82,65 +84,146 @@ static const char* const valid_modargs[] = {
     NULL
 };
 
-static void do_read(struct userdata *u) {
-    ssize_t r;
-    void *p;
-    pa_memchunk chunk;
-
-    assert(u);
-
-    if (!pa_iochannel_is_readable(u->io))
-        return;
-
-    pa_module_set_used(u->module, pa_idxset_size(u->source->outputs));
-
-    if (!u->chunk.memblock) {
-        u->chunk.memblock = pa_memblock_new(u->core->mempool, PIPE_BUF);
-        u->chunk.index = chunk.length = 0;
-    }
-
-    assert(u->chunk.memblock);
-    assert(pa_memblock_get_length(u->chunk.memblock) > u->chunk.index);
-
-    p = pa_memblock_acquire(u->chunk.memblock);
-    if ((r = pa_iochannel_read(u->io, (uint8_t*) p + u->chunk.index, pa_memblock_get_length(u->chunk.memblock) - u->chunk.index)) <= 0) {
-        pa_memblock_release(u->chunk.memblock);
-        pa_log("read(): %s", pa_cstrerror(errno));
-        return;
+static void thread_func(void *userdata) {
+    enum {
+        POLLFD_ASYNCQ,
+        POLLFD_FIFO,
+        POLLFD_MAX,
+    };
+    
+    struct userdata *u = userdata;
+    struct pollfd pollfd[POLLFD_MAX];
+    int read_type = 0;
+
+    pa_assert(u);
+
+    pa_log_debug("Thread starting up");
+
+    pa_memchunk_reset(&u->memchunk);
+    
+    memset(&pollfd, 0, sizeof(pollfd));
+    
+    pollfd[POLLFD_ASYNCQ].fd = pa_asyncmsgq_get_fd(u->asyncmsgq);
+    pollfd[POLLFD_ASYNCQ].events = POLLIN;
+    pollfd[POLLFD_FIFO].fd = u->fd;
+
+    for (;;) {
+        pa_msgobject *object;
+        int code;
+        void *data;
+        pa_memchunk chunk;
+        int r;
+
+        /* Check whether there is a message for us to process */
+        if (pa_asyncmsgq_get(u->asyncmsgq, &object, &code, &data, &chunk, 0) == 0) {
+            int ret;
+
+            if (!object && code == PA_MESSAGE_SHUTDOWN) {
+                pa_asyncmsgq_done(u->asyncmsgq, 0);
+                goto finish;
+            }
+
+            ret = pa_asyncmsgq_dispatch(object, code, data, &chunk);
+            pa_asyncmsgq_done(u->asyncmsgq, ret);
+            continue;
+        }
+
+        /* Render some data and write it to the fifo */
+
+        if (u->source->thread_info.state == PA_SOURCE_RUNNING && pollfd[POLLFD_FIFO].revents) {
+            void *p;
+            ssize_t l;
+            
+            if (!u->memchunk.memblock) {
+                u->memchunk.memblock = pa_memblock_new(u->core->mempool, PIPE_BUF);
+                u->memchunk.index = u->memchunk.length = 0;
+            }
+
+            pa_assert(pa_memblock_get_length(u->memchunk.memblock) > u->memchunk.index);
+            
+            p = pa_memblock_acquire(u->memchunk.memblock);
+            l = pa_read(u->fd, (uint8_t*) p + u->memchunk.index, pa_memblock_get_length(u->memchunk.memblock) - u->memchunk.index, &read_type);
+            pa_memblock_release(u->memchunk.memblock);
+
+            pa_assert(l != 0); /* EOF cannot happen, since we opened the fifo for both reading and writing */
+
+            if (l < 0) {
+
+                if (errno == EINTR)
+                    continue;
+                else if (errno != EAGAIN) {
+                    pa_log("Faile to read data from FIFO: %s", pa_cstrerror(errno));
+                    goto fail;
+                }
+
+            } else {
+                
+                u->memchunk.length = l;
+                pa_source_post(u->source, &u->memchunk);
+                u->memchunk.index += l;
+
+                if (u->memchunk.index >= pa_memblock_get_length(u->memchunk.memblock)) {
+                    pa_memblock_unref(u->memchunk.memblock);
+                    pa_memchunk_reset(&u->memchunk);
+                }
+
+                pollfd[POLLFD_FIFO].revents = 0;
+                continue;
+            }
+        }
+
+        pollfd[POLLFD_FIFO].events = u->source->thread_info.state == PA_SINK_RUNNING ? POLLIN : 0;
+
+        /* Hmm, nothing to do. Let's sleep */
+
+        if (pa_asyncmsgq_before_poll(u->asyncmsgq) < 0)
+            continue;
+
+/*         pa_log("polling for %i", pollfd[POLLFD_FIFO].events); */
+        r = poll(pollfd, POLLFD_MAX, -1);
+/*         pa_log("polling got %i (r=%i) %i", r > 0 ? pollfd[POLLFD_FIFO].revents : 0, r, r > 0 ? pollfd[POLLFD_ASYNCQ].revents: 0); */
+
+        pa_asyncmsgq_after_poll(u->asyncmsgq);
+
+        if (r < 0) {
+            if (errno == EINTR)
+                continue;
+
+            pa_log("poll() failed: %s", pa_cstrerror(errno));
+            goto fail;
+        }
+
+        if (pollfd[POLLFD_FIFO].revents & ~POLLIN) {
+            pa_log("FIFO shutdown.");
+            goto fail;
+        }
+
+        pa_assert((pollfd[POLLFD_ASYNCQ].revents & ~POLLIN) == 0);
     }
-    pa_memblock_release(u->chunk.memblock);
-
-    u->chunk.length = r;
-    pa_source_post(u->source, &u->chunk);
-    u->chunk.index += r;
 
-    if (u->chunk.index >= pa_memblock_get_length(u->chunk.memblock)) {
-        u->chunk.index = u->chunk.length = 0;
-        pa_memblock_unref(u->chunk.memblock);
-        u->chunk.memblock = NULL;
-    }
-}
+fail:
+    /* We have to continue processing messages until we receive the
+     * SHUTDOWN message */
+    pa_asyncmsgq_post(u->core->asyncmsgq, PA_MSGOBJECT(u->core), PA_CORE_MESSAGE_UNLOAD_MODULE, u->module, NULL, NULL);
+    pa_asyncmsgq_wait_for(u->asyncmsgq, PA_MESSAGE_SHUTDOWN);
 
-static void io_callback(PA_GCC_UNUSED pa_iochannel *io, void*userdata) {
-    struct userdata *u = userdata;
-    assert(u);
-    do_read(u);
+finish:
+    pa_log_debug("Thread shutting down");
 }
 
 int pa__init(pa_core *c, pa_module*m) {
-    struct userdata *u = NULL;
+    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;
 
-    assert(c && m);
+    pa_assert(c);
+    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;
     }
 
@@ -150,48 +233,50 @@ int pa__init(pa_core *c, pa_module*m) {
         goto fail;
     }
 
-    mkfifo(p = pa_modargs_get_value(ma, "file", DEFAULT_FIFO_NAME), 0777);
+    u = pa_xnew0(struct userdata, 1);
+    u->core = c;
+    u->module = m;
+    m->userdata = u;
 
-    if ((fd = open(p, O_RDWR)) < 0) {
-        pa_log("open('%s'): %s", p, pa_cstrerror(errno));
+    pa_assert_se(u->asyncmsgq = pa_asyncmsgq_new(0));
+
+    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_fd_set_cloexec(u->fd, 1);
+    pa_make_nonblock_fd(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.");
+        pa_log("Failed to create source.");
         goto fail;
     }
+
     u->source->userdata = u;
+    
     pa_source_set_module(u->source, m);
-    pa_source_set_description(u->source, t = pa_sprintf_malloc("Unix FIFO source '%s'", p));
+    pa_source_set_asyncmsgq(u->source, u->asyncmsgq);
+    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->chunk.memblock = NULL;
-    u->chunk.index = u->chunk.length = 0;
-
-    u->module = m;
-    m->userdata = u;
+    if (!(u->thread = pa_thread_new(thread_func, u))) {
+        pa_log("Failed to create thread.");
+        goto fail;
+    }
 
     pa_modargs_free(ma);
 
@@ -201,9 +286,6 @@ fail:
     if (ma)
         pa_modargs_free(ma);
 
-    if (fd >= 0)
-        close(fd);
-
     pa__done(c, m);
 
     return -1;
@@ -211,21 +293,37 @@ fail:
 
 void pa__done(pa_core *c, pa_module*m) {
     struct userdata *u;
-    assert(c && m);
+    
+    pa_assert(c);
+    pa_assert(m);
 
     if (!(u = m->userdata))
         return;
 
-    if (u->chunk.memblock)
-        pa_memblock_unref(u->chunk.memblock);
+    if (u->source)
+        pa_source_disconnect(u->source);
 
-    pa_source_disconnect(u->source);
-    pa_source_unref(u->source);
-    pa_iochannel_free(u->io);
+    if (u->thread) {
+        pa_asyncmsgq_send(u->asyncmsgq, NULL, PA_MESSAGE_SHUTDOWN, NULL, NULL);
+        pa_thread_free(u->thread);
+    }
+
+    if (u->asyncmsgq)
+        pa_asyncmsgq_free(u->asyncmsgq);
+
+    if (u->source)
+        pa_source_unref(u->source);
+    
+    if (u->memchunk.memblock)
+        pa_memblock_unref(u->memchunk.memblock);
+
+    if (u->filename) {
+        unlink(u->filename);
+        pa_xfree(u->filename);
+    }
 
-    assert(u->filename);
-    unlink(u->filename);
-    pa_xfree(u->filename);
+    if (u->fd >= 0)
+        close(u->fd);
 
     pa_xfree(u);
 }

commit e24c8dea5b359bd960660fa2d0100321cb627207
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sat Jun 23 19:53:11 2007 +0000

    Fix minor typo
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1485 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/memblockq.h b/src/pulsecore/memblockq.h
index 437c5a4..c049d78 100644
--- a/src/pulsecore/memblockq.h
+++ b/src/pulsecore/memblockq.h
@@ -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,

commit 1c9bd201ec88e3493f01b5cd2a7c5a713d829555
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sat Jun 23 20:01:40 2007 +0000

    minor cleanups and optimizations
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1486 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/oss-util.c b/src/modules/oss-util.c
index 4be71e2..155d42e 100644
--- a/src/modules/oss-util.c
+++ b/src/modules/oss-util.c
@@ -26,7 +26,6 @@
 #include <config.h>
 #endif
 
-#include <assert.h>
 #include <sys/soundcard.h>
 #include <sys/ioctl.h>
 #include <stdio.h>
@@ -40,6 +39,7 @@
 #include <pulsecore/core-error.h>
 #include <pulsecore/core-util.h>
 #include <pulsecore/log.h>
+#include <pulsecore/macro.h>
 
 #include "oss-util.h"
 
@@ -47,24 +47,23 @@ 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);
@@ -72,21 +71,19 @@ int pa_oss_open(const char *device, int *mode, int* pcaps) {
             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,6 +91,8 @@ 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
@@ -166,7 +165,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 +199,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 +211,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);
@@ -252,9 +252,9 @@ static int pa_oss_get_volume(int fd, int mixer, const pa_sample_spec *ss, pa_cvo
     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;
@@ -357,7 +357,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, " ");
 

commit fff9081c4bedded92caaabf9191aeb717709354b
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sat Jun 23 20:02:28 2007 +0000

    fix a typo and some minor optimizations
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1487 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-pipe-source.c b/src/modules/module-pipe-source.c
index 42224d5..5dbb1e7 100644
--- a/src/modules/module-pipe-source.c
+++ b/src/modules/module-pipe-source.c
@@ -99,8 +99,6 @@ static void thread_func(void *userdata) {
 
     pa_log_debug("Thread starting up");
 
-    pa_memchunk_reset(&u->memchunk);
-    
     memset(&pollfd, 0, sizeof(pollfd));
     
     pollfd[POLLFD_ASYNCQ].fd = pa_asyncmsgq_get_fd(u->asyncmsgq);
@@ -128,19 +126,19 @@ static void thread_func(void *userdata) {
             continue;
         }
 
-        /* Render some data and write it to the fifo */
+        /* Try to read some data and pass it on to the source driver */
 
         if (u->source->thread_info.state == PA_SOURCE_RUNNING && pollfd[POLLFD_FIFO].revents) {
             void *p;
             ssize_t l;
-            
+
             if (!u->memchunk.memblock) {
                 u->memchunk.memblock = pa_memblock_new(u->core->mempool, PIPE_BUF);
                 u->memchunk.index = u->memchunk.length = 0;
             }
 
             pa_assert(pa_memblock_get_length(u->memchunk.memblock) > u->memchunk.index);
-            
+
             p = pa_memblock_acquire(u->memchunk.memblock);
             l = pa_read(u->fd, (uint8_t*) p + u->memchunk.index, pa_memblock_get_length(u->memchunk.memblock) - u->memchunk.index, &read_type);
             pa_memblock_release(u->memchunk.memblock);
@@ -157,7 +155,7 @@ static void thread_func(void *userdata) {
                 }
 
             } else {
-                
+
                 u->memchunk.length = l;
                 pa_source_post(u->source, &u->memchunk);
                 u->memchunk.index += l;
@@ -172,7 +170,7 @@ static void thread_func(void *userdata) {
             }
         }
 
-        pollfd[POLLFD_FIFO].events = u->source->thread_info.state == PA_SINK_RUNNING ? POLLIN : 0;
+        pollfd[POLLFD_FIFO].events = u->source->thread_info.state == PA_SOURCE_RUNNING ? POLLIN : 0;
 
         /* Hmm, nothing to do. Let's sleep */
 
@@ -237,7 +235,8 @@ int pa__init(pa_core *c, pa_module*m) {
     u->core = c;
     u->module = m;
     m->userdata = u;
-
+    pa_memchunk_reset(&u->memchunk);
+    
     pa_assert_se(u->asyncmsgq = pa_asyncmsgq_new(0));
 
     u->filename = pa_xstrdup(pa_modargs_get_value(ma, "file", DEFAULT_FILE_NAME));

commit f0616367b32fbe993c4d0edb0457b10d241137a2
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sat Jun 23 20:03:00 2007 +0000

    drop silence generation from sink drivers
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1488 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-null-sink.c b/src/modules/module-null-sink.c
index afe130d..3e471d4 100644
--- a/src/modules/module-null-sink.c
+++ b/src/modules/module-null-sink.c
@@ -140,7 +140,7 @@ static void thread_func(void *userdata) {
                 pa_asyncmsgq_done(u->asyncmsgq, 0);
                 goto finish;
             }
-                    
+
             ret = pa_asyncmsgq_dispatch(object, code, data, &chunk);
             pa_asyncmsgq_done(u->asyncmsgq, ret);
             continue;
@@ -151,15 +151,11 @@ static void thread_func(void *userdata) {
             pa_gettimeofday(&now);
 
             if (pa_timeval_cmp(&u->timestamp, &now) <= 0) {
-                size_t l;
 
-                if (pa_sink_render(u->sink, u->block_size, &chunk) >= 0) {
-                    l = chunk.length;
-                    pa_memblock_unref(chunk.memblock);
-                } else
-                    l = u->block_size;
+                pa_sink_render(u->sink, u->block_size, &chunk);
+                pa_memblock_unref(chunk.memblock);
 
-                pa_timeval_add(&u->timestamp, pa_bytes_to_usec(l, &u->sink->sample_spec));
+                pa_timeval_add(&u->timestamp, pa_bytes_to_usec(chunk.length, &u->sink->sample_spec));
                 continue;
             }
 

commit 780f736547616e4e06941d94e77f456abca12a9c
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sat Jun 23 20:03:30 2007 +0000

    don't handle underrun special
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1489 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-pipe-sink.c b/src/modules/module-pipe-sink.c
index 216e42a..e27a237 100644
--- a/src/modules/module-pipe-sink.c
+++ b/src/modules/module-pipe-sink.c
@@ -115,15 +115,12 @@ static void thread_func(void *userdata) {
     
     struct userdata *u = userdata;
     struct pollfd pollfd[POLLFD_MAX];
-    int underrun = 0;
     int write_type = 0;
 
     pa_assert(u);
 
     pa_log_debug("Thread starting up");
 
-    pa_memchunk_reset(&u->memchunk);
-    
     memset(&pollfd, 0, sizeof(pollfd));
     
     pollfd[POLLFD_ASYNCQ].fd = pa_asyncmsgq_get_fd(u->asyncmsgq);
@@ -153,56 +150,53 @@ static void thread_func(void *userdata) {
 
         /* Render some data and write it to the fifo */
 
-        if (u->sink->thread_info.state == PA_SINK_RUNNING && (pollfd[POLLFD_FIFO].revents || underrun)) {
+        if (u->sink->thread_info.state == PA_SINK_RUNNING && pollfd[POLLFD_FIFO].revents) {
+            ssize_t l;
+            void *p;
 
             if (u->memchunk.length <= 0)
                 pa_sink_render(u->sink, PIPE_BUF, &u->memchunk);
 
-            underrun = u->memchunk.length <= 0;
+            pa_assert(u->memchunk.length > 0);
 
-            if (!underrun) {
-                ssize_t l;
-                void *p;
+            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);
 
-                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);
 
-                pa_assert(l != 0);
-                
-                if (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 {
+                if (errno == EINTR)
+                    continue;
+                else if (errno != EAGAIN) {
+                    pa_log("Failed to write data to FIFO: %s", pa_cstrerror(errno));
+                    goto fail;
+                }
 
-                    u->memchunk.index += l;
-                    u->memchunk.length -= l;
+            } else {
 
-                    if (u->memchunk.length <= 0) {
-                        pa_memblock_unref(u->memchunk.memblock);
-                        pa_memchunk_reset(&u->memchunk);
-                    }
+                u->memchunk.index += l;
+                u->memchunk.length -= l;
 
-                    pollfd[POLLFD_FIFO].revents = 0;
-                    continue;
+                if (u->memchunk.length <= 0) {
+                    pa_memblock_unref(u->memchunk.memblock);
+                    pa_memchunk_reset(&u->memchunk);
                 }
+
+                pollfd[POLLFD_FIFO].revents = 0;
+                continue;
             }
         }
 
-        pollfd[POLLFD_FIFO].events = (u->sink->thread_info.state == PA_SINK_RUNNING && !underrun) ? POLLOUT : 0;
+        pollfd[POLLFD_FIFO].events = u->sink->thread_info.state == PA_SINK_RUNNING ? POLLOUT : 0;
 
         /* Hmm, nothing to do. Let's sleep */
 
         if (pa_asyncmsgq_before_poll(u->asyncmsgq) < 0)
             continue;
 
-/*         pa_log("polling for %u (underrun=%i)", pollfd[POLLFD_FIFO].events, underrun);  */
+/*         pa_log("polling for %u", pollfd[POLLFD_FIFO].events);  */
         r = poll(pollfd, POLLFD_MAX, -1);
 /*         pa_log("polling got %u", r > 0 ? pollfd[POLLFD_FIFO].revents : 0);  */
 
@@ -260,6 +254,7 @@ int pa__init(pa_core *c, pa_module*m) {
     u->core = c;
     u->module = m;
     m->userdata = u;
+    pa_memchunk_reset(&u->memchunk);
 
     pa_assert_se(u->asyncmsgq = pa_asyncmsgq_new(0));
     

commit 013a55a692d652ce079b9dbd5f768a0a0680f727
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sat Jun 23 20:04:47 2007 +0000

    remove underrun condition in pa_sinks. Instead return silence in pa_sink_render() when necessary. This is required to guarantee that the time functions in connected sink inputs stays linear
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1490 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c
index 7f00904..11effe2 100644
--- a/src/pulsecore/sink.c
+++ b/src/pulsecore/sink.c
@@ -116,6 +116,7 @@ pa_sink* pa_sink_new(
     s->userdata = NULL;
 
     s->asyncmsgq = NULL;
+    s->silence = NULL;
 
     r = pa_idxset_put(core->sinks, s, &s->index);
     pa_assert(s->index != PA_IDXSET_INVALID && r >= 0);
@@ -222,6 +223,9 @@ static void sink_free(pa_object *o) {
     
     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);
@@ -270,53 +274,85 @@ static unsigned fill_mix_info(pa_sink *s, pa_mix_info *info, unsigned maxinfo) {
     pa_sink_assert_ref(s);
     pa_assert(info);
 
-    while ((i = pa_hashmap_iterate(s->thread_info.inputs, &state, NULL))) {
-        /* 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, &info->chunk, &info->volume) < 0)
             continue;
-        }
 
-        info->userdata = i;
+        info->userdata = pa_sink_input_ref(i);
 
         pa_assert(info->chunk.memblock);
-        pa_assert(info->chunk.length);
+        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) {
+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);
-    pa_assert(info);
 
-    for (; maxinfo > 0; maxinfo--, info++) {
-        pa_sink_input *i = info->userdata;
+    /* We optimize for the case where the order of the inputs has not changed */
 
-        pa_assert(i);
-        pa_assert(info->chunk.memblock);
+    while ((i = pa_hashmap_iterate(s->thread_info.inputs, &state, NULL))) {
+        unsigned j;
+        pa_mix_info* m;
+
+        pa_sink_input_assert_ref(i);
+
+        m = NULL;
+
+        /* 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;
+            }
+
+            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, m ? &m->chunk : NULL, 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;
 
     pa_sink_assert_ref(s);
     pa_assert(length);
@@ -326,10 +362,19 @@ int pa_sink_render(pa_sink*s, size_t length, pa_memchunk *result) {
 
     n = fill_mix_info(s, info, MAX_MIX_CHANNELS);
 
-    if (n <= 0)
-        goto finish;
+    if (n == 0) {
+
+        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;
 
-    if (n == 1) {
+    } else if (n == 1) {
         pa_cvolume volume;
 
         *result = info[0].chunk;
@@ -363,18 +408,12 @@ int pa_sink_render(pa_sink*s, size_t length, pa_memchunk *result) {
     if (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;
 
     pa_sink_assert_ref(s);
     pa_assert(target);
@@ -385,11 +424,9 @@ int pa_sink_render_into(pa_sink*s, pa_memchunk *target) {
 
     n = fill_mix_info(s, info, MAX_MIX_CHANNELS);
 
-    if (n <= 0)
-        goto finish;
-
-
-    if (n == 1) {
+    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;
 
@@ -435,12 +472,7 @@ int pa_sink_render_into(pa_sink*s, pa_memchunk *target) {
     if (s->monitor_source)
         pa_source_post(s->monitor_source, target);
 
-    r = 0;
-
-finish:
     pa_sink_unref(s);
-
-    return r;
 }
 
 void pa_sink_render_into_full(pa_sink *s, pa_memchunk *target) {
@@ -461,20 +493,12 @@ 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);
 }
 
@@ -668,7 +692,7 @@ int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, pa_memchunk *
         case PA_SINK_MESSAGE_SET_STATE:
             s->thread_info.state = PA_PTR_TO_UINT(userdata);
             return 0;
-            
+
         case PA_SINK_MESSAGE_GET_LATENCY:
         case PA_SINK_MESSAGE_MAX:
             ;
diff --git a/src/pulsecore/sink.h b/src/pulsecore/sink.h
index 0b308e5..dab9745 100644
--- a/src/pulsecore/sink.h
+++ b/src/pulsecore/sink.h
@@ -92,6 +92,8 @@ struct pa_sink {
         int soft_muted;
     } thread_info;
 
+    pa_memblock *silence;
+
     void *userdata;
 };
 
@@ -149,9 +151,9 @@ unsigned pa_sink_used_by(pa_sink *s);
 
 /* To be used exclusively by the sink driver thread */
 
-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);
 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(pa_sink*s, pa_memchunk *target);
 void pa_sink_render_into_full(pa_sink *s, pa_memchunk *target);
 
 int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, pa_memchunk *chunk);

commit bb3ad9d38e2be840838b6af5dc2a09e4863566ed
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sat Jun 23 20:05:20 2007 +0000

    Update OSS driver for new lock-free core
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1491 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/Makefile.am b/src/Makefile.am
index 0a5d529..a83424c 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -927,12 +927,12 @@ modlibexec_LTLIBRARIES += \
 		module-x11-publish.la
 endif
 
-#if HAVE_OSS
-#modlibexec_LTLIBRARIES += \
-#		liboss-util.la \
-#		module-oss.la \
+if HAVE_OSS
+modlibexec_LTLIBRARIES += \
+		liboss-util.la \
+		module-oss.la
 #		module-oss-mmap.la
-#endif
+endif
 
 #if HAVE_ALSA
 #modlibexec_LTLIBRARIES += \
@@ -1176,13 +1176,13 @@ module_x11_publish_la_LIBADD = $(AM_LIBADD) $(X_PRE_LIBS) -lX11 $(X_LIBS) $(X_EX
 
 # OSS
 
-#liboss_util_la_SOURCES = modules/oss-util.c modules/oss-util.h
-#liboss_util_la_LDFLAGS = -avoid-version
-#liboss_util_la_LIBADD = libpulsecore.la
+liboss_util_la_SOURCES = modules/oss-util.c modules/oss-util.h
+liboss_util_la_LDFLAGS = -avoid-version
+liboss_util_la_LIBADD = libpulsecore.la
 
-#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
+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
 
 #module_oss_mmap_la_SOURCES = modules/module-oss-mmap.c
 #module_oss_mmap_la_LDFLAGS = -module -avoid-version
diff --git a/src/modules/module-oss.c b/src/modules/module-oss.c
index 9061e11..01fe2b6 100644
--- a/src/modules/module-oss.c
+++ b/src/modules/module-oss.c
@@ -22,12 +22,31 @@
   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 this should be implemented in a
+ *   special suspend-on-idle module that will put us into SUSPEND mode
+ *   as soon and we're idle for too long.
+ *
+ */
+
+/* TODO: handle restoring of volume after suspend */
+
 #ifdef HAVE_CONFIG_H
 #include <config.h>
 #endif
 
 #include <sys/soundcard.h>
 #include <sys/ioctl.h>
+#include <sys/poll.h>
 #include <stdlib.h>
 #include <sys/stat.h>
 #include <stdio.h>
@@ -42,7 +61,7 @@
 #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>
@@ -70,19 +89,33 @@ PA_MODULE_USAGE(
         "fragment_size=<fragment size> "
         "channel_map=<channel map>")
 
+#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_thread *thread;
+    pa_asyncmsgq *asyncmsgq;
 
-    pa_memchunk memchunk, silence;
+    char *device_name;
+    
+    pa_memchunk memchunk;
 
     uint32_t in_fragment_size, out_fragment_size, sample_size;
     int use_getospace, use_getispace;
+    int use_getodelay;
+
+    int use_pcm_volume;
+    int use_input_volume;
+
+    int sink_suspended, source_suspended;
 
     int fd;
-    pa_module *module;
+    int mode;
+
+    int nfrags, frag_size;
 };
 
 static const char* const valid_modargs[] = {
@@ -100,264 +133,500 @@ static const char* const valid_modargs[] = {
     NULL
 };
 
-#define DEFAULT_DEVICE "/dev/dsp"
+static int suspend(struct userdata *u) {
+    pa_assert(u);
+    pa_assert(u->fd >= 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));
+    /* Let's suspend */
+    ioctl(u->fd, SNDCTL_DSP_SYNC);
+    close(u->fd);
+    u->fd = -1;
+    
+    return 0;
 }
 
-static void clear_up(struct userdata *u) {
-    assert(u);
+static int unsuspend(struct userdata *u) {
+    int m;
+    pa_sample_spec ss, *ss_original;
+    int frag_size, in_frag_size, out_frag_size;
+    struct audio_buf_info info;
 
-    if (u->sink) {
-        pa_sink_disconnect(u->sink);
-        pa_sink_unref(u->sink);
-        u->sink = NULL;
+    pa_assert(u);
+    pa_assert(u->fd < 0);
+
+    m = u->mode;
+
+    pa_log_debug("Trying resume...");
+
+    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->source) {
-        pa_source_disconnect(u->source);
-        pa_source_unref(u->source);
-        u->source = NULL;
+    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 (u->io) {
-        pa_iochannel_free(u->io);
-        u->io = NULL;
+    if (ioctl(u->fd, SNDCTL_DSP_GETBLKSIZE, &frag_size) < 0) {
+        pa_log("SNDCTL_DSP_GETBLKSIZE: %s", pa_cstrerror(errno));
+        goto fail;
     }
-}
 
-static void do_write(struct userdata *u) {
-    pa_memchunk *memchunk;
-    ssize_t r;
-    size_t l;
-    int loop = 0;
+    in_frag_size = out_frag_size = frag_size;
 
-    assert(u);
+    if (ioctl(u->fd, SNDCTL_DSP_GETISPACE, &info) >= 0)
+        in_frag_size = info.fragsize;
 
-    if (!u->sink || !pa_iochannel_is_writable(u->io))
-        return;
+    if (ioctl(u->fd, SNDCTL_DSP_GETOSPACE, &info) >= 0)
+        out_frag_size = info.fragsize;
 
-    update_usage(u);
+    if ((u->source && in_frag_size != (int) u->in_fragment_size) || (u->sink && out_frag_size != (int) u->out_fragment_size)) {
+        pa_log_warn("Resume failed, fragment settings don't match.");
+        goto fail;
+    }
 
-    l = u->out_fragment_size;
+    /*
+     * 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) {
+        uint8_t *buf = pa_xnew(uint8_t, u->sample_size);
+        pa_read(u->fd, buf, u->sample_size, NULL);
+        pa_xfree(buf);
+    }
 
-    if (u->use_getospace) {
-        audio_buf_info info;
+    return 0;
 
-        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;
+fail:
+    close(u->fd);
+    u->fd = -1;
+    return -1;
+}
+
+static int sink_process_msg(pa_msgobject *o, int code, void *data, pa_memchunk *chunk) {
+    struct userdata *u = PA_SINK(o)->userdata;
+
+    switch (code) {
+
+        case PA_SINK_MESSAGE_GET_LATENCY: {
+            pa_usec_t r = 0;
+
+            if (u->fd >= 0) {
+                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);
+                    
+                }
+                
+                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, &u->sink->sample_spec);
+
+            *((pa_usec_t*) data) = r;
+
+            break;
         }
-    }
 
-    do {
-        void *p;
-        memchunk = &u->memchunk;
+        case PA_SINK_MESSAGE_SET_STATE:
+
+            if (PA_PTR_TO_UINT(data) != PA_SINK_RUNNING && u->fd >= 0)
+                ioctl(u->fd, SNDCTL_DSP_POST);
+
+            if (PA_PTR_TO_UINT(data) == PA_SINK_SUSPENDED) {
+                pa_assert(u->sink->thread_info.state != PA_SINK_SUSPENDED);
+
+                if (u->source_suspended)
+                    if (suspend(u) < 0)
+                        return -1;
+
+                u->sink_suspended = 1;
+            }
+
+            if (u->sink->thread_info.state == PA_SINK_SUSPENDED) {
+                pa_assert(PA_PTR_TO_UINT(data) != PA_SINK_SUSPENDED);
 
-        if (!memchunk->length)
-            if (pa_sink_render(u->sink, l, memchunk) < 0)
-                memchunk = &u->silence;
+                if (u->source_suspended)
+                    if (unsuspend(u) < 0)
+                        return -1;
 
-        assert(memchunk->memblock);
-        assert(memchunk->length);
+                u->sink_suspended = 0;
+            }
+            
+            break;
 
-        p = pa_memblock_acquire(memchunk->memblock);
-        if ((r = pa_iochannel_write(u->io, (uint8_t*) p + memchunk->index, memchunk->length)) < 0) {
-            pa_memblock_release(memchunk->memblock);
+        case PA_SINK_MESSAGE_SET_VOLUME:
 
-            if (errno != EAGAIN) {
-                pa_log("write() failed: %s", pa_cstrerror(errno));
+            if (u->use_pcm_volume && u->fd >= 0) {
 
-                clear_up(u);
-                pa_module_unload_request(u->module);
+                if (pa_oss_set_pcm_volume(u->fd, &u->sink->sample_spec, ((pa_cvolume*) data)) < 0) {
+                    pa_log_info("Device doesn't support setting mixer settings: %s", pa_cstrerror(errno));
+                    u->use_pcm_volume = 0;
+                } else
+                    return 0;
             }
 
             break;
-        }
 
-        pa_memblock_release(memchunk->memblock);
+        case PA_SINK_MESSAGE_GET_VOLUME:
 
-        if (memchunk == &u->silence)
-            assert(r % u->sample_size == 0);
-        else {
-            u->memchunk.index += r;
-            u->memchunk.length -= r;
+            if (u->use_pcm_volume && u->fd >= 0) {
 
-            if (u->memchunk.length <= 0) {
-                pa_memblock_unref(u->memchunk.memblock);
-                u->memchunk.memblock = NULL;
+                if (pa_oss_get_pcm_volume(u->fd, &u->sink->sample_spec, ((pa_cvolume*) data)) < 0) {
+                    pa_log_info("Device doesn't support reading mixer settings: %s", pa_cstrerror(errno));
+                    u->use_pcm_volume = 0;
+                } else
+                    return 0;
             }
-        }
 
-        l = l > (size_t) r ? l - r : 0;
-    } while (loop && l > 0);
-}
+            break;
+    }
 
-static void do_read(struct userdata *u) {
-    pa_memchunk memchunk;
-    ssize_t r;
-    size_t l;
-    int loop = 0;
-    assert(u);
+    return pa_sink_process_msg(o, code, data, chunk);
+}
 
-    if (!u->source || !pa_iochannel_is_readable(u->io) || !pa_idxset_size(u->source->outputs))
-        return;
+static int source_process_msg(pa_msgobject *o, int code, void *data, pa_memchunk *chunk) {
+    struct userdata *u = PA_SOURCE(o)->userdata;
 
-    update_usage(u);
+    switch (code) {
 
-    l = u->in_fragment_size;
+        case PA_SOURCE_MESSAGE_GET_LATENCY: {
+            pa_usec_t r = 0;
 
-    if (u->use_getispace) {
-        audio_buf_info info;
+            if (u->use_getispace && u->fd >= 0) {
+                struct audio_buf_info info;
 
-        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;
+                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->sink->sample_spec);
             }
+
+            *((pa_usec_t*) data) = r;
+            break;
         }
-    }
 
-    do {
-        void *p;
-        memchunk.memblock = pa_memblock_new(u->core->mempool, l);
+        case PA_SOURCE_MESSAGE_SET_STATE:
 
-        p = pa_memblock_acquire(memchunk.memblock);
+            if (PA_PTR_TO_UINT(data) == PA_SOURCE_SUSPENDED) {
+                pa_assert(u->source->thread_info.state != PA_SOURCE_SUSPENDED);
+
+                if (u->sink_suspended)
+                    if (suspend(u) < 0)
+                        return -1;
+
+                u->source_suspended = 1;
+            }
 
-        if ((r = pa_iochannel_read(u->io, p, pa_memblock_get_length(memchunk.memblock))) < 0) {
-            pa_memblock_release(memchunk.memblock);
-            pa_memblock_unref(memchunk.memblock);
+            if (u->source->thread_info.state == PA_SOURCE_SUSPENDED) {
+                pa_assert(PA_PTR_TO_UINT(data) != PA_SOURCE_SUSPENDED);
 
-            if (errno != EAGAIN) {
-                pa_log("read() failed: %s", pa_cstrerror(errno));
+                if (u->sink_suspended)
+                    if (unsuspend(u) < 0)
+                        return -1;
 
-                clear_up(u);
-                pa_module_unload_request(u->module);
+                u->source_suspended = 0;
             }
 
             break;
-        }
 
-        pa_memblock_release(memchunk.memblock);
+        case PA_SOURCE_MESSAGE_SET_VOLUME:
+
+            if (u->use_input_volume && u->fd >= 0) {
+
+                if (pa_oss_set_input_volume(u->fd, &u->source->sample_spec, ((pa_cvolume*) data)) < 0) {
+                    pa_log_info("Device doesn't support setting mixer settings: %s", pa_cstrerror(errno));
+                    u->use_input_volume = 0;
+                } else
+                    return 0;
+            }
+
+            break;
 
-        assert(r <= (ssize_t) pa_memblock_get_length(memchunk.memblock));
-        memchunk.length = r;
-        memchunk.index = 0;
+        case PA_SOURCE_MESSAGE_GET_VOLUME:
 
-        pa_source_post(u->source, &memchunk);
-        pa_memblock_unref(memchunk.memblock);
+            if (u->use_input_volume && u->fd >= 0) {
 
-        l = l > (size_t) r ? l - r : 0;
-    } while (loop && l > 0);
+                if (pa_oss_get_input_volume(u->fd, &u->source->sample_spec, ((pa_cvolume*) data)) < 0) {
+                    pa_log_info("Device doesn't support reading mixer settings: %s", pa_cstrerror(errno));
+                    u->use_input_volume = 0;
+                } else
+                    return 0;
+            }
+
+            break;
+    }
+
+    return pa_source_process_msg(o, code, data, chunk);
 }
 
-static void io_callback(PA_GCC_UNUSED pa_iochannel *io, void*userdata) {
+static void thread_func(void *userdata) {
+    enum {
+        POLLFD_ASYNCQ,
+        POLLFD_DSP,
+        POLLFD_MAX,
+    };
+
     struct userdata *u = userdata;
-    assert(u);
-    do_write(u);
-    do_read(u);
-}
+    struct pollfd pollfd[POLLFD_MAX];
+    int write_type = 0, read_type = 0;
 
-static void source_notify_cb(pa_source *s) {
-    struct userdata *u = s->userdata;
-    assert(u);
-    do_read(u);
-}
+    pa_assert(u);
 
-static pa_usec_t sink_get_latency_cb(pa_sink *s) {
-    pa_usec_t r = 0;
-    int arg;
-    struct userdata *u = s->userdata;
-    assert(s && u && u->sink);
+    pa_log_debug("Thread starting up");
 
-    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;
+    /*
+     * 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) {
+        uint8_t *buf = pa_xnew(uint8_t, u->sample_size);
+        pa_read(u->fd, buf, u->sample_size, &read_type);
+        pa_xfree(buf);
     }
 
-    r += pa_bytes_to_usec(arg, &s->sample_spec);
+    memset(&pollfd, 0, sizeof(pollfd));
 
-    if (u->memchunk.memblock)
-        r += pa_bytes_to_usec(u->memchunk.length, &s->sample_spec);
+    pollfd[POLLFD_ASYNCQ].fd = pa_asyncmsgq_get_fd(u->asyncmsgq);
+    pollfd[POLLFD_ASYNCQ].events = POLLIN;
+    pollfd[POLLFD_DSP].fd = u->fd;
 
-    return r;
-}
+    for (;;) {
+        pa_msgobject *object;
+        int code;
+        void *data;
+        pa_memchunk chunk;
+        int 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);
+        /* Check whether there is a message for us to process */
+        if (pa_asyncmsgq_get(u->asyncmsgq, &object, &code, &data, &chunk, 0) == 0) {
+            int ret;
 
-    if (!u->use_getispace)
-        return 0;
+            if (!object && code == PA_MESSAGE_SHUTDOWN) {
+                pa_asyncmsgq_done(u->asyncmsgq, 0);
+                goto finish;
+            }
 
-    if (ioctl(u->fd, SNDCTL_DSP_GETISPACE, &info) < 0) {
-        u->use_getispace = 0;
-        return 0;
-    }
+            ret = pa_asyncmsgq_dispatch(object, code, data, &chunk);
+            pa_asyncmsgq_done(u->asyncmsgq, ret);
+            continue;
+        }
 
-    if (info.bytes <= 0)
-        return 0;
+        /* Render some data and write it to the dsp */
 
-    return pa_bytes_to_usec(info.bytes, &s->sample_spec);
-}
+        if (u->sink && u->sink->thread_info.state == PA_SINK_RUNNING && (pollfd[POLLFD_DSP].revents & POLLOUT)) {
+            ssize_t l;
+            void *p;
+            int loop = 0;
 
-static int sink_get_hw_volume(pa_sink *s) {
-    struct userdata *u = s->userdata;
+            l = u->out_fragment_size;
 
-    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;
-    }
+            if (u->use_getospace) {
+                audio_buf_info info;
 
-    return 0;
-}
+                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 {
+                    if (info.bytes >= l) {
+                        l = (info.bytes/l)*l;
+                        loop = 1;
+                    }
+                }
+            }
 
-static int sink_set_hw_volume(pa_sink *s) {
-    struct userdata *u = s->userdata;
+            do {
+                ssize_t t;
 
-    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;
-    }
+                pa_assert(l > 0);
 
-    return 0;
-}
+                if (u->memchunk.length <= 0)
+                    pa_sink_render(u->sink, l, &u->memchunk);
 
-static int source_get_hw_volume(pa_source *s) {
-    struct userdata *u = s->userdata;
+                pa_assert(u->memchunk.length > 0);
 
-    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;
-    }
+                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);
 
-    return 0;
-}
+                pa_assert(t != 0);
 
-static int source_set_hw_volume(pa_source *s) {
-    struct userdata *u = s->userdata;
+                if (t < 0) {
 
-    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;
+                    if (errno == EINTR)
+                        continue;
+
+                    else if (errno == EAGAIN) {
+
+                        pollfd[POLLFD_DSP].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;
+
+                    pollfd[POLLFD_DSP].revents &= ~POLLOUT;
+                }
+
+            } while (loop && l > 0);
+
+            continue;
+        }
+
+        /* Try to read some data and pass it on to the source driver */
+
+        if (u->source && u->source->thread_info.state == PA_SOURCE_RUNNING && ((pollfd[POLLFD_DSP].revents & POLLIN))) {
+            void *p;
+            ssize_t l;
+            pa_memchunk memchunk;
+            int loop = 0;
+
+            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 = 0;
+                } else {
+                    if (info.bytes >= l) {
+                        l = (info.bytes/l)*l;
+                        loop = 1;
+                    }
+                }
+            }
+
+            do {
+                ssize_t t;
+
+                pa_assert(l > 0);
+
+                memchunk.memblock = pa_memblock_new(u->core->mempool, l);
+
+                p = pa_memblock_acquire(memchunk.memblock);
+                t = pa_read(u->fd, p, l, &read_type);
+                pa_memblock_release(memchunk.memblock);
+
+                pa_assert(t != 0); /* EOF cannot happen */
+
+                if (t < 0) {
+                    pa_memblock_unref(memchunk.memblock);
+
+                    if (errno == EINTR)
+                        continue;
+
+                    else if (errno == EAGAIN) {
+                        pollfd[POLLFD_DSP].revents &= ~POLLIN;
+                        break;
+
+                    } else {
+                        pa_log("Faile 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;
+
+                    pollfd[POLLFD_DSP].revents &= ~POLLIN;
+                }
+            } while (loop && l > 0);
+
+            continue;
+        }
+
+
+        if (u->fd >= 0) {
+            pollfd[POLLFD_DSP].fd = u->fd;
+            pollfd[POLLFD_DSP].events =
+                ((u->source && u->source->thread_info.state == PA_SOURCE_RUNNING) ? POLLIN : 0) |
+                ((u->sink && u->sink->thread_info.state == PA_SINK_RUNNING) ? POLLOUT : 0);
+        }
+            
+        /* Hmm, nothing to do. Let's sleep */
+
+        if (pa_asyncmsgq_before_poll(u->asyncmsgq) < 0)
+            continue;
+
+/*         pa_log("polling for %u", pollfd[POLLFD_DSP].events);  */
+        r = poll(pollfd, u->fd >= 0 ? POLLFD_MAX : POLLFD_DSP, -1);
+/*         pa_log("polling got %u", r > 0 ? pollfd[POLLFD_DSP].revents : 0);  */
+
+        pa_asyncmsgq_after_poll(u->asyncmsgq);
+
+        if (u->fd < 0)
+            pollfd[POLLFD_DSP].revents = 0;
+        
+        if (r < 0) {
+            if (errno == EINTR)
+                continue;
+
+            pa_log("poll() failed: %s", pa_cstrerror(errno));
+            goto fail;
+        }
+
+        if (pollfd[POLLFD_DSP].revents & ~(POLLOUT|POLLIN)) {
+            pa_log("DSP shutdown.");
+            goto fail;
+        }
+
+        pa_assert((pollfd[POLLFD_ASYNCQ].revents & ~POLLIN) == 0);
     }
 
-    return 0;
+fail:
+    /* We have to continue processing messages until we receive the
+     * SHUTDOWN message */
+    pa_asyncmsgq_post(u->core->asyncmsgq, PA_MSGOBJECT(u->core), PA_CORE_MESSAGE_UNLOAD_MODULE, u->module, NULL, NULL);
+    pa_asyncmsgq_wait_for(u->asyncmsgq, PA_MESSAGE_SHUTDOWN);
+
+finish:
+    pa_log_debug("Thread shutting down");
 }
 
 int pa__init(pa_core *c, pa_module*m) {
@@ -380,7 +649,7 @@ int pa__init(pa_core *c, pa_module*m) {
     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;
     }
 
@@ -390,15 +659,15 @@ 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;
     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;
     }
 
@@ -407,7 +676,7 @@ int pa__init(pa_core *c, pa_module*m) {
     frag_size = pa_bytes_per_second(&ss)/128;
 
     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;
     }
 
@@ -415,11 +684,11 @@ int pa__init(pa_core *c, pa_module*m) {
         goto fail;
 
     if (pa_oss_get_hw_description(p, hwdesc, sizeof(hwdesc)) >= 0)
-        pa_log_info("hardware name is '%s'.", hwdesc);
+        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)
@@ -435,18 +704,27 @@ int pa__init(pa_core *c, pa_module*m) {
     assert(frag_size);
     in_frag_size = out_frag_size = frag_size;
 
-    u = pa_xmalloc(sizeof(struct userdata));
+    u = pa_xnew0(struct userdata, 1);
     u->core = c;
+    u->module = m;
+    m->userdata = u;
     u->use_getospace = u->use_getispace = 0;
+    u->use_getodelay = 0;
+    u->use_input_volume = u->use_pcm_volume = 0;
+    u->mode = mode;
+    u->device_name = pa_xstrdup(p);
+    u->nfrags = nfrags;
+    u->frag_size = frag_size;
+    pa_assert_se(u->asyncmsgq = pa_asyncmsgq_new(0));
 
     if (ioctl(fd, SNDCTL_DSP_GETISPACE, &info) >= 0) {
-        pa_log_info("input -- %u fragments of size %u.", info.fragstotal, info.fragsize);
+        pa_log_info("Input -- %u fragments of size %u.", info.fragstotal, info.fragsize);
         in_frag_size = info.fragsize;
         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);
+        pa_log_info("Output -- %u fragments of size %u.", info.fragstotal, info.fragsize);
         out_frag_size = info.fragsize;
         u->use_getospace = 1;
     }
@@ -462,12 +740,11 @@ int pa__init(pa_core *c, pa_module*m) {
         if (!(u->source = pa_source_new(c, __FILE__, name, namereg_fail, &ss, &map)))
             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_module(u->source, m);
+        pa_source_set_asyncmsgq(u->source, u->asyncmsgq);
         pa_source_set_description(u->source, t = pa_sprintf_malloc("OSS PCM on %s%s%s%s",
                                                                  p,
                                                                  hwdesc[0] ? " (" : "",
@@ -475,6 +752,7 @@ int pa__init(pa_core *c, pa_module*m) {
                                                                  hwdesc[0] ? ")" : ""));
         pa_xfree(t);
         u->source->is_hardware = 1;
+        u->source->refresh_volume = 1;
     } else
         u->source = NULL;
 
@@ -492,11 +770,11 @@ int pa__init(pa_core *c, pa_module*m) {
         if (!(u->sink = pa_sink_new(c, __FILE__, name, namereg_fail, &ss, &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->parent.process_msg = sink_process_msg;
         u->sink->userdata = u;
-        pa_sink_set_owner(u->sink, m);
+        
+        pa_sink_set_module(u->sink, m);
+        pa_sink_set_asyncmsgq(u->sink, u->asyncmsgq);
         pa_sink_set_description(u->sink, t = pa_sprintf_malloc("OSS PCM on %s%s%s%s",
                                                            p,
                                                            hwdesc[0] ? " (" : "",
@@ -504,6 +782,7 @@ int pa__init(pa_core *c, pa_module*m) {
                                                            hwdesc[0] ? ")" : ""));
         pa_xfree(t);
         u->sink->is_hardware = 1;
+        u->sink->refresh_volume = 1;
     } else
         u->sink = NULL;
 
@@ -512,42 +791,26 @@ int pa__init(pa_core *c, pa_module*m) {
 
     assert(u->source || u->sink);
 
-    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;
 
-    u->memchunk.memblock = NULL;
-    u->memchunk.length = 0;
+    pa_memchunk_reset(&u->memchunk);
     u->sample_size = pa_frame_size(&ss);
 
     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;
 
-    u->module = m;
-    m->userdata = u;
+    if (!(u->thread = pa_thread_new(thread_func, u))) {
+        pa_log("Failed to create thread.");
+        goto fail;
+    }
 
     pa_modargs_free(ma);
 
-    /*
-     * 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);
-    }
-
     /* Read mixer settings */
     if (u->source)
-        source_get_hw_volume(u->source);
+        pa_asyncmsgq_post(u->asyncmsgq, PA_MSGOBJECT(u->source), PA_SOURCE_MESSAGE_GET_VOLUME, &u->source->volume, NULL, NULL);
     if (u->sink)
-        sink_get_hw_volume(u->sink);
+        pa_asyncmsgq_post(u->asyncmsgq, PA_MSGOBJECT(u->sink), PA_SINK_MESSAGE_GET_VOLUME, &u->sink->volume, NULL, NULL);
 
     return 0;
 
@@ -572,12 +835,33 @@ void pa__done(pa_core *c, pa_module*m) {
     if (!(u = m->userdata))
         return;
 
-    clear_up(u);
+    if (u->sink)
+        pa_sink_disconnect(u->sink);
+
+    if (u->source)
+        pa_source_disconnect(u->source);
+
+    if (u->thread) {
+        pa_asyncmsgq_send(u->asyncmsgq, NULL, PA_MESSAGE_SHUTDOWN, NULL, NULL);
+        pa_thread_free(u->thread);
+    }
+
+    if (u->asyncmsgq)
+        pa_asyncmsgq_free(u->asyncmsgq);
+
+    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->fd >= 0)
+        close(u->fd);
+
+    pa_xfree(u->device_name);
+    
     pa_xfree(u);
 }

commit fdd3ac97ff17505454ae1af7ce9fe2f56c86f4fb
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sun Jun 24 16:06:32 2007 +0000

    Make use of dbus_watch_get_unix_fd() instead of dbus_watch_get_fd() because of deprecation of the latter
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1492 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/dbus-util.c b/src/modules/dbus-util.c
index 48a4517..7cd9c1d 100644
--- a/src/modules/dbus-util.c
+++ b/src/modules/dbus-util.c
@@ -93,7 +93,7 @@ static void handle_io_event(PA_GCC_UNUSED pa_mainloop_api *ea, pa_io_event *e,
     unsigned int flags = 0;
     DBusWatch *watch = (DBusWatch*) userdata;
 
-    assert(fd == dbus_watch_get_fd(watch));
+    assert(fd == dbus_watch_get_unix_fd(watch));
 
     if (!dbus_watch_get_enabled(watch)) {
         pa_log_warn("Asked to handle disabled watch: %p %i",
@@ -135,7 +135,7 @@ static dbus_bool_t add_watch(DBusWatch *watch, void *data)
     pa_io_event *ev;
     pa_core *c = (pa_core*) data;
 
-    ev = c->mainloop->io_new(c->mainloop, dbus_watch_get_fd(watch),
+    ev = c->mainloop->io_new(c->mainloop, dbus_watch_get_unix_fd(watch),
                              get_watch_flags(watch),
                              handle_io_event, (void*) watch);
     if (NULL == ev)

commit a9fcd5956b3e91c9ecf1ab43562d4d54ada29e3e
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sun Jun 24 16:09:43 2007 +0000

    Fix length calculation in pa_silence_memblock_new() and make use of pa_assert() everywhere instead of assert()
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1493 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/sample-util.c b/src/pulsecore/sample-util.c
index 2e51427..4603f7e 100644
--- a/src/pulsecore/sample-util.c
+++ b/src/pulsecore/sample-util.c
@@ -28,12 +28,12 @@
 
 #include <stdio.h>
 #include <string.h>
-#include <assert.h>
 #include <stdlib.h>
 
 #include <liboil/liboilfuncs.h>
 
 #include <pulsecore/log.h>
+#include <pulsecore/macro.h>
 
 #include "sample-util.h"
 #include "endianmacros.h"
@@ -42,20 +42,23 @@
 
 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);
 }
@@ -63,8 +66,8 @@ pa_memblock *pa_silence_memblock_new(pa_mempool *pool, const pa_sample_spec *spe
 pa_memblock *pa_silence_memblock(pa_memblock* b, const pa_sample_spec *spec) {
     void *data;
 
-    assert(b);
-    assert(spec);
+    pa_assert(b);
+    pa_assert(spec);
 
     data = pa_memblock_acquire(b);
     pa_silence_memory(data, pa_memblock_get_length(b), spec);
@@ -75,9 +78,9 @@ pa_memblock *pa_silence_memblock(pa_memblock* b, const pa_sample_spec *spec) {
 void pa_silence_memchunk(pa_memchunk *c, const pa_sample_spec *spec) {
     void *data;
 
-    assert(c);
-    assert(c->memblock);
-    assert(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);
@@ -86,7 +89,9 @@ void pa_silence_memchunk(pa_memchunk *c, const pa_sample_spec *spec) {
 
 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:
@@ -103,7 +108,7 @@ void pa_silence_memory(void *p, size_t length, const pa_sample_spec *spec) {
             c = 80;
             break;
         default:
-            assert(0);
+            pa_assert_not_reached();
     }
 
     memset(p, c, length);
@@ -122,10 +127,10 @@ size_t pa_mix(
     size_t d = 0;
     unsigned k;
 
-    assert(streams);
-    assert(data);
-    assert(length);
-    assert(spec);
+    pa_assert(streams);
+    pa_assert(data);
+    pa_assert(length);
+    pa_assert(spec);
 
     if (!volume)
         volume = pa_cvolume_reset(&full_volume, spec->channels);
@@ -347,10 +352,10 @@ void pa_volume_memchunk(
 
     void *ptr;
 
-    assert(c);
-    assert(spec);
-    assert(c->length % pa_frame_size(spec) == 0);
-    assert(volume);
+    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;

commit 099f3f22d16549f6e6e4f4fb71ffcf2e050ad232
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sun Jun 24 16:10:12 2007 +0000

    Include assert.h, since we use assert() for our pa_assert() macro
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1494 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/macro.h b/src/pulsecore/macro.h
index 215c5c0..e0381cf 100644
--- a/src/pulsecore/macro.h
+++ b/src/pulsecore/macro.h
@@ -25,6 +25,7 @@
 ***/
 
 #include <sys/types.h>
+#include <assert.h>
 #include <pulsecore/log.h>
 
 static inline size_t pa_align(size_t l) {

commit 77ebe7044350705648b082812d3580735127430a
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sun Jun 24 16:11:52 2007 +0000

    Make sure the returned pa_msgobject object has a valid refcnt before returning it
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1495 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/asyncmsgq.c b/src/pulsecore/asyncmsgq.c
index d650989..26714a0 100644
--- a/src/pulsecore/asyncmsgq.c
+++ b/src/pulsecore/asyncmsgq.c
@@ -153,18 +153,24 @@ int pa_asyncmsgq_get(pa_asyncmsgq *a, pa_msgobject **object, int *code, void **u
     pa_assert(code);
     pa_assert(!a->current);
 
-    if (!(a->current = pa_asyncq_pop(a->asyncq, wait)))
+    if (!(a->current = pa_asyncq_pop(a->asyncq, wait))) {
+/*         pa_log("failure"); */
         return -1;
+    }
+
+/*     pa_log("success"); */
 
     *code = a->current->code;
     if (userdata)
         *userdata = a->current->userdata;
-    if (object)
-        *object = a->current->object;
+    if (object) {
+        if ((*object = a->current->object))
+            pa_msgobject_assert_ref(*object);
+    }
     if (chunk)
         *chunk = a->current->memchunk;
 
-    pa_log_debug("q=%p object=%p (%s) code=%i data=%p chunk.length=%u", (void*) a, (void*) a->current->object, a->current->object ? a->current->object->parent.type_name : NULL, a->current->code, (void*) a->current->userdata, a->current->memchunk.length);
+    pa_log_debug("Get q=%p object=%p (%s) code=%i data=%p chunk.length=%u", (void*) a, (void*) a->current->object, a->current->object ? a->current->object->parent.type_name : NULL, a->current->code, (void*) a->current->userdata, a->current->memchunk.length);
     
     return 0;
 }

commit d87373181071afe38c35d997facee62f5a3cb604
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sun Jun 24 16:15:56 2007 +0000

    rework the logic of pa_asyncq
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1496 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/asyncq.c b/src/pulsecore/asyncq.c
index c966e7d..025c695 100644
--- a/src/pulsecore/asyncq.c
+++ b/src/pulsecore/asyncq.c
@@ -52,9 +52,10 @@ struct pa_asyncq {
     unsigned size;
     unsigned read_idx;
     unsigned write_idx;
-    pa_atomic_t read_waiting, n_read;
-    pa_atomic_t write_waiting, n_written;
+    pa_atomic_t read_waiting; /* a bool */
+    pa_atomic_t write_waiting; /* a bool */
     int read_fds[2], write_fds[2];
+    pa_atomic_t in_read_fifo, in_write_fifo;
 };
 
 #define PA_ASYNCQ_CELLS(x) ((pa_atomic_ptr_t*) ((uint8_t*) (x) + PA_ALIGN(sizeof(struct pa_asyncq))))
@@ -80,8 +81,8 @@ pa_asyncq *pa_asyncq_new(unsigned size) {
     l->size = size;
     pa_atomic_store(&l->read_waiting, 0);
     pa_atomic_store(&l->write_waiting, 0);
-    pa_atomic_store(&l->n_written, 0);
-    pa_atomic_store(&l->n_read, 0);
+    pa_atomic_store(&l->in_read_fifo, 0);
+    pa_atomic_store(&l->in_write_fifo, 0);
 
     if (pipe(l->read_fds) < 0) {
         pa_xfree(l);
@@ -133,68 +134,79 @@ int pa_asyncq_push(pa_asyncq*l, void *p, int wait) {
 
     if (!pa_atomic_ptr_cmpxchg(&cells[idx], NULL, p)) {
 
-        if (!wait) {
-            /* Let's empty the FIFO from old notifications, before we return */
+        /* Let's empty the FIFO from old notifications, before we return */
             
-            while (pa_atomic_load(&l->n_read) > 0) {
-                ssize_t r;
-                int x[20];
-                
-                errno = 0;
-                if ((r = read(l->write_fds[0], x, sizeof(x))) < 0 && errno != EINTR)
-                    return -1;
+        while (pa_atomic_load(&l->in_write_fifo) > 0) {
+            ssize_t r;
+            int x[20];
+
+            if ((r = read(l->write_fds[0], x, sizeof(x))) < 0) {
 
-                pa_assert(r != 0);
+                if (errno == EINTR)
+                    continue;
                 
-                if (r > 0)
-                    if (pa_atomic_sub(&l->n_read, r) <= r)
-                        break;
+                return -1;
             }
-            
-            return -1;
-        }
-
-        /* First try failed. Let's wait for changes. */
 
-        _Y;
+            pa_assert(r > 0);
+                
+            if (pa_atomic_sub(&l->in_write_fifo, r) <= r)
+                break;
 
-        pa_atomic_inc(&l->write_waiting);
+        }
 
-        for (;;) {
-            char x[20];
-            ssize_t r;
+        /* Now let's make sure that we didn't lose any events */
+        if (!pa_atomic_ptr_cmpxchg(&cells[idx], NULL, p)) {
 
-            _Y;
+            if (!wait)
+                return -1;
 
-            if (pa_atomic_ptr_cmpxchg(&cells[idx], NULL, p))
-                break;
+            /* Let's wait for changes. */
 
             _Y;
 
-            if ((r = read(l->write_fds[0], x, sizeof(x))) < 0 && errno != EINTR) {
-                pa_atomic_dec(&l->write_waiting);
-                return -1;
-            }
+            pa_assert_se(pa_atomic_cmpxchg(&l->write_waiting, 0, 1));
 
-            pa_assert(r != 0);
+            for (;;) {
+                char x[20];
+                ssize_t r;
+                
+                _Y;
+                
+                if (pa_atomic_ptr_cmpxchg(&cells[idx], NULL, p))
+                    break;
+                
+                _Y;
 
-            if (r > 0)
-                pa_atomic_sub(&l->n_read, r);
-        }
+                if ((r = read(l->write_fds[0], x, sizeof(x))) < 0) {
 
-        _Y;
+                    if (errno == EINTR)
+                        continue;
+                    
+                    pa_assert_se(pa_atomic_cmpxchg(&l->write_waiting, 1, 0));
+                    return -1;
+                }
 
-        pa_atomic_dec(&l->write_waiting);
+                pa_assert(r > 0);
+                pa_atomic_sub(&l->in_write_fifo, r);
+            }
+            
+            _Y;
+            
+            pa_assert_se(pa_atomic_cmpxchg(&l->write_waiting, 1, 0));
+        }
     }
 
     _Y;
     l->write_idx++;
 
-    if (pa_atomic_load(&l->read_waiting)) {
+    if (pa_atomic_load(&l->read_waiting) > 0) {
         char x = 'x';
         _Y;
-        if (write(l->read_fds[1], &x, sizeof(x)) > 0)
-            pa_atomic_inc(&l->n_written);
+        if (write(l->read_fds[1], &x, sizeof(x)) > 0) {
+            pa_atomic_inc(&l->in_read_fifo);
+/*             pa_log("increasing %p by 1", l); */
+        }
     }
 
     return 0;
@@ -206,7 +218,7 @@ void* pa_asyncq_pop(pa_asyncq*l, int wait) {
     pa_atomic_ptr_t *cells;
 
     pa_assert(l);
-
+    
     cells = PA_ASYNCQ_CELLS(l);
 
     _Y;
@@ -214,71 +226,86 @@ void* pa_asyncq_pop(pa_asyncq*l, int wait) {
 
     if (!(ret = pa_atomic_ptr_load(&cells[idx]))) {
 
-        /* First try failed. Let's wait for changes. */
+/*         pa_log("pop failed wait=%i", wait); */
 
-        if (!wait) {
-            /* Let's empty the FIFO from old notifications, before we return */
+        /* Hmm, nothing, here, so let's drop all queued events. */
+        while (pa_atomic_load(&l->in_read_fifo) > 0) {
+            ssize_t r;
+            int x[20];
             
-            while (pa_atomic_load(&l->n_written) > 0) {
-                ssize_t r;
-                int x[20];
+            if ((r = read(l->read_fds[0], x, sizeof(x))) < 0) {
                 
-                errno = 0;
-                if ((r = read(l->read_fds[0], x, sizeof(x))) < 0 && errno != EINTR)
-                    return NULL;
-
-                pa_assert(r != 0);
+                if (errno == EINTR)
+                    continue;
                 
-                if (r > 0)
-                    if (pa_atomic_sub(&l->n_written, r) <= r)
-                        break;
+                return NULL;
             }
+
+            pa_assert(r > 0);
+
+/*             pa_log("decreasing %p by %i", l, r); */
             
-            return NULL;
+            if (pa_atomic_sub(&l->in_read_fifo, r) <= r)
+                break;
         }
 
-        _Y;
-
-        pa_atomic_inc(&l->read_waiting);
+        /* Now let's make sure that we didn't lose any events */
+        if (!(ret = pa_atomic_ptr_load(&cells[idx]))) {
 
-        for (;;) {
-            char x[20];
-            ssize_t r;
+            if (!wait)
+                return NULL;
 
+            /* Let's wait for changes. */
+            
             _Y;
+            
+            pa_assert_se(pa_atomic_cmpxchg(&l->read_waiting, 0, 1));
+            
+            for (;;) {
+                char x[20];
+                ssize_t r;
+                
+                _Y;
+                
+                if ((ret = pa_atomic_ptr_load(&cells[idx])))
+                    break;
+                
+                _Y;
+                
+                if ((r = read(l->read_fds[0], x, sizeof(x))) < 0) {
 
-            if ((ret = pa_atomic_ptr_load(&cells[idx])))
-                break;
-
-            _Y;
+                    if (errno == EINTR)
+                        continue;
+                    
+                    pa_assert_se(pa_atomic_cmpxchg(&l->read_waiting, 1, 0));
+                    return NULL;
+                }
 
-            if ((r = read(l->read_fds[0], x, sizeof(x))) < 0 && errno != EINTR) {
-                pa_atomic_dec(&l->read_waiting);
-                return NULL;
+/*                 pa_log("decreasing %p by %i", l, r); */
+                
+                pa_assert(r > 0);
+                pa_atomic_sub(&l->in_read_fifo, r);
             }
 
-            pa_assert(r != 0);
+            _Y;
 
-            if (r > 0)
-                pa_atomic_sub(&l->n_written, r);
+            pa_assert_se(pa_atomic_cmpxchg(&l->read_waiting, 1, 0));
         }
-
-        _Y;
-
-        pa_atomic_dec(&l->read_waiting);
     }
 
+    pa_assert(ret);
+
     /* Guaranteed if we only have a single reader */
     pa_assert_se(pa_atomic_ptr_cmpxchg(&cells[idx], ret, NULL));
 
     _Y;
     l->read_idx++;
 
-    if (pa_atomic_load(&l->write_waiting)) {
+    if (pa_atomic_load(&l->write_waiting) > 0) {
         char x = 'x';
         _Y;
         if (write(l->write_fds[1], &x, sizeof(x)) >= 0)
-            pa_atomic_inc(&l->n_read);
+            pa_atomic_inc(&l->in_write_fifo);
     }
 
     return ret;
@@ -301,13 +328,13 @@ int pa_asyncq_before_poll(pa_asyncq *l) {
     _Y;
     idx = reduce(l, l->read_idx);
 
-    if (pa_atomic_ptr_load(&cells[idx]))
+    if (pa_atomic_ptr_load(&cells[idx]) || pa_atomic_load(&l->in_read_fifo) > 0)
         return -1;
 
-    pa_atomic_inc(&l->read_waiting);
+    pa_assert_se(pa_atomic_cmpxchg(&l->read_waiting, 0, 1));
 
-    if (pa_atomic_ptr_load(&cells[idx])) {
-        pa_atomic_dec(&l->read_waiting);
+    if (pa_atomic_ptr_load(&cells[idx]) || pa_atomic_load(&l->in_read_fifo) > 0) {
+        pa_assert_se(pa_atomic_cmpxchg(&l->read_waiting, 1, 0));
         return -1;
     }
 
@@ -317,7 +344,5 @@ int pa_asyncq_before_poll(pa_asyncq *l) {
 void pa_asyncq_after_poll(pa_asyncq *l) {
     pa_assert(l);
 
-    pa_assert(pa_atomic_load(&l->read_waiting) > 0);
-
-    pa_atomic_dec(&l->read_waiting);
+    pa_assert_se(pa_atomic_cmpxchg(&l->read_waiting, 1, 0));
 }

commit de02c74916d60db6454a6691aca0b8401b9c88fd
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sun Jun 24 16:17:02 2007 +0000

    Track the 'missing' variable safely between the threads
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1497 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/protocol-simple.c b/src/pulsecore/protocol-simple.c
index 0e978c6..fd304c6 100644
--- a/src/pulsecore/protocol-simple.c
+++ b/src/pulsecore/protocol-simple.c
@@ -123,7 +123,7 @@ static void connection_free(pa_object *o) {
 static void connection_drop(connection *c) {
     pa_assert(c);
     
-    pa_idxset_remove_by_data(c->protocol->connections, c, NULL);
+    pa_assert_se(pa_idxset_remove_by_data(c->protocol->connections, c, NULL) == c);
 
     if (c->sink_input) {
         pa_sink_input_disconnect(c->sink_input);
@@ -153,7 +153,7 @@ static int do_read(connection *c) {
 
     pa_assert(c);
 
-    if (!c->sink_input || !(l = pa_atomic_load(&c->playback.missing)))
+    if (!c->sink_input || (l = pa_atomic_load(&c->playback.missing)) <= 0)
         return 0;
 
     if (l > c->playback.fragment_size)
@@ -191,6 +191,7 @@ static int do_read(connection *c) {
     c->playback.memblock_index += r;
 
     pa_asyncmsgq_post(c->sink_input->sink->asyncmsgq, PA_MSGOBJECT(c->sink_input), SINK_INPUT_MESSAGE_POST_DATA, NULL, &chunk, NULL);
+    pa_atomic_sub(&c->playback.missing, r);
 
     return 0;
 }
@@ -309,7 +310,6 @@ static int sink_input_process_msg(pa_msgobject *o, int code, void *userdata, pa_
 
             /* New data from the main loop */
             pa_memblockq_push_align(c->input_memblockq, chunk);
-            pa_atomic_store(&c->playback.missing, pa_memblockq_missing(c->input_memblockq));
 
 /*             pa_log("got data, %u", pa_memblockq_get_length(c->input_memblockq)); */
             
@@ -368,10 +368,10 @@ static void sink_input_drop_cb(pa_sink_input *i, const pa_memchunk *chunk, size_
     pa_memblockq_drop(c->input_memblockq, chunk, length);
     new = pa_memblockq_missing(c->input_memblockq);
 
-    pa_atomic_store(&c->playback.missing, new);
-
-    if (new > old)
-        pa_asyncmsgq_post(c->protocol->core->asyncmsgq, PA_MSGOBJECT(c), MESSAGE_REQUEST_DATA, NULL, NULL, NULL);
+    if (new > old) {
+        if (pa_atomic_add(&c->playback.missing, new - old) <= 0)
+            pa_asyncmsgq_post(c->protocol->core->asyncmsgq, PA_MSGOBJECT(c), MESSAGE_REQUEST_DATA, NULL, NULL, NULL);
+    }
 }
 
 /* Called from main context */

commit 67766785a587ead4bf604ae789bc1112783ad97c
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sun Jun 24 16:17:30 2007 +0000

    Limit silence buffer size for pa_sink_render()
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1498 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c
index 11effe2..d5ca061 100644
--- a/src/pulsecore/sink.c
+++ b/src/pulsecore/sink.c
@@ -46,6 +46,7 @@
 #include "sink.h"
 
 #define MAX_MIX_CHANNELS 32
+#define SILENCE_BUFFER_LENGTH (64*1024)
 
 static PA_DEFINE_CHECK_TYPE(pa_sink, sink_check_type, pa_msgobject_check_type);
 
@@ -364,6 +365,9 @@ void pa_sink_render(pa_sink*s, size_t length, pa_memchunk *result) {
 
     if (n == 0) {
 
+        if (length > SILENCE_BUFFER_LENGTH)
+            length = SILENCE_BUFFER_LENGTH;
+
         if (!s->silence || pa_memblock_get_length(s->silence) < length) {
             if (s->silence)
                 pa_memblock_unref(s->silence);

commit a482b9fd99a970cda92bef53dfac500c4ad6ecd9
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Jun 25 22:33:04 2007 +0000

    make sure we don't free the same connection twice
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1499 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/protocol-simple.c b/src/pulsecore/protocol-simple.c
index fd304c6..c423487 100644
--- a/src/pulsecore/protocol-simple.c
+++ b/src/pulsecore/protocol-simple.c
@@ -123,7 +123,8 @@ static void connection_free(pa_object *o) {
 static void connection_drop(connection *c) {
     pa_assert(c);
     
-    pa_assert_se(pa_idxset_remove_by_data(c->protocol->connections, c, NULL) == c);
+    if (!pa_idxset_remove_by_data(c->protocol->connections, c, NULL))
+        return;
 
     if (c->sink_input) {
         pa_sink_input_disconnect(c->sink_input);

commit 63129389c9d8396b8ea819afb217b6da0b2d6a18
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Jun 25 22:53:09 2007 +0000

    remove pa_memblockq_is_writable() (because it is stupid and not used anywhere anyway, and replace all assert()s with pa_assert()s
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1500 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/memblockq.c b/src/pulsecore/memblockq.c
index a80df33..0c31166 100644
--- a/src/pulsecore/memblockq.c
+++ b/src/pulsecore/memblockq.c
@@ -28,7 +28,6 @@
 #include <sys/time.h>
 #include <time.h>
 #include <stdio.h>
-#include <assert.h>
 #include <stdlib.h>
 #include <string.h>
 
@@ -36,6 +35,7 @@
 
 #include <pulsecore/log.h>
 #include <pulsecore/mcalign.h>
+#include <pulsecore/macro.h>
 
 #include "memblockq.h"
 
@@ -66,8 +66,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;
@@ -80,7 +80,7 @@ pa_memblockq* pa_memblockq_new(
         (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)
@@ -110,7 +110,7 @@ pa_memblockq* pa_memblockq_new(
 }
 
 void pa_memblockq_free(pa_memblockq* bq) {
-    assert(bq);
+    pa_assert(bq);
 
     pa_memblockq_flush(bq);
 
@@ -124,10 +124,10 @@ void pa_memblockq_free(pa_memblockq* bq) {
 }
 
 static void drop_block(pa_memblockq *bq, struct memblock_list *q) {
-    assert(bq);
-    assert(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;
@@ -148,7 +148,7 @@ static void drop_block(pa_memblockq *bq, struct memblock_list *q) {
 static int 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;
@@ -174,11 +174,11 @@ int pa_memblockq_push(pa_memblockq* bq, const pa_memchunk *uchunk) {
     struct memblock_list *q, *n;
     pa_memchunk chunk;
 
-    assert(bq);
-    assert(uchunk);
-    assert(uchunk->memblock);
-    assert(uchunk->length > 0);
-    assert(uchunk->index + uchunk->length <= pa_memblock_get_length(uchunk->memblock));
+    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;
@@ -244,7 +244,7 @@ int pa_memblockq_push(pa_memblockq* bq, const pa_memchunk *uchunk) {
 
                 /* 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;
@@ -274,7 +274,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);
 
@@ -291,8 +291,8 @@ int pa_memblockq_push(pa_memblockq* bq, const pa_memchunk *uchunk) {
     }
 
     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 */
 
@@ -305,7 +305,7 @@ int pa_memblockq_push(pa_memblockq* bq, const pa_memchunk *uchunk) {
             return 0;
         }
     } 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));
 
 
     n = pa_xnew(struct memblock_list, 1);
@@ -332,8 +332,8 @@ int pa_memblockq_push(pa_memblockq* bq, const pa_memchunk *uchunk) {
 }
 
 int pa_memblockq_peek(pa_memblockq* bq, pa_memchunk *chunk) {
-    assert(bq);
-    assert(chunk);
+    pa_assert(bq);
+    pa_assert(chunk);
 
     if (bq->state == PREBUF) {
 
@@ -382,7 +382,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);
@@ -391,10 +391,9 @@ int pa_memblockq_peek(pa_memblockq* bq, pa_memchunk *chunk) {
 }
 
 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);
+    pa_assert(bq);
+    pa_assert(length % bq->base == 0);
+    pa_assert(!chunk || length <= chunk->length);
 
     if (chunk) {
 
@@ -410,7 +409,7 @@ void pa_memblockq_drop(pa_memblockq *bq, const pa_memchunk *chunk, size_t length
 
             /* The first item in the queue is not yet relevant */
 
-            assert(!bq->blocks || bq->blocks->index > bq->read_index);
+            pa_assert(!bq->blocks || bq->blocks->index > bq->read_index);
             l = bq->blocks ? bq->blocks->index - bq->read_index : 0;
 
             if (bq->silence) {
@@ -431,7 +430,7 @@ void pa_memblockq_drop(pa_memblockq *bq, const pa_memchunk *chunk, size_t length
         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 +445,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 */
@@ -475,7 +474,7 @@ void pa_memblockq_drop(pa_memblockq *bq, const pa_memchunk *chunk, size_t length
 }
 
 int pa_memblockq_is_readable(pa_memblockq *bq) {
-    assert(bq);
+    pa_assert(bq);
 
     if (bq->prebuf > 0) {
         size_t l = pa_memblockq_get_length(bq);
@@ -490,17 +489,8 @@ int pa_memblockq_is_readable(pa_memblockq *bq) {
     return 1;
 }
 
-int pa_memblockq_is_writable(pa_memblockq *bq, size_t length) {
-    assert(bq);
-
-    if (length % bq->base)
-        return 0;
-
-    return pa_memblockq_get_length(bq) + length <= bq->tlength;
-}
-
 size_t pa_memblockq_get_length(pa_memblockq *bq) {
-    assert(bq);
+    pa_assert(bq);
 
     if (bq->write_index <= bq->read_index)
         return 0;
@@ -510,7 +500,7 @@ 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;
@@ -520,13 +510,13 @@ size_t pa_memblockq_missing(pa_memblockq *bq) {
 }
 
 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);
+    pa_assert(bq);
 
     switch (seek) {
         case PA_SEEK_RELATIVE:
@@ -543,16 +533,16 @@ void pa_memblockq_seek(pa_memblockq *bq, int64_t offset, pa_seek_mode_t seek) {
             return;
     }
 
-    assert(0);
+    pa_assert_not_reached();
 }
 
 void pa_memblockq_flush(pa_memblockq *bq) {
-    assert(bq);
+    pa_assert(bq);
 
     while (bq->blocks)
         drop_block(bq, bq->blocks);
 
-    assert(bq->n_blocks == 0);
+    pa_assert(bq->n_blocks == 0);
 
     bq->write_index = bq->read_index;
 
@@ -560,26 +550,26 @@ void pa_memblockq_flush(pa_memblockq *bq) {
 }
 
 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 && bq->base);
 
     if (bq->base == 1)
         return pa_memblockq_push(bq, chunk);
@@ -606,7 +596,7 @@ 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);
 
@@ -615,27 +605,27 @@ void pa_memblockq_shorten(pa_memblockq *bq, size_t length) {
 }
 
 void pa_memblockq_prebuf_disable(pa_memblockq *bq) {
-    assert(bq);
+    pa_assert(bq);
 
     if (bq->state == PREBUF)
         bq->state = RUNNING;
 }
 
 void pa_memblockq_prebuf_force(pa_memblockq *bq) {
-    assert(bq);
+    pa_assert(bq);
 
     if (bq->state == RUNNING && bq->prebuf > 0)
         bq->state = PREBUF;
 }
 
 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;
 }
diff --git a/src/pulsecore/memblockq.h b/src/pulsecore/memblockq.h
index c049d78..e824356 100644
--- a/src/pulsecore/memblockq.h
+++ b/src/pulsecore/memblockq.h
@@ -94,9 +94,6 @@ void pa_memblockq_drop(pa_memblockq *bq, const pa_memchunk *chunk, 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);
 

commit eec2fbe6232eedc2decb6b7808ae14dfd6c9f974
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Jun 25 22:54:06 2007 +0000

    Port module-oss to the new lock-free core
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1501 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-oss.c b/src/modules/module-oss.c
index 01fe2b6..d8ff95b 100644
--- a/src/modules/module-oss.c
+++ b/src/modules/module-oss.c
@@ -56,6 +56,7 @@
 #include <fcntl.h>
 #include <unistd.h>
 #include <limits.h>
+#include <signal.h>
 
 #include <pulse/xmalloc.h>
 #include <pulse/util.h>
@@ -138,7 +139,7 @@ static int suspend(struct userdata *u) {
     pa_assert(u->fd >= 0);
 
     /* Let's suspend */
-    ioctl(u->fd, SNDCTL_DSP_SYNC);
+    ioctl(u->fd, SNDCTL_DSP_SYNC, NULL);
     close(u->fd);
     u->fd = -1;
     
@@ -180,7 +181,7 @@ static int unsuspend(struct userdata *u) {
     }
 
     if (ioctl(u->fd, SNDCTL_DSP_GETBLKSIZE, &frag_size) < 0) {
-        pa_log("SNDCTL_DSP_GETBLKSIZE: %s", pa_cstrerror(errno));
+        pa_log_warn("SNDCTL_DSP_GETBLKSIZE: %s", pa_cstrerror(errno));
         goto fail;
     }
 
@@ -256,9 +257,6 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, pa_memchunk *
 
         case PA_SINK_MESSAGE_SET_STATE:
 
-            if (PA_PTR_TO_UINT(data) != PA_SINK_RUNNING && u->fd >= 0)
-                ioctl(u->fd, SNDCTL_DSP_POST);
-
             if (PA_PTR_TO_UINT(data) == PA_SINK_SUSPENDED) {
                 pa_assert(u->sink->thread_info.state != PA_SINK_SUSPENDED);
 
@@ -425,10 +423,14 @@ static void thread_func(void *userdata) {
         pa_memchunk chunk;
         int r;
 
+/*         pa_log("loop"); */
+        
         /* Check whether there is a message for us to process */
         if (pa_asyncmsgq_get(u->asyncmsgq, &object, &code, &data, &chunk, 0) == 0) {
             int ret;
 
+/*             pa_log("processing msg"); */
+
             if (!object && code == PA_MESSAGE_SHUTDOWN) {
                 pa_asyncmsgq_done(u->asyncmsgq, 0);
                 goto finish;
@@ -437,11 +439,13 @@ static void thread_func(void *userdata) {
             ret = pa_asyncmsgq_dispatch(object, code, data, &chunk);
             pa_asyncmsgq_done(u->asyncmsgq, ret);
             continue;
-        }
+        } 
+
+/*         pa_log("loop2"); */
 
         /* Render some data and write it to the dsp */
 
-        if (u->sink && u->sink->thread_info.state == PA_SINK_RUNNING && (pollfd[POLLFD_DSP].revents & POLLOUT)) {
+        if (u->sink && u->sink->thread_info.state != PA_SINK_SUSPENDED && (pollfd[POLLFD_DSP].revents & POLLOUT)) {
             ssize_t l;
             void *p;
             int loop = 0;
@@ -476,6 +480,8 @@ static void thread_func(void *userdata) {
                 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", t); */
+                
                 pa_assert(t != 0);
 
                 if (t < 0) {
@@ -515,7 +521,7 @@ static void thread_func(void *userdata) {
 
         /* Try to read some data and pass it on to the source driver */
 
-        if (u->source && u->source->thread_info.state == PA_SOURCE_RUNNING && ((pollfd[POLLFD_DSP].revents & POLLIN))) {
+        if (u->source && u->source->thread_info.state != PA_SOURCE_SUSPENDED && ((pollfd[POLLFD_DSP].revents & POLLIN))) {
             void *p;
             ssize_t l;
             pa_memchunk memchunk;
@@ -585,8 +591,8 @@ static void thread_func(void *userdata) {
         if (u->fd >= 0) {
             pollfd[POLLFD_DSP].fd = u->fd;
             pollfd[POLLFD_DSP].events =
-                ((u->source && u->source->thread_info.state == PA_SOURCE_RUNNING) ? POLLIN : 0) |
-                ((u->sink && u->sink->thread_info.state == PA_SINK_RUNNING) ? POLLOUT : 0);
+                ((u->source && u->source->thread_info.state != PA_SOURCE_SUSPENDED) ? POLLIN : 0) |
+                ((u->sink && u->sink->thread_info.state != PA_SINK_SUSPENDED) ? POLLOUT : 0);
         }
             
         /* Hmm, nothing to do. Let's sleep */
@@ -594,9 +600,9 @@ static void thread_func(void *userdata) {
         if (pa_asyncmsgq_before_poll(u->asyncmsgq) < 0)
             continue;
 
-/*         pa_log("polling for %u", pollfd[POLLFD_DSP].events);  */
+/*         pa_log("polling for %i", u->fd >= 0 ? pollfd[POLLFD_DSP].events : -1);    */
         r = poll(pollfd, u->fd >= 0 ? POLLFD_MAX : POLLFD_DSP, -1);
-/*         pa_log("polling got %u", r > 0 ? pollfd[POLLFD_DSP].revents : 0);  */
+/*         pa_log("polling got dsp=%i amq=%i (%i)", r > 0 ? pollfd[POLLFD_DSP].revents : 0, r > 0 ? pollfd[POLLFD_ASYNCQ].revents : 0, r);    */
 
         pa_asyncmsgq_after_poll(u->asyncmsgq);
 
@@ -611,6 +617,8 @@ static void thread_func(void *userdata) {
             goto fail;
         }
 
+        pa_assert(r > 0);
+
         if (pollfd[POLLFD_DSP].revents & ~(POLLOUT|POLLIN)) {
             pa_log("DSP shutdown.");
             goto fail;
@@ -708,9 +716,9 @@ int pa__init(pa_core *c, pa_module*m) {
     u->core = c;
     u->module = m;
     m->userdata = u;
-    u->use_getospace = u->use_getispace = 0;
-    u->use_getodelay = 0;
-    u->use_input_volume = u->use_pcm_volume = 0;
+    u->use_getospace = u->use_getispace = 1;
+    u->use_getodelay = 1;
+    u->use_input_volume = u->use_pcm_volume = 1;
     u->mode = mode;
     u->device_name = pa_xstrdup(p);
     u->nfrags = nfrags;

commit 683fc4cef8e0cd785a4af484bad48ba034cbd07a
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Jul 12 15:40:29 2007 +0000

    fix segfault when recording with module-oss.c
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1506 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-oss.c b/src/modules/module-oss.c
index d8ff95b..a0fc0aa 100644
--- a/src/modules/module-oss.c
+++ b/src/modules/module-oss.c
@@ -324,7 +324,7 @@ static int source_process_msg(pa_msgobject *o, int code, void *data, pa_memchunk
                     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->sink->sample_spec);
+                    r = pa_bytes_to_usec(info.bytes, &u->source->sample_spec);
             }
 
             *((pa_usec_t*) data) = r;

commit 1a84664edbb9acf460a020c6a2c3000369d44e3f
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Jul 12 16:00:51 2007 +0000

    Make sure pollfd[POLLFD_ASYNCQ].revents is properly initialized on signal
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1507 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-oss.c b/src/modules/module-oss.c
index a0fc0aa..f402fb6 100644
--- a/src/modules/module-oss.c
+++ b/src/modules/module-oss.c
@@ -142,6 +142,8 @@ static int suspend(struct userdata *u) {
     ioctl(u->fd, SNDCTL_DSP_SYNC, NULL);
     close(u->fd);
     u->fd = -1;
+
+    pa_log_debug("Device suspended...");
     
     return 0;
 }
@@ -208,6 +210,8 @@ static int unsuspend(struct userdata *u) {
         pa_xfree(buf);
     }
 
+    pa_log_debug("Resumed successfully...");
+
     return 0;
 
 fail:
@@ -610,8 +614,11 @@ static void thread_func(void *userdata) {
             pollfd[POLLFD_DSP].revents = 0;
         
         if (r < 0) {
-            if (errno == EINTR)
+            if (errno == EINTR) {
+                pollfd[POLLFD_ASYNCQ].revents = 0;
+                pollfd[POLLFD_DSP].revents = 0;
                 continue;
+            }
 
             pa_log("poll() failed: %s", pa_cstrerror(errno));
             goto fail;

commit 0a095f6266e44df8b2ddf10fa0ee82159bcd65db
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Jul 12 16:15:35 2007 +0000

    Properly initialize all revents on EINTR
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1508 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-null-sink.c b/src/modules/module-null-sink.c
index 3e471d4..bb0a504 100644
--- a/src/modules/module-null-sink.c
+++ b/src/modules/module-null-sink.c
@@ -175,8 +175,10 @@ static void thread_func(void *userdata) {
         pa_asyncmsgq_after_poll(u->asyncmsgq);
 
         if (r < 0) {
-            if (errno == EINTR)
+            if (errno == EINTR) {
+                pollfd.revents = 0;
                 continue;
+            }
 
             pa_log("poll() failed: %s", pa_cstrerror(errno));
             goto fail;
diff --git a/src/modules/module-pipe-sink.c b/src/modules/module-pipe-sink.c
index e27a237..db8b2e1 100644
--- a/src/modules/module-pipe-sink.c
+++ b/src/modules/module-pipe-sink.c
@@ -203,8 +203,11 @@ static void thread_func(void *userdata) {
         pa_asyncmsgq_after_poll(u->asyncmsgq);
 
         if (r < 0) {
-            if (errno == EINTR)
+            if (errno == EINTR) {
+                pollfd[POLLFD_ASYNCQ].revents = 0;
+                pollfd[POLLFD_FIFO].revents = 0;
                 continue;
+            }
 
             pa_log("poll() failed: %s", pa_cstrerror(errno));
             goto fail;

commit 295e1c83aca1928cf4473d67a4a888aab472cf03
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Jul 13 00:09:59 2007 +0000

    Make pa_sink_render_* and pa_source_post work only when in RUNNING state, to fix handling of monitor sources when their sink is suspended
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1509 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c
index d5ca061..ced23a5 100644
--- a/src/pulsecore/sink.c
+++ b/src/pulsecore/sink.c
@@ -361,7 +361,7 @@ void pa_sink_render(pa_sink*s, size_t length, pa_memchunk *result) {
 
     pa_sink_ref(s);
 
-    n = fill_mix_info(s, info, MAX_MIX_CHANNELS);
+    n = s->thread_info.state == PA_SINK_RUNNING ? fill_mix_info(s, info, MAX_MIX_CHANNELS) : 0;
 
     if (n == 0) {
 
@@ -426,7 +426,7 @@ void pa_sink_render_into(pa_sink*s, pa_memchunk *target) {
 
     pa_sink_ref(s);
 
-    n = fill_mix_info(s, info, MAX_MIX_CHANNELS);
+    n = s->thread_info.state == PA_SINK_RUNNING ? fill_mix_info(s, info, MAX_MIX_CHANNELS) : 0;
 
     if (n == 0) {
         pa_silence_memchunk(target, &s->sample_spec);
diff --git a/src/pulsecore/source.c b/src/pulsecore/source.c
index f0a898f..ce1ee98 100644
--- a/src/pulsecore/source.c
+++ b/src/pulsecore/source.c
@@ -232,6 +232,9 @@ void pa_source_post(pa_source*s, const pa_memchunk *chunk) {
     pa_source_assert_ref(s);
     pa_assert(chunk);
 
+    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;
 

commit a42c19edc7b668cf605cec37430dab13fa5c0307
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Jul 13 00:14:11 2007 +0000

    Merge module-oss-mmap into module-oss and make suspending working properly
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1510 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-oss.c b/src/modules/module-oss.c
index f402fb6..249982c 100644
--- a/src/modules/module-oss.c
+++ b/src/modules/module-oss.c
@@ -44,6 +44,10 @@
 #include <config.h>
 #endif
 
+#ifdef HAVE_SYS_MMAN_H
+#include <sys/mman.h>
+#endif
+
 #include <sys/soundcard.h>
 #include <sys/ioctl.h>
 #include <sys/poll.h>
@@ -88,10 +92,14 @@ 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"
 
+#define DEFAULT_NFRAGS 4
+#define DEFAULT_FRAGSIZE_MSEC 25
+
 struct userdata {
     pa_core *core;
     pa_module *module;
@@ -104,7 +112,7 @@ struct userdata {
     
     pa_memchunk memchunk;
 
-    uint32_t in_fragment_size, out_fragment_size, sample_size;
+    uint32_t in_fragment_size, out_fragment_size, in_nfrags, out_nfrags, in_hwbuf_size, out_hwbuf_size;
     int use_getospace, use_getispace;
     int use_getodelay;
 
@@ -117,6 +125,13 @@ struct userdata {
     int mode;
 
     int nfrags, frag_size;
+
+    int 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;
 };
 
 static const char* const valid_modargs[] = {
@@ -131,13 +146,320 @@ static const char* const valid_modargs[] = {
     "rate",
     "channels",
     "channel_map",
+    "mmap",
     NULL
 };
 
+static void trigger(struct userdata *u, int quick) {
+    int enable_bits = 0, zero = 0;
+
+/*     pa_log_debug("trigger"); */
+
+    if (u->source && u->source->thread_info.state != PA_SOURCE_SUSPENDED)
+        enable_bits |= PCM_ENABLE_INPUT;
+    
+    if (u->sink && u->sink->thread_info.state != PA_SINK_SUSPENDED)
+        enable_bits |= PCM_ENABLE_OUTPUT;
+    
+    if (u->use_mmap) {
+
+        if (!quick)
+            /* First, let's stop all playback, capturing */
+            ioctl(u->fd, SNDCTL_DSP_SETTRIGGER, &zero);
+
+#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 (ioctl(u->fd, SNDCTL_DSP_SETTRIGGER, &enable_bits) < 0)
+            pa_log_warn("SNDCTL_DSP_SETTRIGGER: %s", pa_cstrerror(errno));
+        
+        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 && u->source->thread_info.state != PA_SOURCE_SUSPENDED) {
+                uint8_t *buf = pa_xnew(uint8_t, u->in_fragment_size);
+                pa_read(u->fd, buf, u->in_fragment_size, NULL);
+                pa_xfree(buf);
+            }
+        }
+    }
+}
+
+static void mmap_fill_memblocks(struct userdata *u, unsigned n) {
+    pa_assert(u);
+    pa_assert(u->out_mmap_memblocks);
+
+    while (n > 0) {
+        pa_memchunk chunk;
+
+        if (u->out_mmap_memblocks[u->out_mmap_current])
+            pa_memblock_unref_fixed(u->out_mmap_memblocks[u->out_mmap_current]);
+
+        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);
+
+        chunk.length = pa_memblock_get_length(chunk.memblock);
+        chunk.index = 0;
+
+        pa_sink_render_into_full(u->sink, &chunk);
+
+        u->out_mmap_current++;
+        while (u->out_mmap_current >= u->out_nfrags)
+            u->out_mmap_current -= u->out_nfrags;
+
+        n--;
+    }
+}
+
+static int mmap_write(struct userdata *u) {
+    struct count_info info;
+    
+    
+    pa_assert(u);
+    pa_assert(u->sink);
+
+    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);
+    
+    return info.blocks;
+}
+
+static void mmap_post_memblocks(struct userdata *u, unsigned n) {
+    pa_assert(u);
+    pa_assert(u->in_mmap_memblocks);
+
+    while (n > 0) {
+        pa_memchunk chunk;
+
+        if (!u->in_mmap_memblocks[u->in_mmap_current]) {
+            
+            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);
+            
+            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--;
+    }
+}
+
+static void mmap_clear_memblocks(struct userdata*u, unsigned n) {
+    unsigned i = u->in_mmap_current;
+    
+    pa_assert(u);
+    pa_assert(u->in_mmap_memblocks);
+
+    if (n > u->in_nfrags)
+        n = u->in_nfrags;
+
+    while (n > 0) {
+        if (u->in_mmap_memblocks[i]) {
+            pa_memblock_unref_fixed(u->in_mmap_memblocks[i]);
+            u->in_mmap_memblocks[i] = NULL;
+        }
+
+        i++;
+        while (i >= u->in_nfrags)
+            i -= u->in_nfrags;
+
+        n--;
+    }
+}
+
+static int mmap_read(struct userdata *u) {
+    struct count_info info;
+    pa_assert(u);
+    pa_assert(u->source);
+
+    if (ioctl(u->fd, SNDCTL_DSP_GETIPTR, &info) < 0) {
+        pa_log("SNDCTL_DSP_GETIPTR: %s", pa_cstrerror(errno));
+        return -1;
+    }
+
+    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 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 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 io_sink_get_latency(struct userdata *u) {
+    pa_usec_t r = 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);
+        
+    }
+    
+    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, &u->sink->sample_spec);
+
+    return r;
+}
+
+
+static pa_usec_t io_source_get_latency(struct userdata *u) {
+    pa_usec_t r = 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);
+    }
+
+    return r;
+}
+
 static int suspend(struct userdata *u) {
     pa_assert(u);
     pa_assert(u->fd >= 0);
 
+    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);
     close(u->fd);
@@ -152,6 +474,7 @@ 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);
@@ -188,28 +511,53 @@ static int unsuspend(struct userdata *u) {
     }
 
     in_frag_size = out_frag_size = frag_size;
+    in_nfrags = out_nfrags = u->nfrags;
 
-    if (ioctl(u->fd, SNDCTL_DSP_GETISPACE, &info) >= 0)
+    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)
+    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) || (u->sink && out_frag_size != (int) u->out_fragment_size)) {
-        pa_log_warn("Resume failed, fragment settings don't match.");
+    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;
     }
 
-    /*
-     * 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) {
-        uint8_t *buf = pa_xnew(uint8_t, u->sample_size);
-        pa_read(u->fd, buf, u->sample_size, NULL);
-        pa_xfree(buf);
+    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;
+    
+    /* Now, start only what we need */
+    trigger(u, 0);
+
     pa_log_debug("Resumed successfully...");
 
     return 0;
@@ -222,6 +570,7 @@ fail:
 
 static int sink_process_msg(pa_msgobject *o, int code, void *data, pa_memchunk *chunk) {
     struct userdata *u = PA_SINK(o)->userdata;
+    int do_trigger = 0, ret;
 
     switch (code) {
 
@@ -229,31 +578,12 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, pa_memchunk *
             pa_usec_t r = 0;
 
             if (u->fd >= 0) {
-                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);
-                    
-                }
-                
-                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->use_mmap)
+                    r = mmap_sink_get_latency(u);
+                else
+                    r = io_sink_get_latency(u);
             }
 
-            if (u->memchunk.memblock)
-                r += pa_bytes_to_usec(u->memchunk.length, &u->sink->sample_spec);
-
             *((pa_usec_t*) data) = r;
 
             break;
@@ -264,19 +594,25 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, pa_memchunk *
             if (PA_PTR_TO_UINT(data) == PA_SINK_SUSPENDED) {
                 pa_assert(u->sink->thread_info.state != PA_SINK_SUSPENDED);
 
-                if (u->source_suspended)
+                if (u->source_suspended) {
                     if (suspend(u) < 0)
                         return -1;
+                } else
+                    do_trigger = 1;
 
                 u->sink_suspended = 1;
-            }
-
-            if (u->sink->thread_info.state == PA_SINK_SUSPENDED) {
+                
+            } else if (u->sink->thread_info.state == PA_SINK_SUSPENDED) {
                 pa_assert(PA_PTR_TO_UINT(data) != PA_SINK_SUSPENDED);
 
-                if (u->source_suspended)
-                    if (unsuspend(u) < 0)
+                if (u->source_suspended) {
+                    if (unsuspend(u) < 0) 
                         return -1;
+                } else
+                    do_trigger = 1;
+
+                u->out_mmap_current = 0;
+                u->out_mmap_saved_nfrags = 0;
 
                 u->sink_suspended = 0;
             }
@@ -310,27 +646,30 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, pa_memchunk *
             break;
     }
 
-    return pa_sink_process_msg(o, code, data, chunk);
+    ret = pa_sink_process_msg(o, code, data, chunk);
+
+    if (do_trigger)
+        trigger(u, 1);
+    
+    return ret;
 }
 
 static int source_process_msg(pa_msgobject *o, int code, void *data, pa_memchunk *chunk) {
     struct userdata *u = PA_SOURCE(o)->userdata;
+    int do_trigger = 0, ret;
 
     switch (code) {
 
         case PA_SOURCE_MESSAGE_GET_LATENCY: {
             pa_usec_t r = 0;
 
-            if (u->use_getispace && u->fd >= 0) {
-                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 (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;
             break;
         }
@@ -340,19 +679,25 @@ static int source_process_msg(pa_msgobject *o, int code, void *data, pa_memchunk
             if (PA_PTR_TO_UINT(data) == PA_SOURCE_SUSPENDED) {
                 pa_assert(u->source->thread_info.state != PA_SOURCE_SUSPENDED);
 
-                if (u->sink_suspended)
-                    if (suspend(u) < 0)
+                if (u->sink_suspended) {
+                    if (suspend(u) < 0) 
                         return -1;
+                } else
+                    do_trigger = 1;
 
                 u->source_suspended = 1;
-            }
 
-            if (u->source->thread_info.state == PA_SOURCE_SUSPENDED) {
+            } else if (u->source->thread_info.state == PA_SOURCE_SUSPENDED) {
                 pa_assert(PA_PTR_TO_UINT(data) != PA_SOURCE_SUSPENDED);
 
-                if (u->sink_suspended)
-                    if (unsuspend(u) < 0)
+                if (u->sink_suspended) {
+                    if (unsuspend(u) < 0) 
                         return -1;
+                } else
+                    do_trigger = 1;
+                
+                u->in_mmap_current = 0;
+                u->in_mmap_saved_nfrags = 0;
 
                 u->source_suspended = 0;
             }
@@ -386,7 +731,12 @@ static int source_process_msg(pa_msgobject *o, int code, void *data, pa_memchunk
             break;
     }
 
-    return pa_source_process_msg(o, code, data, chunk);
+    ret = pa_source_process_msg(o, code, data, chunk);
+
+    if (do_trigger)
+        trigger(u, 1);
+
+    return ret;
 }
 
 static void thread_func(void *userdata) {
@@ -404,16 +754,8 @@ static void thread_func(void *userdata) {
 
     pa_log_debug("Thread starting up");
 
-    /*
-     * 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) {
-        uint8_t *buf = pa_xnew(uint8_t, u->sample_size);
-        pa_read(u->fd, buf, u->sample_size, &read_type);
-        pa_xfree(buf);
-    }
-
+    trigger(u, 0);
+    
     memset(&pollfd, 0, sizeof(pollfd));
 
     pollfd[POLLFD_ASYNCQ].fd = pa_asyncmsgq_get_fd(u->asyncmsgq);
@@ -427,7 +769,7 @@ static void thread_func(void *userdata) {
         pa_memchunk chunk;
         int r;
 
-/*         pa_log("loop"); */
+/*         pa_log("loop");   */
         
         /* Check whether there is a message for us to process */
         if (pa_asyncmsgq_get(u->asyncmsgq, &object, &code, &data, &chunk, 0) == 0) {
@@ -450,148 +792,181 @@ static void thread_func(void *userdata) {
         /* Render some data and write it to the dsp */
 
         if (u->sink && u->sink->thread_info.state != PA_SINK_SUSPENDED && (pollfd[POLLFD_DSP].revents & POLLOUT)) {
-            ssize_t l;
-            void *p;
-            int loop = 0;
 
-            l = u->out_fragment_size;
+            if (u->use_mmap) {
+                int ret;
 
-            if (u->use_getospace) {
-                audio_buf_info info;
+                if ((ret = mmap_write(u)) < 0)
+                    goto fail;
 
-                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 {
-                    if (info.bytes >= l) {
-                        l = (info.bytes/l)*l;
-                        loop = 1;
+                pollfd[POLLFD_DSP].revents &= ~POLLOUT;
+                
+                if (ret > 0)
+                    continue;
+
+            } else {
+                ssize_t l;
+                void *p;
+                int loop = 0;
+                
+                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 = 0;
+                    } else {
+                        if (info.bytes >= l) {
+                            l = (info.bytes/l)*l;
+                            loop = 1;
+                        }
                     }
                 }
+                
+                do {
+                    ssize_t t;
+                    
+                    pa_assert(l > 0);
+                    
+                    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"); 
+                            
+                            pollfd[POLLFD_DSP].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;
+                        
+                        pollfd[POLLFD_DSP].revents &= ~POLLOUT;
+                    }
+                    
+                } while (loop && l > 0);
+                
+                continue;
             }
+        }
 
-            do {
-                ssize_t t;
-
-                pa_assert(l > 0);
+        /* Try to read some data and pass it on to the source driver */
 
-                if (u->memchunk.length <= 0)
-                    pa_sink_render(u->sink, l, &u->memchunk);
+        if (u->source && u->source->thread_info.state != PA_SOURCE_SUSPENDED && ((pollfd[POLLFD_DSP].revents & POLLIN))) {
 
-                pa_assert(u->memchunk.length > 0);
+            if (u->use_mmap) {
+                int ret;
 
-                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);
+                if ((ret = mmap_read(u)) < 0)
+                    goto fail;
 
-/*                 pa_log("wrote %i bytes", t); */
+                pollfd[POLLFD_DSP].revents &= ~POLLIN;
                 
-                pa_assert(t != 0);
+                if (ret > 0)
+                    continue;
 
-                if (t < 0) {
+            } else {
 
-                    if (errno == EINTR)
-                        continue;
+                void *p;
+                ssize_t l;
+                pa_memchunk memchunk;
+                int loop = 0;
 
-                    else if (errno == EAGAIN) {
+                l = u->in_fragment_size;
 
-                        pollfd[POLLFD_DSP].revents &= ~POLLOUT;
-                        break;
+                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 = 0;
                     } else {
-                        pa_log("Failed to write data to DSP: %s", pa_cstrerror(errno));
-                        goto fail;
+                        if (info.bytes >= l) {
+                            l = (info.bytes/l)*l;
+                            loop = 1;
+                        }
                     }
-
-                } 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;
-
-                    pollfd[POLLFD_DSP].revents &= ~POLLOUT;
                 }
 
-            } while (loop && l > 0);
-
-            continue;
-        }
+                do {
+                    ssize_t t;
 
-        /* Try to read some data and pass it on to the source driver */
+                    pa_assert(l > 0);
 
-        if (u->source && u->source->thread_info.state != PA_SOURCE_SUSPENDED && ((pollfd[POLLFD_DSP].revents & POLLIN))) {
-            void *p;
-            ssize_t l;
-            pa_memchunk memchunk;
-            int loop = 0;
+                    memchunk.memblock = pa_memblock_new(u->core->mempool, l);
 
-            l = u->in_fragment_size;
+                    p = pa_memblock_acquire(memchunk.memblock);
+                    t = pa_read(u->fd, p, l, &read_type);
+                    pa_memblock_release(memchunk.memblock);
 
-            if (u->use_getispace) {
-                audio_buf_info info;
+                    pa_assert(t != 0); /* EOF cannot happen */
 
-                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 {
-                    if (info.bytes >= l) {
-                        l = (info.bytes/l)*l;
-                        loop = 1;
-                    }
-                }
-            }
+/*                     pa_log("read %i bytes of %u", t, l); */
+                    
+                    if (t < 0) {
+                        pa_memblock_unref(memchunk.memblock);
 
-            do {
-                ssize_t t;
+                        if (errno == EINTR)
+                            continue;
 
-                pa_assert(l > 0);
+                        else if (errno == EAGAIN) {
+                            pa_log_debug("EAGAIN"); 
 
-                memchunk.memblock = pa_memblock_new(u->core->mempool, l);
+                            pollfd[POLLFD_DSP].revents &= ~POLLIN;
+                            break;
 
-                p = pa_memblock_acquire(memchunk.memblock);
-                t = pa_read(u->fd, p, l, &read_type);
-                pa_memblock_release(memchunk.memblock);
+                        } else {
+                            pa_log("Failed to read data from DSP: %s", pa_cstrerror(errno));
+                            goto fail;
+                        }
 
-                pa_assert(t != 0); /* EOF cannot happen */
+                    } else {
+                        memchunk.index = 0;
+                        memchunk.length = t;
 
-                if (t < 0) {
-                    pa_memblock_unref(memchunk.memblock);
+                        pa_source_post(u->source, &memchunk);
+                        pa_memblock_unref(memchunk.memblock);
 
-                    if (errno == EINTR)
-                        continue;
+                        l -= t;
 
-                    else if (errno == EAGAIN) {
                         pollfd[POLLFD_DSP].revents &= ~POLLIN;
-                        break;
-
-                    } else {
-                        pa_log("Faile to read data from DSP: %s", pa_cstrerror(errno));
-                        goto fail;
                     }
+                } while (loop && l > 0);
 
-                } else {
-                    memchunk.index = 0;
-                    memchunk.length = t;
-
-                    pa_source_post(u->source, &memchunk);
-                    pa_memblock_unref(memchunk.memblock);
-
-                    l -= t;
-
-                    pollfd[POLLFD_DSP].revents &= ~POLLIN;
-                }
-            } while (loop && l > 0);
-
-            continue;
+                continue;
+            }
         }
 
-
         if (u->fd >= 0) {
             pollfd[POLLFD_DSP].fd = u->fd;
             pollfd[POLLFD_DSP].events =
@@ -604,9 +979,9 @@ static void thread_func(void *userdata) {
         if (pa_asyncmsgq_before_poll(u->asyncmsgq) < 0)
             continue;
 
-/*         pa_log("polling for %i", u->fd >= 0 ? pollfd[POLLFD_DSP].events : -1);    */
+/*         pa_log("polling for %i (legend: %i=POLLIN, %i=POLLOUT)", u->fd >= 0 ? pollfd[POLLFD_DSP].events : -1, POLLIN, POLLOUT); */
         r = poll(pollfd, u->fd >= 0 ? POLLFD_MAX : POLLFD_DSP, -1);
-/*         pa_log("polling got dsp=%i amq=%i (%i)", r > 0 ? pollfd[POLLFD_DSP].revents : 0, r > 0 ? pollfd[POLLFD_ASYNCQ].revents : 0, r);    */
+/*         pa_log("polling got dsp=%i amq=%i (%i)", r > 0 ? pollfd[POLLFD_DSP].revents : 0, r > 0 ? pollfd[POLLFD_ASYNCQ].revents : 0, r); */
 
         pa_asyncmsgq_after_poll(u->asyncmsgq);
 
@@ -649,15 +1024,14 @@ int pa__init(pa_core *c, pa_module*m) {
     struct userdata *u = NULL;
     const char *p;
     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);
@@ -686,18 +1060,29 @@ int pa__init(pa_core *c, pa_module*m) {
         goto fail;
     }
 
-    /* Fix latency to 100ms */
-    nfrags = 12;
-    frag_size = pa_bytes_per_second(&ss)/128;
+    nfrags = DEFAULT_NFRAGS;
+    frag_size = pa_usec_to_bytes(DEFAULT_FRAGSIZE_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");
         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 ((fd = pa_oss_open(p = 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("OSS device not mmap capable, falling back to UNIX read/write mode");
+        use_mmap = 0;
+    }
+    
     if (pa_oss_get_hw_description(p, hwdesc, sizeof(hwdesc)) >= 0)
         pa_log_info("Hardware name is '%s'.", hwdesc);
     else
@@ -717,7 +1102,6 @@ int pa__init(pa_core *c, pa_module*m) {
         goto fail;
     }
     assert(frag_size);
-    in_frag_size = out_frag_size = frag_size;
 
     u = pa_xnew0(struct userdata, 1);
     u->core = c;
@@ -728,23 +1112,46 @@ int pa__init(pa_core *c, pa_module*m) {
     u->use_input_volume = u->use_pcm_volume = 1;
     u->mode = mode;
     u->device_name = pa_xstrdup(p);
-    u->nfrags = nfrags;
-    u->frag_size = frag_size;
+    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_assert_se(u->asyncmsgq = pa_asyncmsgq_new(0));
 
     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;
+        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;
+        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) {
+                if (mode == O_RDWR) {
+                    pa_log_debug("mmap() failed for input. Changing to O_WRONLY mode.");
+                    mode = O_WRONLY;
+                    goto try_write;
+                } else {
+                    pa_log("mmap(): %s", pa_cstrerror(errno));
+                    goto fail;
+                }
+            }
+
+            pa_log_debug("Successfully mmap()ed input buffer.");
+        }
+
         if ((name = pa_modargs_get_value(ma, "source_name", NULL)))
             namereg_fail = 1;
         else {
@@ -752,7 +1159,9 @@ 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(c, __FILE__, name, namereg_fail, &ss, &map);
+        pa_xfree(name_buf);
+        if (!u->source)
             goto fail;
 
         u->source->parent.process_msg = source_process_msg;
@@ -768,13 +1177,32 @@ int pa__init(pa_core *c, pa_module*m) {
         pa_xfree(t);
         u->source->is_hardware = 1;
         u->source->refresh_volume = 1;
-    } else
-        u->source = NULL;
 
-    pa_xfree(name_buf);
-    name_buf = NULL;
+        if (use_mmap)
+            u->in_mmap_memblocks = pa_xnew0(pa_memblock*, u->in_nfrags);
+    }
 
+try_write:
+    
     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("mmap(): %s", pa_cstrerror(errno));
+                    goto fail;
+                }
+            }
+
+            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 {
@@ -782,7 +1210,9 @@ 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(c, __FILE__, name, namereg_fail, &ss, &map);
+        pa_xfree(name_buf);
+        if (!u->sink)
             goto fail;
 
         u->sink->parent.process_msg = sink_process_msg;
@@ -798,21 +1228,18 @@ int pa__init(pa_core *c, pa_module*m) {
         pa_xfree(t);
         u->sink->is_hardware = 1;
         u->sink->refresh_volume = 1;
-    } else
-        u->sink = NULL;
 
-    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);
+go_on:
+    
+    pa_assert(u->source || u->sink);
 
     u->fd = fd;
 
     pa_memchunk_reset(&u->memchunk);
-    u->sample_size = pa_frame_size(&ss);
-
-    u->out_fragment_size = out_frag_size;
-    u->in_fragment_size = in_frag_size;
 
     if (!(u->thread = pa_thread_new(thread_func, u))) {
         pa_log("Failed to create thread.");
@@ -836,8 +1263,6 @@ fail:
     if (ma)
         pa_modargs_free(ma);
 
-    pa_xfree(name_buf);
-
     return -1;
 }
 
@@ -873,9 +1298,31 @@ void pa__done(pa_core *c, pa_module*m) {
     if (u->memchunk.memblock)
         pa_memblock_unref(u->memchunk.memblock);
 
+    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)
         close(u->fd);
 
+    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);
+    }
+
     pa_xfree(u->device_name);
     
     pa_xfree(u);

commit ac1387d3cc8c2f9f92268ac7d007661c7c32ad52
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Jul 13 00:15:59 2007 +0000

    Remove module-oss-mmap, since it is now merged into module-oss
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1511 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/Makefile.am b/src/Makefile.am
index a83424c..c382bcd 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -931,7 +931,6 @@ if HAVE_OSS
 modlibexec_LTLIBRARIES += \
 		liboss-util.la \
 		module-oss.la
-#		module-oss-mmap.la
 endif
 
 #if HAVE_ALSA
@@ -1018,7 +1017,6 @@ SYMDEF_FILES = \
 		modules/module-x11-bell-symdef.h \
 		modules/module-x11-publish-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 \
@@ -1184,10 +1182,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
 
-#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
diff --git a/src/modules/module-oss-mmap.c b/src/modules/module-oss-mmap.c
deleted file mode 100644
index 567230e..0000000
--- a/src/modules/module-oss-mmap.c
+++ /dev/null
@@ -1,637 +0,0 @@
-/* $Id$ */
-
-/***
-  This file is part of PulseAudio.
-
-  Copyright 2004-2006 Lennart Poettering
-  Copyright 2006 Pierre Ossman <ossman at 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 = pa_memblock_get_length(chunk.memblock);
-        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 = pa_memblock_get_length(chunk.memblock);
-            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);
-}

commit ca5874da9bfc0e8bc5dd4ad6dd41e4add3977828
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Jul 13 12:10:44 2007 +0000

    Replace a couple of assert()s by pa_assert()s
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1512 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-oss.c b/src/modules/module-oss.c
index 249982c..cabdf16 100644
--- a/src/modules/module-oss.c
+++ b/src/modules/module-oss.c
@@ -54,7 +54,6 @@
 #include <stdlib.h>
 #include <sys/stat.h>
 #include <stdio.h>
-#include <assert.h>
 #include <errno.h>
 #include <string.h>
 #include <fcntl.h>
@@ -1034,8 +1033,8 @@ int pa__init(pa_core *c, pa_module*m) {
     const char *name;
     int namereg_fail;
 
-    assert(c);
-    assert(m);
+    pa_assert(c);
+    pa_assert(m);
 
     if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
         pa_log("Failed to parse module arguments.");
@@ -1101,7 +1100,7 @@ int pa__init(pa_core *c, pa_module*m) {
         pa_log("SNDCTL_DSP_GETBLKSIZE: %s", pa_cstrerror(errno));
         goto fail;
     }
-    assert(frag_size);
+    pa_assert(frag_size > 0);
 
     u = pa_xnew0(struct userdata, 1);
     u->core = c;
@@ -1269,8 +1268,8 @@ fail:
 void pa__done(pa_core *c, pa_module*m) {
     struct userdata *u;
 
-    assert(c);
-    assert(m);
+    pa_assert(c);
+    pa_assert(m);
 
     if (!(u = m->userdata))
         return;

commit 481b425a28ac02246fc051ab1e9f9a65f2701cf4
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Jul 13 12:11:19 2007 +0000

    Fix off-by-one in mixing code
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1513 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c
index ced23a5..5a79a41 100644
--- a/src/pulsecore/sink.c
+++ b/src/pulsecore/sink.c
@@ -320,7 +320,8 @@ static void inputs_drop(pa_sink *s, pa_mix_info *info, unsigned n, size_t length
                 break;
             }
 
-            if (++p > n)
+            p++;
+            if (p >= n)
                 p = 0;
         }
 

commit 63c231ed36f834a62b3a0f8cc21756ecc6d8533e
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Jul 13 12:12:40 2007 +0000

    Fix concurrency bug when turning memblock into a local memblock
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1514 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/memblock.c b/src/pulsecore/memblock.c
index 71b576a..e5df11f 100644
--- a/src/pulsecore/memblock.c
+++ b/src/pulsecore/memblock.c
@@ -567,10 +567,10 @@ void pa_memblock_unref_fixed(pa_memblock *b) {
     assert(PA_REFCNT_VALUE(b) > 0);
     assert(b->type == PA_MEMBLOCK_FIXED);
 
-    if (PA_REFCNT_DEC(b) > 0)
+    if (PA_REFCNT_VALUE(b) > 1)
         memblock_make_local(b);
-    else
-        memblock_free(b);
+
+    pa_memblock_unref(b);
 }
 
 /* Self-locked. This function is not multiple-caller safe */

commit 59faa5d38b3dc0b59d7ff20a5fd65f495a5e660f
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Jul 13 12:13:25 2007 +0000

    Remove a superfluous pa_memblock_release(); properly handle buf4 allocation
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1515 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/resampler.c b/src/pulsecore/resampler.c
index a43c7c7..7c716dd 100644
--- a/src/pulsecore/resampler.c
+++ b/src/pulsecore/resampler.c
@@ -455,7 +455,7 @@ static pa_memchunk *convert_from_float(pa_resampler *r, pa_memchunk *input) {
     n_frames = input->length / sizeof(float) / r->o_ss.channels;
     n_samples = n_frames * r->o_ss.channels;
 
-    if (u->buf4_samples < n_samples) {
+    if (!u->buf4.memblock || u->buf4_samples < n_samples) {
         if (u->buf4.memblock)
             pa_memblock_unref(u->buf4.memblock);
 
@@ -503,9 +503,6 @@ static void libsamplerate_run(pa_resampler *r, const pa_memchunk *in, pa_memchun
             pa_memchunk_reset(buf);
     } else
         pa_memchunk_reset(out);
-
-    pa_memblock_release(in->memblock);
-
 }
 
 static void libsamplerate_update_input_rate(pa_resampler *r, uint32_t rate) {
@@ -526,7 +523,6 @@ static void libsamplerate_update_input_rate(pa_resampler *r, uint32_t rate) {
     }
 }
 
-
 static void libsamplerate_update_output_rate(pa_resampler *r, uint32_t rate) {
     struct impl_libsamplerate *u;
 

commit 8442926483403d7e2fd9b768e70df87db6759b04
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Jul 13 12:13:55 2007 +0000

    Reenable a couple of more modules
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1516 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/Makefile.am b/src/Makefile.am
index c382bcd..2e37b29 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -873,16 +873,16 @@ modlibexec_LTLIBRARIES += \
 		module-cli.la \
 		module-cli-protocol-tcp.la \
 		module-simple-protocol-tcp.la \
-		module-null-sink.la
+		module-null-sink.la \
 		module-detect.la \
 		module-volume-restore.la \
 		module-rescue-streams.la \
-		module-http-protocol-tcp.la 
+		module-http-protocol-tcp.la \
+		module-sine.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 \

commit 3b912ac41f5406b5f7b02c718bb87cb19965843c
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Jul 13 12:14:30 2007 +0000

    Port module-sine to the new lock-free core
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1517 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-sine.c b/src/modules/module-sine.c
index baf3734..b5b7e60 100644
--- a/src/modules/module-sine.c
+++ b/src/modules/module-sine.c
@@ -58,34 +58,42 @@ 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, 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 = 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, const pa_memchunk *chunk, size_t length) {
     struct userdata *u;
-    assert(i && chunk && length && i->userdata);
+    size_t l;
+    
+    pa_assert(i);
     u = i->userdata;
-
-    assert(chunk->memblock == u->memblock);
-    assert(length <= pa_memblock_get_length(u->memblock)-u->peek_index);
+    pa_assert(u);
+    pa_assert(chunk);
+    pa_assert(length > 0);
 
     u->peek_index += length;
 
-    if (u->peek_index >= pa_memblock_get_length(u->memblock))
-        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 && i->userdata);
     u = i->userdata;
 
     pa_sink_input_disconnect(u->sink_input);
@@ -108,7 +116,6 @@ int pa__init(pa_core *c, 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];
@@ -120,15 +127,14 @@ int pa__init(pa_core *c, pa_module*m) {
         goto fail;
     }
 
-    m->userdata = u = pa_xmalloc(sizeof(struct userdata));
+    m->userdata = u = pa_xnew0(struct userdata, 1);
     u->core = c;
     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(c, pa_modargs_get_value(ma, "sink", NULL), PA_NAMEREG_SINK, 1))) {
         pa_log("No such sink.");
         goto fail;
     }
@@ -160,13 +166,13 @@ int pa__init(pa_core *c, pa_module*m) {
     if (!(u->sink_input = pa_sink_input_new(c, &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;
 
@@ -179,10 +185,12 @@ fail:
 }
 
 void pa__done(pa_core *c, pa_module*m) {
-    struct userdata *u = m->userdata;
-    assert(c && m);
+    struct userdata *u;
+    
+    pa_assert(c);
+    pa_assert(m);
 
-    if (!u)
+    if (!(u = m->userdata))
         return;
 
     if (u->sink_input) {
@@ -192,6 +200,7 @@ void pa__done(pa_core *c, pa_module*m) {
 
     if (u->memblock)
         pa_memblock_unref(u->memblock);
+    
     pa_xfree(u);
 }
 

commit 69bfa351ba89f17b22efad95f1dc6f946cf2df20
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Jul 13 23:21:54 2007 +0000

    Actually make the static flist static
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1518 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/flist.h b/src/pulsecore/flist.h
index 80fd86c..102d30e 100644
--- a/src/pulsecore/flist.h
+++ b/src/pulsecore/flist.h
@@ -41,7 +41,7 @@ int pa_flist_push(pa_flist*l, void *p);
 void* pa_flist_pop(pa_flist*l);
 
 #define PA_STATIC_FLIST_DECLARE(name, size)                     \
-    struct {                                                    \
+    static struct {                                             \
         pa_flist *flist;                                        \
         pa_once_t once;                                         \
     } name##_static_flist = { NULL, PA_ONCE_INIT };             \

commit f2c98d74837e4e98173ef528d25a5f583340fc2c
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Jul 13 23:22:38 2007 +0000

    Make use of static flist for hashmap entry alllocation
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1519 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/hashmap.c b/src/pulsecore/hashmap.c
index 818e12b..450f89c 100644
--- a/src/pulsecore/hashmap.c
+++ b/src/pulsecore/hashmap.c
@@ -33,6 +33,7 @@
 
 #include <pulsecore/idxset.h>
 #include <pulsecore/log.h>
+#include <pulsecore/flist.h>
 
 #include "hashmap.h"
 
@@ -55,6 +56,8 @@ struct pa_hashmap {
     pa_compare_func_t compare_func;
 };
 
+PA_STATIC_FLIST_DECLARE(entries, 0);
+
 pa_hashmap *pa_hashmap_new(pa_hash_func_t hash_func, pa_compare_func_t compare_func) {
     pa_hashmap *h;
 
@@ -88,7 +91,9 @@ static void remove(pa_hashmap *h, struct hashmap_entry *e) {
         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--;
 }
 
@@ -127,7 +132,9 @@ int pa_hashmap_put(pa_hashmap *h, const void *key, void *value) {
     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;

commit 0e84f044dd531ff23b165d8bc07c282b923e5d1e
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Jul 13 23:23:03 2007 +0000

    Minor clarification
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1520 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/resampler.c b/src/pulsecore/resampler.c
index 7c716dd..9c8e32f 100644
--- a/src/pulsecore/resampler.c
+++ b/src/pulsecore/resampler.c
@@ -489,7 +489,8 @@ static void libsamplerate_run(pa_resampler *r, const pa_memchunk *in, pa_memchun
 
     u = r->impl_data;
 
-    buf = convert_to_float(r, (pa_memchunk*) in);
+    buf = (pa_memchunk*) in;
+    buf = convert_to_float(r, buf);
     buf = remap_channels(r, buf);
     buf = resample(r, buf);
 

commit 65d54d6aaf62cca5bac5ec3c5588b797f0ed4c7e
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Jul 13 23:27:15 2007 +0000

    s/assert/pa_assert/g; make use of static flist for memblock allocation where applicable; properly initialize length value in pa_memexport_put()
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1521 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/memblock.c b/src/pulsecore/memblock.c
index e5df11f..8da9ceb 100644
--- a/src/pulsecore/memblock.c
+++ b/src/pulsecore/memblock.c
@@ -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
@@ -31,6 +31,7 @@
 #include <assert.h>
 #include <string.h>
 #include <unistd.h>
+#include <signal.h>
 
 #include <pulse/xmalloc.h>
 #include <pulse/def.h>
@@ -149,10 +150,12 @@ struct pa_mempool {
 
 static void segment_detach(pa_memimport_segment *seg);
 
+PA_STATIC_FLIST_DECLARE(unused_memblocks, 0);
+
 /* 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);
@@ -171,18 +174,18 @@ static void stat_add(pa_memblock*b) {
 
 /* 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);
@@ -197,8 +200,8 @@ static pa_memblock *memblock_new_appended(pa_mempool *p, size_t length);
 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);
@@ -210,8 +213,8 @@ pa_memblock *pa_memblock_new(pa_mempool *p, size_t length) {
 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(PA_ALIGN(sizeof(pa_memblock)) + length);
     PA_REFCNT_INIT(b);
@@ -230,7 +233,7 @@ static pa_memblock *memblock_new_appended(pa_mempool *p, size_t length) {
 /* No lock necessary */
 static struct mempool_slot* mempool_allocate_slot(pa_mempool *p) {
     struct mempool_slot *slot;
-    assert(p);
+    pa_assert(p);
 
     if (!(slot = pa_flist_pop(p->free_slots))) {
         int idx;
@@ -254,17 +257,17 @@ static struct mempool_slot* mempool_allocate_slot(pa_mempool *p) {
 
 /* 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);
 }
 
 /* No lock necessary */
 static unsigned mempool_slot_idx(pa_mempool *p, void *ptr) {
-    assert(p);
+    pa_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((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;
 }
@@ -284,8 +287,8 @@ 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 (p->block_size - sizeof(struct mempool_slot) >= sizeof(pa_memblock) + length) {
 
@@ -301,7 +304,9 @@ pa_memblock *pa_memblock_new_pool(pa_mempool *p, size_t 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;
         pa_atomic_ptr_store(&b->data, mempool_slot_data(slot));
 
@@ -326,11 +331,12 @@ pa_memblock *pa_memblock_new_pool(pa_mempool *p, size_t length) {
 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 > 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;
@@ -348,12 +354,13 @@ pa_memblock *pa_memblock_new_fixed(pa_mempool *p, void *d, size_t length, int re
 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(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;
@@ -371,16 +378,16 @@ pa_memblock *pa_memblock_new_user(pa_mempool *p, void *d, size_t length, void (*
 
 /* No lock necessary */
 int pa_memblock_is_read_only(pa_memblock *b) {
-    assert(b);
-    assert(PA_REFCNT_VALUE(b) > 0);
+    pa_assert(b);
+    pa_assert(PA_REFCNT_VALUE(b) > 0);
 
     return b->read_only && PA_REFCNT_VALUE(b) == 1;
 }
 
 /* No lock necessary */
 void* pa_memblock_acquire(pa_memblock *b) {
-    assert(b);
-    assert(PA_REFCNT_VALUE(b) > 0);
+    pa_assert(b);
+    pa_assert(PA_REFCNT_VALUE(b) > 0);
 
     pa_atomic_inc(&b->n_acquired);
 
@@ -390,11 +397,11 @@ void* pa_memblock_acquire(pa_memblock *b) {
 /* No lock necessary, in corner cases locks by its own */
 void pa_memblock_release(pa_memblock *b) {
     int r;
-    assert(b);
-    assert(PA_REFCNT_VALUE(b) > 0);
+    pa_assert(b);
+    pa_assert(PA_REFCNT_VALUE(b) > 0);
 
     r = pa_atomic_dec(&b->n_acquired);
-    assert(r >= 1);
+    pa_assert(r >= 1);
 
     /* Signal a waiting thread that this memblock is no longer used */
     if (r == 1 && pa_atomic_load(&b->please_signal))
@@ -402,45 +409,47 @@ void pa_memblock_release(pa_memblock *b) {
 }
 
 size_t pa_memblock_get_length(pa_memblock *b) {
-    assert(b);
-    assert(PA_REFCNT_VALUE(b) > 0);
+    pa_assert(b);
+    pa_assert(PA_REFCNT_VALUE(b) > 0);
 
     return b->length;
 }
 
 pa_mempool* pa_memblock_get_pool(pa_memblock *b) {
-    assert(b);
-    assert(PA_REFCNT_VALUE(b) > 0);
+    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;
 }
 
 static void memblock_free(pa_memblock *b) {
-    assert(b);
+    pa_assert(b);
 
-    assert(pa_atomic_load(&b->n_acquired) == 0);
+    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);
+            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 : {
@@ -450,9 +459,9 @@ static void memblock_free(pa_memblock *b) {
             /* FIXME! This should be implemented lock-free */
 
             segment = b->per_type.imported.segment;
-            assert(segment);
+            pa_assert(segment);
             import = segment->import;
-            assert(import);
+            pa_assert(import);
 
             pa_mutex_lock(import->mutex);
             pa_hashmap_remove(import->blocks, PA_UINT32_TO_PTR(b->per_type.imported.id));
@@ -463,7 +472,8 @@ static void memblock_free(pa_memblock *b) {
 
             import->release_cb(import, b->per_type.imported.id, import->userdata);
 
-            pa_xfree(b);
+            if (pa_flist_push(PA_STATIC_FLIST_GET(unused_memblocks), b) < 0)
+                pa_xfree(b);
             break;
         }
 
@@ -473,7 +483,7 @@ static void memblock_free(pa_memblock *b) {
             int call_free;
 
             slot = mempool_slot_by_ptr(b->pool, pa_atomic_ptr_load(&b->data));
-            assert(slot);
+            pa_assert(slot);
 
             call_free = b->type == PA_MEMBLOCK_POOL_EXTERNAL;
 
@@ -484,21 +494,22 @@ static void memblock_free(pa_memblock *b) {
                 ;
 
             if (call_free)
-                pa_xfree(b);
+                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) {
-    assert(b);
-    assert(PA_REFCNT_VALUE(b) > 0);
+    pa_assert(b);
+    pa_assert(PA_REFCNT_VALUE(b) > 0);
 
     if (PA_REFCNT_DEC(b) > 0)
         return;
@@ -508,7 +519,7 @@ void pa_memblock_unref(pa_memblock*b) {
 
 /* Self locked */
 static void memblock_wait(pa_memblock *b) {
-    assert(b);
+    pa_assert(b);
 
     if (pa_atomic_load(&b->n_acquired) > 0) {
         /* We need to wait until all threads gave up access to the
@@ -526,7 +537,7 @@ static void memblock_wait(pa_memblock *b) {
 
 /* 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]);
 
@@ -563,9 +574,9 @@ finish:
 
 /* 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);
@@ -577,17 +588,17 @@ void pa_memblock_unref_fixed(pa_memblock *b) {
 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);
 
@@ -627,7 +638,7 @@ pa_mempool* pa_mempool_new(int shared) {
 
     p->n_blocks = PA_MEMPOOL_SLOTS_MAX;
 
-    assert(p->block_size > sizeof(struct mempool_slot));
+    pa_assert(p->block_size > sizeof(struct mempool_slot));
 
     if (pa_shm_create_rw(&p->memory, p->n_blocks * p->block_size, shared, 0700) < 0) {
         pa_xfree(p);
@@ -646,7 +657,7 @@ pa_mempool* pa_mempool_new(int shared) {
 }
 
 void pa_mempool_free(pa_mempool *p) {
-    assert(p);
+    pa_assert(p);
 
     pa_mutex_lock(p->mutex);
 
@@ -658,8 +669,10 @@ void pa_mempool_free(pa_mempool *p) {
 
     pa_mutex_unlock(p->mutex);
 
-    if (pa_atomic_load(&p->stat.n_allocated) > 0)
+    if (pa_atomic_load(&p->stat.n_allocated) > 0) {
+        raise(SIGTRAP);
         pa_log_warn("WARNING! Memory pool destroyed but not all memory blocks freed!");
+    }
 
     pa_flist_free(p->free_slots, NULL);
     pa_shm_free(&p->memory);
@@ -672,7 +685,7 @@ void pa_mempool_free(pa_mempool *p) {
 
 /* No lock necessary */
 const pa_mempool_stat* pa_mempool_get_stat(pa_mempool *p) {
-    assert(p);
+    pa_assert(p);
 
     return &p->stat;
 }
@@ -682,7 +695,7 @@ void pa_mempool_vacuum(pa_mempool *p) {
     struct mempool_slot *slot;
     pa_flist *list;
 
-    assert(p);
+    pa_assert(p);
 
     list = pa_flist_new(p->n_blocks*2);
 
@@ -704,7 +717,7 @@ void pa_mempool_vacuum(pa_mempool *p) {
 
 /* 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;
@@ -716,7 +729,7 @@ int pa_mempool_get_shm_id(pa_mempool *p, uint32_t *id) {
 
 /* No lock necessary */
 int pa_mempool_is_shared(pa_mempool *p) {
-    assert(p);
+    pa_assert(p);
 
     return !!p->memory.shared;
 }
@@ -725,8 +738,8 @@ 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(0);
@@ -768,7 +781,7 @@ static pa_memimport_segment* segment_attach(pa_memimport *i, uint32_t shm_id) {
 
 /* 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);
@@ -780,14 +793,14 @@ 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);
 
-    assert(pa_hashmap_size(i->segments) == 0);
+    pa_assert(pa_hashmap_size(i->segments) == 0);
 
     pa_mutex_unlock(i->mutex);
 
@@ -814,7 +827,7 @@ pa_memblock* pa_memimport_get(pa_memimport *i, uint32_t block_id, uint32_t shm_i
     pa_memblock *b = NULL;
     pa_memimport_segment *seg;
 
-    assert(i);
+    pa_assert(i);
 
     pa_mutex_lock(i->mutex);
 
@@ -828,7 +841,9 @@ pa_memblock* pa_memimport_get(pa_memimport *i, uint32_t block_id, uint32_t shm_i
     if (offset+size > seg->memory.size)
         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;
@@ -855,7 +870,7 @@ finish:
 
 int pa_memimport_process_revoke(pa_memimport *i, uint32_t id) {
     pa_memblock *b;
-    assert(i);
+    pa_assert(i);
 
     pa_mutex_lock(i->mutex);
 
@@ -873,8 +888,8 @@ int pa_memimport_process_revoke(pa_memimport *i, uint32_t id) {
 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;
@@ -895,7 +910,7 @@ pa_memexport* pa_memexport_new(pa_mempool *p, pa_memexport_revoke_cb_t cb, void
 }
 
 void pa_memexport_free(pa_memexport *e) {
-    assert(e);
+    pa_assert(e);
 
     pa_mutex_lock(e->mutex);
     while (e->used_slots)
@@ -906,6 +921,7 @@ void pa_memexport_free(pa_memexport *e) {
     PA_LLIST_REMOVE(pa_memexport, e->pool->exports, e);
     pa_mutex_unlock(e->pool->mutex);
 
+    pa_mutex_free(e->mutex);
     pa_xfree(e);
 }
 
@@ -913,7 +929,7 @@ void pa_memexport_free(pa_memexport *e) {
 int pa_memexport_process_release(pa_memexport *e, uint32_t id) {
     pa_memblock *b;
 
-    assert(e);
+    pa_assert(e);
 
     pa_mutex_lock(e->mutex);
 
@@ -933,8 +949,8 @@ int pa_memexport_process_release(pa_memexport *e, uint32_t id) {
 
 /*     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) b->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, b->length);
@@ -952,8 +968,8 @@ fail:
 /* 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);
 
@@ -977,13 +993,13 @@ static void memexport_revoke_blocks(pa_memexport *e, pa_memimport *i) {
 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);
     }
 
@@ -999,15 +1015,14 @@ int pa_memexport_put(pa_memexport *e, pa_memblock *b, uint32_t *block_id, uint32
     pa_shm *memory;
     struct memexport_slot *slot;
     void *data;
-    size_t length;
 
-    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;
@@ -1035,25 +1050,25 @@ int pa_memexport_put(pa_memexport *e, pa_memblock *b, uint32_t *block_id, uint32
     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(data >= memory->ptr);
-    assert((uint8_t*) data + 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*) data - (uint8_t*) memory->ptr;
-    *size = length;
+    *size = b->length;
 
     pa_memblock_release(b);
 
     pa_atomic_inc(&e->pool->stat.n_exported);
-    pa_atomic_add(&e->pool->stat.exported_size, length);
+    pa_atomic_add(&e->pool->stat.exported_size, b->length);
 
     return 0;
 }

commit 2a19c466bc66bb5ec8bfc1a5ab7fabe5e4399881
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Jul 13 23:28:11 2007 +0000

    Fix typo in pa_memblock_release() call; s/assert/pa_assert/
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1522 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/tests/memblock-test.c b/src/tests/memblock-test.c
index 1f63499..2b9d340 100644
--- a/src/tests/memblock-test.c
+++ b/src/tests/memblock-test.c
@@ -23,11 +23,11 @@
 #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) {
@@ -88,7 +88,7 @@ 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);
 
@@ -100,7 +100,7 @@ int main(int argc, char *argv[]) {
     blocks[2] = pa_memblock_new_pool(pool_a, sizeof(txt));
     x = pa_memblock_acquire(blocks[2]);
     snprintf(x, pa_memblock_get_length(blocks[2]), "%s", txt);
-    pa_memblock_release(blocks[1]);
+    pa_memblock_release(blocks[2]);
 
     blocks[3] = pa_memblock_new_malloced(pool_a, pa_xstrdup(txt), sizeof(txt));
     blocks[4] = NULL;
@@ -109,35 +109,35 @@ 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);
+        pa_assert(mb_c);
         x = pa_memblock_acquire(mb_c);
         printf("1 data=%s\n", x);
         pa_memblock_release(mb_c);

commit c76d035dad2f5c8768b4ee707a7c84272dfca697
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sat Jul 14 11:26:55 2007 +0000

    Fix a couple of typos in the resampler code
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1523 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/resampler.c b/src/pulsecore/resampler.c
index 9c8e32f..a8c9005 100644
--- a/src/pulsecore/resampler.c
+++ b/src/pulsecore/resampler.c
@@ -315,7 +315,9 @@ static pa_memchunk* convert_to_float(pa_resampler *r, pa_memchunk *input) {
 
     src = (uint8_t*) pa_memblock_acquire(input->memblock) + input->index;
     dst = (uint8_t*) pa_memblock_acquire(u->buf1.memblock);
+
     u->to_float32ne_func(n_samples, src, dst);
+
     pa_memblock_release(input->memblock);
     pa_memblock_release(u->buf1.memblock);
 
@@ -402,9 +404,9 @@ static pa_memchunk *resample(pa_resampler *r, pa_memchunk *input) {
         return input;
 
     in_n_samples = input->length / sizeof(float);
-    in_n_frames = in_n_samples * r->o_ss.channels;
+    in_n_frames = in_n_samples / r->o_ss.channels;
 
-    out_n_frames = (in_n_frames*r->o_ss.rate/r->i_ss.rate)+1024;
+    out_n_frames = ((in_n_frames*r->o_ss.rate)/r->i_ss.rate)+1024;
     out_n_samples = out_n_frames * r->o_ss.channels;
 
     if (!u->buf3.memblock || u->buf3_samples < out_n_samples) {
@@ -464,7 +466,7 @@ static pa_memchunk *convert_from_float(pa_resampler *r, pa_memchunk *input) {
         u->buf4.index = 0;
     }
 
-    src = (uint8_t*) pa_memblock_acquire(input->memblock) + input->length;
+    src = (uint8_t*) pa_memblock_acquire(input->memblock) + input->index;
     dst = pa_memblock_acquire(u->buf4.memblock);
     u->from_float32ne_func(n_samples, src, dst);
     pa_memblock_release(input->memblock);

commit a094923fd5f5012d71383e031256dd9cc5b26a5d
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Jul 25 14:40:12 2007 +0000

    change order of munmap and freeing of memblocks
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1524 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-oss.c b/src/modules/module-oss.c
index cabdf16..b210c17 100644
--- a/src/modules/module-oss.c
+++ b/src/modules/module-oss.c
@@ -1297,15 +1297,6 @@ void pa__done(pa_core *c, pa_module*m) {
     if (u->memchunk.memblock)
         pa_memblock_unref(u->memchunk.memblock);
 
-    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)
-        close(u->fd);
-
     if (u->out_mmap_memblocks) {
         unsigned i;
         for (i = 0; i < u->out_nfrags; i++)
@@ -1322,6 +1313,15 @@ void pa__done(pa_core *c, pa_module*m) {
         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)
+        close(u->fd);
+
     pa_xfree(u->device_name);
     
     pa_xfree(u);

commit 279b1b3311d5e71348a3d5ffa3bc76468e047333
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Jul 25 14:41:54 2007 +0000

    wrap destructor gcc attribute in macro
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1525 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/gccmacro.h b/src/pulsecore/gccmacro.h
index 57d2800..f3ace59 100644
--- a/src/pulsecore/gccmacro.h
+++ b/src/pulsecore/gccmacro.h
@@ -52,4 +52,10 @@
 #define PA_GCC_UNUSED
 #endif
 
+#ifdef __GNUC__
+#define PA_GCC_DESTRUCTOR __attribute__ ((destructor))
+#else
+#define PA_GCC_DESTRUCTOR
+#endif
+
 #endif

commit f42e4438eb5cf81a0a96e2763846faa2f3193223
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Jul 25 14:43:05 2007 +0000

    destruct freelists properly, by using gcc destructors. we do this only to make valgrind shut up, not because it would have any real value during runtime
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1526 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/flist.h b/src/pulsecore/flist.h
index 102d30e..177edd6 100644
--- a/src/pulsecore/flist.h
+++ b/src/pulsecore/flist.h
@@ -27,6 +27,7 @@
 #include <pulse/def.h>
 
 #include <pulsecore/once.h>
+#include <pulsecore/gccmacro.h>
 
 /* A multiple-reader multipler-write lock-free free list implementation */
 
@@ -40,20 +41,26 @@ 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);
 
-#define PA_STATIC_FLIST_DECLARE(name, size)                     \
-    static struct {                                             \
-        pa_flist *flist;                                        \
-        pa_once_t once;                                         \
-    } name##_static_flist = { NULL, PA_ONCE_INIT };             \
-                                                                \
-    static void name##_init(void) {                             \
-        name##_static_flist.flist = pa_flist_new(size);         \
-    }                                                           \
-                                                                \
-    static inline pa_flist* name##_get(void) {                  \
-        pa_once(&name##_static_flist.once, name##_init);        \
-        return name##_static_flist.flist;                       \
-    } \
+/* 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, destroy_cb)                 \
+    static struct {                                                     \
+        pa_flist *flist;                                                \
+        pa_once_t once;                                                 \
+    } name##_static_flist = { NULL, PA_ONCE_INIT };                     \
+    static void name##_init(void) {                                     \
+        name##_static_flist.flist = pa_flist_new(size);                 \
+    }                                                                   \
+    static inline pa_flist* name##_get(void) {                          \
+        pa_once(&name##_static_flist.once, name##_init);                \
+        return name##_static_flist.flist;                               \
+    }                                                                   \
+    static void name##_destructor(void) PA_GCC_DESTRUCTOR;              \
+    static void name##_destructor(void) {                               \
+        if (name##_static_flist.flist)                                  \
+            pa_flist_free(name##_static_flist.flist, destroy_cb);       \
+    }                                                                   \
     struct __stupid_useless_struct_to_allow_trailing_semicolon
 
 #define PA_STATIC_FLIST_GET(name) (name##_get())

commit e339d4b9c49a4e0bc56d8d6608b2f55230d42258
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Jul 25 14:44:00 2007 +0000

    update static free list usage in hashmap
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1527 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/hashmap.c b/src/pulsecore/hashmap.c
index 450f89c..57be818 100644
--- a/src/pulsecore/hashmap.c
+++ b/src/pulsecore/hashmap.c
@@ -56,7 +56,7 @@ struct pa_hashmap {
     pa_compare_func_t compare_func;
 };
 
-PA_STATIC_FLIST_DECLARE(entries, 0);
+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;

commit 9cc20b46b7f8eba94f52a563e7781aff90274bef
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Jul 25 14:44:25 2007 +0000

    update static free list usage in asyncmsgq
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1528 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/asyncmsgq.c b/src/pulsecore/asyncmsgq.c
index 26714a0..1b6d802 100644
--- a/src/pulsecore/asyncmsgq.c
+++ b/src/pulsecore/asyncmsgq.c
@@ -39,7 +39,7 @@
 
 #include "asyncmsgq.h"
 
-PA_STATIC_FLIST_DECLARE(asyncmsgq, 0);
+PA_STATIC_FLIST_DECLARE(asyncmsgq, 0, pa_xfree);
 
 struct asyncmsgq_item {
     int code;

commit 068f5d5eef1cab3615f9899e0e458d59e54e95a2
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Jul 25 14:46:40 2007 +0000

    drop chunk argument from various drop() functions, since it doesn't make any sense if we want to guarantee always monotonously increasing read pointers; a couple of other fixes
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1529 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-sine.c b/src/modules/module-sine.c
index b5b7e60..a784f21 100644
--- a/src/modules/module-sine.c
+++ b/src/modules/module-sine.c
@@ -73,14 +73,13 @@ static int sink_input_peek_cb(pa_sink_input *i, pa_memchunk *chunk) {
     return 0;
 }
 
-static void sink_input_drop_cb(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;
     size_t l;
     
     pa_assert(i);
     u = i->userdata;
     pa_assert(u);
-    pa_assert(chunk);
     pa_assert(length > 0);
 
     u->peek_index += length;
@@ -93,8 +92,10 @@ static void sink_input_drop_cb(pa_sink_input *i, const pa_memchunk *chunk, size_
 
 static void sink_input_kill_cb(pa_sink_input *i) {
     struct userdata *u;
-    pa_assert(i && i->userdata);
+    
+    pa_assert(i);
     u = i->userdata;
+    pa_assert(u);
 
     pa_sink_input_disconnect(u->sink_input);
     pa_sink_input_unref(u->sink_input);
diff --git a/src/modules/rtp/rtp.c b/src/modules/rtp/rtp.c
index f0ab7d8..31dec65 100644
--- a/src/modules/rtp/rtp.c
+++ b/src/modules/rtp/rtp.c
@@ -90,7 +90,7 @@ int pa_rtp_send(pa_rtp_context *c, size_t size, pa_memblockq *q) {
             }
 
             skip += k;
-            pa_memblockq_drop(q, &chunk, k);
+            pa_memblockq_drop(q, k);
         }
 
         if (r < 0 || !chunk.memblock || n >= size || iov_idx >= MAX_IOVECS) {
diff --git a/src/pulse/stream.c b/src/pulse/stream.c
index 44fce52..f18a5dd 100644
--- a/src/pulse/stream.c
+++ b/src/pulse/stream.c
@@ -700,7 +700,7 @@ int pa_stream_drop(pa_stream *s) {
     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)
diff --git a/src/pulsecore/memblock.c b/src/pulsecore/memblock.c
index 8da9ceb..c39147d 100644
--- a/src/pulsecore/memblock.c
+++ b/src/pulsecore/memblock.c
@@ -150,7 +150,7 @@ struct pa_mempool {
 
 static void segment_detach(pa_memimport_segment *seg);
 
-PA_STATIC_FLIST_DECLARE(unused_memblocks, 0);
+PA_STATIC_FLIST_DECLARE(unused_memblocks, 0, pa_xfree);
 
 /* No lock necessary */
 static void stat_add(pa_memblock*b) {
@@ -670,8 +670,8 @@ void pa_mempool_free(pa_mempool *p) {
     pa_mutex_unlock(p->mutex);
 
     if (pa_atomic_load(&p->stat.n_allocated) > 0) {
-        raise(SIGTRAP);
-        pa_log_warn("WARNING! Memory pool destroyed but not all memory blocks freed!");
+/*         raise(SIGTRAP);  */
+        pa_log_warn("WARNING! Memory pool destroyed but not all memory blocks freed! %u remain.", pa_atomic_load(&p->stat.n_allocated));
     }
 
     pa_flist_free(p->free_slots, NULL);
diff --git a/src/pulsecore/memblockq.c b/src/pulsecore/memblockq.c
index 0c31166..ecdf45b 100644
--- a/src/pulsecore/memblockq.c
+++ b/src/pulsecore/memblockq.c
@@ -36,21 +36,24 @@
 #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;
+    int in_prebuf;
     pa_memblock *silence;
     pa_mcalign *mcalign;
 };
@@ -77,13 +80,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;
     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,7 +105,7 @@ 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;
 
@@ -113,7 +116,7 @@ void pa_memblockq_free(pa_memblockq* bq) {
     pa_assert(bq);
 
     pa_memblockq_flush(bq);
-
+    
     if (bq->silence)
         pa_memblock_unref(bq->silence);
 
@@ -123,7 +126,7 @@ void pa_memblockq_free(pa_memblockq* bq) {
     pa_xfree(bq);
 }
 
-static void drop_block(pa_memblockq *bq, struct memblock_list *q) {
+static void drop_block(pa_memblockq *bq, struct list_item *q) {
     pa_assert(bq);
     pa_assert(q);
 
@@ -140,7 +143,9 @@ 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--;
 }
@@ -171,7 +176,7 @@ static int can_push(pa_memblockq *bq, size_t l) {
 
 int pa_memblockq_push(pa_memblockq* bq, const pa_memchunk *uchunk) {
 
-    struct memblock_list *q, *n;
+    struct list_item *q, *n;
     pa_memchunk chunk;
 
     pa_assert(bq);
@@ -198,7 +203,7 @@ 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;
@@ -212,10 +217,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 +228,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,11 +239,13 @@ 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);
 
@@ -263,7 +270,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);
@@ -287,7 +294,6 @@ int pa_memblockq_push(pa_memblockq* bq, const pa_memchunk *uchunk) {
 
             q = q->prev;
         }
-
     }
 
     if (q) {
@@ -308,7 +314,9 @@ int pa_memblockq_push(pa_memblockq* bq, const pa_memchunk *uchunk) {
         pa_assert(!bq->blocks || (bq->write_index + (int64_t)chunk.length <= bq->blocks->index));
 
 
-    n = pa_xnew(struct memblock_list, 1);
+    if (!(n = pa_flist_pop(PA_STATIC_FLIST_GET(list_items))))
+        n = pa_xnew(struct list_item, 1);
+    
     n->chunk = chunk;
     pa_memblock_ref(n->chunk.memblock);
     n->index = bq->write_index;
@@ -331,24 +339,34 @@ int pa_memblockq_push(pa_memblockq* bq, const pa_memchunk *uchunk) {
     return 0;
 }
 
-int pa_memblockq_peek(pa_memblockq* bq, pa_memchunk *chunk) {
+static int memblockq_check_prebuf(pa_memblockq *bq) {
     pa_assert(bq);
-    pa_assert(chunk);
+    
+    if (bq->in_prebuf) {
+        
+        if (pa_memblockq_get_length(bq) < bq->prebuf)
+            return 1;
 
-    if (bq->state == PREBUF) {
+        bq->in_prebuf = 0;
+        return 0;
+    } else {
 
-        /* We need to pre-buffer */
-        if (pa_memblockq_get_length(bq) < bq->prebuf)
-            return -1;
+        if (bq->prebuf > 0 && bq->read_index >= bq->write_index) {
+            bq->in_prebuf = 1;
+            return 1;
+        }
 
-        bq->state = RUNNING;
+        return 0;
+    }
+}
 
-    } else if (bq->prebuf > 0 && bq->read_index >= bq->write_index) {
+int pa_memblockq_peek(pa_memblockq* bq, pa_memchunk *chunk) {
+    pa_assert(bq);
+    pa_assert(chunk);
 
-        /* Buffer underflow protection */
-        bq->state = PREBUF;
+    /* 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) {
@@ -390,43 +408,16 @@ 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) {
+void pa_memblockq_drop(pa_memblockq *bq, size_t length) {
     pa_assert(bq);
     pa_assert(length % bq->base == 0);
-    pa_assert(!chunk || length <= chunk->length);
-
-    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 */
-
-            pa_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 > pa_memblock_get_length(bq->silence))
-                    l = pa_memblock_get_length(bq->silence);
-
-            }
-
-            /* Do the entries still match? */
-            if (chunk->index != 0 || chunk->length != l || chunk->memblock != bq->silence)
-                return;
-        }
-    }
-
+    
     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;
 
@@ -476,15 +467,11 @@ void pa_memblockq_drop(pa_memblockq *bq, const pa_memchunk *chunk, size_t length
 int pa_memblockq_is_readable(pa_memblockq *bq) {
     pa_assert(bq);
 
-    if (bq->prebuf > 0) {
-        size_t l = pa_memblockq_get_length(bq);
-
-        if (bq->state == PREBUF && l < bq->prebuf)
-            return 0;
+    if (memblockq_check_prebuf(bq))
+        return 0;
 
-        if (l <= 0)
-            return 0;
-    }
+    if (pa_memblockq_get_length(bq) <= 0)
+        return 0;
 
     return 1;
 }
@@ -506,7 +493,7 @@ size_t pa_memblockq_missing(pa_memblockq *bq) {
         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) {
@@ -529,7 +516,7 @@ void pa_memblockq_seek(pa_memblockq *bq, int64_t offset, pa_seek_mode_t seek) {
             bq->write_index = bq->read_index + offset;
             return;
         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;
+            bq->write_index = (bq->blocks_tail ? bq->blocks_tail->index + (int64_t) bq->blocks_tail->chunk.length : bq->read_index) + offset;
             return;
     }
 
@@ -569,7 +556,7 @@ int pa_memblockq_push_align(pa_memblockq* bq, const pa_memchunk *chunk) {
     pa_memchunk rchunk;
 
     pa_assert(bq);
-    pa_assert(chunk && bq->base);
+    pa_assert(chunk);
 
     if (bq->base == 1)
         return pa_memblockq_push(bq, chunk);
@@ -601,21 +588,20 @@ void pa_memblockq_shorten(pa_memblockq *bq, size_t length) {
     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) {
     pa_assert(bq);
 
-    if (bq->state == PREBUF)
-        bq->state = RUNNING;
+    bq->in_prebuf = 0;
 }
 
 void pa_memblockq_prebuf_force(pa_memblockq *bq) {
     pa_assert(bq);
 
-    if (bq->state == RUNNING && bq->prebuf > 0)
-        bq->state = PREBUF;
+    if (!bq->in_prebuf && bq->prebuf > 0)
+        bq->in_prebuf = 1;
 }
 
 size_t pa_memblockq_get_maxlength(pa_memblockq *bq) {
diff --git a/src/pulsecore/memblockq.h b/src/pulsecore/memblockq.h
index e824356..5eb23aa 100644
--- a/src/pulsecore/memblockq.h
+++ b/src/pulsecore/memblockq.h
@@ -83,13 +83,16 @@ 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);
diff --git a/src/pulsecore/play-memblockq.c b/src/pulsecore/play-memblockq.c
index 9c5945a..51ea22e 100644
--- a/src/pulsecore/play-memblockq.c
+++ b/src/pulsecore/play-memblockq.c
@@ -37,7 +37,7 @@
 
 #include "play-memblockq.h"
 
-static void sink_input_kill(pa_sink_input *i) {
+static void sink_input_kill_cb(pa_sink_input *i) {
     pa_memblockq *q;
     assert(i);
     assert(i->userdata);
@@ -50,7 +50,7 @@ static void sink_input_kill(pa_sink_input *i) {
     pa_memblockq_free(q);
 }
 
-static int sink_input_peek(pa_sink_input *i, pa_memchunk *chunk) {
+static int sink_input_peek_cb(pa_sink_input *i, pa_memchunk *chunk) {
     pa_memblockq *q;
     assert(i);
     assert(chunk);
@@ -61,11 +61,11 @@ static int sink_input_peek(pa_sink_input *i, pa_memchunk *chunk) {
     return pa_memblockq_peek(q, chunk);
 }
 
-static void si_kill(PA_GCC_UNUSED pa_mainloop_api *m, void *i) {
-    sink_input_kill(i);
+static void si_kill_cb(PA_GCC_UNUSED pa_mainloop_api *m, void *i) {
+    sink_input_kill_cb(i);
 }
 
-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) {
     pa_memblockq *q;
 
     assert(i);
@@ -74,10 +74,10 @@ static void sink_input_drop(pa_sink_input *i, const pa_memchunk*chunk, size_t le
 
     q = i->userdata;
 
-    pa_memblockq_drop(q, chunk, length);
+    pa_memblockq_drop(q, length);
 
     if (pa_memblockq_get_length(q) <= 0)
-        pa_mainloop_api_once(i->sink->core->mainloop, si_kill, i);
+        pa_mainloop_api_once(i->sink->core->mainloop, si_kill_cb, i);
 }
 
 int pa_play_memblockq(
@@ -116,9 +116,9 @@ int pa_play_memblockq(
     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;
+    si->peek = sink_input_peek_cb;
+    si->drop = sink_input_drop_cb;
+    si->kill = sink_input_kill_cb;
 
     si->userdata = q;
 
diff --git a/src/pulsecore/play-memchunk.c b/src/pulsecore/play-memchunk.c
index 65b6e82..7e750ba 100644
--- a/src/pulsecore/play-memchunk.c
+++ b/src/pulsecore/play-memchunk.c
@@ -37,7 +37,7 @@
 
 #include "play-memchunk.h"
 
-static void sink_input_kill(pa_sink_input *i) {
+static void sink_input_kill_cb(pa_sink_input *i) {
     pa_memchunk *c;
     assert(i && i->userdata);
     c = i->userdata;
@@ -49,7 +49,7 @@ static void sink_input_kill(pa_sink_input *i) {
     pa_xfree(c);
 }
 
-static int sink_input_peek(pa_sink_input *i, pa_memchunk *chunk) {
+static int sink_input_peek_cb(pa_sink_input *i, pa_memchunk *chunk) {
     pa_memchunk *c;
     assert(i && chunk && i->userdata);
     c = i->userdata;
@@ -64,23 +64,24 @@ static int sink_input_peek(pa_sink_input *i, pa_memchunk *chunk) {
     return 0;
 }
 
-static void si_kill(PA_GCC_UNUSED pa_mainloop_api *m, void *i) {
-    sink_input_kill(i);
+static void si_kill_cb(PA_GCC_UNUSED pa_mainloop_api *m, void *i) {
+    sink_input_kill_cb(i);
 }
 
-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) {
     pa_memchunk *c;
     assert(i && length && i->userdata);
     c = i->userdata;
 
-    assert(!memcmp(chunk, c, sizeof(chunk)));
-    assert(length <= c->length);
+    if (length >= c->length) {
+        c->length -= length;
+        c->index += length;
+    } else {
 
-    c->length -= length;
-    c->index += length;
+        c->length = 0;
 
-    if (c->length <= 0)
-        pa_mainloop_api_once(i->sink->core->mainloop, si_kill, i);
+        pa_mainloop_api_once(i->sink->core->mainloop, si_kill_cb, i);
+    }
 }
 
 int pa_play_memchunk(
@@ -113,9 +114,9 @@ int pa_play_memchunk(
     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;
+    si->peek = sink_input_peek_cb;
+    si->drop = sink_input_drop_cb;
+    si->kill = sink_input_kill_cb;
 
     si->userdata = nchunk = pa_xnew(pa_memchunk, 1);
     *nchunk = *chunk;
diff --git a/src/pulsecore/protocol-simple.c b/src/pulsecore/protocol-simple.c
index c423487..8f9aed5 100644
--- a/src/pulsecore/protocol-simple.c
+++ b/src/pulsecore/protocol-simple.c
@@ -67,7 +67,6 @@ typedef struct connection {
 
 PA_DECLARE_CLASS(connection);
 #define CONNECTION(o) (connection_cast(o))
-
 static PA_DEFINE_CHECK_TYPE(connection, connection_check_type, pa_msgobject_check_type);
                      
 struct pa_protocol_simple {
@@ -230,7 +229,7 @@ static int do_write(connection *c) {
         return -1;
     }
 
-    pa_memblockq_drop(c->output_memblockq, &chunk, r);
+    pa_memblockq_drop(c->output_memblockq, r);
 
     return 0;
 }
@@ -271,7 +270,6 @@ fail:
 
 static int connection_process_msg(pa_msgobject *o, int code, void*userdata, pa_memchunk *chunk) {
     connection *c = CONNECTION(o);
-    
     connection_assert_ref(c);
 
     switch (code) {
@@ -351,13 +349,13 @@ static int sink_input_peek_cb(pa_sink_input *i, pa_memchunk *chunk) {
 /*     pa_log("peeked %u %i", r >= 0 ? chunk->length: 0, r); */
 
     if (c->dead && r < 0)
-        pa_asyncmsgq_post(c->protocol->core->asyncmsgq, PA_MSGOBJECT(c), MESSAGE_DROP_CONNECTION, c, NULL, NULL);
+        pa_asyncmsgq_post(c->protocol->core->asyncmsgq, PA_MSGOBJECT(c), MESSAGE_DROP_CONNECTION, NULL, NULL, NULL);
 
     return r;
 }
 
 /* Called from thread context */
-static void sink_input_drop_cb(pa_sink_input *i, const pa_memchunk *chunk, size_t length) {
+static void sink_input_drop_cb(pa_sink_input *i, size_t length) {
     connection*c = i->userdata;
     size_t old, new;
 
@@ -366,7 +364,7 @@ static void sink_input_drop_cb(pa_sink_input *i, const pa_memchunk *chunk, size_
     pa_assert(length);
 
     old = pa_memblockq_missing(c->input_memblockq);
-    pa_memblockq_drop(c->input_memblockq, chunk, length);
+    pa_memblockq_drop(c->input_memblockq, length);
     new = pa_memblockq_missing(c->input_memblockq);
 
     if (new > old) {
@@ -378,9 +376,8 @@ static void sink_input_drop_cb(pa_sink_input *i, const pa_memchunk *chunk, size_
 /* Called from main context */
 static void sink_input_kill_cb(pa_sink_input *i) {
     pa_assert(i);
-    pa_assert(i->userdata);
 
-    connection_drop((connection *) i->userdata);
+    connection_drop(CONNECTION(i->userdata));
 }
 
 /*** source_output callbacks ***/
diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c
index d27f00f..db98dd5 100644
--- a/src/pulsecore/sink-input.c
+++ b/src/pulsecore/sink-input.c
@@ -341,7 +341,7 @@ int pa_sink_input_peek(pa_sink_input *i, pa_memchunk *chunk, pa_cvolume *volume)
 /*     } */
 
     if (!i->thread_info.resampler) {
-        do_volume_adj_here = 0;
+        do_volume_adj_here = 0; /* FIXME??? */
         ret = i->peek(i, chunk);
         goto finish;
     }
@@ -356,15 +356,14 @@ int pa_sink_input_peek(pa_sink_input *i, pa_memchunk *chunk, pa_cvolume *volume)
         if ((ret = i->peek(i, &tchunk)) < 0)
             goto finish;
 
-        pa_assert(tchunk.length);
+        pa_assert(tchunk.length > 0);
 
         l = pa_resampler_request(i->thread_info.resampler, CONVERT_BUFFER_LENGTH);
 
-        if (l > tchunk.length)
-            l = tchunk.length;
+        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) {
@@ -377,7 +376,7 @@ int pa_sink_input_peek(pa_sink_input *i, pa_memchunk *chunk, pa_cvolume *volume)
     }
 
     pa_assert(i->thread_info.resampled_chunk.memblock);
-    pa_assert(i->thread_info.resampled_chunk.length);
+    pa_assert(i->thread_info.resampled_chunk.length > 0);
 
     *chunk = i->thread_info.resampled_chunk;
     pa_memblock_ref(i->thread_info.resampled_chunk.memblock);
@@ -409,7 +408,7 @@ finish:
     return ret;
 }
 
-void pa_sink_input_drop(pa_sink_input *i, const pa_memchunk *chunk, size_t length) {
+void pa_sink_input_drop(pa_sink_input *i, size_t length) {
     pa_sink_input_assert_ref(i);
     pa_assert(length > 0);
 
@@ -440,22 +439,67 @@ void pa_sink_input_drop(pa_sink_input *i, const pa_memchunk *chunk, size_t lengt
 /*         return; */
 /*     } */
 
-    if (!i->thread_info.resampler) {
-        if (i->drop)
-            i->drop(i, chunk, length);
-        return;
-    }
-
-    pa_assert(i->thread_info.resampled_chunk.memblock);
-    pa_assert(i->thread_info.resampled_chunk.length >= length);
+    pa_log("dropping %u", length);
+    
+    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;
+
+        pa_log("really dropping %u", l);
+        
+        i->thread_info.resampled_chunk.index += l;
+        i->thread_info.resampled_chunk.length -= l;
+        
+        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);
+        }
 
-    i->thread_info.resampled_chunk.index += length;
-    i->thread_info.resampled_chunk.length -= length;
+        length -= l;
+    }
 
-    if (i->thread_info.resampled_chunk.length <= 0) {
-        pa_memblock_unref(i->thread_info.resampled_chunk.memblock);
-        i->thread_info.resampled_chunk.memblock = NULL;
-        i->thread_info.resampled_chunk.index = i->thread_info.resampled_chunk.length = 0;
+    pa_log("really remaining %u", length);
+    
+    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, &chunk, &volume) >= 0) {
+                    size_t l = chunk.length;
+
+                    if (l > length)
+                        l = length;
+                    
+                    pa_sink_input_drop(i, l);
+                    length -= l;
+                    
+                } else {
+                    /* Hmmm, peeking failed, so let's at least drop
+                     * the right amount of data */
+                    
+                    if (i->drop)
+                        i->drop(i, pa_resampler_request(i->thread_info.resampler, length));
+                            
+                    break;
+                }
+            }
+
+        } else {
+
+            /* We have no resampler, hence let's just drop the data */
+
+            if (i->drop)
+                i->drop(i, length);
+        }
     }
 }
 
diff --git a/src/pulsecore/sink-input.h b/src/pulsecore/sink-input.h
index 426e48c..fe62917 100644
--- a/src/pulsecore/sink-input.h
+++ b/src/pulsecore/sink-input.h
@@ -75,7 +75,7 @@ struct pa_sink_input {
     int muted;
 
     int (*peek) (pa_sink_input *i, pa_memchunk *chunk);
-    void (*drop) (pa_sink_input *i, const pa_memchunk *chunk, size_t length);
+    void (*drop) (pa_sink_input *i, size_t length);
     void (*kill) (pa_sink_input *i);             /* may be NULL */
     pa_usec_t (*get_latency) (pa_sink_input *i); /* may be NULL */
     void (*underrun) (pa_sink_input *i);         /* may be NULL */
@@ -178,7 +178,7 @@ 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, 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_drop(pa_sink_input *i, size_t length);
 int pa_sink_input_process_msg(pa_msgobject *o, int code, void *userdata, pa_memchunk *chunk);
 
 #endif
diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c
index 5a79a41..a66097b 100644
--- a/src/pulsecore/sink.c
+++ b/src/pulsecore/sink.c
@@ -326,7 +326,7 @@ static void inputs_drop(pa_sink *s, pa_mix_info *info, unsigned n, size_t length
         }
 
         /* Drop read data */
-        pa_sink_input_drop(i, m ? &m->chunk : NULL, length);
+        pa_sink_input_drop(i, length);
 
         if (m) {
             pa_sink_input_unref(m->userdata);
diff --git a/src/pulsecore/sound-file-stream.c b/src/pulsecore/sound-file-stream.c
index 974c053..c31187c 100644
--- a/src/pulsecore/sound-file-stream.c
+++ b/src/pulsecore/sound-file-stream.c
@@ -26,7 +26,6 @@
 #endif
 
 #include <stdlib.h>
-#include <assert.h>
 #include <stdio.h>
 #include <string.h>
 
@@ -41,89 +40,177 @@
 
 #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 {
+    MESSAGE_DROP_FILE_STREAM
 };
 
-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, file_stream_check_type, pa_msgobject_check_type);
+
+static void file_stream_free(pa_object *o) {
+    file_stream *u = FILE_STREAM(o);
+    pa_assert(u);
 
+    pa_log("xxxx ffreee");
+    
     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 sink_input_peek(pa_sink_input *i, pa_memchunk *chunk) {
-    struct userdata *u;
-    assert(i && chunk && i->userdata);
-    u = i->userdata;
+static void file_stream_drop(file_stream *u) {
+    file_stream_assert_ref(u);
 
-    if (!u->memchunk.memblock) {
-        uint32_t fs = pa_frame_size(&i->sample_spec);
-        sf_count_t n;
-        void *p;
+    pa_log("xxxx drop");
+    
+    
+    if (u->sink_input) {
+        pa_sink_input_disconnect(u->sink_input);
+        pa_sink_input_unref(u->sink_input);
+        u->sink_input = NULL;
 
-        u->memchunk.memblock = pa_memblock_new(i->sink->core->mempool, BUF_SIZE);
-        u->memchunk.index = 0;
+        /* Make sure we don't decrease the ref count twice. */
+        file_stream_unref(u);
+    }
+}
 
-        p = pa_memblock_acquire(u->memchunk.memblock);
+static int file_stream_process_msg(pa_msgobject *o, int code, void*userdata, pa_memchunk *chunk) {
+    file_stream *u = FILE_STREAM(o);
+    file_stream_assert_ref(u);
+    
+    switch (code) {
+        case MESSAGE_DROP_FILE_STREAM:
+            file_stream_drop(u);
+            break;
+    }
 
-        if (u->readf_function) {
-            if ((n = u->readf_function(u->sndfile, p, BUF_SIZE/fs)) <= 0)
-                n = 0;
+    return 0;
+}
 
-            u->memchunk.length = n * fs;
-        } else {
-            if ((n = sf_read_raw(u->sndfile, p, BUF_SIZE)) <= 0)
-                n = 0;
+static void sink_input_kill_cb(pa_sink_input *i) {
+    pa_assert(i);
+    
+    file_stream_drop(FILE_STREAM(i->userdata));
+}
 
-            u->memchunk.length = n;
+static int sink_input_peek_cb(pa_sink_input *i, pa_memchunk *chunk) {
+    file_stream *u;
+    
+    pa_assert(i);
+    pa_assert(chunk);
+    u = FILE_STREAM(i->userdata);
+    file_stream_assert_ref(u);
+
+    for (;;) {
+        
+        if (!u->memchunk.memblock) {
+            
+            u->memchunk.memblock = pa_memblock_new(i->sink->core->mempool, BUF_SIZE);
+            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, BUF_SIZE/fs);
+                pa_memblock_release(u->memchunk.memblock);
+
+                pa_log("%u/%u = data: %02x %02x %02x %02x %02x %02x %02x %02x",
+                       (unsigned int) n, BUF_SIZE/fs,
+                       ((uint8_t*)p)[0], ((uint8_t*)p)[1], ((uint8_t*)p)[2], ((uint8_t*)p)[3],
+                       ((uint8_t*)p)[4], ((uint8_t*)p)[5], ((uint8_t*)p)[6], ((uint8_t*)p)[7]);
+                
+                if (n <= 0)
+                    n = 0;
+                
+                u->memchunk.length = n * fs;
+            } else {
+                sf_count_t n;
+                void *p;
+
+                p = pa_memblock_acquire(u->memchunk.memblock);
+                n = sf_read_raw(u->sndfile, p, BUF_SIZE);
+                pa_memblock_release(u->memchunk.memblock);
+                
+                if (n <= 0)
+                    n = 0;
+                
+                u->memchunk.length = n;
+            }
+            
+            if (u->memchunk.length <= 0) {
+
+                pa_memblock_unref(u->memchunk.memblock);
+                pa_memchunk_reset(&u->memchunk);
+                
+                pa_asyncmsgq_post(u->core->asyncmsgq, PA_MSGOBJECT(u), MESSAGE_DROP_FILE_STREAM, NULL, NULL, NULL);
+                return -1;
+            }
         }
-        pa_memblock_release(u->memchunk.memblock);
 
-        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);
+    
+    if (u->memchunk.memblock) {
 
-    u->memchunk.index += length;
-    u->memchunk.length -= length;
+        if (length < u->memchunk.length) {
+            u->memchunk.index += length;
+            u->memchunk.length -= length;
+            return;
+        }
 
-    if (u->memchunk.length <= 0) {
+        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(
@@ -131,19 +218,23 @@ 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;
 
-    assert(sink);
-    assert(fname);
+    pa_assert(sink);
+    pa_assert(fname);
 
-    u = pa_xnew(struct userdata, 1);
+    u = pa_msgobject_new(file_stream, file_stream_check_type);
+    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));
 
@@ -152,8 +243,6 @@ int pa_play_file(
         goto fail;
     }
 
-    u->readf_function = NULL;
-
     switch (sfinfo.format & 0xFF) {
         case SF_FORMAT_PCM_16:
         case SF_FORMAT_PCM_U8:
@@ -195,18 +284,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;
 }
diff --git a/src/tests/memblockq-test.c b/src/tests/memblockq-test.c
index 7ad3b2f..25ea399 100644
--- a/src/tests/memblockq-test.c
+++ b/src/tests/memblockq-test.c
@@ -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;
@@ -137,7 +137,7 @@ int main(int argc, char *argv[]) {
         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");

commit 9e9dc0b14d42ebe5465c5dfa63c9ba29ebbdc410
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Jul 25 15:44:28 2007 +0000

    Simplify implementation of pa_assert_se()
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1530 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/macro.h b/src/pulsecore/macro.h
index e0381cf..fe944ae 100644
--- a/src/pulsecore/macro.h
+++ b/src/pulsecore/macro.h
@@ -68,10 +68,11 @@ static inline size_t pa_align(size_t l) {
 #define pa_assert_not_reached() pa_assert(!"Should not be reached.")
 
 /* An assert which guarantees side effects of x */
-#define pa_assert_se(x) do {                  \
-        int _r = !!(x);                       \
-        pa_assert(_r);                        \
-    } while(0)
+#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))

commit 2380ad9254a410235869b18c523787071e2a71d4
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Jul 25 15:49:35 2007 +0000

    add our own implementation for pa_snprintf() because NUL termination is apparently not guaranteed on windows and a couple of other libcs
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1531 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/core-util.c b/src/pulsecore/core-util.c
index e5766b2..9879048 100644
--- a/src/pulsecore/core-util.c
+++ b/src/pulsecore/core-util.c
@@ -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>
@@ -83,6 +82,7 @@
 #include <pulsecore/core-error.h>
 #include <pulsecore/winsock.h>
 #include <pulsecore/log.h>
+#include <pulsecore/macro.h>
 
 #include "core-util.h"
 
@@ -1202,3 +1202,21 @@ int pa_atou(const char *s, uint32_t *ret_u) {
 
     return 0;
 }
+
+/* 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;
+}
diff --git a/src/pulsecore/core-util.h b/src/pulsecore/core-util.h
index 1d921e0..a593317 100644
--- a/src/pulsecore/core-util.h
+++ b/src/pulsecore/core-util.h
@@ -92,4 +92,6 @@ 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_snprintf(char *str, size_t size, const char *format, ...);
+
 #endif

commit 2a43bbf206ea513af77a83c20496ebf99d0ebe5f
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Jul 25 15:50:09 2007 +0000

    Modernize things a little
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1532 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/authkey.c b/src/pulsecore/authkey.c
index a6150d0..1476482 100644
--- a/src/pulsecore/authkey.c
+++ b/src/pulsecore/authkey.c
@@ -26,7 +26,6 @@
 #include <config.h>
 #endif
 
-#include <assert.h>
 #include <unistd.h>
 #include <fcntl.h>
 #include <string.h>
@@ -43,13 +42,17 @@
 #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);
 
@@ -57,7 +60,7 @@ static int generate(int fd, void *ret_data, size_t length) {
     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;
     }
 
@@ -75,11 +78,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 +95,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;
         }
 
@@ -123,13 +130,12 @@ finish:
 int pa_authkey_load(const char *path, void *data, size_t length) {
     int ret;
 
-    assert(path && data && length);
-
-    ret = load(path, data, length);
+    pa_assert(path);
+    pa_assert(data);
+    pa_assert(length > 0);
 
-    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 +143,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 +154,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 +174,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 +192,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;
     }
 

commit 8e838381541d090b5bfd0d68acefd2d6676f0d64
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Jul 25 15:50:40 2007 +0000

    Modernize things a little bith more
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1533 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/sound-file.c b/src/pulsecore/sound-file.c
index 6e93f8a..416ae93 100644
--- a/src/pulsecore/sound-file.c
+++ b/src/pulsecore/sound-file.c
@@ -26,31 +26,35 @@
 #endif
 
 #include <string.h>
-#include <assert.h>
 
 #include <sndfile.h>
 
 #include <pulse/sample.h>
 #include <pulsecore/log.h>
+#include <pulsecore/macro.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;
     void *ptr = NULL;
 
-    assert(fname);
-    assert(ss);
-    assert(chunk);
-
-    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))) {
@@ -93,13 +97,12 @@ 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;
 
@@ -125,17 +128,19 @@ finish:
         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);
@@ -165,8 +170,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;
     }
 

commit 929526de33b60ba48e47071be60619616661c97f
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Jul 25 16:23:03 2007 +0000

    Convert most snprintf() calls to pa_snprintf()
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1534 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/Makefile.am b/src/Makefile.am
index 2e37b29..cda3573 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1292,7 +1292,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)
 
diff --git a/src/daemon/cpulimit.c b/src/daemon/cpulimit.c
index d4ac1d8..6536f46 100644
--- a/src/daemon/cpulimit.c
+++ b/src/daemon/cpulimit.c
@@ -130,7 +130,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
 
diff --git a/src/daemon/dumpmodules.c b/src/daemon/dumpmodules.c
index 6743622..cbbf94f 100644
--- a/src/daemon/dumpmodules.c
+++ b/src/daemon/dumpmodules.c
@@ -35,6 +35,7 @@
 #include <pulse/util.h>
 
 #include <pulsecore/modinfo.h>
+#include <pulsecore/core-util.h>
 
 #include "dumpmodules.h"
 
@@ -93,7 +94,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;
 
@@ -137,7 +138,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/modules/gconf/gconf-helper.c b/src/modules/gconf/gconf-helper.c
index 3483b84..abd1328 100644
--- a/src/modules/gconf/gconf-helper.c
+++ b/src/modules/gconf/gconf-helper.c
@@ -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);
diff --git a/src/modules/module-combine.c b/src/modules/module-combine.c
index 716c20b..b6d718d 100644
--- a/src/modules/module-combine.c
+++ b/src/modules/module-combine.c
@@ -251,7 +251,7 @@ 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_snprintf(t, sizeof(t), "Output stream #%u of sink %s", u->n_outputs+1, u->sink->name);
 
     pa_sink_input_new_data_init(&data);
     data.sink = sink;
diff --git a/src/modules/module-detect.c b/src/modules/module-detect.c
index 29d6fc2..190cda9 100644
--- a/src/modules/module-detect.c
+++ b/src/modules/module-detect.c
@@ -96,7 +96,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;
 
@@ -148,16 +148,16 @@ 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) {
             /* 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;
@@ -193,7 +193,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;
diff --git a/src/modules/module-hal-detect.c b/src/modules/module-hal-detect.c
index 1f48a45..6ae9cd0 100644
--- a/src/modules/module-hal-detect.c
+++ b/src/modules/module-hal-detect.c
@@ -182,10 +182,10 @@ static pa_module* hal_device_load_alsa(struct userdata *u, const char *udi,
 
     if (type == ALSA_TYPE_SINK) {
         module_name = "module-alsa-sink";
-        snprintf(args, sizeof(args), "device=hw:%u sink_name=alsa_output.%s", card, strip_udi(udi));
+        pa_snprintf(args, sizeof(args), "device=hw:%u sink_name=alsa_output.%s", card, strip_udi(udi));
     } else {
         module_name = "module-alsa-source";
-        snprintf(args, sizeof(args), "device=hw:%u source_name=alsa_input.%s", card, strip_udi(udi));
+        pa_snprintf(args, sizeof(args), "device=hw:%u source_name=alsa_input.%s", card, strip_udi(udi));
     }
 
     pa_log_debug("Loading %s with arguments '%s'", module_name, args);
@@ -244,7 +244,7 @@ static pa_module* hal_device_load_oss(struct userdata *u, const char *udi,
     if (!device || dbus_error_is_set(error))
         return NULL;
 
-    snprintf(args, sizeof(args), "device=%s sink_name=oss_output.%s source_name=oss_input.%s", device, strip_udi(udi), strip_udi(udi));
+    pa_snprintf(args, sizeof(args), "device=%s sink_name=oss_output.%s source_name=oss_input.%s", device, strip_udi(udi), strip_udi(udi));
     libhal_free_string(device);
 
     pa_log_debug("Loading module-oss with arguments '%s'", args);
diff --git a/src/modules/module-sine.c b/src/modules/module-sine.c
index a784f21..797ba44 100644
--- a/src/modules/module-sine.c
+++ b/src/modules/module-sine.c
@@ -36,6 +36,7 @@
 #include <pulsecore/modargs.h>
 #include <pulsecore/namereg.h>
 #include <pulsecore/log.h>
+#include <pulsecore/core-util.h>
 
 #include "module-sine-symdef.h"
 
@@ -155,7 +156,7 @@ int pa__init(pa_core *c, pa_module*m) {
     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;
diff --git a/src/modules/module-tunnel.c b/src/modules/module-tunnel.c
index 288e049..b96d46b 100644
--- a/src/modules/module-tunnel.c
+++ b/src/modules/module-tunnel.c
@@ -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);
diff --git a/src/pulse/browser.c b/src/pulse/browser.c
index ea2706e..a35fe81 100644
--- a/src/pulse/browser.c
+++ b/src/pulse/browser.c
@@ -112,10 +112,10 @@ static void resolve_callback(
     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_snprintf(a, sizeof(a), "tcp6:%s:%u", avahi_address_snprint(ip, sizeof(ip), aa), port);
     }
     i.server = a;
 
diff --git a/src/pulse/channelmap.c b/src/pulse/channelmap.c
index d5b8f74..5f1fa95 100644
--- a/src/pulse/channelmap.c
+++ b/src/pulse/channelmap.c
@@ -370,7 +370,7 @@ char* pa_channel_map_snprint(char *s, size_t l, const pa_channel_map *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]));
 
diff --git a/src/pulse/context.c b/src/pulse/context.c
index 58a5a87..0dba905 100644
--- a/src/pulse/context.c
+++ b/src/pulse/context.c
@@ -535,7 +535,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) {
diff --git a/src/pulse/sample.c b/src/pulse/sample.c
index ffdeedf..3d449f5 100644
--- a/src/pulse/sample.c
+++ b/src/pulse/sample.c
@@ -31,6 +31,7 @@
 #include <math.h>
 #include <string.h>
 
+#include <pulsecore/core-util.h>
 #include "sample.h"
 
 size_t pa_sample_size(const pa_sample_spec *spec) {
@@ -117,22 +118,22 @@ char *pa_sample_spec_snprint(char *s, size_t l, const pa_sample_spec *spec) {
     assert(s && l && 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) {
     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;
 }
diff --git a/src/pulse/util.c b/src/pulse/util.c
index d561329..c4f2cf7 100644
--- a/src/pulse/util.c
+++ b/src/pulse/util.c
@@ -90,7 +90,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;
         }
 
diff --git a/src/pulse/volume.c b/src/pulse/volume.c
index feb33f0..8bba834 100644
--- a/src/pulse/volume.c
+++ b/src/pulse/volume.c
@@ -29,6 +29,7 @@
 #include <stdio.h>
 #include <string.h>
 
+#include <pulsecore/core-util.h>
 #include "volume.h"
 
 int pa_cvolume_equal(const pa_cvolume *a, const pa_cvolume *b) {
@@ -125,7 +126,7 @@ char *pa_cvolume_snprint(char *s, size_t l, const pa_cvolume *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);
diff --git a/src/pulsecore/core-scache.c b/src/pulsecore/core-scache.c
index cb27278..d5fe6f2 100644
--- a/src/pulsecore/core-scache.c
+++ b/src/pulsecore/core-scache.c
@@ -415,7 +415,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);
         }
     }
diff --git a/src/pulsecore/core-util.c b/src/pulsecore/core-util.c
index 9879048..e61be70 100644
--- a/src/pulsecore/core-util.c
+++ b/src/pulsecore/core-util.c
@@ -431,6 +431,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;
 
@@ -453,13 +455,14 @@ char *pa_vsprintf_malloc(const char *format, va_list ap) {
         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;
 
@@ -1146,17 +1149,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, PATH_SEP, 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)), PATH_SEP, 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)));
     }
 
 
diff --git a/src/pulsecore/inet_ntop.c b/src/pulsecore/inet_ntop.c
index 302369f..041bc09 100644
--- a/src/pulsecore/inet_ntop.c
+++ b/src/pulsecore/inet_ntop.c
@@ -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],
diff --git a/src/pulsecore/namereg.c b/src/pulsecore/namereg.c
index 7f66af0..5fae3fc 100644
--- a/src/pulsecore/namereg.c
+++ b/src/pulsecore/namereg.c
@@ -142,7 +142,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;
diff --git a/src/pulsecore/pdispatch.c b/src/pulsecore/pdispatch.c
index 10238ac..f5ec1c0 100644
--- a/src/pulsecore/pdispatch.c
+++ b/src/pulsecore/pdispatch.c
@@ -206,7 +206,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);
 }
diff --git a/src/pulsecore/pid.c b/src/pulsecore/pid.c
index 5e670e1..efb6e64 100644
--- a/src/pulsecore/pid.c
+++ b/src/pulsecore/pid.c
@@ -172,7 +172,7 @@ int pa_pid_file_create(void) {
         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) {
diff --git a/src/pulsecore/protocol-esound.c b/src/pulsecore/protocol-esound.c
index 6a5c612..fe0b879 100644
--- a/src/pulsecore/protocol-esound.c
+++ b/src/pulsecore/protocol-esound.c
@@ -626,7 +626,7 @@ 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 */
@@ -1194,7 +1194,7 @@ static void on_connection(pa_socket_server*s, pa_iochannel *io, void *userdata)
     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);
+    pa_snprintf(cname, sizeof(cname), "EsounD client (%s)", pname);
     assert(p->core);
     c->client = pa_client_new(p->core, __FILE__, cname);
     assert(c->client);
diff --git a/src/pulsecore/protocol-http.c b/src/pulsecore/protocol-http.c
index 3541721..eb5bda0 100644
--- a/src/pulsecore/protocol-http.c
+++ b/src/pulsecore/protocol-http.c
@@ -69,7 +69,7 @@ static void http_response(struct connection *c, int code, const char *msg, const
     assert(msg);
     assert(mime);
 
-    snprintf(s, sizeof(s),
+    pa_snprintf(s, sizeof(s),
              "HTTP/1.0 %i %s\n"
              "Connection: close\n"
              "Content-Type: %s\n"
@@ -90,7 +90,7 @@ static void http_message(struct connection *c, int code, const char *msg, const
     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"
diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c
index 8645569..97345f0 100644
--- a/src/pulsecore/protocol-native.c
+++ b/src/pulsecore/protocol-native.c
@@ -2381,7 +2381,7 @@ 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);
+    pa_snprintf(cname, sizeof(cname), "Native client (%s)", pname);
     assert(p->core);
     c->client = pa_client_new(p->core, __FILE__, cname);
     assert(c->client);
diff --git a/src/pulsecore/shm.c b/src/pulsecore/shm.c
index 8c7fb4d..8ef02f6 100644
--- a/src/pulsecore/shm.c
+++ b/src/pulsecore/shm.c
@@ -42,6 +42,7 @@
 #include <pulsecore/core-error.h>
 #include <pulsecore/log.h>
 #include <pulsecore/random.h>
+#include <pulsecore/core-util.h>
 #include <pulse/xmalloc.h>
 
 #include "shm.h"
@@ -53,7 +54,7 @@
 #define MAX_SHM_SIZE (1024*1024*20)
 
 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;
 }
 
diff --git a/src/pulsecore/socket-client.c b/src/pulsecore/socket-client.c
index b83bfea..9e7280d 100644
--- a/src/pulsecore/socket-client.c
+++ b/src/pulsecore/socket-client.c
@@ -445,7 +445,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);
diff --git a/src/pulsecore/socket-server.c b/src/pulsecore/socket-server.c
index b5a6dc3..c900ff3 100644
--- a/src/pulsecore/socket-server.c
+++ b/src/pulsecore/socket-server.c
@@ -438,14 +438,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 +454,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 +474,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 +489,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 +505,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;
         }
 
diff --git a/src/pulsecore/socket-util.c b/src/pulsecore/socket-util.c
index 05cb336..511f12e 100644
--- a/src/pulsecore/socket-util.c
+++ b/src/pulsecore/socket-util.c
@@ -85,7 +85,7 @@ void pa_socket_peer_to_string(int fd, char *c, size_t l) {
 
 #ifndef OS_IS_WIN32
     if (fstat(fd, &st) < 0) {
-        snprintf(c, l, "Invalid client fd");
+        pa_snprintf(c, l, "Invalid client fd");
         return;
     }
 #endif
@@ -108,7 +108,7 @@ 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",
+                pa_snprintf(c, l, "TCP/IP client from %i.%i.%i.%i:%u",
                          ip >> 24,
                          (ip >> 16) & 0xFF,
                          (ip >> 8) & 0xFF,
@@ -121,27 +121,27 @@ 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) {
diff --git a/src/pulsecore/strbuf.c b/src/pulsecore/strbuf.c
index a3ddc11..2c66f5f 100644
--- a/src/pulsecore/strbuf.c
+++ b/src/pulsecore/strbuf.c
@@ -153,6 +153,7 @@ int pa_strbuf_printf(pa_strbuf *sb, const char *format, ...) {
 
         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) {
diff --git a/src/pulsecore/x11wrap.c b/src/pulsecore/x11wrap.c
index 6a6a269..067b7df 100644
--- a/src/pulsecore/x11wrap.c
+++ b/src/pulsecore/x11wrap.c
@@ -29,6 +29,7 @@
 #include <pulsecore/llist.h>
 #include <pulsecore/log.h>
 #include <pulsecore/props.h>
+#include <pulsecore/core-util.h>
 
 #include "x11wrap.h"
 
@@ -198,7 +199,7 @@ pa_x11_wrapper* pa_x11_wrapper_get(pa_core *c, const char *name) {
     pa_x11_wrapper *w;
     assert(c);
 
-    snprintf(t, sizeof(t), "x11-wrapper%s%s", name ? "-" : "", name ? name : "");
+    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);
 

commit 98d36efa82f87a900d4fb83a3ac9f4224651be56
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Jul 25 16:33:56 2007 +0000

    fix some alignment issues and modernize file a little bit
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1535 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/strbuf.c b/src/pulsecore/strbuf.c
index 2c66f5f..ca88c59 100644
--- a/src/pulsecore/strbuf.c
+++ b/src/pulsecore/strbuf.c
@@ -27,12 +27,12 @@
 
 #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,17 @@ struct pa_strbuf {
 };
 
 pa_strbuf *pa_strbuf_new(void) {
-    pa_strbuf *sb = pa_xmalloc(sizeof(pa_strbuf));
+    
+    pa_strbuf *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,9 +75,10 @@ void pa_strbuf_free(pa_strbuf *sb) {
 char *pa_strbuf_tostring(pa_strbuf *sb) {
     char *t, *e;
     struct chunk *c;
-    assert(sb);
+    
+    pa_assert(sb);
 
-    e = t = pa_xmalloc(sb->length+1);
+    e = t = pa_xnew(char, sb->length+1);
 
     for (c = sb->head; c; c = c->next) {
         assert((size_t) (e-t) <= sb->length);
@@ -93,27 +97,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 +135,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,13 +155,14 @@ 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);

commit 8836396c77de2bf05914ca4d9aaa6d72d0589ecd
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Jul 25 21:28:56 2007 +0000

    Store strings directly in strlst elements, other modernizations
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1536 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/strlist.c b/src/pulsecore/strlist.c
index 955b78e..1fcb045 100644
--- a/src/pulsecore/strlist.c
+++ b/src/pulsecore/strlist.c
@@ -26,26 +26,31 @@
 #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;

commit 6ad165c68615bacc10213e99a2dd485b5d1f8ed1
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Jul 26 13:14:26 2007 +0000

    add abstracted file descriptor based semaphore object that is lock-free in the best cases
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1537 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/fdsem.c b/src/pulsecore/fdsem.c
new file mode 100644
index 0000000..4de531a
--- /dev/null
+++ b/src/pulsecore/fdsem.c
@@ -0,0 +1,189 @@
+/* $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 "fdsem.h"
+
+struct pa_fdsem {
+    int fds[2];
+    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);
+    
+    if (pipe(f->fds) < 0) {
+        pa_xfree(f);
+        return NULL;
+    }
+
+    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);
+
+    pa_assert(pa_atomic_load(&f->waiting) == 0);
+    
+    close(f->fds[0]);
+    close(f->fds[1]);
+
+    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];
+        
+        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 (;;) {
+                
+                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;
+        
+        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_atomic_dec(&f->waiting);
+}
+
+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);
+    
+    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_atomic_dec(&f->waiting);
+        return -1;
+    }
+        
+    return 0;
+}
+
+int pa_fdsem_after_poll(pa_fdsem *f) {
+    pa_assert(f);
+
+    pa_atomic_dec(&f->waiting);
+
+    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
index 0000000..f38ef20
--- /dev/null
+++ b/src/pulsecore/fdsem.h
@@ -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

commit bc3693261fa2922ff55133432b212dc03589ba50
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Jul 26 13:15:05 2007 +0000

    port asyncq to make use of new fdsem object
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1538 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/asyncq.c b/src/pulsecore/asyncq.c
index 025c695..2238124 100644
--- a/src/pulsecore/asyncq.c
+++ b/src/pulsecore/asyncq.c
@@ -36,12 +36,15 @@
 #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
@@ -52,10 +55,7 @@ struct pa_asyncq {
     unsigned size;
     unsigned read_idx;
     unsigned write_idx;
-    pa_atomic_t read_waiting; /* a bool */
-    pa_atomic_t write_waiting; /* a bool */
-    int read_fds[2], write_fds[2];
-    pa_atomic_t in_read_fifo, in_write_fifo;
+    pa_fdsem *read_fdsem, *write_fdsem;
 };
 
 #define PA_ASYNCQ_CELLS(x) ((pa_atomic_ptr_t*) ((uint8_t*) (x) + PA_ALIGN(sizeof(struct pa_asyncq))))
@@ -79,26 +79,18 @@ pa_asyncq *pa_asyncq_new(unsigned size) {
     l = pa_xmalloc0(PA_ALIGN(sizeof(pa_asyncq)) + (sizeof(pa_atomic_ptr_t) * size));
 
     l->size = size;
-    pa_atomic_store(&l->read_waiting, 0);
-    pa_atomic_store(&l->write_waiting, 0);
-    pa_atomic_store(&l->in_read_fifo, 0);
-    pa_atomic_store(&l->in_write_fifo, 0);
 
-    if (pipe(l->read_fds) < 0) {
+    if (!(l->read_fdsem = pa_fdsem_new())) {
         pa_xfree(l);
         return NULL;
     }
 
-    if (pipe(l->write_fds) < 0) {
-        pa_close(l->read_fds[0]);
-        pa_close(l->read_fds[1]);
+    if (!(l->write_fdsem = pa_fdsem_new())) {
+        pa_fdsem_free(l->read_fdsem);
         pa_xfree(l);
         return NULL;
     }
 
-    pa_make_nonblock_fd(l->read_fds[1]);
-    pa_make_nonblock_fd(l->write_fds[1]);
-
     return l;
 }
 
@@ -112,11 +104,8 @@ void pa_asyncq_free(pa_asyncq *l, pa_free_cb_t free_cb) {
             free_cb(p);
     }
 
-    pa_close(l->read_fds[0]);
-    pa_close(l->read_fds[1]);
-    pa_close(l->write_fds[0]);
-    pa_close(l->write_fds[1]);
-
+    pa_fdsem_free(l->read_fdsem);
+    pa_fdsem_free(l->write_fdsem);
     pa_xfree(l);
 }
 
@@ -134,80 +123,20 @@ int pa_asyncq_push(pa_asyncq*l, void *p, int wait) {
 
     if (!pa_atomic_ptr_cmpxchg(&cells[idx], NULL, p)) {
 
-        /* Let's empty the FIFO from old notifications, before we return */
-            
-        while (pa_atomic_load(&l->in_write_fifo) > 0) {
-            ssize_t r;
-            int x[20];
-
-            if ((r = read(l->write_fds[0], x, sizeof(x))) < 0) {
-
-                if (errno == EINTR)
-                    continue;
-                
-                return -1;
-            }
-
-            pa_assert(r > 0);
-                
-            if (pa_atomic_sub(&l->in_write_fifo, r) <= r)
-                break;
-
-        }
-
-        /* Now let's make sure that we didn't lose any events */
-        if (!pa_atomic_ptr_cmpxchg(&cells[idx], NULL, p)) {
-
-            if (!wait)
-                return -1;
-
-            /* Let's wait for changes. */
-
-            _Y;
-
-            pa_assert_se(pa_atomic_cmpxchg(&l->write_waiting, 0, 1));
-
-            for (;;) {
-                char x[20];
-                ssize_t r;
-                
-                _Y;
-                
-                if (pa_atomic_ptr_cmpxchg(&cells[idx], NULL, p))
-                    break;
-                
-                _Y;
-
-                if ((r = read(l->write_fds[0], x, sizeof(x))) < 0) {
-
-                    if (errno == EINTR)
-                        continue;
-                    
-                    pa_assert_se(pa_atomic_cmpxchg(&l->write_waiting, 1, 0));
-                    return -1;
-                }
-
-                pa_assert(r > 0);
-                pa_atomic_sub(&l->in_write_fifo, r);
-            }
-            
-            _Y;
-            
-            pa_assert_se(pa_atomic_cmpxchg(&l->write_waiting, 1, 0));
-        }
+        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++;
 
-    if (pa_atomic_load(&l->read_waiting) > 0) {
-        char x = 'x';
-        _Y;
-        if (write(l->read_fds[1], &x, sizeof(x)) > 0) {
-            pa_atomic_inc(&l->in_read_fifo);
-/*             pa_log("increasing %p by 1", l); */
-        }
-    }
+    pa_fdsem_post(l->write_fdsem);
 
     return 0;
 }
@@ -226,95 +155,33 @@ void* pa_asyncq_pop(pa_asyncq*l, int wait) {
 
     if (!(ret = pa_atomic_ptr_load(&cells[idx]))) {
 
-/*         pa_log("pop failed wait=%i", wait); */
-
-        /* Hmm, nothing, here, so let's drop all queued events. */
-        while (pa_atomic_load(&l->in_read_fifo) > 0) {
-            ssize_t r;
-            int x[20];
-            
-            if ((r = read(l->read_fds[0], x, sizeof(x))) < 0) {
-                
-                if (errno == EINTR)
-                    continue;
-                
-                return NULL;
-            }
-
-            pa_assert(r > 0);
-
-/*             pa_log("decreasing %p by %i", l, r); */
-            
-            if (pa_atomic_sub(&l->in_read_fifo, r) <= r)
-                break;
-        }
-
-        /* Now let's make sure that we didn't lose any events */
-        if (!(ret = pa_atomic_ptr_load(&cells[idx]))) {
-
-            if (!wait)
-                return NULL;
-
-            /* Let's wait for changes. */
-            
-            _Y;
-            
-            pa_assert_se(pa_atomic_cmpxchg(&l->read_waiting, 0, 1));
-            
-            for (;;) {
-                char x[20];
-                ssize_t r;
-                
-                _Y;
-                
-                if ((ret = pa_atomic_ptr_load(&cells[idx])))
-                    break;
-                
-                _Y;
-                
-                if ((r = read(l->read_fds[0], x, sizeof(x))) < 0) {
-
-                    if (errno == EINTR)
-                        continue;
-                    
-                    pa_assert_se(pa_atomic_cmpxchg(&l->read_waiting, 1, 0));
-                    return NULL;
-                }
-
-/*                 pa_log("decreasing %p by %i", l, r); */
-                
-                pa_assert(r > 0);
-                pa_atomic_sub(&l->in_read_fifo, r);
-            }
-
-            _Y;
-
-            pa_assert_se(pa_atomic_cmpxchg(&l->read_waiting, 1, 0));
-        }
+        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 if we only have a single reader */
+    /* 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++;
 
-    if (pa_atomic_load(&l->write_waiting) > 0) {
-        char x = 'x';
-        _Y;
-        if (write(l->write_fds[1], &x, sizeof(x)) >= 0)
-            pa_atomic_inc(&l->in_write_fifo);
-    }
-
+    pa_fdsem_post(l->read_fdsem);
+    
     return ret;
 }
 
 int pa_asyncq_get_fd(pa_asyncq *q) {
     pa_assert(q);
 
-    return q->read_fds[0];
+    return pa_fdsem_get(q->write_fdsem);
 }
 
 int pa_asyncq_before_poll(pa_asyncq *l) {
@@ -328,14 +195,12 @@ int pa_asyncq_before_poll(pa_asyncq *l) {
     _Y;
     idx = reduce(l, l->read_idx);
 
-    if (pa_atomic_ptr_load(&cells[idx]) || pa_atomic_load(&l->in_read_fifo) > 0)
-        return -1;
-
-    pa_assert_se(pa_atomic_cmpxchg(&l->read_waiting, 0, 1));
+    for (;;) {
+        if (pa_atomic_ptr_load(&cells[idx]))
+            return -1;
 
-    if (pa_atomic_ptr_load(&cells[idx]) || pa_atomic_load(&l->in_read_fifo) > 0) {
-        pa_assert_se(pa_atomic_cmpxchg(&l->read_waiting, 1, 0));
-        return -1;
+        if (pa_fdsem_before_poll(l->write_fdsem) >= 0)
+            return 0;
     }
 
     return 0;
@@ -344,5 +209,5 @@ int pa_asyncq_before_poll(pa_asyncq *l) {
 void pa_asyncq_after_poll(pa_asyncq *l) {
     pa_assert(l);
 
-    pa_assert_se(pa_atomic_cmpxchg(&l->read_waiting, 1, 0));
+    pa_fdsem_after_poll(l->write_fdsem);
 }

commit 8cdde282e8caacabe6f31c0931d1b4b4f1f8a6b1
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Jul 26 13:15:58 2007 +0000

    reverse order of printf and push to make output more readable
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1539 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/tests/asyncq-test.c b/src/tests/asyncq-test.c
index 600d9d0..2e4b66c 100644
--- a/src/tests/asyncq-test.c
+++ b/src/tests/asyncq-test.c
@@ -40,8 +40,8 @@ static void producer(void *_q) {
     int i;
 
     for (i = 0; i < 1000; i++) {
+        printf("pushing %i\n", i);
         pa_asyncq_push(q, (void*) (i+1), 1);
-        printf("pushed %i\n", i);
     }
 
     pa_asyncq_push(q, (void*) -1, 1);

commit 58af737ebba2f9563deb92da0e0eae77b4e3b319
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Jul 26 13:16:37 2007 +0000

    Add fdsem to makefile
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1540 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/Makefile.am b/src/Makefile.am
index cda3573..be0e584 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -655,6 +655,7 @@ libpulsecore_la_SOURCES += \
 		pulsecore/flist.c pulsecore/flist.h \
 		pulsecore/asyncmsgq.c pulsecore/asyncmsgqq.h \
 		pulsecore/asyncq.c pulsecore/asyncq.h \
+		pulsecore/fdsem.c pulsecore/fdsem.h \
 		pulsecore/object.c pulsecore/object.h \
 		pulsecore/msgobject.c pulsecore/msgobject.h \
 		$(PA_THREAD_OBJS)

commit d80fd10a67e2764d301e8ff41cc271c0eee2399f
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Jul 26 13:17:34 2007 +0000

    properly deref sink_input/source_output objects when removing them from a sink/source
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1541 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c
index a66097b..015cf4d 100644
--- a/src/pulsecore/sink.c
+++ b/src/pulsecore/sink.c
@@ -671,7 +671,8 @@ int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, pa_memchunk *
 
         case PA_SINK_MESSAGE_REMOVE_INPUT: {
             pa_sink_input *i = userdata;
-            pa_hashmap_remove(s->thread_info.inputs, PA_UINT32_TO_PTR(i->index));
+            if (pa_hashmap_remove(s->thread_info.inputs, PA_UINT32_TO_PTR(i->index)))
+                pa_sink_input_unref(i);
             return 0;
         }
 
diff --git a/src/pulsecore/source.c b/src/pulsecore/source.c
index ce1ee98..6ca8172 100644
--- a/src/pulsecore/source.c
+++ b/src/pulsecore/source.c
@@ -384,20 +384,22 @@ unsigned pa_source_used_by(pa_source *s) {
     return pa_idxset_size(s->outputs);
 }
 
-int pa_source_process_msg(pa_msgobject *o, int code, void *userdata, pa_memchunk *chunk) {
-    pa_source *s = PA_SOURCE(o);
+int pa_source_process_msg(pa_msgobject *object, int code, void *userdata, pa_memchunk *chunk) {
+    pa_source *s = PA_SOURCE(object);
     pa_source_assert_ref(s);
 
     switch ((pa_source_message_t) code) {
         case PA_SOURCE_MESSAGE_ADD_OUTPUT: {
-            pa_source_output *i = userdata;
-            pa_hashmap_put(s->thread_info.outputs, PA_UINT32_TO_PTR(i->index), pa_source_output_ref(i));
+            pa_source_output *o = userdata;
+            pa_hashmap_put(s->thread_info.outputs, PA_UINT32_TO_PTR(o->index), pa_source_output_ref(o));
             return 0;
         }
 
         case PA_SOURCE_MESSAGE_REMOVE_OUTPUT: {
-            pa_source_output *i = userdata;
-            pa_hashmap_remove(s->thread_info.outputs, PA_UINT32_TO_PTR(i->index));
+            pa_source_output *o = userdata;
+            if (pa_hashmap_remove(s->thread_info.outputs, PA_UINT32_TO_PTR(o->index)))
+                pa_source_output_unref(o);
+            
             return 0;
         }
 

commit 222a6d270ed49d50d0ab73590d45449a77c17ff2
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Jul 26 13:18:50 2007 +0000

    Increase ref counter of sink input as long as it is included in the sink idxset
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1542 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c
index db98dd5..9683661 100644
--- a/src/pulsecore/sink-input.c
+++ b/src/pulsecore/sink-input.c
@@ -198,7 +198,7 @@ pa_sink_input* pa_sink_input_new(
     i->thread_info.volume = i->volume;
     i->thread_info.muted = i->muted;
 
-    pa_assert_se(pa_idxset_put(core->sink_inputs, i, &i->index) == 0);
+    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",
@@ -235,6 +235,7 @@ void pa_sink_input_disconnect(pa_sink_input *i) {
     pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i->sink), PA_SINK_MESSAGE_REMOVE_INPUT, i, NULL);
     pa_idxset_remove_by_data(i->sink->core->sink_inputs, i, NULL);
     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);
 
diff --git a/src/pulsecore/source-output.c b/src/pulsecore/source-output.c
index defb779..ee76a6e 100644
--- a/src/pulsecore/source-output.c
+++ b/src/pulsecore/source-output.c
@@ -157,7 +157,7 @@ pa_source_output* pa_source_output_new(
     o->thread_info.resampler = resampler;
 
     pa_assert_se(pa_idxset_put(core->source_outputs, o, &o->index) == 0);
-    pa_assert_se( pa_idxset_put(o->source->outputs, o, NULL) == 0);
+    pa_assert_se(pa_idxset_put(o->source->outputs, pa_source_output_ref(o), NULL) == 0);
 
     pa_log_info("Created output %u \"%s\" on %s with sample spec %s",
                 o->index,
@@ -191,6 +191,7 @@ void pa_source_output_disconnect(pa_source_output*o) {
 
     pa_idxset_remove_by_data(o->source->core->source_outputs, o, NULL);
     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);
 

commit bc17b8ea2d772e5069fbef4dde24ef9c63f1cfa1
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Jul 26 13:20:11 2007 +0000

    reverse order flist destruction and mempool allocation warning
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1543 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/memblock.c b/src/pulsecore/memblock.c
index c39147d..f3e400e 100644
--- a/src/pulsecore/memblock.c
+++ b/src/pulsecore/memblock.c
@@ -669,12 +669,13 @@ void pa_mempool_free(pa_mempool *p) {
 
     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("WARNING! Memory pool destroyed but not all memory blocks freed! %u remain.", pa_atomic_load(&p->stat.n_allocated));
     }
 
-    pa_flist_free(p->free_slots, NULL);
     pa_shm_free(&p->memory);
 
     pa_mutex_free(p->mutex);

commit 042cb0939431b47e7d6ac91b89d8ef9ab0ce7744
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Jul 26 13:55:52 2007 +0000

    make valgrind shut up regarding non-freed ident strings. other modernizations
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1544 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/log.c b/src/pulsecore/log.c
index a1197eb..53f8974 100644
--- a/src/pulsecore/log.c
+++ b/src/pulsecore/log.c
@@ -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"
@@ -79,13 +79,22 @@ void pa_log_set_ident(const char *p) {
         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;
 }
@@ -101,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);
@@ -218,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);

commit bbb347fa912a5891c18b93d886e3143ca0545a82
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Jul 26 13:58:50 2007 +0000

    properly free memblocks when skipping over them
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1545 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c
index 9683661..44d00ef 100644
--- a/src/pulsecore/sink-input.c
+++ b/src/pulsecore/sink-input.c
@@ -475,8 +475,11 @@ void pa_sink_input_drop(pa_sink_input *i, size_t length) {
                 pa_cvolume volume;
                 
                 if (pa_sink_input_peek(i, &chunk, &volume) >= 0) {
-                    size_t l = chunk.length;
+                    size_t l;
 
+                    pa_memblock_unref(chunk.memblock);
+
+                    l = chunk.length;
                     if (l > length)
                         l = length;
                     

commit 86abfbf9e858e434330375f711a12f2cbdd3c453
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Jul 26 14:40:17 2007 +0000

    remove debug messages; don't queue request messages like nothing when send file is finished
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1546 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/sound-file-stream.c b/src/pulsecore/sound-file-stream.c
index c31187c..946af3e 100644
--- a/src/pulsecore/sound-file-stream.c
+++ b/src/pulsecore/sound-file-stream.c
@@ -62,8 +62,6 @@ static void file_stream_free(pa_object *o) {
     file_stream *u = FILE_STREAM(o);
     pa_assert(u);
 
-    pa_log("xxxx ffreee");
-    
     if (u->memchunk.memblock)
         pa_memblock_unref(u->memchunk.memblock);
 
@@ -76,11 +74,9 @@ static void file_stream_free(pa_object *o) {
 static void file_stream_drop(file_stream *u) {
     file_stream_assert_ref(u);
 
-    pa_log("xxxx drop");
-    
-    
     if (u->sink_input) {
         pa_sink_input_disconnect(u->sink_input);
+
         pa_sink_input_unref(u->sink_input);
         u->sink_input = NULL;
 
@@ -116,6 +112,9 @@ static int sink_input_peek_cb(pa_sink_input *i, pa_memchunk *chunk) {
     u = FILE_STREAM(i->userdata);
     file_stream_assert_ref(u);
 
+    if (!u->sndfile)
+        return -1;
+    
     for (;;) {
         
         if (!u->memchunk.memblock) {
@@ -132,11 +131,6 @@ static int sink_input_peek_cb(pa_sink_input *i, pa_memchunk *chunk) {
                 n = u->readf_function(u->sndfile, p, BUF_SIZE/fs);
                 pa_memblock_release(u->memchunk.memblock);
 
-                pa_log("%u/%u = data: %02x %02x %02x %02x %02x %02x %02x %02x",
-                       (unsigned int) n, BUF_SIZE/fs,
-                       ((uint8_t*)p)[0], ((uint8_t*)p)[1], ((uint8_t*)p)[2], ((uint8_t*)p)[3],
-                       ((uint8_t*)p)[4], ((uint8_t*)p)[5], ((uint8_t*)p)[6], ((uint8_t*)p)[7]);
-                
                 if (n <= 0)
                     n = 0;
                 
@@ -161,6 +155,10 @@ static int sink_input_peek_cb(pa_sink_input *i, pa_memchunk *chunk) {
                 pa_memchunk_reset(&u->memchunk);
                 
                 pa_asyncmsgq_post(u->core->asyncmsgq, PA_MSGOBJECT(u), MESSAGE_DROP_FILE_STREAM, NULL, NULL, NULL);
+
+                sf_close(u->sndfile);
+                u->sndfile = NULL;
+                
                 return -1;
             }
         }
@@ -293,7 +291,7 @@ int pa_play_file(
 
     /* The reference to u is dangling here, because we want to keep
      * this stream around until it is fully played. */
-
+    
     return 0;
 
 fail:

commit 4cc0d0a18f7f4ffd553f0ab40045bcdeda0e590b
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Jul 26 19:19:42 2007 +0000

    remove some log messages
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1547 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c
index 44d00ef..e4e931f 100644
--- a/src/pulsecore/sink-input.c
+++ b/src/pulsecore/sink-input.c
@@ -440,16 +440,12 @@ void pa_sink_input_drop(pa_sink_input *i, size_t length) {
 /*         return; */
 /*     } */
 
-    pa_log("dropping %u", length);
-    
     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;
 
-        pa_log("really dropping %u", l);
-        
         i->thread_info.resampled_chunk.index += l;
         i->thread_info.resampled_chunk.length -= l;
         
@@ -461,8 +457,6 @@ void pa_sink_input_drop(pa_sink_input *i, size_t length) {
         length -= l;
     }
 
-    pa_log("really remaining %u", length);
-    
     if (length > 0) {
         
         if (i->thread_info.resampler) {

commit c936e53fa28381123bf3381f9c9c7d253082451f
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Jul 26 19:30:51 2007 +0000

    Fix channel remapping in resample; other modernizations
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1548 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/resampler.c b/src/pulsecore/resampler.c
index a8c9005..1405d7e 100644
--- a/src/pulsecore/resampler.c
+++ b/src/pulsecore/resampler.c
@@ -25,7 +25,6 @@
 #include <config.h>
 #endif
 
-#include <assert.h>
 #include <string.h>
 
 #include <samplerate.h>
@@ -33,9 +32,9 @@
 #include <liboil/liboil.h>
 
 #include <pulse/xmalloc.h>
-
 #include <pulsecore/sconv.h>
 #include <pulsecore/log.h>
+#include <pulsecore/macro.h>
 
 #include "resampler.h"
 
@@ -83,12 +82,12 @@ pa_resampler* pa_resampler_new(
 
     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 != PA_RESAMPLER_INVALID);
 
     r = pa_xnew(pa_resampler, 1);
     r->impl_data = NULL;
@@ -145,7 +144,7 @@ fail:
 }
 
 void pa_resampler_free(pa_resampler *r) {
-    assert(r);
+    pa_assert(r);
 
     if (r->impl_free)
         r->impl_free(r);
@@ -154,8 +153,8 @@ void pa_resampler_free(pa_resampler *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;
@@ -167,8 +166,8 @@ void pa_resampler_set_input_rate(pa_resampler *r, uint32_t rate) {
 }
 
 void pa_resampler_set_output_rate(pa_resampler *r, uint32_t rate) {
-    assert(r);
-    assert(rate > 0);
+    pa_assert(r);
+    pa_assert(rate > 0);
 
     if (r->o_ss.rate == rate)
         return;
@@ -180,19 +179,19 @@ void pa_resampler_set_output_rate(pa_resampler *r, uint32_t rate) {
 }
 
 void pa_resampler_run(pa_resampler *r, const pa_memchunk *in, pa_memchunk *out) {
-    assert(r && in && out && r->impl_run);
+    pa_assert(r && in && out && r->impl_run);
 
     r->impl_run(r, in, out);
 }
 
 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;
 }
 
 pa_resample_method_t pa_resampler_get_method(pa_resampler *r) {
-    assert(r);
+    pa_assert(r);
     return r->resample_method;
 }
 
@@ -216,7 +215,7 @@ const char *pa_resample_method_to_string(pa_resample_method_t m) {
 pa_resample_method_t pa_parse_resample_method(const char *string) {
     pa_resample_method_t m;
 
-    assert(string);
+    pa_assert(string);
 
     for (m = 0; m < PA_RESAMPLER_MAX; m++)
         if (!strcmp(string, resample_methods[m]))
@@ -231,8 +230,8 @@ pa_resample_method_t pa_parse_resample_method(const char *string) {
 static void libsamplerate_free(pa_resampler *r) {
     struct impl_libsamplerate *u;
 
-    assert(r);
-    assert(r->impl_data);
+    pa_assert(r);
+    pa_assert(r->impl_data);
 
     u = r->impl_data;
 
@@ -253,12 +252,13 @@ static void libsamplerate_free(pa_resampler *r) {
 static void calc_map_table(pa_resampler *r) {
     struct impl_libsamplerate *u;
     unsigned oc;
-    assert(r);
-    assert(r->impl_data);
+    
+    pa_assert(r);
+    pa_assert(r->impl_data);
 
     u = r->impl_data;
 
-    if (!(u->map_required = (!pa_channel_map_equal(&r->i_cm, &r->o_cm) || r->i_ss.channels != r->o_ss.channels)))
+    if (!(u->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++) {
@@ -290,11 +290,11 @@ static pa_memchunk* convert_to_float(pa_resampler *r, pa_memchunk *input) {
     unsigned n_samples;
     void *src, *dst;
 
-    assert(r);
-    assert(input);
-    assert(input->memblock);
+    pa_assert(r);
+    pa_assert(input);
+    pa_assert(input->memblock);
 
-    assert(r->impl_data);
+    pa_assert(r->impl_data);
     u = r->impl_data;
 
     /* Convert the incoming sample into floats and place them in buf1 */
@@ -328,16 +328,16 @@ static pa_memchunk* convert_to_float(pa_resampler *r, pa_memchunk *input) {
 
 static pa_memchunk *remap_channels(pa_resampler *r, pa_memchunk *input) {
     struct impl_libsamplerate *u;
-    unsigned n_samples, n_frames;
+    unsigned in_n_samples, out_n_samples, n_frames;
     int i_skip, o_skip;
     unsigned oc;
     float *src, *dst;
 
-    assert(r);
-    assert(input);
-    assert(input->memblock);
+    pa_assert(r);
+    pa_assert(input);
+    pa_assert(input->memblock);
 
-    assert(r->impl_data);
+    pa_assert(r->impl_data);
     u = r->impl_data;
 
     /* Remap channels and place the result int buf2 */
@@ -345,22 +345,23 @@ static pa_memchunk *remap_channels(pa_resampler *r, pa_memchunk *input) {
     if (!u->map_required || !input->length)
         return input;
 
-    n_samples = input->length / sizeof(float);
-    n_frames = n_samples / r->o_ss.channels;
+    in_n_samples = input->length / sizeof(float);
+    n_frames = in_n_samples / r->i_ss.channels;
+    out_n_samples = n_frames * r->o_ss.channels;
 
-    if (!u->buf2.memblock || u->buf2_samples < n_samples) {
+    if (!u->buf2.memblock || u->buf2_samples < out_n_samples) {
         if (u->buf2.memblock)
             pa_memblock_unref(u->buf2.memblock);
 
-        u->buf2_samples = n_samples;
-        u->buf2.memblock = pa_memblock_new(r->mempool, u->buf2.length = sizeof(float) * n_samples);
+        u->buf2_samples = out_n_samples;
+        u->buf2.memblock = pa_memblock_new(r->mempool, u->buf2.length = sizeof(float) * out_n_samples);
         u->buf2.index = 0;
     }
 
     src = (float*) ((uint8_t*) pa_memblock_acquire(input->memblock) + input->index);
     dst = (float*) pa_memblock_acquire(u->buf2.memblock);
 
-    memset(dst, 0, n_samples * sizeof(float));
+    memset(dst, 0, u->buf2.length);
 
     o_skip = sizeof(float) * r->o_ss.channels;
     i_skip = sizeof(float) * r->i_ss.channels;
@@ -381,7 +382,7 @@ static pa_memchunk *remap_channels(pa_resampler *r, pa_memchunk *input) {
     pa_memblock_release(input->memblock);
     pa_memblock_release(u->buf2.memblock);
 
-    u->buf2.length = n_frames * sizeof(float) * r->o_ss.channels;
+    u->buf2.length = out_n_samples * sizeof(float);
 
     return &u->buf2;
 }
@@ -393,9 +394,9 @@ static pa_memchunk *resample(pa_resampler *r, pa_memchunk *input) {
     unsigned out_n_frames, out_n_samples;
     int ret;
 
-    assert(r);
-    assert(input);
-    assert(r->impl_data);
+    pa_assert(r);
+    pa_assert(input);
+    pa_assert(r->impl_data);
     u = r->impl_data;
 
     /* Resample the data and place the result in buf3 */
@@ -428,8 +429,8 @@ static pa_memchunk *resample(pa_resampler *r, pa_memchunk *input) {
     data.end_of_input = 0;
 
     ret = src_process(u->src_state, &data);
-    assert(ret == 0);
-    assert((unsigned) data.input_frames_used == in_n_frames);
+    pa_assert(ret == 0);
+    pa_assert((unsigned) data.input_frames_used == in_n_frames);
 
     pa_memblock_release(input->memblock);
     pa_memblock_release(u->buf3.memblock);
@@ -444,9 +445,9 @@ static pa_memchunk *convert_from_float(pa_resampler *r, pa_memchunk *input) {
     unsigned n_samples, n_frames;
     void *src, *dst;
 
-    assert(r);
-    assert(input);
-    assert(r->impl_data);
+    pa_assert(r);
+    pa_assert(input);
+    pa_assert(r->impl_data);
     u = r->impl_data;
 
     /* Convert the data into the correct sample type and place the result in buf4 */
@@ -481,13 +482,13 @@ static void libsamplerate_run(pa_resampler *r, const pa_memchunk *in, pa_memchun
     struct impl_libsamplerate *u;
     pa_memchunk *buf;
 
-    assert(r);
-    assert(in);
-    assert(out);
-    assert(in->length);
-    assert(in->memblock);
-    assert(in->length % r->i_fz == 0);
-    assert(r->impl_data);
+    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);
+    pa_assert(r->impl_data);
 
     u = r->impl_data;
 
@@ -511,36 +512,36 @@ static void libsamplerate_run(pa_resampler *r, const pa_memchunk *in, pa_memchun
 static void libsamplerate_update_input_rate(pa_resampler *r, uint32_t rate) {
     struct impl_libsamplerate *u;
 
-    assert(r);
-    assert(rate > 0);
-    assert(r->impl_data);
+    pa_assert(r);
+    pa_assert(rate > 0);
+    pa_assert(r->impl_data);
     u = r->impl_data;
 
     if (!u->src_state) {
         int err;
         u->src_state = src_new(r->resample_method, r->o_ss.channels, &err);
-        assert(u->src_state);
+        pa_assert(u->src_state);
     } else {
         int ret = src_set_ratio(u->src_state, (double) r->o_ss.rate / rate);
-        assert(ret == 0);
+        pa_assert(ret == 0);
     }
 }
 
 static void libsamplerate_update_output_rate(pa_resampler *r, uint32_t rate) {
     struct impl_libsamplerate *u;
 
-    assert(r);
-    assert(rate > 0);
-    assert(r->impl_data);
+    pa_assert(r);
+    pa_assert(rate > 0);
+    pa_assert(r->impl_data);
     u = r->impl_data;
 
     if (!u->src_state) {
         int err;
         u->src_state = src_new(r->resample_method, r->o_ss.channels, &err);
-        assert(u->src_state);
+        pa_assert(u->src_state);
     } else {
         int ret = src_set_ratio(u->src_state, (double) rate / r->i_ss.rate);
-        assert(ret == 0);
+        pa_assert(ret == 0);
     }
 }
 
@@ -592,15 +593,15 @@ static void trivial_run(pa_resampler *r, const pa_memchunk *in, pa_memchunk *out
     unsigned  n_frames;
     struct impl_trivial *u;
 
-    assert(r);
-    assert(in);
-    assert(out);
-    assert(r->impl_data);
+    pa_assert(r);
+    pa_assert(in);
+    pa_assert(out);
+    pa_assert(r->impl_data);
 
     u = r->impl_data;
 
     fz = r->i_fz;
-    assert(fz == r->o_fz);
+    pa_assert(fz == r->o_fz);
 
     n_frames = in->length/fz;
 
@@ -635,7 +636,7 @@ static void trivial_run(pa_resampler *r, const pa_memchunk *in, pa_memchunk *out
             if (j >= n_frames)
                 break;
 
-            assert(o_index*fz < pa_memblock_get_length(out->memblock));
+            pa_assert(o_index*fz < pa_memblock_get_length(out->memblock));
 
             memcpy((uint8_t*) dst + fz*o_index,
                    (uint8_t*) src + fz*j, fz);
@@ -653,13 +654,13 @@ static void trivial_run(pa_resampler *r, const pa_memchunk *in, pa_memchunk *out
     /* 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);
+        pa_assert(u->o_counter >= r->o_ss.rate);
         u->o_counter -= r->o_ss.rate;
     }
 }
 
 static void trivial_free(pa_resampler *r) {
-    assert(r);
+    pa_assert(r);
 
     pa_xfree(r->impl_data);
 }
@@ -667,9 +668,9 @@ static void trivial_free(pa_resampler *r) {
 static void trivial_update_rate(pa_resampler *r, uint32_t rate) {
     struct impl_trivial *u;
 
-    assert(r);
-    assert(rate > 0);
-    assert(r->impl_data);
+    pa_assert(r);
+    pa_assert(rate > 0);
+    pa_assert(r->impl_data);
 
     u = r->impl_data;
     u->i_counter = 0;
@@ -679,9 +680,9 @@ static void trivial_update_rate(pa_resampler *r, uint32_t rate) {
 static int trivial_init(pa_resampler*r) {
     struct impl_trivial *u;
 
-    assert(r);
-    assert(r->i_ss.format == r->o_ss.format);
-    assert(r->i_ss.channels == r->o_ss.channels);
+    pa_assert(r);
+    pa_assert(r->i_ss.format == r->o_ss.format);
+    pa_assert(r->i_ss.channels == r->o_ss.channels);
 
     r->impl_data = u = pa_xnew(struct impl_trivial, 1);
     u->o_counter = u->i_counter = 0;

commit 8e4660a0b5b34ae465fa3765c68dd8f2d276956f
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Jul 26 19:55:51 2007 +0000

    Disable memory mapping if we open the device in O_WRONLY. Unfortunately we cannot do mmap() in Linux without opening the device for reading as well.
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1549 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-oss.c b/src/modules/module-oss.c
index b210c17..96e0c3c 100644
--- a/src/modules/module-oss.c
+++ b/src/modules/module-oss.c
@@ -1078,10 +1078,15 @@ int pa__init(pa_core *c, pa_module*m) {
         goto fail;
 
     if (use_mmap && (!(caps & DSP_CAP_MMAP) || !(caps & DSP_CAP_TRIGGER))) {
-        pa_log("OSS device not mmap capable, falling back to UNIX read/write mode");
+        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 write only, cannot do memory mapping, falling back to UNIX read/write mode.");
+        use_mmap = 0;
+    }
+
     if (pa_oss_get_hw_description(p, hwdesc, sizeof(hwdesc)) >= 0)
         pa_log_info("Hardware name is '%s'.", hwdesc);
     else

commit c7df4ba6c3f9b0f63e45505c53879cab11c0d696
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sat Jul 28 17:16:05 2007 +0000

    minor modernizations
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1550 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulse/utf8.c b/src/pulse/utf8.c
index 923e021..a179b3f 100644
--- a/src/pulse/utf8.c
+++ b/src/pulse/utf8.c
@@ -50,7 +50,6 @@
 #include <config.h>
 #endif
 
-#include <assert.h>
 #include <errno.h>
 #include <stdlib.h>
 #include <inttypes.h>
@@ -60,6 +59,8 @@
 #include <iconv.h>
 #endif
 
+#include <pulsecore/macro.h>
+
 #include "utf8.h"
 #include "xmalloc.h"
 
@@ -207,10 +208,9 @@ static char* iconv_simple(const char *str, const char *to, const char *from) {
 
     inlen = len = strlen(str) + 1;
     new_str = pa_xmalloc(len);
-    assert(new_str);
 
-    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 +226,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);

commit 787f93533c6f0974d83185e2df1f8071dcce48ee
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sat Jul 28 17:24:28 2007 +0000

    port module-alsa-sink to new lock-free core. also add mmmap'ing support while doing so.
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1551 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/Makefile.am b/src/Makefile.am
index be0e584..ec1bbd0 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -934,12 +934,12 @@ modlibexec_LTLIBRARIES += \
 		module-oss.la
 endif
 
-#if HAVE_ALSA
-#modlibexec_LTLIBRARIES += \
-#		libalsa-util.la \
-#		module-alsa-sink.la \
+if HAVE_ALSA
+modlibexec_LTLIBRARIES += \
+		libalsa-util.la \
+		module-alsa-sink.la
 #		module-alsa-source.la
-#endif
+endif
 
 if HAVE_SOLARIS
 modlibexec_LTLIBRARIES += \
@@ -1185,15 +1185,15 @@ module_oss_la_LIBADD = $(AM_LIBADD) libiochannel.la liboss-util.la
 
 # ALSA
 
-#libalsa_util_la_SOURCES = modules/alsa-util.c modules/alsa-util.h
-#libalsa_util_la_LDFLAGS = -avoid-version
-#libalsa_util_la_LIBADD = $(AM_LIBADD) $(ASOUNDLIB_LIBS) libpulsecore.la
-#libalsa_util_la_CFLAGS = $(AM_CFLAGS) $(ASOUNDLIB_CFLAGS)
+libalsa_util_la_SOURCES = modules/alsa-util.c modules/alsa-util.h
+libalsa_util_la_LDFLAGS = -avoid-version
+libalsa_util_la_LIBADD = $(AM_LIBADD) $(ASOUNDLIB_LIBS) libpulsecore.la
+libalsa_util_la_CFLAGS = $(AM_CFLAGS) $(ASOUNDLIB_CFLAGS)
 
-#module_alsa_sink_la_SOURCES = modules/module-alsa-sink.c
-#module_alsa_sink_la_LDFLAGS = -module -avoid-version
-#module_alsa_sink_la_LIBADD = $(AM_LIBADD) $(ASOUNDLIB_LIBS) libalsa-util.la libpulsecore.la
-#module_alsa_sink_la_CFLAGS = $(AM_CFLAGS) $(ASOUNDLIB_CFLAGS)
+module_alsa_sink_la_SOURCES = modules/module-alsa-sink.c
+module_alsa_sink_la_LDFLAGS = -module -avoid-version
+module_alsa_sink_la_LIBADD = $(AM_LIBADD) $(ASOUNDLIB_LIBS) libalsa-util.la libpulsecore.la
+module_alsa_sink_la_CFLAGS = $(AM_CFLAGS) $(ASOUNDLIB_CFLAGS)
 
 #module_alsa_source_la_SOURCES = modules/module-alsa-source.c
 #module_alsa_source_la_LDFLAGS = -module -avoid-version
diff --git a/src/modules/alsa-util.c b/src/modules/alsa-util.c
index 0a51802..520215f 100644
--- a/src/modules/alsa-util.c
+++ b/src/modules/alsa-util.c
@@ -36,219 +36,6 @@
 
 #include "alsa-util.h"
 
-struct pa_alsa_fdlist {
-    int num_fds;
-    struct pollfd *fds;
-    /* 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;
-    pa_defer_event *defer;
-    pa_io_event **ios;
-
-    int polled;
-
-    void (*cb)(void *userdata);
-    void *userdata;
-};
-
-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;
-    int err, i;
-    unsigned short revents;
-
-    assert(a && fdl && (fdl->pcm || fdl->mixer) && fdl->fds && fdl->work_fds);
-
-    if (fdl->polled)
-        return;
-
-    fdl->polled = 1;
-
-    memcpy(fdl->work_fds, fdl->fds, sizeof(struct pollfd) * fdl->num_fds);
-
-    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;
-            if (events & PA_IO_EVENT_OUTPUT)
-                fdl->work_fds[i].revents |= POLLOUT;
-            if (events & PA_IO_EVENT_ERROR)
-                fdl->work_fds[i].revents |= POLLERR;
-            if (events & PA_IO_EVENT_HANGUP)
-                fdl->work_fds[i].revents |= POLLHUP;
-            break;
-        }
-    }
-
-    assert(i != fdl->num_fds);
-
-    if (fdl->pcm)
-        err = snd_pcm_poll_descriptors_revents(fdl->pcm, fdl->work_fds, fdl->num_fds, &revents);
-    else
-        err = snd_mixer_poll_descriptors_revents(fdl->mixer, fdl->work_fds, fdl->num_fds, &revents);
-
-    if (err < 0) {
-        pa_log_error("Unable to get poll revent: %s",
-            snd_strerror(err));
-        return;
-    }
-
-    a->defer_enable(fdl->defer, 1);
-
-    if (revents) {
-        if (fdl->pcm)
-            fdl->cb(fdl->userdata);
-        else
-            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;
-    int num_fds, i, err;
-    struct pollfd *temp;
-
-    assert(a && fdl && (fdl->pcm || 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);
-
-    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);
-    }
-
-    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));
-        return;
-    }
-
-    fdl->polled = 0;
-
-    if (memcmp(fdl->fds, fdl->work_fds, sizeof(struct pollfd) * num_fds) == 0)
-        return;
-
-    if (fdl->ios) {
-        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);
-        }
-    } else {
-        fdl->ios = pa_xmalloc(sizeof(pa_io_event*) * num_fds);
-        assert(fdl->ios);
-    }
-
-    /* Swap pointers */
-    temp = fdl->work_fds;
-    fdl->work_fds = fdl->fds;
-    fdl->fds = temp;
-
-    fdl->num_fds = num_fds;
-
-    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->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);
-
-    if (fdl->defer) {
-        assert(fdl->m);
-        fdl->m->defer_free(fdl->defer);
-    }
-
-    if (fdl->ios) {
-        int i;
-        assert(fdl->m);
-        for (i = 0;i < fdl->num_fds;i++)
-            fdl->m->io_free(fdl->ios[i]);
-        pa_xfree(fdl->ios);
-    }
-
-    if (fdl->fds)
-        pa_xfree(fdl->fds);
-    if (fdl->work_fds)
-        pa_xfree(fdl->work_fds);
-
-    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);
-
-    fdl->mixer = mixer_handle;
-    fdl->m = m;
-
-    fdl->defer = m->defer_new(m, defer_cb, fdl);
-    assert(fdl->defer);
-
-    return 0;
-}
-
 static int set_format(snd_pcm_t *pcm_handle, snd_pcm_hw_params_t *hwparams, pa_sample_format_t *f) {
 
     static const snd_pcm_format_t format_trans[] = {
@@ -308,7 +95,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;
@@ -325,10 +112,19 @@ int pa_alsa_set_hw_params(snd_pcm_t *pcm_handle, pa_sample_spec *ss, uint32_t *p
 
     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)
+        (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)
+            if ((ret = snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0)
+                goto finish;
+
+    } else if ((ret = snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) 
+        goto finish;
+    else if (*use_mmap)
+        *use_mmap = 0;
+    
     if ((ret = set_format(pcm_handle, hwparams, &f)) < 0)
         goto finish;
 
diff --git a/src/modules/alsa-util.h b/src/modules/alsa-util.h
index ea6c7e1..0cde087 100644
--- a/src/modules/alsa-util.h
+++ b/src/modules/alsa-util.h
@@ -32,15 +32,7 @@
 
 #include <pulse/channelmap.h>
 
-struct 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_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_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);
diff --git a/src/modules/module-alsa-sink.c b/src/modules/module-alsa-sink.c
index f9c4efd..4fc2f3a 100644
--- a/src/modules/module-alsa-sink.c
+++ b/src/modules/module-alsa-sink.c
@@ -26,7 +26,6 @@
 #include <config.h>
 #endif
 
-#include <assert.h>
 #include <stdio.h>
 
 #ifdef HAVE_SYS_POLL_H
@@ -38,6 +37,7 @@
 #include <asoundlib.h>
 
 #include <pulse/xmalloc.h>
+#include <pulse/util.h>
 
 #include <pulsecore/core.h>
 #include <pulsecore/module.h>
@@ -47,6 +47,9 @@
 #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 "alsa-util.h"
 #include "module-alsa-sink-symdef.h"
@@ -62,20 +65,36 @@ 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"
+
+#define DEFAULT_NFRAGS 4
+#define DEFAULT_FRAGSIZE_MSEC 25
 
 struct userdata {
-    snd_pcm_t *pcm_handle;
-    snd_mixer_t *mixer_handle;
-    snd_mixer_elem_t *mixer_elem;
+    pa_core *core;
+    pa_module *module;
     pa_sink *sink;
-    struct pa_alsa_fdlist *pcm_fdl;
-    struct pa_alsa_fdlist *mixer_fdl;
-    long hw_volume_max, hw_volume_min;
+    pa_thread *thread;
+    pa_asyncmsgq *asyncmsgq;
+    
+    snd_pcm_t *pcm_handle;
 
-    size_t frame_size, fragment_size;
-    pa_memchunk memchunk, silence;
-    pa_module *module;
+/*     snd_mixer_t *mixer_handle; */
+/*     snd_mixer_elem_t *mixer_elem; */
+/* long hw_volume_max, hw_volume_min; */
+
+    size_t frame_size, fragment_size, hwbuf_size;
+    unsigned nfragments;
+    pa_memchunk memchunk;
+
+    char *device_name;
+
+    int use_mmap;
+
+    int first;
 };
 
 static const char* const valid_modargs[] = {
@@ -87,327 +106,601 @@ static const char* const valid_modargs[] = {
     "fragments",
     "fragment_size",
     "channel_map",
+    "mmap",
     NULL
 };
 
-#define DEFAULT_DEVICE "default"
+static int mmap_write(struct userdata *u) {
+    snd_pcm_sframes_t n;
+    int err;
+    const snd_pcm_channel_area_t *areas;
+    snd_pcm_uframes_t offset, frames;
+    
+    pa_assert(u);
+    pa_assert(u->sink);
 
-static void update_usage(struct userdata *u) {
-    pa_module_set_used(u->module, u->sink ? pa_sink_used_by(u->sink) : 0);
-}
+    for (;;) {
+        pa_memchunk chunk;
+        void *p;
+        
+        if ((n = snd_pcm_avail_update(u->pcm_handle)) < 0) {
 
-static void clear_up(struct userdata *u) {
-    assert(u);
+            if (n == -EPIPE) {
+                pa_log_debug("snd_pcm_avail_update: Buffer underrun!");
+                u->first = 1;
+            }
+            
+            if ((err = snd_pcm_recover(u->pcm_handle, n, 1)) == 0)
+                continue;
 
-    if (u->sink) {
-        pa_sink_disconnect(u->sink);
-        pa_sink_unref(u->sink);
-        u->sink = NULL;
-    }
+            if (err == EAGAIN)
+                return 0;
+            
+            pa_log("snd_pcm_avail_update: %s", snd_strerror(n));
+            return -1;
+        }
 
-    if (u->pcm_fdl)
-        pa_alsa_fdlist_free(u->pcm_fdl);
-    if (u->mixer_fdl)
-        pa_alsa_fdlist_free(u->mixer_fdl);
+/*         pa_log("Got request for %i samples", (int) n); */
+        
+        if (n <= 0)
+            return 0;
+
+        frames = n;
+        
+        if ((err = snd_pcm_mmap_begin(u->pcm_handle, &areas, &offset, &frames)) < 0) {
+            
+            if (err == -EPIPE) {
+                pa_log_debug("snd_pcm_mmap_begin: Buffer underrun!");
+                u->first = 1;
+            }
 
-    u->pcm_fdl = u->mixer_fdl = NULL;
+            if ((err = snd_pcm_recover(u->pcm_handle, err, 1)) == 0)
+                continue;
 
-    if (u->mixer_handle) {
-        snd_mixer_close(u->mixer_handle);
-        u->mixer_handle = NULL;
-    }
+            if (err == EAGAIN)
+                return 0;
 
-    if (u->pcm_handle) {
-        snd_pcm_drop(u->pcm_handle);
-        snd_pcm_close(u->pcm_handle);
-        u->pcm_handle = NULL;
+            pa_log("Failed to write data to DSP: %s", snd_strerror(err));
+            return -1;
+        }
+
+        /* Check these are multiples of 8 bit */
+        pa_assert((areas[0].first & 7) == 0);
+        pa_assert((areas[0].step & 7)== 0);
+
+        /* We assume a single interleaved memory buffer */
+        pa_assert((areas[0].first >> 3) == 0);
+        pa_assert((areas[0].step >> 3) == u->frame_size);
+
+        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 (err == EAGAIN)
+                return 0;
+            
+            pa_log("Failed to write data to DSP: %s", snd_strerror(err));
+            return -1;
+        }
+
+/*         pa_log("wrote %i samples", (int) frames); */
     }
 }
 
-static int xrun_recovery(struct userdata *u) {
-    int ret;
-    assert(u);
-
-    pa_log_info("*** ALSA-XRUN (playback) ***");
+static pa_usec_t sink_get_latency(struct userdata *u) {
+    pa_usec_t r = 0;
+    snd_pcm_sframes_t frames = 0;
+    int err;
+    
+    pa_assert(u);
 
-    if ((ret = snd_pcm_prepare(u->pcm_handle)) < 0) {
-        pa_log("snd_pcm_prepare() failed: %s", snd_strerror(-ret));
+    snd_pcm_avail_update(u->pcm_handle);
 
-        clear_up(u);
-        pa_module_unload_request(u->module);
-        return -1;
+    if ((err = snd_pcm_delay(u->pcm_handle, &frames)) < 0) {
+        pa_log("Failed to get delay: %s", snd_strerror(err));
+        return 0;
     }
 
-    return ret;
+    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 suspend_recovery(struct userdata *u) {
-    int ret;
-    assert(u);
+static int suspend(struct userdata *u) {
+    pa_assert(u);
+    pa_assert(u->pcm_handle);
 
-    pa_log_info("*** ALSA-SUSPEND (playback) ***");
+    snd_pcm_drain(u->pcm_handle);    /* Let's suspend */
+    snd_pcm_close(u->pcm_handle);
+    u->pcm_handle = NULL;
 
-    if ((ret = snd_pcm_resume(u->pcm_handle)) < 0) {
-        if (ret == -EAGAIN)
-            return -1;
+    pa_log_debug("Device suspended...");
+    
+    return 0;
+}
 
-        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));
-        }
+static int unsuspend(struct userdata *u) {
+    pa_sample_spec ss;
+    int err, b;
+    unsigned nfrags;
+    snd_pcm_uframes_t period_size;
 
-        if (ret < 0) {
-            clear_up(u);
-            pa_module_unload_request(u->module);
-            return -1;
-        }
+    pa_assert(u);
+    pa_assert(!u->pcm_handle);
+
+    pa_log_debug("Trying resume...");
+
+    snd_config_update_free_global();
+    if ((err = snd_pcm_open(&u->pcm_handle, u->device_name, SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK)) < 0) {
+        pa_log("Error opening PCM device %s: %s", u->device_name, snd_strerror(err));
+        goto fail;
     }
 
-    return ret;
-}
+    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;
+    }
 
-static void do_write(struct userdata *u) {
-    assert(u);
+    if (b != u->use_mmap) {
+        pa_log_warn("Resume failed, couldn't get original access mode.");
+        goto fail;
+    }
 
-    update_usage(u);
+    if (!pa_sample_spec_equal(&ss, &u->sink->sample_spec)) {
+        pa_log_warn("Resume failed, couldn't restore original sample settings.");
+        goto fail;
+    }
 
-    for (;;) {
-        void *p;
-        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;
-        }
-        assert(memchunk->memblock);
-        assert(memchunk->length);
-        assert((memchunk->length % u->frame_size) == 0);
+    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;
+    }
 
-        p = pa_memblock_acquire(memchunk->memblock);
+    u->first = 1;
+                
+    pa_log_debug("Resumed successfully...");
 
-        if ((frames = snd_pcm_writei(u->pcm_handle, (uint8_t*) p + memchunk->index, memchunk->length / u->frame_size)) < 0) {
-            pa_memblock_release(memchunk->memblock);
+    return 0;
 
-            if (frames == -EAGAIN)
-                return;
+fail:
+    snd_pcm_close(u->pcm_handle);
+    u->pcm_handle = NULL;
 
-            if (frames == -EPIPE) {
-                if (xrun_recovery(u) < 0)
-                    return;
+    return -1;
+}
 
-                continue;
-            }
+static int sink_process_msg(pa_msgobject *o, int code, void *data, pa_memchunk *chunk) {
+    struct userdata *u = PA_SINK(o)->userdata;
 
-            if (frames == -ESTRPIPE) {
-                if (suspend_recovery(u) < 0)
-                    return;
+    switch (code) {
 
-                continue;
-            }
+        case PA_SINK_MESSAGE_GET_LATENCY: {
+            pa_usec_t r = 0;
+
+            if (u->pcm_handle)
+                r = sink_get_latency(u);
 
-            pa_log("snd_pcm_writei() failed: %s", snd_strerror(-frames));
+            *((pa_usec_t*) data) = r;
 
-            clear_up(u);
-            pa_module_unload_request(u->module);
-            return;
+            break;
         }
 
-        pa_memblock_release(memchunk->memblock);
+        case PA_SINK_MESSAGE_SET_STATE:
+
+            if (PA_PTR_TO_UINT(data) == PA_SINK_SUSPENDED) {
+                pa_assert(u->sink->thread_info.state != PA_SINK_SUSPENDED);
 
-        if (memchunk == &u->memchunk) {
-            size_t l = frames * u->frame_size;
-            memchunk->index += l;
-            memchunk->length -= l;
+                if (suspend(u) < 0)
+                    return -1;
+                
+            } else if (u->sink->thread_info.state == PA_SINK_SUSPENDED) {
+                pa_assert(PA_PTR_TO_UINT(data) != PA_SINK_SUSPENDED);
 
-            if (memchunk->length == 0) {
-                pa_memblock_unref(memchunk->memblock);
-                memchunk->memblock = NULL;
-                memchunk->index = memchunk->length = 0;
+                if (unsuspend(u) < 0)
+                    return -1;
             }
-        }
+            
+            break;
+
+/*         case PA_SINK_MESSAGE_SET_VOLUME: */
+
+/*             if (u->use_pcm_volume && u->fd >= 0) { */
 
-        break;
+/*                 if (pa_oss_set_pcm_volume(u->fd, &u->sink->sample_spec, ((pa_cvolume*) data)) < 0) { */
+/*                     pa_log_info("Device doesn't support setting mixer settings: %s", pa_cstrerror(errno)); */
+/*                     u->use_pcm_volume = 0; */
+/*                 } else */
+/*                     return 0; */
+/*             } */
+
+/*             break; */
+
+/*         case PA_SINK_MESSAGE_GET_VOLUME: */
+
+/*             if (u->use_pcm_volume && u->fd >= 0) { */
+
+/*                 if (pa_oss_get_pcm_volume(u->fd, &u->sink->sample_spec, ((pa_cvolume*) data)) < 0) { */
+/*                     pa_log_info("Device doesn't support reading mixer settings: %s", pa_cstrerror(errno)); */
+/*                     u->use_pcm_volume = 0; */
+/*                 } else */
+/*                     return 0; */
+/*             } */
+
+/*             break; */
     }
+
+    return pa_sink_process_msg(o, code, data, chunk);
 }
 
-static void fdl_callback(void *userdata) {
-    struct userdata *u = userdata;
-    assert(u);
 
-    if (snd_pcm_state(u->pcm_handle) == SND_PCM_STATE_XRUN)
-        if (xrun_recovery(u) < 0)
-            return;
+/* static int mixer_callback(snd_mixer_elem_t *elem, unsigned int mask) { */
+/*     struct userdata *u = snd_mixer_elem_get_callback_private(elem); */
 
-    if (snd_pcm_state(u->pcm_handle) == SND_PCM_STATE_SUSPENDED)
-        if (suspend_recovery(u) < 0)
-            return;
+/*     pa_assert(u && u->mixer_handle); */
 
-    do_write(u);
-}
+/*     if (mask == SND_CTL_EVENT_MASK_REMOVE) */
+/*         return 0; */
 
-static int mixer_callback(snd_mixer_elem_t *elem, unsigned int mask) {
-    struct userdata *u = snd_mixer_elem_get_callback_private(elem);
+/*     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); */
+/*     } */
 
-    assert(u && u->mixer_handle);
+/*     return 0; */
+/* } */
 
-    if (mask == SND_CTL_EVENT_MASK_REMOVE)
-        return 0;
+/* static int sink_get_hw_volume_cb(pa_sink *s) { */
+/*     struct userdata *u = s->userdata; */
+/*     int err; */
+/*     int i; */
 
-    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);
-    }
+/*     pa_assert(u); */
+/*     pa_assert(u->mixer_elem); */
 
-    return 0;
-}
+/*     for (i = 0; i < s->hw_volume.channels; i++) { */
+/*         long set_vol, vol; */
 
-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;
+/*         pa_assert(snd_mixer_selem_has_playback_channel(u->mixer_elem, i)); */
 
-    assert(s && u && u->sink);
+/*         if ((err = snd_mixer_selem_get_playback_volume(u->mixer_elem, i, &vol)) < 0) */
+/*             goto fail; */
 
-    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;
-    }
+/*         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; */
 
-    if (frames < 0)
-        frames = 0;
+/*         /\* 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)); */
+/*     } */
 
-    r += pa_bytes_to_usec(frames * u->frame_size, &s->sample_spec);
+/*     return 0; */
 
-    if (u->memchunk.memblock)
-        r += pa_bytes_to_usec(u->memchunk.length, &s->sample_spec);
+/* fail: */
+/*     pa_log_error("Unable to read volume: %s", snd_strerror(err)); */
+/*     s->get_hw_volume = NULL; */
+/*     s->set_hw_volume = NULL; */
+/*     return -1; */
+/* } */
 
-    return r;
-}
+/* static int sink_set_hw_volume_cb(pa_sink *s) { */
+/*     struct userdata *u = s->userdata; */
+/*     int err; */
+/*     int i; */
+/*     pa_volume_t vol; */
 
-static int sink_get_hw_volume_cb(pa_sink *s) {
-    struct userdata *u = s->userdata;
-    int err;
-    int i;
+/*     pa_assert(u); */
+/*     pa_assert(u->mixer_elem); */
 
-    assert(u);
-    assert(u->mixer_elem);
+/*     for (i = 0; i < s->hw_volume.channels; i++) { */
+/*         long alsa_vol; */
 
-    for (i = 0; i < s->hw_volume.channels; i++) {
-        long set_vol, vol;
+/*         pa_assert(snd_mixer_selem_has_playback_channel(u->mixer_elem, i)); */
 
-        assert(snd_mixer_selem_has_playback_channel(u->mixer_elem, i));
+/*         vol = s->hw_volume.values[i]; */
 
-        if ((err = snd_mixer_selem_get_playback_volume(u->mixer_elem, i, &vol)) < 0)
-            goto fail;
+/*         if (vol > PA_VOLUME_NORM) */
+/*             vol = PA_VOLUME_NORM; */
 
-        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;
+/*         alsa_vol = (long) roundf(((float) vol * (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));
-    }
+/*         if ((err = snd_mixer_selem_set_playback_volume(u->mixer_elem, i, alsa_vol)) < 0) */
+/*             goto fail; */
+/*     } */
 
-    return 0;
+/*     return 0; */
 
-fail:
-    pa_log_error("Unable to read volume: %s", snd_strerror(err));
-    s->get_hw_volume = NULL;
-    s->set_hw_volume = NULL;
-    return -1;
-}
+/* fail: */
+/*     pa_log_error("Unable to set volume: %s", snd_strerror(err)); */
+/*     s->get_hw_volume = NULL; */
+/*     s->set_hw_volume = NULL; */
+/*     return -1; */
+/* } */
 
-static int sink_set_hw_volume_cb(pa_sink *s) {
-    struct userdata *u = s->userdata;
-    int err;
-    int i;
-    pa_volume_t vol;
+/* static int sink_get_hw_mute_cb(pa_sink *s) { */
+/*     struct userdata *u = s->userdata; */
+/*     int err, sw; */
 
-    assert(u);
-    assert(u->mixer_elem);
+/*     pa_assert(u && u->mixer_elem); */
 
-    for (i = 0; i < s->hw_volume.channels; i++) {
-        long alsa_vol;
+/*     err = snd_mixer_selem_get_playback_switch(u->mixer_elem, 0, &sw); */
+/*     if (err) { */
+/*         pa_log_error("Unable to get switch: %s", snd_strerror(err)); */
+/*         s->get_hw_mute = NULL; */
+/*         s->set_hw_mute = NULL; */
+/*         return -1; */
+/*     } */
 
-        assert(snd_mixer_selem_has_playback_channel(u->mixer_elem, i));
+/*     s->hw_muted = !sw; */
 
-        vol = s->hw_volume.values[i];
+/*     return 0; */
+/* } */
 
-        if (vol > PA_VOLUME_NORM)
-            vol = PA_VOLUME_NORM;
+/* static int sink_set_hw_mute_cb(pa_sink *s) { */
+/*     struct userdata *u = s->userdata; */
+/*     int err; */
 
-        alsa_vol = (long) roundf(((float) vol * (u->hw_volume_max - u->hw_volume_min)) / PA_VOLUME_NORM) + u->hw_volume_min;
+/*     pa_assert(u && u->mixer_elem); */
 
-        if ((err = snd_mixer_selem_set_playback_volume(u->mixer_elem, i, alsa_vol)) < 0)
-            goto fail;
-    }
+/*     err = snd_mixer_selem_set_playback_switch_all(u->mixer_elem, !s->hw_muted); */
+/*     if (err) { */
+/*         pa_log_error("Unable to set switch: %s", snd_strerror(err)); */
+/*         s->get_hw_mute = NULL; */
+/*         s->set_hw_mute = NULL; */
+/*         return -1; */
+/*     } */
 
-    return 0;
+/*     return 0; */
+/* } */
 
-fail:
-    pa_log_error("Unable to set volume: %s", snd_strerror(err));
-    s->get_hw_volume = NULL;
-    s->set_hw_volume = NULL;
-    return -1;
-}
+static void thread_func(void *userdata) {
+    enum {
+        POLLFD_ASYNCQ,
+        POLLFD_ALSA_BASE
+    };
+
+    struct userdata *u = userdata;
+    struct pollfd *pollfd = NULL;
+    int n_alsa_fds, err;
+    unsigned short revents = 0;
+    snd_pcm_status_t *status;
 
-static int sink_get_hw_mute_cb(pa_sink *s) {
-    struct userdata *u = s->userdata;
-    int err, sw;
+    pa_assert(u);
+    snd_pcm_status_alloca(&status);
 
-    assert(u && u->mixer_elem);
+    pa_log_debug("Thread starting up");
 
-    err = snd_mixer_selem_get_playback_switch(u->mixer_elem, 0, &sw);
-    if (err) {
-        pa_log_error("Unable to get switch: %s", snd_strerror(err));
-        s->get_hw_mute = NULL;
-        s->set_hw_mute = NULL;
-        return -1;
+    if ((n_alsa_fds = snd_pcm_poll_descriptors_count(u->pcm_handle)) < 0) {
+        pa_log("snd_pcm_poll_descriptors_count() failed: %s", snd_strerror(n_alsa_fds));
+        goto fail;
     }
 
-    s->hw_muted = !sw;
+    pollfd = pa_xnew0(struct pollfd, POLLFD_ALSA_BASE + n_alsa_fds);
 
-    return 0;
-}
+    pollfd[POLLFD_ASYNCQ].fd = pa_asyncmsgq_get_fd(u->asyncmsgq);
+    pollfd[POLLFD_ASYNCQ].events = POLLIN;
 
-static int sink_set_hw_mute_cb(pa_sink *s) {
-    struct userdata *u = s->userdata;
-    int err;
+    if ((err = snd_pcm_poll_descriptors(u->pcm_handle, pollfd+POLLFD_ALSA_BASE, n_alsa_fds)) < 0) {
+        pa_log("snd_pcm_poll_descriptors() failed: %s", snd_strerror(err));
+        goto fail;
+    }
+
+    for (;;) {
+        pa_msgobject *object;
+        int code;
+        void *data;
+        pa_memchunk chunk;
+        int r;
+
+/*          pa_log("loop");    */
+        
+        /* Check whether there is a message for us to process */
+        if (pa_asyncmsgq_get(u->asyncmsgq, &object, &code, &data, &chunk, 0) == 0) {
+            int ret;
+
+/*             pa_log("processing msg"); */
+
+            if (!object && code == PA_MESSAGE_SHUTDOWN) {
+                pa_asyncmsgq_done(u->asyncmsgq, 0);
+                goto finish;
+            }
+
+            ret = pa_asyncmsgq_dispatch(object, code, data, &chunk);
+            pa_asyncmsgq_done(u->asyncmsgq, ret);
+            continue;
+        } 
+
+/*         pa_log("loop2"); */
+
+        /* Render some data and write it to the dsp */
+
+        if (u->sink->thread_info.state != PA_SINK_SUSPENDED && ((revents & POLLOUT) || u->first == 1)) {
+
+            if (u->use_mmap) {
+                int ret;
+
+                if ((ret = mmap_write(u)) < 0)
+                    goto fail;
+
+                revents &= ~POLLOUT;
+                
+                if (ret > 0)
+                    continue;
+
+            } else {
+                ssize_t l;
+
+                snd_pcm_hwsync(u->pcm_handle);
+                if ((err = snd_pcm_status(u->pcm_handle, status)) >= 0)
+                    l = snd_pcm_status_get_avail(status) * u->frame_size;
+                else
+                    l = u->fragment_size;
+                
+                do {
+                    void *p;
+                    snd_pcm_sframes_t t;
+                    
+                    pa_assert(l > 0);
+                    
+                    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 = snd_pcm_writei(u->pcm_handle, (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", t, l); */
+                    
+                    pa_assert(t != 0);
+                    
+                    if (t < 0) {
+
+                        if (t == -EPIPE) {
+                            pa_log_debug("Buffer underrun!");
+                            u->first = 1;
+                        }
+                        
+                        if ((t = snd_pcm_recover(u->pcm_handle, t, 1)) == 0)
+                            continue;
+                        
+                        if (t == EAGAIN) {
+                            pa_log_debug("EAGAIN"); 
+                            
+                            revents &= ~POLLOUT;
+                            break;
+                            
+                        } else {
+                            pa_log("Failed to write data to DSP: %s", snd_strerror(t));
+                            goto fail;
+                        }
+                        
+                    } else {
+                        
+                        u->memchunk.index += t * u->frame_size;
+                        u->memchunk.length -= t * u->frame_size;
+                        
+                        if (u->memchunk.length <= 0) {
+                            pa_memblock_unref(u->memchunk.memblock);
+                            pa_memchunk_reset(&u->memchunk);
+                        }
+                        
+                        l -= t * u->frame_size;
+                        
+                        revents &= ~POLLOUT;
+                    }
+                    
+                } while (l > 0);
+                
+                continue;
+            }
+
+            if (u->first) {
+                pa_log_info("Starting playback.");
+                
+                if ((err = snd_pcm_start(u->pcm_handle)) < 0) {
+                    pa_log("Failed to start PCM playback: %s", snd_strerror(err));
+                    goto fail;
+                }
+
+                u->first = 0;
+            }
+        }
 
-    assert(u && u->mixer_elem);
+        /* Hmm, nothing to do. Let's sleep */
+        if (pa_asyncmsgq_before_poll(u->asyncmsgq) < 0)
+            continue;
 
-    err = snd_mixer_selem_set_playback_switch_all(u->mixer_elem, !s->hw_muted);
-    if (err) {
-        pa_log_error("Unable to set switch: %s", snd_strerror(err));
-        s->get_hw_mute = NULL;
-        s->set_hw_mute = NULL;
-        return -1;
+/*         pa_log("polling for %i", POLLFD_ALSA_BASE + (u->sink->thread_info.state != PA_SINK_SUSPENDED ? n_alsa_fds : 0));  */
+        r = poll(pollfd, POLLFD_ALSA_BASE + (u->sink->thread_info.state != PA_SINK_SUSPENDED ? n_alsa_fds : 0), -1);
+        /*pa_log("polling got dsp=%i amq=%i (%i)", r > 0 ? pollfd[POLLFD_DSP].revents : 0, r > 0 ? pollfd[POLLFD_ASYNCQ].revents : 0, r); */
+/*         pa_log("poll end"); */
+
+        pa_asyncmsgq_after_poll(u->asyncmsgq);
+
+        if (r < 0) {
+            if (errno == EINTR) {
+                pollfd[POLLFD_ASYNCQ].revents = 0;
+                revents = 0;
+                continue;
+            }
+
+            pa_log("poll() failed: %s", pa_cstrerror(errno));
+            goto fail;
+        }
+
+        pa_assert(r > 0);
+
+        if (u->sink->thread_info.state != PA_SINK_SUSPENDED) {
+            if ((err = snd_pcm_poll_descriptors_revents(u->pcm_handle, pollfd + POLLFD_ALSA_BASE, n_alsa_fds, &revents)) < 0) {
+                pa_log("snd_pcm_poll_descriptors_revents() failed: %s", snd_strerror(err));
+                goto fail;
+            }
+
+/*             pa_log("got alsa event"); */
+        } else
+            revents = 0;
+        
+        if (revents & ~(POLLOUT|POLLERR)) {
+            pa_log("DSP shutdown.");
+            goto fail;
+        }
+
+        pa_assert((pollfd[POLLFD_ASYNCQ].revents & ~POLLIN) == 0);
     }
 
-    return 0;
+fail:
+    /* We have to continue processing messages until we receive the
+     * SHUTDOWN message */
+    pa_asyncmsgq_post(u->core->asyncmsgq, PA_MSGOBJECT(u->core), PA_CORE_MESSAGE_UNLOAD_MODULE, u->module, NULL, NULL);
+    pa_asyncmsgq_wait_for(u->asyncmsgq, PA_MESSAGE_SHUTDOWN);
+
+finish:
+    pa_log_debug("Thread shutting down");
+
+    pa_xfree(pollfd);
 }
 
 int pa__init(pa_core *c, pa_module*m) {
+    
     pa_modargs *ma = NULL;
     int ret = -1;
     struct userdata *u = NULL;
     const 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;
@@ -416,6 +709,10 @@ int pa__init(pa_core *c, pa_module*m) {
     const char *name;
     char *name_buf = NULL;
     int namereg_fail;
+    int use_mmap = 1, b;
+
+    pa_assert(c);
+    pa_assert(m);
 
     if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
         pa_log("failed to parse module arguments");
@@ -430,19 +727,29 @@ int pa__init(pa_core *c, pa_module*m) {
 
     frame_size = pa_frame_size(&ss);
 
-    /* Fix latency to 100ms */
-    periods = 8;
-    fragsize = pa_bytes_per_second(&ss)/128;
+    nfrags = DEFAULT_NFRAGS;
+    frag_size = pa_usec_to_bytes(DEFAULT_FRAGSIZE_MSEC*1000, &ss);
+    if (frag_size <= 0)
+        frag_size = frame_size;
 
-    if (pa_modargs_get_value_u32(ma, "fragments", &periods) < 0 || pa_modargs_get_value_u32(ma, "fragment_size", &fragsize) < 0) {
+    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 = fragsize/frame_size;
+    period_size = frag_size/frame_size;
 
+    if (pa_modargs_get_value_boolean(ma, "mmap", &use_mmap) < 0) {
+        pa_log("Failed to parse mmap argument.");
+        goto fail;
+    }
+        
     u = pa_xnew0(struct userdata, 1);
-    m->userdata = u;
+    u->core = c;
     u->module = m;
+    m->userdata = u;
+    u->use_mmap = use_mmap;
+    u->first = 1;
+    pa_assert_se(u->asyncmsgq = pa_asyncmsgq_new(0));
 
     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) {
@@ -450,17 +757,25 @@ int pa__init(pa_core *c, pa_module*m) {
         goto fail;
     }
 
+    u->device_name = pa_xstrdup(dev);
+
     if ((err = snd_pcm_info_malloc(&pcm_info)) < 0 ||
         (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) {
+    b = 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 (use_mmap && !b) {
+        pa_log_info("Device doesn't support mmap(), falling back to UNIX read/write mode.");
+        u->use_mmap = use_mmap = b;
+    }
+
     /* ALSA might tweak the sample spec, so recalculate the frame size */
     frame_size = pa_frame_size(&ss);
 
@@ -468,16 +783,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, "PCM", "Master"))) { */
+/*             snd_mixer_close(u->mixer_handle); */
+/*             u->mixer_handle = NULL; */
+/*         } */
+/*     } */
 
     if ((name = pa_modargs_get_value(ma, "sink_name", NULL)))
         namereg_fail = 1;
@@ -486,84 +801,86 @@ 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(c, __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;
-    if (u->mixer_handle) {
-        assert(u->mixer_elem);
-        if (snd_mixer_selem_has_playback_volume(u->mixer_elem)) {
-            int 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);
-            }
-        }
-        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->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("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) {
-            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;
+    pa_sink_set_module(u->sink, m);
+    pa_sink_set_asyncmsgq(u->sink, u->asyncmsgq);
+    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->sink->is_hardware = 1;
+    
+/*     if (u->mixer_handle) { */
+/*         pa_assert(u->mixer_elem); */
+/*         if (snd_mixer_selem_has_playback_volume(u->mixer_elem)) { */
+/*             int 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); */
+/*             } */
+/*         } */
+/*         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; */
+/*         } */
+/*     } */
+
+/*     if (u->mixer_handle) { */
+/*         u->mixer_fdl = pa_alsa_fdlist_new(); */
+/*         pa_assert(u->mixer_fdl); */
+/*         if (pa_alsa_fdlist_init_mixer(u->mixer_fdl, u->mixer_handle, c->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;
+    u->nfragments = nfrags;
+    u->hwbuf_size = u->fragment_size * nfrags;
 
-    pa_log_info("using %u fragments of size %lu bytes.", periods, (long unsigned)u->fragment_size);
+    pa_log_info("Using %u fragments of size %lu bytes.", nfrags, (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;
+    pa_memchunk_reset(&u->memchunk);
 
-    u->memchunk.memblock = NULL;
-    u->memchunk.index = u->memchunk.length = 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_volume)
+        u->sink->get_volume(u->sink);
+    if (u->sink->get_mute)
+        u->sink->get_mute(u->sink);
 
     ret = 0;
 
-    /* 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);
-
 finish:
 
-    pa_xfree(name_buf);
-
      if (ma)
          pa_modargs_free(ma);
 
@@ -582,18 +899,42 @@ fail:
 
 void pa__done(pa_core *c, pa_module*m) {
     struct userdata *u;
-    assert(c && m);
+    
+    pa_assert(c);
+    pa_assert(m);
 
     if (!(u = m->userdata))
         return;
 
-    clear_up(u);
+    if (u->sink)
+        pa_sink_disconnect(u->sink);
+
+    if (u->thread) {
+        pa_asyncmsgq_send(u->asyncmsgq, NULL, PA_MESSAGE_SHUTDOWN, NULL, NULL);
+        pa_thread_free(u->thread);
+    }
+
+    if (u->asyncmsgq)
+        pa_asyncmsgq_free(u->asyncmsgq);
 
+    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->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);
+
+    snd_config_update_free_global();
+    
     pa_xfree(u);
 }
 
diff --git a/src/modules/module-oss.c b/src/modules/module-oss.c
index 96e0c3c..4db1ed0 100644
--- a/src/modules/module-oss.c
+++ b/src/modules/module-oss.c
@@ -48,9 +48,14 @@
 #include <sys/mman.h>
 #endif
 
+#ifdef HAVE_SYS_POLL_H
+#include <sys/poll.h>
+#else
+#include "poll.h"
+#endif
+
 #include <sys/soundcard.h>
 #include <sys/ioctl.h>
-#include <sys/poll.h>
 #include <stdlib.h>
 #include <sys/stat.h>
 #include <stdio.h>
@@ -73,6 +78,7 @@
 #include <pulsecore/core-util.h>
 #include <pulsecore/modargs.h>
 #include <pulsecore/log.h>
+#include <pulsecore/macro.h>
 
 #include "oss-util.h"
 #include "module-oss-symdef.h"
@@ -805,7 +811,6 @@ static void thread_func(void *userdata) {
 
             } else {
                 ssize_t l;
-                void *p;
                 int loop = 0;
                 
                 l = u->out_fragment_size;
@@ -825,6 +830,7 @@ static void thread_func(void *userdata) {
                 }
                 
                 do {
+                    void *p;
                     ssize_t t;
                     
                     pa_assert(l > 0);
@@ -1019,9 +1025,10 @@ finish:
 }
 
 int pa__init(pa_core *c, 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;
     int mode, caps;
@@ -1074,7 +1081,7 @@ int pa__init(pa_core *c, pa_module*m) {
         goto fail;
     }
     
-    if ((fd = pa_oss_open(p = pa_modargs_get_value(ma, "device", DEFAULT_DEVICE), &mode, &caps)) < 0)
+    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))) {
@@ -1087,7 +1094,7 @@ int pa__init(pa_core *c, pa_module*m) {
         use_mmap = 0;
     }
 
-    if (pa_oss_get_hw_description(p, hwdesc, sizeof(hwdesc)) >= 0)
+    if (pa_oss_get_hw_description(dev, hwdesc, sizeof(hwdesc)) >= 0)
         pa_log_info("Hardware name is '%s'.", hwdesc);
     else
         hwdesc[0] = 0;
@@ -1111,11 +1118,12 @@ int pa__init(pa_core *c, pa_module*m) {
     u->core = c;
     u->module = m;
     m->userdata = u;
+    u->fd = fd;
     u->use_getospace = u->use_getispace = 1;
     u->use_getodelay = 1;
     u->use_input_volume = u->use_pcm_volume = 1;
     u->mode = mode;
-    u->device_name = pa_xstrdup(p);
+    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;
@@ -1159,25 +1167,28 @@ int pa__init(pa_core *c, pa_module*m) {
         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;
         }
 
         u->source = pa_source_new(c, __FILE__, name, namereg_fail, &ss, &map);
         pa_xfree(name_buf);
-        if (!u->source)
+        if (!u->source) {
+            pa_log("Failed to create source object");
             goto fail;
+        }
 
         u->source->parent.process_msg = source_process_msg;
         u->source->userdata = u;
 
         pa_source_set_module(u->source, m);
         pa_source_set_asyncmsgq(u->source, u->asyncmsgq);
-        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_description(u->source, t = pa_sprintf_malloc(
+                                          "OSS PCM on %s%s%s%s",
+                                          dev,
+                                          hwdesc[0] ? " (" : "",
+                                          hwdesc[0] ? hwdesc : "",
+                                          hwdesc[0] ? ")" : ""));
         pa_xfree(t);
         u->source->is_hardware = 1;
         u->source->refresh_volume = 1;
@@ -1210,25 +1221,28 @@ try_write:
         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;
         }
 
         u->sink = pa_sink_new(c, __FILE__, name, namereg_fail, &ss, &map);
         pa_xfree(name_buf);
-        if (!u->sink)
+        if (!u->sink) {
+            pa_log("Failed to create sink object");
             goto fail;
+        }
 
         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->asyncmsgq);
-        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_description(u->sink, t = pa_sprintf_malloc(
+                                        "OSS PCM on %s%s%s%s",
+                                        dev,
+                                        hwdesc[0] ? " (" : "",
+                                        hwdesc[0] ? hwdesc : "",
+                                        hwdesc[0] ? ")" : ""));
         pa_xfree(t);
         u->sink->is_hardware = 1;
         u->sink->refresh_volume = 1;
@@ -1241,8 +1255,6 @@ go_on:
     
     pa_assert(u->source || u->sink);
 
-    u->fd = fd;
-
     pa_memchunk_reset(&u->memchunk);
 
     if (!(u->thread = pa_thread_new(thread_func, u))) {
@@ -1261,7 +1273,10 @@ go_on:
     return 0;
 
 fail:
-    if (fd >= 0)
+
+    if (u)
+        pa__done(c, m);
+    else if (fd >= 0)
         close(fd);
 
     if (ma)

commit dd40020057a1452ed75a682e8b07032e5a35aa9c
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sat Jul 28 19:26:40 2007 +0000

    bring back alsa fd list managemet, since we need it for proper mixer change notification
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1552 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/alsa-util.c b/src/modules/alsa-util.c
index 520215f..dd9ac79 100644
--- a/src/modules/alsa-util.c
+++ b/src/modules/alsa-util.c
@@ -33,9 +33,190 @@
 #include <pulse/xmalloc.h>
 
 #include <pulsecore/log.h>
+#include <pulsecore/macro.h>
 
 #include "alsa-util.h"
 
+struct pa_alsa_fdlist {
+    int num_fds;
+    struct pollfd *fds;
+    /* This is a temporary buffer used to avoid lots of mallocs */
+    struct pollfd *work_fds;
+
+    snd_mixer_t *mixer;
+
+    pa_mainloop_api *m;
+    pa_defer_event *defer;
+    pa_io_event **ios;
+
+    int polled;
+
+    void (*cb)(void *userdata);
+    void *userdata;
+};
+
+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 = userdata;
+    int err, i;
+    unsigned short revents;
+
+    pa_assert(a);
+    pa_assert(fdl);
+    pa_assert(fdl->mixer);
+    pa_assert(fdl->fds);
+    pa_assert(fdl->work_fds);
+
+    if (fdl->polled)
+        return;
+
+    fdl->polled = 1;
+
+    memcpy(fdl->work_fds, fdl->fds, sizeof(struct pollfd) * fdl->num_fds);
+
+    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;
+            if (events & PA_IO_EVENT_OUTPUT)
+                fdl->work_fds[i].revents |= POLLOUT;
+            if (events & PA_IO_EVENT_ERROR)
+                fdl->work_fds[i].revents |= POLLERR;
+            if (events & PA_IO_EVENT_HANGUP)
+                fdl->work_fds[i].revents |= POLLHUP;
+            break;
+        }
+    }
+
+    assert(i != fdl->num_fds);
+
+    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)
+        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 = userdata;
+    int num_fds, i, err;
+    struct pollfd *temp;
+
+    pa_assert(a);
+    pa_assert(fdl);
+    pa_assert(fdl->mixer);
+
+    a->defer_enable(fdl->defer, 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_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 ((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;
+    }
+
+    fdl->polled = 0;
+
+    if (memcmp(fdl->fds, fdl->work_fds, sizeof(struct pollfd) * num_fds) == 0)
+        return;
+
+    if (fdl->ios) {
+        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 = NULL;
+        }
+    }
+
+    if (!fdl->ios)
+        fdl->ios = pa_xnew(pa_io_event*, num_fds);
+
+    /* Swap pointers */
+    temp = fdl->work_fds;
+    fdl->work_fds = fdl->fds;
+    fdl->fds = temp;
+
+    fdl->num_fds = num_fds;
+
+    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);
+}
+
+struct pa_alsa_fdlist *pa_alsa_fdlist_new(void) {
+    struct pa_alsa_fdlist *fdl;
+
+    fdl = pa_xnew0(struct pa_alsa_fdlist, 1);
+
+    fdl->num_fds = 0;
+    fdl->fds = NULL;
+    fdl->work_fds = 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) {
+    pa_assert(fdl);
+
+    if (fdl->defer) {
+        pa_assert(fdl->m);
+        fdl->m->defer_free(fdl->defer);
+    }
+
+    if (fdl->ios) {
+        int i;
+        pa_assert(fdl->m);
+        for (i = 0;i < fdl->num_fds;i++)
+            fdl->m->io_free(fdl->ios[i]);
+        pa_xfree(fdl->ios);
+    }
+
+    if (fdl->fds)
+        pa_xfree(fdl->fds);
+    if (fdl->work_fds)
+        pa_xfree(fdl->work_fds);
+
+    pa_xfree(fdl);
+}
+
+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);
+
+    return 0;
+}
+
 static int set_format(snd_pcm_t *pcm_handle, snd_pcm_hw_params_t *hwparams, pa_sample_format_t *f) {
 
     static const snd_pcm_format_t format_trans[] = {
@@ -61,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;
@@ -103,10 +284,10 @@ 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);
 
     buffer_size = *periods * *period_size;
 
@@ -166,10 +347,10 @@ 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;
 
@@ -183,7 +364,8 @@ finish:
 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));
@@ -206,10 +388,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);
 
diff --git a/src/modules/alsa-util.h b/src/modules/alsa-util.h
index 0cde087..f79325c 100644
--- a/src/modules/alsa-util.h
+++ b/src/modules/alsa-util.h
@@ -32,6 +32,12 @@
 
 #include <pulse/channelmap.h>
 
+typedef struct pa_alsa_fdlist pa_alsa_fdlist;
+
+struct pa_alsa_fdlist *pa_alsa_fdlist_new(void);
+void pa_alsa_fdlist_free(struct pa_alsa_fdlist *fdl);
+int pa_alsa_fdlist_set_mixer(struct pa_alsa_fdlist *fdl, snd_mixer_t *mixer_handle, pa_mainloop_api* m);
+
 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_prepare_mixer(snd_mixer_t *mixer, const char *dev);

commit 9dac60c80e9990a5f9d316233ba2c5b98d68acae
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sat Jul 28 19:27:01 2007 +0000

    reload OSS volume after unsuspend
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1553 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-oss.c b/src/modules/module-oss.c
index 4db1ed0..7ead678 100644
--- a/src/modules/module-oss.c
+++ b/src/modules/module-oss.c
@@ -559,6 +559,11 @@ static int unsuspend(struct userdata *u) {
 
     u->out_mmap_current = u->in_mmap_current = 0;
     u->out_mmap_saved_nfrags = u->in_mmap_saved_nfrags = 0;
+
+    if (u->sink)
+        pa_sink_get_volume(u->sink);
+    if (u->source)
+        pa_source_get_volume(u->source);
     
     /* Now, start only what we need */
     trigger(u, 0);

commit 10cb0483d943f37da0851a665f5a17fa2dc92522
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sat Jul 28 19:30:10 2007 +0000

    restore proper mixer volume control
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1554 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-alsa-sink.c b/src/modules/module-alsa-sink.c
index 4fc2f3a..1350090 100644
--- a/src/modules/module-alsa-sink.c
+++ b/src/modules/module-alsa-sink.c
@@ -82,9 +82,10 @@ struct userdata {
     
     snd_pcm_t *pcm_handle;
 
-/*     snd_mixer_t *mixer_handle; */
-/*     snd_mixer_elem_t *mixer_elem; */
-/* long hw_volume_max, hw_volume_min; */
+    pa_alsa_fdlist *mixer_fdl;
+    snd_mixer_t *mixer_handle;
+    snd_mixer_elem_t *mixer_elem;
+    long hw_volume_max, hw_volume_min;
 
     size_t frame_size, fragment_size, hwbuf_size;
     unsigned nfragments;
@@ -283,6 +284,9 @@ static int unsuspend(struct userdata *u) {
         goto fail;
     }
 
+    pa_sink_get_volume(u->sink);
+    pa_sink_get_mute(u->sink);
+
     u->first = 1;
                 
     pa_log_debug("Resumed successfully...");
@@ -328,160 +332,133 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, pa_memchunk *
             }
             
             break;
-
-/*         case PA_SINK_MESSAGE_SET_VOLUME: */
-
-/*             if (u->use_pcm_volume && u->fd >= 0) { */
-
-/*                 if (pa_oss_set_pcm_volume(u->fd, &u->sink->sample_spec, ((pa_cvolume*) data)) < 0) { */
-/*                     pa_log_info("Device doesn't support setting mixer settings: %s", pa_cstrerror(errno)); */
-/*                     u->use_pcm_volume = 0; */
-/*                 } else */
-/*                     return 0; */
-/*             } */
-
-/*             break; */
-
-/*         case PA_SINK_MESSAGE_GET_VOLUME: */
-
-/*             if (u->use_pcm_volume && u->fd >= 0) { */
-
-/*                 if (pa_oss_get_pcm_volume(u->fd, &u->sink->sample_spec, ((pa_cvolume*) data)) < 0) { */
-/*                     pa_log_info("Device doesn't support reading mixer settings: %s", pa_cstrerror(errno)); */
-/*                     u->use_pcm_volume = 0; */
-/*                 } else */
-/*                     return 0; */
-/*             } */
-
-/*             break; */
     }
 
     return pa_sink_process_msg(o, code, data, chunk);
 }
 
+static int mixer_callback(snd_mixer_elem_t *elem, unsigned int mask) {
+    struct userdata *u = snd_mixer_elem_get_callback_private(elem);
 
-/* 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);
 
-/*     pa_assert(u && u->mixer_handle); */
+    if (mask == SND_CTL_EVENT_MASK_REMOVE)
+        return 0;
 
-/*     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);
+    }
 
-/*     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); */
-/*     } */
+    return 0;
+}
 
-/*     return 0; */
-/* } */
+static int sink_get_volume_cb(pa_sink *s) {
+    struct userdata *u = s->userdata;
+    int err;
+    int i;
 
-/* static int sink_get_hw_volume_cb(pa_sink *s) { */
-/*     struct userdata *u = s->userdata; */
-/*     int err; */
-/*     int i; */
+    pa_assert(u);
+    pa_assert(u->mixer_elem);
 
-/*     pa_assert(u); */
-/*     pa_assert(u->mixer_elem); */
+    for (i = 0; i < s->sample_spec.channels; i++) {
+        long set_vol, vol;
 
-/*     for (i = 0; i < s->hw_volume.channels; i++) { */
-/*         long set_vol, vol; */
+        pa_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;
 
-/*         if ((err = snd_mixer_selem_get_playback_volume(u->mixer_elem, i, &vol)) < 0) */
-/*             goto fail; */
+        set_vol = (long) roundf(((float) s->volume.values[i] * (u->hw_volume_max - u->hw_volume_min)) / PA_VOLUME_NORM) + u->hw_volume_min;
 
-/*         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; */
+        /* Try to avoid superfluous volume changes */
+        if (set_vol != vol)
+            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));
+    }
 
-/*         /\* 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)); */
-/*     } */
+    return 0;
 
-/*     return 0; */
+fail:
+    pa_log_error("Unable to read volume: %s", snd_strerror(err));
+    
+    s->get_volume = NULL;
+    s->set_volume = NULL;
+    return -1;
+}
 
-/* fail: */
-/*     pa_log_error("Unable to read volume: %s", snd_strerror(err)); */
-/*     s->get_hw_volume = NULL; */
-/*     s->set_hw_volume = NULL; */
-/*     return -1; */
-/* } */
+static int sink_set_volume_cb(pa_sink *s) {
+    struct userdata *u = s->userdata;
+    int err;
+    int i;
 
-/* static int sink_set_hw_volume_cb(pa_sink *s) { */
-/*     struct userdata *u = s->userdata; */
-/*     int err; */
-/*     int i; */
-/*     pa_volume_t vol; */
+    pa_assert(u);
+    pa_assert(u->mixer_elem);
 
-/*     pa_assert(u); */
-/*     pa_assert(u->mixer_elem); */
+    for (i = 0; i < s->sample_spec.channels; i++) {
+        long alsa_vol;
+        pa_volume_t vol;
 
-/*     for (i = 0; i < s->hw_volume.channels; i++) { */
-/*         long alsa_vol; */
+        pa_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->volume.values[i];
 
-/*         vol = s->hw_volume.values[i]; */
+        if (vol > PA_VOLUME_NORM)
+            vol = PA_VOLUME_NORM;
 
-/*         if (vol > PA_VOLUME_NORM) */
-/*             vol = PA_VOLUME_NORM; */
+        alsa_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_playback_volume(u->mixer_elem, i, alsa_vol)) < 0)
+            goto fail;
+    }
 
-/*         if ((err = snd_mixer_selem_set_playback_volume(u->mixer_elem, i, alsa_vol)) < 0) */
-/*             goto fail; */
-/*     } */
+    return 0;
 
-/*     return 0; */
+fail:
+    pa_log_error("Unable to set volume: %s", snd_strerror(err));
+    
+    s->get_volume = NULL;
+    s->set_volume = NULL;
+    return -1;
+}
 
-/* fail: */
-/*     pa_log_error("Unable to set volume: %s", snd_strerror(err)); */
-/*     s->get_hw_volume = NULL; */
-/*     s->set_hw_volume = NULL; */
-/*     return -1; */
-/* } */
+static int sink_get_mute_cb(pa_sink *s) {
+    struct userdata *u = s->userdata;
+    int err, sw;
 
-/* static int sink_get_hw_mute_cb(pa_sink *s) { */
-/*     struct userdata *u = s->userdata; */
-/*     int err, sw; */
+    pa_assert(u);
+    pa_assert(u->mixer_elem);
 
-/*     pa_assert(u && u->mixer_elem); */
+    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));
 
-/*     err = snd_mixer_selem_get_playback_switch(u->mixer_elem, 0, &sw); */
-/*     if (err) { */
-/*         pa_log_error("Unable to get switch: %s", snd_strerror(err)); */
-/*         s->get_hw_mute = NULL; */
-/*         s->set_hw_mute = NULL; */
-/*         return -1; */
-/*     } */
+        s->get_mute = NULL;
+        s->set_mute = NULL;
+        return -1;
+    }
 
-/*     s->hw_muted = !sw; */
+    s->muted = !sw;
 
-/*     return 0; */
-/* } */
+    return 0;
+}
 
-/* static int sink_set_hw_mute_cb(pa_sink *s) { */
-/*     struct userdata *u = s->userdata; */
-/*     int err; */
+static int sink_set_mute_cb(pa_sink *s) {
+    struct userdata *u = s->userdata;
+    int err;
 
-/*     pa_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) { */
-/*         pa_log_error("Unable to set switch: %s", snd_strerror(err)); */
-/*         s->get_hw_mute = NULL; */
-/*         s->set_hw_mute = NULL; */
-/*         return -1; */
-/*     } */
+    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_mute = NULL;
+        s->set_mute = NULL;
+        return -1;
+    }
 
-/*     return 0; */
-/* } */
+    return 0;
+}
 
 static void thread_func(void *userdata) {
     enum {
@@ -776,6 +753,9 @@ int pa__init(pa_core *c, pa_module*m) {
         u->use_mmap = use_mmap = b;
     }
 
+    if (u->use_mmap)
+        pa_log_info("Successfully enabled mmap() mode.");
+
     /* ALSA might tweak the sample spec, so recalculate the frame size */
     frame_size = pa_frame_size(&ss);
 
@@ -783,16 +763,17 @@ 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_warn("Error opening mixer: %s", snd_strerror(err)); */
-/*     else { */
+    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, "PCM", "Master"))) {
+            
+            snd_mixer_close(u->mixer_handle);
+            u->mixer_handle = NULL;
+        }
+    }
 
     if ((name = pa_modargs_get_value(ma, "sink_name", NULL)))
         namereg_fail = 1;
@@ -821,41 +802,6 @@ int pa__init(pa_core *c, pa_module*m) {
     pa_xfree(t);
     
     u->sink->is_hardware = 1;
-    
-/*     if (u->mixer_handle) { */
-/*         pa_assert(u->mixer_elem); */
-/*         if (snd_mixer_selem_has_playback_volume(u->mixer_elem)) { */
-/*             int 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); */
-/*             } */
-/*         } */
-/*         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; */
-/*         } */
-/*     } */
-
-/*     if (u->mixer_handle) { */
-/*         u->mixer_fdl = pa_alsa_fdlist_new(); */
-/*         pa_assert(u->mixer_fdl); */
-/*         if (pa_alsa_fdlist_init_mixer(u->mixer_fdl, u->mixer_handle, c->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;
@@ -866,6 +812,44 @@ int pa__init(pa_core *c, pa_module*m) {
 
     pa_memchunk_reset(&u->memchunk);
 
+    if (u->mixer_handle) {
+        /* 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++) {
+                if (!snd_mixer_selem_has_playback_channel(u->mixer_elem, i))
+                    break;
+            }
+
+            if (i == 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);
+            }
+        }
+        if (snd_mixer_selem_has_playback_switch(u->mixer_elem)) {
+            u->sink->get_mute = sink_get_mute_cb;
+            u->sink->set_mute = sink_set_mute_cb;
+        }
+
+        u->mixer_fdl = pa_alsa_fdlist_new();
+        pa_assert(u->mixer_fdl);
+
+        if (pa_alsa_fdlist_set_mixer(u->mixer_fdl, u->mixer_handle, c->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;
+
+
     if (!(u->thread = pa_thread_new(thread_func, u))) {
         pa_log("Failed to create thread.");
         goto fail;
@@ -922,9 +906,12 @@ void pa__done(pa_core *c, pa_module*m) {
     
     if (u->memchunk.memblock)
         pa_memblock_unref(u->memchunk.memblock);
+
+    if (u->mixer_fdl)
+        pa_alsa_fdlist_free(u->mixer_fdl);
     
-/*     if (u->mixer_handle) */
-/*         snd_mixer_close(u->mixer_handle); */
+    if (u->mixer_handle)
+        snd_mixer_close(u->mixer_handle);
 
     if (u->pcm_handle) {
         snd_pcm_drop(u->pcm_handle);

commit 5fbb8e12d6d7a881100f53ea77f646b2bb32fc08
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sat Jul 28 20:58:33 2007 +0000

    add PA_SINK_OPENED/PA_SOURCE_OPENED macros for easier checking for _IDLE or _RUNNING states
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1555 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/sink.h b/src/pulsecore/sink.h
index dab9745..958279c 100644
--- a/src/pulsecore/sink.h
+++ b/src/pulsecore/sink.h
@@ -157,5 +157,9 @@ void pa_sink_render_into(pa_sink*s, pa_memchunk *target);
 void pa_sink_render_into_full(pa_sink *s, pa_memchunk *target);
 
 int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, pa_memchunk *chunk);
-    
+
+static inline int PA_SINK_OPENED(pa_sink_state_t x) {
+    return x == PA_SINK_RUNNING || x == PA_SINK_IDLE;
+}
+
 #endif
diff --git a/src/pulsecore/source.h b/src/pulsecore/source.h
index 4db2ded..e2b02ce 100644
--- a/src/pulsecore/source.h
+++ b/src/pulsecore/source.h
@@ -148,4 +148,8 @@ unsigned pa_source_used_by(pa_source *s);
 void pa_source_post(pa_source*s, const pa_memchunk *b);
 int pa_source_process_msg(pa_msgobject *o, int code, void *userdata, pa_memchunk *chunk);
 
+static inline int PA_SOURCE_OPENED(pa_source_state_t x) {
+    return x == PA_SOURCE_RUNNING || x == PA_SOURCE_IDLE;
+}
+
 #endif

commit 8aee345ccb8292fe2acf354dc9419eb2208eeef8
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sat Jul 28 21:00:16 2007 +0000

    Fix suspending/resuming
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1556 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-alsa-sink.c b/src/modules/module-alsa-sink.c
index 1350090..05fb90b 100644
--- a/src/modules/module-alsa-sink.c
+++ b/src/modules/module-alsa-sink.c
@@ -116,6 +116,7 @@ static int mmap_write(struct userdata *u) {
     int err;
     const snd_pcm_channel_area_t *areas;
     snd_pcm_uframes_t offset, frames;
+    int work_done = 0;
     
     pa_assert(u);
     pa_assert(u->sink);
@@ -134,8 +135,8 @@ static int mmap_write(struct userdata *u) {
             if ((err = snd_pcm_recover(u->pcm_handle, n, 1)) == 0)
                 continue;
 
-            if (err == EAGAIN)
-                return 0;
+            if (err == -EAGAIN)
+                return work_done;
             
             pa_log("snd_pcm_avail_update: %s", snd_strerror(n));
             return -1;
@@ -144,7 +145,7 @@ static int mmap_write(struct userdata *u) {
 /*         pa_log("Got request for %i samples", (int) n); */
         
         if (n <= 0)
-            return 0;
+            return work_done;
 
         frames = n;
         
@@ -158,8 +159,8 @@ static int mmap_write(struct userdata *u) {
             if ((err = snd_pcm_recover(u->pcm_handle, err, 1)) == 0)
                 continue;
 
-            if (err == EAGAIN)
-                return 0;
+            if (err == -EAGAIN)
+                return work_done;
 
             pa_log("Failed to write data to DSP: %s", snd_strerror(err));
             return -1;
@@ -195,13 +196,15 @@ static int mmap_write(struct userdata *u) {
             if ((err = snd_pcm_recover(u->pcm_handle, err, 1)) == 0)
                 continue;
             
-            if (err == EAGAIN)
-                return 0;
+            if (err == -EAGAIN)
+                return work_done;
             
             pa_log("Failed to write data to DSP: %s", snd_strerror(err));
             return -1;
         }
 
+        work_done = 1;
+
 /*         pa_log("wrote %i samples", (int) frames); */
     }
 }
@@ -279,7 +282,7 @@ static int unsuspend(struct userdata *u) {
         goto fail;
     }
 
-    if (!nfrags != u->nfragments || period_size*u->frame_size != u->fragment_size) {
+    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;
     }
@@ -318,17 +321,28 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, pa_memchunk *
 
         case PA_SINK_MESSAGE_SET_STATE:
 
-            if (PA_PTR_TO_UINT(data) == PA_SINK_SUSPENDED) {
-                pa_assert(u->sink->thread_info.state != PA_SINK_SUSPENDED);
-
-                if (suspend(u) < 0)
-                    return -1;
+            switch ((pa_sink_state_t) PA_PTR_TO_UINT(data)) {
                 
-            } else if (u->sink->thread_info.state == PA_SINK_SUSPENDED) {
-                pa_assert(PA_PTR_TO_UINT(data) != PA_SINK_SUSPENDED);
+                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_SUSPENDED) {
+                        if (unsuspend(u) < 0)
+                            return -1;
+                    }
+                    
+                    break;
 
-                if (unsuspend(u) < 0)
-                    return -1;
+                case PA_SINK_DISCONNECTED:
+                    ;
             }
             
             break;
@@ -499,7 +513,7 @@ static void thread_func(void *userdata) {
         pa_memchunk chunk;
         int r;
 
-/*          pa_log("loop");    */
+/*         pa_log("loop");     */
         
         /* Check whether there is a message for us to process */
         if (pa_asyncmsgq_get(u->asyncmsgq, &object, &code, &data, &chunk, 0) == 0) {
@@ -521,19 +535,15 @@ static void thread_func(void *userdata) {
 
         /* Render some data and write it to the dsp */
 
-        if (u->sink->thread_info.state != PA_SINK_SUSPENDED && ((revents & POLLOUT) || u->first == 1)) {
+        if (PA_SINK_OPENED(u->sink->thread_info.state) && ((revents & POLLOUT) || u->first == 1)) {
+            int work_done = 0;
+            pa_assert(u->pcm_handle);
 
             if (u->use_mmap) {
-                int ret;
 
-                if ((ret = mmap_write(u)) < 0)
+                if ((work_done = mmap_write(u)) < 0)
                     goto fail;
 
-                revents &= ~POLLOUT;
-                
-                if (ret > 0)
-                    continue;
-
             } else {
                 ssize_t l;
 
@@ -542,11 +552,11 @@ static void thread_func(void *userdata) {
                     l = snd_pcm_status_get_avail(status) * u->frame_size;
                 else
                     l = u->fragment_size;
-                
-                do {
+
+                while (l > 0) {
                     void *p;
                     snd_pcm_sframes_t t;
-                    
+
                     pa_assert(l > 0);
                     
                     if (u->memchunk.length <= 0)
@@ -558,7 +568,7 @@ static void thread_func(void *userdata) {
                     t = snd_pcm_writei(u->pcm_handle, (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", t, l); */
+/*                     pa_log("wrote %i bytes of %u (%u)", t*u->frame_size, u->memchunk.length, l);   */
                     
                     pa_assert(t != 0);
                     
@@ -572,12 +582,9 @@ static void thread_func(void *userdata) {
                         if ((t = snd_pcm_recover(u->pcm_handle, t, 1)) == 0)
                             continue;
                         
-                        if (t == EAGAIN) {
-                            pa_log_debug("EAGAIN"); 
-                            
-                            revents &= ~POLLOUT;
+                        if (t == -EAGAIN) {
+                            pa_log_debug("EAGAIN");
                             break;
-                            
                         } else {
                             pa_log("Failed to write data to DSP: %s", snd_strerror(t));
                             goto fail;
@@ -594,24 +601,23 @@ static void thread_func(void *userdata) {
                         }
                         
                         l -= t * u->frame_size;
-                        
-                        revents &= ~POLLOUT;
+
+                        work_done = 1;
                     }
-                    
-                } while (l > 0);
-                
-                continue;
+                } 
             }
 
-            if (u->first) {
-                pa_log_info("Starting playback.");
-                
-                if ((err = snd_pcm_start(u->pcm_handle)) < 0) {
-                    pa_log("Failed to start PCM playback: %s", snd_strerror(err));
-                    goto fail;
-                }
+            revents &= ~POLLOUT;
+            
+            if (work_done) {
 
-                u->first = 0;
+                if (u->first) {
+                    pa_log_info("Starting playback.");
+                    snd_pcm_start(u->pcm_handle);
+                    u->first = 0;
+                }
+            
+                continue;
             }
         }
 
@@ -619,8 +625,8 @@ static void thread_func(void *userdata) {
         if (pa_asyncmsgq_before_poll(u->asyncmsgq) < 0)
             continue;
 
-/*         pa_log("polling for %i", POLLFD_ALSA_BASE + (u->sink->thread_info.state != PA_SINK_SUSPENDED ? n_alsa_fds : 0));  */
-        r = poll(pollfd, POLLFD_ALSA_BASE + (u->sink->thread_info.state != PA_SINK_SUSPENDED ? n_alsa_fds : 0), -1);
+/*         pa_log("polling for %i", POLLFD_ALSA_BASE + (PA_SINK_OPENED(u->sink->thread_info.state) ? n_alsa_fds : 0));   */
+        r = poll(pollfd, POLLFD_ALSA_BASE + (PA_SINK_OPENED(u->sink->thread_info.state) ? n_alsa_fds : 0), -1);
         /*pa_log("polling got dsp=%i amq=%i (%i)", r > 0 ? pollfd[POLLFD_DSP].revents : 0, r > 0 ? pollfd[POLLFD_ASYNCQ].revents : 0, r); */
 /*         pa_log("poll end"); */
 
@@ -639,7 +645,7 @@ static void thread_func(void *userdata) {
 
         pa_assert(r > 0);
 
-        if (u->sink->thread_info.state != PA_SINK_SUSPENDED) {
+        if (PA_SINK_OPENED(u->sink->thread_info.state)) {
             if ((err = snd_pcm_poll_descriptors_revents(u->pcm_handle, pollfd + POLLFD_ALSA_BASE, n_alsa_fds, &revents)) < 0) {
                 pa_log("snd_pcm_poll_descriptors_revents() failed: %s", snd_strerror(err));
                 goto fail;

commit 16154507675ba7fa37f5478ecd6717d9c616439d
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sat Jul 28 22:55:12 2007 +0000

    It is now allowed to call pa_sink_get_volume() from thread context
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1557 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-alsa-sink.c b/src/modules/module-alsa-sink.c
index 05fb90b..cf56d8c 100644
--- a/src/modules/module-alsa-sink.c
+++ b/src/modules/module-alsa-sink.c
@@ -287,9 +287,8 @@ static int unsuspend(struct userdata *u) {
         goto fail;
     }
 
-    pa_sink_get_volume(u->sink);
-    pa_sink_get_mute(u->sink);
-
+    /* FIXME: We need to reload the volume somehow */
+    
     u->first = 1;
                 
     pa_log_debug("Resumed successfully...");

commit 81aa8ea37c8cc974246d580d25a604a6e309e472
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sat Jul 28 22:55:44 2007 +0000

    drop data from inputs only when in running state
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1558 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c
index 015cf4d..7f2a8b3 100644
--- a/src/pulsecore/sink.c
+++ b/src/pulsecore/sink.c
@@ -408,7 +408,8 @@ void pa_sink_render(pa_sink*s, size_t length, pa_memchunk *result) {
         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)
         pa_source_post(s->monitor_source, result);
@@ -472,7 +473,8 @@ void pa_sink_render_into(pa_sink*s, pa_memchunk *target) {
         pa_memblock_release(target->memblock);
     }
 
-    inputs_drop(s, info, n, target->length);
+    if (s->thread_info.state == PA_SINK_RUNNING)
+        inputs_drop(s, info, n, target->length);
 
     if (s->monitor_source)
         pa_source_post(s->monitor_source, target);

commit 6afbbba1025d04ee5ebeadba563c138e1d7b2aed
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sat Jul 28 22:56:39 2007 +0000

    fix suspending logic
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1559 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-oss.c b/src/modules/module-oss.c
index 7ead678..63f4d40 100644
--- a/src/modules/module-oss.c
+++ b/src/modules/module-oss.c
@@ -158,18 +158,20 @@ static const char* const valid_modargs[] = {
 static void trigger(struct userdata *u, int quick) {
     int enable_bits = 0, zero = 0;
 
-/*     pa_log_debug("trigger"); */
+    if (u->fd < 0)
+        return;
+
+    pa_log_debug("trigger"); 
 
-    if (u->source && u->source->thread_info.state != PA_SOURCE_SUSPENDED)
+    if (u->source && PA_SOURCE_OPENED(u->source->thread_info.state))
         enable_bits |= PCM_ENABLE_INPUT;
     
-    if (u->sink && u->sink->thread_info.state != PA_SINK_SUSPENDED)
+    if (u->sink && PA_SINK_OPENED(u->sink->thread_info.state))
         enable_bits |= PCM_ENABLE_OUTPUT;
     
     if (u->use_mmap) {
 
         if (!quick)
-            /* First, let's stop all playback, capturing */
             ioctl(u->fd, SNDCTL_DSP_SETTRIGGER, &zero);
 
 #ifdef SNDCTL_DSP_HALT
@@ -199,7 +201,7 @@ static void trigger(struct userdata *u, int quick) {
              * register the fd as ready.
              */
             
-            if (u->source && u->source->thread_info.state != PA_SOURCE_SUSPENDED) {
+            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);
@@ -212,6 +214,8 @@ static void mmap_fill_memblocks(struct userdata *u, unsigned n) {
     pa_assert(u);
     pa_assert(u->out_mmap_memblocks);
 
+/*     pa_log("Mmmap writing %u blocks", n); */
+    
     while (n > 0) {
         pa_memchunk chunk;
 
@@ -241,10 +245,11 @@ static void mmap_fill_memblocks(struct userdata *u, unsigned 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;
@@ -263,6 +268,8 @@ static void mmap_post_memblocks(struct userdata *u, unsigned n) {
     pa_assert(u);
     pa_assert(u->in_mmap_memblocks);
 
+/*     pa_log("Mmmap reading %u blocks", n); */
+
     while (n > 0) {
         pa_memchunk chunk;
 
@@ -317,6 +324,8 @@ static int mmap_read(struct userdata *u) {
     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;
@@ -437,6 +446,8 @@ static int suspend(struct userdata *u) {
     pa_assert(u);
     pa_assert(u->fd >= 0);
 
+    pa_log_debug("Suspending...");
+    
     if (u->out_mmap_memblocks) {
         unsigned i;
         for (i = 0; i < u->out_nfrags; i++)
@@ -559,15 +570,7 @@ static int unsuspend(struct userdata *u) {
 
     u->out_mmap_current = u->in_mmap_current = 0;
     u->out_mmap_saved_nfrags = u->in_mmap_saved_nfrags = 0;
-
-    if (u->sink)
-        pa_sink_get_volume(u->sink);
-    if (u->source)
-        pa_source_get_volume(u->source);
     
-    /* Now, start only what we need */
-    trigger(u, 0);
-
     pa_log_debug("Resumed successfully...");
 
     return 0;
@@ -580,7 +583,7 @@ fail:
 
 static int sink_process_msg(pa_msgobject *o, int code, void *data, pa_memchunk *chunk) {
     struct userdata *u = PA_SINK(o)->userdata;
-    int do_trigger = 0, ret;
+    int do_trigger = 0, ret, quick = 1;
 
     switch (code) {
 
@@ -601,30 +604,44 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, pa_memchunk *
 
         case PA_SINK_MESSAGE_SET_STATE:
 
-            if (PA_PTR_TO_UINT(data) == PA_SINK_SUSPENDED) {
-                pa_assert(u->sink->thread_info.state != PA_SINK_SUSPENDED);
+            switch ((pa_sink_state_t) PA_PTR_TO_UINT(data)) {
 
-                if (u->source_suspended) {
-                    if (suspend(u) < 0)
-                        return -1;
-                } else
-                    do_trigger = 1;
+                case PA_SINK_SUSPENDED:
+                    pa_assert(PA_SINK_OPENED(u->sink->thread_info.state));
 
-                u->sink_suspended = 1;
-                
-            } else if (u->sink->thread_info.state == PA_SINK_SUSPENDED) {
-                pa_assert(PA_PTR_TO_UINT(data) != PA_SINK_SUSPENDED);
+                    if (!u->source || u->source_suspended) {
+                        if (suspend(u) < 0)
+                            return -1;
+                    } 
 
-                if (u->source_suspended) {
-                    if (unsuspend(u) < 0) 
-                        return -1;
-                } else
                     do_trigger = 1;
 
-                u->out_mmap_current = 0;
-                u->out_mmap_saved_nfrags = 0;
+                    u->sink_suspended = 1;
+                    break;
+                    
+                case PA_SINK_IDLE:
+                case PA_SINK_RUNNING:
+                    
+                    if (u->sink->thread_info.state == PA_SINK_SUSPENDED) {
+                        
+                        if (!u->source || u->source_suspended) {
+                            if (unsuspend(u) < 0) 
+                                return -1;
+                            quick = 0;
+                        }
+
+                        do_trigger = 1;
+                        
+                        u->out_mmap_current = 0;
+                        u->out_mmap_saved_nfrags = 0;
+                        
+                        u->sink_suspended = 0;
+                    }
+
+                    break;
 
-                u->sink_suspended = 0;
+                case PA_SINK_DISCONNECTED:
+                    ;
             }
             
             break;
@@ -659,14 +676,14 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, pa_memchunk *
     ret = pa_sink_process_msg(o, code, data, chunk);
 
     if (do_trigger)
-        trigger(u, 1);
+        trigger(u, quick);
     
     return ret;
 }
 
 static int source_process_msg(pa_msgobject *o, int code, void *data, pa_memchunk *chunk) {
     struct userdata *u = PA_SOURCE(o)->userdata;
-    int do_trigger = 0, ret;
+    int do_trigger = 0, ret, quick = 1;
 
     switch (code) {
 
@@ -686,32 +703,44 @@ static int source_process_msg(pa_msgobject *o, int code, void *data, pa_memchunk
 
         case PA_SOURCE_MESSAGE_SET_STATE:
 
-            if (PA_PTR_TO_UINT(data) == PA_SOURCE_SUSPENDED) {
-                pa_assert(u->source->thread_info.state != PA_SOURCE_SUSPENDED);
+            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;
+                    } 
 
-                if (u->sink_suspended) {
-                    if (suspend(u) < 0) 
-                        return -1;
-                } else
                     do_trigger = 1;
+                    
+                    u->source_suspended = 1;
+                    break;
 
-                u->source_suspended = 1;
+                case PA_SOURCE_IDLE:
+                case PA_SOURCE_RUNNING:
+                    
+                    if (u->source->thread_info.state == PA_SOURCE_SUSPENDED) {
 
-            } else if (u->source->thread_info.state == PA_SOURCE_SUSPENDED) {
-                pa_assert(PA_PTR_TO_UINT(data) != PA_SOURCE_SUSPENDED);
+                        if (!u->sink || u->sink_suspended) {
+                            if (unsuspend(u) < 0) 
+                                return -1;
+                            quick = 0;
+                        } 
 
-                if (u->sink_suspended) {
-                    if (unsuspend(u) < 0) 
-                        return -1;
-                } else
-                    do_trigger = 1;
-                
-                u->in_mmap_current = 0;
-                u->in_mmap_saved_nfrags = 0;
+                        do_trigger = 1;
+                        
+                        u->in_mmap_current = 0;
+                        u->in_mmap_saved_nfrags = 0;
+                        
+                        u->source_suspended = 0;
+                    }
+                    break;
 
-                u->source_suspended = 0;
-            }
+                case PA_SOURCE_DISCONNECTED:
+                    ;
 
+            }
             break;
 
         case PA_SOURCE_MESSAGE_SET_VOLUME:
@@ -744,7 +773,7 @@ static int source_process_msg(pa_msgobject *o, int code, void *data, pa_memchunk
     ret = pa_source_process_msg(o, code, data, chunk);
 
     if (do_trigger)
-        trigger(u, 1);
+        trigger(u, quick);
 
     return ret;
 }
@@ -779,7 +808,7 @@ static void thread_func(void *userdata) {
         pa_memchunk chunk;
         int r;
 
-/*         pa_log("loop");   */
+/*        pa_log("loop");    */
         
         /* Check whether there is a message for us to process */
         if (pa_asyncmsgq_get(u->asyncmsgq, &object, &code, &data, &chunk, 0) == 0) {
@@ -801,7 +830,7 @@ static void thread_func(void *userdata) {
 
         /* Render some data and write it to the dsp */
 
-        if (u->sink && u->sink->thread_info.state != PA_SINK_SUSPENDED && (pollfd[POLLFD_DSP].revents & POLLOUT)) {
+        if (u->sink && u->sink->thread_info.state != PA_SINK_DISCONNECTED && u->fd >= 0 && (pollfd[POLLFD_DSP].revents & POLLOUT)) {
 
             if (u->use_mmap) {
                 int ret;
@@ -892,7 +921,7 @@ static void thread_func(void *userdata) {
 
         /* Try to read some data and pass it on to the source driver */
 
-        if (u->source && u->source->thread_info.state != PA_SOURCE_SUSPENDED && ((pollfd[POLLFD_DSP].revents & POLLIN))) {
+        if (u->source && u->source->thread_info.state != PA_SOURCE_DISCONNECTED && u->fd >= 0 && ((pollfd[POLLFD_DSP].revents & POLLIN))) {
 
             if (u->use_mmap) {
                 int ret;
@@ -980,8 +1009,8 @@ static void thread_func(void *userdata) {
         if (u->fd >= 0) {
             pollfd[POLLFD_DSP].fd = u->fd;
             pollfd[POLLFD_DSP].events =
-                ((u->source && u->source->thread_info.state != PA_SOURCE_SUSPENDED) ? POLLIN : 0) |
-                ((u->sink && u->sink->thread_info.state != PA_SINK_SUSPENDED) ? POLLOUT : 0);
+                ((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 */

commit 13a4327c1f36239a08892f8c24cc7f60befcad02
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sat Jul 28 23:49:39 2007 +0000

    minor cleanups
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1560 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-alsa-sink.c b/src/modules/module-alsa-sink.c
index cf56d8c..9ca881d 100644
--- a/src/modules/module-alsa-sink.c
+++ b/src/modules/module-alsa-sink.c
@@ -564,7 +564,7 @@ static void thread_func(void *userdata) {
                     pa_assert(u->memchunk.length > 0);
                     
                     p = pa_memblock_acquire(u->memchunk.memblock);
-                    t = snd_pcm_writei(u->pcm_handle, (uint8_t*) p + u->memchunk.index, u->memchunk.length / u->frame_size);
+                    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);   */
@@ -654,11 +654,6 @@ static void thread_func(void *userdata) {
         } else
             revents = 0;
         
-        if (revents & ~(POLLOUT|POLLERR)) {
-            pa_log("DSP shutdown.");
-            goto fail;
-        }
-
         pa_assert((pollfd[POLLFD_ASYNCQ].revents & ~POLLIN) == 0);
     }
 
@@ -697,13 +692,13 @@ int pa__init(pa_core *c, pa_module*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;
     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;
     }
 
@@ -715,7 +710,7 @@ int pa__init(pa_core *c, pa_module*m) {
         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");
+        pa_log("Failed to parse buffer metrics");
         goto fail;
     }
     period_size = frag_size/frame_size;
@@ -809,7 +804,7 @@ int pa__init(pa_core *c, pa_module*m) {
     u->sink->is_hardware = 1;
 
     u->frame_size = frame_size;
-    u->fragment_size = period_size * frame_size;
+    u->fragment_size = frag_size = period_size * frame_size;
     u->nfragments = nfrags;
     u->hwbuf_size = u->fragment_size * nfrags;
 
@@ -836,13 +831,13 @@ int pa__init(pa_core *c, pa_module*m) {
                 snd_mixer_selem_get_playback_volume_range(u->mixer_elem, &u->hw_volume_min, &u->hw_volume_max);
             }
         }
+        
         if (snd_mixer_selem_has_playback_switch(u->mixer_elem)) {
             u->sink->get_mute = sink_get_mute_cb;
             u->sink->set_mute = sink_set_mute_cb;
         }
 
         u->mixer_fdl = pa_alsa_fdlist_new();
-        pa_assert(u->mixer_fdl);
 
         if (pa_alsa_fdlist_set_mixer(u->mixer_fdl, u->mixer_handle, c->mainloop) < 0) {
             pa_log("failed to initialise file descriptor monitoring");
@@ -854,7 +849,6 @@ int pa__init(pa_core *c, pa_module*m) {
     } else
         u->mixer_fdl = NULL;
 
-
     if (!(u->thread = pa_thread_new(thread_func, u))) {
         pa_log("Failed to create thread.");
         goto fail;
@@ -872,9 +866,9 @@ finish:
 
      if (ma)
          pa_modargs_free(ma);
-
-    if (pcm_info)
-        snd_pcm_info_free(pcm_info);
+     
+     if (pcm_info)
+         snd_pcm_info_free(pcm_info);
 
     return ret;
 
@@ -924,9 +918,8 @@ void pa__done(pa_core *c, pa_module*m) {
     }
     
     pa_xfree(u->device_name);
-
-    snd_config_update_free_global();
-    
     pa_xfree(u);
+    
+    snd_config_update_free_global();
 }
 

commit a82505e72f6680258b8162b846c98c64bea45c37
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sat Jul 28 23:50:20 2007 +0000

    port module-alsa-source to new lock-free core
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1561 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/Makefile.am b/src/Makefile.am
index ec1bbd0..1afe6d6 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -937,8 +937,8 @@ endif
 if HAVE_ALSA
 modlibexec_LTLIBRARIES += \
 		libalsa-util.la \
-		module-alsa-sink.la
-#		module-alsa-source.la
+		module-alsa-sink.la \
+		module-alsa-source.la
 endif
 
 if HAVE_SOLARIS
@@ -1195,10 +1195,10 @@ module_alsa_sink_la_LDFLAGS = -module -avoid-version
 module_alsa_sink_la_LIBADD = $(AM_LIBADD) $(ASOUNDLIB_LIBS) libalsa-util.la libpulsecore.la
 module_alsa_sink_la_CFLAGS = $(AM_CFLAGS) $(ASOUNDLIB_CFLAGS)
 
-#module_alsa_source_la_SOURCES = modules/module-alsa-source.c
-#module_alsa_source_la_LDFLAGS = -module -avoid-version
-#module_alsa_source_la_LIBADD = $(AM_LIBADD) $(ASOUNDLIB_LIBS) libalsa-util.la libpulsecore.la
-#module_alsa_source_la_CFLAGS = $(AM_CFLAGS) $(ASOUNDLIB_CFLAGS)
+module_alsa_source_la_SOURCES = modules/module-alsa-source.c
+module_alsa_source_la_LDFLAGS = -module -avoid-version
+module_alsa_source_la_LIBADD = $(AM_LIBADD) $(ASOUNDLIB_LIBS) libalsa-util.la libpulsecore.la
+module_alsa_source_la_CFLAGS = $(AM_CFLAGS) $(ASOUNDLIB_CFLAGS)
 
 # Solaris
 
diff --git a/src/modules/module-alsa-source.c b/src/modules/module-alsa-source.c
index 6d7e09e..59414d3 100644
--- a/src/modules/module-alsa-source.c
+++ b/src/modules/module-alsa-source.c
@@ -48,6 +48,9 @@
 #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 "alsa-util.h"
 #include "module-alsa-source-symdef.h"
@@ -63,20 +66,33 @@ 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"
+#define DEFAULT_NFRAGS 4
+#define DEFAULT_FRAGSIZE_MSEC 25
 
 struct userdata {
+    pa_core *core;
+    pa_module *module;
+    pa_source *source;
+    pa_thread *thread;
+    pa_asyncmsgq *asyncmsgq;
+
     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;
 };
 
 static const char* const valid_modargs[] = {
@@ -88,261 +104,312 @@ static const char* const valid_modargs[] = {
     "fragments",
     "fragment_size",
     "channel_map",
+    "mmap",
     NULL
 };
 
-#define DEFAULT_DEVICE "default"
+static int mmap_read(struct userdata *u) {
+    snd_pcm_sframes_t n;
+    int err;
+    const snd_pcm_channel_area_t *areas;
+    snd_pcm_uframes_t offset, frames;
+    int work_done = 0;
+    
+    pa_assert(u);
+    pa_assert(u->source);
 
-static void update_usage(struct userdata *u) {
-   pa_module_set_used(u->module, u->source ? pa_source_used_by(u->source) : 0);
-}
+    for (;;) {
+        pa_memchunk chunk;
+        void *p;
+        
+        if ((n = snd_pcm_avail_update(u->pcm_handle)) < 0) {
 
-static void clear_up(struct userdata *u) {
-    assert(u);
+            if (n == -EPIPE)
+                pa_log_debug("snd_pcm_avail_update: Buffer underrun!");
+            
+            if ((err = snd_pcm_recover(u->pcm_handle, n, 1)) == 0)
+                continue;
 
-    if (u->source) {
-        pa_source_disconnect(u->source);
-        pa_source_unref(u->source);
-        u->source = NULL;
-    }
+            if (err == -EAGAIN)
+                return work_done;
+            
+            pa_log("snd_pcm_avail_update: %s", snd_strerror(n));
+            return -1;
+        }
 
-    if (u->pcm_fdl)
-        pa_alsa_fdlist_free(u->pcm_fdl);
-    if (u->mixer_fdl)
-        pa_alsa_fdlist_free(u->mixer_fdl);
+/*         pa_log("Got request for %i samples", (int) n); */
+        
+        if (n <= 0)
+            return work_done;
 
-    u->pcm_fdl = u->mixer_fdl = NULL;
+        frames = n;
+        
+        if ((err = snd_pcm_mmap_begin(u->pcm_handle, &areas, &offset, &frames)) < 0) {
+            
+            if (err == -EPIPE)
+                pa_log_debug("snd_pcm_mmap_begin: Buffer underrun!");
 
-    if (u->mixer_handle) {
-        snd_mixer_close(u->mixer_handle);
-        u->mixer_handle = NULL;
-    }
+            if ((err = snd_pcm_recover(u->pcm_handle, err, 1)) == 0)
+                continue;
 
-    if (u->pcm_handle) {
-        snd_pcm_drop(u->pcm_handle);
-        snd_pcm_close(u->pcm_handle);
-        u->pcm_handle = NULL;
-    }
-}
+            if (err == -EAGAIN)
+                return work_done;
 
-static int xrun_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-XRUN (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_prepare(u->pcm_handle)) < 0) {
-        pa_log("snd_pcm_prepare() failed: %s", snd_strerror(-ret));
+        /* We assume a single interleaved memory buffer */
+        pa_assert((areas[0].first >> 3) == 0);
+        pa_assert((areas[0].step >> 3) == u->frame_size);
 
-        clear_up(u);
-        pa_module_unload_request(u->module);
+        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;
 
-        return -1;
-    }
+        pa_source_post(u->source, &chunk);
 
-    return 0;
-}
+        /* 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) {
 
-static int suspend_recovery(struct userdata *u) {
-    int ret;
-    assert(u);
+            if (err == -EPIPE)
+                pa_log_debug("snd_pcm_mmap_commit: Buffer underrun!");
+            
+            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;
+        }
 
-    pa_log_info("*** ALSA-SUSPEND (capture) ***");
+        work_done = 1;
 
-    if ((ret = snd_pcm_resume(u->pcm_handle)) < 0) {
-        if (ret == -EAGAIN)
-            return -1;
+/*         pa_log("wrote %i samples", (int) frames); */
+    }
+}
 
-        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));
-        }
+static pa_usec_t source_get_latency(struct userdata *u) {
+    pa_usec_t r = 0;
+    snd_pcm_sframes_t frames = 0;
+    int err;
+    
+    pa_assert(u);
 
-        if (ret < 0) {
-            clear_up(u);
-            pa_module_unload_request(u->module);
-            return -1;
-        }
+    snd_pcm_avail_update(u->pcm_handle);
+
+    if ((err = snd_pcm_delay(u->pcm_handle, &frames)) < 0) {
+        pa_log("Failed to get delay: %s", snd_strerror(err));
+        return 0;
     }
 
-    return ret;
+    if (frames > 0)
+        r = pa_bytes_to_usec(frames * u->frame_size, &u->source->sample_spec);
+
+    return r;
 }
 
-static void do_read(struct userdata *u) {
-    assert(u);
+static int suspend(struct userdata *u) {
+    pa_assert(u);
+    pa_assert(u->pcm_handle);
 
-    update_usage(u);
+    /* Let's suspend */
+    snd_pcm_close(u->pcm_handle);
+    u->pcm_handle = NULL;
 
-    for (;;) {
-        pa_memchunk post_memchunk;
-        snd_pcm_sframes_t frames;
-        size_t l;
-        void *p;
+    pa_log_debug("Device suspended...");
+    
+    return 0;
+}
 
-        if (!u->memchunk.memblock) {
-            u->memchunk.memblock = pa_memblock_new(u->source->core->mempool, u->memchunk.length = u->fragment_size);
-            u->memchunk.index = 0;
-        }
+static int unsuspend(struct userdata *u) {
+    pa_sample_spec ss;
+    int err, b;
+    unsigned nfrags;
+    snd_pcm_uframes_t period_size;
 
-        assert(u->memchunk.memblock);
-        assert(u->memchunk.length);
-        assert(u->memchunk.length % u->frame_size == 0);
+    pa_assert(u);
+    pa_assert(!u->pcm_handle);
 
-        p = pa_memblock_acquire(u->memchunk.memblock);
+    pa_log_debug("Trying resume...");
 
-        if ((frames = snd_pcm_readi(u->pcm_handle, (uint8_t*) p + u->memchunk.index, u->memchunk.length / u->frame_size)) < 0) {
-            pa_memblock_release(u->memchunk.memblock);
+    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;
+    }
 
-            if (frames == -EAGAIN)
-                return;
+    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 (frames == -EPIPE) {
-                if (xrun_recovery(u) < 0)
-                    return;
+    if (b != u->use_mmap) {
+        pa_log_warn("Resume failed, couldn't get original access mode.");
+        goto fail;
+    }
 
-                continue;
-            }
+    if (!pa_sample_spec_equal(&ss, &u->source->sample_spec)) {
+        pa_log_warn("Resume failed, couldn't restore original sample settings.");
+        goto fail;
+    }
 
-            if (frames == -ESTRPIPE) {
-                if (suspend_recovery(u) < 0)
-                    return;
+    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;
+    }
 
-                continue;
-            }
+    snd_pcm_start(u->pcm_handle);
+    
+    /* FIXME: We need to reload the volume somehow */
+                
+    pa_log_debug("Resumed successfully...");
 
-            pa_log("snd_pcm_readi() failed: %s", snd_strerror(-frames));
+    return 0;
 
-            clear_up(u);
-            pa_module_unload_request(u->module);
-            return;
-        }
-        pa_memblock_release(u->memchunk.memblock);
+fail:
+    snd_pcm_close(u->pcm_handle);
+    u->pcm_handle = NULL;
+
+    return -1;
+}
+
+static int source_process_msg(pa_msgobject *o, int code, void *data, pa_memchunk *chunk) {
+    struct userdata *u = PA_SOURCE(o)->userdata;
 
-        l = frames * u->frame_size;
+    switch (code) {
 
-        post_memchunk = u->memchunk;
-        post_memchunk.length = l;
+        case PA_SOURCE_MESSAGE_GET_LATENCY: {
+            pa_usec_t r = 0;
 
-        pa_source_post(u->source, &post_memchunk);
+            if (u->pcm_handle)
+                r = source_get_latency(u);
 
-        u->memchunk.index += l;
-        u->memchunk.length -= l;
+            *((pa_usec_t*) data) = r;
 
-        if (u->memchunk.length == 0) {
-            pa_memblock_unref(u->memchunk.memblock);
-            u->memchunk.memblock = NULL;
-            u->memchunk.index = u->memchunk.length = 0;
+            break;
         }
 
-        break;
-    }
-}
+        case PA_SOURCE_MESSAGE_SET_STATE:
 
-static void fdl_callback(void *userdata) {
-    struct userdata *u = userdata;
-    assert(u);
+            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 (snd_pcm_state(u->pcm_handle) == SND_PCM_STATE_XRUN)
-        if (xrun_recovery(u) < 0)
-            return;
+                    if (suspend(u) < 0)
+                        return -1;
+                    
+                    break;
+
+                case PA_SOURCE_IDLE:
+                case PA_SOURCE_RUNNING:
 
-    if (snd_pcm_state(u->pcm_handle) == SND_PCM_STATE_SUSPENDED)
-        if (suspend_recovery(u) < 0)
-            return;
+                    if (u->source->thread_info.state == PA_SOURCE_SUSPENDED) {
+                        if (unsuspend(u) < 0)
+                            return -1;
+                    }
+                    
+                    break;
 
-    do_read(u);
+                case PA_SOURCE_DISCONNECTED:
+                    ;
+            }
+            
+            break;
+    }
+
+    return pa_source_process_msg(o, code, data, chunk);
 }
 
 static int mixer_callback(snd_mixer_elem_t *elem, unsigned int mask) {
     struct userdata *u = snd_mixer_elem_get_callback_private(elem);
 
-    assert(u && u->mixer_handle);
+    pa_assert(u);
+    pa_assert(u->mixer_handle);
 
     if (mask == SND_CTL_EVENT_MASK_REMOVE)
         return 0;
 
     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);
-
-        pa_subscription_post(u->source->core,
-            PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE,
-            u->source->index);
+        pa_source_get_volume(u->source);
+        pa_source_get_mute(u->source);
     }
 
     return 0;
 }
 
-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);
-
-    if (snd_pcm_delay(u->pcm_handle, &frames) < 0) {
-        pa_log("failed to get delay");
-        s->get_latency = NULL;
-        return 0;
-    }
-
-    return pa_bytes_to_usec(frames * u->frame_size, &s->sample_spec);
-}
-
-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->sample_spec.channels; i++) {
+        long alsa_vol;
+        pa_volume_t vol;
 
-    for (i = 0;i < s->hw_volume.channels;i++) {
-        assert(snd_mixer_selem_has_capture_channel(u->mixer_elem, i));
+        pa_assert(snd_mixer_selem_has_capture_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;
 
-        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;
     }
 
@@ -350,55 +417,242 @@ 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;
 }
 
+static void thread_func(void *userdata) {
+    enum {
+        POLLFD_ASYNCQ,
+        POLLFD_ALSA_BASE
+    };
+
+    struct userdata *u = userdata;
+    struct pollfd *pollfd = NULL;
+    int n_alsa_fds, err;
+    unsigned short revents = 0;
+    snd_pcm_status_t *status;
+
+    pa_assert(u);
+    snd_pcm_status_alloca(&status);
+
+    pa_log_debug("Thread starting up");
+
+    if ((n_alsa_fds = snd_pcm_poll_descriptors_count(u->pcm_handle)) < 0) {
+        pa_log("snd_pcm_poll_descriptors_count() failed: %s", snd_strerror(n_alsa_fds));
+        goto fail;
+    }
+
+    pollfd = pa_xnew0(struct pollfd, POLLFD_ALSA_BASE + n_alsa_fds);
+
+    pollfd[POLLFD_ASYNCQ].fd = pa_asyncmsgq_get_fd(u->asyncmsgq);
+    pollfd[POLLFD_ASYNCQ].events = POLLIN;
+
+    if ((err = snd_pcm_poll_descriptors(u->pcm_handle, pollfd+POLLFD_ALSA_BASE, n_alsa_fds)) < 0) {
+        pa_log("snd_pcm_poll_descriptors() failed: %s", snd_strerror(err));
+        goto fail;
+    }
+
+    for (;;) {
+        pa_msgobject *object;
+        int code;
+        void *data;
+        int r;
+        pa_memchunk chunk;
+
+/*         pa_log("loop");     */
+        
+        /* Check whether there is a message for us to process */
+        if (pa_asyncmsgq_get(u->asyncmsgq, &object, &code, &data, &chunk, 0) == 0) {
+            int ret;
+
+/*             pa_log("processing msg"); */
+
+            if (!object && code == PA_MESSAGE_SHUTDOWN) {
+                pa_asyncmsgq_done(u->asyncmsgq, 0);
+                goto finish;
+            }
+
+            ret = pa_asyncmsgq_dispatch(object, code, data, &chunk);
+            pa_asyncmsgq_done(u->asyncmsgq, ret);
+            continue;
+        } 
+
+/*         pa_log("loop2"); */
+
+        /* Render some data and write it to the dsp */
+
+        if (PA_SOURCE_OPENED(u->source->thread_info.state) && (revents & POLLIN)) {
+            int work_done = 0;
+            pa_assert(u->pcm_handle);
+
+            if (u->use_mmap) {
+
+                if ((work_done = mmap_read(u)) < 0)
+                    goto fail;
+
+            } else {
+                ssize_t l;
+
+                snd_pcm_hwsync(u->pcm_handle);
+                if ((err = snd_pcm_status(u->pcm_handle, status)) >= 0)
+                    l = snd_pcm_status_get_avail(status) * u->frame_size;
+                else
+                    l = u->fragment_size;
+
+                while (l > 0) {
+                    void *p;
+                    snd_pcm_sframes_t t;
+
+                    pa_assert(l > 0);
+
+                    chunk.memblock = pa_memblock_new(u->core->mempool, l);
+
+                    p = pa_memblock_acquire(chunk.memblock);
+                    t = snd_pcm_readi(u->pcm_handle, (uint8_t*) p, l / 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 == -EPIPE)
+                            pa_log_debug("Buffer underrun!");
+                        
+                        if ((t = snd_pcm_recover(u->pcm_handle, t, 1)) == 0)
+                            continue;
+                        
+                        if (t == -EAGAIN) {
+                            pa_log_debug("EAGAIN");
+                            break;
+                        } else {
+                            pa_log("Failed to read data from DSP: %s", snd_strerror(t));
+                            goto fail;
+                        }
+                        
+                    } else {
+                        
+                        chunk.index = 0;
+                        chunk.length = t * u->frame_size;
+
+                        pa_source_post(u->source, &chunk);
+                        pa_memblock_unref(chunk.memblock);
+                        
+                        l -= t * u->frame_size;
+
+                        work_done = 1;
+                    }
+                } 
+            }
+
+            revents &= ~POLLIN;
+            
+            if (work_done)
+                continue;
+        }
+
+        /* Hmm, nothing to do. Let's sleep */
+        if (pa_asyncmsgq_before_poll(u->asyncmsgq) < 0)
+            continue;
+
+/*         pa_log("polling for %i", POLLFD_ALSA_BASE + (PA_SOURCE_OPENED(u->source->thread_info.state) ? n_alsa_fds : 0));   */
+        r = poll(pollfd, POLLFD_ALSA_BASE + (PA_SOURCE_OPENED(u->source->thread_info.state) ? n_alsa_fds : 0), -1);
+        /*pa_log("polling got dsp=%i amq=%i (%i)", r > 0 ? pollfd[POLLFD_DSP].revents : 0, r > 0 ? pollfd[POLLFD_ASYNCQ].revents : 0, r); */
+/*         pa_log("poll end"); */
+
+        pa_asyncmsgq_after_poll(u->asyncmsgq);
+
+        if (r < 0) {
+            if (errno == EINTR) {
+                pollfd[POLLFD_ASYNCQ].revents = 0;
+                revents = 0;
+                continue;
+            }
+
+            pa_log("poll() failed: %s", pa_cstrerror(errno));
+            goto fail;
+        }
+
+        pa_assert(r > 0);
+
+        if (PA_SOURCE_OPENED(u->source->thread_info.state)) {
+            if ((err = snd_pcm_poll_descriptors_revents(u->pcm_handle, pollfd + POLLFD_ALSA_BASE, n_alsa_fds, &revents)) < 0) {
+                pa_log("snd_pcm_poll_descriptors_revents() failed: %s", snd_strerror(err));
+                goto fail;
+            }
+
+/*             pa_log("got alsa event"); */
+        } else
+            revents = 0;
+        
+        pa_assert((pollfd[POLLFD_ASYNCQ].revents & ~POLLIN) == 0);
+    }
+
+fail:
+    /* We have to continue processing messages until we receive the
+     * SHUTDOWN message */
+    pa_asyncmsgq_post(u->core->asyncmsgq, PA_MSGOBJECT(u->core), PA_CORE_MESSAGE_UNLOAD_MODULE, u->module, NULL, NULL);
+    pa_asyncmsgq_wait_for(u->asyncmsgq, PA_MESSAGE_SHUTDOWN);
+
+finish:
+    pa_log_debug("Thread shutting down");
+
+    pa_xfree(pollfd);
+}
+
+
 int pa__init(pa_core *c, pa_module*m) {
+    
     pa_modargs *ma = NULL;
     int ret = -1;
     struct userdata *u = NULL;
     const 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;
@@ -407,33 +661,47 @@ int pa__init(pa_core *c, pa_module*m) {
     const char *name;
     char *name_buf = NULL;
     int namereg_fail;
+    int use_mmap = 1, b;
 
+    pa_assert(c);
+    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;
     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 = DEFAULT_NFRAGS;
+    frag_size = pa_usec_to_bytes(DEFAULT_FRAGSIZE_MSEC*1000, &ss);
+    if (frag_size <= 0)
+        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_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 = fragsize/frame_size;
+    period_size = frag_size/frame_size;
 
+    if (pa_modargs_get_value_boolean(ma, "mmap", &use_mmap) < 0) {
+        pa_log("Failed to parse mmap argument.");
+        goto fail;
+    }
+    
     u = pa_xnew0(struct userdata, 1);
-    m->userdata = u;
+    u->core = c;
     u->module = m;
+    m->userdata = u;
+    u->use_mmap = use_mmap;
+    pa_assert_se(u->asyncmsgq = pa_asyncmsgq_new(0));
 
     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) {
@@ -441,30 +709,44 @@ int pa__init(pa_core *c, pa_module*m) {
         goto fail;
     }
 
+    u->device_name = pa_xstrdup(dev);
+
     if ((err = snd_pcm_info_malloc(&pcm_info)) < 0 ||
         (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) {
+    b = 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 (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.");
+    
+    /* 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;
-    }
-
-    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;
+    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 ((name = pa_modargs_get_value(ma, "source_name", NULL)))
@@ -474,16 +756,37 @@ 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(c, __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->asyncmsgq);
+    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->source->is_hardware = 1;
+
+    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);
+        
         if (snd_mixer_selem_has_capture_volume(u->mixer_elem)) {
             int i;
 
@@ -493,64 +796,48 @@ 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, c->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;
+    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_volume)
+        u->source->get_volume(u->source);
+    if (u->source->get_mute)
+        u->source->get_mute(u->source);
 
     snd_pcm_start(u->pcm_handle);
-
+    
     ret = 0;
 
-    /* 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);
-
 finish:
-    pa_xfree(name_buf);
 
     if (ma)
-         pa_modargs_free(ma);
-
+        pa_modargs_free(ma);
+    
     if (pcm_info)
         snd_pcm_info_free(pcm_info);
 
@@ -566,16 +853,41 @@ fail:
 
 void pa__done(pa_core *c, pa_module*m) {
     struct userdata *u;
-    assert(c && m);
+    
+    pa_assert(c);
+    pa_assert(m);
 
     if (!(u = m->userdata))
         return;
 
-    clear_up(u);
+    if (u->source)
+        pa_source_disconnect(u->source);
+
+    if (u->thread) {
+        pa_asyncmsgq_send(u->asyncmsgq, NULL, PA_MESSAGE_SHUTDOWN, NULL, NULL);
+        pa_thread_free(u->thread);
+    }
+
+    if (u->asyncmsgq)
+        pa_asyncmsgq_free(u->asyncmsgq);
 
-    if (u->memchunk.memblock)
-        pa_memblock_unref(u->memchunk.memblock);
+    if (u->source)
+        pa_source_unref(u->source);
 
+    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();
 }
 

commit 0defdfb5607889c35fdefff4af31eb8b0ae0cbcf
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Jul 31 22:44:53 2007 +0000

    A lot of updates, all necessary to get the native protocol ported:
    
    * add an int64_t argument to pa_asyncmsgq because it is very difficult to pass 64 values otherwise
    * simplify subclassing in pa_object
    * s/drop/unlink/ at some places
    * port the native protocol to the lock-free core (not tested, compiles fine)
    * move synchronisation of playback streams into pa_sink_input
    * add "start_corked" field to pa_sink_input_new_data
    * allow casting of NULL values in pa_object
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1562 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/Makefile.am b/src/Makefile.am
index 1afe6d6..4083ea5 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -722,10 +722,10 @@ modlibexec_LTLIBRARIES = \
 		libauthkey-prop.la \
 		libstrlist.la \
 		libprotocol-simple.la \
-		libprotocol-http.la 
+		libprotocol-http.la \
+		libprotocol-native.la
 
 #		libprotocol-esound.la
-#		libprotocol-native.la
 
 # We need to emulate sendmsg/recvmsg to support this on Win32
 if !OS_IS_WIN32
@@ -879,11 +879,10 @@ modlibexec_LTLIBRARIES += \
 		module-volume-restore.la \
 		module-rescue-streams.la \
 		module-http-protocol-tcp.la \
-		module-sine.la
-
+		module-sine.la \
+		module-native-protocol-tcp.la \
+		module-native-protocol-fd.la
 #		module-esound-protocol-tcp.la \
-#		module-native-protocol-tcp.la \
-#		module-native-protocol-fd.la \
 #		module-combine.la \
 #		module-tunnel-sink.la \
 #		module-tunnel-source.la \
@@ -899,10 +898,10 @@ modlibexec_LTLIBRARIES += \
 if HAVE_AF_UNIX
 modlibexec_LTLIBRARIES += \
 		module-cli-protocol-unix.la \
-		module-simple-protocol-unix.la
-		module-http-protocol-unix.la
-#		module-esound-protocol-unix.la \
-#		module-native-protocol-unix.la
+		module-simple-protocol-unix.la \
+		module-http-protocol-unix.la \
+		module-native-protocol-unix.la
+#		module-esound-protocol-unix.la 
 endif
 
 if HAVE_MKFIFO
@@ -1083,20 +1082,20 @@ module_http_protocol_unix_la_LIBADD = $(AM_LIBADD) libpulsecore.la libprotocol-h
 
 # Native protocol
 
-#module_native_protocol_tcp_la_SOURCES = modules/module-protocol-stub.c
-#module_native_protocol_tcp_la_CFLAGS = -DUSE_TCP_SOCKETS -DUSE_PROTOCOL_NATIVE $(AM_CFLAGS)
-#module_native_protocol_tcp_la_LDFLAGS = -module -avoid-version
-#module_native_protocol_tcp_la_LIBADD = $(AM_LIBADD) libpulsecore.la libprotocol-native.la libsocket-server.la
+module_native_protocol_tcp_la_SOURCES = modules/module-protocol-stub.c
+module_native_protocol_tcp_la_CFLAGS = -DUSE_TCP_SOCKETS -DUSE_PROTOCOL_NATIVE $(AM_CFLAGS)
+module_native_protocol_tcp_la_LDFLAGS = -module -avoid-version
+module_native_protocol_tcp_la_LIBADD = $(AM_LIBADD) libpulsecore.la libprotocol-native.la libsocket-server.la
 
-#module_native_protocol_unix_la_SOURCES = modules/module-protocol-stub.c
-#module_native_protocol_unix_la_CFLAGS = -DUSE_UNIX_SOCKETS -DUSE_PROTOCOL_NATIVE $(AM_CFLAGS)
-#module_native_protocol_unix_la_LDFLAGS = -module -avoid-version
-#module_native_protocol_unix_la_LIBADD = $(AM_LIBADD) libpulsecore.la libprotocol-native.la libsocket-server.la libsocket-util.la
+module_native_protocol_unix_la_SOURCES = modules/module-protocol-stub.c
+module_native_protocol_unix_la_CFLAGS = -DUSE_UNIX_SOCKETS -DUSE_PROTOCOL_NATIVE $(AM_CFLAGS)
+module_native_protocol_unix_la_LDFLAGS = -module -avoid-version
+module_native_protocol_unix_la_LIBADD = $(AM_LIBADD) libpulsecore.la libprotocol-native.la libsocket-server.la libsocket-util.la
 
-#module_native_protocol_fd_la_SOURCES = modules/module-native-protocol-fd.c
-#module_native_protocol_fd_la_CFLAGS = $(AM_CFLAGS)
-#module_native_protocol_fd_la_LDFLAGS = -module -avoid-version
-#module_native_protocol_fd_la_LIBADD = $(AM_LIBADD) libpulsecore.la libprotocol-native.la libsocket-server.la libsocket-util.la libiochannel.la
+module_native_protocol_fd_la_SOURCES = modules/module-native-protocol-fd.c
+module_native_protocol_fd_la_CFLAGS = $(AM_CFLAGS)
+module_native_protocol_fd_la_LDFLAGS = -module -avoid-version
+module_native_protocol_fd_la_LIBADD = $(AM_LIBADD) libpulsecore.la libprotocol-native.la libsocket-server.la libsocket-util.la libiochannel.la
 
 # EsounD protocol
 
diff --git a/src/modules/module-alsa-sink.c b/src/modules/module-alsa-sink.c
index 9ca881d..551bad8 100644
--- a/src/modules/module-alsa-sink.c
+++ b/src/modules/module-alsa-sink.c
@@ -302,7 +302,7 @@ fail:
     return -1;
 }
 
-static int sink_process_msg(pa_msgobject *o, int code, void *data, pa_memchunk *chunk) {
+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) {
@@ -347,7 +347,7 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, pa_memchunk *
             break;
     }
 
-    return pa_sink_process_msg(o, code, data, chunk);
+    return pa_sink_process_msg(o, code, data, offset, chunk);
 }
 
 static int mixer_callback(snd_mixer_elem_t *elem, unsigned int mask) {
@@ -510,12 +510,13 @@ static void thread_func(void *userdata) {
         int code;
         void *data;
         pa_memchunk chunk;
+        int64_t offset;
         int r;
 
 /*         pa_log("loop");     */
         
         /* Check whether there is a message for us to process */
-        if (pa_asyncmsgq_get(u->asyncmsgq, &object, &code, &data, &chunk, 0) == 0) {
+        if (pa_asyncmsgq_get(u->asyncmsgq, &object, &code, &data, &offset, &chunk, 0) == 0) {
             int ret;
 
 /*             pa_log("processing msg"); */
@@ -525,7 +526,7 @@ static void thread_func(void *userdata) {
                 goto finish;
             }
 
-            ret = pa_asyncmsgq_dispatch(object, code, data, &chunk);
+            ret = pa_asyncmsgq_dispatch(object, code, data, offset, &chunk);
             pa_asyncmsgq_done(u->asyncmsgq, ret);
             continue;
         } 
@@ -660,7 +661,7 @@ static void thread_func(void *userdata) {
 fail:
     /* We have to continue processing messages until we receive the
      * SHUTDOWN message */
-    pa_asyncmsgq_post(u->core->asyncmsgq, PA_MSGOBJECT(u->core), PA_CORE_MESSAGE_UNLOAD_MODULE, u->module, NULL, NULL);
+    pa_asyncmsgq_post(u->core->asyncmsgq, PA_MSGOBJECT(u->core), PA_CORE_MESSAGE_UNLOAD_MODULE, u->module, 0, NULL, NULL);
     pa_asyncmsgq_wait_for(u->asyncmsgq, PA_MESSAGE_SHUTDOWN);
 
 finish:
@@ -893,7 +894,7 @@ void pa__done(pa_core *c, pa_module*m) {
         pa_sink_disconnect(u->sink);
 
     if (u->thread) {
-        pa_asyncmsgq_send(u->asyncmsgq, NULL, PA_MESSAGE_SHUTDOWN, NULL, NULL);
+        pa_asyncmsgq_send(u->asyncmsgq, NULL, PA_MESSAGE_SHUTDOWN, NULL, 0, NULL);
         pa_thread_free(u->thread);
     }
 
diff --git a/src/modules/module-alsa-source.c b/src/modules/module-alsa-source.c
index 59414d3..c2dad6f 100644
--- a/src/modules/module-alsa-source.c
+++ b/src/modules/module-alsa-source.c
@@ -290,7 +290,7 @@ fail:
     return -1;
 }
 
-static int source_process_msg(pa_msgobject *o, int code, void *data, pa_memchunk *chunk) {
+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) {
@@ -335,7 +335,7 @@ static int source_process_msg(pa_msgobject *o, int code, void *data, pa_memchunk
             break;
     }
 
-    return pa_source_process_msg(o, code, data, chunk);
+    return pa_source_process_msg(o, code, data, offset, chunk);
 }
 
 static int mixer_callback(snd_mixer_elem_t *elem, unsigned int mask) {
@@ -498,12 +498,13 @@ static void thread_func(void *userdata) {
         int code;
         void *data;
         int r;
+        int64_t offset;
         pa_memchunk chunk;
 
 /*         pa_log("loop");     */
         
         /* Check whether there is a message for us to process */
-        if (pa_asyncmsgq_get(u->asyncmsgq, &object, &code, &data, &chunk, 0) == 0) {
+        if (pa_asyncmsgq_get(u->asyncmsgq, &object, &code, &data, &offset, &chunk, 0) == 0) {
             int ret;
 
 /*             pa_log("processing msg"); */
@@ -513,7 +514,7 @@ static void thread_func(void *userdata) {
                 goto finish;
             }
 
-            ret = pa_asyncmsgq_dispatch(object, code, data, &chunk);
+            ret = pa_asyncmsgq_dispatch(object, code, data, offset, &chunk);
             pa_asyncmsgq_done(u->asyncmsgq, ret);
             continue;
         } 
@@ -634,7 +635,7 @@ static void thread_func(void *userdata) {
 fail:
     /* We have to continue processing messages until we receive the
      * SHUTDOWN message */
-    pa_asyncmsgq_post(u->core->asyncmsgq, PA_MSGOBJECT(u->core), PA_CORE_MESSAGE_UNLOAD_MODULE, u->module, NULL, NULL);
+    pa_asyncmsgq_post(u->core->asyncmsgq, PA_MSGOBJECT(u->core), PA_CORE_MESSAGE_UNLOAD_MODULE, u->module, 0, NULL, NULL);
     pa_asyncmsgq_wait_for(u->asyncmsgq, PA_MESSAGE_SHUTDOWN);
 
 finish:
@@ -864,7 +865,7 @@ void pa__done(pa_core *c, pa_module*m) {
         pa_source_disconnect(u->source);
 
     if (u->thread) {
-        pa_asyncmsgq_send(u->asyncmsgq, NULL, PA_MESSAGE_SHUTDOWN, NULL, NULL);
+        pa_asyncmsgq_send(u->asyncmsgq, NULL, PA_MESSAGE_SHUTDOWN, NULL, 0, NULL);
         pa_thread_free(u->thread);
     }
 
diff --git a/src/modules/module-null-sink.c b/src/modules/module-null-sink.c
index bb0a504..f0e3a06 100644
--- a/src/modules/module-null-sink.c
+++ b/src/modules/module-null-sink.c
@@ -83,7 +83,7 @@ static const char* const valid_modargs[] = {
     NULL
 };
 
-static int sink_process_msg(pa_msgobject *o, int code, void *data, pa_memchunk *chunk) {
+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) {
@@ -107,7 +107,7 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, pa_memchunk *
         }
     }
     
-    return pa_sink_process_msg(o, code, data, chunk);
+    return pa_sink_process_msg(o, code, data, offset, chunk);
 }
 
 static void thread_func(void *userdata) {
@@ -131,9 +131,10 @@ static void thread_func(void *userdata) {
         pa_memchunk chunk;
         int r, timeout;
         struct timeval now;
+        int64_t offset;
 
         /* Check whether there is a message for us to process */
-        if (pa_asyncmsgq_get(u->asyncmsgq, &object, &code, &data, &chunk, 0) == 0) {
+        if (pa_asyncmsgq_get(u->asyncmsgq, &object, &code, &data, &offset, &chunk, 0) == 0) {
             int ret;
 
             if (!object && code == PA_MESSAGE_SHUTDOWN) {
@@ -141,7 +142,7 @@ static void thread_func(void *userdata) {
                 goto finish;
             }
 
-            ret = pa_asyncmsgq_dispatch(object, code, data, &chunk);
+            ret = pa_asyncmsgq_dispatch(object, code, data, offset, &chunk);
             pa_asyncmsgq_done(u->asyncmsgq, ret);
             continue;
         }
@@ -190,7 +191,7 @@ static void thread_func(void *userdata) {
 fail:
     /* We have to continue processing messages until we receive the
      * SHUTDOWN message */
-    pa_asyncmsgq_post(u->core->asyncmsgq, PA_MSGOBJECT(u->core), PA_CORE_MESSAGE_UNLOAD_MODULE, u->module, NULL, NULL);
+    pa_asyncmsgq_post(u->core->asyncmsgq, PA_MSGOBJECT(u->core), PA_CORE_MESSAGE_UNLOAD_MODULE, u->module, 0, NULL, NULL);
     pa_asyncmsgq_wait_for(u->asyncmsgq, PA_MESSAGE_SHUTDOWN);
 
 finish:
@@ -271,7 +272,7 @@ void pa__done(pa_core *c, pa_module*m) {
         pa_sink_disconnect(u->sink);
 
     if (u->thread) {
-        pa_asyncmsgq_send(u->asyncmsgq, NULL, PA_MESSAGE_SHUTDOWN, NULL, NULL);
+        pa_asyncmsgq_send(u->asyncmsgq, NULL, PA_MESSAGE_SHUTDOWN, NULL, 0, NULL);
         pa_thread_free(u->thread);
     }
 
diff --git a/src/modules/module-oss.c b/src/modules/module-oss.c
index 63f4d40..a43bdb3 100644
--- a/src/modules/module-oss.c
+++ b/src/modules/module-oss.c
@@ -581,7 +581,7 @@ fail:
     return -1;
 }
 
-static int sink_process_msg(pa_msgobject *o, int code, void *data, pa_memchunk *chunk) {
+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 do_trigger = 0, ret, quick = 1;
 
@@ -673,7 +673,7 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, pa_memchunk *
             break;
     }
 
-    ret = pa_sink_process_msg(o, code, data, chunk);
+    ret = pa_sink_process_msg(o, code, data, offset, chunk);
 
     if (do_trigger)
         trigger(u, quick);
@@ -681,7 +681,7 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, pa_memchunk *
     return ret;
 }
 
-static int source_process_msg(pa_msgobject *o, int code, void *data, pa_memchunk *chunk) {
+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 do_trigger = 0, ret, quick = 1;
 
@@ -770,7 +770,7 @@ static int source_process_msg(pa_msgobject *o, int code, void *data, pa_memchunk
             break;
     }
 
-    ret = pa_source_process_msg(o, code, data, chunk);
+    ret = pa_source_process_msg(o, code, data, offset, chunk);
 
     if (do_trigger)
         trigger(u, quick);
@@ -807,11 +807,12 @@ static void thread_func(void *userdata) {
         void *data;
         pa_memchunk chunk;
         int r;
+        int64_t offset;
 
 /*        pa_log("loop");    */
         
         /* Check whether there is a message for us to process */
-        if (pa_asyncmsgq_get(u->asyncmsgq, &object, &code, &data, &chunk, 0) == 0) {
+        if (pa_asyncmsgq_get(u->asyncmsgq, &object, &code, &data, &offset, &chunk, 0) == 0) {
             int ret;
 
 /*             pa_log("processing msg"); */
@@ -821,7 +822,7 @@ static void thread_func(void *userdata) {
                 goto finish;
             }
 
-            ret = pa_asyncmsgq_dispatch(object, code, data, &chunk);
+            ret = pa_asyncmsgq_dispatch(object, code, data, offset, &chunk);
             pa_asyncmsgq_done(u->asyncmsgq, ret);
             continue;
         } 
@@ -1051,7 +1052,7 @@ static void thread_func(void *userdata) {
 fail:
     /* We have to continue processing messages until we receive the
      * SHUTDOWN message */
-    pa_asyncmsgq_post(u->core->asyncmsgq, PA_MSGOBJECT(u->core), PA_CORE_MESSAGE_UNLOAD_MODULE, u->module, NULL, NULL);
+    pa_asyncmsgq_post(u->core->asyncmsgq, PA_MSGOBJECT(u->core), PA_CORE_MESSAGE_UNLOAD_MODULE, u->module, 0, NULL, NULL);
     pa_asyncmsgq_wait_for(u->asyncmsgq, PA_MESSAGE_SHUTDOWN);
 
 finish:
@@ -1300,9 +1301,9 @@ go_on:
 
     /* Read mixer settings */
     if (u->source)
-        pa_asyncmsgq_post(u->asyncmsgq, PA_MSGOBJECT(u->source), PA_SOURCE_MESSAGE_GET_VOLUME, &u->source->volume, NULL, NULL);
+        pa_asyncmsgq_post(u->asyncmsgq, PA_MSGOBJECT(u->source), PA_SOURCE_MESSAGE_GET_VOLUME, &u->source->volume, 0, NULL, NULL);
     if (u->sink)
-        pa_asyncmsgq_post(u->asyncmsgq, PA_MSGOBJECT(u->sink), PA_SINK_MESSAGE_GET_VOLUME, &u->sink->volume, NULL, NULL);
+        pa_asyncmsgq_post(u->asyncmsgq, PA_MSGOBJECT(u->sink), PA_SINK_MESSAGE_GET_VOLUME, &u->sink->volume, 0, NULL, NULL);
 
     return 0;
 
@@ -1335,7 +1336,7 @@ void pa__done(pa_core *c, pa_module*m) {
         pa_source_disconnect(u->source);
 
     if (u->thread) {
-        pa_asyncmsgq_send(u->asyncmsgq, NULL, PA_MESSAGE_SHUTDOWN, NULL, NULL);
+        pa_asyncmsgq_send(u->asyncmsgq, NULL, PA_MESSAGE_SHUTDOWN, NULL, 0, NULL);
         pa_thread_free(u->thread);
     }
 
diff --git a/src/modules/module-pipe-sink.c b/src/modules/module-pipe-sink.c
index db8b2e1..83ee06b 100644
--- a/src/modules/module-pipe-sink.c
+++ b/src/modules/module-pipe-sink.c
@@ -84,7 +84,7 @@ static const char* const valid_modargs[] = {
     NULL
 };
 
-static int sink_process_msg(pa_msgobject *o, int code, void *data, pa_memchunk *chunk) {
+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) {
@@ -103,7 +103,7 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, pa_memchunk *
         }
     }
     
-    return pa_sink_process_msg(o, code, data, chunk);
+    return pa_sink_process_msg(o, code, data, offset, chunk);
 }
 
 static void thread_func(void *userdata) {
@@ -133,9 +133,10 @@ static void thread_func(void *userdata) {
         void *data;
         pa_memchunk chunk;
         int r;
+        int64_t offset;
 
         /* Check whether there is a message for us to process */
-        if (pa_asyncmsgq_get(u->asyncmsgq, &object, &code, &data, &chunk, 0) == 0) {
+        if (pa_asyncmsgq_get(u->asyncmsgq, &object, &code, &data, &offset, &chunk, 0) == 0) {
             int ret;
 
             if (!object && code == PA_MESSAGE_SHUTDOWN) {
@@ -143,7 +144,7 @@ static void thread_func(void *userdata) {
                 goto finish;
             }
 
-            ret = pa_asyncmsgq_dispatch(object, code, data, &chunk);
+            ret = pa_asyncmsgq_dispatch(object, code, data, offset, &chunk);
             pa_asyncmsgq_done(u->asyncmsgq, ret);
             continue;
         }
@@ -224,7 +225,7 @@ static void thread_func(void *userdata) {
 fail:
     /* We have to continue processing messages until we receive the
      * SHUTDOWN message */
-    pa_asyncmsgq_post(u->core->asyncmsgq, PA_MSGOBJECT(u->core), PA_CORE_MESSAGE_UNLOAD_MODULE, u->module, NULL, NULL);
+    pa_asyncmsgq_post(u->core->asyncmsgq, PA_MSGOBJECT(u->core), PA_CORE_MESSAGE_UNLOAD_MODULE, u->module, 0, NULL, NULL);
     pa_asyncmsgq_wait_for(u->asyncmsgq, PA_MESSAGE_SHUTDOWN);
 
 finish:
@@ -326,7 +327,7 @@ void pa__done(pa_core *c, pa_module*m) {
         pa_sink_disconnect(u->sink);
 
     if (u->thread) {
-        pa_asyncmsgq_send(u->asyncmsgq, NULL, PA_MESSAGE_SHUTDOWN, NULL, NULL);
+        pa_asyncmsgq_send(u->asyncmsgq, NULL, PA_MESSAGE_SHUTDOWN, NULL, 0, NULL);
         pa_thread_free(u->thread);
     }
 
diff --git a/src/modules/module-pipe-source.c b/src/modules/module-pipe-source.c
index 5dbb1e7..a5f95f9 100644
--- a/src/modules/module-pipe-source.c
+++ b/src/modules/module-pipe-source.c
@@ -111,9 +111,10 @@ static void thread_func(void *userdata) {
         void *data;
         pa_memchunk chunk;
         int r;
+        int64_t offset;
 
         /* Check whether there is a message for us to process */
-        if (pa_asyncmsgq_get(u->asyncmsgq, &object, &code, &data, &chunk, 0) == 0) {
+        if (pa_asyncmsgq_get(u->asyncmsgq, &object, &code, &data, &offset, &chunk, 0) == 0) {
             int ret;
 
             if (!object && code == PA_MESSAGE_SHUTDOWN) {
@@ -121,7 +122,7 @@ static void thread_func(void *userdata) {
                 goto finish;
             }
 
-            ret = pa_asyncmsgq_dispatch(object, code, data, &chunk);
+            ret = pa_asyncmsgq_dispatch(object, code, data, offset, &chunk);
             pa_asyncmsgq_done(u->asyncmsgq, ret);
             continue;
         }
@@ -202,7 +203,7 @@ static void thread_func(void *userdata) {
 fail:
     /* We have to continue processing messages until we receive the
      * SHUTDOWN message */
-    pa_asyncmsgq_post(u->core->asyncmsgq, PA_MSGOBJECT(u->core), PA_CORE_MESSAGE_UNLOAD_MODULE, u->module, NULL, NULL);
+    pa_asyncmsgq_post(u->core->asyncmsgq, PA_MSGOBJECT(u->core), PA_CORE_MESSAGE_UNLOAD_MODULE, u->module, 0, NULL, NULL);
     pa_asyncmsgq_wait_for(u->asyncmsgq, PA_MESSAGE_SHUTDOWN);
 
 finish:
@@ -303,7 +304,7 @@ void pa__done(pa_core *c, pa_module*m) {
         pa_source_disconnect(u->source);
 
     if (u->thread) {
-        pa_asyncmsgq_send(u->asyncmsgq, NULL, PA_MESSAGE_SHUTDOWN, NULL, NULL);
+        pa_asyncmsgq_send(u->asyncmsgq, NULL, PA_MESSAGE_SHUTDOWN, NULL, 0, NULL);
         pa_thread_free(u->thread);
     }
 
diff --git a/src/pulsecore/asyncmsgq.c b/src/pulsecore/asyncmsgq.c
index 1b6d802..ed71d37 100644
--- a/src/pulsecore/asyncmsgq.c
+++ b/src/pulsecore/asyncmsgq.c
@@ -46,6 +46,7 @@ struct asyncmsgq_item {
     pa_msgobject *object;
     void *userdata;
     pa_free_cb_t free_cb;
+    int64_t offset;
     pa_memchunk memchunk;
     pa_semaphore *semaphore;
     int ret;
@@ -96,7 +97,7 @@ void pa_asyncmsgq_free(pa_asyncmsgq *a) {
     pa_xfree(a);
 }
 
-void pa_asyncmsgq_post(pa_asyncmsgq *a, pa_msgobject *object, int code, const void *userdata, const pa_memchunk *chunk, pa_free_cb_t free_cb) {
+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(a);
 
@@ -107,6 +108,7 @@ void pa_asyncmsgq_post(pa_asyncmsgq *a, pa_msgobject *object, int code, const vo
     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;
@@ -121,7 +123,7 @@ void pa_asyncmsgq_post(pa_asyncmsgq *a, pa_msgobject *object, int code, const vo
     pa_mutex_unlock(a->mutex);
 }
 
-int pa_asyncmsgq_send(pa_asyncmsgq *a, pa_msgobject *object, int code, const void *userdata, const pa_memchunk *chunk) {
+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(a);
 
@@ -130,6 +132,7 @@ int pa_asyncmsgq_send(pa_asyncmsgq *a, pa_msgobject *object, int code, const voi
     i.userdata = (void*) userdata;
     i.free_cb = NULL;
     i.ret = -1;
+    i.offset = offset;
     if (chunk) {
         pa_assert(chunk->memblock);
         i.memchunk = *chunk;
@@ -148,7 +151,7 @@ int pa_asyncmsgq_send(pa_asyncmsgq *a, pa_msgobject *object, int code, const voi
     return i.ret;
 }
 
-int pa_asyncmsgq_get(pa_asyncmsgq *a, pa_msgobject **object, int *code, void **userdata, pa_memchunk *chunk, int wait) {
+int pa_asyncmsgq_get(pa_asyncmsgq *a, pa_msgobject **object, int *code, void **userdata, int64_t *offset, pa_memchunk *chunk, int wait) {
     pa_assert(a);
     pa_assert(code);
     pa_assert(!a->current);
@@ -163,6 +166,8 @@ int pa_asyncmsgq_get(pa_asyncmsgq *a, pa_msgobject **object, int *code, void **u
     *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);
@@ -207,13 +212,14 @@ int pa_asyncmsgq_wait_for(pa_asyncmsgq *a, int code) {
     do {
         pa_msgobject *o;
         void *data;
+    int64_t offset;
         pa_memchunk chunk;
         int ret;
 
-        if (pa_asyncmsgq_get(a, &o, &c, &data, &chunk, 1) < 0)
+        if (pa_asyncmsgq_get(a, &o, &c, &data, &offset, &chunk, 1) < 0)
             return -1;
 
-        ret = pa_asyncmsgq_dispatch(o, c, data, &chunk);
+        ret = pa_asyncmsgq_dispatch(o, c, data, offset, &chunk);
         pa_asyncmsgq_done(a, ret);
 
     } while (c != code);
@@ -239,10 +245,10 @@ void pa_asyncmsgq_after_poll(pa_asyncmsgq *a) {
     pa_asyncq_after_poll(a->asyncq);
 }
 
-int pa_asyncmsgq_dispatch(pa_msgobject *object, int code, void *userdata, pa_memchunk *memchunk) {
+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, memchunk);
+        return object->process_msg(object, code, userdata, offset, memchunk);
 
     return 0;
 }
diff --git a/src/pulsecore/asyncmsgq.h b/src/pulsecore/asyncmsgq.h
index 17b37e4..b0f1a6e 100644
--- a/src/pulsecore/asyncmsgq.h
+++ b/src/pulsecore/asyncmsgq.h
@@ -57,11 +57,11 @@ typedef struct pa_asyncmsgq pa_asyncmsgq;
 pa_asyncmsgq* pa_asyncmsgq_new(size_t size);
 void pa_asyncmsgq_free(pa_asyncmsgq* q);
 
-void pa_asyncmsgq_post(pa_asyncmsgq *q, pa_msgobject *object, int code, const void *userdata, 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, const pa_memchunk *memchunk);
+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, pa_memchunk *memchunk, int wait);
-int pa_asyncmsgq_dispatch(pa_msgobject *object, int code, void *userdata, 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);
 
diff --git a/src/pulsecore/core.c b/src/pulsecore/core.c
index a940bfc..1a0e50b 100644
--- a/src/pulsecore/core.c
+++ b/src/pulsecore/core.c
@@ -49,9 +49,9 @@
 
 #include "core.h"
 
-static PA_DEFINE_CHECK_TYPE(pa_core, core_check_type, pa_msgobject_check_type);
+static PA_DEFINE_CHECK_TYPE(pa_core, pa_msgobject);
 
-static int core_process_msg(pa_msgobject *o, int code, void *userdata, pa_memchunk *chunk) {
+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);
@@ -79,13 +79,14 @@ static void asyncmsgq_cb(pa_mainloop_api*api, pa_io_event* e, int fd, pa_io_even
         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(c->asyncmsgq, &object, &code, &data, &chunk, 0) == 0) {
+        while (pa_asyncmsgq_get(c->asyncmsgq, &object, &code, &data, &offset, &chunk, 0) == 0) {
             int ret;
 
-            ret = pa_asyncmsgq_dispatch(object, code, data, &chunk);
+            ret = pa_asyncmsgq_dispatch(object, code, data, offset, &chunk);
             pa_asyncmsgq_done(c->asyncmsgq, ret);
         }
 
@@ -116,7 +117,7 @@ pa_core* pa_core_new(pa_mainloop_api *m, int shared) {
         }
     }
 
-    c = pa_msgobject_new(pa_core, core_check_type);
+    c = pa_msgobject_new(pa_core);
     c->parent.parent.free = core_free;
     c->parent.process_msg = core_process_msg;
 
diff --git a/src/pulsecore/msgobject.c b/src/pulsecore/msgobject.c
index 6db630c..f54e69f 100644
--- a/src/pulsecore/msgobject.c
+++ b/src/pulsecore/msgobject.c
@@ -28,15 +28,22 @@
 
 #include "msgobject.h"
 
-PA_DEFINE_CHECK_TYPE(pa_msgobject, pa_msgobject_check_type, pa_object_check_type);
+PA_DEFINE_CHECK_TYPE(pa_msgobject, pa_object);
 
-pa_msgobject *pa_msgobject_new_internal(size_t size, const char *type_name, int (*check_type)(pa_object *o, const char *type_name)) {
+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);
 
-    o = PA_MSGOBJECT(pa_object_new_internal(size, type_name, check_type ? check_type : pa_msgobject_check_type));
+    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
index 65761ae..8221cc3 100644
--- a/src/pulsecore/msgobject.h
+++ b/src/pulsecore/msgobject.h
@@ -37,14 +37,14 @@ typedef struct pa_msgobject pa_msgobject;
 
 struct pa_msgobject {
     pa_object parent;
-    int (*process_msg)(pa_msgobject *o, int code, void *userdata, pa_memchunk *chunk);
+    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)(pa_object *o, const char *type_name));
+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(pa_object *o, const char *type);
+int pa_msgobject_check_type(const char *type);
 
-#define pa_msgobject_new(type, check_type) ((type*) pa_msgobject_new_internal(sizeof(type), #type, check_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)
diff --git a/src/pulsecore/native-common.h b/src/pulsecore/native-common.h
index f7a7da1..d22c8d1 100644
--- a/src/pulsecore/native-common.h
+++ b/src/pulsecore/native-common.h
@@ -115,6 +115,8 @@ enum {
     PA_COMMAND_MOVE_SINK_INPUT,
     PA_COMMAND_MOVE_SOURCE_OUTPUT,
 
+    PA_COMMAND_SET_SINK_INPUT_MUTE,
+
     PA_COMMAND_MAX
 };
 
diff --git a/src/pulsecore/object.c b/src/pulsecore/object.c
index a983c5a..23a4575 100644
--- a/src/pulsecore/object.c
+++ b/src/pulsecore/object.c
@@ -28,17 +28,23 @@
 
 #include "object.h"
 
-pa_object *pa_object_new_internal(size_t size, const char *type_name, int (*check_type)(pa_object *o, const char *type_name)) {
+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 ? check_type : pa_object_check_type;
+    o->check_type = check_type;
 
     return o;
 }
@@ -59,8 +65,7 @@ void pa_object_unref(pa_object *o) {
     }
 }
 
-int pa_object_check_type(pa_object *o, const char *type_name) {
-    pa_assert(o);
+int pa_object_check_type(const char *type_name) {
     pa_assert(type_name);
     
     return type_name == "pa_object" || strcmp(type_name, "pa_object") == 0;
diff --git a/src/pulsecore/object.h b/src/pulsecore/object.h
index 270f289..9c62f74 100644
--- a/src/pulsecore/object.h
+++ b/src/pulsecore/object.h
@@ -38,20 +38,19 @@ struct pa_object {
     PA_REFCNT_DECLARE;
     const char *type_name;
     void (*free)(pa_object *o);
-    int (*check_type)(pa_object *o, const char *type_name);
+    int (*check_type)(const char *type_name);
 };
 
-pa_object *pa_object_new_internal(size_t size, const char *type_name, int (*check_type)(pa_object *o, const char *type_name));
-#define pa_object_new(type, check_type) ((type*) pa_object_new_internal(sizeof(type), #type, check_type)
+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(pa_object *o, const char *type);
+int pa_object_check_type(const char *type);
 
 static inline int pa_object_isinstance(void *o) {
     pa_object *obj = (pa_object*) o;
-    pa_assert(obj);
-    return obj->check_type(obj, "pa_object");
+    return obj ? obj->check_type("pa_object") : 0;
 }
 
 pa_object *pa_object_ref(pa_object *o);
@@ -63,19 +62,18 @@ static inline int pa_object_refcnt(pa_object *o) {
 
 static inline pa_object* pa_object_cast(void *o) {
     pa_object *obj = (pa_object*) o;
-    pa_assert(obj->check_type(obj, "pa_object"));
+    pa_assert(!obj || obj->check_type("pa_object"));
     return obj;
 }
 
-#define pa_object_assert_ref(o) pa_assert(pa_object_refcnt(o))
+#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;                                \
-        pa_assert(obj);                                                 \
-        return obj->check_type(obj, #c);                                \
+        return obj ? obj->check_type(#c) : 1;                           \
     }                                                                   \
     static inline c* c##_cast(void *o) {                                \
         pa_assert(c##_isinstance(o));                                   \
@@ -95,14 +93,13 @@ static inline pa_object* pa_object_cast(void *o) {
     }                                                                   \
     struct __stupid_useless_struct_to_allow_trailing_semicolon
 
-#define PA_DEFINE_CHECK_TYPE(c, func, parent)                           \
-    int func(pa_object *o, const char *type) {                          \
-        pa_assert(o);                                                   \
+#define PA_DEFINE_CHECK_TYPE(c, parent)                                 \
+    int c##_check_type(const char *type) {                              \
         pa_assert(type);                                                \
         if (type == #c ||                                               \
             strcmp(type, #c) == 0)                                      \
             return 1;                                                   \
-        return parent(o, type);                                         \
+        return parent##_check_type(type);                               \
     }                                                                   \
     struct __stupid_useless_struct_to_allow_trailing_semicolon
 
diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c
index 97345f0..3be5eae 100644
--- a/src/pulsecore/protocol-native.c
+++ b/src/pulsecore/protocol-native.c
@@ -28,7 +28,6 @@
 
 #include <string.h>
 #include <stdio.h>
-#include <assert.h>
 #include <stdlib.h>
 #include <unistd.h>
 
@@ -72,54 +71,57 @@
 
 #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 last_missing;
+} 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 +134,31 @@ 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 +169,39 @@ struct pa_protocol_native {
     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_DRAIN, /* disabled prebuf, get playback started. */
+    SINK_INPUT_MESSAGE_FLUSH,
+    SINK_INPUT_MESSAGE_TRIGGER,
+    SINK_INPUT_MESSAGE_SEEK,
+    SINK_INPUT_MESSAGE_PREBUF_FORCE
+};
+
+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 */
+};
+
 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);
+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 +224,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);
@@ -239,12 +283,13 @@ 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_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 +314,145 @@ 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);
+    upload_stream_unref(s);
+    s->connection = NULL;
+}
+
+static void upload_stream_free(pa_object *o) {
+    upload_stream *s = UPLOAD_STREAM(o);
+    pa_assert(s);
 
-    struct upload_stream *s;
-    assert(c && ss && name && length);
+    upload_stream_unlink(s);
 
-    s = pa_xnew(struct upload_stream, 1);
-    s->type = UPLOAD_STREAM;
+    pa_xfree(s->name);
+
+    if (s->memchunk.memblock)
+        pa_memblock_unref(s->memchunk.memblock);
+
+    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);
+    c->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);
 
-    pa_idxset_remove_by_data(o->connection->output_streams, o, NULL);
+    if (!s->connection)
+        return;
 
-    pa_xfree(o->name);
+    if (s->source_output) {
+        pa_source_output_disconnect(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);
+    record_stream_unref(s);    
+    s->connection = NULL;
+}
+
+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);
+}
 
-    if (o->memchunk.memblock)
-        pa_memblock_unref(o->memchunk.memblock);
+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);
+
+    switch (code) {
+        
+        case RECORD_STREAM_MESSAGE_POST_DATA:
+            
+            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);
+            
+            pa_pstream_send_memblock(s->connection->pstream, s->index, 0, PA_SEEK_RELATIVE, chunk);
+            break;
+    }
 
-    pa_xfree(o);
+    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,
+        size_t *maxlength,
+        size_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;
+    data.corked = corked;
     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)))
         return NULL;
 
-    s = pa_xnew(struct record_stream, 1);
+    s = pa_msgobject_new(record_stream);
+    c->parent.parent.free = record_stream_free;
+    c->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 +462,143 @@ 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;
 
-    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);
+    if (s->sink_input) {
+        pa_sink_input_disconnect(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);
+    playback_stream_unref(s);    
+    s->connection = NULL;
+}
+
+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 struct playback_stream* playback_stream_new(
-        struct connection *c,
+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);
+
+    switch (code) {
+        case PLAYBACK_STREAM_MESSAGE_REQUEST_DATA: {
+            pa_tagstruct *t;
+            int32_t l;
+
+            if ((l = pa_atomic_load(&s->missing)) <= 0)
+                break;
+            
+            pa_assert_se(pa_atomic_sub(&s->missing, l) >= l);
+            
+            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;
+        }
+
+        case PLAYBACK_STREAM_MESSAGE_DRAIN_ACK:
+            pa_pstream_send_simple_ack(s->connection->pstream, PA_PTR_TO_UINT(userdata));
+            break;
+
+    }
+
+    return 0;
+}
+
+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,
+        size_t *maxlength,
+        size_t *tlength,
+        size_t *prebuf,
+        size_t *minreq,
         pa_cvolume *volume,
-        uint32_t syncid) {
+        uint32_t syncid,
+        int corked,
+        size_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 +606,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 +623,136 @@ 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.start_corked = corked;
+    data.sync_base = ssync ? ssync->sink_input : NULL;
 
     if (!(sink_input = pa_sink_input_new(c->protocol->core, &data, 0)))
         return NULL;
 
-    s = pa_xnew(struct playback_stream, 1);
-    s->type = PLAYBACK_STREAM;
+    s = pa_msgobject_new(playback_stream);
+    c->parent.parent.free = playback_stream_free;
+    c->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 = pa_memblockq_get_maxlength(s->memblockq);
+    *tlength = pa_memblockq_get_tlength(s->memblockq);
+    *prebuf = pa_memblockq_get_prebuf(s->memblockq);
+    *minreq = pa_memblockq_get_minreq(s->memblockq);
+    *missing = pa_memblockq_missing(s->memblockq);
+    
+    pa_atomic_store(&s->missing, 0);
+    s->last_missing = *missing;
     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 void connection_unlink(connection *c) {
+    record_stream *r;
+    output_stream *o;
 
-    if (p->drain_request)
-        pa_pstream_send_error(p->connection->pstream, p->drain_tag, PA_ERR_NOENTITY);
+    pa_assert(c);
 
-    PA_LLIST_FIND_HEAD(struct playback_stream, p, &head);
-    PA_LLIST_REMOVE(struct playback_stream, head, p);
-
-    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);
-}
-
-static void connection_free(struct connection *c) {
-    struct record_stream *r;
-    struct output_stream *o;
-    assert(c && c->protocol);
+    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_close(c->pstream);
+
+    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);
+    connection_unref(c);
+    c->protocol = NULL;
+}
+
+static void connection_free(pa_object *o) {
+    connection *c = CONNECTION(o);
+    
+    pa_assert(c);
+
+    connection_unlink(c);
+    
+    pa_idxset_free(c->record_streams, NULL, NULL);
+    pa_idxset_free(c->output_streams, NULL, NULL);
+
+    pa_pdispatch_unref(c->pdispatch);
+    pa_pstream_unref(c->pstream);
+    pa_client_free(c->client);
 
     pa_xfree(c);
 }
 
-static void request_bytes(struct playback_stream *s) {
-    pa_tagstruct *t;
-    size_t l;
-    assert(s);
+static void request_bytes(playback_stream *s) {
+    size_t new_missing, delta, previous_missing;
 
-    if (!(l = pa_memblockq_missing(s->memblockq)))
-        return;
-
-    if (l <= s->requested_bytes)
-        return;
+    playback_stream_assert_ref(s);
 
-    l -= s->requested_bytes;
+    new_missing = pa_memblockq_missing(s->memblockq);
 
-    if (l < pa_memblockq_get_minreq(s->memblockq))
+    if (new_missing <= s->last_missing)
         return;
 
-    s->requested_bytes += l;
-
-    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);
+    delta = new_missing - s->last_missing;
+    s->last_missing = new_missing;
 
-/*     pa_log("Requesting %u bytes", l);  */
+    previous_missing = pa_atomic_add(&s->missing, delta);
+    if (previous_missing < pa_memblockq_get_minreq(s->memblockq) && previous_missing+delta >= pa_memblockq_get_minreq(s->memblockq))
+        pa_asyncmsgq_post(s->connection->protocol->core->asyncmsgq, 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 +767,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 +776,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 +787,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);
@@ -603,22 +800,123 @@ static void send_record_stream_killed(struct record_stream *r) {
 
 /*** sinkinput 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;
+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));
+            return 0;
+
+        case SINK_INPUT_MESSAGE_POST_DATA: {
+            pa_assert(chunk);
+
+            if (pa_memblockq_push_align(s->memblockq, chunk) < 0) {
+
+                pa_log_warn("Failed to push data into queue");
+                pa_asyncmsgq_post(s->connection->protocol->core->asyncmsgq, PA_MSGOBJECT(s), PLAYBACK_STREAM_MESSAGE_OVERFLOW, NULL, 0, NULL, NULL);
+                pa_memblockq_seek(s->memblockq, chunk->length, PA_SEEK_RELATIVE);
+            }
+
+            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(s->connection->protocol->core->asyncmsgq, 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;
+            }
+
+            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 PA_SINK_INPUT_MESSAGE_SET_STATE:
+
+            pa_memblockq_prebuf_force(s->memblockq);
+            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;
+        }
+    }
 
-        /* Report that we're empty */
+    return pa_sink_input_process_msg(o, code, userdata, offset, chunk);
+}
+
+static int sink_input_peek_cb(pa_sink_input *i, pa_memchunk *chunk) {
+    playback_stream *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);
+    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(s->connection->protocol->core->asyncmsgq, PA_MSGOBJECT(s), PLAYBACK_STREAM_MESSAGE_UNDERFLOW, NULL, 0, NULL, NULL);
         s->underrun = 1;
     }
 
@@ -632,65 +930,67 @@ static int sink_input_peek_cb(pa_sink_input *i, pa_memchunk *chunk) {
     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;
+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(s->connection->protocol->core->asyncmsgq, PA_MSGOBJECT(s), PLAYBACK_STREAM_MESSAGE_DRAIN_ACK, PA_UINT_TO_PTR(s->drain_tag), 0, NULL, NULL);
     }
 
+    request_bytes(s);
+
 /*     pa_log("after_drop: %u %u", pa_memblockq_get_length(s->memblockq), pa_memblockq_is_readable(s->memblockq));   */
 }
 
 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);
-}
+    playback_stream *s;
 
-static pa_usec_t sink_input_get_latency_cb(pa_sink_input *i) {
-    struct playback_stream *s;
-    assert(i && i->userdata);
-    s = i->userdata;
+    pa_sink_input_assert_ref(i);
+    s = PLAYBACK_STREAM(i->userdata);
+    playback_stream_assert_ref(s);
 
-    /*pa_log("get_latency: %u", pa_memblockq_get_length(s->memblockq));*/
-
-    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 ***/
 
 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(s->connection->protocol->core->asyncmsgq, 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 +999,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 +1021,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;
@@ -731,8 +1031,9 @@ static void command_create_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GC
     pa_sink *sink = NULL;
     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 +1074,33 @@ 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);
 
     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 +1110,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 +1164,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 +1197,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,9 +1216,11 @@ 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);
         return;
@@ -913,16 +1228,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 +1331,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 +1350,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 +1372,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 +1388,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 +1404,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);
-
-    s->drain_request = 0;
-
-    pa_memblockq_prebuf_disable(s->memblockq);
+    CHECK_VALIDITY(c->pstream, playback_stream_isinstance(s), tag, PA_ERR_NOENTITY);
 
-    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 +1436,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,13 +1456,13 @@ 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);
 
     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);
+/*     if (s->sink_input->resampled_chunk.memblock) */  /* FIXME*/ 
+/*         latency += pa_bytes_to_usec(s->sink_input->resampled_chunk.length, &s->sink_input->sample_spec); */
     pa_tagstruct_put_usec(reply, latency);
 
     pa_tagstruct_put_usec(reply, 0);
@@ -1162,12 +1475,14 @@ static void command_get_playback_latency(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_
 }
 
 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 +1507,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 +1545,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 +1563,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 +1612,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 +1636,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 +1646,24 @@ 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->get_volume ? PA_SINK_HW_VOLUME_CTRL : 0) |  /* FIXME */
+        (sink->get_latency ? PA_SINK_LATENCY : 0) |        /* FIXME */ 
         (sink->is_hardware ? PA_SINK_HARDWARE : 0),
         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 +1671,24 @@ 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->get_volume ? PA_SOURCE_HW_VOLUME_CTRL : 0) |     /* FIXME */
+        (source->get_latency ? PA_SOURCE_LATENCY : 0) |              /* FIXME */
         (source->is_hardware ? PA_SOURCE_HARDWARE : 0),
         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 +1696,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);
@@ -1376,7 +1707,9 @@ static void module_fill_tagstruct(pa_tagstruct *t, pa_module *module) {
 }
 
 static void sink_input_fill_tagstruct(pa_tagstruct *t, pa_sink_input *s) {
-    assert(t && 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);
@@ -1392,7 +1725,9 @@ static void sink_input_fill_tagstruct(pa_tagstruct *t, pa_sink_input *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 +1742,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 +1757,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 +1768,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 +1805,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
@@ -1497,12 +1836,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 +1867,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;
     }
 
@@ -1545,7 +1886,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)
                 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 +1896,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 +1930,10 @@ 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);
+    pa_assert(t);
 
     t = pa_tagstruct_new(NULL, 0);
     pa_tagstruct_putu32(t, PA_COMMAND_SUBSCRIBE_EVENT);
@@ -1599,9 +1944,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 +1964,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 +1978,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 +2002,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 +2045,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 +2068,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 +2127,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 +2151,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_TRIGGER, 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_PREBUF_FORCE, 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,11 +2199,13 @@ 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)) {
         protocol_error(c);
@@ -1889,9 +2221,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 +2241,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 +2259,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 +2280,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)) {
@@ -1973,7 +2311,7 @@ static void command_kill(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, uint3
     } 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);
@@ -1985,12 +2323,14 @@ static void command_kill(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, uint3
 }
 
 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 ||
         !pa_tagstruct_eof(t)) {
@@ -2013,10 +2353,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 +2375,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 +2410,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 +2441,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 +2451,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 +2485,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 +2512,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 ||
@@ -2218,69 +2568,49 @@ static void command_move_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag
     }
 
     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);
-
-    if (!(stream = pa_idxset_get_by_index(c->output_streams, channel))) {
+    connection *c = CONNECTION(userdata);
+    output_stream *stream;
+    
+    pa_assert(p);
+    pa_assert(chunk);
+    connection_assert_ref(c);
+
+    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);
-
-            /* 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);
-        }
-
-        ps->underrun = 0;
-
-        pa_sink_notify(ps->sink_input->sink);
-
+    if (playback_stream_isinstance(stream)) {
+        playback_stream *ps = PLAYBACK_STREAM(stream);
+        
+        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);
+        
+        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) {
                 u->memchunk = *chunk;
@@ -2292,7 +2622,7 @@ 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)
@@ -2317,17 +2647,21 @@ 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_assert(p);
+    connection_assert_ref(c);
 
+    connection_unlink(c);
 /*    pa_log("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);
 }
@@ -2335,25 +2669,32 @@ static void pstream_drain_callback(pa_pstream *p, void *userdata) {
 /*** 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(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);
@@ -2361,7 +2702,8 @@ 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->authorized = !!p->public;
 
@@ -2382,15 +2724,15 @@ static void on_connection(PA_GCC_UNUSED pa_socket_server*s, pa_iochannel *io, vo
     c->protocol = p;
     pa_iochannel_socket_peer_to_string(io, pname, sizeof(pname));
     pa_snprintf(cname, sizeof(cname), "Native client (%s)", pname);
-    assert(p->core);
+    pa_assert(p->core);
     c->client = pa_client_new(p->core, __FILE__, cname);
-    assert(c->client);
+    pa_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_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);
@@ -2398,11 +2740,11 @@ static void on_connection(PA_GCC_UNUSED pa_socket_server*s, pa_iochannel *io, vo
     pa_pstream_set_drain_callback(c->pstream, pstream_drain_callback, c);
 
     c->pdispatch = pa_pdispatch_new(p->core->mainloop, command_table, PA_COMMAND_MAX);
-    assert(c->pdispatch);
+    pa_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);
+    pa_assert(c->record_streams && c->output_streams);
 
     c->rrobin_index = PA_IDXSET_INVALID;
     c->subscription = NULL;
@@ -2420,7 +2762,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;
 
@@ -2450,8 +2792,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.");
@@ -2492,7 +2834,7 @@ 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);
+    pa_assert(p->connections);
 
     return p;
 
@@ -2527,11 +2869,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) {
@@ -2563,7 +2905,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)))
diff --git a/src/pulsecore/protocol-simple.c b/src/pulsecore/protocol-simple.c
index 8f9aed5..0ded5d2 100644
--- a/src/pulsecore/protocol-simple.c
+++ b/src/pulsecore/protocol-simple.c
@@ -67,7 +67,7 @@ typedef struct connection {
 
 PA_DECLARE_CLASS(connection);
 #define CONNECTION(o) (connection_cast(o))
-static PA_DEFINE_CHECK_TYPE(connection, connection_check_type, pa_msgobject_check_type);
+static PA_DEFINE_CHECK_TYPE(connection, pa_msgobject);
                      
 struct pa_protocol_simple {
     pa_module *module;
@@ -91,9 +91,9 @@ enum {
 };
 
 enum {
-    MESSAGE_REQUEST_DATA,      /* data requested from sink input from the main loop */
-    MESSAGE_POST_DATA,         /* data from source output to main loop */
-    MESSAGE_DROP_CONNECTION    /* Please drop a aconnection now */
+    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_DROP_CONNECTION    /* Please drop a aconnection now */
 };
 
 
@@ -102,29 +102,12 @@ enum {
 #define RECORD_BUFFER_SECONDS (5)
 #define RECORD_BUFFER_FRAGMENTS (100)
 
-static void connection_free(pa_object *o) {
-    connection *c = CONNECTION(o);
+static void connection_unlink(connection *c) {
     pa_assert(c);
 
-    if (c->playback.current_memblock)
-        pa_memblock_unref(c->playback.current_memblock);
-
-    if (c->io)
-        pa_iochannel_free(c->io);
-    if (c->input_memblockq)
-        pa_memblockq_free(c->input_memblockq);
-    if (c->output_memblockq)
-        pa_memblockq_free(c->output_memblockq);
-
-    pa_xfree(c);
-}
-
-static void connection_drop(connection *c) {
-    pa_assert(c);
-    
-    if (!pa_idxset_remove_by_data(c->protocol->connections, c, NULL))
+    if (!c->protocol)
         return;
-
+    
     if (c->sink_input) {
         pa_sink_input_disconnect(c->sink_input);
         pa_sink_input_unref(c->sink_input);
@@ -142,9 +125,30 @@ static void connection_drop(connection *c) {
         c->client = 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->io)
+        pa_iochannel_free(c->io);
+    if (c->input_memblockq)
+        pa_memblockq_free(c->input_memblockq);
+    if (c->output_memblockq)
+        pa_memblockq_free(c->output_memblockq);
+
+    pa_xfree(c);
+}
+
 static int do_read(connection *c) {
     pa_memchunk chunk;
     ssize_t r;
@@ -190,7 +194,7 @@ static int do_read(connection *c) {
 
     c->playback.memblock_index += r;
 
-    pa_asyncmsgq_post(c->sink_input->sink->asyncmsgq, PA_MSGOBJECT(c->sink_input), SINK_INPUT_MESSAGE_POST_DATA, NULL, &chunk, NULL);
+    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;
@@ -263,28 +267,28 @@ fail:
         pa_iochannel_free(c->io);
         c->io = NULL;
 
-        pa_asyncmsgq_post(c->sink_input->sink->asyncmsgq, PA_MSGOBJECT(c->sink_input), SINK_INPUT_MESSAGE_DISABLE_PREBUF, NULL, NULL, NULL);
+        pa_asyncmsgq_post(c->sink_input->sink->asyncmsgq, PA_MSGOBJECT(c->sink_input), SINK_INPUT_MESSAGE_DISABLE_PREBUF, NULL, 0, NULL, NULL);
     } else
-        connection_drop(c);
+        connection_unlink(c);
 }
 
-static int connection_process_msg(pa_msgobject *o, int code, void*userdata, pa_memchunk *chunk) {
+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);
 
     switch (code) {
-        case MESSAGE_REQUEST_DATA:
+        case CONNECTION_MESSAGE_REQUEST_DATA:
             do_work(c);
             break;
             
-        case MESSAGE_POST_DATA:
+        case CONNECTION_MESSAGE_POST_DATA:
 /*             pa_log("got data %u", chunk->length); */
             pa_memblockq_push_align(c->output_memblockq, chunk);
             do_work(c);
             break;
 
-        case MESSAGE_DROP_CONNECTION:
-            connection_drop(c);
+        case CONNECTION_MESSAGE_DROP_CONNECTION:
+            connection_unlink(c);
             break;
     }
 
@@ -294,13 +298,13 @@ static int connection_process_msg(pa_msgobject *o, int code, void*userdata, pa_m
 /*** sink_input callbacks ***/
 
 /* Called from thread context */
-static int sink_input_process_msg(pa_msgobject *o, int code, void *userdata, pa_memchunk *chunk) {
+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_assert(i);
-    c = i->userdata;
-    pa_assert(c);
+    pa_sink_input_assert_ref(i);
+    c = CONNECTION(i->userdata);
+    connection_assert_ref(c);
 
     switch (code) {
 
@@ -330,7 +334,7 @@ static int sink_input_process_msg(pa_msgobject *o, int code, void *userdata, pa_
         }
 
         default:
-            return pa_sink_input_process_msg(o, code, userdata, chunk);
+            return pa_sink_input_process_msg(o, code, userdata, offset, chunk);
     }
 }
 
@@ -349,7 +353,7 @@ static int sink_input_peek_cb(pa_sink_input *i, pa_memchunk *chunk) {
 /*     pa_log("peeked %u %i", r >= 0 ? chunk->length: 0, r); */
 
     if (c->dead && r < 0)
-        pa_asyncmsgq_post(c->protocol->core->asyncmsgq, PA_MSGOBJECT(c), MESSAGE_DROP_CONNECTION, NULL, NULL, NULL);
+        pa_asyncmsgq_post(c->protocol->core->asyncmsgq, PA_MSGOBJECT(c), CONNECTION_MESSAGE_DROP_CONNECTION, NULL, 0, NULL, NULL);
 
     return r;
 }
@@ -369,19 +373,20 @@ static void sink_input_drop_cb(pa_sink_input *i, size_t length) {
 
     if (new > old) {
         if (pa_atomic_add(&c->playback.missing, new - old) <= 0)
-            pa_asyncmsgq_post(c->protocol->core->asyncmsgq, PA_MSGOBJECT(c), MESSAGE_REQUEST_DATA, NULL, NULL, NULL);
+            pa_asyncmsgq_post(c->protocol->core->asyncmsgq, 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_assert(i);
+    pa_sink_input_assert_ref(i);
 
-    connection_drop(CONNECTION(i->userdata));
+    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) {
     connection *c;
 
@@ -390,24 +395,22 @@ static void source_output_push_cb(pa_source_output *o, const pa_memchunk *chunk)
     pa_assert(c);
     pa_assert(chunk);
 
-    pa_asyncmsgq_post(c->protocol->core->asyncmsgq, PA_MSGOBJECT(c), MESSAGE_POST_DATA, NULL, chunk, NULL);
+    pa_asyncmsgq_post(c->protocol->core->asyncmsgq, 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) {
-    connection*c;
+    pa_source_output_assert_ref(o);
 
-    pa_assert(o);
-    c = o->userdata;
-    pa_assert(c);
-
-    connection_drop(c);
+    connection_unlink(CONNECTION(o->userdata));
 }
 
+/* Called from main context */
 static pa_usec_t source_output_get_latency_cb(pa_source_output *o) {
     connection*c;
 
     pa_assert(o);
-    c = o->userdata;
+    c = CONNECTION(o->userdata);
     pa_assert(c);
 
     return pa_bytes_to_usec(pa_memblockq_get_length(c->output_memblockq), &c->source_output->sample_spec);
@@ -419,16 +422,16 @@ static void client_kill_cb(pa_client *client) {
     connection*c;
 
     pa_assert(client);
-    c = client->userdata;
+    c = CONNECTION(client->userdata);
     pa_assert(c);
 
-    connection_drop(c);
+    connection_unlink(c);
 }
 
 /*** pa_iochannel callbacks ***/
 
 static void io_callback(pa_iochannel*io, void *userdata) {
-    connection *c = userdata;
+    connection *c = CONNECTION(userdata);
 
     pa_assert(io);
     pa_assert(c);
@@ -453,7 +456,7 @@ static void on_connection(pa_socket_server*s, pa_iochannel *io, void *userdata)
         return;
     }
 
-    c = pa_msgobject_new(connection, connection_check_type);
+    c = pa_msgobject_new(connection);
     c->parent.parent.free = connection_free;
     c->parent.process_msg = connection_process_msg;
     c->io = io;
@@ -547,7 +550,6 @@ static void on_connection(pa_socket_server*s, pa_iochannel *io, void *userdata)
         pa_source_output_put(c->source_output);
     }
 
-
     pa_iochannel_set_callback(c->io, io_callback, c);
     pa_idxset_put(p->connections, c, NULL);
 
@@ -555,7 +557,7 @@ static void on_connection(pa_socket_server*s, pa_iochannel *io, void *userdata)
 
 fail:
     if (c)
-        connection_drop(c);
+        connection_unlink(c);
 }
 
 pa_protocol_simple* pa_protocol_simple_new(pa_core *core, pa_socket_server *server, pa_module *m, pa_modargs *ma) {
@@ -618,7 +620,7 @@ void pa_protocol_simple_free(pa_protocol_simple *p) {
 
     if (p->connections) {
         while((c = pa_idxset_first(p->connections, NULL)))
-            connection_drop(c);
+            connection_unlink(c);
 
         pa_idxset_free(p->connections, NULL, NULL);
     }
diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c
index e4e931f..0a7033d 100644
--- a/src/pulsecore/sink-input.c
+++ b/src/pulsecore/sink-input.c
@@ -45,7 +45,7 @@
 #define MOVE_BUFFER_LENGTH (1024*1024)
 #define SILENCE_BUFFER_LENGTH (64*1024)
 
-static PA_DEFINE_CHECK_TYPE(pa_sink_input, sink_input_check_type, pa_msgobject_check_type);
+static PA_DEFINE_CHECK_TYPE(pa_sink_input, pa_msgobject);
 
 static void sink_input_free(pa_object *o);
 
@@ -110,6 +110,7 @@ pa_sink_input* pa_sink_input_new(
 
     pa_return_null_if_fail(data->sink);
     pa_return_null_if_fail(pa_sink_get_state(data->sink) != PA_SINK_DISCONNECTED);
+    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;
@@ -161,12 +162,12 @@ pa_sink_input* pa_sink_input_new(
         data->resample_method = pa_resampler_get_method(resampler);
     }
 
-    i = pa_msgobject_new(pa_sink_input, sink_input_check_type);
+    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_RUNNING;
+    i->state = data->start_corked ? PA_SINK_INPUT_CORKED : PA_SINK_INPUT_RUNNING;
     i->flags = flags;
     i->name = pa_xstrdup(data->name);
     i->driver = pa_xstrdup(data->driver);
@@ -181,6 +182,16 @@ pa_sink_input* pa_sink_input_new(
     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;
@@ -213,6 +224,7 @@ pa_sink_input* pa_sink_input_new(
 }
 
 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)
@@ -221,10 +233,15 @@ static int sink_input_set_state(pa_sink_input *i, pa_sink_input_state_t state) {
     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), NULL) < 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;
 
     i->state = state;
+    for (ssync = i->sync_prev; ssync; ssync = ssync->sync_prev)
+        ssync->state = state;
+    for (ssync = i->sync_next; ssync; ssync = ssync->sync_next)
+        ssync->state = state;
+    
     return 0;
 }
 
@@ -232,10 +249,16 @@ void pa_sink_input_disconnect(pa_sink_input *i) {
     pa_assert(i);
     pa_return_if_fail(i->state != PA_SINK_INPUT_DISCONNECTED);
 
-    pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i->sink), PA_SINK_MESSAGE_REMOVE_INPUT, i, NULL);
+    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_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i->sink), PA_SINK_MESSAGE_REMOVE_INPUT, i, 0, NULL);
     pa_idxset_remove_by_data(i->sink->core->sink_inputs, i, NULL);
     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);
 
@@ -248,6 +271,7 @@ void pa_sink_input_disconnect(pa_sink_input *i) {
     i->kill = NULL;
     i->get_latency = NULL;
     i->underrun = NULL;
+    pa_sink_input_unref(i);
 }
 
 static void sink_input_free(pa_object *o) {
@@ -281,7 +305,7 @@ void pa_sink_input_put(pa_sink_input *i) {
     i->thread_info.volume = i->volume;
     i->thread_info.muted = i->muted;
 
-    pa_asyncmsgq_post(i->sink->asyncmsgq, PA_MSGOBJECT(i->sink), PA_SINK_MESSAGE_ADD_INPUT, pa_sink_input_ref(i), NULL, (pa_free_cb_t) pa_sink_input_unref);
+    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);
@@ -299,7 +323,7 @@ pa_usec_t pa_sink_input_get_latency(pa_sink_input *i) {
 
     pa_sink_input_assert_ref(i);
 
-    if (pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_GET_LATENCY, &r, NULL) < 0)
+    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)
@@ -509,7 +533,7 @@ void pa_sink_input_set_volume(pa_sink_input *i, const pa_cvolume *volume) {
 
     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), NULL, pa_xfree);
+    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);
 }
 
@@ -528,7 +552,7 @@ void pa_sink_input_set_mute(pa_sink_input *i, int mute) {
 
     i->muted = mute;
 
-    pa_asyncmsgq_post(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_SET_MUTE, PA_UINT_TO_PTR(mute), NULL, NULL);
+    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);
 }
 
@@ -553,7 +577,7 @@ int pa_sink_input_set_rate(pa_sink_input *i, uint32_t rate) {
 
     i->sample_spec.rate = rate;
 
-    pa_asyncmsgq_post(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_SET_RATE, PA_UINT_TO_PTR(rate), NULL, NULL);
+    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;
@@ -741,7 +765,7 @@ int pa_sink_input_move_to(pa_sink_input *i, pa_sink *dest, int immediately) {
 /*     return 0; */
 }
 
-int pa_sink_input_process_msg(pa_msgobject *o, int code, void *userdata, pa_memchunk *chunk) {
+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);
@@ -776,12 +800,28 @@ int pa_sink_input_process_msg(pa_msgobject *o, int code, void *userdata, pa_memc
         }
 
         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;
         }
     }
diff --git a/src/pulsecore/sink-input.h b/src/pulsecore/sink-input.h
index fe62917..af3db95 100644
--- a/src/pulsecore/sink-input.h
+++ b/src/pulsecore/sink-input.h
@@ -71,6 +71,8 @@ struct pa_sink_input {
     pa_sample_spec sample_spec;
     pa_channel_map channel_map;
 
+    pa_sink_input *sync_prev, *sync_next;
+    
     pa_cvolume volume;
     int muted;
 
@@ -97,6 +99,8 @@ struct pa_sink_input {
         /*         size_t move_silence; */
         pa_memblock *silence_memblock;               /* may be NULL */
 
+        pa_sink_input *sync_prev, *sync_next;
+        
         pa_cvolume volume;
         int muted;
     } thread_info;
@@ -133,6 +137,9 @@ typedef struct pa_sink_input_new_data {
     int muted_is_set;
 
     pa_resample_method_t resample_method;
+
+    int start_corked;
+    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);
@@ -179,6 +186,6 @@ pa_sink_input_state_t pa_sink_input_get_state(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, size_t length);
-int pa_sink_input_process_msg(pa_msgobject *o, int code, void *userdata, pa_memchunk *chunk);
+int pa_sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offset, pa_memchunk *chunk);
 
 #endif
diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c
index 7f2a8b3..5ab01cb 100644
--- a/src/pulsecore/sink.c
+++ b/src/pulsecore/sink.c
@@ -48,7 +48,7 @@
 #define MAX_MIX_CHANNELS 32
 #define SILENCE_BUFFER_LENGTH (64*1024)
 
-static PA_DEFINE_CHECK_TYPE(pa_sink, sink_check_type, pa_msgobject_check_type);
+static PA_DEFINE_CHECK_TYPE(pa_sink, pa_msgobject);
 
 static void sink_free(pa_object *s);
 
@@ -80,7 +80,7 @@ pa_sink* pa_sink_new(
     pa_return_null_if_fail(!driver || pa_utf8_valid(driver));
     pa_return_null_if_fail(name && pa_utf8_valid(name) && *name);
 
-    s = pa_msgobject_new(pa_sink, sink_check_type);
+    s = pa_msgobject_new(pa_sink);
 
     if (!(name = pa_namereg_register(core, name, PA_NAMEREG_SINK, s, fail))) {
         pa_xfree(s);
@@ -161,7 +161,7 @@ static int sink_set_state(pa_sink *s, pa_sink_state_t 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), NULL) < 0)
+    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;
@@ -264,7 +264,7 @@ int pa_sink_suspend(pa_sink *s, int suspend) {
 void pa_sink_ping(pa_sink *s) {
     pa_sink_assert_ref(s);
 
-    pa_asyncmsgq_post(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_PING, NULL, NULL, NULL);
+    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) {
@@ -530,7 +530,7 @@ pa_usec_t pa_sink_get_latency(pa_sink *s) {
     if (s->get_latency)
         return s->get_latency(s);
 
-    if (pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_GET_LATENCY, &usec, NULL) < 0)
+    if (pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_GET_LATENCY, &usec, 0, NULL) < 0)
         return 0;
 
     return usec;
@@ -549,7 +549,7 @@ void pa_sink_set_volume(pa_sink *s, const pa_cvolume *volume) {
         s->set_volume = NULL;
 
     if (!s->set_volume)
-        pa_asyncmsgq_post(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_SET_VOLUME, pa_xnewdup(struct pa_cvolume, volume, 1), NULL, pa_xfree);
+        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);
@@ -566,7 +566,7 @@ const pa_cvolume *pa_sink_get_volume(pa_sink *s) {
         s->get_volume = NULL;
 
     if (!s->get_volume && s->refresh_volume)
-        pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_GET_VOLUME, &s->volume, NULL);
+        pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_GET_VOLUME, &s->volume, 0, NULL);
 
     if (!pa_cvolume_equal(&old_volume, &s->volume))
         pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
@@ -585,7 +585,7 @@ void pa_sink_set_mute(pa_sink *s, int mute) {
         s->set_mute = NULL;
 
     if (!s->set_mute)
-        pa_asyncmsgq_post(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_SET_MUTE, PA_UINT_TO_PTR(mute), NULL, NULL);
+        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);
@@ -602,7 +602,7 @@ int pa_sink_get_mute(pa_sink *s) {
         s->get_mute = NULL;
 
     if (!s->get_mute && s->refresh_mute)
-        pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_GET_MUTE, &s->muted, NULL);
+        pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_GET_MUTE, &s->muted, 0, NULL);
 
     if (old_muted != s->muted)
         pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
@@ -660,21 +660,58 @@ unsigned pa_sink_used_by(pa_sink *s) {
     return ret;
 }
 
-int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, pa_memchunk *chunk) {
+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);
 
     switch ((pa_sink_message_t) code) {
+        
         case PA_SINK_MESSAGE_ADD_INPUT: {
             pa_sink_input *i = 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;
+            }
+
             return 0;
         }
 
         case PA_SINK_MESSAGE_REMOVE_INPUT: {
             pa_sink_input *i = userdata;
+
+            /* Since the caller sleeps in pa_sink_input_disconnect(),
+             * 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;
         }
 
@@ -698,6 +735,7 @@ int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, pa_memchunk *
             return 0;
 
         case PA_SINK_MESSAGE_SET_STATE:
+            
             s->thread_info.state = PA_PTR_TO_UINT(userdata);
             return 0;
 
diff --git a/src/pulsecore/sink.h b/src/pulsecore/sink.h
index 958279c..494bb6a 100644
--- a/src/pulsecore/sink.h
+++ b/src/pulsecore/sink.h
@@ -156,7 +156,7 @@ 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);
 
-int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, pa_memchunk *chunk);
+int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offset, pa_memchunk *chunk);
 
 static inline int PA_SINK_OPENED(pa_sink_state_t x) {
     return x == PA_SINK_RUNNING || x == PA_SINK_IDLE;
diff --git a/src/pulsecore/sound-file-stream.c b/src/pulsecore/sound-file-stream.c
index 946af3e..f2204f2 100644
--- a/src/pulsecore/sound-file-stream.c
+++ b/src/pulsecore/sound-file-stream.c
@@ -56,7 +56,7 @@ enum {
 
 PA_DECLARE_CLASS(file_stream);
 #define FILE_STREAM(o) (file_stream_cast(o))
-static PA_DEFINE_CHECK_TYPE(file_stream, file_stream_check_type, pa_msgobject_check_type);
+static PA_DEFINE_CHECK_TYPE(file_stream, pa_msgobject);
 
 static void file_stream_free(pa_object *o) {
     file_stream *u = FILE_STREAM(o);
@@ -85,7 +85,7 @@ static void file_stream_drop(file_stream *u) {
     }
 }
 
-static int file_stream_process_msg(pa_msgobject *o, int code, void*userdata, pa_memchunk *chunk) {
+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);
     
@@ -154,7 +154,7 @@ static int sink_input_peek_cb(pa_sink_input *i, pa_memchunk *chunk) {
                 pa_memblock_unref(u->memchunk.memblock);
                 pa_memchunk_reset(&u->memchunk);
                 
-                pa_asyncmsgq_post(u->core->asyncmsgq, PA_MSGOBJECT(u), MESSAGE_DROP_FILE_STREAM, NULL, NULL, NULL);
+                pa_asyncmsgq_post(u->core->asyncmsgq, PA_MSGOBJECT(u), MESSAGE_DROP_FILE_STREAM, NULL, 0, NULL, NULL);
 
                 sf_close(u->sndfile);
                 u->sndfile = NULL;
@@ -224,7 +224,7 @@ int pa_play_file(
     pa_assert(sink);
     pa_assert(fname);
 
-    u = pa_msgobject_new(file_stream, file_stream_check_type);
+    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;
diff --git a/src/pulsecore/source-output.c b/src/pulsecore/source-output.c
index ee76a6e..c3ecf3a 100644
--- a/src/pulsecore/source-output.c
+++ b/src/pulsecore/source-output.c
@@ -38,7 +38,7 @@
 
 #include "source-output.h"
 
-static PA_DEFINE_CHECK_TYPE(pa_source_output, source_output_check_type, pa_msgobject_check_type);
+static PA_DEFINE_CHECK_TYPE(pa_source_output, pa_msgobject);
 
 static void source_output_free(pa_object* mo);
 
@@ -130,12 +130,12 @@ pa_source_output* pa_source_output_new(
         data->resample_method = pa_resampler_get_method(resampler);
     }
 
-    o = pa_msgobject_new(pa_source_output, source_output_check_type);
+    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_RUNNING;
+    o->state = data->corked ? PA_SOURCE_OUTPUT_CORKED : PA_SOURCE_OUTPUT_RUNNING;
     o->flags = flags;
     o->name = pa_xstrdup(data->name);
     o->driver = pa_xstrdup(data->driver);
@@ -176,7 +176,7 @@ static int source_output_set_state(pa_source_output *o, pa_source_output_state_t
     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), NULL) < 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;
 
     o->state = state;
@@ -187,7 +187,7 @@ void pa_source_output_disconnect(pa_source_output*o) {
     pa_assert(o);
     pa_return_if_fail(o->state != PA_SOURCE_OUTPUT_DISCONNECTED);
 
-    pa_asyncmsgq_send(o->source->asyncmsgq, PA_MSGOBJECT(o->source), PA_SOURCE_MESSAGE_REMOVE_OUTPUT, o, NULL);
+    pa_asyncmsgq_send(o->source->asyncmsgq, PA_MSGOBJECT(o->source), PA_SOURCE_MESSAGE_REMOVE_OUTPUT, o, 0, NULL);
 
     pa_idxset_remove_by_data(o->source->core->source_outputs, o, NULL);
     pa_idxset_remove_by_data(o->source->outputs, o, NULL);
@@ -225,7 +225,7 @@ static void source_output_free(pa_object* mo) {
 void pa_source_output_put(pa_source_output *o) {
     pa_source_output_assert_ref(o);
 
-    pa_asyncmsgq_post(o->source->asyncmsgq, PA_MSGOBJECT(o->source), PA_SOURCE_MESSAGE_ADD_OUTPUT, pa_source_output_ref(o), NULL, (pa_free_cb_t) pa_source_output_unref);
+    pa_asyncmsgq_post(o->source->asyncmsgq, PA_MSGOBJECT(o->source), PA_SOURCE_MESSAGE_ADD_OUTPUT, pa_source_output_ref(o), 0, NULL, (pa_free_cb_t) pa_source_output_unref);
     pa_source_update_status(o->source);
 
     pa_subscription_post(o->source->core, PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_NEW, o->index);
@@ -243,7 +243,7 @@ pa_usec_t pa_source_output_get_latency(pa_source_output *o) {
 
     pa_source_output_assert_ref(o);
 
-    if (pa_asyncmsgq_send(o->source->asyncmsgq, PA_MSGOBJECT(o), PA_SOURCE_OUTPUT_MESSAGE_GET_LATENCY, &r, NULL) < 0)
+    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)
@@ -293,7 +293,7 @@ int pa_source_output_set_rate(pa_source_output *o, uint32_t rate) {
 
     o->sample_spec.rate = rate;
 
-    pa_asyncmsgq_post(o->source->asyncmsgq, PA_MSGOBJECT(o), PA_SOURCE_OUTPUT_MESSAGE_SET_RATE, PA_UINT_TO_PTR(rate), NULL, NULL);
+    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;
@@ -380,7 +380,7 @@ int pa_source_output_move_to(pa_source_output *o, pa_source *dest) {
 /*     return 0; */
 }
 
-int pa_source_output_process_msg(pa_msgobject *mo, int code, void *userdata, pa_memchunk* chunk) {
+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);
diff --git a/src/pulsecore/source-output.h b/src/pulsecore/source-output.h
index 7b6afe8..9f982a9 100644
--- a/src/pulsecore/source-output.h
+++ b/src/pulsecore/source-output.h
@@ -103,6 +103,8 @@ typedef struct pa_source_output_new_data {
     int channel_map_is_set;
 
     pa_resample_method_t resample_method;
+
+    int corked;
 } pa_source_output_new_data;
 
 pa_source_output_new_data* pa_source_output_new_data_init(pa_source_output_new_data *data);
@@ -142,6 +144,6 @@ int pa_source_output_move_to(pa_source_output *o, pa_source *dest);
 /* 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, pa_memchunk *chunk);
+int pa_source_output_process_msg(pa_msgobject *mo, int code, void *userdata, int64_t offset, pa_memchunk *chunk);
 
 #endif
diff --git a/src/pulsecore/source.c b/src/pulsecore/source.c
index 6ca8172..eaf1335 100644
--- a/src/pulsecore/source.c
+++ b/src/pulsecore/source.c
@@ -42,7 +42,7 @@
 
 #include "source.h"
 
-static PA_DEFINE_CHECK_TYPE(pa_source, source_check_type, pa_msgobject_check_type);
+static PA_DEFINE_CHECK_TYPE(pa_source, pa_msgobject);
 
 static void source_free(pa_object *o);
 
@@ -73,7 +73,7 @@ pa_source* pa_source_new(
     pa_return_null_if_fail(!driver || pa_utf8_valid(driver));
     pa_return_null_if_fail(pa_utf8_valid(name) && *name);
 
-    s = pa_msgobject_new(pa_source, source_check_type);
+    s = pa_msgobject_new(pa_source);
 
     if (!(name = pa_namereg_register(core, name, PA_NAMEREG_SOURCE, s, fail))) {
         pa_xfree(s);
@@ -140,7 +140,7 @@ static int source_set_state(pa_source *s, pa_source_state_t 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), NULL) < 0)
+    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;
@@ -222,7 +222,7 @@ int pa_source_suspend(pa_source *s, int suspend) {
 void pa_source_ping(pa_source *s) {
     pa_source_assert_ref(s);
 
-    pa_asyncmsgq_post(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_PING, NULL, NULL, NULL);
+    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) {
@@ -266,7 +266,7 @@ pa_usec_t pa_source_get_latency(pa_source *s) {
     if (s->get_latency)
         return s->get_latency(s);
 
-    if (pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_GET_LATENCY, &usec, NULL) < 0)
+    if (pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_GET_LATENCY, &usec, 0, NULL) < 0)
         return 0;
 
     return usec;
@@ -285,7 +285,7 @@ void pa_source_set_volume(pa_source *s, const pa_cvolume *volume) {
         s->set_volume = NULL;
 
     if (!s->set_volume)
-        pa_asyncmsgq_post(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_SET_VOLUME, pa_xnewdup(struct pa_cvolume, volume, 1), NULL, pa_xfree);
+        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 (changed)
         pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
@@ -301,7 +301,7 @@ const pa_cvolume *pa_source_get_volume(pa_source *s) {
         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, NULL);
+        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);
@@ -320,7 +320,7 @@ void pa_source_set_mute(pa_source *s, int mute) {
         s->set_mute = NULL;
 
     if (!s->set_mute)
-        pa_asyncmsgq_post(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_SET_MUTE, PA_UINT_TO_PTR(mute), NULL, NULL);
+        pa_asyncmsgq_post(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_SET_MUTE, PA_UINT_TO_PTR(mute), 0, NULL, NULL);
 
     if (changed)
         pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
@@ -337,7 +337,7 @@ int pa_source_get_mute(pa_source *s) {
         s->get_mute = NULL;
 
     if (!s->get_mute && s->refresh_muted)
-        pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_GET_MUTE, &s->muted, NULL);
+        pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_GET_MUTE, &s->muted, 0, NULL);
 
     if (old_muted != s->muted)
         pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
@@ -384,7 +384,7 @@ unsigned pa_source_used_by(pa_source *s) {
     return pa_idxset_size(s->outputs);
 }
 
-int pa_source_process_msg(pa_msgobject *object, int code, void *userdata, pa_memchunk *chunk) {
+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);
 
diff --git a/src/pulsecore/source.h b/src/pulsecore/source.h
index e2b02ce..fe59e58 100644
--- a/src/pulsecore/source.h
+++ b/src/pulsecore/source.h
@@ -146,7 +146,7 @@ unsigned pa_source_used_by(pa_source *s);
 /* To be used exclusively by the source driver thread */
 
 void pa_source_post(pa_source*s, const pa_memchunk *b);
-int pa_source_process_msg(pa_msgobject *o, int code, void *userdata, pa_memchunk *chunk);
+int pa_source_process_msg(pa_msgobject *o, int code, void *userdata, int64_t, pa_memchunk *chunk);
 
 static inline int PA_SOURCE_OPENED(pa_source_state_t x) {
     return x == PA_SOURCE_RUNNING || x == PA_SOURCE_IDLE;
diff --git a/src/tests/asyncmsgq-test.c b/src/tests/asyncmsgq-test.c
index 847d5be..baf93a0 100644
--- a/src/tests/asyncmsgq-test.c
+++ b/src/tests/asyncmsgq-test.c
@@ -49,7 +49,7 @@ static void the_thread(void *_q) {
     do {
         int code = 0;
 
-        pa_assert_se(pa_asyncmsgq_get(q, NULL, &code, NULL, NULL, 1) == 0);
+        pa_assert_se(pa_asyncmsgq_get(q, NULL, &code, NULL, NULL, NULL, 1) == 0);
 
         switch (code) {
 
@@ -85,22 +85,22 @@ int main(int argc, char *argv[]) {
     pa_assert_se(t = pa_thread_new(the_thread, q));
 
     printf("Operation A post\n");
-    pa_asyncmsgq_post(q, NULL, OPERATION_A, NULL, NULL, NULL);
+    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, NULL, NULL);
+    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, NULL);
+    pa_asyncmsgq_send(q, NULL, OPERATION_C, NULL, 0, NULL);
 
     pa_thread_yield();
 
     printf("Quit post\n");
-    pa_asyncmsgq_post(q, NULL, QUIT, NULL, NULL, NULL);
+    pa_asyncmsgq_post(q, NULL, QUIT, NULL, 0, NULL, NULL);
 
     pa_thread_free(t);
 

commit d3eca287cfc177fc5084ddf72ccfdbe9bee23cae
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Jul 31 22:56:35 2007 +0000

    rename pa_source_output_new_data::corked to start_corked to match pa_sink_input_new_data::start_corked
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1563 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c
index 3be5eae..03f2708 100644
--- a/src/pulsecore/protocol-native.c
+++ b/src/pulsecore/protocol-native.c
@@ -443,7 +443,7 @@ static record_stream* record_stream_new(
     data.source = source;
     data.driver = __FILE__;
     data.name = name;
-    data.corked = corked;
+    data.start_corked = corked;
     pa_source_output_new_data_set_sample_spec(&data, ss);
     pa_source_output_new_data_set_channel_map(&data, map);
 
diff --git a/src/pulsecore/sink-input.h b/src/pulsecore/sink-input.h
index af3db95..0168805 100644
--- a/src/pulsecore/sink-input.h
+++ b/src/pulsecore/sink-input.h
@@ -131,6 +131,7 @@ typedef struct pa_sink_input_new_data {
     int sample_spec_is_set;
     pa_channel_map channel_map;
     int channel_map_is_set;
+    
     pa_cvolume volume;
     int volume_is_set;
     int muted;
diff --git a/src/pulsecore/source-output.c b/src/pulsecore/source-output.c
index c3ecf3a..9b828e1 100644
--- a/src/pulsecore/source-output.c
+++ b/src/pulsecore/source-output.c
@@ -135,7 +135,7 @@ pa_source_output* pa_source_output_new(
     o->parent.process_msg = pa_source_output_process_msg;
 
     o->core = core;
-    o->state = data->corked ? PA_SOURCE_OUTPUT_CORKED : PA_SOURCE_OUTPUT_RUNNING;
+    o->state = data->start_corked ? PA_SOURCE_OUTPUT_CORKED : PA_SOURCE_OUTPUT_RUNNING;
     o->flags = flags;
     o->name = pa_xstrdup(data->name);
     o->driver = pa_xstrdup(data->driver);
diff --git a/src/pulsecore/source-output.h b/src/pulsecore/source-output.h
index 9f982a9..47cc8c4 100644
--- a/src/pulsecore/source-output.h
+++ b/src/pulsecore/source-output.h
@@ -104,7 +104,7 @@ typedef struct pa_source_output_new_data {
 
     pa_resample_method_t resample_method;
 
-    int corked;
+    int start_corked;
 } pa_source_output_new_data;
 
 pa_source_output_new_data* pa_source_output_new_data_init(pa_source_output_new_data *data);

commit 9a4e84ade9b0d5978cd0649ed3adc0d5a94c2e3d
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Aug 3 22:39:18 2007 +0000

    On recommendation of Takashi Iwai prefer Master volume control over PCM and don't control Mic control
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1564 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-alsa-sink.c b/src/modules/module-alsa-sink.c
index 551bad8..9fd01e4 100644
--- a/src/modules/module-alsa-sink.c
+++ b/src/modules/module-alsa-sink.c
@@ -769,7 +769,7 @@ int pa__init(pa_core *c, pa_module*m) {
     else {
 
         if ((pa_alsa_prepare_mixer(u->mixer_handle, dev) < 0) ||
-            !(u->mixer_elem = pa_alsa_find_elem(u->mixer_handle, "PCM", "Master"))) {
+            !(u->mixer_elem = pa_alsa_find_elem(u->mixer_handle, "Master", "PCM"))) {
             
             snd_mixer_close(u->mixer_handle);
             u->mixer_handle = NULL;
diff --git a/src/modules/module-alsa-source.c b/src/modules/module-alsa-source.c
index c2dad6f..b2b0698 100644
--- a/src/modules/module-alsa-source.c
+++ b/src/modules/module-alsa-source.c
@@ -744,7 +744,7 @@ int pa__init(pa_core *c, pa_module*m) {
     else {
         
         if ((pa_alsa_prepare_mixer(u->mixer_handle, dev) < 0) ||
-            !(u->mixer_elem = pa_alsa_find_elem(u->mixer_handle, "Capture", "Mic"))) {
+            !(u->mixer_elem = pa_alsa_find_elem(u->mixer_handle, "Capture", NULL))) {
             snd_mixer_close(u->mixer_handle);
             u->mixer_handle = NULL;
         }

commit a6c44c0e508ede5c25ebac534642d93d101be21e
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Aug 3 22:41:27 2007 +0000

    Remove unnecessary snd_pcm_hwsync()
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1565 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-alsa-sink.c b/src/modules/module-alsa-sink.c
index 9fd01e4..ced42ee 100644
--- a/src/modules/module-alsa-sink.c
+++ b/src/modules/module-alsa-sink.c
@@ -547,7 +547,6 @@ static void thread_func(void *userdata) {
             } else {
                 ssize_t l;
 
-                snd_pcm_hwsync(u->pcm_handle);
                 if ((err = snd_pcm_status(u->pcm_handle, status)) >= 0)
                     l = snd_pcm_status_get_avail(status) * u->frame_size;
                 else
diff --git a/src/modules/module-alsa-source.c b/src/modules/module-alsa-source.c
index b2b0698..0fd7bca 100644
--- a/src/modules/module-alsa-source.c
+++ b/src/modules/module-alsa-source.c
@@ -535,7 +535,6 @@ static void thread_func(void *userdata) {
             } else {
                 ssize_t l;
 
-                snd_pcm_hwsync(u->pcm_handle);
                 if ((err = snd_pcm_status(u->pcm_handle, status)) >= 0)
                     l = snd_pcm_status_get_avail(status) * u->frame_size;
                 else

commit 95fab184d5448bff9f262589390c7374fb1370c8
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Aug 3 23:48:52 2007 +0000

    Don't stop hardware on buffer underruns. Instead continue playing to guarantee that our time function stays as linear as possible.
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1566 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/alsa-util.c b/src/modules/alsa-util.c
index dd9ac79..dd063f3 100644
--- a/src/modules/alsa-util.c
+++ b/src/modules/alsa-util.c
@@ -289,10 +289,11 @@ int pa_alsa_set_hw_params(snd_pcm_t *pcm_handle, pa_sample_spec *ss, uint32_t *p
     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 ||
+    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;
 
@@ -355,12 +356,36 @@ int pa_alsa_set_hw_params(snd_pcm_t *pcm_handle, pa_sample_spec *ss, uint32_t *p
     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(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;
 
diff --git a/src/modules/alsa-util.h b/src/modules/alsa-util.h
index f79325c..6f1f927 100644
--- a/src/modules/alsa-util.h
+++ b/src/modules/alsa-util.h
@@ -39,6 +39,7 @@ 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_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);
diff --git a/src/modules/module-alsa-sink.c b/src/modules/module-alsa-sink.c
index ced42ee..5765d78 100644
--- a/src/modules/module-alsa-sink.c
+++ b/src/modules/module-alsa-sink.c
@@ -545,18 +545,23 @@ static void thread_func(void *userdata) {
                     goto fail;
 
             } else {
-                ssize_t l;
-
-                if ((err = snd_pcm_status(u->pcm_handle, status)) >= 0)
-                    l = snd_pcm_status_get_avail(status) * u->frame_size;
-                else
-                    l = u->fragment_size;
-
-                while (l > 0) {
+                for (;;) {
                     void *p;
                     snd_pcm_sframes_t t;
+                    ssize_t l;
+                
+                    if ((err = snd_pcm_status(u->pcm_handle, status)) < 0) {
+                        pa_log("Failed to query DSP status data: %s", snd_strerror(t));
+                        goto fail;
+                    }
 
-                    pa_assert(l > 0);
+                    if (snd_pcm_status_get_avail_max(status)*u->frame_size >= u->hwbuf_size)
+                        pa_log_debug("Buffer underrun!");
+                    
+                    l = snd_pcm_status_get_avail(status) * u->frame_size;
+
+                    if (l <= 0)
+                        break;
                     
                     if (u->memchunk.length <= 0)
                         pa_sink_render(u->sink, l, &u->memchunk);
@@ -573,10 +578,7 @@ static void thread_func(void *userdata) {
                     
                     if (t < 0) {
 
-                        if (t == -EPIPE) {
-                            pa_log_debug("Buffer underrun!");
-                            u->first = 1;
-                        }
+                        pa_assert(t != -EPIPE);
                         
                         if ((t = snd_pcm_recover(u->pcm_handle, t, 1)) == 0)
                             continue;
@@ -588,21 +590,20 @@ static void thread_func(void *userdata) {
                             pa_log("Failed to write data to DSP: %s", snd_strerror(t));
                             goto fail;
                         }
+                    }
                         
-                    } else {
-                        
-                        u->memchunk.index += t * u->frame_size;
-                        u->memchunk.length -= t * u->frame_size;
-                        
-                        if (u->memchunk.length <= 0) {
-                            pa_memblock_unref(u->memchunk.memblock);
-                            pa_memchunk_reset(&u->memchunk);
-                        }
-                        
-                        l -= t * u->frame_size;
-
-                        work_done = 1;
+                    u->memchunk.index += t * u->frame_size;
+                    u->memchunk.length -= t * u->frame_size;
+                    
+                    if (u->memchunk.length <= 0) {
+                        pa_memblock_unref(u->memchunk.memblock);
+                        pa_memchunk_reset(&u->memchunk);
                     }
+
+                    work_done = 1;
+
+                    if (t * u->frame_size >= (unsigned) l)
+                        break;
                 } 
             }
 
@@ -756,6 +757,11 @@ int pa__init(pa_core *c, pa_module*m) {
     if (u->use_mmap)
         pa_log_info("Successfully enabled mmap() mode.");
 
+    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);
 
diff --git a/src/modules/module-alsa-source.c b/src/modules/module-alsa-source.c
index 0fd7bca..9a5d5ac 100644
--- a/src/modules/module-alsa-source.c
+++ b/src/modules/module-alsa-source.c
@@ -533,19 +533,25 @@ static void thread_func(void *userdata) {
                     goto fail;
 
             } else {
-                ssize_t l;
 
-                if ((err = snd_pcm_status(u->pcm_handle, status)) >= 0)
-                    l = snd_pcm_status_get_avail(status) * u->frame_size;
-                else
-                    l = u->fragment_size;
-
-                while (l > 0) {
+                for (;;) {
                     void *p;
                     snd_pcm_sframes_t t;
+                    ssize_t l;
 
-                    pa_assert(l > 0);
+                    if ((err = snd_pcm_status(u->pcm_handle, status)) < 0) {
+                        pa_log("Failed to query DSP status data: %s", snd_strerror(t));
+                        goto fail;
+                    }
 
+                    if (snd_pcm_status_get_avail_max(status)*u->frame_size >= u->hwbuf_size)
+                        pa_log_debug("Buffer overrun!");
+                    
+                    l = snd_pcm_status_get_avail(status) * u->frame_size;
+
+                    if (l <= 0)
+                        break;
+                    
                     chunk.memblock = pa_memblock_new(u->core->mempool, l);
 
                     p = pa_memblock_acquire(chunk.memblock);
@@ -559,8 +565,7 @@ static void thread_func(void *userdata) {
                     if (t < 0) {
                         pa_memblock_unref(chunk.memblock);
 
-                        if (t == -EPIPE)
-                            pa_log_debug("Buffer underrun!");
+                        pa_assert(t != -EPIPE);
                         
                         if ((t = snd_pcm_recover(u->pcm_handle, t, 1)) == 0)
                             continue;
@@ -573,18 +578,18 @@ static void thread_func(void *userdata) {
                             goto fail;
                         }
                         
-                    } else {
+                    } 
                         
-                        chunk.index = 0;
-                        chunk.length = t * u->frame_size;
+                    chunk.index = 0;
+                    chunk.length = t * u->frame_size;
 
-                        pa_source_post(u->source, &chunk);
-                        pa_memblock_unref(chunk.memblock);
-                        
-                        l -= t * u->frame_size;
+                    pa_source_post(u->source, &chunk);
+                    pa_memblock_unref(chunk.memblock);
+                    
+                    work_done = 1;
 
-                        work_done = 1;
-                    }
+                    if (t * u->frame_size >= (unsigned) l)
+                        break;
                 } 
             }
 
@@ -730,6 +735,11 @@ int pa__init(pa_core *c, pa_module*m) {
 
     if (u->use_mmap)
         pa_log_info("Successfully enabled mmap() mode.");
+
+    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);

commit 81760ad897f309e07ba7edc7f6d0ed6a3a71af9b
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sat Aug 4 20:20:33 2007 +0000

    merge compat changes from trunk
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1569 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/configure.ac b/configure.ac
index 9a1e6c5..89fcb06 100644
--- a/configure.ac
+++ b/configure.ac
@@ -67,6 +67,7 @@ esac
 # CC
 
 AC_PROG_CC
+AM_PROG_CC_C_O
 AC_PROG_GCC_TRADITIONAL
 AC_GNU_SOURCE
 
diff --git a/src/Makefile.am b/src/Makefile.am
index 4083ea5..8fc0f19 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1267,12 +1267,12 @@ module_rtp_recv_la_CFLAGS = $(AM_CFLAGS)
 #module_jack_sink_la_SOURCES = modules/module-jack-sink.c
 #module_jack_sink_la_LDFLAGS = -module -avoid-version
 #module_jack_sink_la_LIBADD = $(AM_LIBADD) libpulsecore.la $(JACK_LIBS)
-#module_jack_sink_la_CFLAGS = $(AM_LIBADD) $(JACK_CFLAGS)
+#module_jack_sink_la_CFLAGS = $(AM_CFLAGS) $(JACK_CFLAGS)
 
 #module_jack_source_la_SOURCES = modules/module-jack-source.c
 #module_jack_source_la_LDFLAGS = -module -avoid-version
 #module_jack_source_la_LIBADD = $(AM_LIBADD) libpulsecore.la $(JACK_LIBS)
-#module_jack_source_la_CFLAGS = $(AM_LIBADD) $(JACK_CFLAGS)
+#module_jack_source_la_CFLAGS = $(AM_CFLAGS) $(JACK_CFLAGS)
 
 # HAL
 libdbus_util_la_SOURCES = modules/dbus-util.c modules/dbus-util.h

commit 34e41657e714dcd7f862f5cb4776dfb9f9cc2e5c
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sun Aug 5 00:06:35 2007 +0000

    minor cleanups
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1570 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/sound-file-stream.c b/src/pulsecore/sound-file-stream.c
index f2204f2..433a73b 100644
--- a/src/pulsecore/sound-file-stream.c
+++ b/src/pulsecore/sound-file-stream.c
@@ -40,6 +40,8 @@
 
 #define BUF_SIZE (1024*10)
 
+/* FIXME: file access needs to be moved to seperate thread */
+
 typedef struct file_stream {
     pa_msgobject parent;
     pa_core *core;
@@ -58,10 +60,27 @@ 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_disconnect(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);
 
@@ -71,27 +90,13 @@ static void file_stream_free(pa_object *o) {
     pa_xfree(u);
 }
 
-static void file_stream_drop(file_stream *u) {
-    file_stream_assert_ref(u);
-
-    if (u->sink_input) {
-        pa_sink_input_disconnect(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 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 MESSAGE_DROP_FILE_STREAM:
-            file_stream_drop(u);
+            file_stream_unlink(u);
             break;
     }
 
@@ -99,9 +104,9 @@ static int file_stream_process_msg(pa_msgobject *o, int code, void*userdata, int
 }
 
 static void sink_input_kill_cb(pa_sink_input *i) {
-    pa_assert(i);
+    pa_sink_input_assert_ref(i);
     
-    file_stream_drop(FILE_STREAM(i->userdata));
+    file_stream_unlink(FILE_STREAM(i->userdata));
 }
 
 static int sink_input_peek_cb(pa_sink_input *i, pa_memchunk *chunk) {

commit 36dd7819da1615ee96b2343246bc7007211a7d0e
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sun Aug 5 00:07:07 2007 +0000

    modernize play-memchunk and port it to the new core
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1571 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/play-memchunk.c b/src/pulsecore/play-memchunk.c
index 7e750ba..a5ba949 100644
--- a/src/pulsecore/play-memchunk.c
+++ b/src/pulsecore/play-memchunk.c
@@ -26,7 +26,6 @@
 #endif
 
 #include <stdlib.h>
-#include <assert.h>
 #include <stdio.h>
 #include <string.h>
 
@@ -37,51 +36,105 @@
 
 #include "play-memchunk.h"
 
-static void sink_input_kill_cb(pa_sink_input *i) {
-    pa_memchunk *c;
-    assert(i && i->userdata);
-    c = i->userdata;
-
-    pa_sink_input_disconnect(i);
-    pa_sink_input_unref(i);
-
-    pa_memblock_unref(c->memblock);
-    pa_xfree(c);
+typedef struct memchunk_stream {
+    pa_msgobject parent;
+    pa_core *core;
+    pa_sink_input *sink_input;
+    pa_memchunk memchunk;
+} memchunk_stream;
+
+enum {
+    MEMCHUNK_STREAM_MESSAGE_UNLINK,
+};
+
+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_disconnect(u->sink_input);
+    
+    pa_sink_input_unref(u->sink_input);
+    u->sink_input = NULL;
+    
+    /* Make sure we don't decrease the ref count twice. */
+    memchunk_stream_unref(u);
 }
 
-static int sink_input_peek_cb(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);
+}
 
-    assert(c->memblock);
-    *chunk = *c;
-    pa_memblock_ref(c->memblock);
+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);
+    
+    switch (code) {
+        case MEMCHUNK_STREAM_MESSAGE_UNLINK:
+            memchunk_stream_unlink(u);
+            break;
+    }
 
     return 0;
 }
 
-static void si_kill_cb(PA_GCC_UNUSED pa_mainloop_api *m, void *i) {
-    sink_input_kill_cb(i);
-}
+static void sink_input_kill_cb(pa_sink_input *i) {
+    pa_sink_input_assert_ref(i);
 
-static void sink_input_drop_cb(pa_sink_input *i, size_t length) {
-    pa_memchunk *c;
-    assert(i && length && i->userdata);
-    c = i->userdata;
+    memchunk_stream_unlink(MEMCHUNK_STREAM(i->userdata));
+}
 
-    if (length >= c->length) {
-        c->length -= length;
-        c->index += length;
-    } else {
+static int sink_input_peek_cb(pa_sink_input *i, pa_memchunk *chunk) {
+    memchunk_stream *u;
 
-        c->length = 0;
+    pa_assert(i);
+    pa_assert(chunk);
+    u = MEMCHUNK_STREAM(i->userdata);
+    memchunk_stream_assert_ref(u);
 
-        pa_mainloop_api_once(i->sink->core->mainloop, si_kill_cb, i);
+    if (!u->memchunk.memblock)
+        return -1;
+    
+    if (u->memchunk.length <= 0) {
+        pa_memblock_unref(u->memchunk.memblock);
+        u->memchunk.memblock = NULL;
+        pa_asyncmsgq_post(u->core->asyncmsgq, PA_MSGOBJECT(u), MEMCHUNK_STREAM_MESSAGE_UNLINK, NULL, 0, NULL, NULL);
+        return -1;
     }
+
+    pa_assert(u->memchunk.memblock);
+    *chunk = u->memchunk;
+    pa_memblock_ref(chunk->memblock);
+
+    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(
@@ -92,36 +145,51 @@ 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;
 
+    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->sink_input = NULL;
+    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;
+    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;
 
-    si->peek = sink_input_peek_cb;
-    si->drop = sink_input_drop_cb;
-    si->kill = sink_input_kill_cb;
+    pa_sink_input_put(u->sink_input);
 
-    si->userdata = nchunk = pa_xnew(pa_memchunk, 1);
-    *nchunk = *chunk;
+    /* The reference to u is dangling here, because we want to keep
+     * this stream around until it is fully played. */
+    
+    return 0;
 
-    pa_memblock_ref(chunk->memblock);
+fail:
+    if (u)
+        memchunk_stream_unref(u);
 
-    return 0;
+    return -1;
 }
+

commit 23d01bb75db12ceaa263fa830b74cf8669ef2dd9
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sun Aug 5 00:07:58 2007 +0000

    Modernize pstream.[ch], reintroduce defer event to make things actually work
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1572 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/pstream.c b/src/pulsecore/pstream.c
index f4aab1c..0ffa583 100644
--- a/src/pulsecore/pstream.c
+++ b/src/pulsecore/pstream.c
@@ -28,7 +28,6 @@
 
 #include <stdio.h>
 #include <stdlib.h>
-#include <assert.h>
 #include <unistd.h>
 
 #ifdef HAVE_SYS_SOCKET_H
@@ -168,8 +167,8 @@ 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);
 
@@ -191,31 +190,42 @@ static void do_something(pa_pstream *p) {
 
 fail:
 
-    p->dead = 1;
-
     if (p->die_callback)
         p->die_callback(p, p->die_callback_userdata);
 
+    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);
 }
 
+static void defer_callback(pa_mainloop_api *m, pa_defer_event *e, void*userdata) {
+    pa_pstream *p = userdata;
+    
+    pa_assert(p);
+    pa_assert(PA_REFCNT_VALUE(p) > 0);
+    pa_assert(p->defer_event == e);
+    pa_assert(p->mainloop == m);
+    
+    do_something(p);
+}
+
 static void memimport_release_cb(pa_memimport *i, uint32_t block_id, void *userdata);
 
 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);
@@ -224,9 +234,11 @@ pa_pstream *pa_pstream_new(pa_mainloop_api *m, pa_iochannel *io, pa_mempool *poo
     p->dead = 0;
 
     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);
+    pa_assert(p->send_queue);
 
     p->write.current = NULL;
     p->write.index = 0;
@@ -264,13 +276,13 @@ pa_pstream *pa_pstream_new(pa_mainloop_api *m, pa_iochannel *io, pa_mempool *poo
 
 static void item_free(void *item, PA_GCC_UNUSED void *p) {
     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);
     }
 
@@ -278,9 +290,9 @@ static void item_free(void *item, PA_GCC_UNUSED void *p) {
 }
 
 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);
 
@@ -302,9 +314,9 @@ static void pstream_free(pa_pstream *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_assert(p);
+    pa_assert(PA_REFCNT_VALUE(p) > 0);
+    pa_assert(packet);
 
     if (p->dead)
         return;
@@ -319,15 +331,17 @@ 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);
 }
 
 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;
 
-    assert(p);
-    assert(PA_REFCNT_VALUE(p) > 0);
-    assert(channel != (uint32_t) -1);
-    assert(chunk);
+    pa_assert(p);
+    pa_assert(PA_REFCNT_VALUE(p) > 0);
+    pa_assert(channel != (uint32_t) -1);
+    pa_assert(chunk);
 
     if (p->dead)
         return;
@@ -366,8 +380,8 @@ static void memimport_release_cb(pa_memimport *i, uint32_t block_id, void *userd
     struct item_info *item;
     pa_pstream *p = userdata;
 
-    assert(p);
-    assert(PA_REFCNT_VALUE(p) > 0);
+    pa_assert(p);
+    pa_assert(PA_REFCNT_VALUE(p) > 0);
 
     if (p->dead)
         return;
@@ -382,14 +396,15 @@ static void memimport_release_cb(pa_memimport *i, uint32_t block_id, void *userd
 #endif
 
     pa_queue_push(p->send_queue, item);
+    p->mainloop->defer_enable(p->defer_event, 1);
 }
 
 static void memexport_revoke_cb(pa_memexport *e, uint32_t block_id, void *userdata) {
     struct item_info *item;
     pa_pstream *p = userdata;
 
-    assert(p);
-    assert(PA_REFCNT_VALUE(p) > 0);
+    pa_assert(p);
+    pa_assert(PA_REFCNT_VALUE(p) > 0);
 
     if (p->dead)
         return;
@@ -403,11 +418,12 @@ static void memexport_revoke_cb(pa_memexport *e, uint32_t block_id, void *userda
 #endif
 
     pa_queue_push(p->send_queue, item);
+    p->mainloop->defer_enable(p->defer_event, 1);
 }
 
 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);
 
     p->write.current = pa_queue_pop(p->send_queue);
 
@@ -426,7 +442,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);
 
@@ -444,8 +460,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));
@@ -457,7 +473,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,
@@ -503,8 +519,8 @@ static int do_write(pa_pstream *p) {
     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);
@@ -516,7 +532,7 @@ 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 || p->write.memchunk.memblock);
+        pa_assert(p->write.data || p->write.memchunk.memblock);
 
         if (p->write.data)
             d = p->write.data;
@@ -529,7 +545,7 @@ static int do_write(pa_pstream *p) {
         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) {
@@ -550,7 +566,7 @@ static int do_write(pa_pstream *p) {
     p->write.index += r;
 
     if (p->write.index >= PA_PSTREAM_DESCRIPTOR_SIZE + ntohl(p->write.descriptor[PA_PSTREAM_DESCRIPTOR_LENGTH])) {
-        assert(p->write.current);
+        pa_assert(p->write.current);
         item_free(p->write.current, (void *) 1);
         p->write.current = NULL;
 
@@ -573,14 +589,14 @@ static int do_read(pa_pstream *p) {
     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->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 || p->read.memblock);
+        pa_assert(p->read.data || p->read.memblock);
 
         if (p->read.data)
             d = p->read.data;
@@ -629,7 +645,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;
@@ -640,7 +656,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;
@@ -653,7 +669,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]);
 
@@ -757,9 +773,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]),
@@ -821,32 +837,32 @@ fail:
 }
 
 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);
 
     p->die_callback = cb;
     p->die_callback_userdata = userdata;
 }
 
 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);
 
     p->drain_callback = cb;
     p->drain_callback_userdata = userdata;
 }
 
 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);
 
     p->recieve_packet_callback = cb;
     p->recieve_packet_callback_userdata = userdata;
 }
 
 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);
 
     p->recieve_memblock_callback = cb;
     p->recieve_memblock_callback_userdata = userdata;
@@ -855,8 +871,8 @@ void pa_pstream_set_recieve_memblock_callback(pa_pstream *p, pa_pstream_memblock
 int pa_pstream_is_pending(pa_pstream *p) {
     int b;
 
-    assert(p);
-    assert(PA_REFCNT_VALUE(p) > 0);
+    pa_assert(p);
+    pa_assert(PA_REFCNT_VALUE(p) > 0);
 
     if (p->dead)
         b = 0;
@@ -867,24 +883,27 @@ int pa_pstream_is_pending(pa_pstream *p) {
 }
 
 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);
 
+    if (p->dead)
+        return;
+    
     p->dead = 1;
 
     if (p->import) {
@@ -902,6 +921,11 @@ void pa_pstream_close(pa_pstream *p) {
         p->io = NULL;
     }
 
+    if (p->defer_event) {
+        p->mainloop->defer_free(p->defer_event);
+        p->defer_event = NULL;
+    }    
+
     p->die_callback = NULL;
     p->drain_callback = NULL;
     p->recieve_packet_callback = NULL;
@@ -909,8 +933,8 @@ void pa_pstream_close(pa_pstream *p) {
 }
 
 void pa_pstream_use_shm(pa_pstream *p, int enable) {
-    assert(p);
-    assert(PA_REFCNT_VALUE(p) > 0);
+    pa_assert(p);
+    pa_assert(PA_REFCNT_VALUE(p) > 0);
 
     p->use_shm = enable;
 
diff --git a/src/pulsecore/pstream.h b/src/pulsecore/pstream.h
index 5900ece..544cba4 100644
--- a/src/pulsecore/pstream.h
+++ b/src/pulsecore/pstream.h
@@ -59,6 +59,6 @@ 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

commit 55e0866297fb1169a06b2cb6cc7188629b315ad0
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sun Aug 5 00:08:27 2007 +0000

    typesafe casts
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1573 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c
index 5ab01cb..150e4cb 100644
--- a/src/pulsecore/sink.c
+++ b/src/pulsecore/sink.c
@@ -667,7 +667,7 @@ int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offse
     switch ((pa_sink_message_t) code) {
         
         case PA_SINK_MESSAGE_ADD_INPUT: {
-            pa_sink_input *i = userdata;
+            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
@@ -690,7 +690,7 @@ int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offse
         }
 
         case PA_SINK_MESSAGE_REMOVE_INPUT: {
-            pa_sink_input *i = userdata;
+            pa_sink_input *i = PA_SINK_INPUT(userdata);
 
             /* Since the caller sleeps in pa_sink_input_disconnect(),
              * we can safely access data outside of thread_info even
diff --git a/src/pulsecore/source.c b/src/pulsecore/source.c
index eaf1335..241e1fb 100644
--- a/src/pulsecore/source.c
+++ b/src/pulsecore/source.c
@@ -390,13 +390,13 @@ int pa_source_process_msg(pa_msgobject *object, int code, void *userdata, int64_
 
     switch ((pa_source_message_t) code) {
         case PA_SOURCE_MESSAGE_ADD_OUTPUT: {
-            pa_source_output *o = userdata;
+            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));
             return 0;
         }
 
         case PA_SOURCE_MESSAGE_REMOVE_OUTPUT: {
-            pa_source_output *o = userdata;
+            pa_source_output *o = PA_SOURCE_OUTPUT(userdata);
             if (pa_hashmap_remove(s->thread_info.outputs, PA_UINT32_TO_PTR(o->index)))
                 pa_source_output_unref(o);
             

commit 241a9e10f15d8e20dc140cfdbd86b19b691f99ac
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sun Aug 5 00:09:02 2007 +0000

    follow rename of pstream_close() to pstream_unlink()
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1574 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulse/context.c b/src/pulse/context.c
index 0dba905..8125c64 100644
--- a/src/pulse/context.c
+++ b/src/pulse/context.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);
     }
 
@@ -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;

commit bd0782eb068bb6d5f407376fb79c689e157c371f
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sun Aug 5 00:09:48 2007 +0000

    initialize method pointers properly
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1575 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c
index 03f2708..2396a38 100644
--- a/src/pulsecore/protocol-native.c
+++ b/src/pulsecore/protocol-native.c
@@ -353,7 +353,7 @@ static upload_stream* upload_stream_new(
     pa_assert(length > 0);
 
     s = pa_msgobject_new(upload_stream);
-    c->parent.parent.free = upload_stream_free;
+    s->parent.parent.parent.free = upload_stream_free;
     s->connection = c;
     s->sample_spec = *ss;
     s->channel_map = *map;
@@ -451,8 +451,8 @@ static record_stream* record_stream_new(
         return NULL;
 
     s = pa_msgobject_new(record_stream);
-    c->parent.parent.free = record_stream_free;
-    c->parent.process_msg = record_stream_process_msg;
+    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;
@@ -630,8 +630,8 @@ static playback_stream* playback_stream_new(
         return NULL;
 
     s = pa_msgobject_new(playback_stream);
-    c->parent.parent.free = playback_stream_free;
-    c->parent.process_msg = playback_stream_process_msg;
+    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;
@@ -697,7 +697,7 @@ static void connection_unlink(connection *c) {
         pa_subscription_free(c->subscription);
 
     if (c->pstream)
-        pa_pstream_close(c->pstream);
+        pa_pstream_unlink(c->pstream);
 
     if (c->auth_timeout_event) {
         c->protocol->core->mainloop->time_free(c->auth_timeout_event);
@@ -705,8 +705,8 @@ static void connection_unlink(connection *c) {
     }
     
     pa_assert_se(pa_idxset_remove_by_data(c->protocol->connections, c, NULL) == c);
-    connection_unref(c);
     c->protocol = NULL;
+    connection_unref(c);
 }
 
 static void connection_free(pa_object *o) {
@@ -1933,7 +1933,6 @@ static void subscription_cb(pa_core *core, pa_subscription_event_type_t e, uint3
     connection *c = CONNECTION(userdata);
 
     connection_assert_ref(c);
-    pa_assert(t);
 
     t = pa_tagstruct_new(NULL, 0);
     pa_tagstruct_putu32(t, PA_COMMAND_SUBSCRIBE_EVENT);
@@ -2653,10 +2652,9 @@ static void pstream_die_callback(pa_pstream *p, void *userdata) {
     connection_assert_ref(c);
 
     connection_unlink(c);
-/*    pa_log("connection died.");*/
+    pa_log_info("connection died.");
 }
 
-
 static void pstream_drain_callback(pa_pstream *p, void *userdata) {
     connection *c = CONNECTION(userdata);
 
@@ -2732,7 +2730,6 @@ static void on_connection(PA_GCC_UNUSED pa_socket_server*s, pa_iochannel *io, vo
     c->client->owner = p->module;
 
     c->pstream = pa_pstream_new(p->core->mainloop, io, p->core->mempool);
-    pa_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);
@@ -2740,18 +2737,15 @@ static void on_connection(PA_GCC_UNUSED pa_socket_server*s, pa_iochannel *io, vo
     pa_pstream_set_drain_callback(c->pstream, pstream_drain_callback, c);
 
     c->pdispatch = pa_pdispatch_new(p->core->mainloop, command_table, PA_COMMAND_MAX);
-    pa_assert(c->pdispatch);
 
     c->record_streams = pa_idxset_new(NULL, NULL);
     c->output_streams = pa_idxset_new(NULL, NULL);
-    pa_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);
@@ -2834,7 +2828,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);
-    pa_assert(p->connections);
 
     return p;
 

commit 9d1eb1bbda22a7648c7e216c98d63cfbcb8829e6
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sun Aug 5 11:22:03 2007 +0000

    play memchunks completely
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1576 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/play-memchunk.c b/src/pulsecore/play-memchunk.c
index a5ba949..419d523 100644
--- a/src/pulsecore/play-memchunk.c
+++ b/src/pulsecore/play-memchunk.c
@@ -130,7 +130,7 @@ static void sink_input_drop_cb(pa_sink_input *i, size_t length) {
     u = MEMCHUNK_STREAM(i->userdata);
     memchunk_stream_assert_ref(u);
 
-    if (length >= u->memchunk.length) {
+    if (length < u->memchunk.length) {
         u->memchunk.length -= length;
         u->memchunk.index += length;
     } else

commit 872951cca18d9c595706b3543570cc764d886cf4
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sun Aug 5 13:51:32 2007 +0000

    use posix_fadvise to avoid page faults when reading audio files from disk
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1577 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/sound-file-stream.c b/src/pulsecore/sound-file-stream.c
index 433a73b..4e0e91e 100644
--- a/src/pulsecore/sound-file-stream.c
+++ b/src/pulsecore/sound-file-stream.c
@@ -28,19 +28,21 @@
 #include <stdlib.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 "sound-file-stream.h"
 
-#define BUF_SIZE (1024*10)
-
-/* FIXME: file access needs to be moved to seperate thread */
+#define BUF_SIZE (1024*16)
 
 typedef struct file_stream {
     pa_msgobject parent;
@@ -53,7 +55,7 @@ typedef struct file_stream {
 } file_stream;
 
 enum {
-    MESSAGE_DROP_FILE_STREAM
+    FILE_STREAM_MESSAGE_UNLINK
 };
 
 PA_DECLARE_CLASS(file_stream);
@@ -95,7 +97,7 @@ static int file_stream_process_msg(pa_msgobject *o, int code, void*userdata, int
     file_stream_assert_ref(u);
     
     switch (code) {
-        case MESSAGE_DROP_FILE_STREAM:
+        case FILE_STREAM_MESSAGE_UNLINK:
             file_stream_unlink(u);
             break;
     }
@@ -159,7 +161,7 @@ static int sink_input_peek_cb(pa_sink_input *i, pa_memchunk *chunk) {
                 pa_memblock_unref(u->memchunk.memblock);
                 pa_memchunk_reset(&u->memchunk);
                 
-                pa_asyncmsgq_post(u->core->asyncmsgq, PA_MSGOBJECT(u), MESSAGE_DROP_FILE_STREAM, NULL, 0, NULL, NULL);
+                pa_asyncmsgq_post(u->core->asyncmsgq, PA_MSGOBJECT(u), FILE_STREAM_MESSAGE_UNLINK, NULL, 0, NULL, NULL);
 
                 sf_close(u->sndfile);
                 u->sndfile = NULL;
@@ -225,7 +227,8 @@ int pa_play_file(
     SF_INFO sfinfo;
     pa_sample_spec ss;
     pa_sink_input_new_data data;
-
+    int fd;
+    
     pa_assert(sink);
     pa_assert(fname);
 
@@ -241,8 +244,31 @@ int pa_play_file(
 
     memset(&sfinfo, 0, sizeof(sfinfo));
 
-    if (!(u->sndfile = sf_open(fname, SFM_READ, &sfinfo))) {
+    if ((fd = open(fname, O_RDONLY|O_NOCTTY)) < 0) {
+        pa_log("Failed to open file %s: %s", fname, pa_cstrerror(errno));
+        goto fail;
+    }
+
+    /* 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. */
+
+    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.");
+    
+    if (!(u->sndfile = sf_open_fd(fd, SFM_READ, &sfinfo, 1))) {
         pa_log("Failed to open file %s", fname);
+        close(fd);
         goto fail;
     }
 

commit 41d67c40d9603228f3bd1a748fa774e49ff50c3e
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sun Aug 5 13:52:01 2007 +0000

    minor optimization for cacheing in of samples by using posix_fadvise
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1578 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/sound-file.c b/src/pulsecore/sound-file.c
index 416ae93..7c8b597 100644
--- a/src/pulsecore/sound-file.c
+++ b/src/pulsecore/sound-file.c
@@ -26,12 +26,16 @@
 #endif
 
 #include <string.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 "sound-file.h"
 #include "core-scache.h"
@@ -49,6 +53,7 @@ int pa_sound_file_load(
     size_t l;
     sf_count_t (*readf_function)(SNDFILE *sndfile, void *ptr, sf_count_t frames) = NULL;
     void *ptr = NULL;
+    int fd;
 
     pa_assert(fname);
     pa_assert(ss);
@@ -57,8 +62,20 @@ int pa_sound_file_load(
     pa_memchunk_reset(chunk);
     memset(&sfinfo, 0, sizeof(sfinfo));
 
-    if (!(sf = sf_open(fname, SFM_READ, &sfinfo))) {
+    if ((fd = open(fname, O_RDONLY|O_NOCTTY)) < 0) {
+        pa_log("Failed to open file %s: %s", fname, pa_cstrerror(errno));
+        goto finish;
+    }
+
+    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.");
+    
+    if (!(sf = sf_open_fd(fd, SFM_READ, &sfinfo, 1))) {
         pa_log("Failed to open file %s", fname);
+        close(fd);
         goto finish;
     }
 

commit 67753869830914f6a25a11460405929741776b61
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sun Aug 5 14:06:47 2007 +0000

    make sure to handle disconnecting our own connection properly
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1579 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c
index 2396a38..8984985 100644
--- a/src/pulsecore/protocol-native.c
+++ b/src/pulsecore/protocol-native.c
@@ -2298,6 +2298,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) {
@@ -2306,6 +2308,7 @@ 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;
@@ -2315,10 +2318,12 @@ static void command_kill(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, uint3
         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) {

commit c306b835255e576e46194c47782939b6f915ae3a
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Aug 6 16:12:54 2007 +0000

    initialize 'length' properly
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1580 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/pstream.c b/src/pulsecore/pstream.c
index 0ffa583..c88f9aa 100644
--- a/src/pulsecore/pstream.c
+++ b/src/pulsecore/pstream.c
@@ -347,7 +347,8 @@ void pa_pstream_send_memblock(pa_pstream*p, uint32_t channel, int64_t offset, pa
         return;
 
     idx = 0;
-
+    length = chunk->length;
+    
     while (length > 0) {
         struct item_info *i;
         size_t n;

commit 62790ccdb4ee529974315c45e11714d56f2a9afa
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Aug 6 16:13:32 2007 +0000

    fix playback over native protocol
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1581 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c
index 8984985..4d7dd63 100644
--- a/src/pulsecore/protocol-native.c
+++ b/src/pulsecore/protocol-native.c
@@ -321,8 +321,8 @@ static void upload_stream_unlink(upload_stream *s) {
         return;
 
     pa_assert_se(pa_idxset_remove_by_data(s->connection->output_streams, s, NULL) == s);
-    upload_stream_unref(s);
     s->connection = NULL;
+    upload_stream_unref(s);
 }
 
 static void upload_stream_free(pa_object *o) {
@@ -379,8 +379,8 @@ static void record_stream_unlink(record_stream *s) {
     }
 
     pa_assert_se(pa_idxset_remove_by_data(s->connection->record_streams, s, NULL) == s);
-    record_stream_unref(s);    
     s->connection = NULL;
+    record_stream_unref(s);    
 }
 
 static void record_stream_free(pa_object *o) {
@@ -496,8 +496,8 @@ static void playback_stream_unlink(playback_stream *s) {
         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);
-    playback_stream_unref(s);    
     s->connection = NULL;
+    playback_stream_unref(s);    
 }
 
 static void playback_stream_free(pa_object* o) {
@@ -531,7 +531,7 @@ static int playback_stream_process_msg(pa_msgobject *o, int code, void*userdata,
             pa_tagstruct_putu32(t, l);
             pa_pstream_send_tagstruct(s->connection->pstream, t);
 
-     /*     pa_log("Requesting %u bytes", l);  */
+/*             pa_log("Requesting %u bytes", l);    */
             break;
         }
 
@@ -729,16 +729,22 @@ static void connection_free(pa_object *o) {
 static void request_bytes(playback_stream *s) {
     size_t new_missing, delta, previous_missing;
 
+
+/*     pa_log("request_bytes()"); */
     playback_stream_assert_ref(s);
 
     new_missing = pa_memblockq_missing(s->memblockq);
-
-    if (new_missing <= s->last_missing)
+    
+    if (new_missing <= s->last_missing) {
+        s->last_missing = new_missing;
         return;
+    }
 
     delta = new_missing - s->last_missing;
     s->last_missing = new_missing;
 
+/*     pa_log("request_bytes(%u)", delta); */
+
     previous_missing = pa_atomic_add(&s->missing, delta);
     if (previous_missing < pa_memblockq_get_minreq(s->memblockq) && previous_missing+delta >= pa_memblockq_get_minreq(s->memblockq))
         pa_asyncmsgq_post(s->connection->protocol->core->asyncmsgq, PA_MSGOBJECT(s), PLAYBACK_STREAM_MESSAGE_REQUEST_DATA, NULL, 0, NULL, NULL);
@@ -812,6 +818,7 @@ static int sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int
 
         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: {
@@ -824,6 +831,8 @@ static int sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int
                 pa_memblockq_seek(s->memblockq, chunk->length, PA_SEEK_RELATIVE);
             }
 
+            request_bytes(s);
+
             s->underrun = 0;
             return 0;
         }
@@ -838,6 +847,7 @@ static int sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int
                 s->drain_tag = PA_PTR_TO_UINT(userdata);
                 s->drain_request = 1;
             }
+            request_bytes(s);
 
             return 0;
         }
@@ -891,6 +901,7 @@ static int sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int
         case PA_SINK_INPUT_MESSAGE_SET_STATE:
 
             pa_memblockq_prebuf_force(s->memblockq);
+            request_bytes(s);
             break;
 
         case PA_SINK_INPUT_MESSAGE_GET_LATENCY: {
@@ -921,11 +932,13 @@ static int sink_input_peek_cb(pa_sink_input *i, pa_memchunk *chunk) {
     }
 
     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;
 }
@@ -1083,6 +1096,8 @@ static void command_create_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GC
     pa_tagstruct_putu32(reply, s->sink_input->index);
     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 */
 
@@ -2158,11 +2173,11 @@ static void command_trigger_or_flush_or_prebuf_playback_stream(PA_GCC_UNUSED pa_
             break;
             
         case PA_COMMAND_PREBUF_PLAYBACK_STREAM:
-            pa_asyncmsgq_send(s->sink_input->sink->asyncmsgq, PA_MSGOBJECT(s->sink_input), SINK_INPUT_MESSAGE_TRIGGER, NULL, 0, NULL);
+            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_asyncmsgq_send(s->sink_input->sink->asyncmsgq, PA_MSGOBJECT(s->sink_input), SINK_INPUT_MESSAGE_PREBUF_FORCE, NULL, 0, NULL);
+            pa_asyncmsgq_send(s->sink_input->sink->asyncmsgq, PA_MSGOBJECT(s->sink_input), SINK_INPUT_MESSAGE_TRIGGER, NULL, 0, NULL);
             break;
 
         default:

commit 455ff8d342a914f29971dfc7b2c48f9cf09c0f1b
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Aug 6 17:37:59 2007 +0000

    fix a memory leak
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1582 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/pstream.c b/src/pulsecore/pstream.c
index c88f9aa..ea23880 100644
--- a/src/pulsecore/pstream.c
+++ b/src/pulsecore/pstream.c
@@ -274,7 +274,7 @@ 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;
     pa_assert(i);
 
@@ -299,15 +299,15 @@ static void pstream_free(pa_pstream *p) {
     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->write.memchunk.memblock)
-        pa_memblock_unref(p->write.memchunk.memblock);
-
     pa_xfree(p);
 }
 
@@ -568,9 +568,14 @@ static int do_write(pa_pstream *p) {
 
     if (p->write.index >= PA_PSTREAM_DESCRIPTOR_SIZE + ntohl(p->write.descriptor[PA_PSTREAM_DESCRIPTOR_LENGTH])) {
         pa_assert(p->write.current);
-        item_free(p->write.current, (void *) 1);
+        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);
     }

commit 74b3b6d4538e46655d09a08041a5626b0a71d3a6
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Aug 6 19:42:15 2007 +0000

    fix playback status querying
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1583 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c
index 4d7dd63..d75815f 100644
--- a/src/pulsecore/protocol-native.c
+++ b/src/pulsecore/protocol-native.c
@@ -1481,7 +1481,7 @@ static void command_get_playback_latency(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_
     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));

commit 243f2fc20a4a69739b347a7da6ae4bf10fc3450b
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Aug 6 21:47:29 2007 +0000

    minor fixes and cleanups
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1584 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c
index d75815f..bd1605b 100644
--- a/src/pulsecore/protocol-native.c
+++ b/src/pulsecore/protocol-native.c
@@ -2710,7 +2710,8 @@ static void on_connection(PA_GCC_UNUSED pa_socket_server*s, pa_iochannel *io, vo
     pa_protocol_native *p = userdata;
     connection *c;
     char cname[256], pname[128];
-    
+
+    pa_assert(s);
     pa_assert(io);
     pa_assert(p);
 
@@ -2742,9 +2743,7 @@ static void on_connection(PA_GCC_UNUSED pa_socket_server*s, pa_iochannel *io, vo
     c->protocol = p;
     pa_iochannel_socket_peer_to_string(io, pname, sizeof(pname));
     pa_snprintf(cname, sizeof(cname), "Native client (%s)", pname);
-    pa_assert(p->core);
     c->client = pa_client_new(p->core, __FILE__, cname);
-    pa_assert(c->client);
     c->client->kill = client_kill_cb;
     c->client->userdata = c;
     c->client->owner = p->module;
diff --git a/src/pulsecore/protocol-simple.c b/src/pulsecore/protocol-simple.c
index 0ded5d2..dd61c7e 100644
--- a/src/pulsecore/protocol-simple.c
+++ b/src/pulsecore/protocol-simple.c
@@ -93,7 +93,7 @@ enum {
 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_DROP_CONNECTION    /* Please drop a aconnection now */
+    CONNECTION_MESSAGE_UNLINK_CONNECTION    /* Please drop a aconnection now */
 };
 
 
@@ -125,6 +125,11 @@ static void connection_unlink(connection *c) {
         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);
@@ -139,8 +144,6 @@ static void connection_free(pa_object *o) {
     if (c->playback.current_memblock)
         pa_memblock_unref(c->playback.current_memblock);
 
-    if (c->io)
-        pa_iochannel_free(c->io);
     if (c->input_memblockq)
         pa_memblockq_free(c->input_memblockq);
     if (c->output_memblockq)
@@ -155,7 +158,7 @@ static int do_read(connection *c) {
     size_t l;
     void *p;
 
-    pa_assert(c);
+    connection_assert_ref(c);
 
     if (!c->sink_input || (l = pa_atomic_load(&c->playback.missing)) <= 0)
         return 0;
@@ -205,7 +208,7 @@ static int do_write(connection *c) {
     ssize_t r;
     void *p;
 
-    pa_assert(c);
+    connection_assert_ref(c);
 
     if (!c->source_output)
         return 0;
@@ -239,7 +242,7 @@ static int do_write(connection *c) {
 }
 
 static void do_work(connection *c) {
-    pa_assert(c);
+    connection_assert_ref(c);
 
     if (c->dead)
         return;
@@ -287,7 +290,7 @@ static int connection_process_msg(pa_msgobject *o, int code, void*userdata, int6
             do_work(c);
             break;
 
-        case CONNECTION_MESSAGE_DROP_CONNECTION:
+        case CONNECTION_MESSAGE_UNLINK_CONNECTION:
             connection_unlink(c);
             break;
     }
@@ -340,12 +343,12 @@ static int sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int
 
 /* Called from thread context */
 static int sink_input_peek_cb(pa_sink_input *i, pa_memchunk *chunk) {
-    connection*c;
+    connection *c;
     int r;
 
     pa_assert(i);
-    c = i->userdata;
-    pa_assert(c);
+    c = CONNECTION(i->userdata);
+    connection_assert_ref(c);
     pa_assert(chunk);
 
     r = pa_memblockq_peek(c->input_memblockq, chunk);
@@ -353,18 +356,19 @@ static int sink_input_peek_cb(pa_sink_input *i, pa_memchunk *chunk) {
 /*     pa_log("peeked %u %i", r >= 0 ? chunk->length: 0, r); */
 
     if (c->dead && r < 0)
-        pa_asyncmsgq_post(c->protocol->core->asyncmsgq, PA_MSGOBJECT(c), CONNECTION_MESSAGE_DROP_CONNECTION, NULL, 0, NULL, NULL);
+        pa_asyncmsgq_post(c->protocol->core->asyncmsgq, 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 = i->userdata;
+    connection *c;
     size_t old, new;
 
     pa_assert(i);
-    pa_assert(c);
+    c = CONNECTION(i->userdata);
+    connection_assert_ref(c);
     pa_assert(length);
 
     old = pa_memblockq_missing(c->input_memblockq);
@@ -391,7 +395,7 @@ static void source_output_push_cb(pa_source_output *o, const pa_memchunk *chunk)
     connection *c;
 
     pa_assert(o);
-    c = o->userdata;
+    c = CONNECTION(o->userdata);
     pa_assert(c);
     pa_assert(chunk);
 
@@ -433,8 +437,8 @@ static void client_kill_cb(pa_client *client) {
 static void io_callback(pa_iochannel*io, void *userdata) {
     connection *c = CONNECTION(userdata);
 
+    connection_assert_ref(c);
     pa_assert(io);
-    pa_assert(c);
 
     do_work(c);
 }
@@ -507,7 +511,6 @@ static void on_connection(pa_socket_server*s, pa_iochannel *io, void *userdata)
                 (size_t) -1,
                 l/PLAYBACK_BUFFER_FRAGMENTS,
                 NULL);
-        pa_assert(c->input_memblockq);
         pa_iochannel_socket_set_rcvbuf(io, l/PLAYBACK_BUFFER_FRAGMENTS*5);
         c->playback.fragment_size = l/PLAYBACK_BUFFER_FRAGMENTS;
 

commit 1f9ce59969e5e778f3baa287fa9c7918fde1b0c9
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Aug 6 21:47:53 2007 +0000

    port esound protocol to new lock-free core
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1585 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/Makefile.am b/src/Makefile.am
index 8fc0f19..0f2cdec 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -723,9 +723,8 @@ modlibexec_LTLIBRARIES = \
 		libstrlist.la \
 		libprotocol-simple.la \
 		libprotocol-http.la \
-		libprotocol-native.la
-
-#		libprotocol-esound.la
+		libprotocol-native.la \
+		libprotocol-esound.la
 
 # We need to emulate sendmsg/recvmsg to support this on Win32
 if !OS_IS_WIN32
@@ -881,8 +880,8 @@ modlibexec_LTLIBRARIES += \
 		module-http-protocol-tcp.la \
 		module-sine.la \
 		module-native-protocol-tcp.la \
-		module-native-protocol-fd.la
-#		module-esound-protocol-tcp.la \
+		module-native-protocol-fd.la \
+		module-esound-protocol-tcp.la
 #		module-combine.la \
 #		module-tunnel-sink.la \
 #		module-tunnel-source.la \
@@ -900,8 +899,8 @@ modlibexec_LTLIBRARIES += \
 		module-cli-protocol-unix.la \
 		module-simple-protocol-unix.la \
 		module-http-protocol-unix.la \
-		module-native-protocol-unix.la
-#		module-esound-protocol-unix.la 
+		module-native-protocol-unix.la \
+		module-esound-protocol-unix.la 
 endif
 
 if HAVE_MKFIFO
@@ -910,11 +909,11 @@ modlibexec_LTLIBRARIES += \
 		module-pipe-source.la
 endif
 
-#if !OS_IS_WIN32
-#modlibexec_LTLIBRARIES += \
-#		module-esound-compat-spawnfd.la \
-#		module-esound-compat-spawnpid.la
-#endif
+if !OS_IS_WIN32
+modlibexec_LTLIBRARIES += \
+		module-esound-compat-spawnfd.la \
+		module-esound-compat-spawnpid.la
+endif
 
 if HAVE_REGEX
 modlibexec_LTLIBRARIES += \
@@ -940,10 +939,10 @@ modlibexec_LTLIBRARIES += \
 		module-alsa-source.la
 endif
 
-if HAVE_SOLARIS
-modlibexec_LTLIBRARIES += \
-		module-solaris.la
-endif
+#if HAVE_SOLARIS
+#modlibexec_LTLIBRARIES += \
+#		module-solaris.la
+#endif
 
 if HAVE_AVAHI
 modlibexec_LTLIBRARIES += \
@@ -974,10 +973,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 += \
@@ -1099,23 +1098,23 @@ module_native_protocol_fd_la_LIBADD = $(AM_LIBADD) libpulsecore.la libprotocol-n
 
 # EsounD protocol
 
-#module_esound_protocol_tcp_la_SOURCES = modules/module-protocol-stub.c
-#module_esound_protocol_tcp_la_CFLAGS = -DUSE_TCP_SOCKETS -DUSE_PROTOCOL_ESOUND $(AM_CFLAGS)
-#module_esound_protocol_tcp_la_LDFLAGS = -module -avoid-version
-#module_esound_protocol_tcp_la_LIBADD = $(AM_LIBADD) libpulsecore.la libprotocol-esound.la libsocket-server.la
+module_esound_protocol_tcp_la_SOURCES = modules/module-protocol-stub.c
+module_esound_protocol_tcp_la_CFLAGS = -DUSE_TCP_SOCKETS -DUSE_PROTOCOL_ESOUND $(AM_CFLAGS)
+module_esound_protocol_tcp_la_LDFLAGS = -module -avoid-version
+module_esound_protocol_tcp_la_LIBADD = $(AM_LIBADD) libpulsecore.la libprotocol-esound.la libsocket-server.la
 
-#module_esound_protocol_unix_la_SOURCES = modules/module-protocol-stub.c
-#module_esound_protocol_unix_la_CFLAGS = -DUSE_UNIX_SOCKETS -DUSE_PROTOCOL_ESOUND $(AM_CFLAGS)
-#module_esound_protocol_unix_la_LDFLAGS = -module -avoid-version
-#module_esound_protocol_unix_la_LIBADD = $(AM_LIBADD) libpulsecore.la libprotocol-esound.la libsocket-server.la libsocket-util.la
+module_esound_protocol_unix_la_SOURCES = modules/module-protocol-stub.c
+module_esound_protocol_unix_la_CFLAGS = -DUSE_UNIX_SOCKETS -DUSE_PROTOCOL_ESOUND $(AM_CFLAGS)
+module_esound_protocol_unix_la_LDFLAGS = -module -avoid-version
+module_esound_protocol_unix_la_LIBADD = $(AM_LIBADD) libpulsecore.la libprotocol-esound.la libsocket-server.la libsocket-util.la
 
-#module_esound_compat_spawnfd_la_SOURCES = modules/module-esound-compat-spawnfd.c
-#module_esound_compat_spawnfd_la_LDFLAGS = -module -avoid-version
-#module_esound_compat_spawnfd_la_LIBADD = $(AM_LIBADD) libpulsecore.la
+module_esound_compat_spawnfd_la_SOURCES = modules/module-esound-compat-spawnfd.c
+module_esound_compat_spawnfd_la_LDFLAGS = -module -avoid-version
+module_esound_compat_spawnfd_la_LIBADD = $(AM_LIBADD) libpulsecore.la
 
-#module_esound_compat_spawnpid_la_SOURCES = modules/module-esound-compat-spawnpid.c
-#module_esound_compat_spawnpid_la_LDFLAGS = -module -avoid-version
-#module_esound_compat_spawnpid_la_LIBADD = $(AM_LIBADD) libpulsecore.la
+module_esound_compat_spawnpid_la_SOURCES = modules/module-esound-compat-spawnpid.c
+module_esound_compat_spawnpid_la_LDFLAGS = -module -avoid-version
+module_esound_compat_spawnpid_la_LIBADD = $(AM_LIBADD) libpulsecore.la
 
 #module_esound_sink_la_SOURCES = modules/module-esound-sink.c
 #module_esound_sink_la_LDFLAGS = -module -avoid-version
@@ -1201,9 +1200,9 @@ module_alsa_source_la_CFLAGS = $(AM_CFLAGS) $(ASOUNDLIB_CFLAGS)
 
 # Solaris
 
-module_solaris_la_SOURCES = modules/module-solaris.c
-module_solaris_la_LDFLAGS = -module -avoid-version
-module_solaris_la_LIBADD = $(AM_LIBADD) libiochannel.la
+#module_solaris_la_SOURCES = modules/module-solaris.c
+#module_solaris_la_LDFLAGS = -module -avoid-version
+#module_solaris_la_LIBADD = $(AM_LIBADD) libiochannel.la
 
 # Avahi
 
@@ -1228,10 +1227,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
diff --git a/src/pulsecore/protocol-esound.c b/src/pulsecore/protocol-esound.c
index fe0b879..7460714 100644
--- a/src/pulsecore/protocol-esound.c
+++ b/src/pulsecore/protocol-esound.c
@@ -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,7 @@
 #include <pulsecore/core-util.h>
 #include <pulsecore/core-error.h>
 #include <pulsecore/ipacl.h>
+#include <pulsecore/macro.h>
 
 #include "endianmacros.h"
 
@@ -77,7 +77,9 @@
 
 /* This is heavily based on esound's code */
 
-struct connection {
+typedef struct connection {
+    pa_msgobject parent;
+    
     uint32_t index;
     int dead;
     pa_protocol_esound *protocol;
@@ -100,6 +102,7 @@ struct connection {
     struct {
         pa_memblock *current_memblock;
         size_t memblock_index, fragment_size;
+        pa_atomic_t missing;
     } playback;
 
     struct {
@@ -109,46 +112,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 void sink_input_drop_cb(pa_sink_input *i, size_t length);
 static int sink_input_peek_cb(pa_sink_input *i, 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 +204,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);
-
-    if (c->state == ESD_STREAMING_DATA)
-        c->protocol->n_player--;
+static void connection_unlink(connection *c) {
+    pa_assert(c);
 
-    pa_client_free(c->client);
+    if (!c->protocol)
+        return;
 
     if (c->sink_input) {
         pa_sink_input_disconnect(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_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 +265,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);
+    pa_assert(ss);
 
     ss->channels = ((format & ESD_MASK_CHAN) == ESD_STEREO) ? 2 : 1;
     if ((format & ESD_MASK_BITS) == ESD_BITS16)
@@ -289,11 +329,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) {
@@ -316,7 +358,7 @@ static int esd_proto_connect(struct connection *c, PA_GCC_UNUSED esd_proto_t req
     else if (ekey == ESD_SWAP_ENDIAN_KEY)
         c->swap_byte_order = 1;
     else {
-        pa_log("client sent invalid endian key");
+        pa_log_warn("Client sent invalid endian key");
         return -1;
     }
 
@@ -325,7 +367,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 +375,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);
+    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);
+    data = (const char*) data + sizeof(int32_t);
 
     ss.rate = rate;
     format_esd2native(format, c->swap_byte_order, &ss);
@@ -362,7 +406,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 +429,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 +456,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);
+    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);
+    data = (const char*) data + sizeof(int32_t);
 
     ss.rate = rate;
     format_esd2native(format, c->swap_byte_order, &ss);
@@ -436,7 +486,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 +505,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 +538,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;
@@ -509,12 +563,14 @@ static int esd_proto_get_latency(struct connection *c, PA_GCC_UNUSED esd_proto_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;
@@ -533,14 +589,16 @@ static int esd_proto_server_info(struct connection *c, PA_GCC_UNUSED esd_proto_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 +619,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);
@@ -602,7 +660,7 @@ static int esd_proto_all_info(struct connection *c, esd_proto_t request, const v
         t -= k;
     }
 
-    assert(t == s*(nsamples+1)+k);
+    pa_assert(t == s*(nsamples+1)+k);
     t -= k;
 
     connection_write(c, terminator, k);
@@ -615,7 +673,7 @@ 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));
@@ -653,19 +711,21 @@ static int esd_proto_all_info(struct connection *c, esd_proto_t request, const v
         }
     }
 
-    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;
@@ -694,13 +754,15 @@ 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);
@@ -727,12 +789,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 +807,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,12 +831,14 @@ 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;
@@ -787,7 +853,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 +865,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 +882,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");  */
 
     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");
@@ -862,7 +931,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 +942,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 (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;
@@ -896,22 +968,24 @@ static int do_read(struct connection *c) {
         ssize_t r;
         void *p;
 
-        assert(c->scache.memchunk.memblock);
-        assert(c->scache.name);
-        assert(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);
-
-        if ((r = pa_iochannel_read(c->io, (uint8_t*) p+c->scache.memchunk.index, c->scache.memchunk.length-c->scache.memchunk.index)) <= 0) {
-            pa_memblock_release(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 (errno == EINTR || errno == EAGAIN)
+                return 0;
+            
             pa_log_debug("read(): %s", r < 0 ? pa_cstrerror(errno) : "EOF");
             return -1;
         }
 
-        pa_memblock_release(c->scache.memchunk.memblock);
-
         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;
@@ -938,11 +1012,11 @@ static int do_read(struct connection *c) {
         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)
@@ -956,47 +1030,50 @@ static int do_read(struct connection *c) {
             }
 
         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);
-            assert(pa_memblock_get_length(c->playback.current_memblock) >= 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;
         }
 
         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 (errno == EINTR || errno == EAGAIN)
+                return 0;
 
-        if ((r = pa_iochannel_read(c->io, (uint8_t*) p+c->playback.memblock_index, l)) <= 0) {
-            pa_memblock_release(c->playback.current_memblock);
             pa_log_debug("read(): %s", r < 0 ? pa_cstrerror(errno) : "EOF");
             return -1;
         }
-        pa_memblock_release(c->playback.current_memblock);
 
         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 (errno == EINTR || errno == EAGAIN)
+                return 0;
+            
             pa_log("write(): %s", pa_cstrerror(errno));
             return -1;
         }
@@ -1009,37 +1086,36 @@ static int do_write(struct connection *c) {
         ssize_t r;
         void *p;
 
-        assert(c->output_memblockq);
         if (pa_memblockq_peek(c->output_memblockq, &chunk) < 0)
             return 0;
 
-        assert(chunk.memblock);
-        assert(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 = pa_iochannel_write(c->io, (uint8_t*) p+chunk.index, chunk.length)) < 0) {
-            pa_memblock_release(chunk.memblock);
-            pa_memblock_unref(chunk.memblock);
+            if (errno == EINTR || errno == EAGAIN)
+                return 0;
+        
             pa_log("write(): %s", pa_cstrerror(errno));
             return -1;
         }
 
-        pa_memblock_release(chunk.memblock);
-
-        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)
@@ -1070,117 +1146,188 @@ fail:
         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);
 }
 
+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);
+
+    switch (code) {
+        case CONNECTION_MESSAGE_REQUEST_DATA:
+            do_work(c);
+            break;
+            
+        case CONNECTION_MESSAGE_POST_DATA:
+/*             pa_log("got data %u", chunk->length); */
+            pa_memblockq_push_align(c->output_memblockq, chunk);
+            do_work(c);
+            break;
+
+        case CONNECTION_MESSAGE_UNLINK_CONNECTION:
+            connection_unlink(c);
+            break;
+    }
+
+    return 0;
+}
+
 /*** sink_input callbacks ***/
 
-static int sink_input_peek_cb(pa_sink_input *i, pa_memchunk *chunk) {
-    struct connection*c;
-    assert(i && i->userdata && chunk);
-    c = i->userdata;
+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;
 
-    if (pa_memblockq_peek(c->input_memblockq, chunk) < 0) {
+    pa_sink_input_assert_ref(i);
+    c = CONNECTION(i->userdata);
+    connection_assert_ref(c);
 
-        if (c->dead)
-            connection_free(c);
+    switch (code) {
 
-        return -1;
-    }
+        case SINK_INPUT_MESSAGE_POST_DATA: {
+            pa_assert(chunk);
 
-    return 0;
+            /* 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;
+
+            *r = pa_bytes_to_usec(pa_memblockq_get_length(c->input_memblockq), &c->sink_input->sample_spec);
+
+            /* 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_drop_cb(pa_sink_input *i, const pa_memchunk *chunk, size_t length) {
-    struct connection*c = i->userdata;
-    assert(i && c && length);
 
-/*     pa_log("DROP"); */
+static int sink_input_peek_cb(pa_sink_input *i, 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(c->protocol->core->asyncmsgq, PA_MSGOBJECT(c), CONNECTION_MESSAGE_UNLINK_CONNECTION, NULL, 0, NULL, NULL);
+
+    return r;
+}
+
+static void sink_input_drop_cb(pa_sink_input *i, size_t length) {
+    connection*c;
+    size_t old, new;
 
-    pa_memblockq_drop(c->input_memblockq, chunk, length);
+    pa_assert(i);
+    c = CONNECTION(i->userdata);
+    connection_assert_ref(c);
+    pa_assert(length);
 
-    /* do something */
-    assert(c->protocol && c->protocol->core && c->protocol->core->mainloop && c->protocol->core->mainloop->defer_enable);
+    /*     pa_log("DROP"); */
 
-    if (!c->dead)
-        c->protocol->core->mainloop->defer_enable(c->defer_event, 1);
+    old = pa_memblockq_missing(c->input_memblockq);
+    pa_memblockq_drop(c->input_memblockq, length);
+    new = pa_memblockq_missing(c->input_memblockq);
 
-/*     assert(pa_memblockq_get_length(c->input_memblockq) > 2048); */
+    if (new > old) {
+        if (pa_atomic_add(&c->playback.missing, new - old) <= 0)
+            pa_asyncmsgq_post(c->protocol->core->asyncmsgq, PA_MSGOBJECT(c), CONNECTION_MESSAGE_REQUEST_DATA, NULL, 0, NULL, NULL);
+    }
 }
 
 static void sink_input_kill_cb(pa_sink_input *i) {
-    assert(i && i->userdata);
-    connection_free((struct connection *) i->userdata);
-}
+    pa_sink_input_assert_ref(i);
 
-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);
+    connection_unlink(CONNECTION(i->userdata));
 }
 
 /*** source_output callbacks ***/
 
 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(c->protocol->core->asyncmsgq, 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);
@@ -1188,16 +1335,16 @@ 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));
     pa_snprintf(cname, sizeof(cname), "EsounD client (%s)", pname);
-    assert(p->core);
     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;
@@ -1224,6 +1371,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;
@@ -1245,7 +1393,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);
@@ -1254,22 +1401,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;
 
@@ -1282,13 +1429,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));
@@ -1302,17 +1448,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);
 }

commit 0a6f9afb8b1f51484ad39c81aefd04a904809170
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Aug 7 10:47:00 2007 +0000

    add global suspend command to cli
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1586 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/cli-command.c b/src/pulsecore/cli-command.c
index d761353..fac8d0e 100644
--- a/src/pulsecore/cli-command.c
+++ b/src/pulsecore/cli-command.c
@@ -117,6 +117,7 @@ static int pa_cli_command_move_source_output(pa_core *c, pa_tokenizer *t, pa_str
 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 */
 
@@ -165,6 +166,7 @@ static const struct command commands[] = {
     { "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 }
 };
 
@@ -961,6 +963,32 @@ static int pa_cli_command_suspend_source(pa_core *c, pa_tokenizer *t, pa_strbuf
     return 0;
 }
 
+static int pa_cli_command_suspend(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) {
+    const char *m;
+    pa_sink *sink;
+    pa_source *source;
+    int suspend;
+    uint32_t idx;
+
+    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;
+    }
+
+    for (sink = pa_idxset_first(c->sinks, &idx); sink; sink = pa_idxset_next(c->sinks, &idx))
+        pa_sink_suspend(sink, suspend);
+
+    for (source = pa_idxset_first(c->sources, &idx); source; source = pa_idxset_next(c->sources, &idx))
+        pa_source_suspend(source, suspend);
+    
+    return 0;
+}
+
 static int pa_cli_command_dump(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_GCC_UNUSED int *fail) {
     pa_module *m;
     pa_sink *sink;
@@ -983,7 +1011,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;

commit 366d1d3441136551e32d375831c1edd85fd370f2
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Aug 7 10:48:29 2007 +0000

    reinitialize sw params after resume
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1587 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-alsa-source.c b/src/modules/module-alsa-source.c
index 9a5d5ac..2db9f48 100644
--- a/src/modules/module-alsa-source.c
+++ b/src/modules/module-alsa-source.c
@@ -264,7 +264,7 @@ static int unsuspend(struct userdata *u) {
         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;
@@ -275,6 +275,11 @@ static int unsuspend(struct userdata *u) {
         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;
+    }
+    
     snd_pcm_start(u->pcm_handle);
     
     /* FIXME: We need to reload the volume somehow */
@@ -565,8 +570,6 @@ static void thread_func(void *userdata) {
                     if (t < 0) {
                         pa_memblock_unref(chunk.memblock);
 
-                        pa_assert(t != -EPIPE);
-                        
                         if ((t = snd_pcm_recover(u->pcm_handle, t, 1)) == 0)
                             continue;
                         

commit 981d5fac832b8c02358b4787e14d519c26e4d9ca
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Aug 8 20:50:37 2007 +0000

    don't print error on socket read/write failure
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1588 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/ioline.c b/src/pulsecore/ioline.c
index 07b60be..23a90a7 100644
--- a/src/pulsecore/ioline.c
+++ b/src/pulsecore/ioline.c
@@ -293,7 +293,7 @@ static int do_read(pa_ioline *l) {
 
         /* 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
@@ -318,9 +318,13 @@ static int do_write(pa_ioline *l) {
 
     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;
         }
 

commit 54b9f55d2e50c8c867c40ef2a926ecabbc690cec
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Aug 8 20:52:52 2007 +0000

    properly reinitialize pollfd array after resume
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1589 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/alsa-util.c b/src/modules/alsa-util.c
index dd063f3..b5dba56 100644
--- a/src/modules/alsa-util.c
+++ b/src/modules/alsa-util.c
@@ -377,6 +377,11 @@ int pa_alsa_set_sw_params(snd_pcm_t *pcm) {
         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));
diff --git a/src/modules/module-alsa-sink.c b/src/modules/module-alsa-sink.c
index 5765d78..0e73b3c 100644
--- a/src/modules/module-alsa-sink.c
+++ b/src/modules/module-alsa-sink.c
@@ -96,6 +96,14 @@ struct userdata {
     int use_mmap;
 
     int first;
+
+    struct pollfd *pollfd;
+    int n_alsa_fds;
+};
+
+enum {
+    POLLFD_ASYNCQ,
+    POLLFD_ALSA_BASE
 };
 
 static const char* const valid_modargs[] = {
@@ -232,6 +240,31 @@ static pa_usec_t sink_get_latency(struct userdata *u) {
     return r;
 }
 
+static int build_pollfd(struct userdata *u) {
+    int err;
+    
+    pa_assert(u);
+    pa_assert(u->pcm_handle);
+
+    if ((u->n_alsa_fds = snd_pcm_poll_descriptors_count(u->pcm_handle)) < 0) {
+        pa_log("snd_pcm_poll_descriptors_count() failed: %s", snd_strerror(u->n_alsa_fds));
+        return -1;
+    }
+
+    pa_xfree(u->pollfd);
+    u->pollfd = pa_xnew0(struct pollfd, POLLFD_ALSA_BASE + u->n_alsa_fds);
+
+    u->pollfd[POLLFD_ASYNCQ].fd = pa_asyncmsgq_get_fd(u->asyncmsgq);
+    u->pollfd[POLLFD_ASYNCQ].events = POLLIN;
+
+    if ((err = snd_pcm_poll_descriptors(u->pcm_handle, u->pollfd+POLLFD_ALSA_BASE, u->n_alsa_fds)) < 0) {
+        pa_log("snd_pcm_poll_descriptors() failed: %s", snd_strerror(err));
+        return -1;
+    }
+    
+    return 0;
+}
+
 static int suspend(struct userdata *u) {
     pa_assert(u);
     pa_assert(u->pcm_handle);
@@ -287,6 +320,14 @@ static int unsuspend(struct userdata *u) {
         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;
@@ -474,36 +515,19 @@ static int sink_set_mute_cb(pa_sink *s) {
 }
 
 static void thread_func(void *userdata) {
-    enum {
-        POLLFD_ASYNCQ,
-        POLLFD_ALSA_BASE
-    };
 
     struct userdata *u = userdata;
-    struct pollfd *pollfd = NULL;
-    int n_alsa_fds, err;
     unsigned short revents = 0;
     snd_pcm_status_t *status;
-
+    int err;
+    
     pa_assert(u);
     snd_pcm_status_alloca(&status);
 
     pa_log_debug("Thread starting up");
 
-    if ((n_alsa_fds = snd_pcm_poll_descriptors_count(u->pcm_handle)) < 0) {
-        pa_log("snd_pcm_poll_descriptors_count() failed: %s", snd_strerror(n_alsa_fds));
+    if (build_pollfd(u) < 0)
         goto fail;
-    }
-
-    pollfd = pa_xnew0(struct pollfd, POLLFD_ALSA_BASE + n_alsa_fds);
-
-    pollfd[POLLFD_ASYNCQ].fd = pa_asyncmsgq_get_fd(u->asyncmsgq);
-    pollfd[POLLFD_ASYNCQ].events = POLLIN;
-
-    if ((err = snd_pcm_poll_descriptors(u->pcm_handle, pollfd+POLLFD_ALSA_BASE, n_alsa_fds)) < 0) {
-        pa_log("snd_pcm_poll_descriptors() failed: %s", snd_strerror(err));
-        goto fail;
-    }
 
     for (;;) {
         pa_msgobject *object;
@@ -513,13 +537,13 @@ static void thread_func(void *userdata) {
         int64_t offset;
         int r;
 
-/*         pa_log("loop");     */
+/*         pa_log("loop");      */
         
         /* Check whether there is a message for us to process */
         if (pa_asyncmsgq_get(u->asyncmsgq, &object, &code, &data, &offset, &chunk, 0) == 0) {
             int ret;
 
-/*             pa_log("processing msg"); */
+/*             pa_log("processing msg");  */
 
             if (!object && code == PA_MESSAGE_SHUTDOWN) {
                 pa_asyncmsgq_done(u->asyncmsgq, 0);
@@ -545,6 +569,7 @@ static void thread_func(void *userdata) {
                     goto fail;
 
             } else {
+                
                 for (;;) {
                     void *p;
                     snd_pcm_sframes_t t;
@@ -560,6 +585,8 @@ static void thread_func(void *userdata) {
                     
                     l = snd_pcm_status_get_avail(status) * u->frame_size;
 
+/*                     pa_log("%u bytes to write", l); */
+                    
                     if (l <= 0)
                         break;
                     
@@ -578,8 +605,6 @@ static void thread_func(void *userdata) {
                     
                     if (t < 0) {
 
-                        pa_assert(t != -EPIPE);
-                        
                         if ((t = snd_pcm_recover(u->pcm_handle, t, 1)) == 0)
                             continue;
                         
@@ -625,16 +650,15 @@ static void thread_func(void *userdata) {
         if (pa_asyncmsgq_before_poll(u->asyncmsgq) < 0)
             continue;
 
-/*         pa_log("polling for %i", POLLFD_ALSA_BASE + (PA_SINK_OPENED(u->sink->thread_info.state) ? n_alsa_fds : 0));   */
-        r = poll(pollfd, POLLFD_ALSA_BASE + (PA_SINK_OPENED(u->sink->thread_info.state) ? n_alsa_fds : 0), -1);
-        /*pa_log("polling got dsp=%i amq=%i (%i)", r > 0 ? pollfd[POLLFD_DSP].revents : 0, r > 0 ? pollfd[POLLFD_ASYNCQ].revents : 0, r); */
+/*         pa_log("polling for %i", POLLFD_ALSA_BASE + (PA_SINK_OPENED(u->sink->thread_info.state) ? u->n_alsa_fds : 0));    */
+        r = poll(u->pollfd, POLLFD_ALSA_BASE + (PA_SINK_OPENED(u->sink->thread_info.state) ? u->n_alsa_fds : 0), -1);
 /*         pa_log("poll end"); */
 
         pa_asyncmsgq_after_poll(u->asyncmsgq);
 
         if (r < 0) {
             if (errno == EINTR) {
-                pollfd[POLLFD_ASYNCQ].revents = 0;
+                u->pollfd[POLLFD_ASYNCQ].revents = 0;
                 revents = 0;
                 continue;
             }
@@ -646,16 +670,25 @@ static void thread_func(void *userdata) {
         pa_assert(r > 0);
 
         if (PA_SINK_OPENED(u->sink->thread_info.state)) {
-            if ((err = snd_pcm_poll_descriptors_revents(u->pcm_handle, pollfd + POLLFD_ALSA_BASE, n_alsa_fds, &revents)) < 0) {
+            if ((err = snd_pcm_poll_descriptors_revents(u->pcm_handle, u->pollfd + POLLFD_ALSA_BASE, u->n_alsa_fds, &revents)) < 0) {
                 pa_log("snd_pcm_poll_descriptors_revents() failed: %s", snd_strerror(err));
                 goto fail;
             }
 
-/*             pa_log("got alsa event"); */
+            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");
+
+                goto fail;
+            }
         } else
             revents = 0;
         
-        pa_assert((pollfd[POLLFD_ASYNCQ].revents & ~POLLIN) == 0);
+        pa_assert((u->pollfd[POLLFD_ASYNCQ].revents & ~POLLIN) == 0);
     }
 
 fail:
@@ -666,8 +699,6 @@ fail:
 
 finish:
     pa_log_debug("Thread shutting down");
-
-    pa_xfree(pollfd);
 }
 
 int pa__init(pa_core *c, pa_module*m) {
@@ -727,6 +758,8 @@ int pa__init(pa_core *c, pa_module*m) {
     m->userdata = u;
     u->use_mmap = use_mmap;
     u->first = 1;
+    u->n_alsa_fds = 0;
+    u->pollfd = NULL;
     pa_assert_se(u->asyncmsgq = pa_asyncmsgq_new(0));
 
     snd_config_update_free_global();
@@ -922,7 +955,8 @@ void pa__done(pa_core *c, pa_module*m) {
         snd_pcm_drop(u->pcm_handle);
         snd_pcm_close(u->pcm_handle);
     }
-    
+
+    pa_xfree(u->pollfd);
     pa_xfree(u->device_name);
     pa_xfree(u);
     

commit df9522cb8c853a26f2deb1f0b36945f0419a4265
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Aug 8 21:20:20 2007 +0000

    properly reinitialize pollfd array after resume
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1590 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-alsa-sink.c b/src/modules/module-alsa-sink.c
index 0e73b3c..708dd1f 100644
--- a/src/modules/module-alsa-sink.c
+++ b/src/modules/module-alsa-sink.c
@@ -685,6 +685,7 @@ static void thread_func(void *userdata) {
 
                 goto fail;
             }
+/*             pa_log("got alsa event"); */
         } else
             revents = 0;
         
diff --git a/src/modules/module-alsa-source.c b/src/modules/module-alsa-source.c
index 2db9f48..61035c7 100644
--- a/src/modules/module-alsa-source.c
+++ b/src/modules/module-alsa-source.c
@@ -93,6 +93,14 @@ struct userdata {
     char *device_name;
 
     int use_mmap;
+
+    struct pollfd *pollfd;
+    int n_alsa_fds;
+};
+
+enum {
+    POLLFD_ASYNCQ,
+    POLLFD_ALSA_BASE
 };
 
 static const char* const valid_modargs[] = {
@@ -220,6 +228,31 @@ static pa_usec_t source_get_latency(struct userdata *u) {
     return r;
 }
 
+static int build_pollfd(struct userdata *u) {
+    int err;
+    
+    pa_assert(u);
+    pa_assert(u->pcm_handle);
+
+    if ((u->n_alsa_fds = snd_pcm_poll_descriptors_count(u->pcm_handle)) < 0) {
+        pa_log("snd_pcm_poll_descriptors_count() failed: %s", snd_strerror(u->n_alsa_fds));
+        return -1;
+    }
+
+    pa_xfree(u->pollfd);
+    u->pollfd = pa_xnew0(struct pollfd, POLLFD_ALSA_BASE + u->n_alsa_fds);
+
+    u->pollfd[POLLFD_ASYNCQ].fd = pa_asyncmsgq_get_fd(u->asyncmsgq);
+    u->pollfd[POLLFD_ASYNCQ].events = POLLIN;
+
+    if ((err = snd_pcm_poll_descriptors(u->pcm_handle, u->pollfd+POLLFD_ALSA_BASE, u->n_alsa_fds)) < 0) {
+        pa_log("snd_pcm_poll_descriptors() failed: %s", snd_strerror(err));
+        return -1;
+    }
+    
+    return 0;
+}
+
 static int suspend(struct userdata *u) {
     pa_assert(u);
     pa_assert(u->pcm_handle);
@@ -279,6 +312,9 @@ static int unsuspend(struct userdata *u) {
         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);
     
@@ -467,14 +503,9 @@ static int source_set_mute_cb(pa_source *s) {
 }
 
 static void thread_func(void *userdata) {
-    enum {
-        POLLFD_ASYNCQ,
-        POLLFD_ALSA_BASE
-    };
 
     struct userdata *u = userdata;
-    struct pollfd *pollfd = NULL;
-    int n_alsa_fds, err;
+    int err;
     unsigned short revents = 0;
     snd_pcm_status_t *status;
 
@@ -483,20 +514,8 @@ static void thread_func(void *userdata) {
 
     pa_log_debug("Thread starting up");
 
-    if ((n_alsa_fds = snd_pcm_poll_descriptors_count(u->pcm_handle)) < 0) {
-        pa_log("snd_pcm_poll_descriptors_count() failed: %s", snd_strerror(n_alsa_fds));
+    if (build_pollfd(u) < 0)
         goto fail;
-    }
-
-    pollfd = pa_xnew0(struct pollfd, POLLFD_ALSA_BASE + n_alsa_fds);
-
-    pollfd[POLLFD_ASYNCQ].fd = pa_asyncmsgq_get_fd(u->asyncmsgq);
-    pollfd[POLLFD_ASYNCQ].events = POLLIN;
-
-    if ((err = snd_pcm_poll_descriptors(u->pcm_handle, pollfd+POLLFD_ALSA_BASE, n_alsa_fds)) < 0) {
-        pa_log("snd_pcm_poll_descriptors() failed: %s", snd_strerror(err));
-        goto fail;
-    }
 
     for (;;) {
         pa_msgobject *object;
@@ -607,15 +626,14 @@ static void thread_func(void *userdata) {
             continue;
 
 /*         pa_log("polling for %i", POLLFD_ALSA_BASE + (PA_SOURCE_OPENED(u->source->thread_info.state) ? n_alsa_fds : 0));   */
-        r = poll(pollfd, POLLFD_ALSA_BASE + (PA_SOURCE_OPENED(u->source->thread_info.state) ? n_alsa_fds : 0), -1);
-        /*pa_log("polling got dsp=%i amq=%i (%i)", r > 0 ? pollfd[POLLFD_DSP].revents : 0, r > 0 ? pollfd[POLLFD_ASYNCQ].revents : 0, r); */
+        r = poll(u->pollfd, POLLFD_ALSA_BASE + (PA_SOURCE_OPENED(u->source->thread_info.state) ? u->n_alsa_fds : 0), -1);
 /*         pa_log("poll end"); */
 
         pa_asyncmsgq_after_poll(u->asyncmsgq);
 
         if (r < 0) {
             if (errno == EINTR) {
-                pollfd[POLLFD_ASYNCQ].revents = 0;
+                u->pollfd[POLLFD_ASYNCQ].revents = 0;
                 revents = 0;
                 continue;
             }
@@ -627,16 +645,26 @@ static void thread_func(void *userdata) {
         pa_assert(r > 0);
 
         if (PA_SOURCE_OPENED(u->source->thread_info.state)) {
-            if ((err = snd_pcm_poll_descriptors_revents(u->pcm_handle, pollfd + POLLFD_ALSA_BASE, n_alsa_fds, &revents)) < 0) {
+            if ((err = snd_pcm_poll_descriptors_revents(u->pcm_handle, u->pollfd + POLLFD_ALSA_BASE, u->n_alsa_fds, &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");
+
+                goto fail;
+            }
 /*             pa_log("got alsa event"); */
         } else
             revents = 0;
         
-        pa_assert((pollfd[POLLFD_ASYNCQ].revents & ~POLLIN) == 0);
+        pa_assert((u->pollfd[POLLFD_ASYNCQ].revents & ~POLLIN) == 0);
     }
 
 fail:
@@ -647,11 +675,8 @@ fail:
 
 finish:
     pa_log_debug("Thread shutting down");
-
-    pa_xfree(pollfd);
 }
 
-
 int pa__init(pa_core *c, pa_module*m) {
     
     pa_modargs *ma = NULL;
@@ -898,6 +923,7 @@ void pa__done(pa_core *c, pa_module*m) {
         snd_pcm_close(u->pcm_handle);
     }
 
+    pa_xfree(u->pollfd);
     pa_xfree(u->device_name);
     pa_xfree(u);
 

commit fedca91468cc75fc4c38d42464d69166d70ddf3a
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Aug 8 21:20:44 2007 +0000

    Remove warning when client is too slow to handle our data
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1591 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c
index bd1605b..893a6c0 100644
--- a/src/pulsecore/protocol-native.c
+++ b/src/pulsecore/protocol-native.c
@@ -402,7 +402,7 @@ static int record_stream_process_msg(pa_msgobject *o, int code, void*userdata, i
         case RECORD_STREAM_MESSAGE_POST_DATA:
             
             if (pa_memblockq_push_align(s->memblockq, chunk) < 0) {
-                pa_log_warn("Failed to push data into output queue.");
+/*                 pa_log_warn("Failed to push data into output queue."); */
                 return -1;
             }
 

commit e4e9a063078ffb6e792848f1f9e441e121ae62b2
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Aug 8 23:48:25 2007 +0000

    be more verbose when device does not support sampling parameters
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1592 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/alsa-util.c b/src/modules/alsa-util.c
index b5dba56..5d49a3c 100644
--- a/src/modules/alsa-util.c
+++ b/src/modules/alsa-util.c
@@ -324,7 +324,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)
@@ -332,12 +332,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;
     }
 

commit 26a024622c045aba55980e100541cad74ca21892
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Aug 8 23:48:47 2007 +0000

    modernize dbus-util.c
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1593 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/dbus-util.c b/src/modules/dbus-util.c
index 7cd9c1d..24936fa 100644
--- a/src/modules/dbus-util.c
+++ b/src/modules/dbus-util.c
@@ -26,7 +26,6 @@
 #include <config.h>
 #endif
 
-#include <assert.h>
 #include <pulsecore/log.h>
 #include <pulsecore/props.h>
 #include <pulse/xmalloc.h>
@@ -35,16 +34,17 @@
 #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,12 +71,14 @@ 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))
         return PA_IO_EVENT_NULL;
@@ -83,21 +88,18 @@ 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_unix_fd(watch));
+    pa_assert(fd == dbus_watch_get_unix_fd(watch));
 
     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 +116,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 +130,188 @@ 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_unix_fd(watch),
-                             get_watch_flags(watch),
-                             handle_io_event, (void*) watch);
-    if (NULL == ev)
-        return FALSE;
+    pa_assert(watch);
+    pa_assert(c);
+
+    ev = c->mainloop->io_new(c->mainloop, dbus_watch_get_unix_fd(watch), get_watch_flags(watch), handle_io_event, watch);
 
-    /* dbus_watch_set_data(watch, (void*) ev, c->mainloop->io_free); */
-    dbus_watch_set_data(watch, (void*) ev, NULL);
+    dbus_watch_set_data(watch, ev, NULL);
 
     return TRUE;
 }
 
 /* DBusRemoveWatchFunction callback for pa mainloop */
-static void remove_watch(DBusWatch *watch, void *data)
-{
-    pa_core *c = (pa_core*) data;
-    pa_io_event *ev = (pa_io_event*) dbus_watch_get_data(watch);
+static void remove_watch(DBusWatch *watch, void *data) {
+    pa_core *c = PA_CORE(data);
+    pa_io_event *ev;
 
-    /* free the event */
-    if (NULL != ev)
+    pa_assert(watch);
+    pa_assert(c);
+    
+    if ((ev = dbus_watch_get_data(watch)))
         c->mainloop->io_free(ev);
 }
 
 /* DBusWatchToggledFunction callback for pa mainloop */
-static void toggle_watch(DBusWatch *watch, void *data)
-{
-    pa_core *c = (pa_core*) data;
-    pa_io_event *ev = (pa_io_event*) dbus_watch_get_data(watch);
+static void toggle_watch(DBusWatch *watch, void *data) {
+    pa_core *c = PA_CORE(data);
+    pa_io_event *ev;
+
+    pa_assert(watch);
+    pa_core_assert_ref(c);
+    
+    pa_assert_se(ev = dbus_watch_get_data(watch));
 
     /* get_watch_flags() checks if the watch is enabled */
     c->mainloop->io_enable(ev, get_watch_flags(watch));
 }
 
 /* DBusAddTimeoutFunction callback for pa mainloop */
-static dbus_bool_t add_timeout(DBusTimeout *timeout, void *data)
-{
-    struct timeval tv;
+static dbus_bool_t add_timeout(DBusTimeout *timeout, void *data) {
+    pa_core *c = PA_CORE(data);
     pa_time_event *ev;
-    pa_core *c = (pa_core*) data;
+    struct timeval tv;
+
+    pa_assert(timeout);
+    pa_assert(c);
 
     if (!dbus_timeout_get_enabled(timeout))
         return FALSE;
 
-    if (!pa_gettimeofday(&tv))
-        return -1;
-
+    pa_gettimeofday(&tv);
     pa_timeval_add(&tv, dbus_timeout_get_interval(timeout) * 1000);
 
-    ev = c->mainloop->time_new(c->mainloop, &tv, handle_time_event,
-                               (void*) timeout);
-    if (NULL == ev)
-        return FALSE;
+    ev = c->mainloop->time_new(c->mainloop, &tv, handle_time_event, timeout);
 
-    /* dbus_timeout_set_data(timeout, (void*) ev, c->mainloop->time_free); */
-    dbus_timeout_set_data(timeout, (void*) ev, NULL);
+    dbus_timeout_set_data(timeout, ev, NULL);
 
     return TRUE;
 }
 
 /* DBusRemoveTimeoutFunction callback for pa mainloop */
-static void remove_timeout(DBusTimeout *timeout, void *data)
-{
-    pa_core *c = (pa_core*) data;
-    pa_time_event *ev = (pa_time_event*) dbus_timeout_get_data(timeout);
+static void remove_timeout(DBusTimeout *timeout, void *data) {
+    pa_core *c = PA_CORE(data);
+    pa_time_event *ev;
 
-    /* free the event */
-    if (NULL != ev)
+    pa_assert(timeout);
+    pa_assert(c);
+    
+    if ((ev = dbus_timeout_get_data(timeout)))
         c->mainloop->time_free(ev);
 }
 
 /* DBusTimeoutToggledFunction callback for pa mainloop */
-static void toggle_timeout(DBusTimeout *timeout, void *data)
-{
-    struct timeval tv;
-    pa_core *c = (pa_core*) data;
-    pa_time_event *ev = (pa_time_event*) dbus_timeout_get_data(timeout);
+static void toggle_timeout(DBusTimeout *timeout, void *data) {
+    pa_core *c = PA_CORE(data);
+    pa_time_event *ev;
+
+    pa_assert(timeout);
+    pa_assert(c);
+    
+    pa_assert_se(ev = dbus_timeout_get_data(timeout));
 
     if (dbus_timeout_get_enabled(timeout)) {
+        struct timeval tv;
+        
         pa_gettimeofday(&tv);
         pa_timeval_add(&tv, dbus_timeout_get_interval(timeout) * 1000);
+        
         c->mainloop->time_restart(ev, &tv);
-    } else {
-        /* disable the timeout */
+    } else
         c->mainloop->time_restart(ev, NULL);
-    }
 }
 
-static void
-pa_dbus_connection_free(pa_dbus_connection *c)
-{
-    assert(c);
-    assert(!dbus_connection_get_is_connected(c->connection));
-
-    /* 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);
-}
+static void wakeup_main(void *userdata) {
+    pa_dbus_connection *c = userdata;
 
-static void
-wakeup_main(void *userdata)
-{
-    pa_dbus_connection *c = (pa_dbus_connection*) userdata;
+    pa_assert(c);
+    
     /* this will wakeup the mainloop and dispatch events, although
      * it may not be the cleanest way of accomplishing it */
     c->core->mainloop->defer_enable(c->dispatch_event, 1);
 }
 
-static pa_dbus_connection* pa_dbus_connection_new(pa_core* c, DBusConnection *conn, const char* name)
-{
-    pa_dbus_connection *pconn = 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;

commit a69f4705c5814cbb29e5ab7dab699adf5eb22253
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Aug 8 23:49:17 2007 +0000

    modernize module-hal-detect.c and check for ALSA pcm_class != modem
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1594 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-hal-detect.c b/src/modules/module-hal-detect.c
index 6ae9cd0..84ac0ce 100644
--- a/src/modules/module-hal-detect.c
+++ b/src/modules/module-hal-detect.c
@@ -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>
@@ -55,25 +54,6 @@ 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",
-#endif
-};
-
 struct device {
     uint32_t index;
     char *udi;
@@ -81,13 +61,10 @@ struct device {
 
 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 +72,23 @@ 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 void hal_device_free(struct device* d) {
+    pa_assert(d);
+    
     pa_xfree(d->udi);
     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 +96,7 @@ static const char *strip_udi(const char *udi) {
 }
 
 #ifdef HAVE_ALSA
+
 typedef enum {
     ALSA_TYPE_SINK,
     ALSA_TYPE_SOURCE,
@@ -126,59 +104,61 @@ 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_device_get_alsa_device(LibHalContext *ctx, const char *udi,
-                                      DBusError *error)
-{
-    return libhal_device_get_property_int(ctx, udi, "alsa.device", 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);
+    
+    return r;
 }
 
-static pa_module* hal_device_load_alsa(struct userdata *u, const char *udi,
-                                       DBusError  *error)
-{
+static pa_module* hal_device_load_alsa(struct userdata *u, const char *udi) {
     char args[128];
     alsa_type_t type;
     int device, card;
     const char *module_name;
+    DBusError error;
+    
+    dbus_error_init(&error);
 
-    type = hal_device_get_alsa_type(u->ctx, udi, error);
-    if (dbus_error_is_set(error) || type == ALSA_TYPE_OTHER)
-        return NULL;
+    type = hal_alsa_device_get_type(u->context, udi, &error);
+    if (dbus_error_is_set(&error) || type == ALSA_TYPE_OTHER)
+        goto fail;
 
-    device = hal_device_get_alsa_device(u->ctx, udi, error);
-    if (dbus_error_is_set(error) || device != 0)
-        return NULL;
+    device = libhal_device_get_property_int(u->context, udi, "alsa.device", &error);
+    if (dbus_error_is_set(&error) || device != 0)
+        goto fail;
 
-    card = hal_device_get_alsa_card(u->ctx, udi, error);
-    if (dbus_error_is_set(error))
-        return NULL;
+    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) {
         module_name = "module-alsa-sink";
@@ -191,58 +171,67 @@ static pa_module* hal_device_load_alsa(struct userdata *u, const char *udi,
     pa_log_debug("Loading %s with arguments '%s'", module_name, args);
 
     return pa_module_load(u->core, module_name, args);
+
+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)
-{
+static pa_module* hal_device_load_oss(struct userdata *u, const char *udi) {
     char args[256];
     char* device;
+    DBusError error;
+    
+    dbus_error_init(&error);
 
-    if (!hal_device_is_oss_pcm(u->ctx, udi, error) || dbus_error_is_set(error))
-        return NULL;
+    if (!hal_oss_device_is_pcm(u->context, udi, &error) || dbus_error_is_set(&error))
+        goto fail;
 
-    device = libhal_device_get_property_string(u->ctx, udi, "oss.device_file",
-                                               error);
-    if (!device || dbus_error_is_set(error))
-        return NULL;
+    device = libhal_device_get_property_string(u->context, udi, "oss.device_file", &error);
+    if (!device || dbus_error_is_set(&error))
+        goto fail;
 
     pa_snprintf(args, sizeof(args), "device=%s sink_name=oss_output.%s source_name=oss_input.%s", device, strip_udi(udi), strip_udi(udi));
     libhal_free_string(device);
@@ -250,139 +239,167 @@ static pa_module* hal_device_load_oss(struct userdata *u, const char *udi,
     pa_log_debug("Loading module-oss with arguments '%s'", args);
 
     return pa_module_load(u->core, "module-oss", args);
+
+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 NULL;
 }
 #endif
 
-static dbus_bool_t hal_device_add(struct userdata *u, const char *udi,
-                                  DBusError *error)
-{
+static int hal_device_add(struct userdata *u, const char *udi) {
     pa_module* m = NULL;
     struct device *d;
 
-    switch(u->capability) {
+    pa_assert(u);
+    pa_assert(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);
 #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);
 #endif
-        default:
-            assert(FALSE); /* never reached */
-            break;
-    }
 
-    if (!m || dbus_error_is_set(error))
-        return FALSE;
+    if (!m)
+        return -1;
 
     d = pa_xnew(struct device, 1);
     d->udi = pa_xstrdup(udi);
     d->index = m->index;
-
     pa_hashmap_put(u->devices, d->udi, d);
 
-    return TRUE;
+    return 0;
 }
 
-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_log_info("Trying capability %u (%s)", capability, cap);
+    pa_assert(u);
+    pa_assert(!u->capability);
+    
     dbus_error_init(&error);
-    udis = libhal_find_device_by_capability(u->ctx, cap, &n, &error);
+
+    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++) {
+            if (hal_device_add(u, udis[i]) < 0)
+                pa_log_debug("Not loaded device %s", udis[i]);
+            else
+                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;
+    int b;
 
     dbus_error_init(&error);
-    if (libhal_device_exists(td->u->ctx, td->udi, &error))
-        hal_device_add(td->u, td->udi, &error);
-
+    
+    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);
+        pa_log_error("Error adding device: %s: %s", error.name, error.message);
         dbus_error_free(&error);
-    }
+    } else if (b)
+        hal_device_add(td->u, td->udi);
 
     pa_xfree(td->udi);
     pa_xfree(td);
     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));
+    
     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;
-    }
 
-    /* skip it */
-    if (!has_cap)
+    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
+    }
+        
+    if (!good)
         return;
 
     /* actually add the device 1/2 second later */
@@ -392,104 +409,81 @@ 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 void hal_context_free(LibHalContext* hal_context) {
     DBusError error;
 
     dbus_error_init(&error);
-    libhal_ctx_shutdown(hal_ctx, &error);
-    libhal_ctx_free(hal_ctx);
+    
+    libhal_ctx_shutdown(hal_context, &error);
+    libhal_ctx_free(hal_context);
 
-    if (dbus_error_is_set(&error)) {
+    if (dbus_error_is_set(&error))
         dbus_error_free(&error);
-    }
 }
 
-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 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);
@@ -501,78 +495,82 @@ int pa__init(pa_core *c, pa_module*m) {
     DBusError error;
     pa_dbus_connection *conn;
     struct userdata *u = NULL;
-    LibHalContext *hal_ctx = NULL;
+    LibHalContext *hal_context = NULL;
     int n = 0;
-
-    assert(c);
-    assert(m);
+    
+    pa_assert(c);
+    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);
+        pa_log_error("Unable to contact DBUS system bus: %s: %s", error.name, error.message);
         dbus_error_free(&error);
         return -1;
     }
 
-    if (!(hal_ctx = pa_hal_context_new(c, pa_dbus_connection_get(conn)))) {
+    if (!(hal_context = hal_context_new(c, pa_dbus_connection_get(conn)))) {
         /* pa_hal_context_new() logs appropriate errors */
+        pa_dbus_connection_unref(conn);
         return -1;
     }
 
     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->context = hal_context;
+    u->connection = conn;
+    u->devices = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func);
+    u->capability = NULL;
+    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) {
-#endif
+    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;
-    }
-#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);*/
+    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);
 
     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);
+    
+    if (!libhal_device_property_watch_all(hal_context, &error)) {
+        pa_log_error("Error monitoring device list: %s: %s", error.name, error.message);
         dbus_error_free(&error);
-        userdata_free(u);
+        pa__done(c, m);
         return -1;
     }
 
-    pa_log_info("loaded %i modules.", n);
+    pa_log_info("Loaded %i modules.", n);
 
     return 0;
 }
 
 
 void pa__done(PA_GCC_UNUSED pa_core *c, pa_module *m) {
-    assert (c && m);
+    struct userdata *u;
+    
+    pa_assert(c);
+    pa_assert(m);
+
+    if (!(u = m->userdata))
+        return;
 
-    /* free the user data */
-    userdata_free(m->userdata);
+    if (u->context)
+        hal_context_free(u->context);
+
+    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);
 }

commit 23ba12572589f1912c2d2bb6edce4d47cbcb74bb
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Aug 9 13:36:06 2007 +0000

    fix bug in handling of defer events
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1595 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulse/mainloop.c b/src/pulse/mainloop.c
index 43cbb19..eaa41d5 100644
--- a/src/pulse/mainloop.c
+++ b/src/pulse/mainloop.c
@@ -574,6 +574,7 @@ static void cleanup_defer_events(pa_mainloop *m, int force) {
             }
 
             if (!e->dead && e->enabled) {
+                e->enabled = 0;
                 assert(m->n_enabled_defer_events > 0);
                 m->n_enabled_defer_events--;
             }

commit 0c29a2f1db37ea5c07dc90f282a4e78135e05909
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Aug 9 13:47:25 2007 +0000

    add new function pa_scache_play_item_by_name
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1596 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/core-scache.c b/src/pulsecore/core-scache.c
index d5fe6f2..8a7ba13 100644
--- a/src/pulsecore/core-scache.c
+++ b/src/pulsecore/core-scache.c
@@ -304,6 +304,19 @@ 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);
diff --git a/src/pulsecore/core-scache.h b/src/pulsecore/core-scache.h
index bbf13f1..ab7ec0e 100644
--- a/src/pulsecore/core-scache.h
+++ b/src/pulsecore/core-scache.h
@@ -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);

commit 33cd5e26cf8f7d43902b76172d8027f347e682cb
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Aug 9 13:49:27 2007 +0000

    listen for HAL ACL events; play an event sound on hw coldplug, hotplug and ACL access
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1597 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-hal-detect.c b/src/modules/module-hal-detect.c
index 84ac0ce..ca22d70 100644
--- a/src/modules/module-hal-detect.c
+++ b/src/modules/module-hal-detect.c
@@ -44,6 +44,8 @@
 #include <pulsecore/hashmap.h>
 #include <pulsecore/idxset.h>
 #include <pulsecore/core-util.h>
+#include <pulsecore/namereg.h>
+#include <pulsecore/core-scache.h>
 
 #include <hal/libhal.h>
 
@@ -57,6 +59,7 @@ PA_MODULE_VERSION(PACKAGE_VERSION)
 struct device {
     uint32_t index;
     char *udi;
+    char *sink_name, *source_name;
 };
 
 struct userdata {
@@ -79,6 +82,8 @@ 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);
 }
 
@@ -136,15 +141,22 @@ static int hal_alsa_device_is_modem(LibHalContext *context, const char *udi, DBu
     return r;
 }
 
-static pa_module* hal_device_load_alsa(struct userdata *u, const char *udi) {
+static pa_module* hal_device_load_alsa(struct userdata *u, const char *udi, char **sink_name, char **source_name) {
     char args[128];
     alsa_type_t type;
     int device, card;
     const char *module_name;
     DBusError error;
+    pa_module *m;
     
     dbus_error_init(&error);
 
+    pa_assert(u);
+    pa_assert(sink_name);
+    pa_assert(source_name);
+
+    *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;
@@ -161,16 +173,28 @@ static pa_module* hal_device_load_alsa(struct userdata *u, const char *udi) {
         goto fail;
 
     if (type == ALSA_TYPE_SINK) {
+        *sink_name = pa_sprintf_malloc("alsa_output.%s", strip_udi(udi));
+        
         module_name = "module-alsa-sink";
-        pa_snprintf(args, sizeof(args), "device=hw:%u sink_name=alsa_output.%s", card, strip_udi(udi));
+        pa_snprintf(args, sizeof(args), "device=hw:%u sink_name=%s", card, *sink_name);
     } else {
+        *source_name = pa_sprintf_malloc("alsa_output.%s", strip_udi(udi));
+        
         module_name = "module-alsa-source";
-        pa_snprintf(args, sizeof(args), "device=hw:%u source_name=alsa_input.%s", card, strip_udi(udi));
+        pa_snprintf(args, sizeof(args), "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);
+
+    if (!m) {
+        pa_xfree(*sink_name);
+        pa_xfree(*source_name);
+        *sink_name = *source_name = NULL;
+    }
+    
+    return m;
 
 fail:
     if (dbus_error_is_set(&error)) {
@@ -219,13 +243,20 @@ finish:
     return r;
 }
 
-static pa_module* hal_device_load_oss(struct userdata *u, const char *udi) {
+static pa_module* hal_device_load_oss(struct userdata *u, const char *udi, char **sink_name, char **source_name) {
     char args[256];
     char* device;
     DBusError error;
+    pa_module *m;
     
     dbus_error_init(&error);
 
+    pa_assert(u);
+    pa_assert(sink_name);
+    pa_assert(source_name);
+
+    *sink_name = *source_name = NULL;
+
     if (!hal_oss_device_is_pcm(u->context, udi, &error) || dbus_error_is_set(&error))
         goto fail;
 
@@ -233,12 +264,23 @@ static pa_module* hal_device_load_oss(struct userdata *u, const char *udi) {
     if (!device || dbus_error_is_set(&error))
         goto fail;
 
-    pa_snprintf(args, sizeof(args), "device=%s sink_name=oss_output.%s source_name=oss_input.%s", device, strip_udi(udi), strip_udi(udi));
+    *sink_name = pa_sprintf_malloc("alsa_output.%s", strip_udi(udi));
+    *source_name = pa_sprintf_malloc("alsa_output.%s", strip_udi(udi));
+    
+    pa_snprintf(args, sizeof(args), "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);
 
-    return pa_module_load(u->core, "module-oss", args);
+    m = pa_module_load(u->core, "module-oss", 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)) {
@@ -250,31 +292,34 @@ fail:
 }
 #endif
 
-static int hal_device_add(struct userdata *u, const char *udi) {
+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);
 
 #ifdef HAVE_ALSA
     if (strcmp(u->capability, CAPABILITY_ALSA) == 0)
-        m = hal_device_load_alsa(u, udi);
+        m = hal_device_load_alsa(u, udi, &sink_name, &source_name);
 #endif
 #ifdef HAVE_OSS
     if (strcmp(u->capability, CAPABILITY_OSS) == 0)
-        m = hal_device_load_oss(u, udi);
+        m = hal_device_load_oss(u, udi, &sink_name, &source_name);
 #endif
 
     if (!m)
-        return -1;
+        return NULL;
 
     d = pa_xnew(struct device, 1);
     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 0;
+    return d;
 }
 
 static int hal_device_add_all(struct userdata *u, const char *capability) {
@@ -300,10 +345,15 @@ static int hal_device_add_all(struct userdata *u, const char *capability) {
         u->capability = capability;
         
         for (i = 0; i < n; i++) {
-            if (hal_device_add(u, udis[i]) < 0)
+            struct device *d;
+            
+            if (!(d = hal_device_add(u, udis[i])))
                 pa_log_debug("Not loaded device %s", udis[i]);
-            else
+            else {
+                if (d->sink_name)
+                    pa_scache_play_item_by_name(u->core, "pulse-coldplug", d->sink_name, PA_VOLUME_NORM, 0);
                 count++;
+            }
         }
     }
 
@@ -325,6 +375,7 @@ static void device_added_time_cb(pa_mainloop_api *ea, pa_time_event *ev, const s
     DBusError error;
     struct timerdata *td = userdata;
     int b;
+    struct device *d;
 
     dbus_error_init(&error);
     
@@ -333,8 +384,14 @@ static void device_added_time_cb(pa_mainloop_api *ea, pa_time_event *ev, const s
     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)
-        hal_device_add(td->u, td->udi);
+    } 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);
     pa_xfree(td);
@@ -446,6 +503,66 @@ static void lost_capability_cb(LibHalContext *context, const char *udi, const ch
         device_removed_cb(context, udi);
 }
 
+
+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);
+
+    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))) {
+                
+                if (d->sink_name) {
+                    pa_sink *sink;
+                    
+                    if ((sink = pa_namereg_get(u->core, d->sink_name, PA_NAMEREG_SINK, 0)))
+                        if (pa_sink_suspend(sink, suspend) >= 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)))
+                        pa_source_suspend(source, suspend);
+                }
+            }
+
+        }
+        
+    }
+
+finish:
+    dbus_error_free(&error);
+        
+    return DBUS_HANDLER_RESULT_HANDLED;
+}
+
 static void hal_context_free(LibHalContext* hal_context) {
     DBusError error;
 
@@ -454,8 +571,7 @@ static void hal_context_free(LibHalContext* hal_context) {
     libhal_ctx_shutdown(hal_context, &error);
     libhal_ctx_free(hal_context);
 
-    if (dbus_error_is_set(&error))
-        dbus_error_free(&error);
+    dbus_error_free(&error);
 }
 
 static LibHalContext* hal_context_new(pa_core* c, DBusConnection *conn) {
@@ -485,8 +601,7 @@ fail:
     if (hal_context)
         hal_context_free(hal_context);
 
-    if (dbus_error_is_set(&error))
-        dbus_error_free(&error);
+    dbus_error_free(&error);
 
     return NULL;
 }
@@ -503,16 +618,17 @@ int pa__init(pa_core *c, pa_module*m) {
 
     dbus_error_init(&error);
     
-    if (!(conn = pa_dbus_bus_get(c, DBUS_BUS_SYSTEM, &error))) {
+    if (!(conn = pa_dbus_bus_get(c, 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);
-        dbus_error_free(&error);
-        return -1;
+        goto fail;
     }
 
     if (!(hal_context = hal_context_new(c, pa_dbus_connection_get(conn)))) {
         /* pa_hal_context_new() logs appropriate errors */
         pa_dbus_connection_unref(conn);
-        return -1;
+        goto fail;
     }
 
     u = pa_xnew(struct userdata, 1);
@@ -539,18 +655,30 @@ int pa__init(pa_core *c, pa_module*m) {
     libhal_ctx_set_device_new_capability(hal_context, new_capability_cb);
     libhal_ctx_set_device_lost_capability(hal_context, lost_capability_cb);
 
-    dbus_error_init(&error);
-    
     if (!libhal_device_property_watch_all(hal_context, &error)) {
         pa_log_error("Error monitoring device list: %s: %s", error.name, error.message);
-        dbus_error_free(&error);
-        pa__done(c, m);
-        return -1;
+        goto fail;
     }
 
+    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_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;
+    }
+    
     pa_log_info("Loaded %i modules.", n);
 
     return 0;
+
+fail:
+    dbus_error_free(&error);
+    pa__done(c, m);
+    return -1;
 }
 
 

commit eaddc0195cf12fa76430d843026188dda6d27aaf
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Aug 9 16:27:24 2007 +0000

    by default, store esd socket in /tmp/.esd-`id -u`/socket, instead of /tmp/.esd/socket, to allow multiple simultaneous esd instances. this is only compatible with a patched esd, which however ubuntu and fedora ship now. other distros need to patch their esd as well, or may pass socket=/tmp/.esd/socket to module-protocol-esound-unix
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1598 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-protocol-stub.c b/src/modules/module-protocol-stub.c
index 5c8733f..3edb59e 100644
--- a/src/modules/module-protocol-stub.c
+++ b/src/modules/module-protocol-stub.c
@@ -154,7 +154,6 @@
   #define protocol_free pa_protocol_esound_free
   #define TCPWRAP_SERVICE "esound"
   #define IPV4_PORT ESD_DEFAULT_PORT
-  #define UNIX_SOCKET ESD_UNIX_SOCKET_NAME
   #define MODULE_ARGUMENTS_COMMON "sink", "source", "auth-anonymous", "cookie",
   #ifdef USE_TCP_SOCKETS
     #include "module-esound-protocol-tcp-symdef.h"
@@ -219,6 +218,10 @@ 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);
@@ -262,11 +265,12 @@ 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 */
 
@@ -274,6 +278,10 @@ int pa__init(pa_core *c, pa_module*m) {
         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) {

commit ed01e1adb52c804bc43a4ba7b5a7060071a60030
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Aug 9 17:52:13 2007 +0000

    don't hit an assert when we cannot resume a device
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1599 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-alsa-sink.c b/src/modules/module-alsa-sink.c
index 708dd1f..1a69954 100644
--- a/src/modules/module-alsa-sink.c
+++ b/src/modules/module-alsa-sink.c
@@ -337,8 +337,10 @@ static int unsuspend(struct userdata *u) {
     return 0;
 
 fail:
-    snd_pcm_close(u->pcm_handle);
-    u->pcm_handle = NULL;
+    if (u->pcm_handle) {
+        snd_pcm_close(u->pcm_handle);
+        u->pcm_handle = NULL;
+    }
 
     return -1;
 }
diff --git a/src/modules/module-alsa-source.c b/src/modules/module-alsa-source.c
index 61035c7..553d028 100644
--- a/src/modules/module-alsa-source.c
+++ b/src/modules/module-alsa-source.c
@@ -325,8 +325,10 @@ static int unsuspend(struct userdata *u) {
     return 0;
 
 fail:
-    snd_pcm_close(u->pcm_handle);
-    u->pcm_handle = NULL;
+    if (u->pcm_handle) {
+        snd_pcm_close(u->pcm_handle);
+        u->pcm_handle = NULL;
+    }
 
     return -1;
 }

commit 30ccf9a5c9b31fcb370d3c724a1a02fdea94ce65
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Aug 9 21:05:20 2007 +0000

    add a couple of additional hooks for modules to use
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1600 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/core.c b/src/pulsecore/core.c
index 1a0e50b..2cdd4a8 100644
--- a/src/pulsecore/core.c
+++ b/src/pulsecore/core.c
@@ -164,10 +164,22 @@ pa_core* pa_core_new(pa_mainloop_api *m, int shared) {
 
     c->is_system_instance = 0;
 
-    pa_hook_init(&c->hook_sink_input_new, c);
+    pa_hook_init(&c->hook_sink_new, c);
+    pa_hook_init(&c->hook_sink_new_post, c);
     pa_hook_init(&c->hook_sink_disconnect, c);
-    pa_hook_init(&c->hook_source_output_new, c);
+    pa_hook_init(&c->hook_sink_disconnect_post, c);
+    pa_hook_init(&c->hook_source_new, c);
+    pa_hook_init(&c->hook_source_new_post, c);
     pa_hook_init(&c->hook_source_disconnect, c);
+    pa_hook_init(&c->hook_source_disconnect_post, c);
+    pa_hook_init(&c->hook_sink_input_new, c);
+    pa_hook_init(&c->hook_sink_input_new_post, c);
+    pa_hook_init(&c->hook_sink_input_disconnect, c);
+    pa_hook_init(&c->hook_sink_input_disconnect_post, c);
+    pa_hook_init(&c->hook_source_output_new, c);
+    pa_hook_init(&c->hook_source_output_new_post, c);
+    pa_hook_init(&c->hook_source_output_disconnect, c);
+    pa_hook_init(&c->hook_source_output_disconnect_post, c);
 
     pa_property_init(c);
 
@@ -226,10 +238,22 @@ static void core_free(pa_object *o) {
 
     c->mainloop->io_free(c->asyncmsgq_event);
 
-    pa_hook_free(&c->hook_sink_input_new);
+    pa_hook_free(&c->hook_sink_new);
+    pa_hook_free(&c->hook_sink_new_post);
     pa_hook_free(&c->hook_sink_disconnect);
-    pa_hook_free(&c->hook_source_output_new);
+    pa_hook_free(&c->hook_sink_disconnect_post);
+    pa_hook_free(&c->hook_source_new);
+    pa_hook_free(&c->hook_source_new_post);
     pa_hook_free(&c->hook_source_disconnect);
+    pa_hook_free(&c->hook_source_disconnect_post);
+    pa_hook_free(&c->hook_sink_input_new);
+    pa_hook_free(&c->hook_sink_input_new_post);
+    pa_hook_free(&c->hook_sink_input_disconnect);
+    pa_hook_free(&c->hook_sink_input_disconnect_post);
+    pa_hook_free(&c->hook_source_output_new);
+    pa_hook_free(&c->hook_source_output_new_post);
+    pa_hook_free(&c->hook_source_output_disconnect);
+    pa_hook_free(&c->hook_source_output_disconnect_post);
 
     pa_xfree(c);
 }
diff --git a/src/pulsecore/core.h b/src/pulsecore/core.h
index a64f217..394785f 100644
--- a/src/pulsecore/core.h
+++ b/src/pulsecore/core.h
@@ -88,10 +88,22 @@ struct pa_core {
 
     /* hooks */
     pa_hook
-        hook_sink_input_new,
+        hook_sink_new,
+        hook_sink_new_post,
         hook_sink_disconnect,
+        hook_sink_disconnect_post,
+        hook_source_new,
+        hook_source_new_post,
+        hook_source_disconnect,
+        hook_source_disconnect_post,
+        hook_sink_input_new,
+        hook_sink_input_new_post,
+        hook_sink_input_disconnect,
+        hook_sink_input_disconnect_post,
         hook_source_output_new,
-        hook_source_disconnect;
+        hook_source_output_new_post,
+        hook_source_output_disconnect,
+        hook_source_output_disconnect_post;
 
     pa_asyncmsgq *asyncmsgq;
     pa_io_event *asyncmsgq_event;
diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c
index 0a7033d..d1bf0ac 100644
--- a/src/pulsecore/sink-input.c
+++ b/src/pulsecore/sink-input.c
@@ -249,6 +249,8 @@ void pa_sink_input_disconnect(pa_sink_input *i) {
     pa_assert(i);
     pa_return_if_fail(i->state != PA_SINK_INPUT_DISCONNECTED);
 
+    pa_hook_fire(&i->sink->core->hook_sink_input_disconnect, i);
+    
     if (i->sync_prev)
         i->sync_prev->sync_next = i->sync_next;
     if (i->sync_next)
@@ -265,12 +267,14 @@ void pa_sink_input_disconnect(pa_sink_input *i) {
     sink_input_set_state(i, PA_SINK_INPUT_DISCONNECTED);
     pa_sink_update_status(i->sink);
     
-    i->sink = NULL;
     i->peek = NULL;
     i->drop = NULL;
     i->kill = NULL;
     i->get_latency = NULL;
     i->underrun = NULL;
+
+    pa_hook_fire(&i->sink->core->hook_sink_input_disconnect_post, i);
+    i->sink = NULL;
     pa_sink_input_unref(i);
 }
 
@@ -309,6 +313,7 @@ void pa_sink_input_put(pa_sink_input *i) {
     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->hook_sink_input_new_post, i);
 }
 
 void pa_sink_input_kill(pa_sink_input*i) {
diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c
index 150e4cb..905fe3f 100644
--- a/src/pulsecore/sink.c
+++ b/src/pulsecore/sink.c
@@ -80,6 +80,9 @@ pa_sink* pa_sink_new(
     pa_return_null_if_fail(!driver || pa_utf8_valid(driver));
     pa_return_null_if_fail(name && pa_utf8_valid(name) && *name);
 
+    if (pa_hook_fire(&core->hook_sink_new, NULL) < 0) /* FIXME */
+        return NULL;
+    
     s = pa_msgobject_new(pa_sink);
 
     if (!(name = pa_namereg_register(core, name, PA_NAMEREG_SINK, s, fail))) {
@@ -146,6 +149,8 @@ pa_sink* pa_sink_new(
 
     pa_subscription_post(core, PA_SUBSCRIPTION_EVENT_SINK | PA_SUBSCRIPTION_EVENT_NEW, s->index);
 
+    pa_hook_fire(&core->hook_sink_new_post, s);
+
     return s;
 }
 
@@ -174,11 +179,11 @@ void pa_sink_disconnect(pa_sink* s) {
     pa_assert(s);
     pa_return_if_fail(s->state != PA_SINK_DISCONNECTED);
 
+    pa_hook_fire(&s->core->hook_sink_disconnect, s);
+    
     pa_namereg_unregister(s->core, s->name);
     pa_idxset_remove_by_data(s->core->sinks, s, NULL);
 
-    pa_hook_fire(&s->core->hook_sink_disconnect, s);
-
     while ((i = pa_idxset_first(s->inputs, NULL))) {
         pa_assert(i != j);
         pa_sink_input_kill(i);
@@ -198,6 +203,8 @@ void pa_sink_disconnect(pa_sink* s) {
     s->set_state = NULL;
 
     pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK | PA_SUBSCRIPTION_EVENT_REMOVE, s->index);
+
+    pa_hook_fire(&s->core->hook_sink_disconnect_post, s);
 }
 
 static void sink_free(pa_object *o) {
diff --git a/src/pulsecore/source-output.c b/src/pulsecore/source-output.c
index 9b828e1..95755f3 100644
--- a/src/pulsecore/source-output.c
+++ b/src/pulsecore/source-output.c
@@ -187,21 +187,26 @@ void pa_source_output_disconnect(pa_source_output*o) {
     pa_assert(o);
     pa_return_if_fail(o->state != PA_SOURCE_OUTPUT_DISCONNECTED);
 
+    pa_hook_fire(&o->source->core->hook_source_output_disconnect, o);
+    
     pa_asyncmsgq_send(o->source->asyncmsgq, PA_MSGOBJECT(o->source), PA_SOURCE_MESSAGE_REMOVE_OUTPUT, o, 0, NULL);
 
     pa_idxset_remove_by_data(o->source->core->source_outputs, o, NULL);
     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);
 
     source_output_set_state(o, PA_SOURCE_OUTPUT_DISCONNECTED);
     pa_source_update_status(o->source);
 
-    o->source = NULL;
     o->push = NULL;
     o->kill = NULL;
     o->get_latency = NULL;
+
+    pa_hook_fire(&o->source->core->hook_source_output_disconnect_post, o);
+
+    o->source = NULL;
+    pa_source_output_unref(o);
 }
 
 static void source_output_free(pa_object* mo) {
@@ -229,6 +234,8 @@ void pa_source_output_put(pa_source_output *o) {
     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->hook_source_output_new_post, o);
 }
 
 void pa_source_output_kill(pa_source_output*o) {
diff --git a/src/pulsecore/source.c b/src/pulsecore/source.c
index 241e1fb..f782593 100644
--- a/src/pulsecore/source.c
+++ b/src/pulsecore/source.c
@@ -73,6 +73,9 @@ pa_source* pa_source_new(
     pa_return_null_if_fail(!driver || pa_utf8_valid(driver));
     pa_return_null_if_fail(pa_utf8_valid(name) && *name);
 
+    if (pa_hook_fire(&core->hook_sink_new, NULL) < 0) /* FIXME */
+        return NULL;
+    
     s = pa_msgobject_new(pa_source);
 
     if (!(name = pa_namereg_register(core, name, PA_NAMEREG_SOURCE, s, fail))) {
@@ -125,6 +128,8 @@ pa_source* pa_source_new(
 
     pa_subscription_post(core, PA_SUBSCRIPTION_EVENT_SOURCE | PA_SUBSCRIPTION_EVENT_NEW, s->index);
 
+    pa_hook_fire(&core->hook_source_new_post, s);
+    
     return s;
 }
 
@@ -153,11 +158,11 @@ void pa_source_disconnect(pa_source *s) {
     pa_assert(s);
     pa_return_if_fail(s->state != PA_SOURCE_DISCONNECTED);
 
+    pa_hook_fire(&s->core->hook_source_disconnect, s);
+
     pa_namereg_unregister(s->core, s->name);
     pa_idxset_remove_by_data(s->core->sources, s, NULL);
 
-    pa_hook_fire(&s->core->hook_source_disconnect, s);
-
     while ((o = pa_idxset_first(s->outputs, NULL))) {
         pa_assert(o != j);
         pa_source_output_kill(o);
@@ -174,6 +179,8 @@ void pa_source_disconnect(pa_source *s) {
     s->set_state = NULL;
 
     pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE | PA_SUBSCRIPTION_EVENT_REMOVE, s->index);
+
+    pa_hook_fire(&s->core->hook_source_disconnect_post, s);
 }
 
 static void source_free(pa_object *o) {

commit 9c89f37acea964a470c42d25e4f145c2b3c6083f
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Aug 9 21:06:08 2007 +0000

    if we get access to a device we don't know yet, add it to our tree instead of ignoring it
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1601 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-hal-detect.c b/src/modules/module-hal-detect.c
index ca22d70..6e1697f 100644
--- a/src/modules/module-hal-detect.c
+++ b/src/modules/module-hal-detect.c
@@ -551,7 +551,9 @@ static DBusHandlerResult filter_cb(DBusConnection *bus, DBusMessage *message, vo
                     if ((source = pa_namereg_get(u->core, d->source_name, PA_NAMEREG_SOURCE, 0)))
                         pa_source_suspend(source, suspend);
                 }
-            }
+                
+            } else if (!suspend)
+                hal_device_add(u, udi);
 
         }
         
@@ -643,7 +645,7 @@ int pa__init(pa_core *c, pa_module*m) {
     n = hal_device_add_all(u, CAPABILITY_ALSA);
 #endif
 #if defined(HAVE_ALSA) && defined(HAVE_OSS)
-    if (n <= 0)
+    if (!u->capability)
 #endif        
 #ifdef HAVE_OSS
         n += hal_device_add_all(u, CAPABILITY_OSS);

commit bb46da3b4aaccdbffa73a7fde19b0f1f73fa75e3
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Aug 9 21:07:14 2007 +0000

    add new module-suspend-on-idle module which suspends sinks/sources which are idle for more than 5s (or any other configurable time). Power saving, here we come\!
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1602 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/Makefile.am b/src/Makefile.am
index 0f2cdec..bea5866 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -877,6 +877,7 @@ modlibexec_LTLIBRARIES += \
 		module-detect.la \
 		module-volume-restore.la \
 		module-rescue-streams.la \
+		module-suspend-on-idle.la \
 		module-http-protocol-tcp.la \
 		module-sine.la \
 		module-native-protocol-tcp.la \
@@ -1027,6 +1028,7 @@ SYMDEF_FILES = \
 		modules/module-jack-source-symdef.h \
 		modules/module-volume-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
 
@@ -1250,6 +1252,12 @@ 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

commit e76efa990e4a157ec6c1599b1fac348fd49acaaf
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Aug 9 21:08:10 2007 +0000

    forgot to actually add the new suspend-on-idle module source code
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1603 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-suspend-on-idle.c b/src/modules/module-suspend-on-idle.c
new file mode 100644
index 0000000..d2c51a1
--- /dev/null
+++ b/src/modules/module-suspend-on-idle.c
@@ -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 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_disconnect_slot, *source_disconnect_slot;
+    pa_hook_slot *sink_input_new_slot, *source_output_new_slot, *sink_input_disconnect_slot, *source_output_disconnect_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_log_info("Sink %s idle for too long, suspending ...", d->sink->name);
+        pa_sink_suspend(d->sink, 1);
+        pa_source_suspend(d->sink->monitor_source, 1);
+    }
+
+    if (d->source && pa_source_used_by(d->source) <= 0) {
+        pa_log_info("Source %s idle for too long, suspending ...", d->source->name);
+        pa_source_suspend(d->source, 1);
+    }
+}
+
+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->source)
+        pa_log_debug("Source %s becomes idle.", d->source->name);
+    if (d->sink)
+        pa_log_debug("Sink %s becomes idle.", d->sink->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);
+    
+    pa_assert_se((d = pa_hashmap_get(u->device_infos, s->sink)));
+    d->userdata->core->mainloop->time_restart(d->time_event, NULL);
+
+    pa_sink_suspend(s->sink, 0);
+    pa_source_suspend(s->sink->monitor_source, 0);
+
+    pa_log_debug("Sink %s becomes busy.", s->sink->name);
+    
+    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);
+    
+    pa_assert_se((d = pa_hashmap_get(u->device_infos, s->source)));
+    d->userdata->core->mainloop->time_restart(d->time_event, NULL);
+
+    pa_source_suspend(s->source, 0);
+    if (s->source->monitor_of)
+        pa_sink_suspend(s->source->monitor_of, 0);
+
+    pa_log_debug("Source %s becomes busy.", s->source->name);
+    
+    return PA_HOOK_OK;
+}
+
+static pa_hook_result_t sink_input_disconnect_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;
+        pa_assert_se((d = pa_hashmap_get(u->device_infos, s->sink)));
+        restart(d);
+    }
+    
+    return PA_HOOK_OK;
+}
+
+static pa_hook_result_t source_output_disconnect_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;
+        pa_assert_se((d = pa_hashmap_get(u->device_infos, s->source)));
+        restart(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_assert(c);
+    pa_object_assert_ref(o);
+    pa_assert(u);
+
+    d = pa_xnew(struct device_info, 1);
+    d->userdata = u;
+    d->source = pa_source_isinstance(o) ? pa_source_ref(PA_SOURCE(o)) : NULL;
+    d->sink = pa_sink_isinstance(o) ? pa_sink_ref(PA_SINK(o)) : NULL;
+    pa_assert(d->source || d->sink);
+    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_disconnect_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);
+
+    pa_assert_se((d = pa_hashmap_remove(u->device_infos, o)));
+    device_info_free(d);
+
+    return PA_HOOK_OK;
+}
+
+int pa__init(pa_core *c, pa_module*m) {
+    pa_modargs *ma = NULL;
+    struct userdata *u;
+    uint32_t timeout = 5;
+    uint32_t idx;
+    pa_sink *sink;
+    pa_source *source;
+
+    assert(c);
+    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 = c;
+    u->timeout = timeout;
+    u->device_infos = pa_hashmap_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
+
+    for (sink = pa_idxset_first(c->sinks, &idx); sink; sink = pa_idxset_next(c->sinks, &idx))
+        device_new_hook_cb(c, PA_OBJECT(sink), u);
+
+    for (source = pa_idxset_first(c->sources, &idx); source; source = pa_idxset_next(c->sources, &idx))
+        device_new_hook_cb(c, PA_OBJECT(source), u);
+
+    u->sink_new_slot = pa_hook_connect(&c->hook_sink_new_post, (pa_hook_cb_t) device_new_hook_cb, u);
+    u->source_new_slot = pa_hook_connect(&c->hook_source_new_post, (pa_hook_cb_t) device_new_hook_cb, u);
+    u->sink_disconnect_slot = pa_hook_connect(&c->hook_sink_disconnect_post, (pa_hook_cb_t) device_disconnect_hook_cb, u);
+    u->source_disconnect_slot = pa_hook_connect(&c->hook_source_disconnect_post, (pa_hook_cb_t) device_disconnect_hook_cb, u);
+
+    u->sink_input_new_slot = pa_hook_connect(&c->hook_sink_input_new_post, (pa_hook_cb_t) sink_input_new_hook_cb, u);
+    u->source_output_new_slot = pa_hook_connect(&c->hook_source_output_new_post, (pa_hook_cb_t) source_output_new_hook_cb, u);
+    u->sink_input_disconnect_slot = pa_hook_connect(&c->hook_sink_input_disconnect_post, (pa_hook_cb_t) sink_input_disconnect_hook_cb, u);
+    u->source_output_disconnect_slot = pa_hook_connect(&c->hook_source_output_disconnect_post, (pa_hook_cb_t) source_output_disconnect_hook_cb, u);
+    
+    pa_modargs_free(ma);
+    return 0;
+
+fail:
+    
+    if (ma)
+        pa_modargs_free(ma);
+    
+    return -1;
+}
+
+void pa__done(pa_core *c, pa_module*m) {
+    struct userdata *u;
+    struct device_info *d;
+    
+    assert(c);
+    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_disconnect_slot)
+        pa_hook_slot_free(u->sink_disconnect_slot);
+
+    if (u->source_new_slot)
+        pa_hook_slot_free(u->source_new_slot);
+    if (u->source_disconnect_slot)
+        pa_hook_slot_free(u->source_disconnect_slot);
+
+    if (u->sink_input_new_slot)
+        pa_hook_slot_free(u->sink_input_new_slot);
+    if (u->sink_input_disconnect_slot)
+        pa_hook_slot_free(u->sink_input_disconnect_slot);
+
+    if (u->source_output_new_slot)
+        pa_hook_slot_free(u->source_output_new_slot);
+    if (u->source_output_disconnect_slot)
+        pa_hook_slot_free(u->source_output_disconnect_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);
+}

commit 0f155748da35e97ea00bea85b2b0e2defa7bf931
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Aug 9 21:17:32 2007 +0000

    protect memimpors with a recursive mutex to avoid deadlock when shutting down
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1604 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/memblock.c b/src/pulsecore/memblock.c
index f3e400e..f0e2b4c 100644
--- a/src/pulsecore/memblock.c
+++ b/src/pulsecore/memblock.c
@@ -743,7 +743,7 @@ pa_memimport* pa_memimport_new(pa_mempool *p, pa_memimport_release_cb_t cb, void
     pa_assert(cb);
 
     i = pa_xnew(pa_memimport, 1);
-    i->mutex = pa_mutex_new(0);
+    i->mutex = pa_mutex_new(1);
     i->pool = p;
     i->segments = pa_hashmap_new(NULL, NULL);
     i->blocks = pa_hashmap_new(NULL, NULL);

commit 02bf2f2dd2c443f3994ca1d0e6c5774b38f05c3c
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Aug 9 21:31:58 2007 +0000

    update default configuration
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1605 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/daemon/default.pa.in b/src/daemon/default.pa.in
index af2a678..47d3e79 100755
--- a/src/daemon/default.pa.in
+++ b/src/daemon/default.pa.in
@@ -1,5 +1,4 @@
-#!@PA_BINARY@ -nF 
-
+#!@PA_BINARY@ -nF
 #
 # This file is part of PulseAudio.
 #
@@ -17,8 +16,19 @@
 # along with PulseAudio; if not, write to the Free Software Foundation,
 # Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
 
+.nofail
+
+### Load 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/email.wav
+load-sample-lazy pulse-coldplug /usr/share/sounds/login.wav
+load-sample-lazy pulse-access /usr/share/sounds/generic.wav
+
+.fail
 
-### Load audio drivers statically
+### 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
@@ -30,17 +40,9 @@
 @HAVE_HAL_TRUE at load-module module-hal-detect
 
 ### Alternatively use the static hardware detection module (for systems that
-### lack HAL support
+### lack HAL support)
 @HAVE_HAL_FALSE at 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
-
 ### Load several protocols
 load-module module-esound-protocol-unix
 load-module module-native-protocol-unix
@@ -65,15 +67,8 @@ load-module module-volume-restore
 ### 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
@@ -85,3 +80,7 @@ load-module module-x11-publish
 ### Please keep in mind that the modules configured by paprefs might conflict with manually
 ### loaded modules.
 load-module module-gconf
+
+### Make some devices default
+#set-default-sink output
+#set-default-source input

commit b751f3a3c76b1376ea11356063d5a62a5304b426
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Aug 9 21:37:19 2007 +0000

    s/login.wav/startup3.wav
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1606 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/daemon/default.pa.in b/src/daemon/default.pa.in
index 47d3e79..63ae82c 100755
--- a/src/daemon/default.pa.in
+++ b/src/daemon/default.pa.in
@@ -21,7 +21,7 @@
 ### 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/email.wav
-load-sample-lazy pulse-coldplug /usr/share/sounds/login.wav
+load-sample-lazy pulse-coldplug /usr/share/sounds/startup3.wav
 load-sample-lazy pulse-access /usr/share/sounds/generic.wav
 
 .fail

commit 1c7b84204e0322933a17db511560e86febb1fcc6
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Aug 9 21:56:23 2007 +0000

    play ACL event sound only when gained access, not when losing it
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1607 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-hal-detect.c b/src/modules/module-hal-detect.c
index 6e1697f..5dffea5 100644
--- a/src/modules/module-hal-detect.c
+++ b/src/modules/module-hal-detect.c
@@ -542,7 +542,8 @@ static DBusHandlerResult filter_cb(DBusConnection *bus, DBusMessage *message, vo
                     
                     if ((sink = pa_namereg_get(u->core, d->sink_name, PA_NAMEREG_SINK, 0)))
                         if (pa_sink_suspend(sink, suspend) >= 0)
-                            pa_scache_play_item_by_name(u->core, "pulse-access", d->sink_name, PA_VOLUME_NORM, 0);
+                            if (!suspend)
+                                pa_scache_play_item_by_name(u->core, "pulse-access", d->sink_name, PA_VOLUME_NORM, 0);
                 }
 
                 if (d->source_name) {

commit 3dfdb217596aec70d04a66ef3698e9674797d878
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Aug 9 21:57:01 2007 +0000

    don't assume that sink/source is already unregistered from namereg when disconnect hook is called
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1608 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-rescue-streams.c b/src/modules/module-rescue-streams.c
index 25005f2..034660e 100644
--- a/src/modules/module-rescue-streams.c
+++ b/src/modules/module-rescue-streams.c
@@ -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) {
@@ -116,8 +130,8 @@ int pa__init(pa_core *c, pa_module*m) {
     pa_modargs *ma = NULL;
     struct userdata *u;
 
-    assert(c);
-    assert(m);
+    pa_assert(c);
+    pa_assert(m);
 
     if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
         pa_log("Failed to parse module arguments");
@@ -135,8 +149,8 @@ int pa__init(pa_core *c, pa_module*m) {
 void pa__done(pa_core *c, pa_module*m) {
     struct userdata *u;
 
-    assert(c);
-    assert(m);
+    pa_assert(c);
+    pa_assert(m);
 
     if (!m->userdata)
         return;

commit 583167722e4e2ed56de682502129d07750d738d9
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Aug 9 23:46:03 2007 +0000

    modernize
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1609 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-x11-bell.c b/src/modules/module-x11-bell.c
index b9c4ad4..0c3c63f 100644
--- a/src/modules/module-x11-bell.c
+++ b/src/modules/module-x11-bell.c
@@ -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);
     }
@@ -99,18 +89,21 @@ static int x11_event_callback(pa_x11_wrapper *w, XEvent *e, void *userdata) {
 }
 
 int pa__init(pa_core *c, 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(c);
+    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));
+    m->userdata = u = pa_xnew(struct userdata, 1);
     u->core = c;
     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));
@@ -130,7 +123,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 +142,22 @@ 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(c, m);
+    
     return -1;
 }
 
 void pa__done(pa_core *c, pa_module*m) {
-    struct userdata *u = m->userdata;
-    assert(c && m && u);
+    struct userdata *u;
+    
+    assert(c);
+    assert(m);
+
+    if (!m->userdata)
+        return;
+
+    u = m->userdata;
 
     pa_xfree(u->scache_item);
     pa_xfree(u->sink_name);

commit d9e44c52cb05df1134087865b1e18de8884af75b
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Aug 9 23:47:06 2007 +0000

    Add X11 XSMP module for hooking into the X11 session manager, for being notified about X11 disconnects before they actually happen, so that we are not killed by the bloody xlibs
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1610 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/Makefile.am b/src/Makefile.am
index bea5866..5edd200 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -924,7 +924,8 @@ 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
@@ -1016,6 +1017,7 @@ 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-alsa-sink-symdef.h \
 		modules/module-alsa-source-symdef.h \
@@ -1173,6 +1175,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
diff --git a/src/daemon/default.pa.in b/src/daemon/default.pa.in
index 63ae82c..583b26c 100755
--- a/src/daemon/default.pa.in
+++ b/src/daemon/default.pa.in
@@ -76,6 +76,9 @@ load-module module-x11-bell sample=x11-bell
 ### Publish connection data in the X11 root window
 load-module module-x11-publish
 
+### Register ourselves in the X11 session manager
+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.
diff --git a/src/modules/module-x11-xsmp.c b/src/modules/module-x11-xsmp.c
new file mode 100644
index 0000000..dc23ebe
--- /dev/null
+++ b/src/modules/module-x11-xsmp.c
@@ -0,0 +1,201 @@
+/* $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)
+
+struct userdata {
+    pa_core *core;
+    SmcConn sm_conn;
+};
+
+static const char* const valid_modargs[] = {
+    NULL
+};
+
+static void die_cb(SmcConn connection, SmPointer client_data){
+    pa_core *c = 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_core *c, pa_module*m) {
+    struct userdata *u = NULL;
+    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;
+    
+    pa_assert(c);
+    pa_assert(m);
+
+    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;
+    }
+
+    m->userdata = u = pa_xnew(struct userdata, 1);
+    u->core = c;
+    u->sm_conn = NULL;
+
+    IceAddConnectionWatch(new_ice_connection, c);
+    
+    memset(&callbacks, 0, sizeof(callbacks));
+    callbacks.die.callback = die_cb;
+    callbacks.die.client_data = c;
+
+    callbacks.save_yourself.callback = save_yourself_cb;
+    callbacks.save_complete.callback = save_complete_cb;
+    callbacks.shutdown_cancelled.callback = shutdown_cancelled_cb;
+    
+    if (!(u->sm_conn = SmcOpenConnection(
+                  NULL, u,
+                  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(u->sm_conn, PA_ELEMENTSOF(prop_list), prop_list);
+
+    pa_log_info("Connected to session manager '%s' as '%s'.", vendor = SmcVendor(u->sm_conn), client_id);
+    free(vendor);
+    free(client_id);
+    
+    pa_modargs_free(ma);
+
+    return 0;
+
+fail:
+    if (ma)
+        pa_modargs_free(ma);
+    
+    pa__done(c, m);
+    
+    return -1;
+}
+
+void pa__done(pa_core *c, pa_module*m) {
+    struct userdata *u;
+    
+    assert(c);
+    assert(m);
+
+    if (!m->userdata)
+        return;
+
+    u = m->userdata;
+
+    if (u->sm_conn)
+        SmcCloseConnection(u->sm_conn, 0, NULL);
+
+    IceRemoveConnectionWatch(new_ice_connection, c);
+    
+    pa_xfree(u);
+}

commit 3b078b20683da8fde7e291373e7cec0c3901cbac
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Aug 10 00:15:20 2007 +0000

    Avoid a race condition when one PA instance gets HAL's ACLAdded message before the previous owner instance has given up access to the device, and thus the device is blocked
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1611 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-hal-detect.c b/src/modules/module-hal-detect.c
index 5dffea5..39d8a44 100644
--- a/src/modules/module-hal-detect.c
+++ b/src/modules/module-hal-detect.c
@@ -540,10 +540,21 @@ static DBusHandlerResult filter_cb(DBusConnection *bus, DBusMessage *message, vo
                 if (d->sink_name) {
                     pa_sink *sink;
                     
-                    if ((sink = pa_namereg_get(u->core, d->sink_name, PA_NAMEREG_SINK, 0)))
-                        if (pa_sink_suspend(sink, suspend) >= 0)
-                            if (!suspend)
+                    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 (pa_sink_suspend(sink, suspend) >= 0) {
+                            if (!suspend && prev_suspended)
                                 pa_scache_play_item_by_name(u->core, "pulse-access", d->sink_name, PA_VOLUME_NORM, 0);
+                            else if (suspend && !prev_suspended) {
+                                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);
+                            }
+                        }
+                    }
                 }
 
                 if (d->source_name) {
@@ -555,9 +566,46 @@ static DBusHandlerResult filter_cb(DBusConnection *bus, DBusMessage *message, vo
                 
             } else if (!suspend)
                 hal_device_add(u, 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;
+
+        pa_log_debug("Got dirty give up message, trying resume ...");
+
+        udi = dbus_message_get_path(message);
+        
+        if ((d = pa_hashmap_get(u->devices, udi))) {
+
+            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 (pa_sink_suspend(sink, 0) >= 0)
+                        if (prev_suspended && !prev_suspended)
+                            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)))
+                    pa_source_suspend(source, 0);
+            }
+            
+        } else 
+            /* Yes, we don't check the UDI for validity, but hopefully HAL will */
+            hal_device_add(u, udi);
     }
 
 finish:
@@ -673,6 +721,12 @@ int pa__init(pa_core *c, pa_module*m) {
         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);
 

commit 1e5ca51016de2b6ea6f9aa8b23e00d62a851b541
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Aug 10 00:29:28 2007 +0000

    handle ACLAdded messages for previously unknown devices identically to a really new device
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1612 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-hal-detect.c b/src/modules/module-hal-detect.c
index 39d8a44..ed21f4d 100644
--- a/src/modules/module-hal-detect.c
+++ b/src/modules/module-hal-detect.c
@@ -503,7 +503,6 @@ static void lost_capability_cb(LibHalContext *context, const char *udi, const ch
         device_removed_cb(context, udi);
 }
 
-
 static DBusHandlerResult filter_cb(DBusConnection *bus, DBusMessage *message, void *userdata) {
     struct userdata*u = userdata;
     DBusError error;
@@ -565,7 +564,7 @@ static DBusHandlerResult filter_cb(DBusConnection *bus, DBusMessage *message, vo
                 }
                 
             } else if (!suspend)
-                hal_device_add(u, udi);
+                device_added_cb(u->context, udi);
         }
         
     } else if (dbus_message_is_signal(message, "org.pulseaudio.Server", "DirtyGiveUpMessage")) {
@@ -605,7 +604,7 @@ static DBusHandlerResult filter_cb(DBusConnection *bus, DBusMessage *message, vo
             
         } else 
             /* Yes, we don't check the UDI for validity, but hopefully HAL will */
-            hal_device_add(u, udi);
+            device_added_cb(u->context, udi);
     }
 
 finish:

commit 10b135a4bf767255ba8497ab51bce68688b6a28f
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Aug 10 00:33:47 2007 +0000

    avoid duplicate loading of modules
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1613 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-hal-detect.c b/src/modules/module-hal-detect.c
index ed21f4d..d73ca0c 100644
--- a/src/modules/module-hal-detect.c
+++ b/src/modules/module-hal-detect.c
@@ -299,7 +299,8 @@ static struct device* hal_device_add(struct userdata *u, const char *udi) {
 
     pa_assert(u);
     pa_assert(u->capability);
-
+    pa_assert(!pa_hashmap_get(u->devices, udi));
+    
 #ifdef HAVE_ALSA
     if (strcmp(u->capability, CAPABILITY_ALSA) == 0)
         m = hal_device_load_alsa(u, udi, &sink_name, &source_name);
@@ -374,22 +375,25 @@ static dbus_bool_t device_has_capability(LibHalContext *context, const char *udi
 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 = userdata;
-    int b;
-    struct device *d;
 
     dbus_error_init(&error);
-    
-    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);
+
+    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);
+            }
         }
     }
 
@@ -406,6 +410,9 @@ static void device_added_cb(LibHalContext *context, const char *udi) {
     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);
 

commit e621071bf1a4f82ce5eba36917e67048ac0c59ef
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Aug 10 12:11:40 2007 +0000

    fix minor memory leakage
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1614 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-volume-restore.c b/src/modules/module-volume-restore.c
index 61a17ae..0f0d998 100644
--- a/src/modules/module-volume-restore.c
+++ b/src/modules/module-volume-restore.c
@@ -396,6 +396,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;
 }
 

commit ffa170807086e959ce7cd9b21fb0c29b104b222b
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Aug 10 14:28:39 2007 +0000

    * drop redundant pa_core argument from module initialization functions
    * make pa__done() implementations optional
    * a couple of modernizations
    * wrap lt_dlsym() at a single place
    * allow passing of an "api" argument to the HAL module, to choose whether OSS devices or ALSA devices should be picked up
    * optimize fd closing a little on linux in the forked gconf helper
    * save a little memory in the xsmp module
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1615 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/Makefile.am b/src/Makefile.am
index 5edd200..8273d33 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -624,6 +624,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 \
@@ -1038,9 +1039,7 @@ EXTRA_DIST += $(SYMDEF_FILES)
 BUILT_SOURCES += $(SYMDEF_FILES)
 
 $(SYMDEF_FILES): modules/module-defs.h.m4
-	-mkdir modules
-	-mkdir modules/gconf
-	-mkdir modules/rtp
+	$(mkdir_p) modules modules/gconf modules/rtp
 	$(M4) -Dfname="$@" $< > $@
 
 # Simple protocol
diff --git a/src/modules/gconf/module-gconf.c b/src/modules/gconf/module-gconf.c
index cbe17d2..7e932c1 100644
--- a/src/modules/gconf/module-gconf.c
+++ b/src/modules/gconf/module-gconf.c
@@ -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,19 +374,46 @@ 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;
+                int fd;
+                
+                errno = 0;
+                fd = strtol(de->d_name, &e, 10);
+                pa_assert(errno == 0 && *e == 0);
 
+                if (fd >= 3)
+                    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);
+#
+#ifdef __linux__
         }
 #endif
 
-        for (i = 3; i < max_fd; i++)
-            close(i);
-
 #ifdef PR_SET_PDEATHSIG
         /* On Linux we can use PR_SET_PDEATHSIG to have the helper
         process killed when the daemon dies abnormally. On non-Linux
@@ -413,12 +442,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 +460,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 +478,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/module-alsa-sink.c b/src/modules/module-alsa-sink.c
index 1a69954..387e70c 100644
--- a/src/modules/module-alsa-sink.c
+++ b/src/modules/module-alsa-sink.c
@@ -704,7 +704,7 @@ finish:
     pa_log_debug("Thread shutting down");
 }
 
-int pa__init(pa_core *c, pa_module*m) {
+int pa__init(pa_module*m) {
     
     pa_modargs *ma = NULL;
     int ret = -1;
@@ -723,7 +723,6 @@ int pa__init(pa_core *c, pa_module*m) {
     int namereg_fail;
     int use_mmap = 1, b;
 
-    pa_assert(c);
     pa_assert(m);
 
     if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
@@ -731,7 +730,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_ALSA) < 0) {
         pa_log("Failed to parse sample specification and channel map");
         goto fail;
@@ -756,7 +755,7 @@ int pa__init(pa_core *c, pa_module*m) {
     }
         
     u = pa_xnew0(struct userdata, 1);
-    u->core = c;
+    u->core = m->core;
     u->module = m;
     m->userdata = u;
     u->use_mmap = use_mmap;
@@ -824,7 +823,7 @@ int pa__init(pa_core *c, pa_module*m) {
         namereg_fail = 0;
     }
 
-    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) {
@@ -881,7 +880,7 @@ int pa__init(pa_core *c, pa_module*m) {
 
         u->mixer_fdl = pa_alsa_fdlist_new();
 
-        if (pa_alsa_fdlist_set_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;
         }
@@ -917,15 +916,14 @@ finish:
 fail:
 
     if (u)
-        pa__done(c, m);
+        pa__done(m);
 
     goto finish;
 }
 
-void pa__done(pa_core *c, pa_module*m) {
+void pa__done(pa_module*m) {
     struct userdata *u;
     
-    pa_assert(c);
     pa_assert(m);
 
     if (!(u = m->userdata))
diff --git a/src/modules/module-alsa-source.c b/src/modules/module-alsa-source.c
index 553d028..7ed430e 100644
--- a/src/modules/module-alsa-source.c
+++ b/src/modules/module-alsa-source.c
@@ -679,7 +679,7 @@ finish:
     pa_log_debug("Thread shutting down");
 }
 
-int pa__init(pa_core *c, pa_module*m) {
+int pa__init(pa_module*m) {
     
     pa_modargs *ma = NULL;
     int ret = -1;
@@ -698,7 +698,6 @@ int pa__init(pa_core *c, pa_module*m) {
     int namereg_fail;
     int use_mmap = 1, b;
 
-    pa_assert(c);
     pa_assert(m);
     
     if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
@@ -706,7 +705,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_ALSA) < 0) {
         pa_log("Failed to parse sample specification");
         goto fail;
@@ -732,7 +731,7 @@ int pa__init(pa_core *c, pa_module*m) {
     }
     
     u = pa_xnew0(struct userdata, 1);
-    u->core = c;
+    u->core = m->core;
     u->module = m;
     m->userdata = u;
     u->use_mmap = use_mmap;
@@ -796,7 +795,7 @@ int pa__init(pa_core *c, pa_module*m) {
         namereg_fail = 0;
     }
 
-    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) {
@@ -849,7 +848,7 @@ int pa__init(pa_core *c, pa_module*m) {
 
         u->mixer_fdl = pa_alsa_fdlist_new();
         
-        if (pa_alsa_fdlist_set_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;
         }
@@ -886,15 +885,14 @@ finish:
 fail:
 
     if (u)
-        pa__done(c, m);
+        pa__done(m);
 
     goto finish;
 }
 
-void pa__done(pa_core *c, pa_module*m) {
+void pa__done(pa_module*m) {
     struct userdata *u;
     
-    pa_assert(c);
     pa_assert(m);
 
     if (!(u = m->userdata))
diff --git a/src/modules/module-cli.c b/src/modules/module-cli.c
index 19ac0c2..fd180bc 100644
--- a/src/modules/module-cli.c
+++ b/src/modules/module-cli.c
@@ -66,15 +66,14 @@ static void eof_and_exit_cb(pa_cli*c, void *userdata) {
     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);
 
-    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);
+void pa__done(pa_module*m) {
     assert(m);
 
-    if (c->running_as_daemon == 0) {
+    if (m->core->running_as_daemon == 0) {
         pa_cli_free(m->userdata);
         pa_stdio_release();
     }
diff --git a/src/modules/module-defs.h.m4 b/src/modules/module-defs.h.m4
index c961412..5bff748 100644
--- a/src/modules/module-defs.h.m4
+++ b/src/modules/module-defs.h.m4
@@ -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);
diff --git a/src/modules/module-detect.c b/src/modules/module-detect.c
index 190cda9..858147e 100644
--- a/src/modules/module-detect.c
+++ b/src/modules/module-detect.c
@@ -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) {
@@ -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 */
-}
-
diff --git a/src/modules/module-esound-compat-spawnfd.c b/src/modules/module-esound-compat-spawnfd.c
index 1aecade..890ebb1 100644
--- a/src/modules/module-esound-compat-spawnfd.c
+++ b/src/modules/module-esound-compat-spawnfd.c
@@ -26,7 +26,6 @@
 #endif
 
 #include <unistd.h>
-#include <assert.h>
 #include <string.h>
 #include <errno.h>
 
@@ -48,21 +47,23 @@ 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("WARNING: write(%u, 1, 1) failed: %s", fd, pa_cstrerror(errno));
 
     close(fd);
 
@@ -76,9 +77,3 @@ finish:
 
     return ret;
 }
-
-void pa__done(pa_core *c, pa_module*m) {
-    assert(c && m);
-}
-
-
diff --git a/src/modules/module-esound-compat-spawnpid.c b/src/modules/module-esound-compat-spawnpid.c
index a9fd166..1cc86d2 100644
--- a/src/modules/module-esound-compat-spawnpid.c
+++ b/src/modules/module-esound-compat-spawnpid.c
@@ -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("WARNING: 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);
-}
-
-
diff --git a/src/modules/module-hal-detect.c b/src/modules/module-hal-detect.c
index d73ca0c..672bdc0 100644
--- a/src/modules/module-hal-detect.c
+++ b/src/modules/module-hal-detect.c
@@ -46,6 +46,7 @@
 #include <pulsecore/core-util.h>
 #include <pulsecore/namereg.h>
 #include <pulsecore/core-scache.h>
+#include <pulsecore/modargs.h>
 
 #include <hal/libhal.h>
 
@@ -55,6 +56,13 @@
 PA_MODULE_AUTHOR("Shahms King")
 PA_MODULE_DESCRIPTION("Detect available audio hardware and load matching drivers")
 PA_MODULE_VERSION(PACKAGE_VERSION)
+#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;
@@ -78,6 +86,11 @@ struct timerdata {
 #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);
     
@@ -663,37 +676,65 @@ fail:
     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_context = NULL;
     int n = 0;
+    pa_modargs *ma;
+    const char *api;
     
-    pa_assert(c);
     pa_assert(m);
 
     dbus_error_init(&error);
-    
-    if (!(conn = pa_dbus_bus_get(c, DBUS_BUS_SYSTEM, &error)) || dbus_error_is_set(&error)) {
+
+    if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
+        pa_log("Failed to parse module arguments");
+        goto fail;
+    }
+
+    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(c, pa_dbus_connection_get(conn)))) {
+    if (!(hal_context = hal_context_new(m->core, pa_dbus_connection_get(conn)))) {
         /* pa_hal_context_new() logs appropriate errors */
         pa_dbus_connection_unref(conn);
         goto fail;
     }
 
     u = pa_xnew(struct userdata, 1);
-    u->core = c;
+    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 = NULL;
+    u->capability = api;
     m->userdata = u;
 
 #ifdef HAVE_ALSA
@@ -736,19 +777,24 @@ int pa__init(pa_core *c, pa_module*m) {
     
     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(c, m);
+    pa__done(m);
+
     return -1;
 }
 
 
-void pa__done(PA_GCC_UNUSED pa_core *c, pa_module *m) {
+void pa__done(pa_module *m) {
     struct userdata *u;
     
-    pa_assert(c);
     pa_assert(m);
 
     if (!(u = m->userdata))
diff --git a/src/modules/module-lirc.c b/src/modules/module-lirc.c
index 452fa1f..6f4e98d 100644
--- a/src/modules/module-lirc.c
+++ b/src/modules/module-lirc.c
@@ -68,11 +68,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 +87,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 +100,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,12 +114,12 @@ 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);
@@ -179,13 +180,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 +199,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 +217,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 +230,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;
diff --git a/src/modules/module-match.c b/src/modules/module-match.c
index 0b051fa..373ed48 100644
--- a/src/modules/module-match.c
+++ b/src/modules/module-match.c
@@ -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;
@@ -185,17 +188,18 @@ static void callback(pa_core *c, pa_subscription_event_type_t t, uint32_t idx, v
     }
 }
 
-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;
diff --git a/src/modules/module-mmkbd-evdev.c b/src/modules/module-mmkbd-evdev.c
index 919b399..03394c0 100644
--- a/src/modules/module-mmkbd-evdev.c
+++ b/src/modules/module-mmkbd-evdev.c
@@ -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,7 +111,7 @@ 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);
@@ -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;
diff --git a/src/modules/module-native-protocol-fd.c b/src/modules/module-native-protocol-fd.c
index 3c1c2bc..b0a9ebb 100644
--- a/src/modules/module-native-protocol-fd.c
+++ b/src/modules/module-native-protocol-fd.c
@@ -26,10 +26,10 @@
 #endif
 
 #include <stdio.h>
-#include <assert.h>
 #include <unistd.h>
 
 #include <pulsecore/module.h>
+#include <pulsecore/macro.h>
 #include <pulsecore/iochannel.h>
 #include <pulsecore/modargs.h>
 #include <pulsecore/protocol-native.h>
@@ -48,25 +48,26 @@ static const char* const valid_modargs[] = {
     NULL,
 };
 
-int pa__init(pa_core *c, pa_module*m) {
+int pa__init(pa_module*m) {
     pa_iochannel *io;
     pa_modargs *ma;
     int fd, r = -1;
-    assert(c && m);
+    
+    pa_assert(m);
 
     if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
-        pa_log("failed to parse module arguments.");
+        pa_log("Failed to parse module arguments.");
         goto finish;
     }
 
     if (pa_modargs_get_value_s32(ma, "fd", &fd) < 0) {
-        pa_log("invalid file descriptor.");
+        pa_log("Invalid file descriptor.");
         goto finish;
     }
 
-    io = pa_iochannel_new(c->mainloop, fd, fd);
+    io = pa_iochannel_new(m->core->mainloop, fd, fd);
 
-    if (!(m->userdata = pa_protocol_native_new_iochannel(c, io, m, ma))) {
+    if (!(m->userdata = pa_protocol_native_new_iochannel(m->core, io, m, ma))) {
         pa_iochannel_free(io);
         goto finish;
     }
@@ -80,8 +81,8 @@ finish:
     return r;
 }
 
-void pa__done(pa_core *c, pa_module*m) {
-    assert(c && m);
+void pa__done(pa_module*m) {
+    pa_assert(m);
 
     pa_protocol_native_free(m->userdata);
 }
diff --git a/src/modules/module-null-sink.c b/src/modules/module-null-sink.c
index f0e3a06..2ede01a 100644
--- a/src/modules/module-null-sink.c
+++ b/src/modules/module-null-sink.c
@@ -198,13 +198,12 @@ 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;
 
-    pa_assert(c);
     pa_assert(m);
 
     if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
@@ -212,20 +211,20 @@ 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("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_assert_se(u->asyncmsgq = pa_asyncmsgq_new(0));
     
-    if (!(u->sink = pa_sink_new(c, __FILE__, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss, &map))) {
+    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;
     }
@@ -254,15 +253,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;
 
-    pa_assert(c);
     pa_assert(m);
 
     if (!(u = m->userdata))
diff --git a/src/modules/module-oss.c b/src/modules/module-oss.c
index a43bdb3..d93d8c7 100644
--- a/src/modules/module-oss.c
+++ b/src/modules/module-oss.c
@@ -1059,7 +1059,7 @@ finish:
     pa_log_debug("Thread shutting down");
 }
 
-int pa__init(pa_core *c, pa_module*m) {
+int pa__init(pa_module*m) {
     
     struct audio_buf_info info;
     struct userdata *u = NULL;
@@ -1075,7 +1075,6 @@ int pa__init(pa_core *c, pa_module*m) {
     const char *name;
     int namereg_fail;
 
-    pa_assert(c);
     pa_assert(m);
 
     if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
@@ -1095,7 +1094,7 @@ int pa__init(pa_core *c, pa_module*m) {
 
     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");
         goto fail;
@@ -1150,7 +1149,7 @@ int pa__init(pa_core *c, pa_module*m) {
     pa_assert(frag_size > 0);
 
     u = pa_xnew0(struct userdata, 1);
-    u->core = c;
+    u->core = m->core;
     u->module = m;
     m->userdata = u;
     u->fd = fd;
@@ -1206,7 +1205,7 @@ int pa__init(pa_core *c, pa_module*m) {
             namereg_fail = 0;
         }
 
-        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");
@@ -1260,7 +1259,7 @@ try_write:
             namereg_fail = 0;
         }
 
-        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");
@@ -1310,7 +1309,7 @@ go_on:
 fail:
 
     if (u)
-        pa__done(c, m);
+        pa__done(m);
     else if (fd >= 0)
         close(fd);
 
@@ -1320,10 +1319,9 @@ fail:
     return -1;
 }
 
-void pa__done(pa_core *c, pa_module*m) {
+void pa__done(pa_module*m) {
     struct userdata *u;
 
-    pa_assert(c);
     pa_assert(m);
 
     if (!(u = m->userdata))
diff --git a/src/modules/module-pipe-sink.c b/src/modules/module-pipe-sink.c
index 83ee06b..1b6d081 100644
--- a/src/modules/module-pipe-sink.c
+++ b/src/modules/module-pipe-sink.c
@@ -232,7 +232,7 @@ 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;
     struct stat st;
     pa_sample_spec ss;
@@ -240,7 +240,6 @@ int pa__init(pa_core *c, pa_module*m) {
     pa_modargs *ma;
     char *t;
 
-    pa_assert(c);
     pa_assert(m);
 
     if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
@@ -248,14 +247,14 @@ 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("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_memchunk_reset(&u->memchunk);
@@ -283,7 +282,7 @@ int pa__init(pa_core *c, pa_module*m) {
         goto fail;
     }
 
-    if (!(u->sink = pa_sink_new(c, __FILE__, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss, &map))) {
+    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;
     }
@@ -309,15 +308,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;
     
-    pa_assert(c);
     pa_assert(m);
 
     if (!(u = m->userdata))
diff --git a/src/modules/module-pipe-source.c b/src/modules/module-pipe-source.c
index a5f95f9..a8fbcf3 100644
--- a/src/modules/module-pipe-source.c
+++ b/src/modules/module-pipe-source.c
@@ -210,7 +210,7 @@ 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;
     struct stat st;
     pa_sample_spec ss;
@@ -218,7 +218,6 @@ int pa__init(pa_core *c, pa_module*m) {
     pa_modargs *ma;
     char *t;
 
-    pa_assert(c);
     pa_assert(m);
 
     if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
@@ -226,14 +225,14 @@ 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("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_memchunk_reset(&u->memchunk);
@@ -261,7 +260,7 @@ int pa__init(pa_core *c, pa_module*m) {
         goto fail;
     }
 
-    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;
     }
@@ -286,15 +285,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;
     
-    pa_assert(c);
     pa_assert(m);
 
     if (!(u = m->userdata))
diff --git a/src/modules/module-protocol-stub.c b/src/modules/module-protocol-stub.c
index 3edb59e..fb7cf22 100644
--- a/src/modules/module-protocol-stub.c
+++ b/src/modules/module-protocol-stub.c
@@ -29,7 +29,6 @@
 #include <string.h>
 #include <errno.h>
 #include <stdio.h>
-#include <assert.h>
 #include <unistd.h>
 #include <limits.h>
 
@@ -43,10 +42,9 @@
 #include <netinet/in.h>
 #endif
 
-#include "../pulsecore/winsock.h"
-
 #include <pulse/xmalloc.h>
 
+#include <pulsecore/winsock.h>
 #include <pulsecore/core-error.h>
 #include <pulsecore/module.h>
 #include <pulsecore/socket-server.h>
@@ -204,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)
@@ -224,7 +221,7 @@ int pa__init(pa_core *c, pa_module*m) {
 #endif
 #endif
 
-    assert(c && m);
+    pa_assert(m);
 
     if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
         pa_log("Failed to parse module arguments");
@@ -242,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)
@@ -274,7 +271,7 @@ int pa__init(pa_core *c, pa_module*m) {
     /* 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;
     }
@@ -292,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
@@ -341,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;
 
@@ -366,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-rescue-streams.c b/src/modules/module-rescue-streams.c
index 034660e..fa22d60 100644
--- a/src/modules/module-rescue-streams.c
+++ b/src/modules/module-rescue-streams.c
@@ -126,11 +126,10 @@ 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;
 
-    pa_assert(c);
     pa_assert(m);
 
     if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
@@ -139,17 +138,16 @@ 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->hook_sink_disconnect, (pa_hook_cb_t) sink_hook_callback, NULL);
+    u->source_slot = pa_hook_connect(&m->core->hook_source_disconnect, (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;
 
-    pa_assert(c);
     pa_assert(m);
 
     if (!m->userdata)
diff --git a/src/modules/module-sine.c b/src/modules/module-sine.c
index 797ba44..f2830ff 100644
--- a/src/modules/module-sine.c
+++ b/src/modules/module-sine.c
@@ -114,7 +114,7 @@ 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;
@@ -130,13 +130,13 @@ int pa__init(pa_core *c, pa_module*m) {
     }
 
     m->userdata = u = pa_xnew0(struct userdata, 1);
-    u->core = c;
+    u->core = m->core;
     u->module = m;
     u->sink_input = NULL;
     u->memblock = NULL;
     u->peek_index = 0;
 
-    if (!(sink = pa_namereg_get(c, pa_modargs_get_value(ma, "sink", NULL), 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;
     }
@@ -151,7 +151,7 @@ int pa__init(pa_core *c, pa_module*m) {
         goto fail;
     }
 
-    u->memblock = pa_memblock_new(c->mempool, pa_bytes_per_second(&ss));
+    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);
@@ -165,7 +165,7 @@ 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_cb;
@@ -182,14 +182,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;
     
-    pa_assert(c);
     pa_assert(m);
 
     if (!(u = m->userdata))
diff --git a/src/modules/module-suspend-on-idle.c b/src/modules/module-suspend-on-idle.c
index d2c51a1..ad14864 100644
--- a/src/modules/module-suspend-on-idle.c
+++ b/src/modules/module-suspend-on-idle.c
@@ -209,7 +209,7 @@ static pa_hook_result_t device_disconnect_hook_cb(pa_core *c, pa_object *o, stru
     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;
     uint32_t timeout = 5;
@@ -217,8 +217,7 @@ int pa__init(pa_core *c, pa_module*m) {
     pa_sink *sink;
     pa_source *source;
 
-    assert(c);
-    assert(m);
+    pa_assert(m);
 
     if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
         pa_log("Failed to parse module arguments.");
@@ -231,25 +230,25 @@ int pa__init(pa_core *c, pa_module*m) {
     }
     
     m->userdata = u = pa_xnew(struct userdata, 1);
-    u->core = c;
+    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(c->sinks, &idx); sink; sink = pa_idxset_next(c->sinks, &idx))
-        device_new_hook_cb(c, PA_OBJECT(sink), u);
+    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(c->sources, &idx); source; source = pa_idxset_next(c->sources, &idx))
-        device_new_hook_cb(c, PA_OBJECT(source), 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(&c->hook_sink_new_post, (pa_hook_cb_t) device_new_hook_cb, u);
-    u->source_new_slot = pa_hook_connect(&c->hook_source_new_post, (pa_hook_cb_t) device_new_hook_cb, u);
-    u->sink_disconnect_slot = pa_hook_connect(&c->hook_sink_disconnect_post, (pa_hook_cb_t) device_disconnect_hook_cb, u);
-    u->source_disconnect_slot = pa_hook_connect(&c->hook_source_disconnect_post, (pa_hook_cb_t) device_disconnect_hook_cb, u);
+    u->sink_new_slot = pa_hook_connect(&m->core->hook_sink_new_post, (pa_hook_cb_t) device_new_hook_cb, u);
+    u->source_new_slot = pa_hook_connect(&m->core->hook_source_new_post, (pa_hook_cb_t) device_new_hook_cb, u);
+    u->sink_disconnect_slot = pa_hook_connect(&m->core->hook_sink_disconnect_post, (pa_hook_cb_t) device_disconnect_hook_cb, u);
+    u->source_disconnect_slot = pa_hook_connect(&m->core->hook_source_disconnect_post, (pa_hook_cb_t) device_disconnect_hook_cb, u);
 
-    u->sink_input_new_slot = pa_hook_connect(&c->hook_sink_input_new_post, (pa_hook_cb_t) sink_input_new_hook_cb, u);
-    u->source_output_new_slot = pa_hook_connect(&c->hook_source_output_new_post, (pa_hook_cb_t) source_output_new_hook_cb, u);
-    u->sink_input_disconnect_slot = pa_hook_connect(&c->hook_sink_input_disconnect_post, (pa_hook_cb_t) sink_input_disconnect_hook_cb, u);
-    u->source_output_disconnect_slot = pa_hook_connect(&c->hook_source_output_disconnect_post, (pa_hook_cb_t) source_output_disconnect_hook_cb, u);
+    u->sink_input_new_slot = pa_hook_connect(&m->core->hook_sink_input_new_post, (pa_hook_cb_t) sink_input_new_hook_cb, u);
+    u->source_output_new_slot = pa_hook_connect(&m->core->hook_source_output_new_post, (pa_hook_cb_t) source_output_new_hook_cb, u);
+    u->sink_input_disconnect_slot = pa_hook_connect(&m->core->hook_sink_input_disconnect_post, (pa_hook_cb_t) sink_input_disconnect_hook_cb, u);
+    u->source_output_disconnect_slot = pa_hook_connect(&m->core->hook_source_output_disconnect_post, (pa_hook_cb_t) source_output_disconnect_hook_cb, u);
     
     pa_modargs_free(ma);
     return 0;
@@ -262,12 +261,11 @@ fail:
     return -1;
 }
 
-void pa__done(pa_core *c, pa_module*m) {
+void pa__done(pa_module*m) {
     struct userdata *u;
     struct device_info *d;
     
-    assert(c);
-    assert(m);
+    pa_assert(m);
 
     if (!m->userdata)
         return;
diff --git a/src/modules/module-volume-restore.c b/src/modules/module-volume-restore.c
index 0f0d998..addd937 100644
--- a/src/modules/module-volume-restore.c
+++ b/src/modules/module-volume-restore.c
@@ -420,11 +420,10 @@ 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);
 
     if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
@@ -444,16 +443,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->hook_sink_input_new, (pa_hook_cb_t) sink_input_hook_callback, u);
+    u->source_output_hook_slot = pa_hook_connect(&m->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);
 
@@ -470,10 +468,9 @@ 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);
 
     if (!(u = m->userdata))
diff --git a/src/modules/module-x11-bell.c b/src/modules/module-x11-bell.c
index 0c3c63f..e59db83 100644
--- a/src/modules/module-x11-bell.c
+++ b/src/modules/module-x11-bell.c
@@ -88,14 +88,13 @@ 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;
     
-    pa_assert(c);
     pa_assert(m);
 
     if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
@@ -104,12 +103,12 @@ int pa__init(pa_core *c, pa_module*m) {
     }
 
     m->userdata = u = pa_xnew(struct userdata, 1);
-    u->core = c;
+    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;
@@ -143,16 +142,15 @@ 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 (!m->userdata)
         return;
diff --git a/src/modules/module-x11-publish.c b/src/modules/module-x11-publish.c
index fd1d532..7da9cc2 100644
--- a/src/modules/module-x11-publish.c
+++ b/src/modules/module-x11-publish.c
@@ -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
index dc23ebe..4ef437a 100644
--- a/src/modules/module-x11-xsmp.c
+++ b/src/modules/module-x11-xsmp.c
@@ -49,17 +49,14 @@ PA_MODULE_AUTHOR("Lennart Poettering")
 PA_MODULE_DESCRIPTION("X11 session management")
 PA_MODULE_VERSION(PACKAGE_VERSION)
 
-struct userdata {
-    pa_core *core;
-    SmcConn sm_conn;
-};
+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 = client_data;
+    pa_core *c = PA_CORE(client_data);
 
     pa_log_debug("Got die message from XSM. Exiting...");
     
@@ -98,18 +95,26 @@ static void new_ice_connection(IceConn connection, IcePointer client_data, Bool
         c->mainloop->io_free(*watch_data);
 }
 
-int pa__init(pa_core *c, pa_module*m) {
-    struct userdata *u = NULL;
+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(c);
     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;
@@ -119,23 +124,19 @@ int pa__init(pa_core *c, pa_module*m) {
         pa_log("X11 session manager not running.");
         goto fail;
     }
-
-    m->userdata = u = pa_xnew(struct userdata, 1);
-    u->core = c;
-    u->sm_conn = NULL;
-
-    IceAddConnectionWatch(new_ice_connection, c);
     
     memset(&callbacks, 0, sizeof(callbacks));
     callbacks.die.callback = die_cb;
-    callbacks.die.client_data = c;
-
+    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 (!(u->sm_conn = SmcOpenConnection(
-                  NULL, u,
+    if (!(m->userdata = connection = SmcOpenConnection(
+                  NULL, m->core,
                   SmProtoMajor, SmProtoMinor,
                   SmcSaveYourselfProcMask | SmcDieProcMask | SmcSaveCompleteProcMask | SmcShutdownCancelledProcMask,
                   &callbacks, NULL, &client_id,
@@ -162,9 +163,9 @@ int pa__init(pa_core *c, pa_module*m) {
     prop_user.vals = &val_user;
     prop_list[1] = &prop_user;
 
-    SmcSetProperties(u->sm_conn, PA_ELEMENTSOF(prop_list), prop_list);
+    SmcSetProperties(connection, PA_ELEMENTSOF(prop_list), prop_list);
 
-    pa_log_info("Connected to session manager '%s' as '%s'.", vendor = SmcVendor(u->sm_conn), client_id);
+    pa_log_info("Connected to session manager '%s' as '%s'.", vendor = SmcVendor(connection), client_id);
     free(vendor);
     free(client_id);
     
@@ -176,26 +177,19 @@ 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;
-    
-    assert(c);
-    assert(m);
-
-    if (!m->userdata)
-        return;
-
-    u = m->userdata;
+void pa__done(pa_module*m) {
+    pa_assert(m);
 
-    if (u->sm_conn)
-        SmcCloseConnection(u->sm_conn, 0, NULL);
+    if (m->userdata)
+        SmcCloseConnection(m->userdata, 0, NULL);
 
-    IceRemoveConnectionWatch(new_ice_connection, c);
-    
-    pa_xfree(u);
+    if (ice_in_use) {
+        IceRemoveConnectionWatch(new_ice_connection, m->core);
+        ice_in_use = 0;
+    }
 }
diff --git a/src/modules/module-zeroconf-publish.c b/src/modules/module-zeroconf-publish.c
index 69508ad..3456539 100644
--- a/src/modules/module-zeroconf-publish.c
+++ b/src/modules/module-zeroconf-publish.c
@@ -102,25 +102,25 @@ struct userdata {
 };
 
 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);
+    pa_assert(u && s && s->loaded.valid && ret_ss && ret_description);
 
     if (s->loaded.type == PA_NAMEREG_SINK) {
         pa_sink *sink = pa_idxset_get_by_index(u->core->sinks, s->loaded.index);
-        assert(sink);
+        pa_assert(sink);
         *ret_ss = sink->sample_spec;
         *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);
+        pa_assert(source);
         *ret_ss = source->sample_spec;
         *ret_description = source->description;
     } else
-        assert(0);
+        pa_assert(0);
 }
 
 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)));
@@ -150,8 +150,8 @@ static int publish_service(struct userdata *u, struct service *s) {
     int r = -1;
     AvahiStringList *txt = NULL;
 
-    assert(u);
-    assert(s);
+    pa_assert(u);
+    pa_assert(s);
 
     if (!u->client || avahi_client_get_state(u->client) != AVAHI_CLIENT_S_RUNNING)
         return 0;
@@ -265,7 +265,7 @@ static struct service *get_service(struct userdata *u, const char *name, const c
 static int publish_sink(struct userdata *u, pa_sink *s) {
     struct service *svc;
     int ret;
-    assert(u && s);
+    pa_assert(u && s);
 
     svc = get_service(u, s->name, s->description);
     if (svc->loaded.valid)
@@ -286,7 +286,7 @@ static int publish_source(struct userdata *u, pa_source *s) {
     struct service *svc;
     int ret;
 
-    assert(u && s);
+    pa_assert(u && s);
 
     svc = get_service(u, s->name, s->description);
     if (svc->loaded.valid)
@@ -309,7 +309,7 @@ static int publish_autoload(struct userdata *u, pa_autoload_entry *s) {
     struct service *svc;
     int ret;
 
-    assert(u && s);
+    pa_assert(u && s);
 
     svc = get_service(u, s->name, NULL);
     if (svc->autoload.valid)
@@ -328,7 +328,7 @@ static int publish_autoload(struct userdata *u, pa_autoload_entry *s) {
 
 static int remove_sink(struct userdata *u, uint32_t idx) {
     struct service *svc;
-    assert(u && idx != PA_INVALID_INDEX);
+    pa_assert(u && idx != PA_INVALID_INDEX);
 
     if (!(svc = pa_dynarray_get(u->sink_dynarray, idx)))
         return 0;
@@ -344,7 +344,7 @@ static int remove_sink(struct userdata *u, uint32_t idx) {
 
 static int remove_source(struct userdata *u, uint32_t idx) {
     struct service *svc;
-    assert(u && idx != PA_INVALID_INDEX);
+    pa_assert(u && idx != PA_INVALID_INDEX);
 
     if (!(svc = pa_dynarray_get(u->source_dynarray, idx)))
         return 0;
@@ -360,7 +360,7 @@ static int remove_source(struct userdata *u, uint32_t idx) {
 
 static int remove_autoload(struct userdata *u, uint32_t idx) {
     struct service *svc;
-    assert(u && idx != PA_INVALID_INDEX);
+    pa_assert(u && idx != PA_INVALID_INDEX);
 
     if (!(svc = pa_dynarray_get(u->autoload_dynarray, idx)))
         return 0;
@@ -376,7 +376,7 @@ static int remove_autoload(struct userdata *u, uint32_t idx) {
 
 static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint32_t idx, void *userdata) {
     struct userdata *u = userdata;
-    assert(u && c);
+    pa_assert(u && c);
 
     switch (t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK)
         case PA_SUBSCRIPTION_EVENT_SINK: {
@@ -439,7 +439,7 @@ static int publish_main_service(struct userdata *u);
 
 static void main_entry_group_callback(AvahiEntryGroup *g, AvahiEntryGroupState state, void *userdata) {
     struct userdata *u = userdata;
-    assert(u);
+    pa_assert(u);
 
     if (state == AVAHI_ENTRY_GROUP_COLLISION) {
         char *t;
@@ -501,7 +501,7 @@ static int publish_all_services(struct userdata *u) {
     int r = -1;
     uint32_t idx;
 
-    assert(u);
+    pa_assert(u);
 
     pa_log_debug("Publishing services in Zeroconf");
 
@@ -531,7 +531,7 @@ static void unpublish_all_services(struct userdata *u, int rem) {
     void *state = NULL;
     struct service *s;
 
-    assert(u);
+    pa_assert(u);
 
     pa_log_debug("Unpublishing services in Zeroconf");
 
@@ -558,7 +558,7 @@ static void unpublish_all_services(struct userdata *u, int rem) {
 
 static void client_callback(AvahiClient *c, AvahiClientState state, void *userdata) {
     struct userdata *u = userdata;
-    assert(c);
+    pa_assert(c);
 
     u->client = c;
 
@@ -587,7 +587,8 @@ 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;
@@ -599,23 +600,23 @@ 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->subscription = pa_subscription_new(c,
+    u->subscription = pa_subscription_new(m->core,
                                           PA_SUBSCRIPTION_MASK_SINK|
                                           PA_SUBSCRIPTION_MASK_SOURCE|
                                           PA_SUBSCRIPTION_MASK_AUTOLOAD, subscribe_callback, u);
@@ -634,7 +635,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);
@@ -646,8 +647,8 @@ static void service_free(void *p, void *userdata) {
     struct service *s = p;
     struct userdata *u = userdata;
 
-    assert(s);
-    assert(u);
+    pa_assert(s);
+    pa_assert(u);
 
     if (s->entry_group)
         avahi_entry_group_free(s->entry_group);
@@ -657,9 +658,9 @@ static void service_free(void *p, void *userdata) {
     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;
diff --git a/src/pulsecore/ltdl-helper.c b/src/pulsecore/ltdl-helper.c
new file mode 100644
index 0000000..bdce18e
--- /dev/null
+++ b/src/pulsecore/ltdl-helper.c
@@ -0,0 +1,64 @@
+/* $Id$ */
+
+/***
+  This file is part of PulseAudio.
+
+  Copyright 2004-2006 Lennart Poettering
+  Copyright 2006 Pierre Ossman <ossman at 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
index 0000000..5c7388a
--- /dev/null
+++ b/src/pulsecore/ltdl-helper.h
@@ -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/modinfo.c b/src/pulsecore/modinfo.c
index 58394e5..79baef8 100644
--- a/src/pulsecore/modinfo.c
+++ b/src/pulsecore/modinfo.c
@@ -26,12 +26,13 @@
 #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"
 
@@ -40,30 +41,24 @@
 #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,14 +67,15 @@ 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;
@@ -87,6 +83,7 @@ pa_modinfo *pa_modinfo_get_by_name(const char *name) {
 
 void pa_modinfo_free(pa_modinfo *i) {
     assert(i);
+    
     pa_xfree(i->author);
     pa_xfree(i->description);
     pa_xfree(i->usage);
diff --git a/src/pulsecore/modinfo.h b/src/pulsecore/modinfo.h
index 3ee33ed..02e536c 100644
--- a/src/pulsecore/modinfo.h
+++ b/src/pulsecore/modinfo.h
@@ -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);
diff --git a/src/pulsecore/module.c b/src/pulsecore/module.c
index 09b15b8..bd56554 100644
--- a/src/pulsecore/module.c
+++ b/src/pulsecore/module.c
@@ -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"
 
@@ -48,69 +49,31 @@
 
 #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,9 @@ static void pa_module_free(pa_module *m) {
 }
 
 void pa_module_unload(pa_core *c, pa_module *m) {
-    assert(c && m);
+    pa_assert(c && m);
 
-    assert(c->modules);
+    pa_assert(c->modules);
     if (!(m = pa_idxset_remove_by_data(c->modules, m, NULL)))
         return;
 
@@ -210,9 +168,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 +179,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 +211,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 +226,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 +237,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 +248,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 +271,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);
 }
diff --git a/src/pulsecore/module.h b/src/pulsecore/module.h
index 750dfaa..7a93a07 100644
--- a/src/pulsecore/module.h
+++ b/src/pulsecore/module.h
@@ -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);

commit 357c0e415f027aaa306d9918bee8d7410ef91054
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Aug 10 14:49:26 2007 +0000

    fix closing of fds in gconf module
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1616 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/gconf/module-gconf.c b/src/modules/gconf/module-gconf.c
index 7e932c1..24f60b1 100644
--- a/src/modules/gconf/module-gconf.c
+++ b/src/modules/gconf/module-gconf.c
@@ -381,14 +381,17 @@ static int start_client(const char *n, pid_t *pid) {
             struct dirent *de;
 
             while ((de = readdir(d))) {
-                char *e;
+                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 == 0);
+                pa_assert(errno == 0 && e && *e == 0);
 
-                if (fd >= 3)
+                if (fd >= 3 && dirfd(d) != fd)
                     close(fd);
             }
             

commit 72840abe8afca442645b00a54fbf7b31928024c0
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Aug 10 15:09:28 2007 +0000

    minor cleanliness fixes
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1617 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulse/mainloop.c b/src/pulse/mainloop.c
index eaa41d5..0563507 100644
--- a/src/pulse/mainloop.c
+++ b/src/pulse/mainloop.c
@@ -305,6 +305,7 @@ static void mainloop_defer_free(pa_defer_event *e) {
     if (e->enabled) {
         assert(e->mainloop->n_enabled_defer_events > 0);
         e->mainloop->n_enabled_defer_events--;
+        e->enabled = 0;
     }
 }
 
@@ -395,6 +396,7 @@ static void mainloop_time_free(pa_time_event *e) {
     if (e->enabled) {
         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)
@@ -541,6 +543,7 @@ static void cleanup_time_events(pa_mainloop *m, int force) {
             if (!e->dead && e->enabled) {
                 assert(m->n_enabled_time_events > 0);
                 m->n_enabled_time_events--;
+                e->enabled = 0;
             }
 
             if (e->destroy_callback)
@@ -574,9 +577,9 @@ static void cleanup_defer_events(pa_mainloop *m, int force) {
             }
 
             if (!e->dead && e->enabled) {
-                e->enabled = 0;
                 assert(m->n_enabled_defer_events > 0);
                 m->n_enabled_defer_events--;
+                e->enabled = 0;
             }
 
             if (e->destroy_callback)

commit ac49cc2029a40c6017b0c9533c4a27b0a1d7e3dd
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Aug 10 15:51:55 2007 +0000

    do not acces playback pa_messagq from main thread
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1618 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c
index 893a6c0..0816ea6 100644
--- a/src/pulsecore/protocol-native.c
+++ b/src/pulsecore/protocol-native.c
@@ -104,6 +104,10 @@ typedef struct playback_stream {
 
     pa_atomic_t missing;
     size_t last_missing;
+
+    /* Only updated after SINK_INPUT_MESSAGE_UPDATE_LATENCY */
+    int64_t read_index, write_index;
+    size_t resampled_chunk_length;
 } playback_stream;
 
 typedef struct upload_stream {
@@ -175,7 +179,8 @@ enum {
     SINK_INPUT_MESSAGE_FLUSH,
     SINK_INPUT_MESSAGE_TRIGGER,
     SINK_INPUT_MESSAGE_SEEK,
-    SINK_INPUT_MESSAGE_PREBUF_FORCE
+    SINK_INPUT_MESSAGE_PREBUF_FORCE,
+    SINK_INPUT_MESSAGE_UPDATE_LATENCY
 };
 
 enum {
@@ -726,10 +731,10 @@ static void connection_free(pa_object *o) {
     pa_xfree(c);
 }
 
+/* Called from thread context */
 static void request_bytes(playback_stream *s) {
     size_t new_missing, delta, previous_missing;
 
-
 /*     pa_log("request_bytes()"); */
     playback_stream_assert_ref(s);
 
@@ -804,8 +809,9 @@ static void send_record_stream_killed(record_stream *r) {
     pa_pstream_send_tagstruct(r->connection->pstream, t);
 }
 
-/*** sinkinput callbacks ***/
+/*** 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);
     playback_stream *s;
@@ -897,6 +903,13 @@ static int sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int
             
             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:
 
@@ -918,6 +931,7 @@ static int sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int
     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, pa_memchunk *chunk) {
     playback_stream *s;
 
@@ -943,6 +957,7 @@ static int sink_input_peek_cb(pa_sink_input *i, pa_memchunk *chunk) {
     return 0;
 }
 
+/* Called from thread context */
 static void sink_input_drop_cb(pa_sink_input *i, size_t length) {
     playback_stream *s;
 
@@ -976,6 +991,7 @@ static void sink_input_kill_cb(pa_sink_input *i) {
 
 /*** source_output callbacks ***/
 
+/* Called from thread context */
 static void source_output_push_cb(pa_source_output *o, const pa_memchunk *chunk) {
     record_stream *s;
 
@@ -1472,20 +1488,21 @@ static void command_get_playback_latency(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_
     s = pa_idxset_get_by_index(c->output_streams, idx);
     CHECK_VALIDITY(c->pstream, s, 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) */  /* FIXME*/ 
-/*         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, 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);
 }
 

commit d4cb042a563f51d47b7b724d7fa1936896d3be24
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Aug 10 16:47:39 2007 +0000

    move pa_queue to an implementation based on pa_flist
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1619 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/Makefile.am b/src/Makefile.am
index 8273d33..6cb3f28 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -223,7 +223,8 @@ noinst_PROGRAMS = \
 		thread-test \
 		flist-test \
 		asyncq-test \
-		asyncmsgq-test
+		asyncmsgq-test \
+		queue-test
 
 if HAVE_SIGXCPU
 noinst_PROGRAMS += \
@@ -293,6 +294,11 @@ 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)
+
 mcalign_test_SOURCES = tests/mcalign-test.c
 mcalign_test_CFLAGS = $(AM_CFLAGS)
 mcalign_test_LDADD = $(AM_LDADD) $(WINSOCK_LIBS) libpulsecore.la
diff --git a/src/pulsecore/queue.c b/src/pulsecore/queue.c
index 1dd0f60..b095481 100644
--- a/src/pulsecore/queue.c
+++ b/src/pulsecore/queue.c
@@ -25,13 +25,16 @@
 #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,40 +47,42 @@ 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);
-
-        pa_xfree(e);
-        e = n;
-    }
+            destroy(data, userdata);
 
+    pa_assert(!q->front);
+    pa_assert(!q->back);
+    pa_assert(q->length == 0);
+    
     pa_xfree(q);
 }
 
 void pa_queue_push(pa_queue *q, void *p) {
     struct queue_entry *e;
 
-    e = pa_xnew(struct queue_entry, 1);
+    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,24 +93,30 @@ 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--;
 
     return p;
 }
 
 int pa_queue_is_empty(pa_queue *q) {
-    assert(q);
+    pa_assert(q);
+    
     return q->length == 0;
 }
diff --git a/src/tests/queue-test.c b/src/tests/queue-test.c
new file mode 100644
index 0000000..088b074
--- /dev/null
+++ b/src/tests/queue-test.c
@@ -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;
+}

commit 27f75a5a1e5243aeb23664f0b1fc5bea18fcc906
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Aug 10 21:59:51 2007 +0000

    Rename pa_once_t to pa_once
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1620 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/flist.h b/src/pulsecore/flist.h
index 177edd6..69b9c74 100644
--- a/src/pulsecore/flist.h
+++ b/src/pulsecore/flist.h
@@ -47,13 +47,13 @@ void* pa_flist_pop(pa_flist*l);
 #define PA_STATIC_FLIST_DECLARE(name, size, destroy_cb)                 \
     static struct {                                                     \
         pa_flist *flist;                                                \
-        pa_once_t once;                                                 \
+        pa_once once;                                                   \
     } name##_static_flist = { NULL, PA_ONCE_INIT };                     \
     static void name##_init(void) {                                     \
         name##_static_flist.flist = pa_flist_new(size);                 \
     }                                                                   \
     static inline pa_flist* name##_get(void) {                          \
-        pa_once(&name##_static_flist.once, name##_init);                \
+        pa_run_once(&name##_static_flist.once, name##_init);            \
         return name##_static_flist.flist;                               \
     }                                                                   \
     static void name##_destructor(void) PA_GCC_DESTRUCTOR;              \
diff --git a/src/pulsecore/once-posix.c b/src/pulsecore/once-posix.c
index 25ccb03..fd6288f 100644
--- a/src/pulsecore/once-posix.c
+++ b/src/pulsecore/once-posix.c
@@ -33,7 +33,7 @@
 #include "once.h"
 
 /* Not reentrant -- how could it be? */
-void pa_once(pa_once_t *control, pa_once_func_t func) {
+void pa_run_once(pa_once *control, pa_once_func_t func) {
     pa_mutex *m;
 
     pa_assert(control);
diff --git a/src/pulsecore/once.h b/src/pulsecore/once.h
index b260212..d9372d8 100644
--- a/src/pulsecore/once.h
+++ b/src/pulsecore/once.h
@@ -30,17 +30,17 @@
 typedef struct pa_once {
     pa_atomic_ptr_t mutex;
     pa_atomic_t ref, done;
-} pa_once_t;
+} pa_once;
 
 #define PA_ONCE_INIT                                                    \
     {                                                                   \
         .mutex = PA_ATOMIC_PTR_INIT(NULL),                              \
-        .ref = PA_ATOMIC_INIT(0),                                   \
-        .done = PA_ATOMIC_INIT(0)                                   \
+        .ref = PA_ATOMIC_INIT(0),                                       \
+        .done = PA_ATOMIC_INIT(0)                                       \
     }
 
 typedef void (*pa_once_func_t) (void);
 
-void pa_once(pa_once_t *o, pa_once_func_t f);
+void pa_run_once(pa_once *o, pa_once_func_t f);
 
 #endif

commit aff77c162bad2c9375a908a871f01a6fddd02278
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Aug 10 22:00:22 2007 +0000

    update thread test to use pa_once instead of pa_once_t
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1621 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/tests/thread-test.c b/src/tests/thread-test.c
index 2153c98..0077cde 100644
--- a/src/tests/thread-test.c
+++ b/src/tests/thread-test.c
@@ -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);
 

commit f7171e86caef4f71f58d4f65d9cada4e53a19396
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Aug 10 22:01:17 2007 +0000

    Wrap two pa_asyncmsq in a new pa_thread_mq object for bidirectional, lock-free communication between a main loop and a thread
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1622 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/Makefile.am b/src/Makefile.am
index 6cb3f28..2d3af07 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -662,6 +662,7 @@ libpulsecore_la_SOURCES += \
 		pulsecore/flist.c pulsecore/flist.h \
 		pulsecore/asyncmsgq.c pulsecore/asyncmsgqq.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 \
diff --git a/src/pulsecore/thread-mq.c b/src/pulsecore/thread-mq.c
new file mode 100644
index 0000000..224a14c
--- /dev/null
+++ b/src/pulsecore/thread-mq.c
@@ -0,0 +1,119 @@
+/* $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"
+
+static pa_once once = PA_ONCE_INIT;
+static pa_tls *tls;
+
+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_assert(pa_asyncmsgq_get_fd(q->outq) == fd);
+    pa_assert(events == PA_IO_EVENT_INPUT);
+
+    pa_asyncmsgq_after_poll(q->outq);
+
+    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(q->outq, &object, &code, &data, &offset, &chunk, 0) == 0) {
+            int ret;
+
+            ret = pa_asyncmsgq_dispatch(object, code, data, offset, &chunk);
+            pa_asyncmsgq_done(q->outq, ret);
+        }
+
+        if (pa_asyncmsgq_before_poll(q->outq) == 0)
+            break;
+    }
+}
+
+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_after_poll(q->outq);
+    pa_asyncmsgq_free(q->inq);
+    pa_asyncmsgq_free(q->outq);
+    q->inq = q->outq = NULL;
+    
+    q->mainloop = NULL;
+}
+
+static void init_tls(void) {
+    tls = pa_tls_new(NULL);
+}
+
+void pa_thread_mq_install(pa_thread_mq *q) {
+    pa_assert(q);
+
+    pa_run_once(&once, init_tls);
+    pa_tls_set(tls, q);
+}
+
+pa_thread_mq *pa_thread_mq_get(void) {
+    pa_thread_mq *q;
+
+    pa_run_once(&once, init_tls);
+    pa_assert_se(q = pa_tls_get(tls));
+    return q;
+}
+
diff --git a/src/pulsecore/thread-mq.h b/src/pulsecore/thread-mq.h
new file mode 100644
index 0000000..13b6e01
--- /dev/null
+++ b/src/pulsecore/thread-mq.h
@@ -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

commit b3f1a133f1600adc112044aafd799e35462fdf7d
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Aug 10 22:01:54 2007 +0000

    minor update
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1623 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/pstream.c b/src/pulsecore/pstream.c
index ea23880..ed55270 100644
--- a/src/pulsecore/pstream.c
+++ b/src/pulsecore/pstream.c
@@ -238,7 +238,6 @@ pa_pstream *pa_pstream_new(pa_mainloop_api *m, pa_iochannel *io, pa_mempool *poo
     m->defer_enable(p->defer_event, 0);
     
     p->send_queue = pa_queue_new();
-    pa_assert(p->send_queue);
 
     p->write.current = NULL;
     p->write.index = 0;
@@ -377,6 +376,7 @@ void pa_pstream_send_memblock(pa_pstream*p, uint32_t channel, int64_t offset, pa
     p->mainloop->defer_enable(p->defer_event, 1);
 }
 
+/* might be called from thread context */
 static void memimport_release_cb(pa_memimport *i, uint32_t block_id, void *userdata) {
     struct item_info *item;
     pa_pstream *p = userdata;
@@ -400,6 +400,7 @@ static void memimport_release_cb(pa_memimport *i, uint32_t block_id, void *userd
     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) {
     struct item_info *item;
     pa_pstream *p = userdata;

commit 3eae9038ebf428c40aae51354b32beb4909c1cbb
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Aug 10 22:02:39 2007 +0000

    make use of pa_thread_mq everywhere
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1624 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-alsa-sink.c b/src/modules/module-alsa-sink.c
index 387e70c..d3fe885 100644
--- a/src/modules/module-alsa-sink.c
+++ b/src/modules/module-alsa-sink.c
@@ -50,6 +50,7 @@
 #include <pulsecore/macro.h>
 #include <pulsecore/thread.h>
 #include <pulsecore/core-error.h>
+#include <pulsecore/thread-mq.h>
 
 #include "alsa-util.h"
 #include "module-alsa-sink-symdef.h"
@@ -78,7 +79,7 @@ struct userdata {
     pa_module *module;
     pa_sink *sink;
     pa_thread *thread;
-    pa_asyncmsgq *asyncmsgq;
+    pa_thread_mq thread_mq;
     
     snd_pcm_t *pcm_handle;
 
@@ -254,7 +255,7 @@ static int build_pollfd(struct userdata *u) {
     pa_xfree(u->pollfd);
     u->pollfd = pa_xnew0(struct pollfd, POLLFD_ALSA_BASE + u->n_alsa_fds);
 
-    u->pollfd[POLLFD_ASYNCQ].fd = pa_asyncmsgq_get_fd(u->asyncmsgq);
+    u->pollfd[POLLFD_ASYNCQ].fd = pa_asyncmsgq_get_fd(u->thread_mq.inq);
     u->pollfd[POLLFD_ASYNCQ].events = POLLIN;
 
     if ((err = snd_pcm_poll_descriptors(u->pcm_handle, u->pollfd+POLLFD_ALSA_BASE, u->n_alsa_fds)) < 0) {
@@ -528,6 +529,8 @@ static void thread_func(void *userdata) {
 
     pa_log_debug("Thread starting up");
 
+    pa_thread_mq_install(&u->thread_mq);
+    
     if (build_pollfd(u) < 0)
         goto fail;
 
@@ -542,18 +545,18 @@ static void thread_func(void *userdata) {
 /*         pa_log("loop");      */
         
         /* Check whether there is a message for us to process */
-        if (pa_asyncmsgq_get(u->asyncmsgq, &object, &code, &data, &offset, &chunk, 0) == 0) {
+        if (pa_asyncmsgq_get(u->thread_mq.inq, &object, &code, &data, &offset, &chunk, 0) == 0) {
             int ret;
 
 /*             pa_log("processing msg");  */
 
             if (!object && code == PA_MESSAGE_SHUTDOWN) {
-                pa_asyncmsgq_done(u->asyncmsgq, 0);
+                pa_asyncmsgq_done(u->thread_mq.inq, 0);
                 goto finish;
             }
 
             ret = pa_asyncmsgq_dispatch(object, code, data, offset, &chunk);
-            pa_asyncmsgq_done(u->asyncmsgq, ret);
+            pa_asyncmsgq_done(u->thread_mq.inq, ret);
             continue;
         } 
 
@@ -649,14 +652,14 @@ static void thread_func(void *userdata) {
         }
 
         /* Hmm, nothing to do. Let's sleep */
-        if (pa_asyncmsgq_before_poll(u->asyncmsgq) < 0)
+        if (pa_asyncmsgq_before_poll(u->thread_mq.inq) < 0)
             continue;
 
 /*         pa_log("polling for %i", POLLFD_ALSA_BASE + (PA_SINK_OPENED(u->sink->thread_info.state) ? u->n_alsa_fds : 0));    */
         r = poll(u->pollfd, POLLFD_ALSA_BASE + (PA_SINK_OPENED(u->sink->thread_info.state) ? u->n_alsa_fds : 0), -1);
 /*         pa_log("poll end"); */
 
-        pa_asyncmsgq_after_poll(u->asyncmsgq);
+        pa_asyncmsgq_after_poll(u->thread_mq.inq);
 
         if (r < 0) {
             if (errno == EINTR) {
@@ -697,8 +700,8 @@ static void thread_func(void *userdata) {
 fail:
     /* We have to continue processing messages until we receive the
      * SHUTDOWN message */
-    pa_asyncmsgq_post(u->core->asyncmsgq, PA_MSGOBJECT(u->core), PA_CORE_MESSAGE_UNLOAD_MODULE, u->module, 0, NULL, NULL);
-    pa_asyncmsgq_wait_for(u->asyncmsgq, 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");
@@ -762,7 +765,7 @@ int pa__init(pa_module*m) {
     u->first = 1;
     u->n_alsa_fds = 0;
     u->pollfd = NULL;
-    pa_assert_se(u->asyncmsgq = pa_asyncmsgq_new(0));
+    pa_thread_mq_init(&u->thread_mq, m->core->mainloop);
 
     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) {
@@ -835,7 +838,7 @@ int pa__init(pa_module*m) {
     u->sink->userdata = u;
 
     pa_sink_set_module(u->sink, m);
-    pa_sink_set_asyncmsgq(u->sink, u->asyncmsgq);
+    pa_sink_set_asyncmsgq(u->sink, u->thread_mq.inq);
     pa_sink_set_description(u->sink, t = pa_sprintf_malloc(
                                     "ALSA PCM on %s (%s)",
                                     dev,
@@ -933,13 +936,12 @@ void pa__done(pa_module*m) {
         pa_sink_disconnect(u->sink);
 
     if (u->thread) {
-        pa_asyncmsgq_send(u->asyncmsgq, NULL, PA_MESSAGE_SHUTDOWN, NULL, 0, NULL);
+        pa_asyncmsgq_send(u->thread_mq.inq, NULL, PA_MESSAGE_SHUTDOWN, NULL, 0, NULL);
         pa_thread_free(u->thread);
     }
 
-    if (u->asyncmsgq)
-        pa_asyncmsgq_free(u->asyncmsgq);
-
+    pa_thread_mq_done(&u->thread_mq);
+    
     if (u->sink)
         pa_sink_unref(u->sink);
     
diff --git a/src/modules/module-alsa-source.c b/src/modules/module-alsa-source.c
index 7ed430e..55af473 100644
--- a/src/modules/module-alsa-source.c
+++ b/src/modules/module-alsa-source.c
@@ -51,6 +51,7 @@
 #include <pulsecore/macro.h>
 #include <pulsecore/thread.h>
 #include <pulsecore/core-error.h>
+#include <pulsecore/thread-mq.h>
 
 #include "alsa-util.h"
 #include "module-alsa-source-symdef.h"
@@ -78,7 +79,7 @@ struct userdata {
     pa_module *module;
     pa_source *source;
     pa_thread *thread;
-    pa_asyncmsgq *asyncmsgq;
+    pa_thread_mq thread_mq;
 
     snd_pcm_t *pcm_handle;
 
@@ -242,7 +243,7 @@ static int build_pollfd(struct userdata *u) {
     pa_xfree(u->pollfd);
     u->pollfd = pa_xnew0(struct pollfd, POLLFD_ALSA_BASE + u->n_alsa_fds);
 
-    u->pollfd[POLLFD_ASYNCQ].fd = pa_asyncmsgq_get_fd(u->asyncmsgq);
+    u->pollfd[POLLFD_ASYNCQ].fd = pa_asyncmsgq_get_fd(u->thread_mq.inq);
     u->pollfd[POLLFD_ASYNCQ].events = POLLIN;
 
     if ((err = snd_pcm_poll_descriptors(u->pcm_handle, u->pollfd+POLLFD_ALSA_BASE, u->n_alsa_fds)) < 0) {
@@ -516,6 +517,8 @@ static void thread_func(void *userdata) {
 
     pa_log_debug("Thread starting up");
 
+    pa_thread_mq_install(&u->thread_mq);
+    
     if (build_pollfd(u) < 0)
         goto fail;
 
@@ -530,18 +533,18 @@ static void thread_func(void *userdata) {
 /*         pa_log("loop");     */
         
         /* Check whether there is a message for us to process */
-        if (pa_asyncmsgq_get(u->asyncmsgq, &object, &code, &data, &offset, &chunk, 0) == 0) {
+        if (pa_asyncmsgq_get(u->thread_mq.inq, &object, &code, &data, &offset, &chunk, 0) == 0) {
             int ret;
 
 /*             pa_log("processing msg"); */
 
             if (!object && code == PA_MESSAGE_SHUTDOWN) {
-                pa_asyncmsgq_done(u->asyncmsgq, 0);
+                pa_asyncmsgq_done(u->thread_mq.inq, 0);
                 goto finish;
             }
 
             ret = pa_asyncmsgq_dispatch(object, code, data, offset, &chunk);
-            pa_asyncmsgq_done(u->asyncmsgq, ret);
+            pa_asyncmsgq_done(u->thread_mq.inq, ret);
             continue;
         } 
 
@@ -624,14 +627,14 @@ static void thread_func(void *userdata) {
         }
 
         /* Hmm, nothing to do. Let's sleep */
-        if (pa_asyncmsgq_before_poll(u->asyncmsgq) < 0)
+        if (pa_asyncmsgq_before_poll(u->thread_mq.inq) < 0)
             continue;
 
 /*         pa_log("polling for %i", POLLFD_ALSA_BASE + (PA_SOURCE_OPENED(u->source->thread_info.state) ? n_alsa_fds : 0));   */
         r = poll(u->pollfd, POLLFD_ALSA_BASE + (PA_SOURCE_OPENED(u->source->thread_info.state) ? u->n_alsa_fds : 0), -1);
 /*         pa_log("poll end"); */
 
-        pa_asyncmsgq_after_poll(u->asyncmsgq);
+        pa_asyncmsgq_after_poll(u->thread_mq.inq);
 
         if (r < 0) {
             if (errno == EINTR) {
@@ -672,8 +675,8 @@ static void thread_func(void *userdata) {
 fail:
     /* We have to continue processing messages until we receive the
      * SHUTDOWN message */
-    pa_asyncmsgq_post(u->core->asyncmsgq, PA_MSGOBJECT(u->core), PA_CORE_MESSAGE_UNLOAD_MODULE, u->module, 0, NULL, NULL);
-    pa_asyncmsgq_wait_for(u->asyncmsgq, 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");
@@ -735,7 +738,9 @@ int pa__init(pa_module*m) {
     u->module = m;
     m->userdata = u;
     u->use_mmap = use_mmap;
-    pa_assert_se(u->asyncmsgq = pa_asyncmsgq_new(0));
+    u->n_alsa_fds = 0;
+    u->pollfd = NULL;
+    pa_thread_mq_init(&u->thread_mq, m->core->mainloop);
 
     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) {
@@ -807,7 +812,7 @@ int pa__init(pa_module*m) {
     u->source->userdata = u;
 
     pa_source_set_module(u->source, m);
-    pa_source_set_asyncmsgq(u->source, u->asyncmsgq);
+    pa_source_set_asyncmsgq(u->source, u->thread_mq.inq);
     pa_source_set_description(u->source, t = pa_sprintf_malloc(
                                       "ALSA PCM on %s (%s)",
                                       dev,
@@ -902,12 +907,11 @@ void pa__done(pa_module*m) {
         pa_source_disconnect(u->source);
 
     if (u->thread) {
-        pa_asyncmsgq_send(u->asyncmsgq, NULL, PA_MESSAGE_SHUTDOWN, NULL, 0, NULL);
+        pa_asyncmsgq_send(u->thread_mq.inq, NULL, PA_MESSAGE_SHUTDOWN, NULL, 0, NULL);
         pa_thread_free(u->thread);
     }
 
-    if (u->asyncmsgq)
-        pa_asyncmsgq_free(u->asyncmsgq);
+    pa_thread_mq_done(&u->thread_mq);
 
     if (u->source)
         pa_source_unref(u->source);
diff --git a/src/modules/module-null-sink.c b/src/modules/module-null-sink.c
index 2ede01a..8b17b59 100644
--- a/src/modules/module-null-sink.c
+++ b/src/modules/module-null-sink.c
@@ -46,6 +46,7 @@
 #include <pulsecore/modargs.h>
 #include <pulsecore/log.h>
 #include <pulsecore/thread.h>
+#include <pulsecore/thread-mq.h>
 
 #include "module-null-sink-symdef.h"
 
@@ -67,7 +68,7 @@ struct userdata {
     pa_module *module;
     pa_sink *sink;
     pa_thread *thread;
-    pa_asyncmsgq *asyncmsgq;
+    pa_thread_mq thread_mq;
     size_t block_size;
     
     struct timeval timestamp;
@@ -118,10 +119,12 @@ static void thread_func(void *userdata) {
 
     pa_log_debug("Thread starting up");
 
+    pa_thread_mq_install(&u->thread_mq);
+
     pa_gettimeofday(&u->timestamp);
 
     memset(&pollfd, 0, sizeof(pollfd));
-    pollfd.fd = pa_asyncmsgq_get_fd(u->asyncmsgq);
+    pollfd.fd = pa_asyncmsgq_get_fd(u->thread_mq.inq);
     pollfd.events = POLLIN;
 
     for (;;) {
@@ -134,16 +137,16 @@ static void thread_func(void *userdata) {
         int64_t offset;
 
         /* Check whether there is a message for us to process */
-        if (pa_asyncmsgq_get(u->asyncmsgq, &object, &code, &data, &offset, &chunk, 0) == 0) {
+        if (pa_asyncmsgq_get(u->thread_mq.inq, &object, &code, &data, &offset, &chunk, 0) == 0) {
             int ret;
 
             if (!object && code == PA_MESSAGE_SHUTDOWN) {
-                pa_asyncmsgq_done(u->asyncmsgq, 0);
+                pa_asyncmsgq_done(u->thread_mq.inq, 0);
                 goto finish;
             }
 
             ret = pa_asyncmsgq_dispatch(object, code, data, offset, &chunk);
-            pa_asyncmsgq_done(u->asyncmsgq, ret);
+            pa_asyncmsgq_done(u->thread_mq.inq, ret);
             continue;
         }
 
@@ -169,11 +172,11 @@ static void thread_func(void *userdata) {
 
         /* Hmm, nothing to do. Let's sleep */
 
-        if (pa_asyncmsgq_before_poll(u->asyncmsgq) < 0)
+        if (pa_asyncmsgq_before_poll(u->thread_mq.inq) < 0)
             continue;
 
         r = poll(&pollfd, 1, timeout);
-        pa_asyncmsgq_after_poll(u->asyncmsgq);
+        pa_asyncmsgq_after_poll(u->thread_mq.inq);
 
         if (r < 0) {
             if (errno == EINTR) {
@@ -191,8 +194,8 @@ static void thread_func(void *userdata) {
 fail:
     /* We have to continue processing messages until we receive the
      * SHUTDOWN message */
-    pa_asyncmsgq_post(u->core->asyncmsgq, PA_MSGOBJECT(u->core), PA_CORE_MESSAGE_UNLOAD_MODULE, u->module, 0, NULL, NULL);
-    pa_asyncmsgq_wait_for(u->asyncmsgq, 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");
@@ -222,7 +225,7 @@ int pa__init(pa_module*m) {
     u->module = m;
     m->userdata = u;
 
-    pa_assert_se(u->asyncmsgq = pa_asyncmsgq_new(0));
+    pa_thread_mq_init(&u->thread_mq, m->core->mainloop);
     
     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.");
@@ -233,7 +236,7 @@ int pa__init(pa_module*m) {
     u->sink->userdata = u;
 
     pa_sink_set_module(u->sink, m);
-    pa_sink_set_asyncmsgq(u->sink, u->asyncmsgq);
+    pa_sink_set_asyncmsgq(u->sink, u->thread_mq.inq);
     pa_sink_set_description(u->sink, pa_modargs_get_value(ma, "description", "NULL sink"));
 
     u->block_size = pa_bytes_per_second(&ss) / 20; /* 50 ms */
@@ -270,12 +273,11 @@ void pa__done(pa_module*m) {
         pa_sink_disconnect(u->sink);
 
     if (u->thread) {
-        pa_asyncmsgq_send(u->asyncmsgq, NULL, PA_MESSAGE_SHUTDOWN, NULL, 0, NULL);
+        pa_asyncmsgq_send(u->thread_mq.inq, NULL, PA_MESSAGE_SHUTDOWN, NULL, 0, NULL);
         pa_thread_free(u->thread);
     }
 
-    if (u->asyncmsgq)
-        pa_asyncmsgq_free(u->asyncmsgq);
+    pa_thread_mq_done(&u->thread_mq);
 
     if (u->sink)
         pa_sink_unref(u->sink);
diff --git a/src/modules/module-oss.c b/src/modules/module-oss.c
index d93d8c7..d71de99 100644
--- a/src/modules/module-oss.c
+++ b/src/modules/module-oss.c
@@ -79,6 +79,7 @@
 #include <pulsecore/modargs.h>
 #include <pulsecore/log.h>
 #include <pulsecore/macro.h>
+#include <pulsecore/thread-mq.h>
 
 #include "oss-util.h"
 #include "module-oss-symdef.h"
@@ -111,7 +112,7 @@ struct userdata {
     pa_sink *sink;
     pa_source *source;
     pa_thread *thread;
-    pa_asyncmsgq *asyncmsgq;
+    pa_thread_mq thread_mq;
 
     char *device_name;
     
@@ -793,11 +794,13 @@ static void thread_func(void *userdata) {
 
     pa_log_debug("Thread starting up");
 
+    pa_thread_mq_install(&u->thread_mq);
+
     trigger(u, 0);
     
     memset(&pollfd, 0, sizeof(pollfd));
 
-    pollfd[POLLFD_ASYNCQ].fd = pa_asyncmsgq_get_fd(u->asyncmsgq);
+    pollfd[POLLFD_ASYNCQ].fd = pa_asyncmsgq_get_fd(u->thread_mq.inq);
     pollfd[POLLFD_ASYNCQ].events = POLLIN;
     pollfd[POLLFD_DSP].fd = u->fd;
 
@@ -812,18 +815,18 @@ static void thread_func(void *userdata) {
 /*        pa_log("loop");    */
         
         /* Check whether there is a message for us to process */
-        if (pa_asyncmsgq_get(u->asyncmsgq, &object, &code, &data, &offset, &chunk, 0) == 0) {
+        if (pa_asyncmsgq_get(u->thread_mq.inq, &object, &code, &data, &offset, &chunk, 0) == 0) {
             int ret;
 
 /*             pa_log("processing msg"); */
 
             if (!object && code == PA_MESSAGE_SHUTDOWN) {
-                pa_asyncmsgq_done(u->asyncmsgq, 0);
+                pa_asyncmsgq_done(u->thread_mq.inq, 0);
                 goto finish;
             }
 
             ret = pa_asyncmsgq_dispatch(object, code, data, offset, &chunk);
-            pa_asyncmsgq_done(u->asyncmsgq, ret);
+            pa_asyncmsgq_done(u->thread_mq.inq, ret);
             continue;
         } 
 
@@ -1016,14 +1019,14 @@ static void thread_func(void *userdata) {
             
         /* Hmm, nothing to do. Let's sleep */
 
-        if (pa_asyncmsgq_before_poll(u->asyncmsgq) < 0)
+        if (pa_asyncmsgq_before_poll(u->thread_mq.inq) < 0)
             continue;
 
 /*         pa_log("polling for %i (legend: %i=POLLIN, %i=POLLOUT)", u->fd >= 0 ? pollfd[POLLFD_DSP].events : -1, POLLIN, POLLOUT); */
         r = poll(pollfd, u->fd >= 0 ? POLLFD_MAX : POLLFD_DSP, -1);
 /*         pa_log("polling got dsp=%i amq=%i (%i)", r > 0 ? pollfd[POLLFD_DSP].revents : 0, r > 0 ? pollfd[POLLFD_ASYNCQ].revents : 0, r); */
 
-        pa_asyncmsgq_after_poll(u->asyncmsgq);
+        pa_asyncmsgq_after_poll(u->thread_mq.inq);
 
         if (u->fd < 0)
             pollfd[POLLFD_DSP].revents = 0;
@@ -1052,8 +1055,8 @@ static void thread_func(void *userdata) {
 fail:
     /* We have to continue processing messages until we receive the
      * SHUTDOWN message */
-    pa_asyncmsgq_post(u->core->asyncmsgq, PA_MSGOBJECT(u->core), PA_CORE_MESSAGE_UNLOAD_MODULE, u->module, 0, NULL, NULL);
-    pa_asyncmsgq_wait_for(u->asyncmsgq, 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");
@@ -1161,7 +1164,7 @@ int pa__init(pa_module*m) {
     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_assert_se(u->asyncmsgq = pa_asyncmsgq_new(0));
+    pa_thread_mq_init(&u->thread_mq, m->core->mainloop);
 
     if (ioctl(fd, SNDCTL_DSP_GETISPACE, &info) >= 0) {
         pa_log_info("Input -- %u fragments of size %u.", info.fragstotal, info.fragsize);
@@ -1216,7 +1219,7 @@ int pa__init(pa_module*m) {
         u->source->userdata = u;
 
         pa_source_set_module(u->source, m);
-        pa_source_set_asyncmsgq(u->source, u->asyncmsgq);
+        pa_source_set_asyncmsgq(u->source, u->thread_mq.inq);
         pa_source_set_description(u->source, t = pa_sprintf_malloc(
                                           "OSS PCM on %s%s%s%s",
                                           dev,
@@ -1270,7 +1273,7 @@ try_write:
         u->sink->userdata = u;
         
         pa_sink_set_module(u->sink, m);
-        pa_sink_set_asyncmsgq(u->sink, u->asyncmsgq);
+        pa_sink_set_asyncmsgq(u->sink, u->thread_mq.inq);
         pa_sink_set_description(u->sink, t = pa_sprintf_malloc(
                                         "OSS PCM on %s%s%s%s",
                                         dev,
@@ -1300,9 +1303,9 @@ go_on:
 
     /* Read mixer settings */
     if (u->source)
-        pa_asyncmsgq_post(u->asyncmsgq, PA_MSGOBJECT(u->source), PA_SOURCE_MESSAGE_GET_VOLUME, &u->source->volume, 0, NULL, NULL);
+        pa_asyncmsgq_post(u->thread_mq.inq, PA_MSGOBJECT(u->source), PA_SOURCE_MESSAGE_GET_VOLUME, &u->source->volume, 0, NULL, NULL);
     if (u->sink)
-        pa_asyncmsgq_post(u->asyncmsgq, PA_MSGOBJECT(u->sink), PA_SINK_MESSAGE_GET_VOLUME, &u->sink->volume, 0, NULL, NULL);
+        pa_asyncmsgq_post(u->thread_mq.inq, PA_MSGOBJECT(u->sink), PA_SINK_MESSAGE_GET_VOLUME, &u->sink->volume, 0, NULL, NULL);
 
     return 0;
 
@@ -1334,12 +1337,11 @@ void pa__done(pa_module*m) {
         pa_source_disconnect(u->source);
 
     if (u->thread) {
-        pa_asyncmsgq_send(u->asyncmsgq, NULL, PA_MESSAGE_SHUTDOWN, NULL, 0, NULL);
+        pa_asyncmsgq_send(u->thread_mq.inq, NULL, PA_MESSAGE_SHUTDOWN, NULL, 0, NULL);
         pa_thread_free(u->thread);
     }
 
-    if (u->asyncmsgq)
-        pa_asyncmsgq_free(u->asyncmsgq);
+    pa_thread_mq_done(&u->thread_mq);
 
     if (u->sink)
         pa_sink_unref(u->sink);
diff --git a/src/modules/module-pipe-sink.c b/src/modules/module-pipe-sink.c
index 1b6d081..2f82cae 100644
--- a/src/modules/module-pipe-sink.c
+++ b/src/modules/module-pipe-sink.c
@@ -45,6 +45,7 @@
 #include <pulsecore/modargs.h>
 #include <pulsecore/log.h>
 #include <pulsecore/thread.h>
+#include <pulsecore/thread-mq.h>
 
 #include "module-pipe-sink-symdef.h"
 
@@ -67,7 +68,7 @@ struct userdata {
     pa_module *module;
     pa_sink *sink;
     pa_thread *thread;
-    pa_asyncmsgq *asyncmsgq;
+    pa_thread_mq thread_mq;
     char *filename;
     int fd;
 
@@ -121,9 +122,11 @@ static void thread_func(void *userdata) {
 
     pa_log_debug("Thread starting up");
 
+    pa_thread_mq_install(&u->thread_mq);
+
     memset(&pollfd, 0, sizeof(pollfd));
     
-    pollfd[POLLFD_ASYNCQ].fd = pa_asyncmsgq_get_fd(u->asyncmsgq);
+    pollfd[POLLFD_ASYNCQ].fd = pa_asyncmsgq_get_fd(u->thread_mq.inq);
     pollfd[POLLFD_ASYNCQ].events = POLLIN;
     pollfd[POLLFD_FIFO].fd = u->fd;
 
@@ -136,16 +139,16 @@ static void thread_func(void *userdata) {
         int64_t offset;
 
         /* Check whether there is a message for us to process */
-        if (pa_asyncmsgq_get(u->asyncmsgq, &object, &code, &data, &offset, &chunk, 0) == 0) {
+        if (pa_asyncmsgq_get(u->thread_mq.inq, &object, &code, &data, &offset, &chunk, 0) == 0) {
             int ret;
 
             if (!object && code == PA_MESSAGE_SHUTDOWN) {
-                pa_asyncmsgq_done(u->asyncmsgq, 0);
+                pa_asyncmsgq_done(u->thread_mq.inq, 0);
                 goto finish;
             }
 
             ret = pa_asyncmsgq_dispatch(object, code, data, offset, &chunk);
-            pa_asyncmsgq_done(u->asyncmsgq, ret);
+            pa_asyncmsgq_done(u->thread_mq.inq, ret);
             continue;
         }
 
@@ -194,14 +197,14 @@ static void thread_func(void *userdata) {
 
         /* Hmm, nothing to do. Let's sleep */
 
-        if (pa_asyncmsgq_before_poll(u->asyncmsgq) < 0)
+        if (pa_asyncmsgq_before_poll(u->thread_mq.inq) < 0)
             continue;
 
 /*         pa_log("polling for %u", pollfd[POLLFD_FIFO].events);  */
         r = poll(pollfd, POLLFD_MAX, -1);
 /*         pa_log("polling got %u", r > 0 ? pollfd[POLLFD_FIFO].revents : 0);  */
 
-        pa_asyncmsgq_after_poll(u->asyncmsgq);
+        pa_asyncmsgq_after_poll(u->thread_mq.inq);
 
         if (r < 0) {
             if (errno == EINTR) {
@@ -225,8 +228,8 @@ static void thread_func(void *userdata) {
 fail:
     /* We have to continue processing messages until we receive the
      * SHUTDOWN message */
-    pa_asyncmsgq_post(u->core->asyncmsgq, PA_MSGOBJECT(u->core), PA_CORE_MESSAGE_UNLOAD_MODULE, u->module, 0, NULL, NULL);
-    pa_asyncmsgq_wait_for(u->asyncmsgq, 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");
@@ -258,8 +261,7 @@ int pa__init(pa_module*m) {
     u->module = m;
     m->userdata = u;
     pa_memchunk_reset(&u->memchunk);
-
-    pa_assert_se(u->asyncmsgq = pa_asyncmsgq_new(0));
+    pa_thread_mq_init(&u->thread_mq, m->core->mainloop);
     
     u->filename = pa_xstrdup(pa_modargs_get_value(ma, "file", DEFAULT_FILE_NAME));
 
@@ -291,7 +293,7 @@ int pa__init(pa_module*m) {
     u->sink->userdata = u;
     
     pa_sink_set_module(u->sink, m);
-    pa_sink_set_asyncmsgq(u->sink, u->asyncmsgq);
+    pa_sink_set_asyncmsgq(u->sink, u->thread_mq.inq);
     pa_sink_set_description(u->sink, t = pa_sprintf_malloc("Unix FIFO sink '%s'", u->filename));
     pa_xfree(t);
 
@@ -325,12 +327,11 @@ void pa__done(pa_module*m) {
         pa_sink_disconnect(u->sink);
 
     if (u->thread) {
-        pa_asyncmsgq_send(u->asyncmsgq, NULL, PA_MESSAGE_SHUTDOWN, NULL, 0, NULL);
+        pa_asyncmsgq_send(u->thread_mq.inq, NULL, PA_MESSAGE_SHUTDOWN, NULL, 0, NULL);
         pa_thread_free(u->thread);
     }
 
-    if (u->asyncmsgq)
-        pa_asyncmsgq_free(u->asyncmsgq);
+    pa_thread_mq_done(&u->thread_mq);
     
     if (u->sink)
         pa_sink_unref(u->sink);
diff --git a/src/modules/module-pipe-source.c b/src/modules/module-pipe-source.c
index a8fbcf3..2209d1e 100644
--- a/src/modules/module-pipe-source.c
+++ b/src/modules/module-pipe-source.c
@@ -44,6 +44,7 @@
 #include <pulsecore/modargs.h>
 #include <pulsecore/log.h>
 #include <pulsecore/thread.h>
+#include <pulsecore/thread-mq.h>
 
 #include "module-pipe-source-symdef.h"
 
@@ -66,7 +67,7 @@ struct userdata {
     pa_module *module;
     pa_source *source;
     pa_thread *thread;
-    pa_asyncmsgq *asyncmsgq;
+    pa_thread_mq thread_mq;
     
     char *filename;
     int fd;
@@ -99,9 +100,11 @@ static void thread_func(void *userdata) {
 
     pa_log_debug("Thread starting up");
 
+    pa_thread_mq_install(&u->thread_mq);
+
     memset(&pollfd, 0, sizeof(pollfd));
     
-    pollfd[POLLFD_ASYNCQ].fd = pa_asyncmsgq_get_fd(u->asyncmsgq);
+    pollfd[POLLFD_ASYNCQ].fd = pa_asyncmsgq_get_fd(u->thread_mq.inq);
     pollfd[POLLFD_ASYNCQ].events = POLLIN;
     pollfd[POLLFD_FIFO].fd = u->fd;
 
@@ -114,16 +117,16 @@ static void thread_func(void *userdata) {
         int64_t offset;
 
         /* Check whether there is a message for us to process */
-        if (pa_asyncmsgq_get(u->asyncmsgq, &object, &code, &data, &offset, &chunk, 0) == 0) {
+        if (pa_asyncmsgq_get(u->thread_mq.inq, &object, &code, &data, &offset, &chunk, 0) == 0) {
             int ret;
 
             if (!object && code == PA_MESSAGE_SHUTDOWN) {
-                pa_asyncmsgq_done(u->asyncmsgq, 0);
+                pa_asyncmsgq_done(u->thread_mq.inq, 0);
                 goto finish;
             }
 
             ret = pa_asyncmsgq_dispatch(object, code, data, offset, &chunk);
-            pa_asyncmsgq_done(u->asyncmsgq, ret);
+            pa_asyncmsgq_done(u->thread_mq.inq, ret);
             continue;
         }
 
@@ -175,14 +178,14 @@ static void thread_func(void *userdata) {
 
         /* Hmm, nothing to do. Let's sleep */
 
-        if (pa_asyncmsgq_before_poll(u->asyncmsgq) < 0)
+        if (pa_asyncmsgq_before_poll(u->thread_mq.inq) < 0)
             continue;
 
 /*         pa_log("polling for %i", pollfd[POLLFD_FIFO].events); */
         r = poll(pollfd, POLLFD_MAX, -1);
 /*         pa_log("polling got %i (r=%i) %i", r > 0 ? pollfd[POLLFD_FIFO].revents : 0, r, r > 0 ? pollfd[POLLFD_ASYNCQ].revents: 0); */
 
-        pa_asyncmsgq_after_poll(u->asyncmsgq);
+        pa_asyncmsgq_after_poll(u->thread_mq.inq);
 
         if (r < 0) {
             if (errno == EINTR)
@@ -203,8 +206,8 @@ static void thread_func(void *userdata) {
 fail:
     /* We have to continue processing messages until we receive the
      * SHUTDOWN message */
-    pa_asyncmsgq_post(u->core->asyncmsgq, PA_MSGOBJECT(u->core), PA_CORE_MESSAGE_UNLOAD_MODULE, u->module, 0, NULL, NULL);
-    pa_asyncmsgq_wait_for(u->asyncmsgq, 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");
@@ -236,8 +239,7 @@ int pa__init(pa_module*m) {
     u->module = m;
     m->userdata = u;
     pa_memchunk_reset(&u->memchunk);
-    
-    pa_assert_se(u->asyncmsgq = pa_asyncmsgq_new(0));
+    pa_thread_mq_init(&u->thread_mq, m->core->mainloop);
 
     u->filename = pa_xstrdup(pa_modargs_get_value(ma, "file", DEFAULT_FILE_NAME));
     
@@ -268,7 +270,7 @@ int pa__init(pa_module*m) {
     u->source->userdata = u;
     
     pa_source_set_module(u->source, m);
-    pa_source_set_asyncmsgq(u->source, u->asyncmsgq);
+    pa_source_set_asyncmsgq(u->source, u->thread_mq.inq);
     pa_source_set_description(u->source, t = pa_sprintf_malloc("Unix FIFO source '%s'", u->filename));
     pa_xfree(t);
 
@@ -302,12 +304,11 @@ void pa__done(pa_module*m) {
         pa_source_disconnect(u->source);
 
     if (u->thread) {
-        pa_asyncmsgq_send(u->asyncmsgq, NULL, PA_MESSAGE_SHUTDOWN, NULL, 0, NULL);
+        pa_asyncmsgq_send(u->thread_mq.inq, NULL, PA_MESSAGE_SHUTDOWN, NULL, 0, NULL);
         pa_thread_free(u->thread);
     }
 
-    if (u->asyncmsgq)
-        pa_asyncmsgq_free(u->asyncmsgq);
+    pa_thread_mq_done(&u->thread_mq);
 
     if (u->source)
         pa_source_unref(u->source);
diff --git a/src/pulsecore/core.c b/src/pulsecore/core.c
index 2cdd4a8..a56dd4e 100644
--- a/src/pulsecore/core.c
+++ b/src/pulsecore/core.c
@@ -67,34 +67,6 @@ static int core_process_msg(pa_msgobject *o, int code, void *userdata, int64_t o
     }
 }
 
-static void asyncmsgq_cb(pa_mainloop_api*api, pa_io_event* e, int fd, pa_io_event_flags_t events, void *userdata) {
-    pa_core *c = userdata;
-
-    pa_assert(pa_asyncmsgq_get_fd(c->asyncmsgq) == fd);
-    pa_assert(events == PA_IO_EVENT_INPUT);
-
-    pa_asyncmsgq_after_poll(c->asyncmsgq);
-
-    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(c->asyncmsgq, &object, &code, &data, &offset, &chunk, 0) == 0) {
-            int ret;
-
-            ret = pa_asyncmsgq_dispatch(object, code, data, offset, &chunk);
-            pa_asyncmsgq_done(c->asyncmsgq, ret);
-        }
-
-        if (pa_asyncmsgq_before_poll(c->asyncmsgq) == 0)
-            break;
-    }
-}
-
 static void core_free(pa_object *o);
 
 pa_core* pa_core_new(pa_mainloop_api *m, int shared) {
@@ -189,10 +161,6 @@ pa_core* pa_core_new(pa_mainloop_api *m, int shared) {
     pa_check_signal_is_blocked(SIGPIPE);
 #endif
 
-    pa_assert_se(c->asyncmsgq = pa_asyncmsgq_new(0));
-    pa_assert_se(pa_asyncmsgq_before_poll(c->asyncmsgq) == 0);
-    pa_assert_se(c->asyncmsgq_event = c->mainloop->io_new(c->mainloop, pa_asyncmsgq_get_fd(c->asyncmsgq), PA_IO_EVENT_INPUT, asyncmsgq_cb, c));
-
     return c;
 }
 
@@ -229,15 +197,10 @@ static void core_free(pa_object *o) {
     pa_xfree(c->default_source_name);
     pa_xfree(c->default_sink_name);
 
-    pa_asyncmsgq_after_poll(c->asyncmsgq);
-    pa_asyncmsgq_free(c->asyncmsgq);
-
     pa_mempool_free(c->mempool);
 
     pa_property_cleanup(c);
 
-    c->mainloop->io_free(c->asyncmsgq_event);
-
     pa_hook_free(&c->hook_sink_new);
     pa_hook_free(&c->hook_sink_new_post);
     pa_hook_free(&c->hook_sink_disconnect);
@@ -260,13 +223,13 @@ static void core_free(pa_object *o) {
 
 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;
diff --git a/src/pulsecore/core.h b/src/pulsecore/core.h
index 394785f..d86d551 100644
--- a/src/pulsecore/core.h
+++ b/src/pulsecore/core.h
@@ -104,9 +104,6 @@ struct pa_core {
         hook_source_output_new_post,
         hook_source_output_disconnect,
         hook_source_output_disconnect_post;
-
-    pa_asyncmsgq *asyncmsgq;
-    pa_io_event *asyncmsgq_event;
 };
 
 PA_DECLARE_CLASS(pa_core);
diff --git a/src/pulsecore/play-memchunk.c b/src/pulsecore/play-memchunk.c
index 419d523..d2d7180 100644
--- a/src/pulsecore/play-memchunk.c
+++ b/src/pulsecore/play-memchunk.c
@@ -33,6 +33,7 @@
 
 #include <pulsecore/sink-input.h>
 #include <pulsecore/gccmacro.h>
+#include <pulsecore/thread-mq.h>
 
 #include "play-memchunk.h"
 
@@ -111,7 +112,7 @@ static int sink_input_peek_cb(pa_sink_input *i, pa_memchunk *chunk) {
     if (u->memchunk.length <= 0) {
         pa_memblock_unref(u->memchunk.memblock);
         u->memchunk.memblock = NULL;
-        pa_asyncmsgq_post(u->core->asyncmsgq, PA_MSGOBJECT(u), MEMCHUNK_STREAM_MESSAGE_UNLINK, NULL, 0, NULL, NULL);
+        pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(u), MEMCHUNK_STREAM_MESSAGE_UNLINK, NULL, 0, NULL, NULL);
         return -1;
     }
 
diff --git a/src/pulsecore/protocol-esound.c b/src/pulsecore/protocol-esound.c
index 7460714..c5505e5 100644
--- a/src/pulsecore/protocol-esound.c
+++ b/src/pulsecore/protocol-esound.c
@@ -53,6 +53,7 @@
 #include <pulsecore/core-error.h>
 #include <pulsecore/ipacl.h>
 #include <pulsecore/macro.h>
+#include <pulsecore/thread-mq.h>
 
 #include "endianmacros.h"
 
@@ -1194,6 +1195,7 @@ static int connection_process_msg(pa_msgobject *o, int code, void*userdata, int6
 
 /*** 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;
@@ -1234,7 +1236,7 @@ static int sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int
     }
 }
 
-
+/* Called from thread context */
 static int sink_input_peek_cb(pa_sink_input *i, pa_memchunk *chunk) {
     connection*c;
     int r;
@@ -1245,11 +1247,12 @@ static int sink_input_peek_cb(pa_sink_input *i, pa_memchunk *chunk) {
     pa_assert(chunk);
 
     if ((r = pa_memblockq_peek(c->input_memblockq, chunk)) < 0 && c->dead)
-        pa_asyncmsgq_post(c->protocol->core->asyncmsgq, PA_MSGOBJECT(c), CONNECTION_MESSAGE_UNLINK_CONNECTION, NULL, 0, NULL, NULL);
+        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;
@@ -1267,7 +1270,7 @@ static void sink_input_drop_cb(pa_sink_input *i, size_t length) {
 
     if (new > old) {
         if (pa_atomic_add(&c->playback.missing, new - old) <= 0)
-            pa_asyncmsgq_post(c->protocol->core->asyncmsgq, PA_MSGOBJECT(c), CONNECTION_MESSAGE_REQUEST_DATA, NULL, 0, NULL, NULL);
+            pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(c), CONNECTION_MESSAGE_REQUEST_DATA, NULL, 0, NULL, NULL);
     }
 }
 
@@ -1279,6 +1282,7 @@ static void sink_input_kill_cb(pa_sink_input *i) {
 
 /*** source_output callbacks ***/
 
+/* Called from thread context */
 static void source_output_push_cb(pa_source_output *o, const pa_memchunk *chunk) {
     connection *c;
 
@@ -1287,7 +1291,7 @@ static void source_output_push_cb(pa_source_output *o, const pa_memchunk *chunk)
     pa_assert(c);
     pa_assert(chunk);
 
-    pa_asyncmsgq_post(c->protocol->core->asyncmsgq, PA_MSGOBJECT(c), CONNECTION_MESSAGE_POST_DATA, NULL, 0, chunk, NULL);
+    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) {
diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c
index 0816ea6..00b4d13 100644
--- a/src/pulsecore/protocol-native.c
+++ b/src/pulsecore/protocol-native.c
@@ -60,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"
 
@@ -752,7 +753,7 @@ static void request_bytes(playback_stream *s) {
 
     previous_missing = pa_atomic_add(&s->missing, delta);
     if (previous_missing < pa_memblockq_get_minreq(s->memblockq) && previous_missing+delta >= pa_memblockq_get_minreq(s->memblockq))
-        pa_asyncmsgq_post(s->connection->protocol->core->asyncmsgq, PA_MSGOBJECT(s), PLAYBACK_STREAM_MESSAGE_REQUEST_DATA, NULL, 0, NULL, NULL);
+        pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(s), PLAYBACK_STREAM_MESSAGE_REQUEST_DATA, NULL, 0, NULL, NULL);
 }
 
 static void send_memblock(connection *c) {
@@ -833,7 +834,7 @@ static int sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int
             if (pa_memblockq_push_align(s->memblockq, chunk) < 0) {
 
                 pa_log_warn("Failed to push data into queue");
-                pa_asyncmsgq_post(s->connection->protocol->core->asyncmsgq, PA_MSGOBJECT(s), PLAYBACK_STREAM_MESSAGE_OVERFLOW, NULL, 0, NULL, NULL);
+                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);
             }
 
@@ -848,7 +849,7 @@ static int sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int
             pa_memblockq_prebuf_disable(s->memblockq);
 
             if (!pa_memblockq_is_readable(s->memblockq))
-                pa_asyncmsgq_post(s->connection->protocol->core->asyncmsgq, PA_MSGOBJECT(s), PLAYBACK_STREAM_MESSAGE_DRAIN_ACK, userdata, 0, NULL, NULL);
+                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;
@@ -941,7 +942,7 @@ static int sink_input_peek_cb(pa_sink_input *i, pa_memchunk *chunk) {
     pa_assert(chunk);
 
     if (pa_memblockq_get_length(s->memblockq) <= 0 && !s->underrun) {
-        pa_asyncmsgq_post(s->connection->protocol->core->asyncmsgq, PA_MSGOBJECT(s), PLAYBACK_STREAM_MESSAGE_UNDERFLOW, NULL, 0, NULL, NULL);
+        pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(s), PLAYBACK_STREAM_MESSAGE_UNDERFLOW, NULL, 0, NULL, NULL);
         s->underrun = 1;
     }
 
@@ -970,7 +971,7 @@ static void sink_input_drop_cb(pa_sink_input *i, size_t length) {
 
     if (s->drain_request && !pa_memblockq_is_readable(s->memblockq)) {
         s->drain_request = 0;
-        pa_asyncmsgq_post(s->connection->protocol->core->asyncmsgq, PA_MSGOBJECT(s), PLAYBACK_STREAM_MESSAGE_DRAIN_ACK, PA_UINT_TO_PTR(s->drain_tag), 0, NULL, NULL);
+        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);
     }
 
     request_bytes(s);
@@ -1000,7 +1001,7 @@ static void source_output_push_cb(pa_source_output *o, const pa_memchunk *chunk)
     record_stream_assert_ref(s);
     pa_assert(chunk);
 
-    pa_asyncmsgq_post(s->connection->protocol->core->asyncmsgq, PA_MSGOBJECT(s), RECORD_STREAM_MESSAGE_POST_DATA, NULL, 0, chunk, NULL);
+    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) {
diff --git a/src/pulsecore/protocol-simple.c b/src/pulsecore/protocol-simple.c
index dd61c7e..bc48ac3 100644
--- a/src/pulsecore/protocol-simple.c
+++ b/src/pulsecore/protocol-simple.c
@@ -41,6 +41,7 @@
 #include <pulsecore/log.h>
 #include <pulsecore/core-error.h>
 #include <pulsecore/atomic.h>
+#include <pulsecore/thread-mq.h>
 
 #include "protocol-simple.h"
 
@@ -356,7 +357,7 @@ static int sink_input_peek_cb(pa_sink_input *i, pa_memchunk *chunk) {
 /*     pa_log("peeked %u %i", r >= 0 ? chunk->length: 0, r); */
 
     if (c->dead && r < 0)
-        pa_asyncmsgq_post(c->protocol->core->asyncmsgq, PA_MSGOBJECT(c), CONNECTION_MESSAGE_UNLINK_CONNECTION, NULL, 0, NULL, NULL);
+        pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(c), CONNECTION_MESSAGE_UNLINK_CONNECTION, NULL, 0, NULL, NULL);
 
     return r;
 }
@@ -377,7 +378,7 @@ static void sink_input_drop_cb(pa_sink_input *i, size_t length) {
 
     if (new > old) {
         if (pa_atomic_add(&c->playback.missing, new - old) <= 0)
-            pa_asyncmsgq_post(c->protocol->core->asyncmsgq, PA_MSGOBJECT(c), CONNECTION_MESSAGE_REQUEST_DATA, NULL, 0, NULL, NULL);
+            pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(c), CONNECTION_MESSAGE_REQUEST_DATA, NULL, 0, NULL, NULL);
     }
 }
 
@@ -399,7 +400,7 @@ static void source_output_push_cb(pa_source_output *o, const pa_memchunk *chunk)
     pa_assert(c);
     pa_assert(chunk);
 
-    pa_asyncmsgq_post(c->protocol->core->asyncmsgq, PA_MSGOBJECT(c), CONNECTION_MESSAGE_POST_DATA, NULL, 0, chunk, NULL);
+    pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(c), CONNECTION_MESSAGE_POST_DATA, NULL, 0, chunk, NULL);
 }
 
 /* Called from main context */
diff --git a/src/pulsecore/sound-file-stream.c b/src/pulsecore/sound-file-stream.c
index 4e0e91e..e0d51a7 100644
--- a/src/pulsecore/sound-file-stream.c
+++ b/src/pulsecore/sound-file-stream.c
@@ -39,6 +39,7 @@
 #include <pulsecore/core-error.h>
 #include <pulsecore/sink-input.h>
 #include <pulsecore/log.h>
+#include <pulsecore/thread-mq.h>
 
 #include "sound-file-stream.h"
 
@@ -161,7 +162,7 @@ static int sink_input_peek_cb(pa_sink_input *i, pa_memchunk *chunk) {
                 pa_memblock_unref(u->memchunk.memblock);
                 pa_memchunk_reset(&u->memchunk);
                 
-                pa_asyncmsgq_post(u->core->asyncmsgq, PA_MSGOBJECT(u), FILE_STREAM_MESSAGE_UNLINK, NULL, 0, NULL, NULL);
+                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;

commit 4e145b676ab76235468953634ba6d17717a3d933
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Aug 10 23:40:05 2007 +0000

    if no thread-mq is attached to the current thread, return an error, don't hit an assert
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1625 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/thread-mq.c b/src/pulsecore/thread-mq.c
index 224a14c..89b65e5 100644
--- a/src/pulsecore/thread-mq.c
+++ b/src/pulsecore/thread-mq.c
@@ -110,10 +110,7 @@ void pa_thread_mq_install(pa_thread_mq *q) {
 }
 
 pa_thread_mq *pa_thread_mq_get(void) {
-    pa_thread_mq *q;
-
     pa_run_once(&once, init_tls);
-    pa_assert_se(q = pa_tls_get(tls));
-    return q;
+    return pa_tls_get(tls);
 }
 

commit ff4814cac79bc947d6430d79c1ae09d21247305c
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Aug 10 23:41:50 2007 +0000

    add callbacks for the revoke/release stuff, so that we can make this thing thread-safe
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1626 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/pstream.c b/src/pulsecore/pstream.c
index ed55270..b91813e 100644
--- a/src/pulsecore/pstream.c
+++ b/src/pulsecore/pstream.c
@@ -155,6 +155,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
@@ -254,7 +260,11 @@ 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;
 
     p->use_shm = 0;
@@ -376,11 +386,8 @@ void pa_pstream_send_memblock(pa_pstream*p, uint32_t channel, int64_t offset, pa
     p->mainloop->defer_enable(p->defer_event, 1);
 }
 
-/* might be called from thread context */
-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;
-
     pa_assert(p);
     pa_assert(PA_REFCNT_VALUE(p) > 0);
 
@@ -401,8 +408,7 @@ static void memimport_release_cb(pa_memimport *i, uint32_t block_id, void *userd
 }
 
 /* might be called from thread context */
-static void memexport_revoke_cb(pa_memexport *e, uint32_t block_id, void *userdata) {
-    struct item_info *item;
+static void memimport_release_cb(pa_memimport *i, uint32_t block_id, void *userdata) {
     pa_pstream *p = userdata;
 
     pa_assert(p);
@@ -410,6 +416,20 @@ static void memexport_revoke_cb(pa_memexport *e, uint32_t block_id, void *userda
 
     if (p->dead)
         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);
@@ -423,6 +443,19 @@ static void memexport_revoke_cb(pa_memexport *e, uint32_t block_id, void *userda
     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;
+
+    pa_assert(p);
+    pa_assert(PA_REFCNT_VALUE(p) > 0);
+
+    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) {
     pa_assert(p);
     pa_assert(PA_REFCNT_VALUE(p) > 0);
@@ -875,6 +908,22 @@ void pa_pstream_set_recieve_memblock_callback(pa_pstream *p, pa_pstream_memblock
     p->recieve_memblock_callback_userdata = userdata;
 }
 
+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;
 
diff --git a/src/pulsecore/pstream.h b/src/pulsecore/pstream.h
index 544cba4..72babea 100644
--- a/src/pulsecore/pstream.h
+++ b/src/pulsecore/pstream.h
@@ -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,12 +49,15 @@ 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);
 

commit d2fed9d419be4cc3aa7417471166e16f1de3f7dd
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Aug 10 23:42:17 2007 +0000

    make revoke/release thread safe in the native protocol
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1627 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c
index 00b4d13..a67f9b0 100644
--- a/src/pulsecore/protocol-native.c
+++ b/src/pulsecore/protocol-native.c
@@ -139,7 +139,6 @@ 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);
@@ -195,6 +194,11 @@ 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, 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);
@@ -681,6 +685,24 @@ static playback_stream* playback_stream_new(
     return s;
 }
 
+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);
+
+    switch (code) {
+        
+        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_unlink(connection *c) {
     record_stream *r;
     output_stream *o;
@@ -2702,6 +2724,24 @@ static void pstream_drain_callback(pa_pstream *p, void *userdata) {
     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) {
@@ -2741,6 +2781,7 @@ static void on_connection(PA_GCC_UNUSED pa_socket_server*s, pa_iochannel *io, vo
 
     c = pa_msgobject_new(connection);
     c->parent.parent.free = connection_free;
+    c->parent.process_msg = connection_process_msg;
 
     c->authorized = !!p->public;
 
@@ -2772,6 +2813,8 @@ static void on_connection(PA_GCC_UNUSED pa_socket_server*s, pa_iochannel *io, vo
     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);
 

commit 59c9ed5473a04e51eed51112612a9065f4f41093
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sat Aug 11 00:10:29 2007 +0000

    move pstream item allocation to pa_flist
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1628 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/pstream.c b/src/pulsecore/pstream.c
index b91813e..33bc520 100644
--- a/src/pulsecore/pstream.c
+++ b/src/pulsecore/pstream.c
@@ -49,6 +49,7 @@
 #include <pulsecore/core-scache.h>
 #include <pulsecore/creds.h>
 #include <pulsecore/refcnt.h>
+#include <pulsecore/flist.h>
 
 #include "pstream.h"
 
@@ -84,6 +85,8 @@ typedef uint32_t pa_pstream_descriptor[PA_PSTREAM_DESCRIPTOR_MAX];
 #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 {
         PA_PSTREAM_ITEM_PACKET,
@@ -92,7 +95,6 @@ struct item_info {
         PA_PSTREAM_ITEM_SHMREVOKE
     } type;
 
-
     /* packet info */
     pa_packet *packet;
 #ifdef HAVE_CREDS
@@ -295,7 +297,8 @@ static void item_free(void *item, PA_GCC_UNUSED void *q) {
         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) {
@@ -330,7 +333,9 @@ void pa_pstream_send_packet(pa_pstream*p, pa_packet *packet, const pa_creds *cre
     if (p->dead)
         return;
 
-    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_PACKET;
     i->packet = pa_packet_ref(packet);
 
@@ -362,7 +367,8 @@ void pa_pstream_send_memblock(pa_pstream*p, uint32_t channel, int64_t offset, pa
         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;
@@ -396,7 +402,8 @@ void pa_pstream_send_release(pa_pstream *p, uint32_t block_id) {
 
 /*     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
@@ -432,7 +439,8 @@ void pa_pstream_send_revoke(pa_pstream *p, uint32_t block_id) {
         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

commit b44ce9e4e04ac41436fec9f57b509c49a78b617b
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sat Aug 11 15:56:06 2007 +0000

    add default fragment settings variables to pa_core
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1629 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/core.c b/src/pulsecore/core.c
index a56dd4e..8b10d39 100644
--- a/src/pulsecore/core.c
+++ b/src/pulsecore/core.c
@@ -112,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;
diff --git a/src/pulsecore/core.h b/src/pulsecore/core.h
index d86d551..003b24b 100644
--- a/src/pulsecore/core.h
+++ b/src/pulsecore/core.h
@@ -65,6 +65,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;
 

commit e2a10de756136110d7fdeac0d8543e452dd610ad
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sat Aug 11 15:56:57 2007 +0000

    allow setting the default sample and fragment settings from the config file
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1630 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/daemon/daemon-conf.c b/src/daemon/daemon-conf.c
index 8cab327..b6e8d54 100644
--- a/src/daemon/daemon-conf.c
+++ b/src/daemon/daemon-conf.c
@@ -29,7 +29,6 @@
 #include <errno.h>
 #include <stdio.h>
 #include <string.h>
-#include <assert.h>
 #include <unistd.h>
 
 #include <pulse/xmalloc.h>
@@ -39,6 +38,7 @@
 #include <pulsecore/strbuf.h>
 #include <pulsecore/conf-parser.h>
 #include <pulsecore/resampler.h>
+#include <pulsecore/macro.h>
 
 #include "daemon-conf.h"
 
@@ -77,7 +77,10 @@ static const pa_daemon_conf default_conf = {
     .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 },
@@ -96,7 +99,7 @@ static const pa_daemon_conf default_conf = {
 
 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 +109,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 +118,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 +137,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 +163,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 +175,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 +191,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 +207,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 +224,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 +237,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 +250,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 +401,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;
 
@@ -351,12 +469,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 +495,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);
diff --git a/src/daemon/daemon-conf.h b/src/daemon/daemon-conf.h
index 4843a61..cb717ec 100644
--- a/src/daemon/daemon-conf.h
+++ b/src/daemon/daemon-conf.h
@@ -26,6 +26,7 @@
 ***/
 
 #include <pulsecore/log.h>
+#include <pulse/sample.h>
 
 #ifdef HAVE_SYS_RESOURCE_H
 #include <sys/resource.h>
@@ -80,6 +81,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 */
diff --git a/src/daemon/daemon.conf.in b/src/daemon/daemon.conf.in
index 29b22a4..9bd5cba 100644
--- a/src/daemon/daemon.conf.in
+++ b/src/daemon/daemon.conf.in
@@ -99,3 +99,12 @@
 
 ## 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
diff --git a/src/daemon/main.c b/src/daemon/main.c
index a1926fe..eac470b 100644
--- a/src/daemon/main.c
+++ b/src/daemon/main.c
@@ -573,6 +573,9 @@ int main(int argc, char *argv[]) {
     }
 
     c->is_system_instance = !!conf->system_instance;
+    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;
 
     r = pa_signal_init(pa_mainloop_get_api(mainloop));
     assert(r == 0);

commit a7a5f43f6770facb030481afde00a9363fa8fe1c
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sat Aug 11 15:57:21 2007 +0000

    modernization
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1631 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/conf-parser.c b/src/pulsecore/conf-parser.c
index 12efbd2..47ec72c 100644
--- a/src/pulsecore/conf-parser.c
+++ b/src/pulsecore/conf-parser.c
@@ -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"
 
@@ -43,7 +43,10 @@
 
 /* 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) {
@@ -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;

commit 793f750429a32379fd034d06ee24a3ed768df4a4
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sat Aug 11 15:58:15 2007 +0000

    fix default device naming and fix api selection code
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1632 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-hal-detect.c b/src/modules/module-hal-detect.c
index 672bdc0..e95e97f 100644
--- a/src/modules/module-hal-detect.c
+++ b/src/modules/module-hal-detect.c
@@ -155,7 +155,7 @@ static int hal_alsa_device_is_modem(LibHalContext *context, const char *udi, DBu
 }
 
 static pa_module* hal_device_load_alsa(struct userdata *u, const char *udi, char **sink_name, char **source_name) {
-    char args[128];
+    char *args;
     alsa_type_t type;
     int device, card;
     const char *module_name;
@@ -189,18 +189,20 @@ static pa_module* hal_device_load_alsa(struct userdata *u, const char *udi, char
         *sink_name = pa_sprintf_malloc("alsa_output.%s", strip_udi(udi));
         
         module_name = "module-alsa-sink";
-        pa_snprintf(args, sizeof(args), "device=hw:%u sink_name=%s", card, *sink_name);
+        args = pa_sprintf_malloc("device=hw:%u sink_name=%s", card, *sink_name);
     } else {
-        *source_name = pa_sprintf_malloc("alsa_output.%s", strip_udi(udi));
+        *source_name = pa_sprintf_malloc("alsa_input.%s", strip_udi(udi));
         
         module_name = "module-alsa-source";
-        pa_snprintf(args, sizeof(args), "device=hw:%u source_name=%s", card, *source_name);
+        args = pa_sprintf_malloc("device=hw:%u source_name=%s", card, *source_name);
     }
 
     pa_log_debug("Loading %s with arguments '%s'", 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);
@@ -257,7 +259,7 @@ finish:
 }
 
 static pa_module* hal_device_load_oss(struct userdata *u, const char *udi, char **sink_name, char **source_name) {
-    char args[256];
+    char* args;
     char* device;
     DBusError error;
     pa_module *m;
@@ -277,15 +279,15 @@ static pa_module* hal_device_load_oss(struct userdata *u, const char *udi, char
     if (!device || dbus_error_is_set(&error))
         goto fail;
 
-    *sink_name = pa_sprintf_malloc("alsa_output.%s", strip_udi(udi));
-    *source_name = pa_sprintf_malloc("alsa_output.%s", strip_udi(udi));
+    *sink_name = pa_sprintf_malloc("oss_output.%s", strip_udi(udi));
+    *source_name = pa_sprintf_malloc("oss_input.%s", strip_udi(udi));
     
-    pa_snprintf(args, sizeof(args), "device=%s sink_name=%s source_name=%s", device, sink_name, source_name);
+    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);
@@ -342,10 +344,12 @@ static int hal_device_add_all(struct userdata *u, const char *capability) {
     char** udis;
 
     pa_assert(u);
-    pa_assert(!u->capability);
     
     dbus_error_init(&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);
@@ -356,7 +360,6 @@ static int hal_device_add_all(struct userdata *u, const char *capability) {
     }
 
     if (n > 0) {
-        u->capability = capability;
         
         for (i = 0; i < n; i++) {
             struct device *d;
@@ -741,7 +744,7 @@ int pa__init(pa_module*m) {
     n = hal_device_add_all(u, CAPABILITY_ALSA);
 #endif
 #if defined(HAVE_ALSA) && defined(HAVE_OSS)
-    if (!u->capability)
+    if (n <= 0)
 #endif        
 #ifdef HAVE_OSS
         n += hal_device_add_all(u, CAPABILITY_OSS);

commit e1100b5b20a39813a86559a91afa5da3afb51752
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sat Aug 11 15:59:02 2007 +0000

    modify alsa drivers to make use of new global fragment setting variables
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1633 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-alsa-sink.c b/src/modules/module-alsa-sink.c
index d3fe885..af03a95 100644
--- a/src/modules/module-alsa-sink.c
+++ b/src/modules/module-alsa-sink.c
@@ -71,9 +71,6 @@ PA_MODULE_USAGE(
 
 #define DEFAULT_DEVICE "default"
 
-#define DEFAULT_NFRAGS 4
-#define DEFAULT_FRAGSIZE_MSEC 25
-
 struct userdata {
     pa_core *core;
     pa_module *module;
@@ -741,8 +738,8 @@ int pa__init(pa_module*m) {
 
     frame_size = pa_frame_size(&ss);
 
-    nfrags = DEFAULT_NFRAGS;
-    frag_size = pa_usec_to_bytes(DEFAULT_FRAGSIZE_MSEC*1000, &ss);
+    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;
 
diff --git a/src/modules/module-alsa-source.c b/src/modules/module-alsa-source.c
index 55af473..5de2406 100644
--- a/src/modules/module-alsa-source.c
+++ b/src/modules/module-alsa-source.c
@@ -71,8 +71,6 @@ PA_MODULE_USAGE(
         "mmap=<enable memory mapping?>")
 
 #define DEFAULT_DEVICE "default"
-#define DEFAULT_NFRAGS 4
-#define DEFAULT_FRAGSIZE_MSEC 25
 
 struct userdata {
     pa_core *core;
@@ -716,9 +714,8 @@ int pa__init(pa_module*m) {
 
     frame_size = pa_frame_size(&ss);
 
-    /* Fix latency to 100ms */
-    nfrags = DEFAULT_NFRAGS;
-    frag_size = pa_usec_to_bytes(DEFAULT_FRAGSIZE_MSEC*1000, &ss);
+    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;
 

commit f7b707b9541fa2e5e7a709ccb3f26c0be11bc6a9
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sat Aug 11 16:00:02 2007 +0000

    allow destruction of pa_fdsem object that are still in 'poll' state
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1634 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/fdsem.c b/src/pulsecore/fdsem.c
index 4de531a..c51ebba 100644
--- a/src/pulsecore/fdsem.c
+++ b/src/pulsecore/fdsem.c
@@ -64,8 +64,6 @@ pa_fdsem *pa_fdsem_new(void) {
 void pa_fdsem_free(pa_fdsem *f) {
     pa_assert(f);
 
-    pa_assert(pa_atomic_load(&f->waiting) == 0);
-    
     close(f->fds[0]);
     close(f->fds[1]);
 
@@ -168,17 +166,16 @@ int pa_fdsem_before_poll(pa_fdsem *f) {
     pa_atomic_inc(&f->waiting);
 
     if (pa_atomic_cmpxchg(&f->signalled, 1, 0)) {
-        pa_atomic_dec(&f->waiting);
+        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_atomic_dec(&f->waiting);
+    pa_assert_se(pa_atomic_dec(&f->waiting) >= 1);
 
     flush(f);
 

commit c1c59b4675d1c6912badc3f93fbc5d9ccecb7610
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sat Aug 11 16:01:25 2007 +0000

    add proper refcounting to pa_asyncmsgq objects, to allow destruction from the dispatched callbacks
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1635 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/asyncmsgq.c b/src/pulsecore/asyncmsgq.c
index ed71d37..1bef8bd 100644
--- a/src/pulsecore/asyncmsgq.c
+++ b/src/pulsecore/asyncmsgq.c
@@ -53,6 +53,7 @@ struct asyncmsgq_item {
 };
 
 struct pa_asyncmsgq {
+    PA_REFCNT_DECLARE;
     pa_asyncq *asyncq;
     pa_mutex *mutex; /* only for the writer side */
 
@@ -64,6 +65,7 @@ pa_asyncmsgq *pa_asyncmsgq_new(unsigned size) {
 
     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(0));
     a->current = NULL;
@@ -71,7 +73,7 @@ pa_asyncmsgq *pa_asyncmsgq_new(unsigned size) {
     return a;
 }
 
-void pa_asyncmsgq_free(pa_asyncmsgq *a) {
+static void asyncmsgq_free(pa_asyncmsgq *a) {
     struct asyncmsgq_item *i;
     pa_assert(a);
 
@@ -97,9 +99,23 @@ void pa_asyncmsgq_free(pa_asyncmsgq *a) {
     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(a);
+    pa_assert(PA_REFCNT_VALUE(a) > 0);
 
     if (!(i = pa_flist_pop(PA_STATIC_FLIST_GET(asyncmsgq))))
         i = pa_xnew(struct asyncmsgq_item, 1);
@@ -125,7 +141,7 @@ void pa_asyncmsgq_post(pa_asyncmsgq *a, pa_msgobject *object, int code, const vo
 
 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(a);
+    pa_assert(PA_REFCNT_VALUE(a) > 0);
 
     i.code = code;
     i.object = object;
@@ -152,7 +168,7 @@ int pa_asyncmsgq_send(pa_asyncmsgq *a, pa_msgobject *object, int code, const voi
 }
 
 int pa_asyncmsgq_get(pa_asyncmsgq *a, pa_msgobject **object, int *code, void **userdata, int64_t *offset, pa_memchunk *chunk, int wait) {
-    pa_assert(a);
+    pa_assert(PA_REFCNT_VALUE(a) > 0);
     pa_assert(code);
     pa_assert(!a->current);
 
@@ -181,6 +197,7 @@ int pa_asyncmsgq_get(pa_asyncmsgq *a, pa_msgobject **object, int *code, void **u
 }
 
 void pa_asyncmsgq_done(pa_asyncmsgq *a, int ret) {
+    pa_assert(PA_REFCNT_VALUE(a) > 0);
     pa_assert(a);
     pa_assert(a->current);
 
@@ -207,12 +224,14 @@ void pa_asyncmsgq_done(pa_asyncmsgq *a, int ret) {
 
 int pa_asyncmsgq_wait_for(pa_asyncmsgq *a, int code) {
     int c;
-    pa_assert(a);
+    pa_assert(PA_REFCNT_VALUE(a) > 0);
+
+    pa_asyncmsgq_ref(a);
 
     do {
         pa_msgobject *o;
         void *data;
-    int64_t offset;
+        int64_t offset;
         pa_memchunk chunk;
         int ret;
 
@@ -224,23 +243,25 @@ int pa_asyncmsgq_wait_for(pa_asyncmsgq *a, int code) {
 
     } while (c != code);
 
+    pa_asyncmsgq_unref(a);
+    
     return 0;
 }
 
 int pa_asyncmsgq_get_fd(pa_asyncmsgq *a) {
-    pa_assert(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(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(a);
+    pa_assert(PA_REFCNT_VALUE(a) > 0);
 
     pa_asyncq_after_poll(a->asyncq);
 }
diff --git a/src/pulsecore/asyncmsgq.h b/src/pulsecore/asyncmsgq.h
index b0f1a6e..2f18837 100644
--- a/src/pulsecore/asyncmsgq.h
+++ b/src/pulsecore/asyncmsgq.h
@@ -49,13 +49,14 @@
  * latter waits for completion, synchronously. */
 
 enum {
-    PA_MESSAGE_SHUTDOWN /* A generic message to inform the handler of this queue to quit */
+    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(size_t size);
-void pa_asyncmsgq_free(pa_asyncmsgq* q);
+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);
diff --git a/src/pulsecore/thread-mq.c b/src/pulsecore/thread-mq.c
index 89b65e5..513409d 100644
--- a/src/pulsecore/thread-mq.c
+++ b/src/pulsecore/thread-mq.c
@@ -46,11 +46,13 @@ static pa_tls *tls;
 
 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_after_poll(q->outq);
+    pa_asyncmsgq_ref(aq = q->outq);
+    pa_asyncmsgq_after_poll(aq);
 
     for (;;) {
         pa_msgobject *object;
@@ -60,16 +62,18 @@ static void asyncmsgq_cb(pa_mainloop_api*api, pa_io_event* e, int fd, pa_io_even
         pa_memchunk chunk;
 
         /* Check whether there is a message for us to process */
-        while (pa_asyncmsgq_get(q->outq, &object, &code, &data, &offset, &chunk, 0) == 0) {
+        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(q->outq, ret);
+            pa_asyncmsgq_done(aq, ret);
         }
 
-        if (pa_asyncmsgq_before_poll(q->outq) == 0)
+        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) {
@@ -90,9 +94,8 @@ void pa_thread_mq_done(pa_thread_mq *q) {
     q->mainloop->io_free(q->io_event);
     q->io_event = NULL;
 
-    pa_asyncmsgq_after_poll(q->outq);
-    pa_asyncmsgq_free(q->inq);
-    pa_asyncmsgq_free(q->outq);
+    pa_asyncmsgq_unref(q->inq);
+    pa_asyncmsgq_unref(q->outq);
     q->inq = q->outq = NULL;
     
     q->mainloop = NULL;
diff --git a/src/tests/asyncmsgq-test.c b/src/tests/asyncmsgq-test.c
index baf93a0..e7d662e 100644
--- a/src/tests/asyncmsgq-test.c
+++ b/src/tests/asyncmsgq-test.c
@@ -104,7 +104,7 @@ int main(int argc, char *argv[]) {
 
     pa_thread_free(t);
 
-    pa_asyncmsgq_free(q);
+    pa_asyncmsgq_unref(q);
 
     return 0;
 }

commit 107b23d202ca62eb5d510438799702bdfe1ef54e
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sat Aug 11 16:07:38 2007 +0000

    fix module-hal when no api= argument is specified
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1636 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-hal-detect.c b/src/modules/module-hal-detect.c
index e95e97f..f00a60d 100644
--- a/src/modules/module-hal-detect.c
+++ b/src/modules/module-hal-detect.c
@@ -360,6 +360,7 @@ static int hal_device_add_all(struct userdata *u, const char *capability) {
     }
 
     if (n > 0) {
+        u->capability = capability;
         
         for (i = 0; i < n; i++) {
             struct device *d;

commit 447c4a53276516f1ac71a4684ca5a6277a442c79
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sat Aug 11 16:08:20 2007 +0000

    deal with messages properly which are recieved after destruction of a stream
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1637 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c
index a67f9b0..1a112a8 100644
--- a/src/pulsecore/protocol-native.c
+++ b/src/pulsecore/protocol-native.c
@@ -407,6 +407,9 @@ static int record_stream_process_msg(pa_msgobject *o, int code, void*userdata, i
     record_stream *s = RECORD_STREAM(o);
     record_stream_assert_ref(s);
 
+    if (!s->connection)
+        return -1;
+    
     switch (code) {
         
         case RECORD_STREAM_MESSAGE_POST_DATA:
@@ -524,6 +527,9 @@ static int playback_stream_process_msg(pa_msgobject *o, int code, void*userdata,
     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;
@@ -689,6 +695,9 @@ static int connection_process_msg(pa_msgobject *o, int code, void*userdata, int6
     connection *c = CONNECTION(o);
     connection_assert_ref(c);
 
+    if (!c->protocol)
+        return -1;
+    
     switch (code) {
         
         case CONNECTION_MESSAGE_REVOKE:

commit b71dde0e358cd53505a7ec85f942d7724acef5c1
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sat Aug 11 16:51:21 2007 +0000

    make sure that the device access event sound is only generated once
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1638 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-hal-detect.c b/src/modules/module-hal-detect.c
index f00a60d..441ebfe 100644
--- a/src/modules/module-hal-detect.c
+++ b/src/modules/module-hal-detect.c
@@ -68,6 +68,7 @@ struct device {
     uint32_t index;
     char *udi;
     char *sink_name, *source_name;
+    int acl_race_fix;
 };
 
 struct userdata {
@@ -329,6 +330,7 @@ static struct device* hal_device_add(struct userdata *u, const char *udi) {
         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;
@@ -559,23 +561,27 @@ static DBusHandlerResult filter_cb(DBusConnection *bus, DBusMessage *message, vo
             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 (pa_sink_suspend(sink, suspend) >= 0) {
-                            if (!suspend && prev_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 if (suspend && !prev_suspended) {
-                                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
+                                d->acl_race_fix = 1;
+                            
+                        } else if (!prev_suspended && suspend) {
+                            /* suspend */
+                            if (pa_sink_suspend(sink, 1) >= 0)
+                                send_acl_race_fix_message = 1;
                         }
                     }
                 }
@@ -583,10 +589,29 @@ static DBusHandlerResult filter_cb(DBusConnection *bus, DBusMessage *message, vo
                 if (d->source_name) {
                     pa_source *source;
 
-                    if ((source = pa_namereg_get(u->core, d->source_name, PA_NAMEREG_SOURCE, 0)))
-                        pa_source_suspend(source, suspend);
+                    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);
         }
@@ -600,30 +625,38 @@ static DBusHandlerResult filter_cb(DBusConnection *bus, DBusMessage *message, vo
         const char *udi;
         struct device *d;
 
-        pa_log_debug("Got dirty give up message, trying resume ...");
-
         udi = dbus_message_get_path(message);
         
-        if ((d = pa_hashmap_get(u->devices, udi))) {
+        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 (pa_sink_suspend(sink, 0) >= 0)
-                        if (prev_suspended && !prev_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)))
-                    pa_source_suspend(source, 0);
+                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 

commit a3cd8002b524ab323b964847fc0daa08e85f1bc8
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sat Aug 11 17:09:07 2007 +0000

    port oss driver to make use of the default fragment sizes as defined in pa_core: store in the sink/source description whether mmap is used; if mmap() fails, fall back to UNIX read/write mode instead of bailing out immediately
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1639 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-oss.c b/src/modules/module-oss.c
index d71de99..1a36663 100644
--- a/src/modules/module-oss.c
+++ b/src/modules/module-oss.c
@@ -103,9 +103,6 @@ PA_MODULE_USAGE(
 
 #define DEFAULT_DEVICE "/dev/dsp"
 
-#define DEFAULT_NFRAGS 4
-#define DEFAULT_FRAGSIZE_MSEC 25
-
 struct userdata {
     pa_core *core;
     pa_module *module;
@@ -1103,8 +1100,8 @@ int pa__init(pa_module*m) {
         goto fail;
     }
 
-    nfrags = DEFAULT_NFRAGS;
-    frag_size = pa_usec_to_bytes(DEFAULT_FRAGSIZE_MSEC*1000, &ss);
+    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);
 
@@ -1127,7 +1124,7 @@ int pa__init(pa_module*m) {
     }
     
     if (use_mmap && mode == O_WRONLY) {
-        pa_log_info("Device opened for write only, cannot do memory mapping, falling back to UNIX read/write mode.");
+        pa_log_info("Device opened for playback only, cannot do memory mapping, falling back to UNIX write() mode.");
         use_mmap = 0;
     }
 
@@ -1188,17 +1185,11 @@ int pa__init(pa_module*m) {
 
         if (use_mmap) {
             if ((u->in_mmap = mmap(NULL, u->in_hwbuf_size, PROT_READ, 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 try_write;
-                } else {
-                    pa_log("mmap(): %s", pa_cstrerror(errno));
-                    goto fail;
-                }
-            }
-
-            pa_log_debug("Successfully mmap()ed input buffer.");
+                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)))
@@ -1221,11 +1212,12 @@ int pa__init(pa_module*m) {
         pa_source_set_module(u->source, m);
         pa_source_set_asyncmsgq(u->source, u->thread_mq.inq);
         pa_source_set_description(u->source, t = pa_sprintf_malloc(
-                                          "OSS PCM on %s%s%s%s",
+                                          "OSS PCM on %s%s%s%s%s",
                                           dev,
                                           hwdesc[0] ? " (" : "",
                                           hwdesc[0] ? hwdesc : "",
-                                          hwdesc[0] ? ")" : ""));
+                                          hwdesc[0] ? ")" : "",
+                                          use_mmap ? " via DMA" : ""));
         pa_xfree(t);
         u->source->is_hardware = 1;
         u->source->refresh_volume = 1;
@@ -1234,8 +1226,6 @@ int pa__init(pa_module*m) {
             u->in_mmap_memblocks = pa_xnew0(pa_memblock*, u->in_nfrags);
     }
 
-try_write:
-    
     if (mode != O_RDONLY) {
         char *name_buf = NULL;
 
@@ -1246,13 +1236,14 @@ try_write:
                     mode = O_WRONLY;
                     goto go_on;
                 } else {
-                    pa_log("mmap(): %s", pa_cstrerror(errno));
-                    goto fail;
+                    pa_log_warn("mmap(PROT_WRITE) failed, reverting to non-mmap mode: %s", pa_cstrerror(errno));
+                    u->use_mmap = use_mmap = 0;
+                    u->out_mmap = NULL;
                 }
+            } else {
+                pa_log_debug("Successfully mmap()ed output buffer.");
+                pa_silence_memory(u->out_mmap, u->out_hwbuf_size, &ss);
             }
-
-            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)))
@@ -1275,11 +1266,12 @@ try_write:
         pa_sink_set_module(u->sink, m);
         pa_sink_set_asyncmsgq(u->sink, u->thread_mq.inq);
         pa_sink_set_description(u->sink, t = pa_sprintf_malloc(
-                                        "OSS PCM on %s%s%s%s",
+                                        "OSS PCM on %s%s%s%s%s",
                                         dev,
                                         hwdesc[0] ? " (" : "",
                                         hwdesc[0] ? hwdesc : "",
-                                        hwdesc[0] ? ")" : ""));
+                                        hwdesc[0] ? ")" : "",
+                                        use_mmap ? " via DMA" : ""));
         pa_xfree(t);
         u->sink->is_hardware = 1;
         u->sink->refresh_volume = 1;

commit 50e014e7a9bc1742d5a9f37f7fa057a6a23a1d6c
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sat Aug 11 19:08:06 2007 +0000

    use single array for storing pa_core hook lists, add sink state changed hook, drop NO_HOOKS flags for sink inputs/source outputs, listen for resume events in module-suspend-on-idle.c
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1640 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-rescue-streams.c b/src/modules/module-rescue-streams.c
index fa22d60..e0eed03 100644
--- a/src/modules/module-rescue-streams.c
+++ b/src/modules/module-rescue-streams.c
@@ -138,8 +138,8 @@ int pa__init(pa_module*m) {
     }
 
     m->userdata = u = pa_xnew(struct userdata, 1);
-    u->sink_slot = pa_hook_connect(&m->core->hook_sink_disconnect, (pa_hook_cb_t) sink_hook_callback, NULL);
-    u->source_slot = pa_hook_connect(&m->core->hook_source_disconnect, (pa_hook_cb_t) source_hook_callback, NULL);
+    u->sink_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_DISCONNECT], (pa_hook_cb_t) sink_hook_callback, NULL);
+    u->source_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_DISCONNECT], (pa_hook_cb_t) source_hook_callback, NULL);
 
     pa_modargs_free(ma);
     return 0;
diff --git a/src/modules/module-suspend-on-idle.c b/src/modules/module-suspend-on-idle.c
index ad14864..0d21cfb 100644
--- a/src/modules/module-suspend-on-idle.c
+++ b/src/modules/module-suspend-on-idle.c
@@ -50,7 +50,7 @@ struct userdata {
     pa_core *core;
     pa_usec_t timeout;
     pa_hashmap *device_infos;
-    pa_hook_slot *sink_new_slot, *source_new_slot, *sink_disconnect_slot, *source_disconnect_slot;
+    pa_hook_slot *sink_new_slot, *source_new_slot, *sink_disconnect_slot, *source_disconnect_slot, *sink_state_changed_slot, *source_state_changed_slot;
     pa_hook_slot *sink_input_new_slot, *source_output_new_slot, *sink_input_disconnect_slot, *source_output_disconnect_slot;
 };
 
@@ -69,13 +69,13 @@ static void timeout_cb(pa_mainloop_api*a, pa_time_event* e, const struct timeval
 
     d->userdata->core->mainloop->time_restart(d->time_event, NULL);
     
-    if (d->sink && pa_sink_used_by(d->sink) <= 0) {
+    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, 1);
         pa_source_suspend(d->sink->monitor_source, 1);
     }
 
-    if (d->source && pa_source_used_by(d->source) <= 0) {
+    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, 1);
     }
@@ -209,6 +209,40 @@ static pa_hook_result_t device_disconnect_hook_cb(pa_core *c, pa_object *o, stru
     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);
+        
+        if (pa_sink_used_by(s) <= 0) {
+            pa_sink_state_t state = pa_sink_get_state(s);
+
+            if (state == PA_SINK_RUNNING || state == PA_SINK_IDLE)
+                restart(d);
+        }
+        
+    } else if (pa_source_isinstance(o)) {
+        pa_source *s = PA_SOURCE(o);
+
+        if (pa_source_used_by(s) <= 0) {
+            pa_sink_state_t state = pa_source_get_state(s);
+
+            if (state == PA_SINK_RUNNING || state == PA_SINK_IDLE)
+                restart(d);
+        }
+    }
+            
+    return PA_HOOK_OK;
+}
+
 int pa__init(pa_module*m) {
     pa_modargs *ma = NULL;
     struct userdata *u;
@@ -240,15 +274,17 @@ int pa__init(pa_module*m) {
     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->hook_sink_new_post, (pa_hook_cb_t) device_new_hook_cb, u);
-    u->source_new_slot = pa_hook_connect(&m->core->hook_source_new_post, (pa_hook_cb_t) device_new_hook_cb, u);
-    u->sink_disconnect_slot = pa_hook_connect(&m->core->hook_sink_disconnect_post, (pa_hook_cb_t) device_disconnect_hook_cb, u);
-    u->source_disconnect_slot = pa_hook_connect(&m->core->hook_source_disconnect_post, (pa_hook_cb_t) device_disconnect_hook_cb, u);
-
-    u->sink_input_new_slot = pa_hook_connect(&m->core->hook_sink_input_new_post, (pa_hook_cb_t) sink_input_new_hook_cb, u);
-    u->source_output_new_slot = pa_hook_connect(&m->core->hook_source_output_new_post, (pa_hook_cb_t) source_output_new_hook_cb, u);
-    u->sink_input_disconnect_slot = pa_hook_connect(&m->core->hook_sink_input_disconnect_post, (pa_hook_cb_t) sink_input_disconnect_hook_cb, u);
-    u->source_output_disconnect_slot = pa_hook_connect(&m->core->hook_source_output_disconnect_post, (pa_hook_cb_t) source_output_disconnect_hook_cb, 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_disconnect_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_DISCONNECT], (pa_hook_cb_t) device_disconnect_hook_cb, u);
+    u->source_disconnect_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_DISCONNECT], (pa_hook_cb_t) device_disconnect_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_disconnect_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_INPUT_DISCONNECT_POST], (pa_hook_cb_t) sink_input_disconnect_hook_cb, u);
+    u->source_output_disconnect_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_DISCONNECT_POST], (pa_hook_cb_t) source_output_disconnect_hook_cb, u);
     
     pa_modargs_free(ma);
     return 0;
@@ -276,11 +312,15 @@ void pa__done(pa_module*m) {
         pa_hook_slot_free(u->sink_new_slot);
     if (u->sink_disconnect_slot)
         pa_hook_slot_free(u->sink_disconnect_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_disconnect_slot)
         pa_hook_slot_free(u->source_disconnect_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);
diff --git a/src/modules/module-volume-restore.c b/src/modules/module-volume-restore.c
index addd937..0041760 100644
--- a/src/modules/module-volume-restore.c
+++ b/src/modules/module-volume-restore.c
@@ -444,8 +444,8 @@ int pa__init(pa_module*m) {
         goto fail;
 
     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->hook_sink_input_new, (pa_hook_cb_t) sink_input_hook_callback, u);
-    u->source_output_hook_slot = pa_hook_connect(&m->core->hook_source_output_new, (pa_hook_cb_t) source_output_hook_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;
diff --git a/src/pulsecore/core.c b/src/pulsecore/core.c
index 8b10d39..2e9d96b 100644
--- a/src/pulsecore/core.c
+++ b/src/pulsecore/core.c
@@ -72,7 +72,8 @@ 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) {
@@ -138,22 +139,8 @@ pa_core* pa_core_new(pa_mainloop_api *m, int shared) {
 
     c->is_system_instance = 0;
 
-    pa_hook_init(&c->hook_sink_new, c);
-    pa_hook_init(&c->hook_sink_new_post, c);
-    pa_hook_init(&c->hook_sink_disconnect, c);
-    pa_hook_init(&c->hook_sink_disconnect_post, c);
-    pa_hook_init(&c->hook_source_new, c);
-    pa_hook_init(&c->hook_source_new_post, c);
-    pa_hook_init(&c->hook_source_disconnect, c);
-    pa_hook_init(&c->hook_source_disconnect_post, c);
-    pa_hook_init(&c->hook_sink_input_new, c);
-    pa_hook_init(&c->hook_sink_input_new_post, c);
-    pa_hook_init(&c->hook_sink_input_disconnect, c);
-    pa_hook_init(&c->hook_sink_input_disconnect_post, c);
-    pa_hook_init(&c->hook_source_output_new, c);
-    pa_hook_init(&c->hook_source_output_new_post, c);
-    pa_hook_init(&c->hook_source_output_disconnect, c);
-    pa_hook_init(&c->hook_source_output_disconnect_post, c);
+    for (j = 0; j < PA_CORE_HOOK_MAX; j++)
+        pa_hook_init(&c->hooks[j], c);
 
     pa_property_init(c);
 
@@ -168,6 +155,7 @@ pa_core* pa_core_new(pa_mainloop_api *m, int shared) {
 
 static void core_free(pa_object *o) {
     pa_core *c = PA_CORE(o);
+    int j;
     pa_assert(c);
 
     pa_module_unload_all(c);
@@ -203,22 +191,8 @@ static void core_free(pa_object *o) {
 
     pa_property_cleanup(c);
 
-    pa_hook_free(&c->hook_sink_new);
-    pa_hook_free(&c->hook_sink_new_post);
-    pa_hook_free(&c->hook_sink_disconnect);
-    pa_hook_free(&c->hook_sink_disconnect_post);
-    pa_hook_free(&c->hook_source_new);
-    pa_hook_free(&c->hook_source_new_post);
-    pa_hook_free(&c->hook_source_disconnect);
-    pa_hook_free(&c->hook_source_disconnect_post);
-    pa_hook_free(&c->hook_sink_input_new);
-    pa_hook_free(&c->hook_sink_input_new_post);
-    pa_hook_free(&c->hook_sink_input_disconnect);
-    pa_hook_free(&c->hook_sink_input_disconnect_post);
-    pa_hook_free(&c->hook_source_output_new);
-    pa_hook_free(&c->hook_source_output_new_post);
-    pa_hook_free(&c->hook_source_output_disconnect);
-    pa_hook_free(&c->hook_source_output_disconnect_post);
+    for (j = 0; j < PA_CORE_HOOK_MAX; j++)
+        pa_hook_free(&c->hooks[j]);
 
     pa_xfree(c);
 }
diff --git a/src/pulsecore/core.h b/src/pulsecore/core.h
index 003b24b..c49a77d 100644
--- a/src/pulsecore/core.h
+++ b/src/pulsecore/core.h
@@ -42,6 +42,26 @@ typedef struct pa_core pa_core;
 #include <pulsecore/sink-input.h>
 #include <pulsecore/msgobject.h>
 
+typedef enum pa_core_hook {
+    PA_CORE_HOOK_SINK_NEW_POST,
+    PA_CORE_HOOK_SINK_DISCONNECT,
+    PA_CORE_HOOK_SINK_DISCONNECT_POST,
+    PA_CORE_HOOK_SINK_STATE_CHANGED,
+    PA_CORE_HOOK_SOURCE_NEW_POST,
+    PA_CORE_HOOK_SOURCE_DISCONNECT,
+    PA_CORE_HOOK_SOURCE_DISCONNECT_POST,
+    PA_CORE_HOOK_SOURCE_STATE_CHANGED,
+    PA_CORE_HOOK_SINK_INPUT_NEW,
+    PA_CORE_HOOK_SINK_INPUT_PUT,
+    PA_CORE_HOOK_SINK_INPUT_DISCONNECT,
+    PA_CORE_HOOK_SINK_INPUT_DISCONNECT_POST,
+    PA_CORE_HOOK_SOURCE_OUTPUT_NEW,
+    PA_CORE_HOOK_SOURCE_OUTPUT_PUT,
+    PA_CORE_HOOK_SOURCE_OUTPUT_DISCONNECT,
+    PA_CORE_HOOK_SOURCE_OUTPUT_DISCONNECT_POST,
+    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. */
@@ -89,23 +109,7 @@ struct pa_core {
     int is_system_instance;
 
     /* hooks */
-    pa_hook
-        hook_sink_new,
-        hook_sink_new_post,
-        hook_sink_disconnect,
-        hook_sink_disconnect_post,
-        hook_source_new,
-        hook_source_new_post,
-        hook_source_disconnect,
-        hook_source_disconnect_post,
-        hook_sink_input_new,
-        hook_sink_input_new_post,
-        hook_sink_input_disconnect,
-        hook_sink_input_disconnect_post,
-        hook_source_output_new,
-        hook_source_output_new_post,
-        hook_source_output_disconnect,
-        hook_source_output_disconnect_post;
+    pa_hook hooks[PA_CORE_HOOK_MAX];
 };
 
 PA_DECLARE_CLASS(pa_core);
diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c
index d1bf0ac..77b95fe 100644
--- a/src/pulsecore/sink-input.c
+++ b/src/pulsecore/sink-input.c
@@ -98,9 +98,8 @@ pa_sink_input* pa_sink_input_new(
     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;
 
     pa_return_null_if_fail(!data->driver || pa_utf8_valid(data->driver));
     pa_return_null_if_fail(!data->name || pa_utf8_valid(data->name));
@@ -249,7 +248,7 @@ void pa_sink_input_disconnect(pa_sink_input *i) {
     pa_assert(i);
     pa_return_if_fail(i->state != PA_SINK_INPUT_DISCONNECTED);
 
-    pa_hook_fire(&i->sink->core->hook_sink_input_disconnect, i);
+    pa_hook_fire(&i->sink->core->hooks[PA_CORE_HOOK_SINK_INPUT_DISCONNECT], i);
     
     if (i->sync_prev)
         i->sync_prev->sync_next = i->sync_next;
@@ -273,7 +272,7 @@ void pa_sink_input_disconnect(pa_sink_input *i) {
     i->get_latency = NULL;
     i->underrun = NULL;
 
-    pa_hook_fire(&i->sink->core->hook_sink_input_disconnect_post, i);
+    pa_hook_fire(&i->sink->core->hooks[PA_CORE_HOOK_SINK_INPUT_DISCONNECT_POST], i);
     i->sink = NULL;
     pa_sink_input_unref(i);
 }
@@ -313,7 +312,7 @@ void pa_sink_input_put(pa_sink_input *i) {
     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->hook_sink_input_new_post, i);
+    pa_hook_fire(&i->sink->core->hooks[PA_CORE_HOOK_SINK_INPUT_PUT], i);
 }
 
 void pa_sink_input_kill(pa_sink_input*i) {
diff --git a/src/pulsecore/sink-input.h b/src/pulsecore/sink-input.h
index 0168805..5a48418 100644
--- a/src/pulsecore/sink-input.h
+++ b/src/pulsecore/sink-input.h
@@ -47,7 +47,6 @@ typedef enum pa_sink_input_state {
 
 typedef enum pa_sink_input_flags {
     PA_SINK_INPUT_VARIABLE_RATE = 1,
-    PA_SINK_INPUT_NO_HOOKS = 2
 } pa_sink_input_flags_t;
 
 struct pa_sink_input {
diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c
index 905fe3f..929542c 100644
--- a/src/pulsecore/sink.c
+++ b/src/pulsecore/sink.c
@@ -80,9 +80,6 @@ pa_sink* pa_sink_new(
     pa_return_null_if_fail(!driver || pa_utf8_valid(driver));
     pa_return_null_if_fail(name && pa_utf8_valid(name) && *name);
 
-    if (pa_hook_fire(&core->hook_sink_new, NULL) < 0) /* FIXME */
-        return NULL;
-    
     s = pa_msgobject_new(pa_sink);
 
     if (!(name = pa_namereg_register(core, name, PA_NAMEREG_SINK, s, fail))) {
@@ -149,7 +146,7 @@ pa_sink* pa_sink_new(
 
     pa_subscription_post(core, PA_SUBSCRIPTION_EVENT_SINK | PA_SUBSCRIPTION_EVENT_NEW, s->index);
 
-    pa_hook_fire(&core->hook_sink_new_post, s);
+    pa_hook_fire(&core->hooks[PA_CORE_HOOK_SINK_NEW_POST], s);
 
     return s;
 }
@@ -170,6 +167,8 @@ static int sink_set_state(pa_sink *s, pa_sink_state_t state) {
         return -1;
 
     s->state = state;
+    
+    pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SINK_STATE_CHANGED], s);
     return 0;
 }
 
@@ -179,7 +178,7 @@ void pa_sink_disconnect(pa_sink* s) {
     pa_assert(s);
     pa_return_if_fail(s->state != PA_SINK_DISCONNECTED);
 
-    pa_hook_fire(&s->core->hook_sink_disconnect, s);
+    pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SINK_DISCONNECT], s);
     
     pa_namereg_unregister(s->core, s->name);
     pa_idxset_remove_by_data(s->core->sinks, s, NULL);
@@ -204,7 +203,7 @@ void pa_sink_disconnect(pa_sink* s) {
 
     pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK | PA_SUBSCRIPTION_EVENT_REMOVE, s->index);
 
-    pa_hook_fire(&s->core->hook_sink_disconnect_post, s);
+    pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SINK_DISCONNECT_POST], s);
 }
 
 static void sink_free(pa_object *o) {
diff --git a/src/pulsecore/source-output.c b/src/pulsecore/source-output.c
index 95755f3..2dc66bf 100644
--- a/src/pulsecore/source-output.c
+++ b/src/pulsecore/source-output.c
@@ -76,9 +76,8 @@ pa_source_output* pa_source_output_new(
     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;
 
     pa_return_null_if_fail(!data->driver || pa_utf8_valid(data->driver));
     pa_return_null_if_fail(!data->name || pa_utf8_valid(data->name));
@@ -187,7 +186,7 @@ void pa_source_output_disconnect(pa_source_output*o) {
     pa_assert(o);
     pa_return_if_fail(o->state != PA_SOURCE_OUTPUT_DISCONNECTED);
 
-    pa_hook_fire(&o->source->core->hook_source_output_disconnect, o);
+    pa_hook_fire(&o->source->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_DISCONNECT], o);
     
     pa_asyncmsgq_send(o->source->asyncmsgq, PA_MSGOBJECT(o->source), PA_SOURCE_MESSAGE_REMOVE_OUTPUT, o, 0, NULL);
 
@@ -203,7 +202,7 @@ void pa_source_output_disconnect(pa_source_output*o) {
     o->kill = NULL;
     o->get_latency = NULL;
 
-    pa_hook_fire(&o->source->core->hook_source_output_disconnect_post, o);
+    pa_hook_fire(&o->source->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_DISCONNECT_POST], o);
 
     o->source = NULL;
     pa_source_output_unref(o);
@@ -235,7 +234,7 @@ void pa_source_output_put(pa_source_output *o) {
 
     pa_subscription_post(o->source->core, PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_NEW, o->index);
 
-    pa_hook_fire(&o->source->core->hook_source_output_new_post, o);
+    pa_hook_fire(&o->source->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_PUT], o);
 }
 
 void pa_source_output_kill(pa_source_output*o) {
diff --git a/src/pulsecore/source-output.h b/src/pulsecore/source-output.h
index 47cc8c4..b17adcb 100644
--- a/src/pulsecore/source-output.h
+++ b/src/pulsecore/source-output.h
@@ -42,8 +42,7 @@ typedef enum pa_source_output_state {
 } pa_source_output_state_t;
 
 typedef enum pa_source_output_flags {
-    PA_SOURCE_OUTPUT_NO_HOOKS = 1,
-    PA_SOURCE_OUTPUT_VARIABLE_RATE = 2
+    PA_SOURCE_OUTPUT_VARIABLE_RATE = 1
 } pa_source_output_flags_t;
 
 struct pa_source_output {
diff --git a/src/pulsecore/source.c b/src/pulsecore/source.c
index f782593..0e448f6 100644
--- a/src/pulsecore/source.c
+++ b/src/pulsecore/source.c
@@ -73,9 +73,6 @@ pa_source* pa_source_new(
     pa_return_null_if_fail(!driver || pa_utf8_valid(driver));
     pa_return_null_if_fail(pa_utf8_valid(name) && *name);
 
-    if (pa_hook_fire(&core->hook_sink_new, NULL) < 0) /* FIXME */
-        return NULL;
-    
     s = pa_msgobject_new(pa_source);
 
     if (!(name = pa_namereg_register(core, name, PA_NAMEREG_SOURCE, s, fail))) {
@@ -128,7 +125,7 @@ pa_source* pa_source_new(
 
     pa_subscription_post(core, PA_SUBSCRIPTION_EVENT_SOURCE | PA_SUBSCRIPTION_EVENT_NEW, s->index);
 
-    pa_hook_fire(&core->hook_source_new_post, s);
+    pa_hook_fire(&core->hooks[PA_CORE_HOOK_SOURCE_NEW_POST], s);
     
     return s;
 }
@@ -149,6 +146,7 @@ static int source_set_state(pa_source *s, pa_source_state_t state) {
         return -1;
 
     s->state = state;
+    pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SOURCE_STATE_CHANGED], s);
     return 0;
 }
 
@@ -158,7 +156,7 @@ void pa_source_disconnect(pa_source *s) {
     pa_assert(s);
     pa_return_if_fail(s->state != PA_SOURCE_DISCONNECTED);
 
-    pa_hook_fire(&s->core->hook_source_disconnect, s);
+    pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SOURCE_DISCONNECT], s);    
 
     pa_namereg_unregister(s->core, s->name);
     pa_idxset_remove_by_data(s->core->sources, s, NULL);
@@ -180,7 +178,7 @@ void pa_source_disconnect(pa_source *s) {
 
     pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE | PA_SUBSCRIPTION_EVENT_REMOVE, s->index);
 
-    pa_hook_fire(&s->core->hook_source_disconnect_post, s);
+    pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SOURCE_DISCONNECT_POST], s);    
 }
 
 static void source_free(pa_object *o) {

commit e71a34762ec607f6c28130987a622bed3ae5fbb5
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sat Aug 11 20:29:42 2007 +0000

    restore the ability move record streams between sources
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1641 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/core.h b/src/pulsecore/core.h
index c49a77d..4d92960 100644
--- a/src/pulsecore/core.h
+++ b/src/pulsecore/core.h
@@ -55,10 +55,14 @@ typedef enum pa_core_hook {
     PA_CORE_HOOK_SINK_INPUT_PUT,
     PA_CORE_HOOK_SINK_INPUT_DISCONNECT,
     PA_CORE_HOOK_SINK_INPUT_DISCONNECT_POST,
+    PA_CORE_HOOK_SINK_INPUT_MOVE,
+    PA_CORE_HOOK_SINK_INPUT_MOVE_POST,
     PA_CORE_HOOK_SOURCE_OUTPUT_NEW,
     PA_CORE_HOOK_SOURCE_OUTPUT_PUT,
     PA_CORE_HOOK_SOURCE_OUTPUT_DISCONNECT,
     PA_CORE_HOOK_SOURCE_OUTPUT_DISCONNECT_POST,
+    PA_CORE_HOOK_SOURCE_OUTPUT_MOVE,
+    PA_CORE_HOOK_SOURCE_OUTPUT_MOVE_POST,
     PA_CORE_HOOK_MAX
 } pa_core_hook_t;
 
diff --git a/src/pulsecore/source-output.c b/src/pulsecore/source-output.c
index 2dc66bf..34bb9de 100644
--- a/src/pulsecore/source-output.c
+++ b/src/pulsecore/source-output.c
@@ -229,7 +229,7 @@ static void source_output_free(pa_object* mo) {
 void pa_source_output_put(pa_source_output *o) {
     pa_source_output_assert_ref(o);
 
-    pa_asyncmsgq_post(o->source->asyncmsgq, PA_MSGOBJECT(o->source), PA_SOURCE_MESSAGE_ADD_OUTPUT, pa_source_output_ref(o), 0, NULL, (pa_free_cb_t) pa_source_output_unref);
+    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);
@@ -327,63 +327,73 @@ 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) {
-/*     pa_source *origin; */
-/*     pa_resampler *new_resampler = NULL; */
+    pa_source *origin;
+    pa_resampler *new_resampler = NULL;
 
     pa_source_output_assert_ref(o);
     pa_source_assert_ref(dest);
+    
+    origin = o->source;
 
-    return -1;
+    if (dest == origin)
+        return 0;
 
-/*     origin = o->source; */
+    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 (dest == origin) */
-/*         return 0; */
+    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))
 
-/*     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; */
-/*     } */
+        /* Try to reuse the old resampler if possible */
+        new_resampler = o->thread_info.resampler;
 
-/*     if (o->resampler && */
-/*         pa_sample_spec_equal(&origin->sample_spec, &dest->sample_spec) && */
-/*         pa_channel_map_equal(&origin->channel_map, &dest->channel_map)) */
+    else if (!pa_sample_spec_equal(&o->sample_spec, &dest->sample_spec) ||
+        !pa_channel_map_equal(&o->channel_map, &dest->channel_map)) {
 
-/*         /\* Try to reuse the old resampler if possible *\/ */
-/*         new_resampler = o->resampler; */
+        /* Okey, we need a new resampler for the new source */
 
-/*     else if (!pa_sample_spec_equal(&o->sample_spec, &dest->sample_spec) || */
-/*         !pa_channel_map_equal(&o->channel_map, &dest->channel_map)) { */
+        if (!(new_resampler = pa_resampler_new(
+                      dest->core->mempool,
+                      &dest->sample_spec, &dest->channel_map,
+                      &o->sample_spec, &o->channel_map,
+                      o->resample_method))) {
+            pa_log_warn("Unsupported resampling operation.");
+            return -1;
+        }
+    }
 
-/*         /\* Okey, we need a new resampler for the new source *\/ */
+    pa_hook_fire(&o->source->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_MOVE], o);
 
-/*         if (!(new_resampler = pa_resampler_new( */
-/*                       dest->core->mempool, */
-/*                       &dest->sample_spec, &dest->channel_map, */
-/*                       &o->sample_spec, &o->channel_map, */
-/*                       o->resample_method))) { */
-/*             pa_log_warn("Unsupported resampling operation."); */
-/*             return -1; */
-/*         } */
-/*     } */
+    /* 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;
+
+    /* Replace 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);
 
-/*     /\* Okey, let's move it *\/ */
-/*     pa_idxset_remove_by_data(origin->outputs, o, NULL); */
-/*     pa_idxset_put(dest->outputs, o, NULL); */
-/*     o->source = dest; */
+    pa_source_update_status(origin);
+    pa_source_update_status(dest);
 
-/*     /\* Replace resampler *\/ */
-/*     if (new_resampler != o->resampler) { */
-/*         if (o->resampler) */
-/*             pa_resampler_free(o->resampler); */
-/*         o->resampler = new_resampler; */
-/*     } */
+    pa_hook_fire(&o->source->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_MOVE_POST], o);
 
-/*     /\* Notify everyone *\/ */
-/*     pa_subscription_post(o->source->core, PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_CHANGE, o->index); */
-/*     pa_source_notify(o->source); */
+    pa_log_debug("Successfully moved source output %i from %s to %s.", o->index, origin->name, dest->name);
 
-/*     return 0; */
+    /* Notify everyone */
+    pa_subscription_post(o->source->core, PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_CHANGE, o->index);
+
+    return 0;
 }
 
 int pa_source_output_process_msg(pa_msgobject *mo, int code, void *userdata, int64_t offset, pa_memchunk* chunk) {

commit 44b82a1925dd5a229999828191c4e14c65086160
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sat Aug 11 20:30:21 2007 +0000

    Add 'via DMA' to sink/source description if device is accessed with mmap()
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1642 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-alsa-sink.c b/src/modules/module-alsa-sink.c
index af03a95..5491aac 100644
--- a/src/modules/module-alsa-sink.c
+++ b/src/modules/module-alsa-sink.c
@@ -837,9 +837,10 @@ int pa__init(pa_module*m) {
     pa_sink_set_module(u->sink, m);
     pa_sink_set_asyncmsgq(u->sink, u->thread_mq.inq);
     pa_sink_set_description(u->sink, t = pa_sprintf_malloc(
-                                    "ALSA PCM on %s (%s)",
+                                    "ALSA PCM on %s (%s)%s",
                                     dev,
-                                    snd_pcm_info_get_name(pcm_info)));
+                                    snd_pcm_info_get_name(pcm_info),
+                                    use_mmap ? " via DMA" : ""));
     pa_xfree(t);
     
     u->sink->is_hardware = 1;
diff --git a/src/modules/module-alsa-source.c b/src/modules/module-alsa-source.c
index 5de2406..b647185 100644
--- a/src/modules/module-alsa-source.c
+++ b/src/modules/module-alsa-source.c
@@ -811,9 +811,10 @@ int pa__init(pa_module*m) {
     pa_source_set_module(u->source, m);
     pa_source_set_asyncmsgq(u->source, u->thread_mq.inq);
     pa_source_set_description(u->source, t = pa_sprintf_malloc(
-                                      "ALSA PCM on %s (%s)",
+                                      "ALSA PCM on %s (%s)%s",
                                       dev,
-                                      snd_pcm_info_get_name(pcm_info)));
+                                      snd_pcm_info_get_name(pcm_info),
+                                      use_mmap ? " via DMA" : ""));
     pa_xfree(t);
 
     u->source->is_hardware = 1;

commit 57734ec414c7411a9a8724a2f9ee0cb77c6a37f9
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sat Aug 11 20:31:08 2007 +0000

    hook into move operations for resuming/suspending devices appropriately
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1643 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-suspend-on-idle.c b/src/modules/module-suspend-on-idle.c
index 0d21cfb..d2f9b7d 100644
--- a/src/modules/module-suspend-on-idle.c
+++ b/src/modules/module-suspend-on-idle.c
@@ -50,8 +50,23 @@ struct userdata {
     pa_core *core;
     pa_usec_t timeout;
     pa_hashmap *device_infos;
-    pa_hook_slot *sink_new_slot, *source_new_slot, *sink_disconnect_slot, *source_disconnect_slot, *sink_state_changed_slot, *source_state_changed_slot;
-    pa_hook_slot *sink_input_new_slot, *source_output_new_slot, *sink_input_disconnect_slot, *source_output_disconnect_slot;
+    pa_hook_slot
+        *sink_new_slot,
+        *source_new_slot,
+        *sink_disconnect_slot,
+        *source_disconnect_slot,
+        *sink_state_changed_slot,
+        *source_state_changed_slot;
+    
+    pa_hook_slot
+        *sink_input_new_slot,
+        *source_output_new_slot,
+        *sink_input_disconnect_slot,
+        *source_output_disconnect_slot,
+        *sink_input_move_slot,
+        *source_output_move_slot,
+        *sink_input_move_post_slot,
+        *source_output_move_post_slot;
 };
 
 struct device_info {
@@ -90,10 +105,31 @@ static void restart(struct device_info *d) {
     pa_timeval_add(&tv, d->userdata->timeout*1000000);
     d->userdata->core->mainloop->time_restart(d->time_event, &tv);
 
-    if (d->source)
-        pa_log_debug("Source %s becomes idle.", d->source->name);
     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, 0);
+        pa_source_suspend(d->sink->monitor_source, 0);
+        
+        pa_log_debug("Sink %s becomes busy.", d->sink->name);
+    }
+
+    if (d->source) {
+        pa_source_suspend(d->source, 0);
+        if (d->source->monitor_of)
+            pa_sink_suspend(d->source->monitor_of, 0);
+
+        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) {
@@ -104,12 +140,7 @@ static pa_hook_result_t sink_input_new_hook_cb(pa_core *c, pa_sink_input *s, str
     pa_assert(u);
     
     pa_assert_se((d = pa_hashmap_get(u->device_infos, s->sink)));
-    d->userdata->core->mainloop->time_restart(d->time_event, NULL);
-
-    pa_sink_suspend(s->sink, 0);
-    pa_source_suspend(s->sink->monitor_source, 0);
-
-    pa_log_debug("Sink %s becomes busy.", s->sink->name);
+    resume(d);
     
     return PA_HOOK_OK;
 }
@@ -122,13 +153,7 @@ static pa_hook_result_t source_output_new_hook_cb(pa_core *c, pa_source_output *
     pa_assert(u);
     
     pa_assert_se((d = pa_hashmap_get(u->device_infos, s->source)));
-    d->userdata->core->mainloop->time_restart(d->time_event, NULL);
-
-    pa_source_suspend(s->source, 0);
-    if (s->source->monitor_of)
-        pa_sink_suspend(s->source->monitor_of, 0);
-
-    pa_log_debug("Source %s becomes busy.", s->source->name);
+    resume(d);
     
     return PA_HOOK_OK;
 }
@@ -161,6 +186,58 @@ static pa_hook_result_t source_output_disconnect_hook_cb(pa_core *c, pa_source_o
     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;
+        pa_assert_se((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);
+
+    pa_assert_se((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;
+        pa_assert_se((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);
+
+    pa_assert_se((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;
     
@@ -276,8 +353,8 @@ int pa__init(pa_module*m) {
 
     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_disconnect_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_DISCONNECT], (pa_hook_cb_t) device_disconnect_hook_cb, u);
-    u->source_disconnect_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_DISCONNECT], (pa_hook_cb_t) device_disconnect_hook_cb, u);
+    u->sink_disconnect_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_DISCONNECT_POST], (pa_hook_cb_t) device_disconnect_hook_cb, u);
+    u->source_disconnect_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_DISCONNECT_POST], (pa_hook_cb_t) device_disconnect_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);
 
@@ -285,6 +362,11 @@ int pa__init(pa_module*m) {
     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_disconnect_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_INPUT_DISCONNECT_POST], (pa_hook_cb_t) sink_input_disconnect_hook_cb, u);
     u->source_output_disconnect_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_DISCONNECT_POST], (pa_hook_cb_t) source_output_disconnect_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);
+
     
     pa_modargs_free(ma);
     return 0;
@@ -326,11 +408,19 @@ void pa__done(pa_module*m) {
         pa_hook_slot_free(u->sink_input_new_slot);
     if (u->sink_input_disconnect_slot)
         pa_hook_slot_free(u->sink_input_disconnect_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->source_output_new_slot)
         pa_hook_slot_free(u->source_output_new_slot);
     if (u->source_output_disconnect_slot)
         pa_hook_slot_free(u->source_output_disconnect_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);
 
     while ((d = pa_hashmap_steal_first(u->device_infos)))
         device_info_free(d);

commit 06f2799d8f695fc4545a5027980518be72c18788
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sat Aug 11 20:31:34 2007 +0000

    minor modernizations
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1644 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-volume-restore.c b/src/modules/module-volume-restore.c
index 0041760..8c916c3 100644
--- a/src/modules/module-volume-restore.c
+++ b/src/modules/module-volume-restore.c
@@ -26,7 +26,6 @@
 #endif
 
 #include <unistd.h>
-#include <assert.h>
 #include <string.h>
 #include <errno.h>
 #include <sys/types.h>
@@ -85,8 +84,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 +169,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 +296,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 +312,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 +340,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 +362,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 +377,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;
@@ -405,7 +404,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;
@@ -424,7 +423,7 @@ int pa__init(pa_module*m) {
     pa_modargs *ma = NULL;
     struct userdata *u;
 
-    assert(m);
+    pa_assert(m);
 
     if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
         pa_log("Failed to parse module arguments");
@@ -460,7 +459,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);
@@ -471,7 +470,7 @@ static void free_func(void *p, void *userdata) {
 void pa__done(pa_module*m) {
     struct userdata* u;
 
-    assert(m);
+    pa_assert(m);
 
     if (!(u = m->userdata))
         return;

commit 45e495499e5dede1d7c0e8b18b4b2ef3df215d3e
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sat Aug 11 23:43:39 2007 +0000

    fix latency reporting for oss and alsa modules
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1645 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-alsa-sink.c b/src/modules/module-alsa-sink.c
index 5491aac..cf999a9 100644
--- a/src/modules/module-alsa-sink.c
+++ b/src/modules/module-alsa-sink.c
@@ -217,17 +217,18 @@ static int mmap_write(struct userdata *u) {
 
 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);
 
-    snd_pcm_avail_update(u->pcm_handle);
-
-    if ((err = snd_pcm_delay(u->pcm_handle, &frames)) < 0) {
+    if ((err = snd_pcm_status(u->pcm_handle, status)) < 0) 
         pa_log("Failed to get delay: %s", snd_strerror(err));
-        return 0;
-    }
+    else
+        frames = snd_pcm_status_get_delay(status);
 
     if (frames > 0)
         r = pa_bytes_to_usec(frames * u->frame_size, &u->sink->sample_spec);
@@ -356,7 +357,7 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
 
             *((pa_usec_t*) data) = r;
 
-            break;
+            return 0;
         }
 
         case PA_SINK_MESSAGE_SET_STATE:
diff --git a/src/modules/module-alsa-source.c b/src/modules/module-alsa-source.c
index b647185..8ff074d 100644
--- a/src/modules/module-alsa-source.c
+++ b/src/modules/module-alsa-source.c
@@ -209,17 +209,18 @@ static int mmap_read(struct userdata *u) {
 
 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;
+
+    snd_pcm_status_alloca(&status);
     
     pa_assert(u);
 
-    snd_pcm_avail_update(u->pcm_handle);
-
-    if ((err = snd_pcm_delay(u->pcm_handle, &frames)) < 0) {
+    if ((err = snd_pcm_status(u->pcm_handle, status)) < 0) 
         pa_log("Failed to get delay: %s", snd_strerror(err));
-        return 0;
-    }
+    else
+        frames = snd_pcm_status_get_delay(status);
 
     if (frames > 0)
         r = pa_bytes_to_usec(frames * u->frame_size, &u->source->sample_spec);
@@ -345,7 +346,7 @@ static int source_process_msg(pa_msgobject *o, int code, void *data, int64_t off
 
             *((pa_usec_t*) data) = r;
 
-            break;
+            return 0;
         }
 
         case PA_SOURCE_MESSAGE_SET_STATE:
diff --git a/src/modules/module-oss.c b/src/modules/module-oss.c
index 1a36663..d9b5b96 100644
--- a/src/modules/module-oss.c
+++ b/src/modules/module-oss.c
@@ -597,7 +597,7 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
 
             *((pa_usec_t*) data) = r;
 
-            break;
+            return 0;
         }
 
         case PA_SINK_MESSAGE_SET_STATE:

commit 14d93fce4467b6fe4cfab8424e29a97521590c72
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sat Aug 11 23:44:00 2007 +0000

    minor cleanup
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1646 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/play-memchunk.c b/src/pulsecore/play-memchunk.c
index d2d7180..f2925d1 100644
--- a/src/pulsecore/play-memchunk.c
+++ b/src/pulsecore/play-memchunk.c
@@ -63,7 +63,6 @@ static void memchunk_stream_unlink(memchunk_stream *u) {
     pa_sink_input_unref(u->sink_input);
     u->sink_input = NULL;
     
-    /* Make sure we don't decrease the ref count twice. */
     memchunk_stream_unref(u);
 }
 
@@ -160,7 +159,6 @@ int pa_play_memchunk(
     u->parent.parent.free = memchunk_stream_free;
     u->parent.process_msg = memchunk_stream_process_msg;
     u->core = sink->core;
-    u->sink_input = NULL;
     u->memchunk = *chunk;
     pa_memblock_ref(u->memchunk.memblock);
 

commit 3d81dde3355db7f5f61a06670dfd6610b723adad
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sat Aug 11 23:45:13 2007 +0000

    modernize pa_play_memblockq() and add a new function pa_memblockq_sink_input_new() which allows creation of memblockq streams without activating them immediately
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1647 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/play-memblockq.c b/src/pulsecore/play-memblockq.c
index 51ea22e..0d7efc5 100644
--- a/src/pulsecore/play-memblockq.c
+++ b/src/pulsecore/play-memblockq.c
@@ -26,7 +26,6 @@
 #endif
 
 #include <stdlib.h>
-#include <assert.h>
 #include <stdio.h>
 #include <string.h>
 
@@ -34,53 +33,106 @@
 
 #include <pulsecore/sink-input.h>
 #include <pulsecore/gccmacro.h>
+#include <pulsecore/thread-mq.h>
 
 #include "play-memblockq.h"
 
-static void sink_input_kill_cb(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;
+
+enum {
+    MEMBLOCKQ_STREAM_MESSAGE_UNLINK,
+};
+
+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_disconnect(u->sink_input);
+    
+    pa_sink_input_unref(u->sink_input);
+    u->sink_input = NULL;
+    
+    memblockq_stream_unref(u);
+}
 
-    q = i->userdata;
+static void memblockq_stream_free(pa_object *o) {
+    memblockq_stream *u = MEMBLOCKQ_STREAM(o);
+    pa_assert(u);
 
-    pa_sink_input_disconnect(i);
-    pa_sink_input_unref(i);
+    memblockq_stream_unlink(u);
+    
+    if (u->memblockq)
+        pa_memblockq_free(u->memblockq);
 
-    pa_memblockq_free(q);
+    pa_xfree(u);
 }
 
-static int sink_input_peek_cb(pa_sink_input *i, pa_memchunk *chunk) {
-    pa_memblockq *q;
-    assert(i);
-    assert(chunk);
-    assert(i->userdata);
-
-    q = i->userdata;
+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 pa_memblockq_peek(q, chunk);
+    return 0;
 }
 
-static void si_kill_cb(PA_GCC_UNUSED pa_mainloop_api *m, void *i) {
-    sink_input_kill_cb(i);
+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_cb(pa_sink_input *i, size_t length) {
-    pa_memblockq *q;
+static int sink_input_peek_cb(pa_sink_input *i, 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, 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_cb, 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,39 +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);
+    
+    /* The reference to u is dangling here, because we want
+     * to keep this stream around until it is fully played. */
+
+    /* This sink input is not "put" yet, i.e. pa_sink_input_put() has
+     * not been called! */
+    
+    return pa_sink_input_ref(u->sink_input);
+
+fail:
+    if (u)
+        memblockq_stream_unref(u);
+
+    return NULL;
+}
 
-    si->peek = sink_input_peek_cb;
-    si->drop = sink_input_drop_cb;
-    si->kill = sink_input_kill_cb;
+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;
 
-    si->userdata = q;
+    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;
+}
diff --git a/src/pulsecore/play-memblockq.h b/src/pulsecore/play-memblockq.h
index 8248e85..d879031 100644
--- a/src/pulsecore/play-memblockq.h
+++ b/src/pulsecore/play-memblockq.h
@@ -27,6 +27,16 @@
 #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,

commit 79a586db1775bdadc5f1716f3e398c6c45237af1
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sat Aug 11 23:45:50 2007 +0000

    add comments describing the context these functions are called from
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1648 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/source-output.c b/src/pulsecore/source-output.c
index 34bb9de..ce81fcc 100644
--- a/src/pulsecore/source-output.c
+++ b/src/pulsecore/source-output.c
@@ -258,6 +258,7 @@ pa_usec_t pa_source_output_get_latency(pa_source_output *o) {
     return r;
 }
 
+/* Called from thread context */
 void pa_source_output_push(pa_source_output *o, const pa_memchunk *chunk) {
     pa_memchunk rchunk;
 
@@ -396,6 +397,7 @@ int pa_source_output_move_to(pa_source_output *o, pa_source *dest) {
     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);
 

commit 1cecd46d9573d7bbe1a4e53b469b232a86e47b2a
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sat Aug 11 23:46:51 2007 +0000

    Resurrect ability to move streams between sinks
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1649 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c
index 77b95fe..5fd1da4 100644
--- a/src/pulsecore/sink-input.c
+++ b/src/pulsecore/sink-input.c
@@ -202,7 +202,7 @@ pa_sink_input* pa_sink_input_new(
     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; */
+    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;
@@ -336,6 +336,7 @@ pa_usec_t pa_sink_input_get_latency(pa_sink_input *i) {
     return r;
 }
 
+/* Called from thread context */
 int pa_sink_input_peek(pa_sink_input *i, pa_memchunk *chunk, pa_cvolume *volume) {
     int ret = -1;
     int do_volume_adj_here;
@@ -350,24 +351,24 @@ int pa_sink_input_peek(pa_sink_input *i, pa_memchunk *chunk, pa_cvolume *volume)
 
     pa_assert(i->thread_info.state == PA_SINK_INPUT_RUNNING || i->thread_info.state == PA_SINK_INPUT_DRAINED);
 
-/*     if (i->thread_info.move_silence > 0) { */
-/*         size_t l; */
+    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 *\/ */
+        /* We have just been moved and shall play some silence for a
+         * while until the old sink has drained its playback buffer */
 
-/*         if (!i->thread_info.silence_memblock) */
-/*             i->thread_info.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, SILENCE_BUFFER_LENGTH);
 
-/*         chunk->memblock = pa_memblock_ref(i->thread_info.silence_memblock); */
-/*         chunk->index = 0; */
-/*         l = pa_memblock_get_length(chunk->memblock); */
-/*         chunk->length = i->move_silence < l ? i->move_silence : l; */
+        chunk->memblock = pa_memblock_ref(i->thread_info.silence_memblock);
+        chunk->index = 0;
+        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; */
-/*     } */
+        ret = 0;
+        do_volume_adj_here = 1;
+        goto finish;
+    }
 
     if (!i->thread_info.resampler) {
         do_volume_adj_here = 0; /* FIXME??? */
@@ -437,36 +438,25 @@ finish:
     return ret;
 }
 
+/* Called from thread context */
 void pa_sink_input_drop(pa_sink_input *i, size_t length) {
     pa_sink_input_assert_ref(i);
     pa_assert(length > 0);
 
-/*     if (i->move_silence > 0) { */
-
-/*         if (chunk) { */
-/*             size_t l; */
-
-/*             l = pa_memblock_get_length(i->silence_memblock); */
-
-/*             if (chunk->memblock != i->silence_memblock || */
-/*                 chunk->index != 0 || */
-/*                 (chunk->memblock && (chunk->length != (l < i->move_silence ? l : i->move_silence)))) */
-/*                 return; */
-
-/*         } */
+    if (i->thread_info.move_silence > 0) {
 
-/*         pa_assert(i->move_silence >= length); */
+        pa_assert(i->thread_info.move_silence >= length);
 
-/*         i->move_silence -= length; */
+        i->thread_info.move_silence -= length;
 
-/*         if (i->move_silence <= 0) { */
-/*             pa_assert(i->silence_memblock); */
-/*             pa_memblock_unref(i->silence_memblock); */
-/*             i->silence_memblock = NULL; */
-/*         } */
+        if (i->thread_info.move_silence <= 0) {
+            pa_assert(i->thread_info.silence_memblock);
+            pa_memblock_unref(i->thread_info.silence_memblock);
+            i->thread_info.silence_memblock = NULL;
+        }
 
-/*         return; */
-/*     } */
+        return;
+    }
 
     if (i->thread_info.resampled_chunk.memblock) {
         size_t l = length;
@@ -509,11 +499,14 @@ void pa_sink_input_drop(pa_sink_input *i, size_t length) {
                     length -= l;
                     
                 } else {
+                    size_t l;
+
                     /* Hmmm, peeking failed, so let's at least drop
                      * the right amount of data */
-                    
-                    if (i->drop)
-                        i->drop(i, pa_resampler_request(i->thread_info.resampler, length));
+
+                    if ((l = pa_resampler_request(i->thread_info.resampler, length)) > 0)
+                        if (i->drop)
+                            i->drop(i, l);
                             
                     break;
                 }
@@ -609,166 +602,166 @@ 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_resampler *new_resampler = NULL; */
-/*     pa_memblockq *buffer = NULL; */
-/*     pa_sink *origin; */
+    pa_resampler *new_resampler = NULL;
+    pa_sink *origin;
+    pa_usec_t silence_usec = 0;
+    pa_sink_input_move_info info;
 
     pa_sink_input_assert_ref(i);
     pa_sink_assert_ref(dest);
 
-    return -1;
-
-/*     origin = i->sink; */
-
-/*     if (dest == origin) */
-/*         return 0; */
-
-/*     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 && */
-/*         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; */
-
-/*     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)) { */
+    origin = i->sink;
 
-/*         /\* Okey, we need a new resampler for the new sink *\/ */
-
-/*         if (!(new_resampler = pa_resampler_new( */
-/*                       dest->core->mempool, */
-/*                       &i->sample_spec, &i->channel_map, */
-/*                       &dest->sample_spec, &dest->channel_map, */
-/*                       i->resample_method))) { */
-/*             pa_log_warn("Unsupported resampling operation."); */
-/*             return -1; */
-/*         } */
-/*     } */
-
-/*     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 *\/ */
+    if (dest == origin)
+        return 0;
 
-/*         old_latency = pa_sink_get_latency(origin); */
-/*         new_latency = pa_sink_get_latency(dest); */
+    if (i->sync_next || i->sync_prev) {
+        pa_log_warn("Moving synchronised streams not supported.");
+        return -1;
+    }
 
-/*         /\* The already resampled data should go to the old sink *\/ */
+    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 (old_latency >= new_latency) { */
+    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))
 
-/*             /\* The latency of the old sink is larger than the latency */
-/*              * of the new sink. Therefore to compensate for the */
-/*              * difference we to play silence on the new one for a */
-/*              * while *\/ */
+        /* Try to reuse the old resampler if possible */
+        new_resampler = i->thread_info.resampler;
 
-/*             silence_usec = old_latency - new_latency; */
+    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)) {
 
-/*         } else { */
-/*             size_t l; */
-/*             int volume_is_norm; */
+        /* Okey, we need a new resampler for the new sink */
 
-/*             /\* The latency of new sink is larger than the latency of */
-/*              * the old sink. Therefore we have to precompute a little */
-/*              * and make sure that this is still played on the old */
-/*              * sink, until we can play the first sample on the new */
-/*              * sink.*\/ */
+        if (!(new_resampler = pa_resampler_new(
+                      dest->core->mempool,
+                      &i->sample_spec, &i->channel_map,
+                      &dest->sample_spec, &dest->channel_map,
+                      i->resample_method))) {
+            pa_log_warn("Unsupported resampling operation.");
+            return -1;
+        }
+    }
 
-/*             l = pa_usec_to_bytes(new_latency - old_latency, &origin->sample_spec); */
+    pa_hook_fire(&i->sink->core->hooks[PA_CORE_HOOK_SINK_INPUT_MOVE], i);
 
-/*             volume_is_norm = pa_cvolume_is_norm(&i->volume); */
+    memset(&info, 0, sizeof(info));
+    info.sink_input = i;
+    
+    if (!immediately) {
+        pa_usec_t old_latency, new_latency;
 
-/*             while (l > 0) { */
-/*                 pa_memchunk chunk; */
-/*                 pa_cvolume volume; */
-/*                 size_t n; */
+        /* Let's do a little bit of Voodoo for compensating latency
+         * differences. We assume that the accuracy for our
+         * estimations is still good enough, even though we do these
+         * operations non-atomic. */
 
-/*                 if (pa_sink_input_peek(i, &chunk, &volume) < 0) */
-/*                     break; */
+        old_latency = pa_sink_get_latency(origin);
+        new_latency = pa_sink_get_latency(dest);
 
-/*                 n = chunk.length > l ? l : chunk.length; */
-/*                 pa_sink_input_drop(i, &chunk, n); */
-/*                 chunk.length = n; */
+        /* The already resampled data should go to the old sink */
 
-/*                 if (!volume_is_norm) { */
-/*                     pa_memchunk_make_writable(&chunk, 0); */
-/*                     pa_volume_memchunk(&chunk, &origin->sample_spec, &volume); */
-/*                 } */
+        if (old_latency >= new_latency) {
 
-/*                 if (pa_memblockq_push(buffer, &chunk) < 0) { */
-/*                     pa_memblock_unref(chunk.memblock); */
-/*                     break; */
-/*                 } */
+            /* The latency of the old sink is larger than the latency
+             * of the new sink. Therefore to compensate for the
+             * difference we to play silence on the new one for a
+             * while */
 
-/*                 pa_memblock_unref(chunk.memblock); */
-/*                 l -= n; */
-/*             } */
-/*         } */
+            silence_usec = old_latency - new_latency;
 
-/*         if (i->resampled_chunk.memblock) { */
+        } else {
 
-/*             /\* 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 *\/ */
+            /* The latency of new sink is larger than the latency of
+             * the old sink. Therefore we have to precompute a little
+             * and make sure that this is still played on the old
+             * sink, until we can play the first sample on the new
+             * sink.*/
 
-/*             pa_memblockq_push(buffer, &i->resampled_chunk); */
-/*             silence_usec += pa_bytes_to_usec(i->resampled_chunk.length, &origin->sample_spec); */
-/*         } */
+            info.buffer_bytes = pa_usec_to_bytes(new_latency - old_latency, &origin->sample_spec);
+        }
 
-/*         /\* 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); */
-/*     } */
+        /* Okey, let's move it */
+        
+        if (info.buffer_bytes > 0) {
+            
+            info.ghost_sink_input = pa_memblockq_sink_input_new(
+                    origin,
+                    "Ghost Stream",
+                    &origin->sample_spec,
+                    &origin->channel_map,
+                    NULL,
+                    NULL);
+
+            info.buffer = pa_memblockq_new(0, MOVE_BUFFER_LENGTH, 0, pa_frame_size(&origin->sample_spec), 0, 0, NULL);
+        }
+    }
 
-/*     /\* Okey, let's move it *\/ */
-/*     pa_idxset_remove_by_data(origin->inputs, i, NULL); */
-/*     pa_idxset_put(dest->inputs, i, NULL); */
-/*     i->sink = dest; */
+    pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i->sink), PA_SINK_MESSAGE_REMOVE_INPUT_AND_BUFFER, &info, 0, NULL);
 
-/*     /\* Replace resampler *\/ */
-/*     if (new_resampler != i->resampler) { */
-/*         if (i->resampler) */
-/*             pa_resampler_free(i->resampler); */
-/*         i->resampler = new_resampler; */
+    if (info.ghost_sink_input) {
+        /* Basically, do what pa_sink_input_put() does ...*/
+        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);
+    }
+    
+    pa_idxset_remove_by_data(origin->inputs, i, NULL);
+    pa_idxset_put(dest->inputs, i, NULL);
+    i->sink = dest;
+
+    /* Replace 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->thread_info.silence_memblock) {
+            pa_memblock_unref(i->thread_info.silence_memblock);
+            i->thread_info.silence_memblock = NULL;
+        }
+    }
 
-/*         /\* 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; */
-/*         } */
-/*     } */
+    /* Dump already resampled data */
+    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);
+    }
 
-/*     /\* 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; */
-/*     } */
+    /* 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, &i->sample_spec) +
+                silence_usec,
+                &i->sample_spec);
 
-/*     /\* Notify everyone *\/ */
-/*     pa_subscription_post(i->sink->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index); */
-/*     pa_sink_notify(i->sink); */
+    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);
 
-/*     /\* Ok, now 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); */
+    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);
 
-/*     return 0; */
+    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);
 
@@ -789,19 +782,18 @@ int pa_sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int64_t
             if (i->thread_info.resampled_chunk.memblock)
                 *r += pa_bytes_to_usec(i->thread_info.resampled_chunk.length, &i->sink->sample_spec);
 
-/*             if (i->move_silence) */
-/*                 r += pa_bytes_to_usec(i->move_silence, &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: {
+        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;
diff --git a/src/pulsecore/sink-input.h b/src/pulsecore/sink-input.h
index 5a48418..d728d46 100644
--- a/src/pulsecore/sink-input.h
+++ b/src/pulsecore/sink-input.h
@@ -95,7 +95,7 @@ struct pa_sink_input {
         /* 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; */
+        size_t move_silence;
         pa_memblock *silence_memblock;               /* may be NULL */
 
         pa_sink_input *sync_prev, *sync_next;
@@ -188,4 +188,11 @@ int pa_sink_input_peek(pa_sink_input *i, 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
diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c
index 929542c..df08ff6 100644
--- a/src/pulsecore/sink.c
+++ b/src/pulsecore/sink.c
@@ -42,6 +42,7 @@
 #include <pulsecore/core-subscribe.h>
 #include <pulsecore/log.h>
 #include <pulsecore/macro.h>
+#include <pulsecore/play-memblockq.h>
 
 #include "sink.h"
 
@@ -721,6 +722,72 @@ int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offse
             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->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 %u bytes ...", 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, &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 %u bytes ...", 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;
+            }
+            
+            return 0;
+        }
+
         case PA_SINK_MESSAGE_SET_VOLUME:
             s->thread_info.soft_volume = *((pa_cvolume*) userdata);
             return 0;
diff --git a/src/pulsecore/sink.h b/src/pulsecore/sink.h
index 494bb6a..8a6fa23 100644
--- a/src/pulsecore/sink.h
+++ b/src/pulsecore/sink.h
@@ -110,6 +110,7 @@ typedef enum pa_sink_message {
     PA_SINK_MESSAGE_GET_LATENCY,
     PA_SINK_MESSAGE_SET_STATE,
     PA_SINK_MESSAGE_PING,
+    PA_SINK_MESSAGE_REMOVE_INPUT_AND_BUFFER,
     PA_SINK_MESSAGE_MAX
 } pa_sink_message_t;
 

commit b16d8e2df4ad18074195da590831cb0ca3d48dee
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sun Aug 12 18:40:50 2007 +0000

    bump soname and stuff for fedora pre-release
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1650 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/configure.ac b/configure.ac
index 89fcb06..ba93bcb 100644
--- a/configure.ac
+++ b/configure.ac
@@ -26,7 +26,7 @@ AC_PREREQ(2.57)
 
 m4_define(PA_MAJOR, [0])
 m4_define(PA_MINOR, [9])
-m4_define(PA_MICRO, [6])
+m4_define(PA_MICRO, [7])
 
 AC_INIT([pulseaudio], PA_MAJOR.PA_MINOR.PA_MICRO,[mzcbylcnhqvb (at) 0pointer (dot) de])
 AC_CONFIG_SRCDIR([src/daemon/main.c])
@@ -39,8 +39,8 @@ AC_SUBST(PACKAGE_URL, [http://0pointer.de/lennart/projects/pulseaudio/])
 AC_SUBST(PA_API_VERSION, 10)
 AC_SUBST(PA_PROTOCOL_VERSION, 10)
 
-AC_SUBST(LIBPULSE_VERSION_INFO, [2:0:2])
-AC_SUBST(LIBPULSECORE_VERSION_INFO, [3:0:0])
+AC_SUBST(LIBPULSE_VERSION_INFO, [2:1:2])
+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])

commit 55f3d34923caf6421b40ac2e901441ac8b165f5b
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sun Aug 12 20:24:03 2007 +0000

    ship full libltdl tree in SVN to make sure we can build this crack on fedora
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1651 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/bootstrap.sh b/bootstrap.sh
index b85f025..b8db16f 100755
--- a/bootstrap.sh
+++ b/bootstrap.sh
@@ -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"
@@ -54,7 +54,7 @@ else
     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 "$@" 
diff --git a/configure.ac b/configure.ac
index ba93bcb..6d7f0be 100644
--- a/configure.ac
+++ b/configure.ac
@@ -110,12 +110,11 @@ fi
 
 AC_LTDL_ENABLE_INSTALL
 AC_LIBLTDL_INSTALLABLE
-AC_SUBST(LTDLINCL)
-AC_SUBST(LIBLTDL)
 AC_LIBTOOL_DLOPEN
 AC_LIBTOOL_WIN32_DLL
 AC_PROG_LIBTOOL
-AC_CONFIG_SUBDIRS(libltdl)
+AC_SUBST(LTDLINCL)
+AC_SUBST(LIBLTDL)
 
 if test "x$enable_ltdl_install" = "xno" && test "x$ac_cv_lib_ltdl_lt_dlinit" = "xno" ; then
     AC_MSG_ERROR([[
@@ -783,6 +782,8 @@ src/pulse/version.h
 ])
 AC_OUTPUT
 
+AC_CONFIG_SUBDIRS(libltdl)
+
 # ==========================================================================
 ENABLE_X11=no
 if test "x$HAVE_X11" = "x1" ; then
diff --git a/libltdl/COPYING.LIB b/libltdl/COPYING.LIB
new file mode 100644
index 0000000..ba2be48
--- /dev/null
+++ b/libltdl/COPYING.LIB
@@ -0,0 +1,515 @@
+
+                  GNU LESSER GENERAL PUBLIC LICENSE
+                       Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+     51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL.  It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+                            Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+  This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it.  You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations
+below.
+
+  When we speak of free software, we are referring to freedom of use,
+not price.  Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+  To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights.  These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+  For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you.  You must make sure that they, too, receive or can get the source
+code.  If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it.  And you must show them these terms so they know their rights.
+
+  We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+  To protect each distributor, we want to make it very clear that
+there is no warranty for the free library.  Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+^L
+  Finally, software patents pose a constant threat to the existence of
+any free program.  We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder.  Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+  Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License.  This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License.  We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+  When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library.  The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom.  The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+  We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License.  It also provides other free software developers Less
+of an advantage over competing non-free programs.  These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries.  However, the Lesser license provides advantages in certain
+special circumstances.
+
+  For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it
+becomes
+a de-facto standard.  To achieve this, non-free programs must be
+allowed to use the library.  A more frequent case is that a free
+library does the same job as widely used non-free libraries.  In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+  In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software.  For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+  Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.  Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library".  The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+^L
+                  GNU LESSER GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+  A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+  The "Library", below, refers to any such software library or work
+which has been distributed under these terms.  A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language.  (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+  "Source code" for a work means the preferred form of the work for
+making modifications to it.  For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control
+compilation
+and installation of the library.
+
+  Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it).  Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+  1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+  You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+  2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) The modified work must itself be a software library.
+
+    b) You must cause the files modified to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    c) You must cause the whole of the work to be licensed at no
+    charge to all third parties under the terms of this License.
+
+    d) If a facility in the modified Library refers to a function or a
+    table of data to be supplied by an application program that uses
+    the facility, other than as an argument passed when the facility
+    is invoked, then you must make a good faith effort to ensure that,
+    in the event an application does not supply such function or
+    table, the facility still operates, and performs whatever part of
+    its purpose remains meaningful.
+
+    (For example, a function in a library to compute square roots has
+    a purpose that is entirely well-defined independent of the
+    application.  Therefore, Subsection 2d requires that any
+    application-supplied function or table used by this function must
+    be optional: if the application does not supply it, the square
+    root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library.  To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License.  (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.)  Do not make any other change in
+these notices.
+^L
+  Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+  This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+  4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+  If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library".  Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+  However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library".  The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+  When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library.  The
+threshold for this to be true is not precisely defined by law.
+
+  If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work.  (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+  Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+^L
+  6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+  You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License.  You must supply a copy of this License.  If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License.  Also, you must do one
+of these things:
+
+    a) Accompany the work with the complete corresponding
+    machine-readable source code for the Library including whatever
+    changes were used in the work (which must be distributed under
+    Sections 1 and 2 above); and, if the work is an executable linked
+    with the Library, with the complete machine-readable "work that
+    uses the Library", as object code and/or source code, so that the
+    user can modify the Library and then relink to produce a modified
+    executable containing the modified Library.  (It is understood
+    that the user who changes the contents of definitions files in the
+    Library will not necessarily be able to recompile the application
+    to use the modified definitions.)
+
+    b) Use a suitable shared library mechanism for linking with the
+    Library.  A suitable mechanism is one that (1) uses at run time a
+    copy of the library already present on the user's computer system,
+    rather than copying library functions into the executable, and (2)
+    will operate properly with a modified version of the library, if
+    the user installs one, as long as the modified version is
+    interface-compatible with the version that the work was made with.
+
+    c) Accompany the work with a written offer, valid for at
+    least three years, to give the same user the materials
+    specified in Subsection 6a, above, for a charge no more
+    than the cost of performing this distribution.
+
+    d) If distribution of the work is made by offering access to copy
+    from a designated place, offer equivalent access to copy the above
+    specified materials from the same place.
+
+    e) Verify that the user has already received a copy of these
+    materials or that you have already sent this user a copy.
+
+  For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it.  However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+  It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system.  Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+^L
+  7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+    a) Accompany the combined library with a copy of the same work
+    based on the Library, uncombined with any other library
+    facilities.  This must be distributed under the terms of the
+    Sections above.
+
+    b) Give prominent notice with the combined library of the fact
+    that part of it is a work based on the Library, and explaining
+    where to find the accompanying uncombined form of the same work.
+
+  8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License.  Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License.  However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+  9. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Library or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+  10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+^L
+  11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply, and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License
+may add an explicit geographical distribution limitation excluding those
+countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation.  If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+^L
+  14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission.  For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this.  Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+                            NO WARRANTY
+
+  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+                     END OF TERMS AND CONDITIONS
+^L
+           How to Apply These Terms to Your New Libraries
+
+  If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change.  You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms
+of the ordinary General Public License).
+
+  To apply these terms, attach the following notices to the library.
+It is safest to attach them to the start of each source file to most
+effectively convey the exclusion of warranty; and each file should
+have at least the "copyright" line and a pointer to where the full
+notice is found.
+
+
+    <one line to give the library's name and a brief idea of what it
+does.>
+    Copyright (C) <year>  <name of author>
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
+
+Also add information on how to contact you by electronic and paper
+mail.
+
+You should also get your employer (if you work as a programmer) or
+your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the
+  library `Frob' (a library for tweaking knobs) written by James
+Random Hacker.
+
+  <signature of Ty Coon>, 1 April 1990
+  Ty Coon, President of Vice
+
+That's all there is to it!
+
+
diff --git a/libltdl/Makefile b/libltdl/Makefile
new file mode 100644
index 0000000..90fddd7
--- /dev/null
+++ b/libltdl/Makefile
@@ -0,0 +1,656 @@
+# Makefile.in generated by automake 1.10 from Makefile.am.
+# Makefile.  Generated from Makefile.in by configure.
+
+# 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.
+
+
+
+
+
+pkgdatadir = $(datadir)/libltdl
+pkglibdir = $(libdir)/libltdl
+pkgincludedir = $(includedir)/libltdl
+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 = i686-pc-linux-gnu
+host_triplet = i686-pc-linux-gnu
+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 $@
+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)
+#am_libltdlc_la_rpath =
+DEFAULT_INCLUDES = -I.
+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 = ${SHELL} /home/lennart/projects/pulseaudio/libltdl/missing --run aclocal-1.10
+AMTAR = ${SHELL} /home/lennart/projects/pulseaudio/libltdl/missing --run tar
+AR = ar
+AS = as
+AUTOCONF = ${SHELL} /home/lennart/projects/pulseaudio/libltdl/missing --run autoconf
+AUTOHEADER = ${SHELL} /home/lennart/projects/pulseaudio/libltdl/missing --run autoheader
+AUTOMAKE = ${SHELL} /home/lennart/projects/pulseaudio/libltdl/missing --run automake-1.10
+AWK = gawk
+CC = gcc
+CCDEPMODE = depmode=none
+CFLAGS = -g -O2
+CPP = gcc -E
+CPPFLAGS = 
+CXX = g++
+CXXCPP = g++ -E
+CXXDEPMODE = depmode=none
+CXXFLAGS = -g -O2
+CYGPATH_W = echo
+DEFS = -DHAVE_CONFIG_H
+DEPDIR = .deps
+DLLTOOL = dlltool
+ECHO = echo
+ECHO_C = 
+ECHO_N = -n
+ECHO_T = 
+EGREP = /bin/grep -E
+EXEEXT = 
+F77 = gfortran
+FFLAGS = -g -O2
+GREP = /bin/grep
+INSTALL = /usr/bin/install -c
+INSTALL_DATA = ${INSTALL} -m 644
+INSTALL_PROGRAM = ${INSTALL}
+INSTALL_SCRIPT = ${INSTALL}
+INSTALL_STRIP_PROGRAM = $(install_sh) -c -s
+LDFLAGS = 
+LIBADD_DL = -ldl
+LIBOBJS = 
+LIBS = 
+LIBTOOL = $(SHELL) $(top_builddir)/libtool
+LIBTOOL_DEPS = ./ltmain.sh
+LN_S = ln -s
+LTLIBOBJS = 
+MAKEINFO = ${SHELL} /home/lennart/projects/pulseaudio/libltdl/missing --run makeinfo
+MKDIR_P = /bin/mkdir -p
+OBJDUMP = objdump
+OBJEXT = o
+PACKAGE = libltdl
+PACKAGE_BUGREPORT = bug-libtool at gnu.org
+PACKAGE_NAME = libltdl
+PACKAGE_STRING = libltdl 1.2
+PACKAGE_TARNAME = libltdl
+PACKAGE_VERSION = 1.2
+PATH_SEPARATOR = :
+RANLIB = ranlib
+SED = /bin/sed
+SET_MAKE = 
+SHELL = /bin/sh
+STRIP = strip
+VERSION = 1.2
+abs_builddir = /home/lennart/projects/pulseaudio/libltdl
+abs_srcdir = /home/lennart/projects/pulseaudio/libltdl
+abs_top_builddir = /home/lennart/projects/pulseaudio/libltdl
+abs_top_srcdir = /home/lennart/projects/pulseaudio/libltdl
+ac_ct_CC = gcc
+ac_ct_CXX = g++
+ac_ct_F77 = gfortran
+am__include = include
+am__leading_dot = .
+am__quote = 
+am__tar = ${AMTAR} chof - "$$tardir"
+am__untar = ${AMTAR} xf -
+bindir = ${exec_prefix}/bin
+build = i686-pc-linux-gnu
+build_alias = 
+build_cpu = i686
+build_os = linux-gnu
+build_vendor = pc
+builddir = .
+datadir = ${datarootdir}
+datarootdir = ${prefix}/share
+docdir = ${datarootdir}/doc/${PACKAGE_TARNAME}
+dvidir = ${docdir}
+exec_prefix = ${prefix}
+host = i686-pc-linux-gnu
+host_alias = 
+host_cpu = i686
+host_os = linux-gnu
+host_vendor = pc
+htmldir = ${docdir}
+includedir = ${prefix}/include
+infodir = ${datarootdir}/info
+install_sh = $(SHELL) /home/lennart/projects/pulseaudio/libltdl/install-sh
+libdir = ${exec_prefix}/lib
+libexecdir = ${exec_prefix}/libexec
+localedir = ${datarootdir}/locale
+localstatedir = ${prefix}/var
+mandir = ${datarootdir}/man
+mkdir_p = /bin/mkdir -p
+oldincludedir = /usr/include
+pdfdir = ${docdir}
+prefix = /usr/local
+program_transform_name = s,x,x,
+psdir = ${docdir}
+sbindir = ${exec_prefix}/sbin
+sharedstatedir = ${prefix}/com
+srcdir = .
+sysconfdir = ${prefix}/etc
+target_alias = 
+top_builddir = .
+top_srcdir = .
+AUTOMAKE_OPTIONS = no-dependencies foreign
+include_HEADERS = ltdl.h
+lib_LTLIBRARIES = libltdl.la
+#noinst_HEADERS = ltdl.h
+#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/Makefile.am b/libltdl/Makefile.am
new file mode 100644
index 0000000..2a1e701
--- /dev/null
+++ b/libltdl/Makefile.am
@@ -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
index 0000000..4319156
--- /dev/null
+++ b/libltdl/Makefile.in
@@ -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.
+
+ at 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 $@
+ at 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)
+ at CONVENIENCE_LTDL_TRUE@am_libltdlc_la_rpath =
+DEFAULT_INCLUDES = -I. at 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
+ at INSTALL_LTDL_TRUE@include_HEADERS = ltdl.h
+ at INSTALL_LTDL_TRUE@lib_LTLIBRARIES = libltdl.la
+ at INSTALL_LTDL_FALSE@noinst_HEADERS = ltdl.h
+ at 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
index 0000000..da0a449
--- /dev/null
+++ b/libltdl/README
@@ -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
index 0000000..3f1dd40
--- /dev/null
+++ b/libltdl/acinclude.m4
@@ -0,0 +1,7012 @@
+# 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 at 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 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*)
+      libsuff=64
+      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
+  sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}"
+  sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}"
+
+  # 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="$sys_lib_dlsearch_path_spec $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'
+  ;;
+
+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 at 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*)
+  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 at 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*)
+    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 at 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*)
+	;;
+      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'
+  ;;
+  *)
+    _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 at 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 at 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
+      else
+	_LT_AC_TAGVAR(ld_shlibs, $1)=no
+      fi
+      ;;
+
+    netbsd*)
+      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*)
+      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*)
+    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
index 0000000..fcc414d
--- /dev/null
+++ b/libltdl/aclocal.m4
@@ -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
index 0000000..b864071
--- /dev/null
+++ b/libltdl/config-h.in
@@ -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
index 0000000..951383e
--- /dev/null
+++ b/libltdl/config.guess
@@ -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-05-17'
+
+# 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 at bothner.com>.
+# Please send patches to <config-patches at 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 at 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 at 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 at 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.*:* | ix86xen: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 at ccMail.Census.GOV>
+        echo i586-unisys-sysv4
+        exit ;;
+    *:UNIX_System_V:4*:FTX*)
+	# From Gerald Hewes <hewes at openmarket.com>.
+	# How about differentiating between stratus architectures? -djm
+	echo hppa1.1-stratus-sysv4
+	exit ;;
+    *:*:*:FTX*)
+	# From seanf at swdc.stratus.com.
+	echo i860-stratus-sysv4
+	exit ;;
+    i*86:VOS:*:*)
+	# From Paul.Green at stratus.com.
+	echo ${UNAME_MACHINE}-stratus-vos
+	exit ;;
+    *:VOS:*:*)
+	# From Paul.Green at 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 at 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
index 0000000..0fe3124
--- /dev/null
+++ b/libltdl/config.h
@@ -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 "/usr/lib:/lib:/usr/lib/qt-3.3/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 at 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.log b/libltdl/config.log
new file mode 100644
index 0000000..1aca1d9
--- /dev/null
+++ b/libltdl/config.log
@@ -0,0 +1,1609 @@
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+
+It was created by libltdl configure 1.2, which was
+generated by GNU Autoconf 2.61.  Invocation command line was
+
+  $ ./configure 
+
+## --------- ##
+## Platform. ##
+## --------- ##
+
+hostname = lambda
+uname -m = i686
+uname -r = 2.6.23-0.73.rc2.fc8
+uname -s = Linux
+uname -v = #1 SMP Mon Aug 6 20:26:04 EDT 2007
+
+/usr/bin/uname -p = unknown
+/bin/uname -X     = unknown
+
+/bin/arch              = i686
+/usr/bin/arch -k       = unknown
+/usr/convex/getsysinfo = unknown
+/usr/bin/hostinfo      = unknown
+/bin/machine           = unknown
+/usr/bin/oslevel       = unknown
+/bin/universe          = unknown
+
+PATH: /home/lennart/bin
+PATH: /usr/lib/qt-3.3/bin
+PATH: /usr/kerberos/bin
+PATH: /usr/lib/ccache
+PATH: /usr/local/bin
+PATH: /bin
+PATH: /usr/bin
+
+
+## ----------- ##
+## Core tests. ##
+## ----------- ##
+
+configure:2017: checking for a BSD-compatible install
+configure:2073: result: /usr/bin/install -c
+configure:2084: checking whether build environment is sane
+configure:2127: result: yes
+configure:2155: checking for a thread-safe mkdir -p
+configure:2194: result: /bin/mkdir -p
+configure:2207: checking for gawk
+configure:2223: found /bin/gawk
+configure:2234: result: gawk
+configure:2245: checking whether make sets $(MAKE)
+configure:2266: result: yes
+configure:2500: checking for gcc
+configure:2516: found /usr/lib/ccache/gcc
+configure:2527: result: gcc
+configure:2765: checking for C compiler version
+configure:2772: gcc --version >&5
+gcc (GCC) 4.1.2 20070723 (Red Hat 4.1.2-17)
+Copyright (C) 2006 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.
+
+configure:2775: $? = 0
+configure:2782: gcc -v >&5
+Using built-in specs.
+Target: i386-redhat-linux
+Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --enable-shared --enable-threads=posix --enable-checking=release --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-languages=c,c++,objc,obj-c++,java,fortran,ada --enable-java-awt=gtk --disable-dssi --enable-plugin --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-1.5.0.0/jre --enable-libgcj-multifile --enable-java-maintainer-mode --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --with-cpu=generic --host=i386-redhat-linux
+Thread model: posix
+gcc version 4.1.2 20070723 (Red Hat 4.1.2-17)
+configure:2785: $? = 0
+configure:2792: gcc -V >&5
+gcc: '-V' option must have argument
+configure:2795: $? = 1
+configure:2818: checking for C compiler default output file name
+configure:2845: gcc    conftest.c  >&5
+configure:2848: $? = 0
+configure:2886: result: a.out
+configure:2903: checking whether the C compiler works
+configure:2913: ./a.out
+configure:2916: $? = 0
+configure:2933: result: yes
+configure:2940: checking whether we are cross compiling
+configure:2942: result: no
+configure:2945: checking for suffix of executables
+configure:2952: gcc -o conftest    conftest.c  >&5
+configure:2955: $? = 0
+configure:2979: result: 
+configure:2985: checking for suffix of object files
+configure:3011: gcc -c   conftest.c >&5
+configure:3014: $? = 0
+configure:3037: result: o
+configure:3041: checking whether we are using the GNU C compiler
+configure:3070: gcc -c   conftest.c >&5
+configure:3076: $? = 0
+configure:3093: result: yes
+configure:3098: checking whether gcc accepts -g
+configure:3128: gcc -c -g  conftest.c >&5
+configure:3134: $? = 0
+configure:3233: result: yes
+configure:3250: checking for gcc option to accept ISO C89
+configure:3324: gcc  -c -g -O2  conftest.c >&5
+configure:3330: $? = 0
+configure:3353: result: none needed
+configure:3382: checking for style of include used by make
+configure:3410: result: GNU
+configure:3435: checking dependency style of gcc
+configure:3526: result: none
+configure:3542: checking for an ANSI C-conforming const
+configure:3617: gcc -c -g -O2  conftest.c >&5
+configure:3623: $? = 0
+configure:3638: result: yes
+configure:3648: checking for inline
+configure:3674: gcc -c -g -O2  conftest.c >&5
+configure:3680: $? = 0
+configure:3698: result: inline
+configure:3802: checking build system type
+configure:3820: result: i686-pc-linux-gnu
+configure:3842: checking host system type
+configure:3857: result: i686-pc-linux-gnu
+configure:3879: checking for a sed that does not truncate output
+configure:3935: result: /bin/sed
+configure:3938: checking for grep that handles long lines and -e
+configure:4012: result: /bin/grep
+configure:4017: checking for egrep
+configure:4095: result: /bin/grep -E
+configure:4111: checking for ld used by gcc
+configure:4178: result: /usr/bin/ld
+configure:4187: checking if the linker (/usr/bin/ld) is GNU ld
+configure:4202: result: yes
+configure:4207: checking for /usr/bin/ld option to reload object files
+configure:4214: result: -r
+configure:4232: checking for BSD-compatible nm
+configure:4281: result: /usr/bin/nm -B
+configure:4285: checking whether ln -s works
+configure:4289: result: yes
+configure:4296: checking how to recognize dependent libraries
+configure:4482: result: pass_all
+configure:5013: checking how to run the C preprocessor
+configure:5053: gcc -E  conftest.c
+configure:5059: $? = 0
+configure:5090: gcc -E  conftest.c
+conftest.c:8:28: error: ac_nonexistent.h: No such file or directory
+configure:5096: $? = 1
+configure: failed program was:
+| /* confdefs.h.  */
+| #define PACKAGE_NAME "libltdl"
+| #define PACKAGE_TARNAME "libltdl"
+| #define PACKAGE_VERSION "1.2"
+| #define PACKAGE_STRING "libltdl 1.2"
+| #define PACKAGE_BUGREPORT "bug-libtool at gnu.org"
+| /* end confdefs.h.  */
+| #include <ac_nonexistent.h>
+configure:5129: result: gcc -E
+configure:5158: gcc -E  conftest.c
+configure:5164: $? = 0
+configure:5195: gcc -E  conftest.c
+conftest.c:8:28: error: ac_nonexistent.h: No such file or directory
+configure:5201: $? = 1
+configure: failed program was:
+| /* confdefs.h.  */
+| #define PACKAGE_NAME "libltdl"
+| #define PACKAGE_TARNAME "libltdl"
+| #define PACKAGE_VERSION "1.2"
+| #define PACKAGE_STRING "libltdl 1.2"
+| #define PACKAGE_BUGREPORT "bug-libtool at gnu.org"
+| /* end confdefs.h.  */
+| #include <ac_nonexistent.h>
+configure:5239: checking for ANSI C header files
+configure:5269: gcc -c -g -O2  conftest.c >&5
+configure:5275: $? = 0
+configure:5374: gcc -o conftest -g -O2   conftest.c  >&5
+configure:5377: $? = 0
+configure:5383: ./conftest
+configure:5386: $? = 0
+configure:5403: result: yes
+configure:5427: checking for sys/types.h
+configure:5448: gcc -c -g -O2  conftest.c >&5
+configure:5454: $? = 0
+configure:5470: result: yes
+configure:5427: checking for sys/stat.h
+configure:5448: gcc -c -g -O2  conftest.c >&5
+configure:5454: $? = 0
+configure:5470: result: yes
+configure:5427: checking for stdlib.h
+configure:5448: gcc -c -g -O2  conftest.c >&5
+configure:5454: $? = 0
+configure:5470: result: yes
+configure:5427: checking for string.h
+configure:5448: gcc -c -g -O2  conftest.c >&5
+configure:5454: $? = 0
+configure:5470: result: yes
+configure:5427: checking for memory.h
+configure:5448: gcc -c -g -O2  conftest.c >&5
+configure:5454: $? = 0
+configure:5470: result: yes
+configure:5427: checking for strings.h
+configure:5448: gcc -c -g -O2  conftest.c >&5
+configure:5454: $? = 0
+configure:5470: result: yes
+configure:5427: checking for inttypes.h
+configure:5448: gcc -c -g -O2  conftest.c >&5
+configure:5454: $? = 0
+configure:5470: result: yes
+configure:5427: checking for stdint.h
+configure:5448: gcc -c -g -O2  conftest.c >&5
+configure:5454: $? = 0
+configure:5470: result: yes
+configure:5427: checking for unistd.h
+configure:5448: gcc -c -g -O2  conftest.c >&5
+configure:5454: $? = 0
+configure:5470: result: yes
+configure:5497: checking dlfcn.h usability
+configure:5514: gcc -c -g -O2  conftest.c >&5
+configure:5520: $? = 0
+configure:5534: result: yes
+configure:5538: checking dlfcn.h presence
+configure:5553: gcc -E  conftest.c
+configure:5559: $? = 0
+configure:5573: result: yes
+configure:5606: checking for dlfcn.h
+configure:5614: result: yes
+configure:5685: checking for g++
+configure:5701: found /usr/lib/ccache/g++
+configure:5712: result: g++
+configure:5743: checking for C++ compiler version
+configure:5750: g++ --version >&5
+g++ (GCC) 4.1.2 20070704 (Red Hat 4.1.2-15)
+Copyright (C) 2006 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.
+
+configure:5753: $? = 0
+configure:5760: g++ -v >&5
+Using built-in specs.
+Target: i386-redhat-linux
+Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --enable-shared --enable-threads=posix --enable-checking=release --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-languages=c,c++,objc,obj-c++,java,fortran,ada --enable-java-awt=gtk --disable-dssi --enable-plugin --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-1.5.0.0/jre --enable-libgcj-multifile --enable-java-maintainer-mode --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --with-cpu=generic --host=i386-redhat-linux
+Thread model: posix
+gcc version 4.1.2 20070704 (Red Hat 4.1.2-15)
+configure:5763: $? = 0
+configure:5770: g++ -V >&5
+g++: '-V' option must have argument
+configure:5773: $? = 1
+configure:5776: checking whether we are using the GNU C++ compiler
+configure:5805: g++ -c   conftest.cpp >&5
+configure:5811: $? = 0
+configure:5828: result: yes
+configure:5833: checking whether g++ accepts -g
+configure:5863: g++ -c -g  conftest.cpp >&5
+configure:5869: $? = 0
+configure:5968: result: yes
+configure:5993: checking dependency style of g++
+configure:6084: result: none
+configure:6109: checking how to run the C++ preprocessor
+configure:6145: g++ -E  conftest.cpp
+configure:6151: $? = 0
+configure:6182: g++ -E  conftest.cpp
+conftest.cpp:19:28: error: ac_nonexistent.h: No such file or directory
+configure:6188: $? = 1
+configure: failed program was:
+| /* confdefs.h.  */
+| #define PACKAGE_NAME "libltdl"
+| #define PACKAGE_TARNAME "libltdl"
+| #define PACKAGE_VERSION "1.2"
+| #define PACKAGE_STRING "libltdl 1.2"
+| #define PACKAGE_BUGREPORT "bug-libtool at gnu.org"
+| #define STDC_HEADERS 1
+| #define HAVE_SYS_TYPES_H 1
+| #define HAVE_SYS_STAT_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_MEMORY_H 1
+| #define HAVE_STRINGS_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_UNISTD_H 1
+| #define HAVE_DLFCN_H 1
+| /* end confdefs.h.  */
+| #include <ac_nonexistent.h>
+configure:6221: result: g++ -E
+configure:6250: g++ -E  conftest.cpp
+configure:6256: $? = 0
+configure:6287: g++ -E  conftest.cpp
+conftest.cpp:19:28: error: ac_nonexistent.h: No such file or directory
+configure:6293: $? = 1
+configure: failed program was:
+| /* confdefs.h.  */
+| #define PACKAGE_NAME "libltdl"
+| #define PACKAGE_TARNAME "libltdl"
+| #define PACKAGE_VERSION "1.2"
+| #define PACKAGE_STRING "libltdl 1.2"
+| #define PACKAGE_BUGREPORT "bug-libtool at gnu.org"
+| #define STDC_HEADERS 1
+| #define HAVE_SYS_TYPES_H 1
+| #define HAVE_SYS_STAT_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_MEMORY_H 1
+| #define HAVE_STRINGS_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_UNISTD_H 1
+| #define HAVE_DLFCN_H 1
+| /* end confdefs.h.  */
+| #include <ac_nonexistent.h>
+configure:6386: checking for g77
+configure:6416: result: no
+configure:6386: checking for xlf
+configure:6416: result: no
+configure:6386: checking for f77
+configure:6416: result: no
+configure:6386: checking for frt
+configure:6416: result: no
+configure:6386: checking for pgf77
+configure:6416: result: no
+configure:6386: checking for cf77
+configure:6416: result: no
+configure:6386: checking for fort77
+configure:6416: result: no
+configure:6386: checking for fl32
+configure:6416: result: no
+configure:6386: checking for af77
+configure:6416: result: no
+configure:6386: checking for xlf90
+configure:6416: result: no
+configure:6386: checking for f90
+configure:6416: result: no
+configure:6386: checking for pgf90
+configure:6416: result: no
+configure:6386: checking for pghpf
+configure:6416: result: no
+configure:6386: checking for epcf90
+configure:6416: result: no
+configure:6386: checking for gfortran
+configure:6402: found /usr/bin/gfortran
+configure:6413: result: gfortran
+configure:6443: checking for Fortran 77 compiler version
+configure:6450: gfortran --version >&5
+GNU Fortran (GCC) 4.1.2 20070704 (Red Hat 4.1.2-15)
+Copyright (C) 2007 Free Software Foundation, Inc.
+
+GNU Fortran comes with NO WARRANTY, to the extent permitted by law.
+You may redistribute copies of GNU Fortran
+under the terms of the GNU General Public License.
+For more information about these matters, see the file named COPYING
+
+configure:6453: $? = 0
+configure:6460: gfortran -v >&5
+Using built-in specs.
+Target: i386-redhat-linux
+Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --enable-shared --enable-threads=posix --enable-checking=release --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-languages=c,c++,objc,obj-c++,java,fortran,ada --enable-java-awt=gtk --disable-dssi --enable-plugin --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-1.5.0.0/jre --enable-libgcj-multifile --enable-java-maintainer-mode --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --with-cpu=generic --host=i386-redhat-linux
+Thread model: posix
+gcc version 4.1.2 20070704 (Red Hat 4.1.2-15)
+configure:6463: $? = 0
+configure:6470: gfortran -V >&5
+gfortran: '-V' option must have argument
+configure:6473: $? = 1
+configure:6481: checking whether we are using the GNU Fortran 77 compiler
+configure:6500: gfortran -c  conftest.F >&5
+configure:6506: $? = 0
+configure:6523: result: yes
+configure:6529: checking whether gfortran accepts -g
+configure:6546: gfortran -c -g conftest.f >&5
+configure:6552: $? = 0
+configure:6568: result: yes
+configure:6598: checking the maximum length of command line arguments
+configure:6710: result: 98304
+configure:6722: checking command to parse /usr/bin/nm -B output from gcc object
+configure:6827: gcc -c -g -O2  conftest.c >&5
+configure:6830: $? = 0
+configure:6834: /usr/bin/nm -B conftest.o \| sed -n -e 's/^.*[ 	]\([ABCDGIRSTW][ABCDGIRSTW]*\)[ 	][ 	]*\([_A-Za-z][_A-Za-z0-9]*\)$/\1 \2 \2/p' \> conftest.nm
+configure:6837: $? = 0
+configure:6889: gcc -o conftest -g -O2   conftest.c conftstm.o >&5
+configure:6892: $? = 0
+configure:6930: result: ok
+configure:6934: checking for objdir
+configure:6949: result: .libs
+configure:7041: checking for ar
+configure:7057: found /usr/bin/ar
+configure:7068: result: ar
+configure:7137: checking for ranlib
+configure:7153: found /usr/bin/ranlib
+configure:7164: result: ranlib
+configure:7233: checking for strip
+configure:7249: found /usr/bin/strip
+configure:7260: result: strip
+configure:7550: checking if gcc supports -fno-rtti -fno-exceptions
+configure:7568: gcc -c -g -O2  -fno-rtti -fno-exceptions conftest.c >&5
+cc1: warning: command line option "-fno-rtti" is valid for C++/ObjC++ but not for C
+cc1: warning: command line option "-fno-rtti" is valid for C++/ObjC++ but not for C
+configure:7572: $? = 0
+configure:7585: result: no
+configure:7600: checking for gcc option to produce PIC
+configure:7832: result: -fPIC
+configure:7840: checking if gcc PIC flag -fPIC works
+configure:7858: gcc -c -g -O2  -fPIC -DPIC conftest.c >&5
+configure:7862: $? = 0
+configure:7875: result: yes
+configure:7903: checking if gcc static flag -static works
+configure:7931: result: yes
+configure:7941: checking if gcc supports -c -o file.o
+configure:7962: gcc -c -g -O2  -o out/conftest2.o conftest.c >&5
+configure:7966: $? = 0
+configure:7988: result: yes
+configure:8014: checking whether the gcc linker (/usr/bin/ld) supports shared libraries
+configure:8994: result: yes
+configure:9015: checking whether -lc should be explicitly linked in
+configure:9020: gcc -c -g -O2  conftest.c >&5
+configure:9023: $? = 0
+configure:9038: gcc -shared conftest.o  -v -Wl,-soname -Wl,conftest -o conftest 2\>\&1 \| grep  -lc  \>/dev/null 2\>\&1
+configure:9041: $? = 0
+configure:9053: result: no
+configure:9061: checking dynamic linker characteristics
+configure:9665: result: GNU/Linux ld.so
+configure:9674: checking how to hardcode library paths into programs
+configure:9699: result: immediate
+configure:9713: checking whether stripping libraries is possible
+configure:9718: result: yes
+configure:10520: checking if libtool supports shared libraries
+configure:10522: result: yes
+configure:10525: checking whether to build shared libraries
+configure:10546: result: yes
+configure:10549: checking whether to build static libraries
+configure:10553: result: yes
+configure:10646: creating libtool
+configure:11234: checking for ld used by g++
+configure:11301: result: /usr/bin/ld
+configure:11310: checking if the linker (/usr/bin/ld) is GNU ld
+configure:11325: result: yes
+configure:11376: checking whether the g++ linker (/usr/bin/ld) supports shared libraries
+configure:12350: result: yes
+configure:12372: g++ -c -g -O2  conftest.cpp >&5
+configure:12375: $? = 0
+configure:12527: checking for g++ option to produce PIC
+configure:12811: result: -fPIC
+configure:12819: checking if g++ PIC flag -fPIC works
+configure:12837: g++ -c -g -O2  -fPIC -DPIC conftest.cpp >&5
+configure:12841: $? = 0
+configure:12854: result: yes
+configure:12882: checking if g++ static flag -static works
+configure:12910: result: yes
+configure:12920: checking if g++ supports -c -o file.o
+configure:12941: g++ -c -g -O2  -o out/conftest2.o conftest.cpp >&5
+configure:12945: $? = 0
+configure:12967: result: yes
+configure:12993: checking whether the g++ linker (/usr/bin/ld) supports shared libraries
+configure:13018: result: yes
+configure:13085: checking dynamic linker characteristics
+configure:13637: result: GNU/Linux ld.so
+configure:13646: checking how to hardcode library paths into programs
+configure:13671: result: immediate
+configure:14205: checking if libtool supports shared libraries
+configure:14207: result: yes
+configure:14210: checking whether to build shared libraries
+configure:14230: result: yes
+configure:14233: checking whether to build static libraries
+configure:14237: result: yes
+configure:14247: checking for gfortran option to produce PIC
+configure:14479: result: -fPIC
+configure:14487: checking if gfortran PIC flag -fPIC works
+configure:14505: gfortran -c -g -O2 -fPIC conftest.f >&5
+configure:14509: $? = 0
+configure:14522: result: yes
+configure:14550: checking if gfortran static flag -static works
+configure:14578: result: yes
+configure:14588: checking if gfortran supports -c -o file.o
+configure:14609: gfortran -c -g -O2 -o out/conftest2.o conftest.f >&5
+configure:14613: $? = 0
+configure:14635: result: yes
+configure:14661: checking whether the gfortran linker (/usr/bin/ld) supports shared libraries
+configure:15621: result: yes
+configure:15688: checking dynamic linker characteristics
+configure:16240: result: GNU/Linux ld.so
+configure:16249: checking how to hardcode library paths into programs
+configure:16274: result: immediate
+configure:19860: checking for dirent.h that defines DIR
+configure:19889: gcc -c -g -O2  conftest.c >&5
+configure:19895: $? = 0
+configure:19911: result: yes
+configure:19924: checking for library containing opendir
+configure:19965: gcc -o conftest -g -O2   conftest.c  >&5
+configure:19971: $? = 0
+configure:19999: result: none required
+configure:20117: checking which extension is used for loadable modules
+configure:20127: result: .so
+configure:20138: checking which variable specifies run-time library path
+configure:20145: result: LD_LIBRARY_PATH
+configure:20156: checking for the default library search path
+configure:20163: result: /usr/lib /lib /usr/lib/qt-3.3/lib 
+configure:20181: checking for objdir
+configure:20202: result: .libs
+configure:20211: checking whether libtool supports -dlopen/-dlpreopen
+configure:20223: result: yes
+configure:20242: checking for shl_load
+configure:20298: gcc -o conftest -g -O2   conftest.c  >&5
+/tmp/ccPBezQi.o: In function `main':
+/home/lennart/projects/pulseaudio/libltdl/conftest.c:59: undefined reference to `shl_load'
+collect2: ld returned 1 exit status
+configure:20304: $? = 1
+configure: failed program was:
+| /* confdefs.h.  */
+| #define PACKAGE_NAME "libltdl"
+| #define PACKAGE_TARNAME "libltdl"
+| #define PACKAGE_VERSION "1.2"
+| #define PACKAGE_STRING "libltdl 1.2"
+| #define PACKAGE_BUGREPORT "bug-libtool at gnu.org"
+| #define STDC_HEADERS 1
+| #define HAVE_SYS_TYPES_H 1
+| #define HAVE_SYS_STAT_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_MEMORY_H 1
+| #define HAVE_STRINGS_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_UNISTD_H 1
+| #define HAVE_DLFCN_H 1
+| #define HAVE_DIRENT_H 1
+| #define LTDL_SHLIB_EXT ".so"
+| #define LTDL_SHLIBPATH_VAR "LD_LIBRARY_PATH"
+| #define LTDL_SYSSEARCHPATH "/usr/lib:/lib:/usr/lib/qt-3.3/lib"
+| #define LTDL_OBJDIR ".libs/"
+| #define HAVE_PRELOADED_SYMBOLS 1
+| /* 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;
+| }
+configure:20321: result: no
+configure:20330: checking for shl_load in -ldld
+configure:20365: gcc -o conftest -g -O2   conftest.c -ldld   >&5
+/usr/bin/ld: cannot find -ldld
+collect2: ld returned 1 exit status
+configure:20371: $? = 1
+configure: failed program was:
+| /* confdefs.h.  */
+| #define PACKAGE_NAME "libltdl"
+| #define PACKAGE_TARNAME "libltdl"
+| #define PACKAGE_VERSION "1.2"
+| #define PACKAGE_STRING "libltdl 1.2"
+| #define PACKAGE_BUGREPORT "bug-libtool at gnu.org"
+| #define STDC_HEADERS 1
+| #define HAVE_SYS_TYPES_H 1
+| #define HAVE_SYS_STAT_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_MEMORY_H 1
+| #define HAVE_STRINGS_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_UNISTD_H 1
+| #define HAVE_DLFCN_H 1
+| #define HAVE_DIRENT_H 1
+| #define LTDL_SHLIB_EXT ".so"
+| #define LTDL_SHLIBPATH_VAR "LD_LIBRARY_PATH"
+| #define LTDL_SYSSEARCHPATH "/usr/lib:/lib:/usr/lib/qt-3.3/lib"
+| #define LTDL_OBJDIR ".libs/"
+| #define HAVE_PRELOADED_SYMBOLS 1
+| /* 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;
+| }
+configure:20389: result: no
+configure:20399: checking for dlopen in -ldl
+configure:20434: gcc -o conftest -g -O2   conftest.c -ldl   >&5
+configure:20440: $? = 0
+configure:20458: result: yes
+configure:20769: checking for dlerror
+configure:20825: gcc -o conftest -g -O2   conftest.c  -ldl >&5
+configure:20831: $? = 0
+configure:20849: result: yes
+configure:20869: checking for _ prefix in compiled symbols
+configure:20879: gcc -c -g -O2  conftest.c >&5
+configure:20882: $? = 0
+configure:20886: /usr/bin/nm -B conftest.o \| sed -n -e 's/^.*[ 	]\([ABCDGIRSTW][ABCDGIRSTW]*\)[ 	][ 	]*\([_A-Za-z][_A-Za-z0-9]*\)$/\1 \2 \2/p' \> conftest.nm
+configure:20889: $? = 0
+configure:20911: result: no
+configure:21031: checking whether deplibs are loaded by dlopen
+configure:21115: result: yes
+configure:21140: checking argz.h usability
+configure:21157: gcc -c -g -O2  conftest.c >&5
+configure:21163: $? = 0
+configure:21177: result: yes
+configure:21181: checking argz.h presence
+configure:21196: gcc -E  conftest.c
+configure:21202: $? = 0
+configure:21216: result: yes
+configure:21249: checking for argz.h
+configure:21257: result: yes
+configure:21271: checking for error_t
+configure:21304: gcc -c -g -O2  conftest.c >&5
+configure:21310: $? = 0
+configure:21325: result: yes
+configure:21351: checking for argz_append
+configure:21407: gcc -o conftest -g -O2   conftest.c  >&5
+configure:21413: $? = 0
+configure:21431: result: yes
+configure:21351: checking for argz_create_sep
+configure:21407: gcc -o conftest -g -O2   conftest.c  >&5
+configure:21413: $? = 0
+configure:21431: result: yes
+configure:21351: checking for argz_insert
+configure:21407: gcc -o conftest -g -O2   conftest.c  >&5
+configure:21413: $? = 0
+configure:21431: result: yes
+configure:21351: checking for argz_next
+configure:21407: gcc -o conftest -g -O2   conftest.c  >&5
+configure:21413: $? = 0
+configure:21431: result: yes
+configure:21351: checking for argz_stringify
+configure:21407: gcc -o conftest -g -O2   conftest.c  >&5
+configure:21413: $? = 0
+configure:21431: result: yes
+configure:21483: checking assert.h usability
+configure:21500: gcc -c -g -O2  conftest.c >&5
+configure:21506: $? = 0
+configure:21520: result: yes
+configure:21524: checking assert.h presence
+configure:21539: gcc -E  conftest.c
+configure:21545: $? = 0
+configure:21559: result: yes
+configure:21592: checking for assert.h
+configure:21600: result: yes
+configure:21483: checking ctype.h usability
+configure:21500: gcc -c -g -O2  conftest.c >&5
+configure:21506: $? = 0
+configure:21520: result: yes
+configure:21524: checking ctype.h presence
+configure:21539: gcc -E  conftest.c
+configure:21545: $? = 0
+configure:21559: result: yes
+configure:21592: checking for ctype.h
+configure:21600: result: yes
+configure:21483: checking errno.h usability
+configure:21500: gcc -c -g -O2  conftest.c >&5
+configure:21506: $? = 0
+configure:21520: result: yes
+configure:21524: checking errno.h presence
+configure:21539: gcc -E  conftest.c
+configure:21545: $? = 0
+configure:21559: result: yes
+configure:21592: checking for errno.h
+configure:21600: result: yes
+configure:21483: checking malloc.h usability
+configure:21500: gcc -c -g -O2  conftest.c >&5
+configure:21506: $? = 0
+configure:21520: result: yes
+configure:21524: checking malloc.h presence
+configure:21539: gcc -E  conftest.c
+configure:21545: $? = 0
+configure:21559: result: yes
+configure:21592: checking for malloc.h
+configure:21600: result: yes
+configure:21473: checking for memory.h
+configure:21479: result: yes
+configure:21473: checking for stdlib.h
+configure:21479: result: yes
+configure:21483: checking stdio.h usability
+configure:21500: gcc -c -g -O2  conftest.c >&5
+configure:21506: $? = 0
+configure:21520: result: yes
+configure:21524: checking stdio.h presence
+configure:21539: gcc -E  conftest.c
+configure:21545: $? = 0
+configure:21559: result: yes
+configure:21592: checking for stdio.h
+configure:21600: result: yes
+configure:21473: checking for unistd.h
+configure:21479: result: yes
+configure:21631: checking dl.h usability
+configure:21648: gcc -c -g -O2  conftest.c >&5
+conftest.c:75:16: error: dl.h: No such file or directory
+configure:21654: $? = 1
+configure: failed program was:
+| /* confdefs.h.  */
+| #define PACKAGE_NAME "libltdl"
+| #define PACKAGE_TARNAME "libltdl"
+| #define PACKAGE_VERSION "1.2"
+| #define PACKAGE_STRING "libltdl 1.2"
+| #define PACKAGE_BUGREPORT "bug-libtool at gnu.org"
+| #define STDC_HEADERS 1
+| #define HAVE_SYS_TYPES_H 1
+| #define HAVE_SYS_STAT_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_MEMORY_H 1
+| #define HAVE_STRINGS_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_UNISTD_H 1
+| #define HAVE_DLFCN_H 1
+| #define HAVE_DIRENT_H 1
+| #define LTDL_SHLIB_EXT ".so"
+| #define LTDL_SHLIBPATH_VAR "LD_LIBRARY_PATH"
+| #define LTDL_SYSSEARCHPATH "/usr/lib:/lib:/usr/lib/qt-3.3/lib"
+| #define LTDL_OBJDIR ".libs/"
+| #define HAVE_PRELOADED_SYMBOLS 1
+| #define HAVE_LIBDL 1
+| #define HAVE_DLERROR 1
+| #define HAVE_ARGZ_H 1
+| #define HAVE_ERROR_T 1
+| #define HAVE_ARGZ_APPEND 1
+| #define HAVE_ARGZ_CREATE_SEP 1
+| #define HAVE_ARGZ_INSERT 1
+| #define HAVE_ARGZ_NEXT 1
+| #define HAVE_ARGZ_STRINGIFY 1
+| #define HAVE_ASSERT_H 1
+| #define HAVE_CTYPE_H 1
+| #define HAVE_ERRNO_H 1
+| #define HAVE_MALLOC_H 1
+| #define HAVE_MEMORY_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STDIO_H 1
+| #define HAVE_UNISTD_H 1
+| /* end confdefs.h.  */
+| #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
+| #include <dl.h>
+configure:21668: result: no
+configure:21672: checking dl.h presence
+configure:21687: gcc -E  conftest.c
+conftest.c:42:16: error: dl.h: No such file or directory
+configure:21693: $? = 1
+configure: failed program was:
+| /* confdefs.h.  */
+| #define PACKAGE_NAME "libltdl"
+| #define PACKAGE_TARNAME "libltdl"
+| #define PACKAGE_VERSION "1.2"
+| #define PACKAGE_STRING "libltdl 1.2"
+| #define PACKAGE_BUGREPORT "bug-libtool at gnu.org"
+| #define STDC_HEADERS 1
+| #define HAVE_SYS_TYPES_H 1
+| #define HAVE_SYS_STAT_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_MEMORY_H 1
+| #define HAVE_STRINGS_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_UNISTD_H 1
+| #define HAVE_DLFCN_H 1
+| #define HAVE_DIRENT_H 1
+| #define LTDL_SHLIB_EXT ".so"
+| #define LTDL_SHLIBPATH_VAR "LD_LIBRARY_PATH"
+| #define LTDL_SYSSEARCHPATH "/usr/lib:/lib:/usr/lib/qt-3.3/lib"
+| #define LTDL_OBJDIR ".libs/"
+| #define HAVE_PRELOADED_SYMBOLS 1
+| #define HAVE_LIBDL 1
+| #define HAVE_DLERROR 1
+| #define HAVE_ARGZ_H 1
+| #define HAVE_ERROR_T 1
+| #define HAVE_ARGZ_APPEND 1
+| #define HAVE_ARGZ_CREATE_SEP 1
+| #define HAVE_ARGZ_INSERT 1
+| #define HAVE_ARGZ_NEXT 1
+| #define HAVE_ARGZ_STRINGIFY 1
+| #define HAVE_ASSERT_H 1
+| #define HAVE_CTYPE_H 1
+| #define HAVE_ERRNO_H 1
+| #define HAVE_MALLOC_H 1
+| #define HAVE_MEMORY_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STDIO_H 1
+| #define HAVE_UNISTD_H 1
+| /* end confdefs.h.  */
+| #include <dl.h>
+configure:21707: result: no
+configure:21740: checking for dl.h
+configure:21748: result: no
+configure:21631: checking sys/dl.h usability
+configure:21648: gcc -c -g -O2  conftest.c >&5
+conftest.c:75:20: error: sys/dl.h: No such file or directory
+configure:21654: $? = 1
+configure: failed program was:
+| /* confdefs.h.  */
+| #define PACKAGE_NAME "libltdl"
+| #define PACKAGE_TARNAME "libltdl"
+| #define PACKAGE_VERSION "1.2"
+| #define PACKAGE_STRING "libltdl 1.2"
+| #define PACKAGE_BUGREPORT "bug-libtool at gnu.org"
+| #define STDC_HEADERS 1
+| #define HAVE_SYS_TYPES_H 1
+| #define HAVE_SYS_STAT_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_MEMORY_H 1
+| #define HAVE_STRINGS_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_UNISTD_H 1
+| #define HAVE_DLFCN_H 1
+| #define HAVE_DIRENT_H 1
+| #define LTDL_SHLIB_EXT ".so"
+| #define LTDL_SHLIBPATH_VAR "LD_LIBRARY_PATH"
+| #define LTDL_SYSSEARCHPATH "/usr/lib:/lib:/usr/lib/qt-3.3/lib"
+| #define LTDL_OBJDIR ".libs/"
+| #define HAVE_PRELOADED_SYMBOLS 1
+| #define HAVE_LIBDL 1
+| #define HAVE_DLERROR 1
+| #define HAVE_ARGZ_H 1
+| #define HAVE_ERROR_T 1
+| #define HAVE_ARGZ_APPEND 1
+| #define HAVE_ARGZ_CREATE_SEP 1
+| #define HAVE_ARGZ_INSERT 1
+| #define HAVE_ARGZ_NEXT 1
+| #define HAVE_ARGZ_STRINGIFY 1
+| #define HAVE_ASSERT_H 1
+| #define HAVE_CTYPE_H 1
+| #define HAVE_ERRNO_H 1
+| #define HAVE_MALLOC_H 1
+| #define HAVE_MEMORY_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STDIO_H 1
+| #define HAVE_UNISTD_H 1
+| /* end confdefs.h.  */
+| #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
+| #include <sys/dl.h>
+configure:21668: result: no
+configure:21672: checking sys/dl.h presence
+configure:21687: gcc -E  conftest.c
+conftest.c:42:20: error: sys/dl.h: No such file or directory
+configure:21693: $? = 1
+configure: failed program was:
+| /* confdefs.h.  */
+| #define PACKAGE_NAME "libltdl"
+| #define PACKAGE_TARNAME "libltdl"
+| #define PACKAGE_VERSION "1.2"
+| #define PACKAGE_STRING "libltdl 1.2"
+| #define PACKAGE_BUGREPORT "bug-libtool at gnu.org"
+| #define STDC_HEADERS 1
+| #define HAVE_SYS_TYPES_H 1
+| #define HAVE_SYS_STAT_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_MEMORY_H 1
+| #define HAVE_STRINGS_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_UNISTD_H 1
+| #define HAVE_DLFCN_H 1
+| #define HAVE_DIRENT_H 1
+| #define LTDL_SHLIB_EXT ".so"
+| #define LTDL_SHLIBPATH_VAR "LD_LIBRARY_PATH"
+| #define LTDL_SYSSEARCHPATH "/usr/lib:/lib:/usr/lib/qt-3.3/lib"
+| #define LTDL_OBJDIR ".libs/"
+| #define HAVE_PRELOADED_SYMBOLS 1
+| #define HAVE_LIBDL 1
+| #define HAVE_DLERROR 1
+| #define HAVE_ARGZ_H 1
+| #define HAVE_ERROR_T 1
+| #define HAVE_ARGZ_APPEND 1
+| #define HAVE_ARGZ_CREATE_SEP 1
+| #define HAVE_ARGZ_INSERT 1
+| #define HAVE_ARGZ_NEXT 1
+| #define HAVE_ARGZ_STRINGIFY 1
+| #define HAVE_ASSERT_H 1
+| #define HAVE_CTYPE_H 1
+| #define HAVE_ERRNO_H 1
+| #define HAVE_MALLOC_H 1
+| #define HAVE_MEMORY_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STDIO_H 1
+| #define HAVE_UNISTD_H 1
+| /* end confdefs.h.  */
+| #include <sys/dl.h>
+configure:21707: result: no
+configure:21740: checking for sys/dl.h
+configure:21748: result: no
+configure:21631: checking dld.h usability
+configure:21648: gcc -c -g -O2  conftest.c >&5
+conftest.c:75:17: error: dld.h: No such file or directory
+configure:21654: $? = 1
+configure: failed program was:
+| /* confdefs.h.  */
+| #define PACKAGE_NAME "libltdl"
+| #define PACKAGE_TARNAME "libltdl"
+| #define PACKAGE_VERSION "1.2"
+| #define PACKAGE_STRING "libltdl 1.2"
+| #define PACKAGE_BUGREPORT "bug-libtool at gnu.org"
+| #define STDC_HEADERS 1
+| #define HAVE_SYS_TYPES_H 1
+| #define HAVE_SYS_STAT_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_MEMORY_H 1
+| #define HAVE_STRINGS_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_UNISTD_H 1
+| #define HAVE_DLFCN_H 1
+| #define HAVE_DIRENT_H 1
+| #define LTDL_SHLIB_EXT ".so"
+| #define LTDL_SHLIBPATH_VAR "LD_LIBRARY_PATH"
+| #define LTDL_SYSSEARCHPATH "/usr/lib:/lib:/usr/lib/qt-3.3/lib"
+| #define LTDL_OBJDIR ".libs/"
+| #define HAVE_PRELOADED_SYMBOLS 1
+| #define HAVE_LIBDL 1
+| #define HAVE_DLERROR 1
+| #define HAVE_ARGZ_H 1
+| #define HAVE_ERROR_T 1
+| #define HAVE_ARGZ_APPEND 1
+| #define HAVE_ARGZ_CREATE_SEP 1
+| #define HAVE_ARGZ_INSERT 1
+| #define HAVE_ARGZ_NEXT 1
+| #define HAVE_ARGZ_STRINGIFY 1
+| #define HAVE_ASSERT_H 1
+| #define HAVE_CTYPE_H 1
+| #define HAVE_ERRNO_H 1
+| #define HAVE_MALLOC_H 1
+| #define HAVE_MEMORY_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STDIO_H 1
+| #define HAVE_UNISTD_H 1
+| /* end confdefs.h.  */
+| #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
+| #include <dld.h>
+configure:21668: result: no
+configure:21672: checking dld.h presence
+configure:21687: gcc -E  conftest.c
+conftest.c:42:17: error: dld.h: No such file or directory
+configure:21693: $? = 1
+configure: failed program was:
+| /* confdefs.h.  */
+| #define PACKAGE_NAME "libltdl"
+| #define PACKAGE_TARNAME "libltdl"
+| #define PACKAGE_VERSION "1.2"
+| #define PACKAGE_STRING "libltdl 1.2"
+| #define PACKAGE_BUGREPORT "bug-libtool at gnu.org"
+| #define STDC_HEADERS 1
+| #define HAVE_SYS_TYPES_H 1
+| #define HAVE_SYS_STAT_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_MEMORY_H 1
+| #define HAVE_STRINGS_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_UNISTD_H 1
+| #define HAVE_DLFCN_H 1
+| #define HAVE_DIRENT_H 1
+| #define LTDL_SHLIB_EXT ".so"
+| #define LTDL_SHLIBPATH_VAR "LD_LIBRARY_PATH"
+| #define LTDL_SYSSEARCHPATH "/usr/lib:/lib:/usr/lib/qt-3.3/lib"
+| #define LTDL_OBJDIR ".libs/"
+| #define HAVE_PRELOADED_SYMBOLS 1
+| #define HAVE_LIBDL 1
+| #define HAVE_DLERROR 1
+| #define HAVE_ARGZ_H 1
+| #define HAVE_ERROR_T 1
+| #define HAVE_ARGZ_APPEND 1
+| #define HAVE_ARGZ_CREATE_SEP 1
+| #define HAVE_ARGZ_INSERT 1
+| #define HAVE_ARGZ_NEXT 1
+| #define HAVE_ARGZ_STRINGIFY 1
+| #define HAVE_ASSERT_H 1
+| #define HAVE_CTYPE_H 1
+| #define HAVE_ERRNO_H 1
+| #define HAVE_MALLOC_H 1
+| #define HAVE_MEMORY_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STDIO_H 1
+| #define HAVE_UNISTD_H 1
+| /* end confdefs.h.  */
+| #include <dld.h>
+configure:21707: result: no
+configure:21740: checking for dld.h
+configure:21748: result: no
+configure:21631: checking mach-o/dyld.h usability
+configure:21648: gcc -c -g -O2  conftest.c >&5
+conftest.c:75:25: error: mach-o/dyld.h: No such file or directory
+configure:21654: $? = 1
+configure: failed program was:
+| /* confdefs.h.  */
+| #define PACKAGE_NAME "libltdl"
+| #define PACKAGE_TARNAME "libltdl"
+| #define PACKAGE_VERSION "1.2"
+| #define PACKAGE_STRING "libltdl 1.2"
+| #define PACKAGE_BUGREPORT "bug-libtool at gnu.org"
+| #define STDC_HEADERS 1
+| #define HAVE_SYS_TYPES_H 1
+| #define HAVE_SYS_STAT_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_MEMORY_H 1
+| #define HAVE_STRINGS_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_UNISTD_H 1
+| #define HAVE_DLFCN_H 1
+| #define HAVE_DIRENT_H 1
+| #define LTDL_SHLIB_EXT ".so"
+| #define LTDL_SHLIBPATH_VAR "LD_LIBRARY_PATH"
+| #define LTDL_SYSSEARCHPATH "/usr/lib:/lib:/usr/lib/qt-3.3/lib"
+| #define LTDL_OBJDIR ".libs/"
+| #define HAVE_PRELOADED_SYMBOLS 1
+| #define HAVE_LIBDL 1
+| #define HAVE_DLERROR 1
+| #define HAVE_ARGZ_H 1
+| #define HAVE_ERROR_T 1
+| #define HAVE_ARGZ_APPEND 1
+| #define HAVE_ARGZ_CREATE_SEP 1
+| #define HAVE_ARGZ_INSERT 1
+| #define HAVE_ARGZ_NEXT 1
+| #define HAVE_ARGZ_STRINGIFY 1
+| #define HAVE_ASSERT_H 1
+| #define HAVE_CTYPE_H 1
+| #define HAVE_ERRNO_H 1
+| #define HAVE_MALLOC_H 1
+| #define HAVE_MEMORY_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STDIO_H 1
+| #define HAVE_UNISTD_H 1
+| /* end confdefs.h.  */
+| #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
+| #include <mach-o/dyld.h>
+configure:21668: result: no
+configure:21672: checking mach-o/dyld.h presence
+configure:21687: gcc -E  conftest.c
+conftest.c:42:25: error: mach-o/dyld.h: No such file or directory
+configure:21693: $? = 1
+configure: failed program was:
+| /* confdefs.h.  */
+| #define PACKAGE_NAME "libltdl"
+| #define PACKAGE_TARNAME "libltdl"
+| #define PACKAGE_VERSION "1.2"
+| #define PACKAGE_STRING "libltdl 1.2"
+| #define PACKAGE_BUGREPORT "bug-libtool at gnu.org"
+| #define STDC_HEADERS 1
+| #define HAVE_SYS_TYPES_H 1
+| #define HAVE_SYS_STAT_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_MEMORY_H 1
+| #define HAVE_STRINGS_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_UNISTD_H 1
+| #define HAVE_DLFCN_H 1
+| #define HAVE_DIRENT_H 1
+| #define LTDL_SHLIB_EXT ".so"
+| #define LTDL_SHLIBPATH_VAR "LD_LIBRARY_PATH"
+| #define LTDL_SYSSEARCHPATH "/usr/lib:/lib:/usr/lib/qt-3.3/lib"
+| #define LTDL_OBJDIR ".libs/"
+| #define HAVE_PRELOADED_SYMBOLS 1
+| #define HAVE_LIBDL 1
+| #define HAVE_DLERROR 1
+| #define HAVE_ARGZ_H 1
+| #define HAVE_ERROR_T 1
+| #define HAVE_ARGZ_APPEND 1
+| #define HAVE_ARGZ_CREATE_SEP 1
+| #define HAVE_ARGZ_INSERT 1
+| #define HAVE_ARGZ_NEXT 1
+| #define HAVE_ARGZ_STRINGIFY 1
+| #define HAVE_ASSERT_H 1
+| #define HAVE_CTYPE_H 1
+| #define HAVE_ERRNO_H 1
+| #define HAVE_MALLOC_H 1
+| #define HAVE_MEMORY_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STDIO_H 1
+| #define HAVE_UNISTD_H 1
+| /* end confdefs.h.  */
+| #include <mach-o/dyld.h>
+configure:21707: result: no
+configure:21740: checking for mach-o/dyld.h
+configure:21748: result: no
+configure:21767: checking for string.h
+configure:21773: result: yes
+configure:21913: checking for strchr
+configure:21969: gcc -o conftest -g -O2   conftest.c  >&5
+conftest.c:66: warning: conflicting types for built-in function 'strchr'
+configure:21975: $? = 0
+configure:21993: result: yes
+configure:22008: checking for strrchr
+configure:22064: gcc -o conftest -g -O2   conftest.c  >&5
+conftest.c:67: warning: conflicting types for built-in function 'strrchr'
+configure:22070: $? = 0
+configure:22088: result: yes
+configure:22103: checking for memcpy
+configure:22159: gcc -o conftest -g -O2   conftest.c  >&5
+conftest.c:68: warning: conflicting types for built-in function 'memcpy'
+configure:22165: $? = 0
+configure:22183: result: yes
+configure:22198: checking for memmove
+configure:22254: gcc -o conftest -g -O2   conftest.c  >&5
+conftest.c:69: warning: conflicting types for built-in function 'memmove'
+configure:22260: $? = 0
+configure:22278: result: yes
+configure:22198: checking for strcmp
+configure:22254: gcc -o conftest -g -O2   conftest.c  >&5
+conftest.c:70: warning: conflicting types for built-in function 'strcmp'
+configure:22260: $? = 0
+configure:22278: result: yes
+configure:22294: checking for closedir
+configure:22350: gcc -o conftest -g -O2   conftest.c  >&5
+configure:22356: $? = 0
+configure:22374: result: yes
+configure:22294: checking for opendir
+configure:22350: gcc -o conftest -g -O2   conftest.c  >&5
+configure:22356: $? = 0
+configure:22374: result: yes
+configure:22294: checking for readdir
+configure:22350: gcc -o conftest -g -O2   conftest.c  >&5
+configure:22356: $? = 0
+configure:22374: result: yes
+configure:22527: creating ./config.status
+
+## ---------------------- ##
+## Running config.status. ##
+## ---------------------- ##
+
+This file was extended by libltdl config.status 1.2, which was
+generated by GNU Autoconf 2.61.  Invocation command line was
+
+  CONFIG_FILES    = 
+  CONFIG_HEADERS  = 
+  CONFIG_LINKS    = 
+  CONFIG_COMMANDS = 
+  $ ./config.status 
+
+on lambda
+
+config.status:671: creating Makefile
+config.status:671: creating config.h
+config.status:936: config.h is unchanged
+config.status:982: executing depfiles commands
+
+## ---------------- ##
+## Cache variables. ##
+## ---------------- ##
+
+ac_cv_build=i686-pc-linux-gnu
+ac_cv_c_compiler_gnu=yes
+ac_cv_c_const=yes
+ac_cv_c_inline=inline
+ac_cv_cxx_compiler_gnu=yes
+ac_cv_env_CCC_set=
+ac_cv_env_CCC_value=
+ac_cv_env_CC_set=
+ac_cv_env_CC_value=
+ac_cv_env_CFLAGS_set=
+ac_cv_env_CFLAGS_value=
+ac_cv_env_CPPFLAGS_set=
+ac_cv_env_CPPFLAGS_value=
+ac_cv_env_CPP_set=
+ac_cv_env_CPP_value=
+ac_cv_env_CXXCPP_set=
+ac_cv_env_CXXCPP_value=
+ac_cv_env_CXXFLAGS_set=
+ac_cv_env_CXXFLAGS_value=
+ac_cv_env_CXX_set=
+ac_cv_env_CXX_value=
+ac_cv_env_F77_set=
+ac_cv_env_F77_value=
+ac_cv_env_FFLAGS_set=
+ac_cv_env_FFLAGS_value=
+ac_cv_env_LDFLAGS_set=
+ac_cv_env_LDFLAGS_value=
+ac_cv_env_LIBS_set=
+ac_cv_env_LIBS_value=
+ac_cv_env_build_alias_set=
+ac_cv_env_build_alias_value=
+ac_cv_env_host_alias_set=
+ac_cv_env_host_alias_value=
+ac_cv_env_target_alias_set=
+ac_cv_env_target_alias_value=
+ac_cv_f77_compiler_gnu=yes
+ac_cv_func_argz_append=yes
+ac_cv_func_argz_create_sep=yes
+ac_cv_func_argz_insert=yes
+ac_cv_func_argz_next=yes
+ac_cv_func_argz_stringify=yes
+ac_cv_func_closedir=yes
+ac_cv_func_dlerror=yes
+ac_cv_func_memcpy=yes
+ac_cv_func_memmove=yes
+ac_cv_func_opendir=yes
+ac_cv_func_readdir=yes
+ac_cv_func_shl_load=no
+ac_cv_func_strchr=yes
+ac_cv_func_strcmp=yes
+ac_cv_func_strrchr=yes
+ac_cv_header_argz_h=yes
+ac_cv_header_assert_h=yes
+ac_cv_header_ctype_h=yes
+ac_cv_header_dirent_dirent_h=yes
+ac_cv_header_dl_h=no
+ac_cv_header_dld_h=no
+ac_cv_header_dlfcn_h=yes
+ac_cv_header_errno_h=yes
+ac_cv_header_inttypes_h=yes
+ac_cv_header_mach_o_dyld_h=no
+ac_cv_header_malloc_h=yes
+ac_cv_header_memory_h=yes
+ac_cv_header_stdc=yes
+ac_cv_header_stdint_h=yes
+ac_cv_header_stdio_h=yes
+ac_cv_header_stdlib_h=yes
+ac_cv_header_string_h=yes
+ac_cv_header_strings_h=yes
+ac_cv_header_sys_dl_h=no
+ac_cv_header_sys_stat_h=yes
+ac_cv_header_sys_types_h=yes
+ac_cv_header_unistd_h=yes
+ac_cv_host=i686-pc-linux-gnu
+ac_cv_lib_dl_dlopen=yes
+ac_cv_lib_dld_shl_load=no
+ac_cv_objext=o
+ac_cv_path_EGREP='/bin/grep -E'
+ac_cv_path_GREP=/bin/grep
+ac_cv_path_install='/usr/bin/install -c'
+ac_cv_path_mkdir=/bin/mkdir
+ac_cv_prog_AWK=gawk
+ac_cv_prog_CPP='gcc -E'
+ac_cv_prog_CXXCPP='g++ -E'
+ac_cv_prog_ac_ct_AR=ar
+ac_cv_prog_ac_ct_CC=gcc
+ac_cv_prog_ac_ct_CXX=g++
+ac_cv_prog_ac_ct_F77=gfortran
+ac_cv_prog_ac_ct_RANLIB=ranlib
+ac_cv_prog_ac_ct_STRIP=strip
+ac_cv_prog_cc_c89=
+ac_cv_prog_cc_g=yes
+ac_cv_prog_cxx_g=yes
+ac_cv_prog_f77_g=yes
+ac_cv_prog_make_make_set=yes
+ac_cv_search_opendir='none required'
+ac_cv_sys_symbol_underscore=no
+ac_cv_type_error_t=yes
+am_cv_CC_dependencies_compiler_type=none
+am_cv_CXX_dependencies_compiler_type=none
+libltdl_cv_lib_dl_dlopen=yes
+libltdl_cv_objdir=.libs
+libltdl_cv_preloaded_symbols=yes
+libltdl_cv_shlibext=.so
+libltdl_cv_shlibpath_var=LD_LIBRARY_PATH
+libltdl_cv_sys_dlopen_deplibs=yes
+libltdl_cv_sys_search_path='/usr/lib /lib /usr/lib/qt-3.3/lib '
+lt_cv_deplibs_check_method=pass_all
+lt_cv_file_magic_cmd='$MAGIC_CMD'
+lt_cv_file_magic_test_file=
+lt_cv_ld_reload_flag=-r
+lt_cv_objdir=.libs
+lt_cv_path_LD=/usr/bin/ld
+lt_cv_path_LDCXX=/usr/bin/ld
+lt_cv_path_NM='/usr/bin/nm -B'
+lt_cv_path_SED=/bin/sed
+lt_cv_prog_compiler_c_o=yes
+lt_cv_prog_compiler_c_o_CXX=yes
+lt_cv_prog_compiler_c_o_F77=yes
+lt_cv_prog_compiler_rtti_exceptions=no
+lt_cv_prog_gnu_ld=yes
+lt_cv_prog_gnu_ldcxx=yes
+lt_cv_sys_global_symbol_pipe='sed -n -e '\''s/^.*[ 	]\([ABCDGIRSTW][ABCDGIRSTW]*\)[ 	][ 	]*\([_A-Za-z][_A-Za-z0-9]*\)$/\1 \2 \2/p'\'''
+lt_cv_sys_global_symbol_to_c_name_address='sed -n -e '\''s/^: \([^ ]*\) $/  {\"\1\", (lt_ptr) 0},/p'\'' -e '\''s/^[BCDEGRST] \([^ ]*\) \([^ ]*\)$/  {"\2", (lt_ptr) \&\2},/p'\'''
+lt_cv_sys_global_symbol_to_cdecl='sed -n -e '\''s/^. .* \(.*\)$/extern int \1;/p'\'''
+lt_cv_sys_max_cmd_len=98304
+lt_lt_cv_prog_compiler_c_o='"yes"'
+lt_lt_cv_prog_compiler_c_o_CXX='"yes"'
+lt_lt_cv_prog_compiler_c_o_F77='"yes"'
+lt_lt_cv_sys_global_symbol_pipe='"sed -n -e '\''s/^.*[ 	]\\([ABCDGIRSTW][ABCDGIRSTW]*\\)[ 	][ 	]*\\([_A-Za-z][_A-Za-z0-9]*\\)\$/\\1 \\2 \\2/p'\''"'
+lt_lt_cv_sys_global_symbol_to_c_name_address='"sed -n -e '\''s/^: \\([^ ]*\\) \$/  {\\\"\\1\\\", (lt_ptr) 0},/p'\'' -e '\''s/^[BCDEGRST] \\([^ ]*\\) \\([^ ]*\\)\$/  {\"\\2\", (lt_ptr) \\&\\2},/p'\''"'
+lt_lt_cv_sys_global_symbol_to_cdecl='"sed -n -e '\''s/^. .* \\(.*\\)\$/extern int \\1;/p'\''"'
+
+## ----------------- ##
+## Output variables. ##
+## ----------------- ##
+
+ACLOCAL='${SHELL} /home/lennart/projects/pulseaudio/libltdl/missing --run aclocal-1.10'
+AMDEPBACKSLASH='\'
+AMDEP_FALSE='#'
+AMDEP_TRUE=''
+AMTAR='${SHELL} /home/lennart/projects/pulseaudio/libltdl/missing --run tar'
+AR='ar'
+AS='as'
+AUTOCONF='${SHELL} /home/lennart/projects/pulseaudio/libltdl/missing --run autoconf'
+AUTOHEADER='${SHELL} /home/lennart/projects/pulseaudio/libltdl/missing --run autoheader'
+AUTOMAKE='${SHELL} /home/lennart/projects/pulseaudio/libltdl/missing --run automake-1.10'
+AWK='gawk'
+CC='gcc'
+CCDEPMODE='depmode=none'
+CFLAGS='-g -O2'
+CONVENIENCE_LTDL_FALSE=''
+CONVENIENCE_LTDL_TRUE='#'
+CPP='gcc -E'
+CPPFLAGS=''
+CXX='g++'
+CXXCPP='g++ -E'
+CXXDEPMODE='depmode=none'
+CXXFLAGS='-g -O2'
+CYGPATH_W='echo'
+DEFS='-DHAVE_CONFIG_H'
+DEPDIR='.deps'
+DLLTOOL='dlltool'
+ECHO='echo'
+ECHO_C=''
+ECHO_N='-n'
+ECHO_T=''
+EGREP='/bin/grep -E'
+EXEEXT=''
+F77='gfortran'
+FFLAGS='-g -O2'
+GREP='/bin/grep'
+INSTALL_DATA='${INSTALL} -m 644'
+INSTALL_LTDL_FALSE='#'
+INSTALL_LTDL_TRUE=''
+INSTALL_PROGRAM='${INSTALL}'
+INSTALL_SCRIPT='${INSTALL}'
+INSTALL_STRIP_PROGRAM='$(install_sh) -c -s'
+LDFLAGS=''
+LIBADD_DL='-ldl'
+LIBOBJS=''
+LIBS=''
+LIBTOOL='$(SHELL) $(top_builddir)/libtool'
+LIBTOOL_DEPS='./ltmain.sh'
+LN_S='ln -s'
+LTLIBOBJS=''
+MAKEINFO='${SHELL} /home/lennart/projects/pulseaudio/libltdl/missing --run makeinfo'
+OBJDUMP='objdump'
+OBJEXT='o'
+PACKAGE='libltdl'
+PACKAGE_BUGREPORT='bug-libtool at gnu.org'
+PACKAGE_NAME='libltdl'
+PACKAGE_STRING='libltdl 1.2'
+PACKAGE_TARNAME='libltdl'
+PACKAGE_VERSION='1.2'
+PATH_SEPARATOR=':'
+RANLIB='ranlib'
+SED='/bin/sed'
+SET_MAKE=''
+SHELL='/bin/sh'
+STRIP='strip'
+VERSION='1.2'
+ac_ct_CC='gcc'
+ac_ct_CXX='g++'
+ac_ct_F77='gfortran'
+am__fastdepCC_FALSE=''
+am__fastdepCC_TRUE='#'
+am__fastdepCXX_FALSE=''
+am__fastdepCXX_TRUE='#'
+am__include='include'
+am__isrc=''
+am__leading_dot='.'
+am__quote=''
+am__tar='${AMTAR} chof - "$$tardir"'
+am__untar='${AMTAR} xf -'
+bindir='${exec_prefix}/bin'
+build='i686-pc-linux-gnu'
+build_alias=''
+build_cpu='i686'
+build_os='linux-gnu'
+build_vendor='pc'
+datadir='${datarootdir}'
+datarootdir='${prefix}/share'
+docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
+dvidir='${docdir}'
+exec_prefix='${prefix}'
+host='i686-pc-linux-gnu'
+host_alias=''
+host_cpu='i686'
+host_os='linux-gnu'
+host_vendor='pc'
+htmldir='${docdir}'
+includedir='${prefix}/include'
+infodir='${datarootdir}/info'
+install_sh='$(SHELL) /home/lennart/projects/pulseaudio/libltdl/install-sh'
+libdir='${exec_prefix}/lib'
+libexecdir='${exec_prefix}/libexec'
+localedir='${datarootdir}/locale'
+localstatedir='${prefix}/var'
+mandir='${datarootdir}/man'
+mkdir_p='/bin/mkdir -p'
+oldincludedir='/usr/include'
+pdfdir='${docdir}'
+prefix='/usr/local'
+program_transform_name='s,x,x,'
+psdir='${docdir}'
+sbindir='${exec_prefix}/sbin'
+sharedstatedir='${prefix}/com'
+sysconfdir='${prefix}/etc'
+target_alias=''
+
+## ----------- ##
+## confdefs.h. ##
+## ----------- ##
+
+#define PACKAGE_NAME "libltdl"
+#define PACKAGE_TARNAME "libltdl"
+#define PACKAGE_VERSION "1.2"
+#define PACKAGE_STRING "libltdl 1.2"
+#define PACKAGE_BUGREPORT "bug-libtool at gnu.org"
+#define STDC_HEADERS 1
+#define HAVE_SYS_TYPES_H 1
+#define HAVE_SYS_STAT_H 1
+#define HAVE_STDLIB_H 1
+#define HAVE_STRING_H 1
+#define HAVE_MEMORY_H 1
+#define HAVE_STRINGS_H 1
+#define HAVE_INTTYPES_H 1
+#define HAVE_STDINT_H 1
+#define HAVE_UNISTD_H 1
+#define HAVE_DLFCN_H 1
+#define HAVE_DIRENT_H 1
+#define LTDL_SHLIB_EXT ".so"
+#define LTDL_SHLIBPATH_VAR "LD_LIBRARY_PATH"
+#define LTDL_SYSSEARCHPATH "/usr/lib:/lib:/usr/lib/qt-3.3/lib"
+#define LTDL_OBJDIR ".libs/"
+#define HAVE_PRELOADED_SYMBOLS 1
+#define HAVE_LIBDL 1
+#define HAVE_DLERROR 1
+#define HAVE_ARGZ_H 1
+#define HAVE_ERROR_T 1
+#define HAVE_ARGZ_APPEND 1
+#define HAVE_ARGZ_CREATE_SEP 1
+#define HAVE_ARGZ_INSERT 1
+#define HAVE_ARGZ_NEXT 1
+#define HAVE_ARGZ_STRINGIFY 1
+#define HAVE_ASSERT_H 1
+#define HAVE_CTYPE_H 1
+#define HAVE_ERRNO_H 1
+#define HAVE_MALLOC_H 1
+#define HAVE_MEMORY_H 1
+#define HAVE_STDLIB_H 1
+#define HAVE_STDIO_H 1
+#define HAVE_UNISTD_H 1
+#define HAVE_STRING_H 1
+#define HAVE_STRCHR 1
+#define HAVE_STRRCHR 1
+#define HAVE_MEMCPY 1
+#define HAVE_MEMMOVE 1
+#define HAVE_STRCMP 1
+#define HAVE_CLOSEDIR 1
+#define HAVE_OPENDIR 1
+#define HAVE_READDIR 1
+
+configure: exit 0
diff --git a/libltdl/config.status b/libltdl/config.status
new file mode 100755
index 0000000..c7316a4
--- /dev/null
+++ b/libltdl/config.status
@@ -0,0 +1,1118 @@
+#! /bin/sh
+# Generated by configure.
+# 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-/bin/sh}
+## --------------------- ##
+## 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`
+"
+
+# Files that config.status was made for.
+config_files=" Makefile"
+config_headers=" config.h:config-h.in"
+config_commands=" depfiles"
+
+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 at gnu.org>."
+
+ac_cs_version="\
+libltdl config.status 1.2
+configured by ./configure, generated by GNU Autoconf 2.61,
+  with options \"\"
+
+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='/home/lennart/projects/pulseaudio/libltdl'
+srcdir='.'
+INSTALL='/usr/bin/install -c'
+MKDIR_P='/bin/mkdir -p'
+# 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
+
+if $ac_cs_recheck; then
+  echo "running CONFIG_SHELL=/bin/sh /bin/sh ./configure " $ac_configure_extra_args " --no-create --no-recursion" >&6
+  CONFIG_SHELL=/bin/sh
+  export CONFIG_SHELL
+  exec /bin/sh "./configure" $ac_configure_extra_args --no-create --no-recursion
+fi
+
+exec 5>>config.log
+{
+  echo
+  sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## Running $as_me. ##
+_ASBOX
+  echo "$ac_log"
+} >&5
+
+#
+# INIT-COMMANDS
+#
+AMDEP_TRUE="" ac_aux_dir="."
+
+
+# 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
+
+cat >"$tmp/subs-1.sed" <<\CEOF
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+s, at SHELL@,|#_!!_#|/bin/sh,g
+s, at PATH_SEPARATOR@,|#_!!_#|:,g
+s, at PACKAGE_NAME@,|#_!!_#|libltdl,g
+s, at PACKAGE_TARNAME@,|#_!!_#|libltdl,g
+s, at PACKAGE_VERSION@,|#_!!_#|1.2,g
+s, at PACKAGE_STRING@,|#_!!_#|libltdl 1.2,g
+s, at PACKAGE_BUGREPORT@,|#_!!_#|bug-libtool@|#_!!_#|gnu.org,g
+s, at exec_prefix@,|#_!!_#|${prefix},g
+s, at prefix@,|#_!!_#|/usr/local,g
+s, at program_transform_name@,|#_!!_#|s\,x\,x\,,g
+s, at bindir@,|#_!!_#|${exec_prefix}/bin,g
+s, at sbindir@,|#_!!_#|${exec_prefix}/sbin,g
+s, at libexecdir@,|#_!!_#|${exec_prefix}/libexec,g
+s, at datarootdir@,|#_!!_#|${prefix}/share,g
+s, at datadir@,|#_!!_#|${datarootdir},g
+s, at sysconfdir@,|#_!!_#|${prefix}/etc,g
+s, at sharedstatedir@,|#_!!_#|${prefix}/com,g
+s, at localstatedir@,|#_!!_#|${prefix}/var,g
+s, at includedir@,|#_!!_#|${prefix}/include,g
+s, at oldincludedir@,|#_!!_#|/usr/include,g
+s, at docdir@,|#_!!_#|${datarootdir}/doc/${PACKAGE_TARNAME},g
+s, at infodir@,|#_!!_#|${datarootdir}/info,g
+s, at htmldir@,|#_!!_#|${docdir},g
+s, at dvidir@,|#_!!_#|${docdir},g
+s, at pdfdir@,|#_!!_#|${docdir},g
+s, at psdir@,|#_!!_#|${docdir},g
+s, at libdir@,|#_!!_#|${exec_prefix}/lib,g
+s, at localedir@,|#_!!_#|${datarootdir}/locale,g
+s, at mandir@,|#_!!_#|${datarootdir}/man,g
+s, at DEFS@,|#_!!_#|-DHAVE_CONFIG_H,g
+s, at ECHO_C@,|#_!!_#|,g
+s, at ECHO_N@,|#_!!_#|-n,g
+s, at ECHO_T@,|#_!!_#|,g
+s, at LIBS@,|#_!!_#|,g
+s, at build_alias@,|#_!!_#|,g
+s, at host_alias@,|#_!!_#|,g
+s, at target_alias@,|#_!!_#|,g
+s, at INSTALL_PROGRAM@,|#_!!_#|${INSTALL},g
+s, at INSTALL_SCRIPT@,|#_!!_#|${INSTALL},g
+s, at INSTALL_DATA@,|#_!!_#|${INSTALL} -m 644,g
+s, at am__isrc@,|#_!!_#|,g
+s, at CYGPATH_W@,|#_!!_#|echo,g
+s, at PACKAGE@,|#_!!_#|libltdl,g
+s, at VERSION@,|#_!!_#|1.2,g
+s, at ACLOCAL@,|#_!!_#|${SHELL} /home/lennart/projects/pulseaudio/libltdl/missing --run aclocal-1.10,g
+s, at AUTOCONF@,|#_!!_#|${SHELL} /home/lennart/projects/pulseaudio/libltdl/missing --run autoconf,g
+s, at AUTOMAKE@,|#_!!_#|${SHELL} /home/lennart/projects/pulseaudio/libltdl/missing --run automake-1.10,g
+s, at AUTOHEADER@,|#_!!_#|${SHELL} /home/lennart/projects/pulseaudio/libltdl/missing --run autoheader,g
+s, at MAKEINFO@,|#_!!_#|${SHELL} /home/lennart/projects/pulseaudio/libltdl/missing --run makeinfo,g
+s, at install_sh@,|#_!!_#|$(SHELL) /home/lennart/projects/pulseaudio/libltdl/install-sh,g
+s, at STRIP@,|#_!!_#|strip,g
+s, at INSTALL_STRIP_PROGRAM@,|#_!!_#|$(install_sh) -c -s,g
+s, at mkdir_p@,|#_!!_#|/bin/mkdir -p,g
+s, at AWK@,|#_!!_#|gawk,g
+s, at SET_MAKE@,|#_!!_#|,g
+s, at am__leading_dot@,|#_!!_#|.,g
+s, at AMTAR@,|#_!!_#|${SHELL} /home/lennart/projects/pulseaudio/libltdl/missing --run tar,g
+s, at am__tar@,|#_!!_#|${AMTAR} chof - "$$tardir",g
+s, at am__untar@,|#_!!_#|${AMTAR} xf -,g
+s, at CC@,|#_!!_#|gcc,g
+s, at CFLAGS@,|#_!!_#|-g -O2,g
+s, at LDFLAGS@,|#_!!_#|,g
+s, at CPPFLAGS@,|#_!!_#|,g
+s, at ac_ct_CC@,|#_!!_#|gcc,g
+s, at EXEEXT@,|#_!!_#|,g
+s, at OBJEXT@,|#_!!_#|o,g
+s, at DEPDIR@,|#_!!_#|.deps,g
+s, at am__include@,|#_!!_#|include,g
+s, at am__quote@,|#_!!_#|,g
+s, at AMDEP_TRUE@,|#_!!_#|,g
+s, at AMDEP_FALSE@,|#_!!_#|#,g
+s, at AMDEPBACKSLASH@,|#_!!_#|\\,g
+s, at CCDEPMODE@,|#_!!_#|depmode=none,g
+s, at am__fastdepCC_TRUE@,|#_!!_#|#,g
+s, at am__fastdepCC_FALSE@,|#_!!_#|,g
+s, at build@,|#_!!_#|i686-pc-linux-gnu,g
+s, at build_cpu@,|#_!!_#|i686,g
+s, at build_vendor@,|#_!!_#|pc,g
+s, at build_os@,|#_!!_#|linux-gnu,g
+s, at host@,|#_!!_#|i686-pc-linux-gnu,g
+s, at host_cpu@,|#_!!_#|i686,g
+s, at host_vendor@,|#_!!_#|pc,g
+s, at host_os@,|#_!!_#|linux-gnu,g
+s, at SED@,|#_!!_#|/bin/sed,g
+s, at GREP@,|#_!!_#|/bin/grep,g
+s, at EGREP@,|#_!!_#|/bin/grep -E,g
+s, at LN_S@,|#_!!_#|ln -s,g
+s, at ECHO@,|#_!!_#|echo,g
+s, at AR@,|#_!!_#|ar,g
+s, at RANLIB@,|#_!!_#|ranlib,g
+s, at DLLTOOL@,|#_!!_#|dlltool,g
+s, at AS@,|#_!!_#|as,g
+s, at OBJDUMP@,|#_!!_#|objdump,g
+s, at CPP@,|#_!!_#|gcc -E,g
+s, at CXX@,|#_!!_#|g++,g
+s, at CXXFLAGS@,|#_!!_#|-g -O2,g
+s, at ac_ct_CXX@,|#_!!_#|g++,g
+CEOF
+cat >"$tmp/subs-2.sed" <<\CEOF
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b end
+s, at CXXDEPMODE@,|#_!!_#|depmode=none,g
+s, at am__fastdepCXX_TRUE@,|#_!!_#|#,g
+s, at am__fastdepCXX_FALSE@,|#_!!_#|,g
+s, at CXXCPP@,|#_!!_#|g++ -E,g
+s, at F77@,|#_!!_#|gfortran,g
+s, at FFLAGS@,|#_!!_#|-g -O2,g
+s, at ac_ct_F77@,|#_!!_#|gfortran,g
+s, at LIBTOOL@,|#_!!_#|$(SHELL) $(top_builddir)/libtool,g
+s, at LIBTOOL_DEPS@,|#_!!_#|./ltmain.sh,g
+s, at INSTALL_LTDL_TRUE@,|#_!!_#|,g
+s, at INSTALL_LTDL_FALSE@,|#_!!_#|#,g
+s, at CONVENIENCE_LTDL_TRUE@,|#_!!_#|#,g
+s, at CONVENIENCE_LTDL_FALSE@,|#_!!_#|,g
+s, at LIBADD_DL@,|#_!!_#|-ldl,g
+s, at LIBOBJS@,|#_!!_#|,g
+s, at LTLIBOBJS@,|#_!!_#|,g
+:end
+s/|#_!!_#|//g
+CEOF
+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
+# 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;}
+  ac_datarootdir_hack='
+  s&@datadir@&${datarootdir}&g
+  s&@docdir@&${datarootdir}/doc/${PACKAGE_TARNAME}&g
+  s&@infodir@&${datarootdir}/info&g
+  s&@localedir@&${datarootdir}/locale&g
+  s&@mandir@&${datarootdir}/man&g
+    s&\${datarootdir}&${prefix}/share&g' ;;
+esac
+  sed "/^[	 ]*VPATH[	 ]*=/{
+s/:*\$(srcdir):*/:/
+s/:*\${srcdir}:*/:/
+s/:*@srcdir@:*/:/
+s/^\([^=]*=[	 ]*\):*/\1/
+s/:*$//
+s/^[^=]*=[	 ]*$//
+}
+
+: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
+  #
+    # First, check the format of the line:
+    cat >"$tmp/defines.sed" <<\CEOF
+/^[	 ]*#[	 ]*undef[	 ][	 ]*[_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ][_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789]*[	 ]*$/b def
+/^[	 ]*#[	 ]*define[	 ][	 ]*[_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ][_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789]*[(	 ]/b def
+b
+:def
+s/$/ /
+s,^\([	 #]*\)[^	 ]*\([	 ]*PACKAGE_NAME\)[	 (].*,\1define\2 "libltdl" ,
+s,^\([	 #]*\)[^	 ]*\([	 ]*PACKAGE_TARNAME\)[	 (].*,\1define\2 "libltdl" ,
+s,^\([	 #]*\)[^	 ]*\([	 ]*PACKAGE_VERSION\)[	 (].*,\1define\2 "1.2" ,
+s,^\([	 #]*\)[^	 ]*\([	 ]*PACKAGE_STRING\)[	 (].*,\1define\2 "libltdl 1.2" ,
+s,^\([	 #]*\)[^	 ]*\([	 ]*PACKAGE_BUGREPORT\)[	 (].*,\1define\2 "bug-libtool at gnu.org" ,
+s,^\([	 #]*\)[^	 ]*\([	 ]*STDC_HEADERS\)[	 (].*,\1define\2 1 ,
+s,^\([	 #]*\)[^	 ]*\([	 ]*HAVE_SYS_TYPES_H\)[	 (].*,\1define\2 1 ,
+s,^\([	 #]*\)[^	 ]*\([	 ]*HAVE_SYS_STAT_H\)[	 (].*,\1define\2 1 ,
+s,^\([	 #]*\)[^	 ]*\([	 ]*HAVE_STDLIB_H\)[	 (].*,\1define\2 1 ,
+s,^\([	 #]*\)[^	 ]*\([	 ]*HAVE_STRING_H\)[	 (].*,\1define\2 1 ,
+s,^\([	 #]*\)[^	 ]*\([	 ]*HAVE_MEMORY_H\)[	 (].*,\1define\2 1 ,
+s,^\([	 #]*\)[^	 ]*\([	 ]*HAVE_STRINGS_H\)[	 (].*,\1define\2 1 ,
+s,^\([	 #]*\)[^	 ]*\([	 ]*HAVE_INTTYPES_H\)[	 (].*,\1define\2 1 ,
+s,^\([	 #]*\)[^	 ]*\([	 ]*HAVE_STDINT_H\)[	 (].*,\1define\2 1 ,
+s,^\([	 #]*\)[^	 ]*\([	 ]*HAVE_UNISTD_H\)[	 (].*,\1define\2 1 ,
+s,^\([	 #]*\)[^	 ]*\([	 ]*HAVE_DLFCN_H\)[	 (].*,\1define\2 1 ,
+s,^\([	 #]*\)[^	 ]*\([	 ]*HAVE_DIRENT_H\)[	 (].*,\1define\2 1 ,
+s,^\([	 #]*\)[^	 ]*\([	 ]*LTDL_SHLIB_EXT\)[	 (].*,\1define\2 ".so" ,
+s,^\([	 #]*\)[^	 ]*\([	 ]*LTDL_SHLIBPATH_VAR\)[	 (].*,\1define\2 "LD_LIBRARY_PATH" ,
+s,^\([	 #]*\)[^	 ]*\([	 ]*LTDL_SYSSEARCHPATH\)[	 (].*,\1define\2 "/usr/lib:/lib:/usr/lib/qt-3.3/lib" ,
+s,^\([	 #]*\)[^	 ]*\([	 ]*LTDL_OBJDIR\)[	 (].*,\1define\2 ".libs/" ,
+s,^\([	 #]*\)[^	 ]*\([	 ]*HAVE_PRELOADED_SYMBOLS\)[	 (].*,\1define\2 1 ,
+s,^\([	 #]*\)[^	 ]*\([	 ]*HAVE_LIBDL\)[	 (].*,\1define\2 1 ,
+s,^\([	 #]*\)[^	 ]*\([	 ]*HAVE_DLERROR\)[	 (].*,\1define\2 1 ,
+s,^\([	 #]*\)[^	 ]*\([	 ]*HAVE_ARGZ_H\)[	 (].*,\1define\2 1 ,
+s,^\([	 #]*\)[^	 ]*\([	 ]*HAVE_ERROR_T\)[	 (].*,\1define\2 1 ,
+s,^\([	 #]*\)[^	 ]*\([	 ]*HAVE_ARGZ_APPEND\)[	 (].*,\1define\2 1 ,
+s,^\([	 #]*\)[^	 ]*\([	 ]*HAVE_ARGZ_CREATE_SEP\)[	 (].*,\1define\2 1 ,
+s,^\([	 #]*\)[^	 ]*\([	 ]*HAVE_ARGZ_INSERT\)[	 (].*,\1define\2 1 ,
+s,^\([	 #]*\)[^	 ]*\([	 ]*HAVE_ARGZ_NEXT\)[	 (].*,\1define\2 1 ,
+s,^\([	 #]*\)[^	 ]*\([	 ]*HAVE_ARGZ_STRINGIFY\)[	 (].*,\1define\2 1 ,
+s,^\([	 #]*\)[^	 ]*\([	 ]*HAVE_ASSERT_H\)[	 (].*,\1define\2 1 ,
+s,^\([	 #]*\)[^	 ]*\([	 ]*HAVE_CTYPE_H\)[	 (].*,\1define\2 1 ,
+s,^\([	 #]*\)[^	 ]*\([	 ]*HAVE_ERRNO_H\)[	 (].*,\1define\2 1 ,
+s,^\([	 #]*\)[^	 ]*\([	 ]*HAVE_MALLOC_H\)[	 (].*,\1define\2 1 ,
+s,^\([	 #]*\)[^	 ]*\([	 ]*HAVE_MEMORY_H\)[	 (].*,\1define\2 1 ,
+s,^\([	 #]*\)[^	 ]*\([	 ]*HAVE_STDLIB_H\)[	 (].*,\1define\2 1 ,
+s,^\([	 #]*\)[^	 ]*\([	 ]*HAVE_STDIO_H\)[	 (].*,\1define\2 1 ,
+s,^\([	 #]*\)[^	 ]*\([	 ]*HAVE_UNISTD_H\)[	 (].*,\1define\2 1 ,
+s,^\([	 #]*\)[^	 ]*\([	 ]*HAVE_STRING_H\)[	 (].*,\1define\2 1 ,
+s,^\([	 #]*\)[^	 ]*\([	 ]*HAVE_STRCHR\)[	 (].*,\1define\2 1 ,
+s,^\([	 #]*\)[^	 ]*\([	 ]*HAVE_STRRCHR\)[	 (].*,\1define\2 1 ,
+s,^\([	 #]*\)[^	 ]*\([	 ]*HAVE_MEMCPY\)[	 (].*,\1define\2 1 ,
+s,^\([	 #]*\)[^	 ]*\([	 ]*HAVE_MEMMOVE\)[	 (].*,\1define\2 1 ,
+s,^\([	 #]*\)[^	 ]*\([	 ]*HAVE_STRCMP\)[	 (].*,\1define\2 1 ,
+s,^\([	 #]*\)[^	 ]*\([	 ]*HAVE_CLOSEDIR\)[	 (].*,\1define\2 1 ,
+s,^\([	 #]*\)[^	 ]*\([	 ]*HAVE_OPENDIR\)[	 (].*,\1define\2 1 ,
+s,^\([	 #]*\)[^	 ]*\([	 ]*HAVE_READDIR\)[	 (].*,\1define\2 1 ,
+s/ $//
+CEOF
+    sed -f "$tmp/defines.sed" $ac_file_inputs >"$tmp/out1"
+    # First, check the format of the line:
+    cat >"$tmp/defines.sed" <<\CEOF
+/^[	 ]*#[	 ]*undef[	 ][	 ]*[_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ][_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789]*[	 ]*$/b def
+/^[	 ]*#[	 ]*define[	 ][	 ]*[_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ][_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789]*[(	 ]/b def
+b
+:def
+s,^[	 #]*u.*,/* & */,
+CEOF
+    sed -f "$tmp/defines.sed" "$tmp/out1" >"$tmp/out2"
+ac_result="$tmp/out2"
+  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; }
diff --git a/libltdl/config.sub b/libltdl/config.sub
new file mode 100755
index 0000000..c060f44
--- /dev/null
+++ b/libltdl/config.sub
@@ -0,0 +1,1626 @@
+#! /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-04-29'
+
+# 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 at 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 at 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
+		;;
+	mingw32ce)
+		basic_machine=arm-unknown
+		os=-mingw32ce
+		;;
+	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
index 0000000..62dface
--- /dev/null
+++ b/libltdl/configure
@@ -0,0 +1,23808 @@
+#! /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 at 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 at 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 at 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 at 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 at 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 at 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 at 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 at 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 at 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 at 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*)
+  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*)
+      libsuff=64
+      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 at 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 at 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 at 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 at 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 at 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 at 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 at 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 at 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 at 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 at 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 at 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 at 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 at 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 at 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 at 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 at 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 at 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 at 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 at 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:7568: $lt_compile\"" >&5)
+   (eval "$lt_compile" 2>conftest.err)
+   ac_status=$?
+   cat conftest.err >&5
+   echo "$as_me:7572: \$? = $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:7858: $lt_compile\"" >&5)
+   (eval "$lt_compile" 2>conftest.err)
+   ac_status=$?
+   cat conftest.err >&5
+   echo "$as_me:7862: \$? = $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:7962: $lt_compile\"" >&5)
+   (eval "$lt_compile" 2>out/conftest.err)
+   ac_status=$?
+   cat out/conftest.err >&5
+   echo "$as_me:7966: \$? = $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 at 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 at 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
+      else
+	ld_shlibs=no
+      fi
+      ;;
+
+    netbsd*)
+      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*)
+      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
+  sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}"
+  sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}"
+
+  # 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="$sys_lib_dlsearch_path_spec $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'
+  ;;
+
+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 10313 "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 10413 "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 at 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 at 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*)
+    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*)
+	;;
+      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:12837: $lt_compile\"" >&5)
+   (eval "$lt_compile" 2>conftest.err)
+   ac_status=$?
+   cat conftest.err >&5
+   echo "$as_me:12841: \$? = $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:12941: $lt_compile\"" >&5)
+   (eval "$lt_compile" 2>out/conftest.err)
+   ac_status=$?
+   cat out/conftest.err >&5
+   echo "$as_me:12945: \$? = $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'
+  ;;
+  *)
+    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
+  sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}"
+  sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}"
+
+  # 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="$sys_lib_dlsearch_path_spec $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'
+  ;;
+
+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:14505: $lt_compile\"" >&5)
+   (eval "$lt_compile" 2>conftest.err)
+   ac_status=$?
+   cat conftest.err >&5
+   echo "$as_me:14509: \$? = $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:14609: $lt_compile\"" >&5)
+   (eval "$lt_compile" 2>out/conftest.err)
+   ac_status=$?
+   cat out/conftest.err >&5
+   echo "$as_me:14613: \$? = $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 at 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 at 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
+      else
+	ld_shlibs_F77=no
+      fi
+      ;;
+
+    netbsd*)
+      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*)
+      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
+  sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}"
+  sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}"
+
+  # 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="$sys_lib_dlsearch_path_spec $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'
+  ;;
+
+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:16802: $lt_compile\"" >&5)
+   (eval "$lt_compile" 2>conftest.err)
+   ac_status=$?
+   cat conftest.err >&5
+   echo "$as_me:16806: \$? = $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:17092: $lt_compile\"" >&5)
+   (eval "$lt_compile" 2>conftest.err)
+   ac_status=$?
+   cat conftest.err >&5
+   echo "$as_me:17096: \$? = $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:17196: $lt_compile\"" >&5)
+   (eval "$lt_compile" 2>out/conftest.err)
+   ac_status=$?
+   cat out/conftest.err >&5
+   echo "$as_me:17200: \$? = $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 at 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 at 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
+      else
+	ld_shlibs_GCJ=no
+      fi
+      ;;
+
+    netbsd*)
+      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*)
+      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
+  sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}"
+  sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}"
+
+  # 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="$sys_lib_dlsearch_path_spec $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'
+  ;;
+
+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 20932 "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*)
+    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 at 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 at 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 at 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 at 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 at 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
index 0000000..1446efb
--- /dev/null
+++ b/libltdl/configure.ac
@@ -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 at 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
index 0000000..a5897de
--- /dev/null
+++ b/libltdl/install-sh
@@ -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/libtool b/libltdl/libtool
new file mode 100755
index 0000000..2413813
--- /dev/null
+++ b/libltdl/libtool
@@ -0,0 +1,7895 @@
+#! /bin/sh
+
+# libtoolT - Provide generalized library-building support services.
+# Generated automatically by  (GNU libltdl 1.2)
+# 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 at 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="/bin/sed"
+
+# Sed that helps us avoid accidentally triggering echo(1) options like -n.
+Xsed="/bin/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=" CXX F77"
+
+# ### BEGIN LIBTOOL CONFIG
+
+# Libtool was configured on host lambda:
+
+# Shell to use when invoking shell scripts.
+SHELL="/bin/sh"
+
+# Whether or not to build shared libraries.
+build_libtool_libs=yes
+
+# Whether or not to build static libraries.
+build_old_libs=yes
+
+# Whether or not to add -lc for building shared libraries.
+build_libtool_need_lc=no
+
+# Whether or not to disallow shared libs when runtime libs are static
+allow_libtool_libs_with_static_runtimes=no
+
+# Whether or not to optimize for fast installation.
+fast_install=yes
+
+# The host system.
+host_alias=
+host=i686-pc-linux-gnu
+host_os=linux-gnu
+
+# The build system.
+build_alias=
+build=i686-pc-linux-gnu
+build_os=linux-gnu
+
+# An echo program that does not interpret backslashes.
+echo="echo"
+
+# The archiver.
+AR="ar"
+AR_FLAGS="cru"
+
+# A C compiler.
+LTCC="gcc"
+
+# LTCC compiler flags.
+LTCFLAGS="-g -O2"
+
+# A language-specific compiler.
+CC="gcc"
+
+# Is the compiler the GNU C compiler?
+with_gcc=yes
+
+# An ERE matcher.
+EGREP="/bin/grep -E"
+
+# The linker used to build libraries.
+LD="/usr/bin/ld"
+
+# Whether we need hard or soft links.
+LN_S="ln -s"
+
+# A BSD-compatible nm program.
+NM="/usr/bin/nm -B"
+
+# A symbol stripping program
+STRIP="strip"
+
+# Used to examine libraries when file_magic_cmd begins "file"
+MAGIC_CMD=file
+
+# 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=.libs
+
+# How to create reloadable object files.
+reload_flag=" -r"
+reload_cmds="\$LD\$reload_flag -o \$output\$reload_objs"
+
+# How to pass a linker flag through the compiler.
+wl="-Wl,"
+
+# Object file suffix (normally "o").
+objext="o"
+
+# Old archive suffix (normally "a").
+libext="a"
+
+# Shared library suffix (normally ".so").
+shrext_cmds='.so'
+
+# Executable file suffix (normally "").
+exeext=""
+
+# Additional compiler flags for building library objects.
+pic_flag=" -fPIC -DPIC"
+pic_mode=default
+
+# What is the maximum length of a command?
+max_cmd_len=98304
+
+# Does compiler simultaneously support -c and -o options?
+compiler_c_o="yes"
+
+# Must we lock files when doing compilation?
+need_locks="no"
+
+# Do we need the lib prefix for modules?
+need_lib_prefix=no
+
+# Do we need a version for libraries?
+need_version=no
+
+# Whether dlopen is supported.
+dlopen_support=unknown
+
+# Whether dlopen of programs is supported.
+dlopen_self=unknown
+
+# Whether dlopen of statically linked programs is supported.
+dlopen_self_static=unknown
+
+# Compiler flag to prevent dynamic linking.
+link_static_flag="-static"
+
+# Compiler flag to turn off builtin functions.
+no_builtin_flag=" -fno-builtin"
+
+# Compiler flag to allow reflexive dlopens.
+export_dynamic_flag_spec="\${wl}--export-dynamic"
+
+# Compiler flag to generate shared objects directly from archives.
+whole_archive_flag_spec="\${wl}--whole-archive\$convenience \${wl}--no-whole-archive"
+
+# Compiler flag to generate thread-safe objects.
+thread_safe_flag_spec=""
+
+# Library versioning type.
+version_type=linux
+
+# Format of library name prefix.
+libname_spec="lib\$name"
+
+# 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="\${libname}\${release}\${shared_ext}\$versuffix \${libname}\${release}\${shared_ext}\$major \$libname\${shared_ext}"
+
+# The coded name of the library, if different from the real name.
+soname_spec="\${libname}\${release}\${shared_ext}\$major"
+
+# Commands used to build and install an old-style archive.
+RANLIB="ranlib"
+old_archive_cmds="\$AR \$AR_FLAGS \$oldlib\$oldobjs~\$RANLIB \$oldlib"
+old_postinstall_cmds="chmod 644 \$oldlib~\$RANLIB \$oldlib"
+old_postuninstall_cmds=""
+
+# Create an old-style archive from a shared archive.
+old_archive_from_new_cmds=""
+
+# Create a temporary old-style archive to link instead of a shared archive.
+old_archive_from_expsyms_cmds=""
+
+# Commands used to build and install a shared archive.
+archive_cmds="\$CC -shared \$libobjs \$deplibs \$compiler_flags \${wl}-soname \$wl\$soname -o \$lib"
+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 -shared \$libobjs \$deplibs \$compiler_flags \${wl}-soname \$wl\$soname \${wl}-version-script \${wl}\$output_objdir/\$libname.ver -o \$lib"
+postinstall_cmds=""
+postuninstall_cmds=""
+
+# Commands used to build a loadable module (assumed same as above if empty)
+module_cmds=""
+module_expsym_cmds=""
+
+# Commands to strip libraries.
+old_striplib="strip --strip-debug"
+striplib="strip --strip-unneeded"
+
+# Dependencies to place before the objects being linked to create a
+# shared library.
+predep_objects=""
+
+# Dependencies to place after the objects being linked to create a
+# shared library.
+postdep_objects=""
+
+# Dependencies to place before the objects being linked to create a
+# shared library.
+predeps=""
+
+# Dependencies to place after the objects being linked to create a
+# shared library.
+postdeps=""
+
+# The library search path used internally by the compiler when linking
+# a shared library.
+compiler_lib_search_path=""
+
+# Method to check whether dependent libraries are shared objects.
+deplibs_check_method="pass_all"
+
+# Command to use when deplibs_check_method == file_magic.
+file_magic_cmd="\$MAGIC_CMD"
+
+# Flag that allows shared libraries with undefined symbols to be built.
+allow_undefined_flag=""
+
+# Flag that forces no undefined symbols.
+no_undefined_flag=""
+
+# Commands used to finish a libtool library installation in a directory.
+finish_cmds="PATH=\\\"\\\$PATH:/sbin\\\" ldconfig -n \$libdir"
+
+# Same as above, but a single script fragment to be evaled but not shown.
+finish_eval=""
+
+# Take the output of nm and produce a listing of raw symbols and C names.
+global_symbol_pipe="sed -n -e 's/^.*[ 	]\\([ABCDGIRSTW][ABCDGIRSTW]*\\)[ 	][ 	]*\\([_A-Za-z][_A-Za-z0-9]*\\)\$/\\1 \\2 \\2/p'"
+
+# Transform the output of nm in a proper C declaration
+global_symbol_to_cdecl="sed -n -e 's/^. .* \\(.*\\)\$/extern int \\1;/p'"
+
+# Transform the output of nm in a C name address pair
+global_symbol_to_c_name_address="sed -n -e 's/^: \\([^ ]*\\) \$/  {\\\"\\1\\\", (lt_ptr) 0},/p' -e 's/^[BCDEGRST] \\([^ ]*\\) \\([^ ]*\\)\$/  {\"\\2\", (lt_ptr) \\&\\2},/p'"
+
+# This is the shared library runtime path variable.
+runpath_var=LD_RUN_PATH
+
+# This is the shared library path variable.
+shlibpath_var=LD_LIBRARY_PATH
+
+# Is shlibpath searched before the hard-coded library search path?
+shlibpath_overrides_runpath=no
+
+# How to hardcode a shared library path into an executable.
+hardcode_action=immediate
+
+# Whether we should hardcode library paths into libraries.
+hardcode_into_libs=yes
+
+# Flag to hardcode $libdir into a binary during linking.
+# This must work even if $libdir does not exist.
+hardcode_libdir_flag_spec="\${wl}--rpath \${wl}\$libdir"
+
+# 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=""
+
+# Whether we need a single -rpath flag with a separated argument.
+hardcode_libdir_separator=""
+
+# Set to yes if using DIR/libNAME during linking hardcodes DIR into the
+# resulting binary.
+hardcode_direct=no
+
+# Set to yes if using the -LDIR flag during linking hardcodes DIR into the
+# resulting binary.
+hardcode_minus_L=no
+
+# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into
+# the resulting binary.
+hardcode_shlibpath_var=unsupported
+
+# 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=no
+
+# Variables whose values should be saved in libtool wrapper scripts and
+# restored at relink time.
+variables_saved_for_relink="PATH LD_LIBRARY_PATH LD_RUN_PATH GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH"
+
+# Whether libtool must link a program against all its dependency libraries.
+link_all_deplibs=unknown
+
+# Compile-time system search path for libraries
+sys_lib_search_path_spec="/usr/lib /lib /usr/local/lib"
+
+# Run-time system search path for libraries
+sys_lib_dlsearch_path_spec="/usr/lib /lib /usr/lib/qt-3.3/lib "
+
+# Fix the shell variable $srcfile for the compiler.
+fix_srcfile_path=""
+
+# Set to yes if exported symbols are required.
+always_export_symbols=no
+
+# The commands to list exported symbols.
+export_symbols_cmds="\$NM \$libobjs \$convenience | \$global_symbol_pipe | \$SED 's/.* //' | sort | uniq > \$export_symbols"
+
+# The commands to extract the exported symbol list from a shared archive.
+extract_expsyms_cmds=""
+
+# Symbols that should not be listed in the preloaded symbols.
+exclude_expsyms="_GLOBAL_OFFSET_TABLE_"
+
+# Symbols that must always be exported.
+include_expsyms=""
+
+# ### END LIBTOOL CONFIG
+
+# 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 at 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
+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% $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
+	    ;;
+	  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 at 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:
+# ### BEGIN LIBTOOL TAG CONFIG: CXX
+
+# Libtool was configured on host lambda:
+
+# Shell to use when invoking shell scripts.
+SHELL="/bin/sh"
+
+# Whether or not to build shared libraries.
+build_libtool_libs=yes
+
+# Whether or not to build static libraries.
+build_old_libs=yes
+
+# Whether or not to add -lc for building shared libraries.
+build_libtool_need_lc=no
+
+# Whether or not to disallow shared libs when runtime libs are static
+allow_libtool_libs_with_static_runtimes=no
+
+# Whether or not to optimize for fast installation.
+fast_install=yes
+
+# The host system.
+host_alias=
+host=i686-pc-linux-gnu
+host_os=linux-gnu
+
+# The build system.
+build_alias=
+build=i686-pc-linux-gnu
+build_os=linux-gnu
+
+# An echo program that does not interpret backslashes.
+echo="echo"
+
+# The archiver.
+AR="ar"
+AR_FLAGS="cru"
+
+# A C compiler.
+LTCC="gcc"
+
+# LTCC compiler flags.
+LTCFLAGS="-g -O2"
+
+# A language-specific compiler.
+CC="g++"
+
+# Is the compiler the GNU C compiler?
+with_gcc=yes
+
+# An ERE matcher.
+EGREP="/bin/grep -E"
+
+# The linker used to build libraries.
+LD="/usr/bin/ld"
+
+# Whether we need hard or soft links.
+LN_S="ln -s"
+
+# A BSD-compatible nm program.
+NM="/usr/bin/nm -B"
+
+# A symbol stripping program
+STRIP="strip"
+
+# Used to examine libraries when file_magic_cmd begins "file"
+MAGIC_CMD=file
+
+# 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=.libs
+
+# How to create reloadable object files.
+reload_flag=" -r"
+reload_cmds="\$LD\$reload_flag -o \$output\$reload_objs"
+
+# How to pass a linker flag through the compiler.
+wl="-Wl,"
+
+# Object file suffix (normally "o").
+objext="o"
+
+# Old archive suffix (normally "a").
+libext="a"
+
+# Shared library suffix (normally ".so").
+shrext_cmds='.so'
+
+# Executable file suffix (normally "").
+exeext=""
+
+# Additional compiler flags for building library objects.
+pic_flag=" -fPIC -DPIC"
+pic_mode=default
+
+# What is the maximum length of a command?
+max_cmd_len=98304
+
+# Does compiler simultaneously support -c and -o options?
+compiler_c_o="yes"
+
+# Must we lock files when doing compilation?
+need_locks="no"
+
+# Do we need the lib prefix for modules?
+need_lib_prefix=no
+
+# Do we need a version for libraries?
+need_version=no
+
+# Whether dlopen is supported.
+dlopen_support=unknown
+
+# Whether dlopen of programs is supported.
+dlopen_self=unknown
+
+# Whether dlopen of statically linked programs is supported.
+dlopen_self_static=unknown
+
+# Compiler flag to prevent dynamic linking.
+link_static_flag="-static"
+
+# Compiler flag to turn off builtin functions.
+no_builtin_flag=" -fno-builtin"
+
+# Compiler flag to allow reflexive dlopens.
+export_dynamic_flag_spec="\${wl}--export-dynamic"
+
+# Compiler flag to generate shared objects directly from archives.
+whole_archive_flag_spec="\${wl}--whole-archive\$convenience \${wl}--no-whole-archive"
+
+# Compiler flag to generate thread-safe objects.
+thread_safe_flag_spec=""
+
+# Library versioning type.
+version_type=linux
+
+# Format of library name prefix.
+libname_spec="lib\$name"
+
+# 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="\${libname}\${release}\${shared_ext}\$versuffix \${libname}\${release}\${shared_ext}\$major \$libname\${shared_ext}"
+
+# The coded name of the library, if different from the real name.
+soname_spec="\${libname}\${release}\${shared_ext}\$major"
+
+# Commands used to build and install an old-style archive.
+RANLIB="ranlib"
+old_archive_cmds="\$AR \$AR_FLAGS \$oldlib\$oldobjs~\$RANLIB \$oldlib"
+old_postinstall_cmds="chmod 644 \$oldlib~\$RANLIB \$oldlib"
+old_postuninstall_cmds=""
+
+# Create an old-style archive from a shared archive.
+old_archive_from_new_cmds=""
+
+# Create a temporary old-style archive to link instead of a shared archive.
+old_archive_from_expsyms_cmds=""
+
+# Commands used to build and install a shared archive.
+archive_cmds="\$CC -shared -nostdlib \$predep_objects \$libobjs \$deplibs \$postdep_objects \$compiler_flags \${wl}-soname \$wl\$soname -o \$lib"
+archive_expsym_cmds="\$CC -shared -nostdlib \$predep_objects \$libobjs \$deplibs \$postdep_objects \$compiler_flags \${wl}-soname \$wl\$soname \${wl}-retain-symbols-file \$wl\$export_symbols -o \$lib"
+postinstall_cmds=""
+postuninstall_cmds=""
+
+# Commands used to build a loadable module (assumed same as above if empty)
+module_cmds=""
+module_expsym_cmds=""
+
+# Commands to strip libraries.
+old_striplib="strip --strip-debug"
+striplib="strip --strip-unneeded"
+
+# Dependencies to place before the objects being linked to create a
+# shared library.
+predep_objects="/usr/lib/gcc/i386-redhat-linux/4.1.2/../../../crti.o /usr/lib/gcc/i386-redhat-linux/4.1.2/crtbeginS.o"
+
+# Dependencies to place after the objects being linked to create a
+# shared library.
+postdep_objects="/usr/lib/gcc/i386-redhat-linux/4.1.2/crtendS.o /usr/lib/gcc/i386-redhat-linux/4.1.2/../../../crtn.o"
+
+# Dependencies to place before the objects being linked to create a
+# shared library.
+predeps=""
+
+# Dependencies to place after the objects being linked to create a
+# shared library.
+postdeps="-lstdc++ -lm -lgcc_s -lc -lgcc_s"
+
+# The library search path used internally by the compiler when linking
+# a shared library.
+compiler_lib_search_path="-L/usr/lib/gcc/i386-redhat-linux/4.1.2 -L/usr/lib/gcc/i386-redhat-linux/4.1.2 -L/usr/lib/gcc/i386-redhat-linux/4.1.2/../../.."
+
+# Method to check whether dependent libraries are shared objects.
+deplibs_check_method="pass_all"
+
+# Command to use when deplibs_check_method == file_magic.
+file_magic_cmd="\$MAGIC_CMD"
+
+# Flag that allows shared libraries with undefined symbols to be built.
+allow_undefined_flag=""
+
+# Flag that forces no undefined symbols.
+no_undefined_flag=""
+
+# Commands used to finish a libtool library installation in a directory.
+finish_cmds="PATH=\\\"\\\$PATH:/sbin\\\" ldconfig -n \$libdir"
+
+# Same as above, but a single script fragment to be evaled but not shown.
+finish_eval=""
+
+# Take the output of nm and produce a listing of raw symbols and C names.
+global_symbol_pipe="sed -n -e 's/^.*[ 	]\\([ABCDGIRSTW][ABCDGIRSTW]*\\)[ 	][ 	]*\\([_A-Za-z][_A-Za-z0-9]*\\)\$/\\1 \\2 \\2/p'"
+
+# Transform the output of nm in a proper C declaration
+global_symbol_to_cdecl="sed -n -e 's/^. .* \\(.*\\)\$/extern int \\1;/p'"
+
+# Transform the output of nm in a C name address pair
+global_symbol_to_c_name_address="sed -n -e 's/^: \\([^ ]*\\) \$/  {\\\"\\1\\\", (lt_ptr) 0},/p' -e 's/^[BCDEGRST] \\([^ ]*\\) \\([^ ]*\\)\$/  {\"\\2\", (lt_ptr) \\&\\2},/p'"
+
+# This is the shared library runtime path variable.
+runpath_var=LD_RUN_PATH
+
+# This is the shared library path variable.
+shlibpath_var=LD_LIBRARY_PATH
+
+# Is shlibpath searched before the hard-coded library search path?
+shlibpath_overrides_runpath=no
+
+# How to hardcode a shared library path into an executable.
+hardcode_action=immediate
+
+# Whether we should hardcode library paths into libraries.
+hardcode_into_libs=yes
+
+# Flag to hardcode $libdir into a binary during linking.
+# This must work even if $libdir does not exist.
+hardcode_libdir_flag_spec="\${wl}--rpath \${wl}\$libdir"
+
+# 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=""
+
+# Whether we need a single -rpath flag with a separated argument.
+hardcode_libdir_separator=""
+
+# Set to yes if using DIR/libNAME during linking hardcodes DIR into the
+# resulting binary.
+hardcode_direct=no
+
+# Set to yes if using the -LDIR flag during linking hardcodes DIR into the
+# resulting binary.
+hardcode_minus_L=no
+
+# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into
+# the resulting binary.
+hardcode_shlibpath_var=unsupported
+
+# 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=no
+
+# Variables whose values should be saved in libtool wrapper scripts and
+# restored at relink time.
+variables_saved_for_relink="PATH LD_LIBRARY_PATH LD_RUN_PATH GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH"
+
+# Whether libtool must link a program against all its dependency libraries.
+link_all_deplibs=unknown
+
+# Compile-time system search path for libraries
+sys_lib_search_path_spec="/usr/lib /lib /usr/local/lib"
+
+# Run-time system search path for libraries
+sys_lib_dlsearch_path_spec="/usr/lib /lib /usr/lib/qt-3.3/lib "
+
+# Fix the shell variable $srcfile for the compiler.
+fix_srcfile_path=""
+
+# Set to yes if exported symbols are required.
+always_export_symbols=no
+
+# The commands to list exported symbols.
+export_symbols_cmds="\$NM \$libobjs \$convenience | \$global_symbol_pipe | \$SED 's/.* //' | sort | uniq > \$export_symbols"
+
+# The commands to extract the exported symbol list from a shared archive.
+extract_expsyms_cmds=""
+
+# Symbols that should not be listed in the preloaded symbols.
+exclude_expsyms=""
+
+# Symbols that must always be exported.
+include_expsyms=""
+
+# ### END LIBTOOL TAG CONFIG: CXX
+
+# ### BEGIN LIBTOOL TAG CONFIG: F77
+
+# Libtool was configured on host lambda:
+
+# Shell to use when invoking shell scripts.
+SHELL="/bin/sh"
+
+# Whether or not to build shared libraries.
+build_libtool_libs=yes
+
+# Whether or not to build static libraries.
+build_old_libs=yes
+
+# Whether or not to add -lc for building shared libraries.
+build_libtool_need_lc=no
+
+# Whether or not to disallow shared libs when runtime libs are static
+allow_libtool_libs_with_static_runtimes=no
+
+# Whether or not to optimize for fast installation.
+fast_install=yes
+
+# The host system.
+host_alias=
+host=i686-pc-linux-gnu
+host_os=linux-gnu
+
+# The build system.
+build_alias=
+build=i686-pc-linux-gnu
+build_os=linux-gnu
+
+# An echo program that does not interpret backslashes.
+echo="echo"
+
+# The archiver.
+AR="ar"
+AR_FLAGS="cru"
+
+# A C compiler.
+LTCC="gcc"
+
+# LTCC compiler flags.
+LTCFLAGS="-g -O2"
+
+# A language-specific compiler.
+CC="gfortran"
+
+# Is the compiler the GNU C compiler?
+with_gcc=yes
+
+# An ERE matcher.
+EGREP="/bin/grep -E"
+
+# The linker used to build libraries.
+LD="/usr/bin/ld"
+
+# Whether we need hard or soft links.
+LN_S="ln -s"
+
+# A BSD-compatible nm program.
+NM="/usr/bin/nm -B"
+
+# A symbol stripping program
+STRIP="strip"
+
+# Used to examine libraries when file_magic_cmd begins "file"
+MAGIC_CMD=file
+
+# 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=.libs
+
+# How to create reloadable object files.
+reload_flag=" -r"
+reload_cmds="\$LD\$reload_flag -o \$output\$reload_objs"
+
+# How to pass a linker flag through the compiler.
+wl="-Wl,"
+
+# Object file suffix (normally "o").
+objext="o"
+
+# Old archive suffix (normally "a").
+libext="a"
+
+# Shared library suffix (normally ".so").
+shrext_cmds='.so'
+
+# Executable file suffix (normally "").
+exeext=""
+
+# Additional compiler flags for building library objects.
+pic_flag=" -fPIC"
+pic_mode=default
+
+# What is the maximum length of a command?
+max_cmd_len=98304
+
+# Does compiler simultaneously support -c and -o options?
+compiler_c_o="yes"
+
+# Must we lock files when doing compilation?
+need_locks="no"
+
+# Do we need the lib prefix for modules?
+need_lib_prefix=no
+
+# Do we need a version for libraries?
+need_version=no
+
+# Whether dlopen is supported.
+dlopen_support=unknown
+
+# Whether dlopen of programs is supported.
+dlopen_self=unknown
+
+# Whether dlopen of statically linked programs is supported.
+dlopen_self_static=unknown
+
+# Compiler flag to prevent dynamic linking.
+link_static_flag="-static"
+
+# Compiler flag to turn off builtin functions.
+no_builtin_flag=""
+
+# Compiler flag to allow reflexive dlopens.
+export_dynamic_flag_spec="\${wl}--export-dynamic"
+
+# Compiler flag to generate shared objects directly from archives.
+whole_archive_flag_spec="\${wl}--whole-archive\$convenience \${wl}--no-whole-archive"
+
+# Compiler flag to generate thread-safe objects.
+thread_safe_flag_spec=""
+
+# Library versioning type.
+version_type=linux
+
+# Format of library name prefix.
+libname_spec="lib\$name"
+
+# 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="\${libname}\${release}\${shared_ext}\$versuffix \${libname}\${release}\${shared_ext}\$major \$libname\${shared_ext}"
+
+# The coded name of the library, if different from the real name.
+soname_spec="\${libname}\${release}\${shared_ext}\$major"
+
+# Commands used to build and install an old-style archive.
+RANLIB="ranlib"
+old_archive_cmds="\$AR \$AR_FLAGS \$oldlib\$oldobjs~\$RANLIB \$oldlib"
+old_postinstall_cmds="chmod 644 \$oldlib~\$RANLIB \$oldlib"
+old_postuninstall_cmds=""
+
+# Create an old-style archive from a shared archive.
+old_archive_from_new_cmds=""
+
+# Create a temporary old-style archive to link instead of a shared archive.
+old_archive_from_expsyms_cmds=""
+
+# Commands used to build and install a shared archive.
+archive_cmds="\$CC -shared \$libobjs \$deplibs \$compiler_flags \${wl}-soname \$wl\$soname -o \$lib"
+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 -shared \$libobjs \$deplibs \$compiler_flags \${wl}-soname \$wl\$soname \${wl}-version-script \${wl}\$output_objdir/\$libname.ver -o \$lib"
+postinstall_cmds=""
+postuninstall_cmds=""
+
+# Commands used to build a loadable module (assumed same as above if empty)
+module_cmds=""
+module_expsym_cmds=""
+
+# Commands to strip libraries.
+old_striplib="strip --strip-debug"
+striplib="strip --strip-unneeded"
+
+# Dependencies to place before the objects being linked to create a
+# shared library.
+predep_objects=""
+
+# Dependencies to place after the objects being linked to create a
+# shared library.
+postdep_objects=""
+
+# Dependencies to place before the objects being linked to create a
+# shared library.
+predeps=""
+
+# Dependencies to place after the objects being linked to create a
+# shared library.
+postdeps=""
+
+# The library search path used internally by the compiler when linking
+# a shared library.
+compiler_lib_search_path=""
+
+# Method to check whether dependent libraries are shared objects.
+deplibs_check_method="pass_all"
+
+# Command to use when deplibs_check_method == file_magic.
+file_magic_cmd="\$MAGIC_CMD"
+
+# Flag that allows shared libraries with undefined symbols to be built.
+allow_undefined_flag=""
+
+# Flag that forces no undefined symbols.
+no_undefined_flag=""
+
+# Commands used to finish a libtool library installation in a directory.
+finish_cmds="PATH=\\\"\\\$PATH:/sbin\\\" ldconfig -n \$libdir"
+
+# Same as above, but a single script fragment to be evaled but not shown.
+finish_eval=""
+
+# Take the output of nm and produce a listing of raw symbols and C names.
+global_symbol_pipe="sed -n -e 's/^.*[ 	]\\([ABCDGIRSTW][ABCDGIRSTW]*\\)[ 	][ 	]*\\([_A-Za-z][_A-Za-z0-9]*\\)\$/\\1 \\2 \\2/p'"
+
+# Transform the output of nm in a proper C declaration
+global_symbol_to_cdecl="sed -n -e 's/^. .* \\(.*\\)\$/extern int \\1;/p'"
+
+# Transform the output of nm in a C name address pair
+global_symbol_to_c_name_address="sed -n -e 's/^: \\([^ ]*\\) \$/  {\\\"\\1\\\", (lt_ptr) 0},/p' -e 's/^[BCDEGRST] \\([^ ]*\\) \\([^ ]*\\)\$/  {\"\\2\", (lt_ptr) \\&\\2},/p'"
+
+# This is the shared library runtime path variable.
+runpath_var=LD_RUN_PATH
+
+# This is the shared library path variable.
+shlibpath_var=LD_LIBRARY_PATH
+
+# Is shlibpath searched before the hard-coded library search path?
+shlibpath_overrides_runpath=no
+
+# How to hardcode a shared library path into an executable.
+hardcode_action=immediate
+
+# Whether we should hardcode library paths into libraries.
+hardcode_into_libs=yes
+
+# Flag to hardcode $libdir into a binary during linking.
+# This must work even if $libdir does not exist.
+hardcode_libdir_flag_spec="\${wl}--rpath \${wl}\$libdir"
+
+# 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=""
+
+# Whether we need a single -rpath flag with a separated argument.
+hardcode_libdir_separator=""
+
+# Set to yes if using DIR/libNAME during linking hardcodes DIR into the
+# resulting binary.
+hardcode_direct=no
+
+# Set to yes if using the -LDIR flag during linking hardcodes DIR into the
+# resulting binary.
+hardcode_minus_L=no
+
+# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into
+# the resulting binary.
+hardcode_shlibpath_var=unsupported
+
+# 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=no
+
+# Variables whose values should be saved in libtool wrapper scripts and
+# restored at relink time.
+variables_saved_for_relink="PATH LD_LIBRARY_PATH LD_RUN_PATH GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH"
+
+# Whether libtool must link a program against all its dependency libraries.
+link_all_deplibs=unknown
+
+# Compile-time system search path for libraries
+sys_lib_search_path_spec="/usr/lib /lib /usr/local/lib"
+
+# Run-time system search path for libraries
+sys_lib_dlsearch_path_spec="/usr/lib /lib /usr/lib/qt-3.3/lib "
+
+# Fix the shell variable $srcfile for the compiler.
+fix_srcfile_path=""
+
+# Set to yes if exported symbols are required.
+always_export_symbols=no
+
+# The commands to list exported symbols.
+export_symbols_cmds="\$NM \$libobjs \$convenience | \$global_symbol_pipe | \$SED 's/.* //' | sort | uniq > \$export_symbols"
+
+# The commands to extract the exported symbol list from a shared archive.
+extract_expsyms_cmds=""
+
+# Symbols that should not be listed in the preloaded symbols.
+exclude_expsyms="_GLOBAL_OFFSET_TABLE_"
+
+# Symbols that must always be exported.
+include_expsyms=""
+
+# ### END LIBTOOL TAG CONFIG: F77
+
diff --git a/libltdl/ltdl.c b/libltdl/ltdl.c
new file mode 100644
index 0000000..5f56fbb
--- /dev/null
+++ b/libltdl/ltdl.c
@@ -0,0 +1,4543 @@
+/* ltdl.c -- system independent dlopen wrapper
+   Copyright (C) 1998, 1999, 2000, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
+   Originally by Thomas Tanner <tanner at 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 at 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
+
+#ifdef RTLD_GLOBAL
+#  define LT_GLOBAL		RTLD_GLOBAL
+#else
+#  ifdef DL_GLOBAL
+#    define LT_GLOBAL		DL_GLOBAL
+#  endif
+#endif /* !RTLD_GLOBAL */
+#ifndef LT_GLOBAL
+#  define LT_GLOBAL		0
+#endif /* !LT_GLOBAL */
+
+/* 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_GLOBAL | 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)
+	{
+	  /* don't open .la files in current directory, root might get tricked to run a binary in a prepared directory */
+	  if(!strncmp((filename + strlen(filename) - 3), LTDL_ARCHIVE_EXT,3) || strstr(filename,"/"))
+	    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
index 0000000..a180245
--- /dev/null
+++ b/libltdl/ltdl.h
@@ -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 at 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
index 0000000..8e5a930
--- /dev/null
+++ b/libltdl/ltmain.sh
@@ -0,0 +1,6930 @@
+# 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 at 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
+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% $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
+	    ;;
+	  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 at 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
index 0000000..894e786
--- /dev/null
+++ b/libltdl/missing
@@ -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 at 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 at 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
index 0000000..ef7e16f
--- /dev/null
+++ b/libltdl/mkinstalldirs
@@ -0,0 +1,161 @@
+#! /bin/sh
+# mkinstalldirs --- make directory hierarchy
+
+scriptversion=2006-05-11.19
+
+# Original author: Noah Friedman <friedman at prep.ai.mit.edu>
+# Created: 1993-05-16
+# Public domain.
+#
+# This file is maintained in Automake, please report
+# bugs to <bug-automake at gnu.org> or send patches to
+# <automake-patches at 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 at 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
index 0000000..4547fe1
--- /dev/null
+++ b/libltdl/stamp-h1
@@ -0,0 +1 @@
+timestamp for config.h

commit db7fdf6e32f795188f3f1bdae56114cfc4dc166b
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sun Aug 12 20:35:05 2007 +0000

    make make dist work
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1652 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/Makefile.am b/src/Makefile.am
index 2d3af07..a10fe73 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -79,7 +79,8 @@ 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/semaphore-win32.c pulsecore/semaphore.h
+		pulsecore/semaphore.h
+#pulsecore/semaphore-win32.c pulsecore/semaphore.h
 else
 PA_THREAD_OBJS = \
 		pulsecore/atomic.h \
@@ -660,7 +661,7 @@ libpulsecore_la_SOURCES += \
 		pulsecore/hook-list.c pulsecore/hook-list.h \
 		pulsecore/shm.c pulsecore/shm.h \
 		pulsecore/flist.c pulsecore/flist.h \
-		pulsecore/asyncmsgq.c pulsecore/asyncmsgqq.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 \

commit e6714e1cb188b0058dfc785d683a979edfb84426
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sun Aug 12 20:51:58 2007 +0000

    make make distcheck pass
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1653 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/configure.ac b/configure.ac
index 6d7f0be..1bde5cc 100644
--- a/configure.ac
+++ b/configure.ac
@@ -115,6 +115,7 @@ 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
     AC_MSG_ERROR([[
@@ -782,8 +783,6 @@ src/pulse/version.h
 ])
 AC_OUTPUT
 
-AC_CONFIG_SUBDIRS(libltdl)
-
 # ==========================================================================
 ENABLE_X11=no
 if test "x$HAVE_X11" = "x1" ; then
diff --git a/libltdl/Makefile b/libltdl/Makefile
deleted file mode 100644
index 90fddd7..0000000
--- a/libltdl/Makefile
+++ /dev/null
@@ -1,656 +0,0 @@
-# Makefile.in generated by automake 1.10 from Makefile.am.
-# Makefile.  Generated from Makefile.in by configure.
-
-# 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.
-
-
-
-
-
-pkgdatadir = $(datadir)/libltdl
-pkglibdir = $(libdir)/libltdl
-pkgincludedir = $(includedir)/libltdl
-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 = i686-pc-linux-gnu
-host_triplet = i686-pc-linux-gnu
-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 $@
-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)
-#am_libltdlc_la_rpath =
-DEFAULT_INCLUDES = -I.
-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 = ${SHELL} /home/lennart/projects/pulseaudio/libltdl/missing --run aclocal-1.10
-AMTAR = ${SHELL} /home/lennart/projects/pulseaudio/libltdl/missing --run tar
-AR = ar
-AS = as
-AUTOCONF = ${SHELL} /home/lennart/projects/pulseaudio/libltdl/missing --run autoconf
-AUTOHEADER = ${SHELL} /home/lennart/projects/pulseaudio/libltdl/missing --run autoheader
-AUTOMAKE = ${SHELL} /home/lennart/projects/pulseaudio/libltdl/missing --run automake-1.10
-AWK = gawk
-CC = gcc
-CCDEPMODE = depmode=none
-CFLAGS = -g -O2
-CPP = gcc -E
-CPPFLAGS = 
-CXX = g++
-CXXCPP = g++ -E
-CXXDEPMODE = depmode=none
-CXXFLAGS = -g -O2
-CYGPATH_W = echo
-DEFS = -DHAVE_CONFIG_H
-DEPDIR = .deps
-DLLTOOL = dlltool
-ECHO = echo
-ECHO_C = 
-ECHO_N = -n
-ECHO_T = 
-EGREP = /bin/grep -E
-EXEEXT = 
-F77 = gfortran
-FFLAGS = -g -O2
-GREP = /bin/grep
-INSTALL = /usr/bin/install -c
-INSTALL_DATA = ${INSTALL} -m 644
-INSTALL_PROGRAM = ${INSTALL}
-INSTALL_SCRIPT = ${INSTALL}
-INSTALL_STRIP_PROGRAM = $(install_sh) -c -s
-LDFLAGS = 
-LIBADD_DL = -ldl
-LIBOBJS = 
-LIBS = 
-LIBTOOL = $(SHELL) $(top_builddir)/libtool
-LIBTOOL_DEPS = ./ltmain.sh
-LN_S = ln -s
-LTLIBOBJS = 
-MAKEINFO = ${SHELL} /home/lennart/projects/pulseaudio/libltdl/missing --run makeinfo
-MKDIR_P = /bin/mkdir -p
-OBJDUMP = objdump
-OBJEXT = o
-PACKAGE = libltdl
-PACKAGE_BUGREPORT = bug-libtool at gnu.org
-PACKAGE_NAME = libltdl
-PACKAGE_STRING = libltdl 1.2
-PACKAGE_TARNAME = libltdl
-PACKAGE_VERSION = 1.2
-PATH_SEPARATOR = :
-RANLIB = ranlib
-SED = /bin/sed
-SET_MAKE = 
-SHELL = /bin/sh
-STRIP = strip
-VERSION = 1.2
-abs_builddir = /home/lennart/projects/pulseaudio/libltdl
-abs_srcdir = /home/lennart/projects/pulseaudio/libltdl
-abs_top_builddir = /home/lennart/projects/pulseaudio/libltdl
-abs_top_srcdir = /home/lennart/projects/pulseaudio/libltdl
-ac_ct_CC = gcc
-ac_ct_CXX = g++
-ac_ct_F77 = gfortran
-am__include = include
-am__leading_dot = .
-am__quote = 
-am__tar = ${AMTAR} chof - "$$tardir"
-am__untar = ${AMTAR} xf -
-bindir = ${exec_prefix}/bin
-build = i686-pc-linux-gnu
-build_alias = 
-build_cpu = i686
-build_os = linux-gnu
-build_vendor = pc
-builddir = .
-datadir = ${datarootdir}
-datarootdir = ${prefix}/share
-docdir = ${datarootdir}/doc/${PACKAGE_TARNAME}
-dvidir = ${docdir}
-exec_prefix = ${prefix}
-host = i686-pc-linux-gnu
-host_alias = 
-host_cpu = i686
-host_os = linux-gnu
-host_vendor = pc
-htmldir = ${docdir}
-includedir = ${prefix}/include
-infodir = ${datarootdir}/info
-install_sh = $(SHELL) /home/lennart/projects/pulseaudio/libltdl/install-sh
-libdir = ${exec_prefix}/lib
-libexecdir = ${exec_prefix}/libexec
-localedir = ${datarootdir}/locale
-localstatedir = ${prefix}/var
-mandir = ${datarootdir}/man
-mkdir_p = /bin/mkdir -p
-oldincludedir = /usr/include
-pdfdir = ${docdir}
-prefix = /usr/local
-program_transform_name = s,x,x,
-psdir = ${docdir}
-sbindir = ${exec_prefix}/sbin
-sharedstatedir = ${prefix}/com
-srcdir = .
-sysconfdir = ${prefix}/etc
-target_alias = 
-top_builddir = .
-top_srcdir = .
-AUTOMAKE_OPTIONS = no-dependencies foreign
-include_HEADERS = ltdl.h
-lib_LTLIBRARIES = libltdl.la
-#noinst_HEADERS = ltdl.h
-#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/config.log b/libltdl/config.log
deleted file mode 100644
index 1aca1d9..0000000
--- a/libltdl/config.log
+++ /dev/null
@@ -1,1609 +0,0 @@
-This file contains any messages produced by compilers while
-running configure, to aid debugging if configure makes a mistake.
-
-It was created by libltdl configure 1.2, which was
-generated by GNU Autoconf 2.61.  Invocation command line was
-
-  $ ./configure 
-
-## --------- ##
-## Platform. ##
-## --------- ##
-
-hostname = lambda
-uname -m = i686
-uname -r = 2.6.23-0.73.rc2.fc8
-uname -s = Linux
-uname -v = #1 SMP Mon Aug 6 20:26:04 EDT 2007
-
-/usr/bin/uname -p = unknown
-/bin/uname -X     = unknown
-
-/bin/arch              = i686
-/usr/bin/arch -k       = unknown
-/usr/convex/getsysinfo = unknown
-/usr/bin/hostinfo      = unknown
-/bin/machine           = unknown
-/usr/bin/oslevel       = unknown
-/bin/universe          = unknown
-
-PATH: /home/lennart/bin
-PATH: /usr/lib/qt-3.3/bin
-PATH: /usr/kerberos/bin
-PATH: /usr/lib/ccache
-PATH: /usr/local/bin
-PATH: /bin
-PATH: /usr/bin
-
-
-## ----------- ##
-## Core tests. ##
-## ----------- ##
-
-configure:2017: checking for a BSD-compatible install
-configure:2073: result: /usr/bin/install -c
-configure:2084: checking whether build environment is sane
-configure:2127: result: yes
-configure:2155: checking for a thread-safe mkdir -p
-configure:2194: result: /bin/mkdir -p
-configure:2207: checking for gawk
-configure:2223: found /bin/gawk
-configure:2234: result: gawk
-configure:2245: checking whether make sets $(MAKE)
-configure:2266: result: yes
-configure:2500: checking for gcc
-configure:2516: found /usr/lib/ccache/gcc
-configure:2527: result: gcc
-configure:2765: checking for C compiler version
-configure:2772: gcc --version >&5
-gcc (GCC) 4.1.2 20070723 (Red Hat 4.1.2-17)
-Copyright (C) 2006 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.
-
-configure:2775: $? = 0
-configure:2782: gcc -v >&5
-Using built-in specs.
-Target: i386-redhat-linux
-Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --enable-shared --enable-threads=posix --enable-checking=release --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-languages=c,c++,objc,obj-c++,java,fortran,ada --enable-java-awt=gtk --disable-dssi --enable-plugin --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-1.5.0.0/jre --enable-libgcj-multifile --enable-java-maintainer-mode --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --with-cpu=generic --host=i386-redhat-linux
-Thread model: posix
-gcc version 4.1.2 20070723 (Red Hat 4.1.2-17)
-configure:2785: $? = 0
-configure:2792: gcc -V >&5
-gcc: '-V' option must have argument
-configure:2795: $? = 1
-configure:2818: checking for C compiler default output file name
-configure:2845: gcc    conftest.c  >&5
-configure:2848: $? = 0
-configure:2886: result: a.out
-configure:2903: checking whether the C compiler works
-configure:2913: ./a.out
-configure:2916: $? = 0
-configure:2933: result: yes
-configure:2940: checking whether we are cross compiling
-configure:2942: result: no
-configure:2945: checking for suffix of executables
-configure:2952: gcc -o conftest    conftest.c  >&5
-configure:2955: $? = 0
-configure:2979: result: 
-configure:2985: checking for suffix of object files
-configure:3011: gcc -c   conftest.c >&5
-configure:3014: $? = 0
-configure:3037: result: o
-configure:3041: checking whether we are using the GNU C compiler
-configure:3070: gcc -c   conftest.c >&5
-configure:3076: $? = 0
-configure:3093: result: yes
-configure:3098: checking whether gcc accepts -g
-configure:3128: gcc -c -g  conftest.c >&5
-configure:3134: $? = 0
-configure:3233: result: yes
-configure:3250: checking for gcc option to accept ISO C89
-configure:3324: gcc  -c -g -O2  conftest.c >&5
-configure:3330: $? = 0
-configure:3353: result: none needed
-configure:3382: checking for style of include used by make
-configure:3410: result: GNU
-configure:3435: checking dependency style of gcc
-configure:3526: result: none
-configure:3542: checking for an ANSI C-conforming const
-configure:3617: gcc -c -g -O2  conftest.c >&5
-configure:3623: $? = 0
-configure:3638: result: yes
-configure:3648: checking for inline
-configure:3674: gcc -c -g -O2  conftest.c >&5
-configure:3680: $? = 0
-configure:3698: result: inline
-configure:3802: checking build system type
-configure:3820: result: i686-pc-linux-gnu
-configure:3842: checking host system type
-configure:3857: result: i686-pc-linux-gnu
-configure:3879: checking for a sed that does not truncate output
-configure:3935: result: /bin/sed
-configure:3938: checking for grep that handles long lines and -e
-configure:4012: result: /bin/grep
-configure:4017: checking for egrep
-configure:4095: result: /bin/grep -E
-configure:4111: checking for ld used by gcc
-configure:4178: result: /usr/bin/ld
-configure:4187: checking if the linker (/usr/bin/ld) is GNU ld
-configure:4202: result: yes
-configure:4207: checking for /usr/bin/ld option to reload object files
-configure:4214: result: -r
-configure:4232: checking for BSD-compatible nm
-configure:4281: result: /usr/bin/nm -B
-configure:4285: checking whether ln -s works
-configure:4289: result: yes
-configure:4296: checking how to recognize dependent libraries
-configure:4482: result: pass_all
-configure:5013: checking how to run the C preprocessor
-configure:5053: gcc -E  conftest.c
-configure:5059: $? = 0
-configure:5090: gcc -E  conftest.c
-conftest.c:8:28: error: ac_nonexistent.h: No such file or directory
-configure:5096: $? = 1
-configure: failed program was:
-| /* confdefs.h.  */
-| #define PACKAGE_NAME "libltdl"
-| #define PACKAGE_TARNAME "libltdl"
-| #define PACKAGE_VERSION "1.2"
-| #define PACKAGE_STRING "libltdl 1.2"
-| #define PACKAGE_BUGREPORT "bug-libtool at gnu.org"
-| /* end confdefs.h.  */
-| #include <ac_nonexistent.h>
-configure:5129: result: gcc -E
-configure:5158: gcc -E  conftest.c
-configure:5164: $? = 0
-configure:5195: gcc -E  conftest.c
-conftest.c:8:28: error: ac_nonexistent.h: No such file or directory
-configure:5201: $? = 1
-configure: failed program was:
-| /* confdefs.h.  */
-| #define PACKAGE_NAME "libltdl"
-| #define PACKAGE_TARNAME "libltdl"
-| #define PACKAGE_VERSION "1.2"
-| #define PACKAGE_STRING "libltdl 1.2"
-| #define PACKAGE_BUGREPORT "bug-libtool at gnu.org"
-| /* end confdefs.h.  */
-| #include <ac_nonexistent.h>
-configure:5239: checking for ANSI C header files
-configure:5269: gcc -c -g -O2  conftest.c >&5
-configure:5275: $? = 0
-configure:5374: gcc -o conftest -g -O2   conftest.c  >&5
-configure:5377: $? = 0
-configure:5383: ./conftest
-configure:5386: $? = 0
-configure:5403: result: yes
-configure:5427: checking for sys/types.h
-configure:5448: gcc -c -g -O2  conftest.c >&5
-configure:5454: $? = 0
-configure:5470: result: yes
-configure:5427: checking for sys/stat.h
-configure:5448: gcc -c -g -O2  conftest.c >&5
-configure:5454: $? = 0
-configure:5470: result: yes
-configure:5427: checking for stdlib.h
-configure:5448: gcc -c -g -O2  conftest.c >&5
-configure:5454: $? = 0
-configure:5470: result: yes
-configure:5427: checking for string.h
-configure:5448: gcc -c -g -O2  conftest.c >&5
-configure:5454: $? = 0
-configure:5470: result: yes
-configure:5427: checking for memory.h
-configure:5448: gcc -c -g -O2  conftest.c >&5
-configure:5454: $? = 0
-configure:5470: result: yes
-configure:5427: checking for strings.h
-configure:5448: gcc -c -g -O2  conftest.c >&5
-configure:5454: $? = 0
-configure:5470: result: yes
-configure:5427: checking for inttypes.h
-configure:5448: gcc -c -g -O2  conftest.c >&5
-configure:5454: $? = 0
-configure:5470: result: yes
-configure:5427: checking for stdint.h
-configure:5448: gcc -c -g -O2  conftest.c >&5
-configure:5454: $? = 0
-configure:5470: result: yes
-configure:5427: checking for unistd.h
-configure:5448: gcc -c -g -O2  conftest.c >&5
-configure:5454: $? = 0
-configure:5470: result: yes
-configure:5497: checking dlfcn.h usability
-configure:5514: gcc -c -g -O2  conftest.c >&5
-configure:5520: $? = 0
-configure:5534: result: yes
-configure:5538: checking dlfcn.h presence
-configure:5553: gcc -E  conftest.c
-configure:5559: $? = 0
-configure:5573: result: yes
-configure:5606: checking for dlfcn.h
-configure:5614: result: yes
-configure:5685: checking for g++
-configure:5701: found /usr/lib/ccache/g++
-configure:5712: result: g++
-configure:5743: checking for C++ compiler version
-configure:5750: g++ --version >&5
-g++ (GCC) 4.1.2 20070704 (Red Hat 4.1.2-15)
-Copyright (C) 2006 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.
-
-configure:5753: $? = 0
-configure:5760: g++ -v >&5
-Using built-in specs.
-Target: i386-redhat-linux
-Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --enable-shared --enable-threads=posix --enable-checking=release --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-languages=c,c++,objc,obj-c++,java,fortran,ada --enable-java-awt=gtk --disable-dssi --enable-plugin --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-1.5.0.0/jre --enable-libgcj-multifile --enable-java-maintainer-mode --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --with-cpu=generic --host=i386-redhat-linux
-Thread model: posix
-gcc version 4.1.2 20070704 (Red Hat 4.1.2-15)
-configure:5763: $? = 0
-configure:5770: g++ -V >&5
-g++: '-V' option must have argument
-configure:5773: $? = 1
-configure:5776: checking whether we are using the GNU C++ compiler
-configure:5805: g++ -c   conftest.cpp >&5
-configure:5811: $? = 0
-configure:5828: result: yes
-configure:5833: checking whether g++ accepts -g
-configure:5863: g++ -c -g  conftest.cpp >&5
-configure:5869: $? = 0
-configure:5968: result: yes
-configure:5993: checking dependency style of g++
-configure:6084: result: none
-configure:6109: checking how to run the C++ preprocessor
-configure:6145: g++ -E  conftest.cpp
-configure:6151: $? = 0
-configure:6182: g++ -E  conftest.cpp
-conftest.cpp:19:28: error: ac_nonexistent.h: No such file or directory
-configure:6188: $? = 1
-configure: failed program was:
-| /* confdefs.h.  */
-| #define PACKAGE_NAME "libltdl"
-| #define PACKAGE_TARNAME "libltdl"
-| #define PACKAGE_VERSION "1.2"
-| #define PACKAGE_STRING "libltdl 1.2"
-| #define PACKAGE_BUGREPORT "bug-libtool at gnu.org"
-| #define STDC_HEADERS 1
-| #define HAVE_SYS_TYPES_H 1
-| #define HAVE_SYS_STAT_H 1
-| #define HAVE_STDLIB_H 1
-| #define HAVE_STRING_H 1
-| #define HAVE_MEMORY_H 1
-| #define HAVE_STRINGS_H 1
-| #define HAVE_INTTYPES_H 1
-| #define HAVE_STDINT_H 1
-| #define HAVE_UNISTD_H 1
-| #define HAVE_DLFCN_H 1
-| /* end confdefs.h.  */
-| #include <ac_nonexistent.h>
-configure:6221: result: g++ -E
-configure:6250: g++ -E  conftest.cpp
-configure:6256: $? = 0
-configure:6287: g++ -E  conftest.cpp
-conftest.cpp:19:28: error: ac_nonexistent.h: No such file or directory
-configure:6293: $? = 1
-configure: failed program was:
-| /* confdefs.h.  */
-| #define PACKAGE_NAME "libltdl"
-| #define PACKAGE_TARNAME "libltdl"
-| #define PACKAGE_VERSION "1.2"
-| #define PACKAGE_STRING "libltdl 1.2"
-| #define PACKAGE_BUGREPORT "bug-libtool at gnu.org"
-| #define STDC_HEADERS 1
-| #define HAVE_SYS_TYPES_H 1
-| #define HAVE_SYS_STAT_H 1
-| #define HAVE_STDLIB_H 1
-| #define HAVE_STRING_H 1
-| #define HAVE_MEMORY_H 1
-| #define HAVE_STRINGS_H 1
-| #define HAVE_INTTYPES_H 1
-| #define HAVE_STDINT_H 1
-| #define HAVE_UNISTD_H 1
-| #define HAVE_DLFCN_H 1
-| /* end confdefs.h.  */
-| #include <ac_nonexistent.h>
-configure:6386: checking for g77
-configure:6416: result: no
-configure:6386: checking for xlf
-configure:6416: result: no
-configure:6386: checking for f77
-configure:6416: result: no
-configure:6386: checking for frt
-configure:6416: result: no
-configure:6386: checking for pgf77
-configure:6416: result: no
-configure:6386: checking for cf77
-configure:6416: result: no
-configure:6386: checking for fort77
-configure:6416: result: no
-configure:6386: checking for fl32
-configure:6416: result: no
-configure:6386: checking for af77
-configure:6416: result: no
-configure:6386: checking for xlf90
-configure:6416: result: no
-configure:6386: checking for f90
-configure:6416: result: no
-configure:6386: checking for pgf90
-configure:6416: result: no
-configure:6386: checking for pghpf
-configure:6416: result: no
-configure:6386: checking for epcf90
-configure:6416: result: no
-configure:6386: checking for gfortran
-configure:6402: found /usr/bin/gfortran
-configure:6413: result: gfortran
-configure:6443: checking for Fortran 77 compiler version
-configure:6450: gfortran --version >&5
-GNU Fortran (GCC) 4.1.2 20070704 (Red Hat 4.1.2-15)
-Copyright (C) 2007 Free Software Foundation, Inc.
-
-GNU Fortran comes with NO WARRANTY, to the extent permitted by law.
-You may redistribute copies of GNU Fortran
-under the terms of the GNU General Public License.
-For more information about these matters, see the file named COPYING
-
-configure:6453: $? = 0
-configure:6460: gfortran -v >&5
-Using built-in specs.
-Target: i386-redhat-linux
-Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --enable-shared --enable-threads=posix --enable-checking=release --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-languages=c,c++,objc,obj-c++,java,fortran,ada --enable-java-awt=gtk --disable-dssi --enable-plugin --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-1.5.0.0/jre --enable-libgcj-multifile --enable-java-maintainer-mode --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --with-cpu=generic --host=i386-redhat-linux
-Thread model: posix
-gcc version 4.1.2 20070704 (Red Hat 4.1.2-15)
-configure:6463: $? = 0
-configure:6470: gfortran -V >&5
-gfortran: '-V' option must have argument
-configure:6473: $? = 1
-configure:6481: checking whether we are using the GNU Fortran 77 compiler
-configure:6500: gfortran -c  conftest.F >&5
-configure:6506: $? = 0
-configure:6523: result: yes
-configure:6529: checking whether gfortran accepts -g
-configure:6546: gfortran -c -g conftest.f >&5
-configure:6552: $? = 0
-configure:6568: result: yes
-configure:6598: checking the maximum length of command line arguments
-configure:6710: result: 98304
-configure:6722: checking command to parse /usr/bin/nm -B output from gcc object
-configure:6827: gcc -c -g -O2  conftest.c >&5
-configure:6830: $? = 0
-configure:6834: /usr/bin/nm -B conftest.o \| sed -n -e 's/^.*[ 	]\([ABCDGIRSTW][ABCDGIRSTW]*\)[ 	][ 	]*\([_A-Za-z][_A-Za-z0-9]*\)$/\1 \2 \2/p' \> conftest.nm
-configure:6837: $? = 0
-configure:6889: gcc -o conftest -g -O2   conftest.c conftstm.o >&5
-configure:6892: $? = 0
-configure:6930: result: ok
-configure:6934: checking for objdir
-configure:6949: result: .libs
-configure:7041: checking for ar
-configure:7057: found /usr/bin/ar
-configure:7068: result: ar
-configure:7137: checking for ranlib
-configure:7153: found /usr/bin/ranlib
-configure:7164: result: ranlib
-configure:7233: checking for strip
-configure:7249: found /usr/bin/strip
-configure:7260: result: strip
-configure:7550: checking if gcc supports -fno-rtti -fno-exceptions
-configure:7568: gcc -c -g -O2  -fno-rtti -fno-exceptions conftest.c >&5
-cc1: warning: command line option "-fno-rtti" is valid for C++/ObjC++ but not for C
-cc1: warning: command line option "-fno-rtti" is valid for C++/ObjC++ but not for C
-configure:7572: $? = 0
-configure:7585: result: no
-configure:7600: checking for gcc option to produce PIC
-configure:7832: result: -fPIC
-configure:7840: checking if gcc PIC flag -fPIC works
-configure:7858: gcc -c -g -O2  -fPIC -DPIC conftest.c >&5
-configure:7862: $? = 0
-configure:7875: result: yes
-configure:7903: checking if gcc static flag -static works
-configure:7931: result: yes
-configure:7941: checking if gcc supports -c -o file.o
-configure:7962: gcc -c -g -O2  -o out/conftest2.o conftest.c >&5
-configure:7966: $? = 0
-configure:7988: result: yes
-configure:8014: checking whether the gcc linker (/usr/bin/ld) supports shared libraries
-configure:8994: result: yes
-configure:9015: checking whether -lc should be explicitly linked in
-configure:9020: gcc -c -g -O2  conftest.c >&5
-configure:9023: $? = 0
-configure:9038: gcc -shared conftest.o  -v -Wl,-soname -Wl,conftest -o conftest 2\>\&1 \| grep  -lc  \>/dev/null 2\>\&1
-configure:9041: $? = 0
-configure:9053: result: no
-configure:9061: checking dynamic linker characteristics
-configure:9665: result: GNU/Linux ld.so
-configure:9674: checking how to hardcode library paths into programs
-configure:9699: result: immediate
-configure:9713: checking whether stripping libraries is possible
-configure:9718: result: yes
-configure:10520: checking if libtool supports shared libraries
-configure:10522: result: yes
-configure:10525: checking whether to build shared libraries
-configure:10546: result: yes
-configure:10549: checking whether to build static libraries
-configure:10553: result: yes
-configure:10646: creating libtool
-configure:11234: checking for ld used by g++
-configure:11301: result: /usr/bin/ld
-configure:11310: checking if the linker (/usr/bin/ld) is GNU ld
-configure:11325: result: yes
-configure:11376: checking whether the g++ linker (/usr/bin/ld) supports shared libraries
-configure:12350: result: yes
-configure:12372: g++ -c -g -O2  conftest.cpp >&5
-configure:12375: $? = 0
-configure:12527: checking for g++ option to produce PIC
-configure:12811: result: -fPIC
-configure:12819: checking if g++ PIC flag -fPIC works
-configure:12837: g++ -c -g -O2  -fPIC -DPIC conftest.cpp >&5
-configure:12841: $? = 0
-configure:12854: result: yes
-configure:12882: checking if g++ static flag -static works
-configure:12910: result: yes
-configure:12920: checking if g++ supports -c -o file.o
-configure:12941: g++ -c -g -O2  -o out/conftest2.o conftest.cpp >&5
-configure:12945: $? = 0
-configure:12967: result: yes
-configure:12993: checking whether the g++ linker (/usr/bin/ld) supports shared libraries
-configure:13018: result: yes
-configure:13085: checking dynamic linker characteristics
-configure:13637: result: GNU/Linux ld.so
-configure:13646: checking how to hardcode library paths into programs
-configure:13671: result: immediate
-configure:14205: checking if libtool supports shared libraries
-configure:14207: result: yes
-configure:14210: checking whether to build shared libraries
-configure:14230: result: yes
-configure:14233: checking whether to build static libraries
-configure:14237: result: yes
-configure:14247: checking for gfortran option to produce PIC
-configure:14479: result: -fPIC
-configure:14487: checking if gfortran PIC flag -fPIC works
-configure:14505: gfortran -c -g -O2 -fPIC conftest.f >&5
-configure:14509: $? = 0
-configure:14522: result: yes
-configure:14550: checking if gfortran static flag -static works
-configure:14578: result: yes
-configure:14588: checking if gfortran supports -c -o file.o
-configure:14609: gfortran -c -g -O2 -o out/conftest2.o conftest.f >&5
-configure:14613: $? = 0
-configure:14635: result: yes
-configure:14661: checking whether the gfortran linker (/usr/bin/ld) supports shared libraries
-configure:15621: result: yes
-configure:15688: checking dynamic linker characteristics
-configure:16240: result: GNU/Linux ld.so
-configure:16249: checking how to hardcode library paths into programs
-configure:16274: result: immediate
-configure:19860: checking for dirent.h that defines DIR
-configure:19889: gcc -c -g -O2  conftest.c >&5
-configure:19895: $? = 0
-configure:19911: result: yes
-configure:19924: checking for library containing opendir
-configure:19965: gcc -o conftest -g -O2   conftest.c  >&5
-configure:19971: $? = 0
-configure:19999: result: none required
-configure:20117: checking which extension is used for loadable modules
-configure:20127: result: .so
-configure:20138: checking which variable specifies run-time library path
-configure:20145: result: LD_LIBRARY_PATH
-configure:20156: checking for the default library search path
-configure:20163: result: /usr/lib /lib /usr/lib/qt-3.3/lib 
-configure:20181: checking for objdir
-configure:20202: result: .libs
-configure:20211: checking whether libtool supports -dlopen/-dlpreopen
-configure:20223: result: yes
-configure:20242: checking for shl_load
-configure:20298: gcc -o conftest -g -O2   conftest.c  >&5
-/tmp/ccPBezQi.o: In function `main':
-/home/lennart/projects/pulseaudio/libltdl/conftest.c:59: undefined reference to `shl_load'
-collect2: ld returned 1 exit status
-configure:20304: $? = 1
-configure: failed program was:
-| /* confdefs.h.  */
-| #define PACKAGE_NAME "libltdl"
-| #define PACKAGE_TARNAME "libltdl"
-| #define PACKAGE_VERSION "1.2"
-| #define PACKAGE_STRING "libltdl 1.2"
-| #define PACKAGE_BUGREPORT "bug-libtool at gnu.org"
-| #define STDC_HEADERS 1
-| #define HAVE_SYS_TYPES_H 1
-| #define HAVE_SYS_STAT_H 1
-| #define HAVE_STDLIB_H 1
-| #define HAVE_STRING_H 1
-| #define HAVE_MEMORY_H 1
-| #define HAVE_STRINGS_H 1
-| #define HAVE_INTTYPES_H 1
-| #define HAVE_STDINT_H 1
-| #define HAVE_UNISTD_H 1
-| #define HAVE_DLFCN_H 1
-| #define HAVE_DIRENT_H 1
-| #define LTDL_SHLIB_EXT ".so"
-| #define LTDL_SHLIBPATH_VAR "LD_LIBRARY_PATH"
-| #define LTDL_SYSSEARCHPATH "/usr/lib:/lib:/usr/lib/qt-3.3/lib"
-| #define LTDL_OBJDIR ".libs/"
-| #define HAVE_PRELOADED_SYMBOLS 1
-| /* 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;
-| }
-configure:20321: result: no
-configure:20330: checking for shl_load in -ldld
-configure:20365: gcc -o conftest -g -O2   conftest.c -ldld   >&5
-/usr/bin/ld: cannot find -ldld
-collect2: ld returned 1 exit status
-configure:20371: $? = 1
-configure: failed program was:
-| /* confdefs.h.  */
-| #define PACKAGE_NAME "libltdl"
-| #define PACKAGE_TARNAME "libltdl"
-| #define PACKAGE_VERSION "1.2"
-| #define PACKAGE_STRING "libltdl 1.2"
-| #define PACKAGE_BUGREPORT "bug-libtool at gnu.org"
-| #define STDC_HEADERS 1
-| #define HAVE_SYS_TYPES_H 1
-| #define HAVE_SYS_STAT_H 1
-| #define HAVE_STDLIB_H 1
-| #define HAVE_STRING_H 1
-| #define HAVE_MEMORY_H 1
-| #define HAVE_STRINGS_H 1
-| #define HAVE_INTTYPES_H 1
-| #define HAVE_STDINT_H 1
-| #define HAVE_UNISTD_H 1
-| #define HAVE_DLFCN_H 1
-| #define HAVE_DIRENT_H 1
-| #define LTDL_SHLIB_EXT ".so"
-| #define LTDL_SHLIBPATH_VAR "LD_LIBRARY_PATH"
-| #define LTDL_SYSSEARCHPATH "/usr/lib:/lib:/usr/lib/qt-3.3/lib"
-| #define LTDL_OBJDIR ".libs/"
-| #define HAVE_PRELOADED_SYMBOLS 1
-| /* 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;
-| }
-configure:20389: result: no
-configure:20399: checking for dlopen in -ldl
-configure:20434: gcc -o conftest -g -O2   conftest.c -ldl   >&5
-configure:20440: $? = 0
-configure:20458: result: yes
-configure:20769: checking for dlerror
-configure:20825: gcc -o conftest -g -O2   conftest.c  -ldl >&5
-configure:20831: $? = 0
-configure:20849: result: yes
-configure:20869: checking for _ prefix in compiled symbols
-configure:20879: gcc -c -g -O2  conftest.c >&5
-configure:20882: $? = 0
-configure:20886: /usr/bin/nm -B conftest.o \| sed -n -e 's/^.*[ 	]\([ABCDGIRSTW][ABCDGIRSTW]*\)[ 	][ 	]*\([_A-Za-z][_A-Za-z0-9]*\)$/\1 \2 \2/p' \> conftest.nm
-configure:20889: $? = 0
-configure:20911: result: no
-configure:21031: checking whether deplibs are loaded by dlopen
-configure:21115: result: yes
-configure:21140: checking argz.h usability
-configure:21157: gcc -c -g -O2  conftest.c >&5
-configure:21163: $? = 0
-configure:21177: result: yes
-configure:21181: checking argz.h presence
-configure:21196: gcc -E  conftest.c
-configure:21202: $? = 0
-configure:21216: result: yes
-configure:21249: checking for argz.h
-configure:21257: result: yes
-configure:21271: checking for error_t
-configure:21304: gcc -c -g -O2  conftest.c >&5
-configure:21310: $? = 0
-configure:21325: result: yes
-configure:21351: checking for argz_append
-configure:21407: gcc -o conftest -g -O2   conftest.c  >&5
-configure:21413: $? = 0
-configure:21431: result: yes
-configure:21351: checking for argz_create_sep
-configure:21407: gcc -o conftest -g -O2   conftest.c  >&5
-configure:21413: $? = 0
-configure:21431: result: yes
-configure:21351: checking for argz_insert
-configure:21407: gcc -o conftest -g -O2   conftest.c  >&5
-configure:21413: $? = 0
-configure:21431: result: yes
-configure:21351: checking for argz_next
-configure:21407: gcc -o conftest -g -O2   conftest.c  >&5
-configure:21413: $? = 0
-configure:21431: result: yes
-configure:21351: checking for argz_stringify
-configure:21407: gcc -o conftest -g -O2   conftest.c  >&5
-configure:21413: $? = 0
-configure:21431: result: yes
-configure:21483: checking assert.h usability
-configure:21500: gcc -c -g -O2  conftest.c >&5
-configure:21506: $? = 0
-configure:21520: result: yes
-configure:21524: checking assert.h presence
-configure:21539: gcc -E  conftest.c
-configure:21545: $? = 0
-configure:21559: result: yes
-configure:21592: checking for assert.h
-configure:21600: result: yes
-configure:21483: checking ctype.h usability
-configure:21500: gcc -c -g -O2  conftest.c >&5
-configure:21506: $? = 0
-configure:21520: result: yes
-configure:21524: checking ctype.h presence
-configure:21539: gcc -E  conftest.c
-configure:21545: $? = 0
-configure:21559: result: yes
-configure:21592: checking for ctype.h
-configure:21600: result: yes
-configure:21483: checking errno.h usability
-configure:21500: gcc -c -g -O2  conftest.c >&5
-configure:21506: $? = 0
-configure:21520: result: yes
-configure:21524: checking errno.h presence
-configure:21539: gcc -E  conftest.c
-configure:21545: $? = 0
-configure:21559: result: yes
-configure:21592: checking for errno.h
-configure:21600: result: yes
-configure:21483: checking malloc.h usability
-configure:21500: gcc -c -g -O2  conftest.c >&5
-configure:21506: $? = 0
-configure:21520: result: yes
-configure:21524: checking malloc.h presence
-configure:21539: gcc -E  conftest.c
-configure:21545: $? = 0
-configure:21559: result: yes
-configure:21592: checking for malloc.h
-configure:21600: result: yes
-configure:21473: checking for memory.h
-configure:21479: result: yes
-configure:21473: checking for stdlib.h
-configure:21479: result: yes
-configure:21483: checking stdio.h usability
-configure:21500: gcc -c -g -O2  conftest.c >&5
-configure:21506: $? = 0
-configure:21520: result: yes
-configure:21524: checking stdio.h presence
-configure:21539: gcc -E  conftest.c
-configure:21545: $? = 0
-configure:21559: result: yes
-configure:21592: checking for stdio.h
-configure:21600: result: yes
-configure:21473: checking for unistd.h
-configure:21479: result: yes
-configure:21631: checking dl.h usability
-configure:21648: gcc -c -g -O2  conftest.c >&5
-conftest.c:75:16: error: dl.h: No such file or directory
-configure:21654: $? = 1
-configure: failed program was:
-| /* confdefs.h.  */
-| #define PACKAGE_NAME "libltdl"
-| #define PACKAGE_TARNAME "libltdl"
-| #define PACKAGE_VERSION "1.2"
-| #define PACKAGE_STRING "libltdl 1.2"
-| #define PACKAGE_BUGREPORT "bug-libtool at gnu.org"
-| #define STDC_HEADERS 1
-| #define HAVE_SYS_TYPES_H 1
-| #define HAVE_SYS_STAT_H 1
-| #define HAVE_STDLIB_H 1
-| #define HAVE_STRING_H 1
-| #define HAVE_MEMORY_H 1
-| #define HAVE_STRINGS_H 1
-| #define HAVE_INTTYPES_H 1
-| #define HAVE_STDINT_H 1
-| #define HAVE_UNISTD_H 1
-| #define HAVE_DLFCN_H 1
-| #define HAVE_DIRENT_H 1
-| #define LTDL_SHLIB_EXT ".so"
-| #define LTDL_SHLIBPATH_VAR "LD_LIBRARY_PATH"
-| #define LTDL_SYSSEARCHPATH "/usr/lib:/lib:/usr/lib/qt-3.3/lib"
-| #define LTDL_OBJDIR ".libs/"
-| #define HAVE_PRELOADED_SYMBOLS 1
-| #define HAVE_LIBDL 1
-| #define HAVE_DLERROR 1
-| #define HAVE_ARGZ_H 1
-| #define HAVE_ERROR_T 1
-| #define HAVE_ARGZ_APPEND 1
-| #define HAVE_ARGZ_CREATE_SEP 1
-| #define HAVE_ARGZ_INSERT 1
-| #define HAVE_ARGZ_NEXT 1
-| #define HAVE_ARGZ_STRINGIFY 1
-| #define HAVE_ASSERT_H 1
-| #define HAVE_CTYPE_H 1
-| #define HAVE_ERRNO_H 1
-| #define HAVE_MALLOC_H 1
-| #define HAVE_MEMORY_H 1
-| #define HAVE_STDLIB_H 1
-| #define HAVE_STDIO_H 1
-| #define HAVE_UNISTD_H 1
-| /* end confdefs.h.  */
-| #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
-| #include <dl.h>
-configure:21668: result: no
-configure:21672: checking dl.h presence
-configure:21687: gcc -E  conftest.c
-conftest.c:42:16: error: dl.h: No such file or directory
-configure:21693: $? = 1
-configure: failed program was:
-| /* confdefs.h.  */
-| #define PACKAGE_NAME "libltdl"
-| #define PACKAGE_TARNAME "libltdl"
-| #define PACKAGE_VERSION "1.2"
-| #define PACKAGE_STRING "libltdl 1.2"
-| #define PACKAGE_BUGREPORT "bug-libtool at gnu.org"
-| #define STDC_HEADERS 1
-| #define HAVE_SYS_TYPES_H 1
-| #define HAVE_SYS_STAT_H 1
-| #define HAVE_STDLIB_H 1
-| #define HAVE_STRING_H 1
-| #define HAVE_MEMORY_H 1
-| #define HAVE_STRINGS_H 1
-| #define HAVE_INTTYPES_H 1
-| #define HAVE_STDINT_H 1
-| #define HAVE_UNISTD_H 1
-| #define HAVE_DLFCN_H 1
-| #define HAVE_DIRENT_H 1
-| #define LTDL_SHLIB_EXT ".so"
-| #define LTDL_SHLIBPATH_VAR "LD_LIBRARY_PATH"
-| #define LTDL_SYSSEARCHPATH "/usr/lib:/lib:/usr/lib/qt-3.3/lib"
-| #define LTDL_OBJDIR ".libs/"
-| #define HAVE_PRELOADED_SYMBOLS 1
-| #define HAVE_LIBDL 1
-| #define HAVE_DLERROR 1
-| #define HAVE_ARGZ_H 1
-| #define HAVE_ERROR_T 1
-| #define HAVE_ARGZ_APPEND 1
-| #define HAVE_ARGZ_CREATE_SEP 1
-| #define HAVE_ARGZ_INSERT 1
-| #define HAVE_ARGZ_NEXT 1
-| #define HAVE_ARGZ_STRINGIFY 1
-| #define HAVE_ASSERT_H 1
-| #define HAVE_CTYPE_H 1
-| #define HAVE_ERRNO_H 1
-| #define HAVE_MALLOC_H 1
-| #define HAVE_MEMORY_H 1
-| #define HAVE_STDLIB_H 1
-| #define HAVE_STDIO_H 1
-| #define HAVE_UNISTD_H 1
-| /* end confdefs.h.  */
-| #include <dl.h>
-configure:21707: result: no
-configure:21740: checking for dl.h
-configure:21748: result: no
-configure:21631: checking sys/dl.h usability
-configure:21648: gcc -c -g -O2  conftest.c >&5
-conftest.c:75:20: error: sys/dl.h: No such file or directory
-configure:21654: $? = 1
-configure: failed program was:
-| /* confdefs.h.  */
-| #define PACKAGE_NAME "libltdl"
-| #define PACKAGE_TARNAME "libltdl"
-| #define PACKAGE_VERSION "1.2"
-| #define PACKAGE_STRING "libltdl 1.2"
-| #define PACKAGE_BUGREPORT "bug-libtool at gnu.org"
-| #define STDC_HEADERS 1
-| #define HAVE_SYS_TYPES_H 1
-| #define HAVE_SYS_STAT_H 1
-| #define HAVE_STDLIB_H 1
-| #define HAVE_STRING_H 1
-| #define HAVE_MEMORY_H 1
-| #define HAVE_STRINGS_H 1
-| #define HAVE_INTTYPES_H 1
-| #define HAVE_STDINT_H 1
-| #define HAVE_UNISTD_H 1
-| #define HAVE_DLFCN_H 1
-| #define HAVE_DIRENT_H 1
-| #define LTDL_SHLIB_EXT ".so"
-| #define LTDL_SHLIBPATH_VAR "LD_LIBRARY_PATH"
-| #define LTDL_SYSSEARCHPATH "/usr/lib:/lib:/usr/lib/qt-3.3/lib"
-| #define LTDL_OBJDIR ".libs/"
-| #define HAVE_PRELOADED_SYMBOLS 1
-| #define HAVE_LIBDL 1
-| #define HAVE_DLERROR 1
-| #define HAVE_ARGZ_H 1
-| #define HAVE_ERROR_T 1
-| #define HAVE_ARGZ_APPEND 1
-| #define HAVE_ARGZ_CREATE_SEP 1
-| #define HAVE_ARGZ_INSERT 1
-| #define HAVE_ARGZ_NEXT 1
-| #define HAVE_ARGZ_STRINGIFY 1
-| #define HAVE_ASSERT_H 1
-| #define HAVE_CTYPE_H 1
-| #define HAVE_ERRNO_H 1
-| #define HAVE_MALLOC_H 1
-| #define HAVE_MEMORY_H 1
-| #define HAVE_STDLIB_H 1
-| #define HAVE_STDIO_H 1
-| #define HAVE_UNISTD_H 1
-| /* end confdefs.h.  */
-| #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
-| #include <sys/dl.h>
-configure:21668: result: no
-configure:21672: checking sys/dl.h presence
-configure:21687: gcc -E  conftest.c
-conftest.c:42:20: error: sys/dl.h: No such file or directory
-configure:21693: $? = 1
-configure: failed program was:
-| /* confdefs.h.  */
-| #define PACKAGE_NAME "libltdl"
-| #define PACKAGE_TARNAME "libltdl"
-| #define PACKAGE_VERSION "1.2"
-| #define PACKAGE_STRING "libltdl 1.2"
-| #define PACKAGE_BUGREPORT "bug-libtool at gnu.org"
-| #define STDC_HEADERS 1
-| #define HAVE_SYS_TYPES_H 1
-| #define HAVE_SYS_STAT_H 1
-| #define HAVE_STDLIB_H 1
-| #define HAVE_STRING_H 1
-| #define HAVE_MEMORY_H 1
-| #define HAVE_STRINGS_H 1
-| #define HAVE_INTTYPES_H 1
-| #define HAVE_STDINT_H 1
-| #define HAVE_UNISTD_H 1
-| #define HAVE_DLFCN_H 1
-| #define HAVE_DIRENT_H 1
-| #define LTDL_SHLIB_EXT ".so"
-| #define LTDL_SHLIBPATH_VAR "LD_LIBRARY_PATH"
-| #define LTDL_SYSSEARCHPATH "/usr/lib:/lib:/usr/lib/qt-3.3/lib"
-| #define LTDL_OBJDIR ".libs/"
-| #define HAVE_PRELOADED_SYMBOLS 1
-| #define HAVE_LIBDL 1
-| #define HAVE_DLERROR 1
-| #define HAVE_ARGZ_H 1
-| #define HAVE_ERROR_T 1
-| #define HAVE_ARGZ_APPEND 1
-| #define HAVE_ARGZ_CREATE_SEP 1
-| #define HAVE_ARGZ_INSERT 1
-| #define HAVE_ARGZ_NEXT 1
-| #define HAVE_ARGZ_STRINGIFY 1
-| #define HAVE_ASSERT_H 1
-| #define HAVE_CTYPE_H 1
-| #define HAVE_ERRNO_H 1
-| #define HAVE_MALLOC_H 1
-| #define HAVE_MEMORY_H 1
-| #define HAVE_STDLIB_H 1
-| #define HAVE_STDIO_H 1
-| #define HAVE_UNISTD_H 1
-| /* end confdefs.h.  */
-| #include <sys/dl.h>
-configure:21707: result: no
-configure:21740: checking for sys/dl.h
-configure:21748: result: no
-configure:21631: checking dld.h usability
-configure:21648: gcc -c -g -O2  conftest.c >&5
-conftest.c:75:17: error: dld.h: No such file or directory
-configure:21654: $? = 1
-configure: failed program was:
-| /* confdefs.h.  */
-| #define PACKAGE_NAME "libltdl"
-| #define PACKAGE_TARNAME "libltdl"
-| #define PACKAGE_VERSION "1.2"
-| #define PACKAGE_STRING "libltdl 1.2"
-| #define PACKAGE_BUGREPORT "bug-libtool at gnu.org"
-| #define STDC_HEADERS 1
-| #define HAVE_SYS_TYPES_H 1
-| #define HAVE_SYS_STAT_H 1
-| #define HAVE_STDLIB_H 1
-| #define HAVE_STRING_H 1
-| #define HAVE_MEMORY_H 1
-| #define HAVE_STRINGS_H 1
-| #define HAVE_INTTYPES_H 1
-| #define HAVE_STDINT_H 1
-| #define HAVE_UNISTD_H 1
-| #define HAVE_DLFCN_H 1
-| #define HAVE_DIRENT_H 1
-| #define LTDL_SHLIB_EXT ".so"
-| #define LTDL_SHLIBPATH_VAR "LD_LIBRARY_PATH"
-| #define LTDL_SYSSEARCHPATH "/usr/lib:/lib:/usr/lib/qt-3.3/lib"
-| #define LTDL_OBJDIR ".libs/"
-| #define HAVE_PRELOADED_SYMBOLS 1
-| #define HAVE_LIBDL 1
-| #define HAVE_DLERROR 1
-| #define HAVE_ARGZ_H 1
-| #define HAVE_ERROR_T 1
-| #define HAVE_ARGZ_APPEND 1
-| #define HAVE_ARGZ_CREATE_SEP 1
-| #define HAVE_ARGZ_INSERT 1
-| #define HAVE_ARGZ_NEXT 1
-| #define HAVE_ARGZ_STRINGIFY 1
-| #define HAVE_ASSERT_H 1
-| #define HAVE_CTYPE_H 1
-| #define HAVE_ERRNO_H 1
-| #define HAVE_MALLOC_H 1
-| #define HAVE_MEMORY_H 1
-| #define HAVE_STDLIB_H 1
-| #define HAVE_STDIO_H 1
-| #define HAVE_UNISTD_H 1
-| /* end confdefs.h.  */
-| #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
-| #include <dld.h>
-configure:21668: result: no
-configure:21672: checking dld.h presence
-configure:21687: gcc -E  conftest.c
-conftest.c:42:17: error: dld.h: No such file or directory
-configure:21693: $? = 1
-configure: failed program was:
-| /* confdefs.h.  */
-| #define PACKAGE_NAME "libltdl"
-| #define PACKAGE_TARNAME "libltdl"
-| #define PACKAGE_VERSION "1.2"
-| #define PACKAGE_STRING "libltdl 1.2"
-| #define PACKAGE_BUGREPORT "bug-libtool at gnu.org"
-| #define STDC_HEADERS 1
-| #define HAVE_SYS_TYPES_H 1
-| #define HAVE_SYS_STAT_H 1
-| #define HAVE_STDLIB_H 1
-| #define HAVE_STRING_H 1
-| #define HAVE_MEMORY_H 1
-| #define HAVE_STRINGS_H 1
-| #define HAVE_INTTYPES_H 1
-| #define HAVE_STDINT_H 1
-| #define HAVE_UNISTD_H 1
-| #define HAVE_DLFCN_H 1
-| #define HAVE_DIRENT_H 1
-| #define LTDL_SHLIB_EXT ".so"
-| #define LTDL_SHLIBPATH_VAR "LD_LIBRARY_PATH"
-| #define LTDL_SYSSEARCHPATH "/usr/lib:/lib:/usr/lib/qt-3.3/lib"
-| #define LTDL_OBJDIR ".libs/"
-| #define HAVE_PRELOADED_SYMBOLS 1
-| #define HAVE_LIBDL 1
-| #define HAVE_DLERROR 1
-| #define HAVE_ARGZ_H 1
-| #define HAVE_ERROR_T 1
-| #define HAVE_ARGZ_APPEND 1
-| #define HAVE_ARGZ_CREATE_SEP 1
-| #define HAVE_ARGZ_INSERT 1
-| #define HAVE_ARGZ_NEXT 1
-| #define HAVE_ARGZ_STRINGIFY 1
-| #define HAVE_ASSERT_H 1
-| #define HAVE_CTYPE_H 1
-| #define HAVE_ERRNO_H 1
-| #define HAVE_MALLOC_H 1
-| #define HAVE_MEMORY_H 1
-| #define HAVE_STDLIB_H 1
-| #define HAVE_STDIO_H 1
-| #define HAVE_UNISTD_H 1
-| /* end confdefs.h.  */
-| #include <dld.h>
-configure:21707: result: no
-configure:21740: checking for dld.h
-configure:21748: result: no
-configure:21631: checking mach-o/dyld.h usability
-configure:21648: gcc -c -g -O2  conftest.c >&5
-conftest.c:75:25: error: mach-o/dyld.h: No such file or directory
-configure:21654: $? = 1
-configure: failed program was:
-| /* confdefs.h.  */
-| #define PACKAGE_NAME "libltdl"
-| #define PACKAGE_TARNAME "libltdl"
-| #define PACKAGE_VERSION "1.2"
-| #define PACKAGE_STRING "libltdl 1.2"
-| #define PACKAGE_BUGREPORT "bug-libtool at gnu.org"
-| #define STDC_HEADERS 1
-| #define HAVE_SYS_TYPES_H 1
-| #define HAVE_SYS_STAT_H 1
-| #define HAVE_STDLIB_H 1
-| #define HAVE_STRING_H 1
-| #define HAVE_MEMORY_H 1
-| #define HAVE_STRINGS_H 1
-| #define HAVE_INTTYPES_H 1
-| #define HAVE_STDINT_H 1
-| #define HAVE_UNISTD_H 1
-| #define HAVE_DLFCN_H 1
-| #define HAVE_DIRENT_H 1
-| #define LTDL_SHLIB_EXT ".so"
-| #define LTDL_SHLIBPATH_VAR "LD_LIBRARY_PATH"
-| #define LTDL_SYSSEARCHPATH "/usr/lib:/lib:/usr/lib/qt-3.3/lib"
-| #define LTDL_OBJDIR ".libs/"
-| #define HAVE_PRELOADED_SYMBOLS 1
-| #define HAVE_LIBDL 1
-| #define HAVE_DLERROR 1
-| #define HAVE_ARGZ_H 1
-| #define HAVE_ERROR_T 1
-| #define HAVE_ARGZ_APPEND 1
-| #define HAVE_ARGZ_CREATE_SEP 1
-| #define HAVE_ARGZ_INSERT 1
-| #define HAVE_ARGZ_NEXT 1
-| #define HAVE_ARGZ_STRINGIFY 1
-| #define HAVE_ASSERT_H 1
-| #define HAVE_CTYPE_H 1
-| #define HAVE_ERRNO_H 1
-| #define HAVE_MALLOC_H 1
-| #define HAVE_MEMORY_H 1
-| #define HAVE_STDLIB_H 1
-| #define HAVE_STDIO_H 1
-| #define HAVE_UNISTD_H 1
-| /* end confdefs.h.  */
-| #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
-| #include <mach-o/dyld.h>
-configure:21668: result: no
-configure:21672: checking mach-o/dyld.h presence
-configure:21687: gcc -E  conftest.c
-conftest.c:42:25: error: mach-o/dyld.h: No such file or directory
-configure:21693: $? = 1
-configure: failed program was:
-| /* confdefs.h.  */
-| #define PACKAGE_NAME "libltdl"
-| #define PACKAGE_TARNAME "libltdl"
-| #define PACKAGE_VERSION "1.2"
-| #define PACKAGE_STRING "libltdl 1.2"
-| #define PACKAGE_BUGREPORT "bug-libtool at gnu.org"
-| #define STDC_HEADERS 1
-| #define HAVE_SYS_TYPES_H 1
-| #define HAVE_SYS_STAT_H 1
-| #define HAVE_STDLIB_H 1
-| #define HAVE_STRING_H 1
-| #define HAVE_MEMORY_H 1
-| #define HAVE_STRINGS_H 1
-| #define HAVE_INTTYPES_H 1
-| #define HAVE_STDINT_H 1
-| #define HAVE_UNISTD_H 1
-| #define HAVE_DLFCN_H 1
-| #define HAVE_DIRENT_H 1
-| #define LTDL_SHLIB_EXT ".so"
-| #define LTDL_SHLIBPATH_VAR "LD_LIBRARY_PATH"
-| #define LTDL_SYSSEARCHPATH "/usr/lib:/lib:/usr/lib/qt-3.3/lib"
-| #define LTDL_OBJDIR ".libs/"
-| #define HAVE_PRELOADED_SYMBOLS 1
-| #define HAVE_LIBDL 1
-| #define HAVE_DLERROR 1
-| #define HAVE_ARGZ_H 1
-| #define HAVE_ERROR_T 1
-| #define HAVE_ARGZ_APPEND 1
-| #define HAVE_ARGZ_CREATE_SEP 1
-| #define HAVE_ARGZ_INSERT 1
-| #define HAVE_ARGZ_NEXT 1
-| #define HAVE_ARGZ_STRINGIFY 1
-| #define HAVE_ASSERT_H 1
-| #define HAVE_CTYPE_H 1
-| #define HAVE_ERRNO_H 1
-| #define HAVE_MALLOC_H 1
-| #define HAVE_MEMORY_H 1
-| #define HAVE_STDLIB_H 1
-| #define HAVE_STDIO_H 1
-| #define HAVE_UNISTD_H 1
-| /* end confdefs.h.  */
-| #include <mach-o/dyld.h>
-configure:21707: result: no
-configure:21740: checking for mach-o/dyld.h
-configure:21748: result: no
-configure:21767: checking for string.h
-configure:21773: result: yes
-configure:21913: checking for strchr
-configure:21969: gcc -o conftest -g -O2   conftest.c  >&5
-conftest.c:66: warning: conflicting types for built-in function 'strchr'
-configure:21975: $? = 0
-configure:21993: result: yes
-configure:22008: checking for strrchr
-configure:22064: gcc -o conftest -g -O2   conftest.c  >&5
-conftest.c:67: warning: conflicting types for built-in function 'strrchr'
-configure:22070: $? = 0
-configure:22088: result: yes
-configure:22103: checking for memcpy
-configure:22159: gcc -o conftest -g -O2   conftest.c  >&5
-conftest.c:68: warning: conflicting types for built-in function 'memcpy'
-configure:22165: $? = 0
-configure:22183: result: yes
-configure:22198: checking for memmove
-configure:22254: gcc -o conftest -g -O2   conftest.c  >&5
-conftest.c:69: warning: conflicting types for built-in function 'memmove'
-configure:22260: $? = 0
-configure:22278: result: yes
-configure:22198: checking for strcmp
-configure:22254: gcc -o conftest -g -O2   conftest.c  >&5
-conftest.c:70: warning: conflicting types for built-in function 'strcmp'
-configure:22260: $? = 0
-configure:22278: result: yes
-configure:22294: checking for closedir
-configure:22350: gcc -o conftest -g -O2   conftest.c  >&5
-configure:22356: $? = 0
-configure:22374: result: yes
-configure:22294: checking for opendir
-configure:22350: gcc -o conftest -g -O2   conftest.c  >&5
-configure:22356: $? = 0
-configure:22374: result: yes
-configure:22294: checking for readdir
-configure:22350: gcc -o conftest -g -O2   conftest.c  >&5
-configure:22356: $? = 0
-configure:22374: result: yes
-configure:22527: creating ./config.status
-
-## ---------------------- ##
-## Running config.status. ##
-## ---------------------- ##
-
-This file was extended by libltdl config.status 1.2, which was
-generated by GNU Autoconf 2.61.  Invocation command line was
-
-  CONFIG_FILES    = 
-  CONFIG_HEADERS  = 
-  CONFIG_LINKS    = 
-  CONFIG_COMMANDS = 
-  $ ./config.status 
-
-on lambda
-
-config.status:671: creating Makefile
-config.status:671: creating config.h
-config.status:936: config.h is unchanged
-config.status:982: executing depfiles commands
-
-## ---------------- ##
-## Cache variables. ##
-## ---------------- ##
-
-ac_cv_build=i686-pc-linux-gnu
-ac_cv_c_compiler_gnu=yes
-ac_cv_c_const=yes
-ac_cv_c_inline=inline
-ac_cv_cxx_compiler_gnu=yes
-ac_cv_env_CCC_set=
-ac_cv_env_CCC_value=
-ac_cv_env_CC_set=
-ac_cv_env_CC_value=
-ac_cv_env_CFLAGS_set=
-ac_cv_env_CFLAGS_value=
-ac_cv_env_CPPFLAGS_set=
-ac_cv_env_CPPFLAGS_value=
-ac_cv_env_CPP_set=
-ac_cv_env_CPP_value=
-ac_cv_env_CXXCPP_set=
-ac_cv_env_CXXCPP_value=
-ac_cv_env_CXXFLAGS_set=
-ac_cv_env_CXXFLAGS_value=
-ac_cv_env_CXX_set=
-ac_cv_env_CXX_value=
-ac_cv_env_F77_set=
-ac_cv_env_F77_value=
-ac_cv_env_FFLAGS_set=
-ac_cv_env_FFLAGS_value=
-ac_cv_env_LDFLAGS_set=
-ac_cv_env_LDFLAGS_value=
-ac_cv_env_LIBS_set=
-ac_cv_env_LIBS_value=
-ac_cv_env_build_alias_set=
-ac_cv_env_build_alias_value=
-ac_cv_env_host_alias_set=
-ac_cv_env_host_alias_value=
-ac_cv_env_target_alias_set=
-ac_cv_env_target_alias_value=
-ac_cv_f77_compiler_gnu=yes
-ac_cv_func_argz_append=yes
-ac_cv_func_argz_create_sep=yes
-ac_cv_func_argz_insert=yes
-ac_cv_func_argz_next=yes
-ac_cv_func_argz_stringify=yes
-ac_cv_func_closedir=yes
-ac_cv_func_dlerror=yes
-ac_cv_func_memcpy=yes
-ac_cv_func_memmove=yes
-ac_cv_func_opendir=yes
-ac_cv_func_readdir=yes
-ac_cv_func_shl_load=no
-ac_cv_func_strchr=yes
-ac_cv_func_strcmp=yes
-ac_cv_func_strrchr=yes
-ac_cv_header_argz_h=yes
-ac_cv_header_assert_h=yes
-ac_cv_header_ctype_h=yes
-ac_cv_header_dirent_dirent_h=yes
-ac_cv_header_dl_h=no
-ac_cv_header_dld_h=no
-ac_cv_header_dlfcn_h=yes
-ac_cv_header_errno_h=yes
-ac_cv_header_inttypes_h=yes
-ac_cv_header_mach_o_dyld_h=no
-ac_cv_header_malloc_h=yes
-ac_cv_header_memory_h=yes
-ac_cv_header_stdc=yes
-ac_cv_header_stdint_h=yes
-ac_cv_header_stdio_h=yes
-ac_cv_header_stdlib_h=yes
-ac_cv_header_string_h=yes
-ac_cv_header_strings_h=yes
-ac_cv_header_sys_dl_h=no
-ac_cv_header_sys_stat_h=yes
-ac_cv_header_sys_types_h=yes
-ac_cv_header_unistd_h=yes
-ac_cv_host=i686-pc-linux-gnu
-ac_cv_lib_dl_dlopen=yes
-ac_cv_lib_dld_shl_load=no
-ac_cv_objext=o
-ac_cv_path_EGREP='/bin/grep -E'
-ac_cv_path_GREP=/bin/grep
-ac_cv_path_install='/usr/bin/install -c'
-ac_cv_path_mkdir=/bin/mkdir
-ac_cv_prog_AWK=gawk
-ac_cv_prog_CPP='gcc -E'
-ac_cv_prog_CXXCPP='g++ -E'
-ac_cv_prog_ac_ct_AR=ar
-ac_cv_prog_ac_ct_CC=gcc
-ac_cv_prog_ac_ct_CXX=g++
-ac_cv_prog_ac_ct_F77=gfortran
-ac_cv_prog_ac_ct_RANLIB=ranlib
-ac_cv_prog_ac_ct_STRIP=strip
-ac_cv_prog_cc_c89=
-ac_cv_prog_cc_g=yes
-ac_cv_prog_cxx_g=yes
-ac_cv_prog_f77_g=yes
-ac_cv_prog_make_make_set=yes
-ac_cv_search_opendir='none required'
-ac_cv_sys_symbol_underscore=no
-ac_cv_type_error_t=yes
-am_cv_CC_dependencies_compiler_type=none
-am_cv_CXX_dependencies_compiler_type=none
-libltdl_cv_lib_dl_dlopen=yes
-libltdl_cv_objdir=.libs
-libltdl_cv_preloaded_symbols=yes
-libltdl_cv_shlibext=.so
-libltdl_cv_shlibpath_var=LD_LIBRARY_PATH
-libltdl_cv_sys_dlopen_deplibs=yes
-libltdl_cv_sys_search_path='/usr/lib /lib /usr/lib/qt-3.3/lib '
-lt_cv_deplibs_check_method=pass_all
-lt_cv_file_magic_cmd='$MAGIC_CMD'
-lt_cv_file_magic_test_file=
-lt_cv_ld_reload_flag=-r
-lt_cv_objdir=.libs
-lt_cv_path_LD=/usr/bin/ld
-lt_cv_path_LDCXX=/usr/bin/ld
-lt_cv_path_NM='/usr/bin/nm -B'
-lt_cv_path_SED=/bin/sed
-lt_cv_prog_compiler_c_o=yes
-lt_cv_prog_compiler_c_o_CXX=yes
-lt_cv_prog_compiler_c_o_F77=yes
-lt_cv_prog_compiler_rtti_exceptions=no
-lt_cv_prog_gnu_ld=yes
-lt_cv_prog_gnu_ldcxx=yes
-lt_cv_sys_global_symbol_pipe='sed -n -e '\''s/^.*[ 	]\([ABCDGIRSTW][ABCDGIRSTW]*\)[ 	][ 	]*\([_A-Za-z][_A-Za-z0-9]*\)$/\1 \2 \2/p'\'''
-lt_cv_sys_global_symbol_to_c_name_address='sed -n -e '\''s/^: \([^ ]*\) $/  {\"\1\", (lt_ptr) 0},/p'\'' -e '\''s/^[BCDEGRST] \([^ ]*\) \([^ ]*\)$/  {"\2", (lt_ptr) \&\2},/p'\'''
-lt_cv_sys_global_symbol_to_cdecl='sed -n -e '\''s/^. .* \(.*\)$/extern int \1;/p'\'''
-lt_cv_sys_max_cmd_len=98304
-lt_lt_cv_prog_compiler_c_o='"yes"'
-lt_lt_cv_prog_compiler_c_o_CXX='"yes"'
-lt_lt_cv_prog_compiler_c_o_F77='"yes"'
-lt_lt_cv_sys_global_symbol_pipe='"sed -n -e '\''s/^.*[ 	]\\([ABCDGIRSTW][ABCDGIRSTW]*\\)[ 	][ 	]*\\([_A-Za-z][_A-Za-z0-9]*\\)\$/\\1 \\2 \\2/p'\''"'
-lt_lt_cv_sys_global_symbol_to_c_name_address='"sed -n -e '\''s/^: \\([^ ]*\\) \$/  {\\\"\\1\\\", (lt_ptr) 0},/p'\'' -e '\''s/^[BCDEGRST] \\([^ ]*\\) \\([^ ]*\\)\$/  {\"\\2\", (lt_ptr) \\&\\2},/p'\''"'
-lt_lt_cv_sys_global_symbol_to_cdecl='"sed -n -e '\''s/^. .* \\(.*\\)\$/extern int \\1;/p'\''"'
-
-## ----------------- ##
-## Output variables. ##
-## ----------------- ##
-
-ACLOCAL='${SHELL} /home/lennart/projects/pulseaudio/libltdl/missing --run aclocal-1.10'
-AMDEPBACKSLASH='\'
-AMDEP_FALSE='#'
-AMDEP_TRUE=''
-AMTAR='${SHELL} /home/lennart/projects/pulseaudio/libltdl/missing --run tar'
-AR='ar'
-AS='as'
-AUTOCONF='${SHELL} /home/lennart/projects/pulseaudio/libltdl/missing --run autoconf'
-AUTOHEADER='${SHELL} /home/lennart/projects/pulseaudio/libltdl/missing --run autoheader'
-AUTOMAKE='${SHELL} /home/lennart/projects/pulseaudio/libltdl/missing --run automake-1.10'
-AWK='gawk'
-CC='gcc'
-CCDEPMODE='depmode=none'
-CFLAGS='-g -O2'
-CONVENIENCE_LTDL_FALSE=''
-CONVENIENCE_LTDL_TRUE='#'
-CPP='gcc -E'
-CPPFLAGS=''
-CXX='g++'
-CXXCPP='g++ -E'
-CXXDEPMODE='depmode=none'
-CXXFLAGS='-g -O2'
-CYGPATH_W='echo'
-DEFS='-DHAVE_CONFIG_H'
-DEPDIR='.deps'
-DLLTOOL='dlltool'
-ECHO='echo'
-ECHO_C=''
-ECHO_N='-n'
-ECHO_T=''
-EGREP='/bin/grep -E'
-EXEEXT=''
-F77='gfortran'
-FFLAGS='-g -O2'
-GREP='/bin/grep'
-INSTALL_DATA='${INSTALL} -m 644'
-INSTALL_LTDL_FALSE='#'
-INSTALL_LTDL_TRUE=''
-INSTALL_PROGRAM='${INSTALL}'
-INSTALL_SCRIPT='${INSTALL}'
-INSTALL_STRIP_PROGRAM='$(install_sh) -c -s'
-LDFLAGS=''
-LIBADD_DL='-ldl'
-LIBOBJS=''
-LIBS=''
-LIBTOOL='$(SHELL) $(top_builddir)/libtool'
-LIBTOOL_DEPS='./ltmain.sh'
-LN_S='ln -s'
-LTLIBOBJS=''
-MAKEINFO='${SHELL} /home/lennart/projects/pulseaudio/libltdl/missing --run makeinfo'
-OBJDUMP='objdump'
-OBJEXT='o'
-PACKAGE='libltdl'
-PACKAGE_BUGREPORT='bug-libtool at gnu.org'
-PACKAGE_NAME='libltdl'
-PACKAGE_STRING='libltdl 1.2'
-PACKAGE_TARNAME='libltdl'
-PACKAGE_VERSION='1.2'
-PATH_SEPARATOR=':'
-RANLIB='ranlib'
-SED='/bin/sed'
-SET_MAKE=''
-SHELL='/bin/sh'
-STRIP='strip'
-VERSION='1.2'
-ac_ct_CC='gcc'
-ac_ct_CXX='g++'
-ac_ct_F77='gfortran'
-am__fastdepCC_FALSE=''
-am__fastdepCC_TRUE='#'
-am__fastdepCXX_FALSE=''
-am__fastdepCXX_TRUE='#'
-am__include='include'
-am__isrc=''
-am__leading_dot='.'
-am__quote=''
-am__tar='${AMTAR} chof - "$$tardir"'
-am__untar='${AMTAR} xf -'
-bindir='${exec_prefix}/bin'
-build='i686-pc-linux-gnu'
-build_alias=''
-build_cpu='i686'
-build_os='linux-gnu'
-build_vendor='pc'
-datadir='${datarootdir}'
-datarootdir='${prefix}/share'
-docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
-dvidir='${docdir}'
-exec_prefix='${prefix}'
-host='i686-pc-linux-gnu'
-host_alias=''
-host_cpu='i686'
-host_os='linux-gnu'
-host_vendor='pc'
-htmldir='${docdir}'
-includedir='${prefix}/include'
-infodir='${datarootdir}/info'
-install_sh='$(SHELL) /home/lennart/projects/pulseaudio/libltdl/install-sh'
-libdir='${exec_prefix}/lib'
-libexecdir='${exec_prefix}/libexec'
-localedir='${datarootdir}/locale'
-localstatedir='${prefix}/var'
-mandir='${datarootdir}/man'
-mkdir_p='/bin/mkdir -p'
-oldincludedir='/usr/include'
-pdfdir='${docdir}'
-prefix='/usr/local'
-program_transform_name='s,x,x,'
-psdir='${docdir}'
-sbindir='${exec_prefix}/sbin'
-sharedstatedir='${prefix}/com'
-sysconfdir='${prefix}/etc'
-target_alias=''
-
-## ----------- ##
-## confdefs.h. ##
-## ----------- ##
-
-#define PACKAGE_NAME "libltdl"
-#define PACKAGE_TARNAME "libltdl"
-#define PACKAGE_VERSION "1.2"
-#define PACKAGE_STRING "libltdl 1.2"
-#define PACKAGE_BUGREPORT "bug-libtool at gnu.org"
-#define STDC_HEADERS 1
-#define HAVE_SYS_TYPES_H 1
-#define HAVE_SYS_STAT_H 1
-#define HAVE_STDLIB_H 1
-#define HAVE_STRING_H 1
-#define HAVE_MEMORY_H 1
-#define HAVE_STRINGS_H 1
-#define HAVE_INTTYPES_H 1
-#define HAVE_STDINT_H 1
-#define HAVE_UNISTD_H 1
-#define HAVE_DLFCN_H 1
-#define HAVE_DIRENT_H 1
-#define LTDL_SHLIB_EXT ".so"
-#define LTDL_SHLIBPATH_VAR "LD_LIBRARY_PATH"
-#define LTDL_SYSSEARCHPATH "/usr/lib:/lib:/usr/lib/qt-3.3/lib"
-#define LTDL_OBJDIR ".libs/"
-#define HAVE_PRELOADED_SYMBOLS 1
-#define HAVE_LIBDL 1
-#define HAVE_DLERROR 1
-#define HAVE_ARGZ_H 1
-#define HAVE_ERROR_T 1
-#define HAVE_ARGZ_APPEND 1
-#define HAVE_ARGZ_CREATE_SEP 1
-#define HAVE_ARGZ_INSERT 1
-#define HAVE_ARGZ_NEXT 1
-#define HAVE_ARGZ_STRINGIFY 1
-#define HAVE_ASSERT_H 1
-#define HAVE_CTYPE_H 1
-#define HAVE_ERRNO_H 1
-#define HAVE_MALLOC_H 1
-#define HAVE_MEMORY_H 1
-#define HAVE_STDLIB_H 1
-#define HAVE_STDIO_H 1
-#define HAVE_UNISTD_H 1
-#define HAVE_STRING_H 1
-#define HAVE_STRCHR 1
-#define HAVE_STRRCHR 1
-#define HAVE_MEMCPY 1
-#define HAVE_MEMMOVE 1
-#define HAVE_STRCMP 1
-#define HAVE_CLOSEDIR 1
-#define HAVE_OPENDIR 1
-#define HAVE_READDIR 1
-
-configure: exit 0
diff --git a/libltdl/config.status b/libltdl/config.status
deleted file mode 100755
index c7316a4..0000000
--- a/libltdl/config.status
+++ /dev/null
@@ -1,1118 +0,0 @@
-#! /bin/sh
-# Generated by configure.
-# 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-/bin/sh}
-## --------------------- ##
-## 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`
-"
-
-# Files that config.status was made for.
-config_files=" Makefile"
-config_headers=" config.h:config-h.in"
-config_commands=" depfiles"
-
-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 at gnu.org>."
-
-ac_cs_version="\
-libltdl config.status 1.2
-configured by ./configure, generated by GNU Autoconf 2.61,
-  with options \"\"
-
-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='/home/lennart/projects/pulseaudio/libltdl'
-srcdir='.'
-INSTALL='/usr/bin/install -c'
-MKDIR_P='/bin/mkdir -p'
-# 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
-
-if $ac_cs_recheck; then
-  echo "running CONFIG_SHELL=/bin/sh /bin/sh ./configure " $ac_configure_extra_args " --no-create --no-recursion" >&6
-  CONFIG_SHELL=/bin/sh
-  export CONFIG_SHELL
-  exec /bin/sh "./configure" $ac_configure_extra_args --no-create --no-recursion
-fi
-
-exec 5>>config.log
-{
-  echo
-  sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
-## Running $as_me. ##
-_ASBOX
-  echo "$ac_log"
-} >&5
-
-#
-# INIT-COMMANDS
-#
-AMDEP_TRUE="" ac_aux_dir="."
-
-
-# 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
-
-cat >"$tmp/subs-1.sed" <<\CEOF
-/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
-s, at SHELL@,|#_!!_#|/bin/sh,g
-s, at PATH_SEPARATOR@,|#_!!_#|:,g
-s, at PACKAGE_NAME@,|#_!!_#|libltdl,g
-s, at PACKAGE_TARNAME@,|#_!!_#|libltdl,g
-s, at PACKAGE_VERSION@,|#_!!_#|1.2,g
-s, at PACKAGE_STRING@,|#_!!_#|libltdl 1.2,g
-s, at PACKAGE_BUGREPORT@,|#_!!_#|bug-libtool@|#_!!_#|gnu.org,g
-s, at exec_prefix@,|#_!!_#|${prefix},g
-s, at prefix@,|#_!!_#|/usr/local,g
-s, at program_transform_name@,|#_!!_#|s\,x\,x\,,g
-s, at bindir@,|#_!!_#|${exec_prefix}/bin,g
-s, at sbindir@,|#_!!_#|${exec_prefix}/sbin,g
-s, at libexecdir@,|#_!!_#|${exec_prefix}/libexec,g
-s, at datarootdir@,|#_!!_#|${prefix}/share,g
-s, at datadir@,|#_!!_#|${datarootdir},g
-s, at sysconfdir@,|#_!!_#|${prefix}/etc,g
-s, at sharedstatedir@,|#_!!_#|${prefix}/com,g
-s, at localstatedir@,|#_!!_#|${prefix}/var,g
-s, at includedir@,|#_!!_#|${prefix}/include,g
-s, at oldincludedir@,|#_!!_#|/usr/include,g
-s, at docdir@,|#_!!_#|${datarootdir}/doc/${PACKAGE_TARNAME},g
-s, at infodir@,|#_!!_#|${datarootdir}/info,g
-s, at htmldir@,|#_!!_#|${docdir},g
-s, at dvidir@,|#_!!_#|${docdir},g
-s, at pdfdir@,|#_!!_#|${docdir},g
-s, at psdir@,|#_!!_#|${docdir},g
-s, at libdir@,|#_!!_#|${exec_prefix}/lib,g
-s, at localedir@,|#_!!_#|${datarootdir}/locale,g
-s, at mandir@,|#_!!_#|${datarootdir}/man,g
-s, at DEFS@,|#_!!_#|-DHAVE_CONFIG_H,g
-s, at ECHO_C@,|#_!!_#|,g
-s, at ECHO_N@,|#_!!_#|-n,g
-s, at ECHO_T@,|#_!!_#|,g
-s, at LIBS@,|#_!!_#|,g
-s, at build_alias@,|#_!!_#|,g
-s, at host_alias@,|#_!!_#|,g
-s, at target_alias@,|#_!!_#|,g
-s, at INSTALL_PROGRAM@,|#_!!_#|${INSTALL},g
-s, at INSTALL_SCRIPT@,|#_!!_#|${INSTALL},g
-s, at INSTALL_DATA@,|#_!!_#|${INSTALL} -m 644,g
-s, at am__isrc@,|#_!!_#|,g
-s, at CYGPATH_W@,|#_!!_#|echo,g
-s, at PACKAGE@,|#_!!_#|libltdl,g
-s, at VERSION@,|#_!!_#|1.2,g
-s, at ACLOCAL@,|#_!!_#|${SHELL} /home/lennart/projects/pulseaudio/libltdl/missing --run aclocal-1.10,g
-s, at AUTOCONF@,|#_!!_#|${SHELL} /home/lennart/projects/pulseaudio/libltdl/missing --run autoconf,g
-s, at AUTOMAKE@,|#_!!_#|${SHELL} /home/lennart/projects/pulseaudio/libltdl/missing --run automake-1.10,g
-s, at AUTOHEADER@,|#_!!_#|${SHELL} /home/lennart/projects/pulseaudio/libltdl/missing --run autoheader,g
-s, at MAKEINFO@,|#_!!_#|${SHELL} /home/lennart/projects/pulseaudio/libltdl/missing --run makeinfo,g
-s, at install_sh@,|#_!!_#|$(SHELL) /home/lennart/projects/pulseaudio/libltdl/install-sh,g
-s, at STRIP@,|#_!!_#|strip,g
-s, at INSTALL_STRIP_PROGRAM@,|#_!!_#|$(install_sh) -c -s,g
-s, at mkdir_p@,|#_!!_#|/bin/mkdir -p,g
-s, at AWK@,|#_!!_#|gawk,g
-s, at SET_MAKE@,|#_!!_#|,g
-s, at am__leading_dot@,|#_!!_#|.,g
-s, at AMTAR@,|#_!!_#|${SHELL} /home/lennart/projects/pulseaudio/libltdl/missing --run tar,g
-s, at am__tar@,|#_!!_#|${AMTAR} chof - "$$tardir",g
-s, at am__untar@,|#_!!_#|${AMTAR} xf -,g
-s, at CC@,|#_!!_#|gcc,g
-s, at CFLAGS@,|#_!!_#|-g -O2,g
-s, at LDFLAGS@,|#_!!_#|,g
-s, at CPPFLAGS@,|#_!!_#|,g
-s, at ac_ct_CC@,|#_!!_#|gcc,g
-s, at EXEEXT@,|#_!!_#|,g
-s, at OBJEXT@,|#_!!_#|o,g
-s, at DEPDIR@,|#_!!_#|.deps,g
-s, at am__include@,|#_!!_#|include,g
-s, at am__quote@,|#_!!_#|,g
-s, at AMDEP_TRUE@,|#_!!_#|,g
-s, at AMDEP_FALSE@,|#_!!_#|#,g
-s, at AMDEPBACKSLASH@,|#_!!_#|\\,g
-s, at CCDEPMODE@,|#_!!_#|depmode=none,g
-s, at am__fastdepCC_TRUE@,|#_!!_#|#,g
-s, at am__fastdepCC_FALSE@,|#_!!_#|,g
-s, at build@,|#_!!_#|i686-pc-linux-gnu,g
-s, at build_cpu@,|#_!!_#|i686,g
-s, at build_vendor@,|#_!!_#|pc,g
-s, at build_os@,|#_!!_#|linux-gnu,g
-s, at host@,|#_!!_#|i686-pc-linux-gnu,g
-s, at host_cpu@,|#_!!_#|i686,g
-s, at host_vendor@,|#_!!_#|pc,g
-s, at host_os@,|#_!!_#|linux-gnu,g
-s, at SED@,|#_!!_#|/bin/sed,g
-s, at GREP@,|#_!!_#|/bin/grep,g
-s, at EGREP@,|#_!!_#|/bin/grep -E,g
-s, at LN_S@,|#_!!_#|ln -s,g
-s, at ECHO@,|#_!!_#|echo,g
-s, at AR@,|#_!!_#|ar,g
-s, at RANLIB@,|#_!!_#|ranlib,g
-s, at DLLTOOL@,|#_!!_#|dlltool,g
-s, at AS@,|#_!!_#|as,g
-s, at OBJDUMP@,|#_!!_#|objdump,g
-s, at CPP@,|#_!!_#|gcc -E,g
-s, at CXX@,|#_!!_#|g++,g
-s, at CXXFLAGS@,|#_!!_#|-g -O2,g
-s, at ac_ct_CXX@,|#_!!_#|g++,g
-CEOF
-cat >"$tmp/subs-2.sed" <<\CEOF
-/@[a-zA-Z_][a-zA-Z_0-9]*@/!b end
-s, at CXXDEPMODE@,|#_!!_#|depmode=none,g
-s, at am__fastdepCXX_TRUE@,|#_!!_#|#,g
-s, at am__fastdepCXX_FALSE@,|#_!!_#|,g
-s, at CXXCPP@,|#_!!_#|g++ -E,g
-s, at F77@,|#_!!_#|gfortran,g
-s, at FFLAGS@,|#_!!_#|-g -O2,g
-s, at ac_ct_F77@,|#_!!_#|gfortran,g
-s, at LIBTOOL@,|#_!!_#|$(SHELL) $(top_builddir)/libtool,g
-s, at LIBTOOL_DEPS@,|#_!!_#|./ltmain.sh,g
-s, at INSTALL_LTDL_TRUE@,|#_!!_#|,g
-s, at INSTALL_LTDL_FALSE@,|#_!!_#|#,g
-s, at CONVENIENCE_LTDL_TRUE@,|#_!!_#|#,g
-s, at CONVENIENCE_LTDL_FALSE@,|#_!!_#|,g
-s, at LIBADD_DL@,|#_!!_#|-ldl,g
-s, at LIBOBJS@,|#_!!_#|,g
-s, at LTLIBOBJS@,|#_!!_#|,g
-:end
-s/|#_!!_#|//g
-CEOF
-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
-# 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;}
-  ac_datarootdir_hack='
-  s&@datadir@&${datarootdir}&g
-  s&@docdir@&${datarootdir}/doc/${PACKAGE_TARNAME}&g
-  s&@infodir@&${datarootdir}/info&g
-  s&@localedir@&${datarootdir}/locale&g
-  s&@mandir@&${datarootdir}/man&g
-    s&\${datarootdir}&${prefix}/share&g' ;;
-esac
-  sed "/^[	 ]*VPATH[	 ]*=/{
-s/:*\$(srcdir):*/:/
-s/:*\${srcdir}:*/:/
-s/:*@srcdir@:*/:/
-s/^\([^=]*=[	 ]*\):*/\1/
-s/:*$//
-s/^[^=]*=[	 ]*$//
-}
-
-: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
-  #
-    # First, check the format of the line:
-    cat >"$tmp/defines.sed" <<\CEOF
-/^[	 ]*#[	 ]*undef[	 ][	 ]*[_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ][_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789]*[	 ]*$/b def
-/^[	 ]*#[	 ]*define[	 ][	 ]*[_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ][_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789]*[(	 ]/b def
-b
-:def
-s/$/ /
-s,^\([	 #]*\)[^	 ]*\([	 ]*PACKAGE_NAME\)[	 (].*,\1define\2 "libltdl" ,
-s,^\([	 #]*\)[^	 ]*\([	 ]*PACKAGE_TARNAME\)[	 (].*,\1define\2 "libltdl" ,
-s,^\([	 #]*\)[^	 ]*\([	 ]*PACKAGE_VERSION\)[	 (].*,\1define\2 "1.2" ,
-s,^\([	 #]*\)[^	 ]*\([	 ]*PACKAGE_STRING\)[	 (].*,\1define\2 "libltdl 1.2" ,
-s,^\([	 #]*\)[^	 ]*\([	 ]*PACKAGE_BUGREPORT\)[	 (].*,\1define\2 "bug-libtool at gnu.org" ,
-s,^\([	 #]*\)[^	 ]*\([	 ]*STDC_HEADERS\)[	 (].*,\1define\2 1 ,
-s,^\([	 #]*\)[^	 ]*\([	 ]*HAVE_SYS_TYPES_H\)[	 (].*,\1define\2 1 ,
-s,^\([	 #]*\)[^	 ]*\([	 ]*HAVE_SYS_STAT_H\)[	 (].*,\1define\2 1 ,
-s,^\([	 #]*\)[^	 ]*\([	 ]*HAVE_STDLIB_H\)[	 (].*,\1define\2 1 ,
-s,^\([	 #]*\)[^	 ]*\([	 ]*HAVE_STRING_H\)[	 (].*,\1define\2 1 ,
-s,^\([	 #]*\)[^	 ]*\([	 ]*HAVE_MEMORY_H\)[	 (].*,\1define\2 1 ,
-s,^\([	 #]*\)[^	 ]*\([	 ]*HAVE_STRINGS_H\)[	 (].*,\1define\2 1 ,
-s,^\([	 #]*\)[^	 ]*\([	 ]*HAVE_INTTYPES_H\)[	 (].*,\1define\2 1 ,
-s,^\([	 #]*\)[^	 ]*\([	 ]*HAVE_STDINT_H\)[	 (].*,\1define\2 1 ,
-s,^\([	 #]*\)[^	 ]*\([	 ]*HAVE_UNISTD_H\)[	 (].*,\1define\2 1 ,
-s,^\([	 #]*\)[^	 ]*\([	 ]*HAVE_DLFCN_H\)[	 (].*,\1define\2 1 ,
-s,^\([	 #]*\)[^	 ]*\([	 ]*HAVE_DIRENT_H\)[	 (].*,\1define\2 1 ,
-s,^\([	 #]*\)[^	 ]*\([	 ]*LTDL_SHLIB_EXT\)[	 (].*,\1define\2 ".so" ,
-s,^\([	 #]*\)[^	 ]*\([	 ]*LTDL_SHLIBPATH_VAR\)[	 (].*,\1define\2 "LD_LIBRARY_PATH" ,
-s,^\([	 #]*\)[^	 ]*\([	 ]*LTDL_SYSSEARCHPATH\)[	 (].*,\1define\2 "/usr/lib:/lib:/usr/lib/qt-3.3/lib" ,
-s,^\([	 #]*\)[^	 ]*\([	 ]*LTDL_OBJDIR\)[	 (].*,\1define\2 ".libs/" ,
-s,^\([	 #]*\)[^	 ]*\([	 ]*HAVE_PRELOADED_SYMBOLS\)[	 (].*,\1define\2 1 ,
-s,^\([	 #]*\)[^	 ]*\([	 ]*HAVE_LIBDL\)[	 (].*,\1define\2 1 ,
-s,^\([	 #]*\)[^	 ]*\([	 ]*HAVE_DLERROR\)[	 (].*,\1define\2 1 ,
-s,^\([	 #]*\)[^	 ]*\([	 ]*HAVE_ARGZ_H\)[	 (].*,\1define\2 1 ,
-s,^\([	 #]*\)[^	 ]*\([	 ]*HAVE_ERROR_T\)[	 (].*,\1define\2 1 ,
-s,^\([	 #]*\)[^	 ]*\([	 ]*HAVE_ARGZ_APPEND\)[	 (].*,\1define\2 1 ,
-s,^\([	 #]*\)[^	 ]*\([	 ]*HAVE_ARGZ_CREATE_SEP\)[	 (].*,\1define\2 1 ,
-s,^\([	 #]*\)[^	 ]*\([	 ]*HAVE_ARGZ_INSERT\)[	 (].*,\1define\2 1 ,
-s,^\([	 #]*\)[^	 ]*\([	 ]*HAVE_ARGZ_NEXT\)[	 (].*,\1define\2 1 ,
-s,^\([	 #]*\)[^	 ]*\([	 ]*HAVE_ARGZ_STRINGIFY\)[	 (].*,\1define\2 1 ,
-s,^\([	 #]*\)[^	 ]*\([	 ]*HAVE_ASSERT_H\)[	 (].*,\1define\2 1 ,
-s,^\([	 #]*\)[^	 ]*\([	 ]*HAVE_CTYPE_H\)[	 (].*,\1define\2 1 ,
-s,^\([	 #]*\)[^	 ]*\([	 ]*HAVE_ERRNO_H\)[	 (].*,\1define\2 1 ,
-s,^\([	 #]*\)[^	 ]*\([	 ]*HAVE_MALLOC_H\)[	 (].*,\1define\2 1 ,
-s,^\([	 #]*\)[^	 ]*\([	 ]*HAVE_MEMORY_H\)[	 (].*,\1define\2 1 ,
-s,^\([	 #]*\)[^	 ]*\([	 ]*HAVE_STDLIB_H\)[	 (].*,\1define\2 1 ,
-s,^\([	 #]*\)[^	 ]*\([	 ]*HAVE_STDIO_H\)[	 (].*,\1define\2 1 ,
-s,^\([	 #]*\)[^	 ]*\([	 ]*HAVE_UNISTD_H\)[	 (].*,\1define\2 1 ,
-s,^\([	 #]*\)[^	 ]*\([	 ]*HAVE_STRING_H\)[	 (].*,\1define\2 1 ,
-s,^\([	 #]*\)[^	 ]*\([	 ]*HAVE_STRCHR\)[	 (].*,\1define\2 1 ,
-s,^\([	 #]*\)[^	 ]*\([	 ]*HAVE_STRRCHR\)[	 (].*,\1define\2 1 ,
-s,^\([	 #]*\)[^	 ]*\([	 ]*HAVE_MEMCPY\)[	 (].*,\1define\2 1 ,
-s,^\([	 #]*\)[^	 ]*\([	 ]*HAVE_MEMMOVE\)[	 (].*,\1define\2 1 ,
-s,^\([	 #]*\)[^	 ]*\([	 ]*HAVE_STRCMP\)[	 (].*,\1define\2 1 ,
-s,^\([	 #]*\)[^	 ]*\([	 ]*HAVE_CLOSEDIR\)[	 (].*,\1define\2 1 ,
-s,^\([	 #]*\)[^	 ]*\([	 ]*HAVE_OPENDIR\)[	 (].*,\1define\2 1 ,
-s,^\([	 #]*\)[^	 ]*\([	 ]*HAVE_READDIR\)[	 (].*,\1define\2 1 ,
-s/ $//
-CEOF
-    sed -f "$tmp/defines.sed" $ac_file_inputs >"$tmp/out1"
-    # First, check the format of the line:
-    cat >"$tmp/defines.sed" <<\CEOF
-/^[	 ]*#[	 ]*undef[	 ][	 ]*[_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ][_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789]*[	 ]*$/b def
-/^[	 ]*#[	 ]*define[	 ][	 ]*[_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ][_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789]*[(	 ]/b def
-b
-:def
-s,^[	 #]*u.*,/* & */,
-CEOF
-    sed -f "$tmp/defines.sed" "$tmp/out1" >"$tmp/out2"
-ac_result="$tmp/out2"
-  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; }
diff --git a/libltdl/libtool b/libltdl/libtool
deleted file mode 100755
index 2413813..0000000
--- a/libltdl/libtool
+++ /dev/null
@@ -1,7895 +0,0 @@
-#! /bin/sh
-
-# libtoolT - Provide generalized library-building support services.
-# Generated automatically by  (GNU libltdl 1.2)
-# 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 at 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="/bin/sed"
-
-# Sed that helps us avoid accidentally triggering echo(1) options like -n.
-Xsed="/bin/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=" CXX F77"
-
-# ### BEGIN LIBTOOL CONFIG
-
-# Libtool was configured on host lambda:
-
-# Shell to use when invoking shell scripts.
-SHELL="/bin/sh"
-
-# Whether or not to build shared libraries.
-build_libtool_libs=yes
-
-# Whether or not to build static libraries.
-build_old_libs=yes
-
-# Whether or not to add -lc for building shared libraries.
-build_libtool_need_lc=no
-
-# Whether or not to disallow shared libs when runtime libs are static
-allow_libtool_libs_with_static_runtimes=no
-
-# Whether or not to optimize for fast installation.
-fast_install=yes
-
-# The host system.
-host_alias=
-host=i686-pc-linux-gnu
-host_os=linux-gnu
-
-# The build system.
-build_alias=
-build=i686-pc-linux-gnu
-build_os=linux-gnu
-
-# An echo program that does not interpret backslashes.
-echo="echo"
-
-# The archiver.
-AR="ar"
-AR_FLAGS="cru"
-
-# A C compiler.
-LTCC="gcc"
-
-# LTCC compiler flags.
-LTCFLAGS="-g -O2"
-
-# A language-specific compiler.
-CC="gcc"
-
-# Is the compiler the GNU C compiler?
-with_gcc=yes
-
-# An ERE matcher.
-EGREP="/bin/grep -E"
-
-# The linker used to build libraries.
-LD="/usr/bin/ld"
-
-# Whether we need hard or soft links.
-LN_S="ln -s"
-
-# A BSD-compatible nm program.
-NM="/usr/bin/nm -B"
-
-# A symbol stripping program
-STRIP="strip"
-
-# Used to examine libraries when file_magic_cmd begins "file"
-MAGIC_CMD=file
-
-# 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=.libs
-
-# How to create reloadable object files.
-reload_flag=" -r"
-reload_cmds="\$LD\$reload_flag -o \$output\$reload_objs"
-
-# How to pass a linker flag through the compiler.
-wl="-Wl,"
-
-# Object file suffix (normally "o").
-objext="o"
-
-# Old archive suffix (normally "a").
-libext="a"
-
-# Shared library suffix (normally ".so").
-shrext_cmds='.so'
-
-# Executable file suffix (normally "").
-exeext=""
-
-# Additional compiler flags for building library objects.
-pic_flag=" -fPIC -DPIC"
-pic_mode=default
-
-# What is the maximum length of a command?
-max_cmd_len=98304
-
-# Does compiler simultaneously support -c and -o options?
-compiler_c_o="yes"
-
-# Must we lock files when doing compilation?
-need_locks="no"
-
-# Do we need the lib prefix for modules?
-need_lib_prefix=no
-
-# Do we need a version for libraries?
-need_version=no
-
-# Whether dlopen is supported.
-dlopen_support=unknown
-
-# Whether dlopen of programs is supported.
-dlopen_self=unknown
-
-# Whether dlopen of statically linked programs is supported.
-dlopen_self_static=unknown
-
-# Compiler flag to prevent dynamic linking.
-link_static_flag="-static"
-
-# Compiler flag to turn off builtin functions.
-no_builtin_flag=" -fno-builtin"
-
-# Compiler flag to allow reflexive dlopens.
-export_dynamic_flag_spec="\${wl}--export-dynamic"
-
-# Compiler flag to generate shared objects directly from archives.
-whole_archive_flag_spec="\${wl}--whole-archive\$convenience \${wl}--no-whole-archive"
-
-# Compiler flag to generate thread-safe objects.
-thread_safe_flag_spec=""
-
-# Library versioning type.
-version_type=linux
-
-# Format of library name prefix.
-libname_spec="lib\$name"
-
-# 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="\${libname}\${release}\${shared_ext}\$versuffix \${libname}\${release}\${shared_ext}\$major \$libname\${shared_ext}"
-
-# The coded name of the library, if different from the real name.
-soname_spec="\${libname}\${release}\${shared_ext}\$major"
-
-# Commands used to build and install an old-style archive.
-RANLIB="ranlib"
-old_archive_cmds="\$AR \$AR_FLAGS \$oldlib\$oldobjs~\$RANLIB \$oldlib"
-old_postinstall_cmds="chmod 644 \$oldlib~\$RANLIB \$oldlib"
-old_postuninstall_cmds=""
-
-# Create an old-style archive from a shared archive.
-old_archive_from_new_cmds=""
-
-# Create a temporary old-style archive to link instead of a shared archive.
-old_archive_from_expsyms_cmds=""
-
-# Commands used to build and install a shared archive.
-archive_cmds="\$CC -shared \$libobjs \$deplibs \$compiler_flags \${wl}-soname \$wl\$soname -o \$lib"
-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 -shared \$libobjs \$deplibs \$compiler_flags \${wl}-soname \$wl\$soname \${wl}-version-script \${wl}\$output_objdir/\$libname.ver -o \$lib"
-postinstall_cmds=""
-postuninstall_cmds=""
-
-# Commands used to build a loadable module (assumed same as above if empty)
-module_cmds=""
-module_expsym_cmds=""
-
-# Commands to strip libraries.
-old_striplib="strip --strip-debug"
-striplib="strip --strip-unneeded"
-
-# Dependencies to place before the objects being linked to create a
-# shared library.
-predep_objects=""
-
-# Dependencies to place after the objects being linked to create a
-# shared library.
-postdep_objects=""
-
-# Dependencies to place before the objects being linked to create a
-# shared library.
-predeps=""
-
-# Dependencies to place after the objects being linked to create a
-# shared library.
-postdeps=""
-
-# The library search path used internally by the compiler when linking
-# a shared library.
-compiler_lib_search_path=""
-
-# Method to check whether dependent libraries are shared objects.
-deplibs_check_method="pass_all"
-
-# Command to use when deplibs_check_method == file_magic.
-file_magic_cmd="\$MAGIC_CMD"
-
-# Flag that allows shared libraries with undefined symbols to be built.
-allow_undefined_flag=""
-
-# Flag that forces no undefined symbols.
-no_undefined_flag=""
-
-# Commands used to finish a libtool library installation in a directory.
-finish_cmds="PATH=\\\"\\\$PATH:/sbin\\\" ldconfig -n \$libdir"
-
-# Same as above, but a single script fragment to be evaled but not shown.
-finish_eval=""
-
-# Take the output of nm and produce a listing of raw symbols and C names.
-global_symbol_pipe="sed -n -e 's/^.*[ 	]\\([ABCDGIRSTW][ABCDGIRSTW]*\\)[ 	][ 	]*\\([_A-Za-z][_A-Za-z0-9]*\\)\$/\\1 \\2 \\2/p'"
-
-# Transform the output of nm in a proper C declaration
-global_symbol_to_cdecl="sed -n -e 's/^. .* \\(.*\\)\$/extern int \\1;/p'"
-
-# Transform the output of nm in a C name address pair
-global_symbol_to_c_name_address="sed -n -e 's/^: \\([^ ]*\\) \$/  {\\\"\\1\\\", (lt_ptr) 0},/p' -e 's/^[BCDEGRST] \\([^ ]*\\) \\([^ ]*\\)\$/  {\"\\2\", (lt_ptr) \\&\\2},/p'"
-
-# This is the shared library runtime path variable.
-runpath_var=LD_RUN_PATH
-
-# This is the shared library path variable.
-shlibpath_var=LD_LIBRARY_PATH
-
-# Is shlibpath searched before the hard-coded library search path?
-shlibpath_overrides_runpath=no
-
-# How to hardcode a shared library path into an executable.
-hardcode_action=immediate
-
-# Whether we should hardcode library paths into libraries.
-hardcode_into_libs=yes
-
-# Flag to hardcode $libdir into a binary during linking.
-# This must work even if $libdir does not exist.
-hardcode_libdir_flag_spec="\${wl}--rpath \${wl}\$libdir"
-
-# 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=""
-
-# Whether we need a single -rpath flag with a separated argument.
-hardcode_libdir_separator=""
-
-# Set to yes if using DIR/libNAME during linking hardcodes DIR into the
-# resulting binary.
-hardcode_direct=no
-
-# Set to yes if using the -LDIR flag during linking hardcodes DIR into the
-# resulting binary.
-hardcode_minus_L=no
-
-# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into
-# the resulting binary.
-hardcode_shlibpath_var=unsupported
-
-# 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=no
-
-# Variables whose values should be saved in libtool wrapper scripts and
-# restored at relink time.
-variables_saved_for_relink="PATH LD_LIBRARY_PATH LD_RUN_PATH GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH"
-
-# Whether libtool must link a program against all its dependency libraries.
-link_all_deplibs=unknown
-
-# Compile-time system search path for libraries
-sys_lib_search_path_spec="/usr/lib /lib /usr/local/lib"
-
-# Run-time system search path for libraries
-sys_lib_dlsearch_path_spec="/usr/lib /lib /usr/lib/qt-3.3/lib "
-
-# Fix the shell variable $srcfile for the compiler.
-fix_srcfile_path=""
-
-# Set to yes if exported symbols are required.
-always_export_symbols=no
-
-# The commands to list exported symbols.
-export_symbols_cmds="\$NM \$libobjs \$convenience | \$global_symbol_pipe | \$SED 's/.* //' | sort | uniq > \$export_symbols"
-
-# The commands to extract the exported symbol list from a shared archive.
-extract_expsyms_cmds=""
-
-# Symbols that should not be listed in the preloaded symbols.
-exclude_expsyms="_GLOBAL_OFFSET_TABLE_"
-
-# Symbols that must always be exported.
-include_expsyms=""
-
-# ### END LIBTOOL CONFIG
-
-# 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 at 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
-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% $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
-	    ;;
-	  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 at 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:
-# ### BEGIN LIBTOOL TAG CONFIG: CXX
-
-# Libtool was configured on host lambda:
-
-# Shell to use when invoking shell scripts.
-SHELL="/bin/sh"
-
-# Whether or not to build shared libraries.
-build_libtool_libs=yes
-
-# Whether or not to build static libraries.
-build_old_libs=yes
-
-# Whether or not to add -lc for building shared libraries.
-build_libtool_need_lc=no
-
-# Whether or not to disallow shared libs when runtime libs are static
-allow_libtool_libs_with_static_runtimes=no
-
-# Whether or not to optimize for fast installation.
-fast_install=yes
-
-# The host system.
-host_alias=
-host=i686-pc-linux-gnu
-host_os=linux-gnu
-
-# The build system.
-build_alias=
-build=i686-pc-linux-gnu
-build_os=linux-gnu
-
-# An echo program that does not interpret backslashes.
-echo="echo"
-
-# The archiver.
-AR="ar"
-AR_FLAGS="cru"
-
-# A C compiler.
-LTCC="gcc"
-
-# LTCC compiler flags.
-LTCFLAGS="-g -O2"
-
-# A language-specific compiler.
-CC="g++"
-
-# Is the compiler the GNU C compiler?
-with_gcc=yes
-
-# An ERE matcher.
-EGREP="/bin/grep -E"
-
-# The linker used to build libraries.
-LD="/usr/bin/ld"
-
-# Whether we need hard or soft links.
-LN_S="ln -s"
-
-# A BSD-compatible nm program.
-NM="/usr/bin/nm -B"
-
-# A symbol stripping program
-STRIP="strip"
-
-# Used to examine libraries when file_magic_cmd begins "file"
-MAGIC_CMD=file
-
-# 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=.libs
-
-# How to create reloadable object files.
-reload_flag=" -r"
-reload_cmds="\$LD\$reload_flag -o \$output\$reload_objs"
-
-# How to pass a linker flag through the compiler.
-wl="-Wl,"
-
-# Object file suffix (normally "o").
-objext="o"
-
-# Old archive suffix (normally "a").
-libext="a"
-
-# Shared library suffix (normally ".so").
-shrext_cmds='.so'
-
-# Executable file suffix (normally "").
-exeext=""
-
-# Additional compiler flags for building library objects.
-pic_flag=" -fPIC -DPIC"
-pic_mode=default
-
-# What is the maximum length of a command?
-max_cmd_len=98304
-
-# Does compiler simultaneously support -c and -o options?
-compiler_c_o="yes"
-
-# Must we lock files when doing compilation?
-need_locks="no"
-
-# Do we need the lib prefix for modules?
-need_lib_prefix=no
-
-# Do we need a version for libraries?
-need_version=no
-
-# Whether dlopen is supported.
-dlopen_support=unknown
-
-# Whether dlopen of programs is supported.
-dlopen_self=unknown
-
-# Whether dlopen of statically linked programs is supported.
-dlopen_self_static=unknown
-
-# Compiler flag to prevent dynamic linking.
-link_static_flag="-static"
-
-# Compiler flag to turn off builtin functions.
-no_builtin_flag=" -fno-builtin"
-
-# Compiler flag to allow reflexive dlopens.
-export_dynamic_flag_spec="\${wl}--export-dynamic"
-
-# Compiler flag to generate shared objects directly from archives.
-whole_archive_flag_spec="\${wl}--whole-archive\$convenience \${wl}--no-whole-archive"
-
-# Compiler flag to generate thread-safe objects.
-thread_safe_flag_spec=""
-
-# Library versioning type.
-version_type=linux
-
-# Format of library name prefix.
-libname_spec="lib\$name"
-
-# 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="\${libname}\${release}\${shared_ext}\$versuffix \${libname}\${release}\${shared_ext}\$major \$libname\${shared_ext}"
-
-# The coded name of the library, if different from the real name.
-soname_spec="\${libname}\${release}\${shared_ext}\$major"
-
-# Commands used to build and install an old-style archive.
-RANLIB="ranlib"
-old_archive_cmds="\$AR \$AR_FLAGS \$oldlib\$oldobjs~\$RANLIB \$oldlib"
-old_postinstall_cmds="chmod 644 \$oldlib~\$RANLIB \$oldlib"
-old_postuninstall_cmds=""
-
-# Create an old-style archive from a shared archive.
-old_archive_from_new_cmds=""
-
-# Create a temporary old-style archive to link instead of a shared archive.
-old_archive_from_expsyms_cmds=""
-
-# Commands used to build and install a shared archive.
-archive_cmds="\$CC -shared -nostdlib \$predep_objects \$libobjs \$deplibs \$postdep_objects \$compiler_flags \${wl}-soname \$wl\$soname -o \$lib"
-archive_expsym_cmds="\$CC -shared -nostdlib \$predep_objects \$libobjs \$deplibs \$postdep_objects \$compiler_flags \${wl}-soname \$wl\$soname \${wl}-retain-symbols-file \$wl\$export_symbols -o \$lib"
-postinstall_cmds=""
-postuninstall_cmds=""
-
-# Commands used to build a loadable module (assumed same as above if empty)
-module_cmds=""
-module_expsym_cmds=""
-
-# Commands to strip libraries.
-old_striplib="strip --strip-debug"
-striplib="strip --strip-unneeded"
-
-# Dependencies to place before the objects being linked to create a
-# shared library.
-predep_objects="/usr/lib/gcc/i386-redhat-linux/4.1.2/../../../crti.o /usr/lib/gcc/i386-redhat-linux/4.1.2/crtbeginS.o"
-
-# Dependencies to place after the objects being linked to create a
-# shared library.
-postdep_objects="/usr/lib/gcc/i386-redhat-linux/4.1.2/crtendS.o /usr/lib/gcc/i386-redhat-linux/4.1.2/../../../crtn.o"
-
-# Dependencies to place before the objects being linked to create a
-# shared library.
-predeps=""
-
-# Dependencies to place after the objects being linked to create a
-# shared library.
-postdeps="-lstdc++ -lm -lgcc_s -lc -lgcc_s"
-
-# The library search path used internally by the compiler when linking
-# a shared library.
-compiler_lib_search_path="-L/usr/lib/gcc/i386-redhat-linux/4.1.2 -L/usr/lib/gcc/i386-redhat-linux/4.1.2 -L/usr/lib/gcc/i386-redhat-linux/4.1.2/../../.."
-
-# Method to check whether dependent libraries are shared objects.
-deplibs_check_method="pass_all"
-
-# Command to use when deplibs_check_method == file_magic.
-file_magic_cmd="\$MAGIC_CMD"
-
-# Flag that allows shared libraries with undefined symbols to be built.
-allow_undefined_flag=""
-
-# Flag that forces no undefined symbols.
-no_undefined_flag=""
-
-# Commands used to finish a libtool library installation in a directory.
-finish_cmds="PATH=\\\"\\\$PATH:/sbin\\\" ldconfig -n \$libdir"
-
-# Same as above, but a single script fragment to be evaled but not shown.
-finish_eval=""
-
-# Take the output of nm and produce a listing of raw symbols and C names.
-global_symbol_pipe="sed -n -e 's/^.*[ 	]\\([ABCDGIRSTW][ABCDGIRSTW]*\\)[ 	][ 	]*\\([_A-Za-z][_A-Za-z0-9]*\\)\$/\\1 \\2 \\2/p'"
-
-# Transform the output of nm in a proper C declaration
-global_symbol_to_cdecl="sed -n -e 's/^. .* \\(.*\\)\$/extern int \\1;/p'"
-
-# Transform the output of nm in a C name address pair
-global_symbol_to_c_name_address="sed -n -e 's/^: \\([^ ]*\\) \$/  {\\\"\\1\\\", (lt_ptr) 0},/p' -e 's/^[BCDEGRST] \\([^ ]*\\) \\([^ ]*\\)\$/  {\"\\2\", (lt_ptr) \\&\\2},/p'"
-
-# This is the shared library runtime path variable.
-runpath_var=LD_RUN_PATH
-
-# This is the shared library path variable.
-shlibpath_var=LD_LIBRARY_PATH
-
-# Is shlibpath searched before the hard-coded library search path?
-shlibpath_overrides_runpath=no
-
-# How to hardcode a shared library path into an executable.
-hardcode_action=immediate
-
-# Whether we should hardcode library paths into libraries.
-hardcode_into_libs=yes
-
-# Flag to hardcode $libdir into a binary during linking.
-# This must work even if $libdir does not exist.
-hardcode_libdir_flag_spec="\${wl}--rpath \${wl}\$libdir"
-
-# 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=""
-
-# Whether we need a single -rpath flag with a separated argument.
-hardcode_libdir_separator=""
-
-# Set to yes if using DIR/libNAME during linking hardcodes DIR into the
-# resulting binary.
-hardcode_direct=no
-
-# Set to yes if using the -LDIR flag during linking hardcodes DIR into the
-# resulting binary.
-hardcode_minus_L=no
-
-# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into
-# the resulting binary.
-hardcode_shlibpath_var=unsupported
-
-# 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=no
-
-# Variables whose values should be saved in libtool wrapper scripts and
-# restored at relink time.
-variables_saved_for_relink="PATH LD_LIBRARY_PATH LD_RUN_PATH GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH"
-
-# Whether libtool must link a program against all its dependency libraries.
-link_all_deplibs=unknown
-
-# Compile-time system search path for libraries
-sys_lib_search_path_spec="/usr/lib /lib /usr/local/lib"
-
-# Run-time system search path for libraries
-sys_lib_dlsearch_path_spec="/usr/lib /lib /usr/lib/qt-3.3/lib "
-
-# Fix the shell variable $srcfile for the compiler.
-fix_srcfile_path=""
-
-# Set to yes if exported symbols are required.
-always_export_symbols=no
-
-# The commands to list exported symbols.
-export_symbols_cmds="\$NM \$libobjs \$convenience | \$global_symbol_pipe | \$SED 's/.* //' | sort | uniq > \$export_symbols"
-
-# The commands to extract the exported symbol list from a shared archive.
-extract_expsyms_cmds=""
-
-# Symbols that should not be listed in the preloaded symbols.
-exclude_expsyms=""
-
-# Symbols that must always be exported.
-include_expsyms=""
-
-# ### END LIBTOOL TAG CONFIG: CXX
-
-# ### BEGIN LIBTOOL TAG CONFIG: F77
-
-# Libtool was configured on host lambda:
-
-# Shell to use when invoking shell scripts.
-SHELL="/bin/sh"
-
-# Whether or not to build shared libraries.
-build_libtool_libs=yes
-
-# Whether or not to build static libraries.
-build_old_libs=yes
-
-# Whether or not to add -lc for building shared libraries.
-build_libtool_need_lc=no
-
-# Whether or not to disallow shared libs when runtime libs are static
-allow_libtool_libs_with_static_runtimes=no
-
-# Whether or not to optimize for fast installation.
-fast_install=yes
-
-# The host system.
-host_alias=
-host=i686-pc-linux-gnu
-host_os=linux-gnu
-
-# The build system.
-build_alias=
-build=i686-pc-linux-gnu
-build_os=linux-gnu
-
-# An echo program that does not interpret backslashes.
-echo="echo"
-
-# The archiver.
-AR="ar"
-AR_FLAGS="cru"
-
-# A C compiler.
-LTCC="gcc"
-
-# LTCC compiler flags.
-LTCFLAGS="-g -O2"
-
-# A language-specific compiler.
-CC="gfortran"
-
-# Is the compiler the GNU C compiler?
-with_gcc=yes
-
-# An ERE matcher.
-EGREP="/bin/grep -E"
-
-# The linker used to build libraries.
-LD="/usr/bin/ld"
-
-# Whether we need hard or soft links.
-LN_S="ln -s"
-
-# A BSD-compatible nm program.
-NM="/usr/bin/nm -B"
-
-# A symbol stripping program
-STRIP="strip"
-
-# Used to examine libraries when file_magic_cmd begins "file"
-MAGIC_CMD=file
-
-# 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=.libs
-
-# How to create reloadable object files.
-reload_flag=" -r"
-reload_cmds="\$LD\$reload_flag -o \$output\$reload_objs"
-
-# How to pass a linker flag through the compiler.
-wl="-Wl,"
-
-# Object file suffix (normally "o").
-objext="o"
-
-# Old archive suffix (normally "a").
-libext="a"
-
-# Shared library suffix (normally ".so").
-shrext_cmds='.so'
-
-# Executable file suffix (normally "").
-exeext=""
-
-# Additional compiler flags for building library objects.
-pic_flag=" -fPIC"
-pic_mode=default
-
-# What is the maximum length of a command?
-max_cmd_len=98304
-
-# Does compiler simultaneously support -c and -o options?
-compiler_c_o="yes"
-
-# Must we lock files when doing compilation?
-need_locks="no"
-
-# Do we need the lib prefix for modules?
-need_lib_prefix=no
-
-# Do we need a version for libraries?
-need_version=no
-
-# Whether dlopen is supported.
-dlopen_support=unknown
-
-# Whether dlopen of programs is supported.
-dlopen_self=unknown
-
-# Whether dlopen of statically linked programs is supported.
-dlopen_self_static=unknown
-
-# Compiler flag to prevent dynamic linking.
-link_static_flag="-static"
-
-# Compiler flag to turn off builtin functions.
-no_builtin_flag=""
-
-# Compiler flag to allow reflexive dlopens.
-export_dynamic_flag_spec="\${wl}--export-dynamic"
-
-# Compiler flag to generate shared objects directly from archives.
-whole_archive_flag_spec="\${wl}--whole-archive\$convenience \${wl}--no-whole-archive"
-
-# Compiler flag to generate thread-safe objects.
-thread_safe_flag_spec=""
-
-# Library versioning type.
-version_type=linux
-
-# Format of library name prefix.
-libname_spec="lib\$name"
-
-# 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="\${libname}\${release}\${shared_ext}\$versuffix \${libname}\${release}\${shared_ext}\$major \$libname\${shared_ext}"
-
-# The coded name of the library, if different from the real name.
-soname_spec="\${libname}\${release}\${shared_ext}\$major"
-
-# Commands used to build and install an old-style archive.
-RANLIB="ranlib"
-old_archive_cmds="\$AR \$AR_FLAGS \$oldlib\$oldobjs~\$RANLIB \$oldlib"
-old_postinstall_cmds="chmod 644 \$oldlib~\$RANLIB \$oldlib"
-old_postuninstall_cmds=""
-
-# Create an old-style archive from a shared archive.
-old_archive_from_new_cmds=""
-
-# Create a temporary old-style archive to link instead of a shared archive.
-old_archive_from_expsyms_cmds=""
-
-# Commands used to build and install a shared archive.
-archive_cmds="\$CC -shared \$libobjs \$deplibs \$compiler_flags \${wl}-soname \$wl\$soname -o \$lib"
-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 -shared \$libobjs \$deplibs \$compiler_flags \${wl}-soname \$wl\$soname \${wl}-version-script \${wl}\$output_objdir/\$libname.ver -o \$lib"
-postinstall_cmds=""
-postuninstall_cmds=""
-
-# Commands used to build a loadable module (assumed same as above if empty)
-module_cmds=""
-module_expsym_cmds=""
-
-# Commands to strip libraries.
-old_striplib="strip --strip-debug"
-striplib="strip --strip-unneeded"
-
-# Dependencies to place before the objects being linked to create a
-# shared library.
-predep_objects=""
-
-# Dependencies to place after the objects being linked to create a
-# shared library.
-postdep_objects=""
-
-# Dependencies to place before the objects being linked to create a
-# shared library.
-predeps=""
-
-# Dependencies to place after the objects being linked to create a
-# shared library.
-postdeps=""
-
-# The library search path used internally by the compiler when linking
-# a shared library.
-compiler_lib_search_path=""
-
-# Method to check whether dependent libraries are shared objects.
-deplibs_check_method="pass_all"
-
-# Command to use when deplibs_check_method == file_magic.
-file_magic_cmd="\$MAGIC_CMD"
-
-# Flag that allows shared libraries with undefined symbols to be built.
-allow_undefined_flag=""
-
-# Flag that forces no undefined symbols.
-no_undefined_flag=""
-
-# Commands used to finish a libtool library installation in a directory.
-finish_cmds="PATH=\\\"\\\$PATH:/sbin\\\" ldconfig -n \$libdir"
-
-# Same as above, but a single script fragment to be evaled but not shown.
-finish_eval=""
-
-# Take the output of nm and produce a listing of raw symbols and C names.
-global_symbol_pipe="sed -n -e 's/^.*[ 	]\\([ABCDGIRSTW][ABCDGIRSTW]*\\)[ 	][ 	]*\\([_A-Za-z][_A-Za-z0-9]*\\)\$/\\1 \\2 \\2/p'"
-
-# Transform the output of nm in a proper C declaration
-global_symbol_to_cdecl="sed -n -e 's/^. .* \\(.*\\)\$/extern int \\1;/p'"
-
-# Transform the output of nm in a C name address pair
-global_symbol_to_c_name_address="sed -n -e 's/^: \\([^ ]*\\) \$/  {\\\"\\1\\\", (lt_ptr) 0},/p' -e 's/^[BCDEGRST] \\([^ ]*\\) \\([^ ]*\\)\$/  {\"\\2\", (lt_ptr) \\&\\2},/p'"
-
-# This is the shared library runtime path variable.
-runpath_var=LD_RUN_PATH
-
-# This is the shared library path variable.
-shlibpath_var=LD_LIBRARY_PATH
-
-# Is shlibpath searched before the hard-coded library search path?
-shlibpath_overrides_runpath=no
-
-# How to hardcode a shared library path into an executable.
-hardcode_action=immediate
-
-# Whether we should hardcode library paths into libraries.
-hardcode_into_libs=yes
-
-# Flag to hardcode $libdir into a binary during linking.
-# This must work even if $libdir does not exist.
-hardcode_libdir_flag_spec="\${wl}--rpath \${wl}\$libdir"
-
-# 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=""
-
-# Whether we need a single -rpath flag with a separated argument.
-hardcode_libdir_separator=""
-
-# Set to yes if using DIR/libNAME during linking hardcodes DIR into the
-# resulting binary.
-hardcode_direct=no
-
-# Set to yes if using the -LDIR flag during linking hardcodes DIR into the
-# resulting binary.
-hardcode_minus_L=no
-
-# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into
-# the resulting binary.
-hardcode_shlibpath_var=unsupported
-
-# 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=no
-
-# Variables whose values should be saved in libtool wrapper scripts and
-# restored at relink time.
-variables_saved_for_relink="PATH LD_LIBRARY_PATH LD_RUN_PATH GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH"
-
-# Whether libtool must link a program against all its dependency libraries.
-link_all_deplibs=unknown
-
-# Compile-time system search path for libraries
-sys_lib_search_path_spec="/usr/lib /lib /usr/local/lib"
-
-# Run-time system search path for libraries
-sys_lib_dlsearch_path_spec="/usr/lib /lib /usr/lib/qt-3.3/lib "
-
-# Fix the shell variable $srcfile for the compiler.
-fix_srcfile_path=""
-
-# Set to yes if exported symbols are required.
-always_export_symbols=no
-
-# The commands to list exported symbols.
-export_symbols_cmds="\$NM \$libobjs \$convenience | \$global_symbol_pipe | \$SED 's/.* //' | sort | uniq > \$export_symbols"
-
-# The commands to extract the exported symbol list from a shared archive.
-extract_expsyms_cmds=""
-
-# Symbols that should not be listed in the preloaded symbols.
-exclude_expsyms="_GLOBAL_OFFSET_TABLE_"
-
-# Symbols that must always be exported.
-include_expsyms=""
-
-# ### END LIBTOOL TAG CONFIG: F77
-
diff --git a/src/Makefile.am b/src/Makefile.am
index a10fe73..aa5160a 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -667,6 +667,7 @@ libpulsecore_la_SOURCES += \
 		pulsecore/fdsem.c pulsecore/fdsem.h \
 		pulsecore/object.c pulsecore/object.h \
 		pulsecore/msgobject.c pulsecore/msgobject.h \
+		pulsecore/macro.h \
 		$(PA_THREAD_OBJS)
 
 if OS_IS_WIN32

commit 3cbcb982e2d3d789bb28f0e92cc5ce4750b06147
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sun Aug 12 21:14:25 2007 +0000

    build fix for newer glibc
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1654 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/utils/padsp.c b/src/utils/padsp.c
index 041115e..078b2e5 100644
--- a/src/utils/padsp.c
+++ b/src/utils/padsp.c
@@ -1436,6 +1436,7 @@ fail:
     return -1;
 }
 
+#undef open
 int open(const char *filename, int flags, ...) {
     va_list args;
     mode_t mode = 0;

commit 5e96d5da78c0ec989ac589a85f8184090b5a3c8c
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sun Aug 12 21:20:08 2007 +0000

    yet another new glibc build fix
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1655 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/utils/padsp.c b/src/utils/padsp.c
index 078b2e5..556ac2b 100644
--- a/src/utils/padsp.c
+++ b/src/utils/padsp.c
@@ -2491,6 +2491,7 @@ int stat64(const char *pathname, struct stat64 *buf) {
     return 0;
 }
 
+#undef open64
 int open64(const char *filename, int flags, ...) {
     va_list args;
     mode_t mode = 0;

commit e381dd9e4d6e4f518af49e244ad03ed093200938
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sun Aug 12 23:24:05 2007 +0000

    64 bit fixes and minor gcc shut ups
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1656 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/asyncmsgq.c b/src/pulsecore/asyncmsgq.c
index 1bef8bd..cc57d3a 100644
--- a/src/pulsecore/asyncmsgq.c
+++ b/src/pulsecore/asyncmsgq.c
@@ -191,7 +191,7 @@ int pa_asyncmsgq_get(pa_asyncmsgq *a, pa_msgobject **object, int *code, void **u
     if (chunk)
         *chunk = a->current->memchunk;
 
-    pa_log_debug("Get q=%p object=%p (%s) code=%i data=%p chunk.length=%u", (void*) a, (void*) a->current->object, a->current->object ? a->current->object->parent.type_name : NULL, a->current->code, (void*) a->current->userdata, a->current->memchunk.length);
+    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;
 }
diff --git a/src/pulsecore/asyncmsgq.h b/src/pulsecore/asyncmsgq.h
index 2f18837..55812c6 100644
--- a/src/pulsecore/asyncmsgq.h
+++ b/src/pulsecore/asyncmsgq.h
@@ -54,7 +54,7 @@ enum {
 
 typedef struct pa_asyncmsgq pa_asyncmsgq;
 
-pa_asyncmsgq* pa_asyncmsgq_new(size_t size);
+pa_asyncmsgq* pa_asyncmsgq_new(unsigned size);
 pa_asyncmsgq* pa_asyncmsgq_ref(pa_asyncmsgq *q);
 void pa_asyncmsgq_unref(pa_asyncmsgq* q);
 
diff --git a/src/pulsecore/asyncq.h b/src/pulsecore/asyncq.h
index 729ec46..53d4586 100644
--- a/src/pulsecore/asyncq.h
+++ b/src/pulsecore/asyncq.h
@@ -43,7 +43,7 @@
 
 typedef struct pa_asyncq pa_asyncq;
 
-pa_asyncq* pa_asyncq_new(size_t size);
+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);
diff --git a/src/pulsecore/authkey.c b/src/pulsecore/authkey.c
index 1476482..d805624 100644
--- a/src/pulsecore/authkey.c
+++ b/src/pulsecore/authkey.c
@@ -57,7 +57,7 @@ static int generate(int fd, void *ret_data, size_t length) {
     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));
diff --git a/src/pulsecore/core-scache.c b/src/pulsecore/core-scache.c
index 8a7ba13..6176dcb 100644
--- a/src/pulsecore/core-scache.c
+++ b/src/pulsecore/core-scache.c
@@ -164,8 +164,8 @@ 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_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;
@@ -316,7 +316,6 @@ int pa_scache_play_item_by_name(pa_core *c, const char *name, const char*sink_na
     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);
diff --git a/src/pulsecore/core-util.c b/src/pulsecore/core-util.c
index e61be70..165fcf3 100644
--- a/src/pulsecore/core-util.c
+++ b/src/pulsecore/core-util.c
@@ -169,7 +169,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
diff --git a/src/pulsecore/memblock.c b/src/pulsecore/memblock.c
index f0e2b4c..da99609 100644
--- a/src/pulsecore/memblock.c
+++ b/src/pulsecore/memblock.c
@@ -311,7 +311,7 @@ pa_memblock *pa_memblock_new_pool(pa_mempool *p, size_t length) {
         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 - sizeof(struct mempool_slot)));
         pa_atomic_inc(&p->stat.n_too_large_for_pool);
         return NULL;
     }
diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c
index df08ff6..ced8038 100644
--- a/src/pulsecore/sink.c
+++ b/src/pulsecore/sink.c
@@ -738,7 +738,7 @@ int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offse
                 
                 volume_is_norm = pa_cvolume_is_norm(&info->sink_input->thread_info.volume);
 
-                pa_log_debug("Buffering %u bytes ...", info->buffer_bytes);
+                pa_log_debug("Buffering l%u bytes ...", (unsigned long) info->buffer_bytes);
                 
                 while (info->buffer_bytes > 0) {
                     pa_memchunk memchunk;
@@ -772,7 +772,7 @@ int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offse
 
                 pa_memblockq_sink_input_set_queue(info->ghost_sink_input, info->buffer);
 
-                pa_log_debug("Buffered %u bytes ...", pa_memblockq_get_length(info->buffer));
+                pa_log_debug("Buffered %lu bytes ...", (unsigned long) pa_memblockq_get_length(info->buffer));
             }
 
             /* Let's remove the sink input ...*/

commit 1d5e9f0205330207c37203d21ff642946f043bf7
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sun Aug 12 23:29:12 2007 +0000

    deactivate module-x11-xsmp by default, due to a deadlock when pa is being started from gnome-session
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1657 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/daemon/default.pa.in b/src/daemon/default.pa.in
index 583b26c..c472c09 100755
--- a/src/daemon/default.pa.in
+++ b/src/daemon/default.pa.in
@@ -77,7 +77,8 @@ load-module module-x11-bell sample=x11-bell
 load-module module-x11-publish
 
 ### Register ourselves in the X11 session manager
-load-module module-x11-xsmp
+# Deactivated by default, to avoid deadlock when PA is started from gnome-session
+# 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

commit 8a663d4cda21c22849c7185690f2e47ff7d0219a
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Aug 13 00:15:55 2007 +0000

    a couple of build fixes
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1658 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/oss-util.c b/src/modules/oss-util.c
index 155d42e..5a939cf 100644
--- a/src/modules/oss-util.c
+++ b/src/modules/oss-util.c
@@ -268,7 +268,7 @@ static int pa_oss_get_volume(int fd, int mixer, const pa_sample_spec *ss, pa_cvo
     return 0;
 }
 
-static int pa_oss_set_volume(int fd, int mixer, const pa_sample_spec *ss, const pa_cvolume *volume) {
+static 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;
diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c
index 1a112a8..6b49efe 100644
--- a/src/pulsecore/protocol-native.c
+++ b/src/pulsecore/protocol-native.c
@@ -590,14 +590,14 @@ static playback_stream* playback_stream_new(
         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,
         int corked,
-        size_t *missing) {
+        uint32_t *missing) {
 
     playback_stream *s, *ssync;
     pa_sink_input *sink_input;
@@ -674,11 +674,11 @@ static playback_stream* playback_stream_new(
 
     pa_memblock_unref(silence);
 
-    *maxlength = pa_memblockq_get_maxlength(s->memblockq);
-    *tlength = pa_memblockq_get_tlength(s->memblockq);
-    *prebuf = pa_memblockq_get_prebuf(s->memblockq);
-    *minreq = pa_memblockq_get_minreq(s->memblockq);
-    *missing = pa_memblockq_missing(s->memblockq);
+    *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_missing(s->memblockq);
     
     pa_atomic_store(&s->missing, 0);
     s->last_missing = *missing;
diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c
index ced8038..cfead9b 100644
--- a/src/pulsecore/sink.c
+++ b/src/pulsecore/sink.c
@@ -738,7 +738,7 @@ int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offse
                 
                 volume_is_norm = pa_cvolume_is_norm(&info->sink_input->thread_info.volume);
 
-                pa_log_debug("Buffering l%u bytes ...", (unsigned long) info->buffer_bytes);
+                pa_log_debug("Buffering %lu bytes ...", (unsigned long) info->buffer_bytes);
                 
                 while (info->buffer_bytes > 0) {
                     pa_memchunk memchunk;
diff --git a/src/tests/asyncq-test.c b/src/tests/asyncq-test.c
index 2e4b66c..09b2004 100644
--- a/src/tests/asyncq-test.c
+++ b/src/tests/asyncq-test.c
@@ -41,10 +41,10 @@ static void producer(void *_q) {
 
     for (i = 0; i < 1000; i++) {
         printf("pushing %i\n", i);
-        pa_asyncq_push(q, (void*) (i+1), 1);
+        pa_asyncq_push(q, PA_UINT_TO_PTR(i+1), 1);
     }
 
-    pa_asyncq_push(q, (void*) -1, 1);
+    pa_asyncq_push(q, PA_UINT_TO_PTR(-1), 1);
     printf("pushed end\n");
 }
 
@@ -58,10 +58,10 @@ static void consumer(void *_q) {
     for (i = 0;; i++) {
         p = pa_asyncq_pop(q, 1);
 
-        if (p == (void*) -1)
+        if (p == PA_UINT_TO_PTR(-1))
             break;
 
-        pa_assert(p == (void *) (i+1));
+        pa_assert(p == PA_UINT_TO_PTR(i+1));
 
         printf("popped %i\n", i);
     }

commit 80f5abf6d967a26ac8e40ee3276c8258f6e0af59
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Aug 13 23:34:46 2007 +0000

    add load-module and unload-module commands to pactl
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1659 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/utils/pactl.c b/src/utils/pactl.c
index b95cbfe..cfc3f55 100644
--- a/src/utils/pactl.c
+++ b/src/utils/pactl.c
@@ -48,8 +48,9 @@
 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 SNDFILE *sndfile = NULL;
 static pa_stream *sample_stream = NULL;
@@ -69,7 +70,9 @@ static enum {
     REMOVE_SAMPLE,
     LIST,
     MOVE_SINK_INPUT,
-    MOVE_SOURCE_OUTPUT
+    MOVE_SOURCE_OUTPUT,
+    LOAD_MODULE,
+    UNLOAD_MODULE,
 } action = NONE;
 
 static void quit(int ret) {
@@ -492,6 +495,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 +609,14 @@ 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;
+                    
                 default:
                     assert(0);
             }
@@ -624,12 +647,14 @@ 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\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);
 }
 
 enum { ARG_VERSION = 256 };
@@ -728,7 +753,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 +765,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 +773,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,14 +782,48 @@ 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 source output index and a source\n");
+                goto quit;
+            }
+
+            module_index = atoi(argv[optind+1]);
         }
+            
     }
 
     if (action == NONE) {
@@ -819,6 +878,7 @@ quit:
     pa_xfree(sample_name);
     pa_xfree(sink_name);
     pa_xfree(source_name);
+    pa_xfree(module_args);
 
     return ret;
 }

commit 44f91cfafa0c615f773095a822ab7c0c5bdcb585
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Aug 13 23:49:26 2007 +0000

    load module-x11-xsmp from a /etc/xdg/autostart file, to make sure it is loaded when we have XSMP
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1660 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/Makefile.am b/src/Makefile.am
index aa5160a..a962826 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -30,6 +30,7 @@ pulseincludedir=$(includedir)/pulse
 pulsecoreincludedir=$(includedir)/pulsecore
 pulseconfdir=$(sysconfdir)/pulse
 pulselibexecdir=$(libexecdir)/pulse
+xdgautostartdir=$(sysconfdir)/xdg/autostart
 
 ###################################
 #            Defines              #
@@ -103,13 +104,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
 
diff --git a/src/daemon/default.pa.in b/src/daemon/default.pa.in
index c472c09..6ece607 100755
--- a/src/daemon/default.pa.in
+++ b/src/daemon/default.pa.in
@@ -77,7 +77,8 @@ load-module module-x11-bell sample=x11-bell
 load-module module-x11-publish
 
 ### Register ourselves in the X11 session manager
-# Deactivated by default, to avoid deadlock when PA is started from gnome-session
+# 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.
diff --git a/src/daemon/pulseaudio-module-xsmp.desktop b/src/daemon/pulseaudio-module-xsmp.desktop
new file mode 100644
index 0000000..fa719a7
--- /dev/null
+++ b/src/daemon/pulseaudio-module-xsmp.desktop
@@ -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=

commit 6f714d988750336df036d8036cea9c01dfe6cf39
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Aug 15 19:25:42 2007 +0000

    actually mute sinks when asked for i, add new function pa_sink_suspend_all
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1661 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c
index cfead9b..2c7c661 100644
--- a/src/pulsecore/sink.c
+++ b/src/pulsecore/sink.c
@@ -587,6 +587,7 @@ void pa_sink_set_mute(pa_sink *s, int mute) {
     pa_sink_assert_ref(s);
 
     changed = s->muted != mute;
+    s->muted = mute;
 
     if (s->set_mute && s->set_mute(s) < 0)
         s->set_mute = NULL;
@@ -819,3 +820,16 @@ int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offse
 
     return -1;
 }
+
+int pa_sink_suspend_all(pa_core *c, int 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;
+}
diff --git a/src/pulsecore/sink.h b/src/pulsecore/sink.h
index 8a6fa23..fadc76e 100644
--- a/src/pulsecore/sink.h
+++ b/src/pulsecore/sink.h
@@ -163,4 +163,6 @@ static inline int PA_SINK_OPENED(pa_sink_state_t x) {
     return x == PA_SINK_RUNNING || x == PA_SINK_IDLE;
 }
 
+int pa_sink_suspend_all(pa_core *c, int suspend);
+
 #endif

commit 3d9299029c89d1bdc23c5e39bf627b0f4d7f2f3c
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Aug 15 19:25:56 2007 +0000

    actually mute sinks when asked for i, add new function pa_sink_suspend_all
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1662 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/source.c b/src/pulsecore/source.c
index 0e448f6..30a45cb 100644
--- a/src/pulsecore/source.c
+++ b/src/pulsecore/source.c
@@ -320,6 +320,7 @@ void pa_source_set_mute(pa_source *s, int mute) {
     pa_source_assert_ref(s);
 
     changed = s->muted != mute;
+    s->muted = mute;
 
     if (s->set_mute && s->set_mute(s) < 0)
         s->set_mute = NULL;
@@ -438,3 +439,16 @@ int pa_source_process_msg(pa_msgobject *object, int code, void *userdata, int64_
 
     return -1;
 }
+
+int pa_source_suspend_all(pa_core *c, int 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;
+}
diff --git a/src/pulsecore/source.h b/src/pulsecore/source.h
index fe59e58..ffe5107 100644
--- a/src/pulsecore/source.h
+++ b/src/pulsecore/source.h
@@ -152,4 +152,6 @@ static inline int PA_SOURCE_OPENED(pa_source_state_t x) {
     return x == PA_SOURCE_RUNNING || x == PA_SOURCE_IDLE;
 }
 
+int pa_source_suspend_all(pa_core *c, int suspend);
+
 #endif

commit a74e804973eff2c6d9dff34fe415df9a0bb40683
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Aug 15 19:26:38 2007 +0000

    fix muting for sink inputs
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1663 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c
index 5fd1da4..8bec5d5 100644
--- a/src/pulsecore/sink-input.c
+++ b/src/pulsecore/sink-input.c
@@ -398,7 +398,11 @@ int pa_sink_input_peek(pa_sink_input *i, pa_memchunk *chunk, pa_cvolume *volume)
         /* 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->thread_info.sample_spec, &i->thread_info.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->thread_info.resampler, &tchunk, &i->thread_info.resampled_chunk);
@@ -430,8 +434,10 @@ 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*/
+            pa_cvolume_mute(volume, i->sink->sample_spec.channels);
+        else
             *volume = i->thread_info.volume;
     }
 

commit b20d204a30f3f5e1fa79ba236ce18a9025b0877b
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Aug 15 19:27:12 2007 +0000

    use pa_source_suspend_all/pa_sink_suspend_all for suspending all sinks/sources
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1664 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/cli-command.c b/src/pulsecore/cli-command.c
index fac8d0e..7440e74 100644
--- a/src/pulsecore/cli-command.c
+++ b/src/pulsecore/cli-command.c
@@ -965,10 +965,8 @@ static int pa_cli_command_suspend_source(pa_core *c, pa_tokenizer *t, pa_strbuf
 
 static int pa_cli_command_suspend(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) {
     const char *m;
-    pa_sink *sink;
-    pa_source *source;
     int suspend;
-    uint32_t idx;
+    int ret;
 
     if (!(m = pa_tokenizer_get(t, 1))) {
         pa_strbuf_puts(buf, "You need to specify a suspend switch setting (0/1).\n");
@@ -980,11 +978,12 @@ static int pa_cli_command_suspend(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, i
         return -1;
     }
 
-    for (sink = pa_idxset_first(c->sinks, &idx); sink; sink = pa_idxset_next(c->sinks, &idx))
-        pa_sink_suspend(sink, suspend);
+    ret = - (pa_sink_suspend_all(c, suspend) < 0);
+    if (pa_source_suspend_all(c, suspend) < 0)
+        ret = -1;
 
-    for (source = pa_idxset_first(c->sources, &idx); source; source = pa_idxset_next(c->sources, &idx))
-        pa_source_suspend(source, suspend);
+    if (ret < 0)
+        pa_strbuf_puts(buf, "Failed to resume/suspend all sinks/sources.\n");
     
     return 0;
 }

commit 0640615c4ab87422379c043d67fc137c1bea6c1f
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Aug 15 19:27:52 2007 +0000

    bump protocol revision and soname of libpulse
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1665 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/configure.ac b/configure.ac
index 1bde5cc..b037b89 100644
--- a/configure.ac
+++ b/configure.ac
@@ -37,9 +37,9 @@ AC_SUBST(PA_MAJORMINOR, "PA_MAJOR.PA_MINOR")
 AC_SUBST(PACKAGE_URL, [http://0pointer.de/lennart/projects/pulseaudio/])
 
 AC_SUBST(PA_API_VERSION, 10)
-AC_SUBST(PA_PROTOCOL_VERSION, 10)
+AC_SUBST(PA_PROTOCOL_VERSION, 11)
 
-AC_SUBST(LIBPULSE_VERSION_INFO, [2:1:2])
+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])

commit d2d0978454458f3604cea8c20bef0940fbff32d5
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Aug 15 19:30:04 2007 +0000

    add protocol support for muting sink inputs and suspending sinks/sources
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1666 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulse/introspect.c b/src/pulse/introspect.c
index 7f6406c..568749d 100644
--- a/src/pulse/introspect.c
+++ b/src/pulse/introspect.c
@@ -47,6 +47,8 @@ static void context_stat_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNU
     assert(o);
     assert(o->ref >= 1);
 
+    memset(&i, 0, sizeof(i));
+    
     if (!o->context)
         goto finish;
 
@@ -59,8 +61,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;
     }
@@ -89,6 +90,8 @@ static void context_get_server_info_callback(pa_pdispatch *pd, uint32_t command,
     assert(o);
     assert(o->ref >= 1);
 
+    memset(&i, 0, sizeof(i));
+    
     if (!o->context)
         goto finish;
 
@@ -104,8 +107,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;
@@ -148,6 +150,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 ||
@@ -258,6 +261,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 ||
@@ -367,6 +371,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 ||
@@ -441,6 +446,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 ||
@@ -516,7 +522,8 @@ 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 ||
                 pa_tagstruct_getu32(t, &i.owner_module) < 0 ||
@@ -528,7 +535,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;
@@ -600,6 +608,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 ||
@@ -781,6 +791,29 @@ 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;
+
+    assert(c);
+    assert(c->ref >= 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;
@@ -900,6 +933,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 ||
@@ -1096,6 +1131,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 ||
@@ -1341,3 +1378,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;
+
+    assert(c);
+    assert(c->ref >= 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;
+
+    assert(c);
+    assert(c->ref >= 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;
+
+    assert(c);
+    assert(c->ref >= 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;
+
+    assert(c);
+    assert(c->ref >= 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;
+}
diff --git a/src/pulse/introspect.h b/src/pulse/introspect.h
index 43e430b..e700e39 100644
--- a/src/pulse/introspect.h
+++ b/src/pulse/introspect.h
@@ -249,7 +249,7 @@ typedef struct pa_source_info {
     const char *monitor_of_sink_name;   /**< Name of the owning sink, or PA_INVALID_INDEX */
     pa_usec_t latency;                  /**< Length of filled record buffer of this source. \since 0.5 */
     const char *driver;                 /**< Driver name \since 0.8 */
-    pa_source_flags_t flags;            /**< Flags \since 0.8 */
+    pa_source_flags_t flags;            /**< Flags \since 0.8 */    
 } pa_source_info;
 
 /** Callback prototype for pa_context_get_source_info_by_name() and friends */
@@ -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
diff --git a/src/pulsecore/native-common.h b/src/pulsecore/native-common.h
index d22c8d1..9defc4a 100644
--- a/src/pulsecore/native-common.h
+++ b/src/pulsecore/native-common.h
@@ -117,6 +117,9 @@ enum {
 
     PA_COMMAND_SET_SINK_INPUT_MUTE,
 
+    PA_COMMAND_SUSPEND_SINK,
+    PA_COMMAND_SUSPEND_SOURCE,
+
     PA_COMMAND_MAX
 };
 
diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c
index 6b49efe..fe73865 100644
--- a/src/pulsecore/protocol-native.c
+++ b/src/pulsecore/protocol-native.c
@@ -247,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,
@@ -296,6 +297,9 @@ static const pa_pdispatch_cb_t command_table[PA_COMMAND_MAX] = {
     [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_trigger_or_flush_or_prebuf_playback_stream,
     [PA_COMMAND_TRIGGER_PLAYBACK_STREAM] = command_trigger_or_flush_or_prebuf_playback_stream,
@@ -1770,7 +1774,7 @@ 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) {
+static void sink_input_fill_tagstruct(connection *c, pa_tagstruct *t, pa_sink_input *s) {
     pa_assert(t);
     pa_sink_input_assert_ref(s);
 
@@ -1786,6 +1790,8 @@ 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) {
@@ -1891,7 +1897,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
@@ -1946,7 +1952,7 @@ 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 {
@@ -2620,6 +2626,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)
@@ -2638,6 +2646,80 @@ 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) {

commit 5679de5cfc4b4bbb7998e0d9eb5804e55c5786be
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Aug 15 19:57:12 2007 +0000

    add new commands suspend-source, suspend-sink
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1667 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/utils/pactl.c b/src/utils/pactl.c
index cfc3f55..7c49007 100644
--- a/src/utils/pactl.c
+++ b/src/utils/pactl.c
@@ -51,6 +51,7 @@ static pa_mainloop_api *mainloop_api = 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;
@@ -73,6 +74,8 @@ static enum {
     MOVE_SOURCE_OUTPUT,
     LOAD_MODULE,
     UNLOAD_MODULE,
+    SUSPEND_SINK,
+    SUSPEND_SOURCE,
 } action = NONE;
 
 static void quit(int ret) {
@@ -357,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");
@@ -616,6 +619,20 @@ static void context_state_callback(pa_context *c, void *userdata) {
                 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);
@@ -649,12 +666,14 @@ static void help(const char *argv0) {
            "%s [options] move-source-output ID SOURCE\n"
            "%s [options] remove-sample NAME\n"
            "%s [options] load-module NAME [ARGS ...]\n"
-           "%s [options] unload-module ID\n\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, argv0, argv0);
 }
 
 enum { ARG_VERSION = 256 };
@@ -817,13 +836,38 @@ int main(int argc, char *argv[]) {
             action = UNLOAD_MODULE;
             
             if (argc != optind+2) {
-                fprintf(stderr, "You have to specify a source output index and a source\n");
+                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]);
+        }
     }
 
     if (action == NONE) {
@@ -879,6 +923,7 @@ quit:
     pa_xfree(sink_name);
     pa_xfree(source_name);
     pa_xfree(module_args);
+    pa_xfree(client_name);
 
     return ret;
 }

commit 33c6f9dd52fe3f0617dc1c29c4eb2e145432afc7
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Aug 15 20:47:53 2007 +0000

    set CLOEXEC on more fds
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1668 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulse/mainloop.c b/src/pulse/mainloop.c
index 0563507..0dd0e11 100644
--- a/src/pulse/mainloop.c
+++ b/src/pulse/mainloop.c
@@ -460,6 +460,8 @@ pa_mainloop *pa_mainloop_new(void) {
 
     pa_make_nonblock_fd(m->wakeup_pipe[0]);
     pa_make_nonblock_fd(m->wakeup_pipe[1]);
+    pa_fd_set_cloexec(m->wakeup_pipe[0], 1);
+    pa_fd_set_cloexec(m->wakeup_pipe[1], 1);
     m->wakeup_requested = 0;
 
     PA_LLIST_HEAD_INIT(pa_io_event, m->io_events);
diff --git a/src/pulsecore/fdsem.c b/src/pulsecore/fdsem.c
index c51ebba..20d262e 100644
--- a/src/pulsecore/fdsem.c
+++ b/src/pulsecore/fdsem.c
@@ -54,6 +54,9 @@ pa_fdsem *pa_fdsem_new(void) {
         return NULL;
     }
 
+    pa_fd_set_cloexec(f->fds[0], 1);
+    pa_fd_set_cloexec(f->fds[1], 1);
+
     pa_atomic_store(&f->waiting, 0);
     pa_atomic_store(&f->signalled, 0);
     pa_atomic_store(&f->in_pipe, 0);

commit a96c5f813706f5c9ccf91a2d40b20362eb6c446c
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Aug 15 20:50:15 2007 +0000

    add new tool pasuspender which temporarily suspends all sinks and resumes them later again
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1669 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/Makefile.am b/src/Makefile.am
index a962826..a711de2 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -161,7 +161,8 @@ endif
 bin_PROGRAMS += \
 		pacat \
 		pactl \
-		paplay
+		paplay \
+		pasuspender
 
 if HAVE_AF_UNIX
 bin_PROGRAMS += pacmd
@@ -192,6 +193,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
diff --git a/src/utils/pasuspender.c b/src/utils/pasuspender.c
new file mode 100644
index 0000000..2172ccf
--- /dev/null
+++ b/src/utils/pasuspender.c
@@ -0,0 +1,286 @@
+/* $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/prctl.h>
+#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>
+
+#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 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);
+    }
+
+    if (n >= 2) {
+        
+        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 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:
+            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));
+            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)));
+            quit(1);
+    }
+}
+
+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;
+    }
+
+    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));
+}
+
+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, 0, 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;
+}

commit 1ff47862c4e9432225b5f95d5727eb00ad0a4234
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Aug 15 21:03:53 2007 +0000

    don't fail if no pa is srunning
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1670 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/utils/pasuspender.c b/src/utils/pasuspender.c
index 2172ccf..9ffd6d6 100644
--- a/src/utils/pasuspender.c
+++ b/src/utils/pasuspender.c
@@ -77,6 +77,32 @@ static void drain(void) {
         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;
 
@@ -85,33 +111,11 @@ static void suspend_complete(pa_context *c, int success, void *userdata) {
     if (!success) {
         fprintf(stderr, "Failure to suspend: %s\n", pa_strerror(pa_context_errno(c)));
         quit(1);
+        return;
     }
 
-    if (n >= 2) {
-        
-        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;
-        }
-    }
+    if (n >= 2)
+        start_child();
 }
 
 static void resume_complete(pa_context *c, int success, void *userdata) {
@@ -150,7 +154,18 @@ static void context_state_callback(pa_context *c, void *userdata) {
         case PA_CONTEXT_FAILED:
         default:
             fprintf(stderr, "Connection failure: %s\n", pa_strerror(pa_context_errno(c)));
-            quit(1);
+
+            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;
     }
 }
 
@@ -177,8 +192,13 @@ static void sigchld_callback(pa_mainloop_api *m, pa_signal_event *e, int sig, vo
         child_ret = 1;
     }
 
-    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));
+    if (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
+        /* Hmm, no context here, so let's terminate right away */
+        quit(0);
 }
 
 static void help(const char *argv0) {
@@ -261,7 +281,7 @@ int main(int argc, char *argv[]) {
     }
 
     pa_context_set_state_callback(context, context_state_callback, NULL);
-    pa_context_connect(context, server, 0, NULL);
+    pa_context_connect(context, server, PA_CONTEXT_NOAUTOSPAWN, NULL);
 
     if (pa_mainloop_run(m, &ret) < 0) {
         fprintf(stderr, "pa_mainloop_run() failed.\n");

commit c0d668431b252587021586bf4f52d99f8934035d
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Aug 15 22:47:59 2007 +0000

    fix an awful race condition when handling data requests
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1671 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c
index fe73865..a0b7066 100644
--- a/src/pulsecore/protocol-native.c
+++ b/src/pulsecore/protocol-native.c
@@ -537,13 +537,23 @@ static int playback_stream_process_msg(pa_msgobject *o, int code, void*userdata,
     switch (code) {
         case PLAYBACK_STREAM_MESSAGE_REQUEST_DATA: {
             pa_tagstruct *t;
-            int32_t l;
+            int32_t l = 0;
 
-            if ((l = pa_atomic_load(&s->missing)) <= 0)
+            for (;;) {
+                int32_t k;
+                
+                if ((k = pa_atomic_load(&s->missing)) <= 0)
+                    break;
+
+                l += k;
+                
+                if (pa_atomic_sub(&s->missing, k) <= k)
+                    break;
+            }
+
+            if (l <= 0)
                 break;
             
-            pa_assert_se(pa_atomic_sub(&s->missing, l) >= l);
-            
             t = pa_tagstruct_new(NULL, 0);
             pa_tagstruct_putu32(t, PA_COMMAND_REQUEST);
             pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
@@ -551,7 +561,7 @@ static int playback_stream_process_msg(pa_msgobject *o, int code, void*userdata,
             pa_tagstruct_putu32(t, l);
             pa_pstream_send_tagstruct(s->connection->pstream, t);
 
-/*             pa_log("Requesting %u bytes", l);    */
+/*             pa_log("Requesting %u bytes", l);     */
             break;
         }
 
@@ -770,24 +780,22 @@ static void connection_free(pa_object *o) {
 /* Called from thread context */
 static void request_bytes(playback_stream *s) {
     size_t new_missing, delta, previous_missing;
+    size_t minreq;
 
-/*     pa_log("request_bytes()"); */
     playback_stream_assert_ref(s);
 
     new_missing = pa_memblockq_missing(s->memblockq);
-    
-    if (new_missing <= s->last_missing) {
-        s->last_missing = new_missing;
-        return;
-    }
-
-    delta = new_missing - s->last_missing;
+    delta = new_missing > s->last_missing ? new_missing - s->last_missing : 0;
     s->last_missing = new_missing;
 
+    if (delta <= 0)
+        return;
+
 /*     pa_log("request_bytes(%u)", delta); */
+    minreq = pa_memblockq_get_minreq(s->memblockq);
 
     previous_missing = pa_atomic_add(&s->missing, delta);
-    if (previous_missing < pa_memblockq_get_minreq(s->memblockq) && previous_missing+delta >= pa_memblockq_get_minreq(s->memblockq))
+    if (previous_missing < minreq && previous_missing+delta >= minreq)
         pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(s), PLAYBACK_STREAM_MESSAGE_REQUEST_DATA, NULL, 0, NULL, NULL);
 }
 

commit 81cdb3798c146a577f5b362367137cc93610cba4
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Aug 15 23:13:53 2007 +0000

    add fedora-snapshot target
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1672 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/Makefile.am b/Makefile.am
index 0fd4ccc..288c24e 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -51,4 +51,7 @@ eolspace:
 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

commit 03b0b1db7b9d20d3b0b563becda07c3ef93b85de
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Aug 16 13:46:32 2007 +0000

    add pa_truncate_utf8() function for truncating a string and guaranteeing it stays valid UTF8 afterwards
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1673 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/core-util.c b/src/pulsecore/core-util.c
index 165fcf3..9d846c6 100644
--- a/src/pulsecore/core-util.c
+++ b/src/pulsecore/core-util.c
@@ -78,6 +78,7 @@
 
 #include <pulse/xmalloc.h>
 #include <pulse/util.h>
+#include <pulse/utf8.h>
 
 #include <pulsecore/core-error.h>
 #include <pulsecore/winsock.h>
@@ -1223,3 +1224,20 @@ int pa_snprintf(char *str, size_t size, const char *format, ...) {
 
     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;
+}
diff --git a/src/pulsecore/core-util.h b/src/pulsecore/core-util.h
index a593317..88ed23f 100644
--- a/src/pulsecore/core-util.h
+++ b/src/pulsecore/core-util.h
@@ -94,4 +94,6 @@ int pa_atou(const char *s, uint32_t *ret_u);
 
 int pa_snprintf(char *str, size_t size, const char *format, ...);
 
+char *pa_truncate_utf8(char *c, size_t l);
+
 #endif

commit 39d1e653387e9c139cfaa69820b2925234356b2a
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Aug 16 13:47:18 2007 +0000

    truncate service names if necessary, include user name in service string
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1674 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-zeroconf-publish.c b/src/modules/module-zeroconf-publish.c
index 3456539..1cdde84 100644
--- a/src/modules/module-zeroconf-publish.c
+++ b/src/modules/module-zeroconf-publish.c
@@ -35,6 +35,7 @@
 #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>
@@ -102,25 +103,31 @@ struct userdata {
 };
 
 static void get_service_data(struct userdata *u, struct service *s, pa_sample_spec *ret_ss, char **ret_description) {
-    pa_assert(u && s && s->loaded.valid && ret_ss && ret_description);
+    pa_assert(u);
+    pa_assert(s);
+    pa_assert(s->loaded.valid);
+    pa_assert(ret_ss);
+    pa_assert(ret_description);
 
     if (s->loaded.type == PA_NAMEREG_SINK) {
-        pa_sink *sink = pa_idxset_get_by_index(u->core->sinks, s->loaded.index);
-        pa_assert(sink);
+        pa_sink *sink = PA_SINK(pa_idxset_get_by_index(u->core->sinks, s->loaded.index));
+        pa_sink_assert_ref(sink);
         *ret_ss = sink->sample_spec;
         *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);
-        pa_assert(source);
+        pa_source *source = PA_SOURCE(pa_idxset_get_by_index(u->core->sources, s->loaded.index));
+        pa_source_assert_ref(source);
         *ret_ss = source->sample_spec;
         *ret_description = source->description;
     } else
-        pa_assert(0);
+        pa_assert_not_reached();
 }
 
 static AvahiStringList* txt_record_server_data(pa_core *c, AvahiStringList *l) {
     char s[128];
-    pa_assert(c);
+    
+    pa_core_assert_ref(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)));
@@ -135,6 +142,8 @@ static int publish_service(struct userdata *u, struct service *s);
 static void service_entry_group_callback(AvahiEntryGroup *g, AvahiEntryGroupState state, void *userdata) {
     struct service *s = userdata;
 
+    pa_assert(s);
+
     if (state == AVAHI_ENTRY_GROUP_COLLISION) {
         char *t;
 
@@ -244,7 +253,7 @@ finish:
 
 static struct service *get_service(struct userdata *u, const char *name, const char *description) {
     struct service *s;
-    char hn[64];
+    char hn[64], un[64];
 
     if ((s = pa_hashmap_get(u->services, name)))
         return s;
@@ -255,7 +264,7 @@ static struct service *get_service(struct userdata *u, const char *name, const c
     s->published = UNPUBLISHED;
     s->name = pa_xstrdup(name);
     s->loaded.valid = s->autoload.valid = 0;
-    s->service_name = pa_sprintf_malloc("%s on %s", description ? description : s->name, pa_get_host_name(hn, sizeof(hn)));
+    s->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)), description ? description : s->name), AVAHI_LABEL_MAX-1);
 
     pa_hashmap_put(u->services, s->name, s);
 
@@ -265,7 +274,9 @@ static struct service *get_service(struct userdata *u, const char *name, const c
 static int publish_sink(struct userdata *u, pa_sink *s) {
     struct service *svc;
     int ret;
-    pa_assert(u && s);
+
+    pa_assert(u);
+    pa_sink_assert_ref(s);
 
     svc = get_service(u, s->name, s->description);
     if (svc->loaded.valid)
@@ -286,7 +297,8 @@ static int publish_source(struct userdata *u, pa_source *s) {
     struct service *svc;
     int ret;
 
-    pa_assert(u && s);
+    pa_assert(u);
+    pa_source_assert_ref(s);
 
     svc = get_service(u, s->name, s->description);
     if (svc->loaded.valid)
@@ -309,7 +321,8 @@ static int publish_autoload(struct userdata *u, pa_autoload_entry *s) {
     struct service *svc;
     int ret;
 
-    pa_assert(u && s);
+    pa_assert(u);
+    pa_assert(s);
 
     svc = get_service(u, s->name, NULL);
     if (svc->autoload.valid)
@@ -328,7 +341,9 @@ static int publish_autoload(struct userdata *u, pa_autoload_entry *s) {
 
 static int remove_sink(struct userdata *u, uint32_t idx) {
     struct service *svc;
-    pa_assert(u && idx != PA_INVALID_INDEX);
+    
+    pa_assert(u);
+    pa_assert(idx != PA_INVALID_INDEX);
 
     if (!(svc = pa_dynarray_get(u->sink_dynarray, idx)))
         return 0;
@@ -344,7 +359,9 @@ static int remove_sink(struct userdata *u, uint32_t idx) {
 
 static int remove_source(struct userdata *u, uint32_t idx) {
     struct service *svc;
-    pa_assert(u && idx != PA_INVALID_INDEX);
+    
+    pa_assert(u);
+    pa_assert(idx != PA_INVALID_INDEX);
 
     if (!(svc = pa_dynarray_get(u->source_dynarray, idx)))
         return 0;
@@ -360,7 +377,9 @@ static int remove_source(struct userdata *u, uint32_t idx) {
 
 static int remove_autoload(struct userdata *u, uint32_t idx) {
     struct service *svc;
-    pa_assert(u && idx != PA_INVALID_INDEX);
+    
+    pa_assert(u);
+    pa_assert(idx != PA_INVALID_INDEX);
 
     if (!(svc = pa_dynarray_get(u->autoload_dynarray, idx)))
         return 0;
@@ -376,14 +395,17 @@ static int remove_autoload(struct userdata *u, uint32_t idx) {
 
 static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint32_t idx, void *userdata) {
     struct userdata *u = userdata;
-    pa_assert(u && c);
+    
+    pa_assert(u);
+    pa_core_assert_ref(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 ((sink = PA_SINK(pa_idxset_get_by_index(c->sinks, idx)))) {
                     if (publish_sink(u, sink) < 0)
                         goto fail;
                 }
@@ -399,7 +421,7 @@ static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint3
             if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_NEW) {
                 pa_source *source;
 
-                if ((source = pa_idxset_get_by_index(c->sources, idx))) {
+                if ((source = PA_SOURCE(pa_idxset_get_by_index(c->sources, idx)))) {
                     if (publish_source(u, source) < 0)
                         goto fail;
                 }
@@ -456,6 +478,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)));
@@ -505,11 +529,11 @@ static int publish_all_services(struct userdata *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))
+    for (sink = PA_SINK(pa_idxset_first(u->core->sinks, &idx)); sink; sink = PA_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))
+    for (source = PA_SOURCE(pa_idxset_first(u->core->sources, &idx)); source; source = PA_SOURCE(pa_idxset_next(u->core->sources, &idx)))
         if (publish_source(u, source) < 0)
             goto fail;
 
@@ -558,7 +582,9 @@ static void unpublish_all_services(struct userdata *u, int rem) {
 
 static void client_callback(AvahiClient *c, AvahiClientState state, void *userdata) {
     struct userdata *u = userdata;
+    
     pa_assert(c);
+    pa_assert(u);
 
     u->client = c;
 
@@ -592,7 +618,7 @@ 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))) {
@@ -623,7 +649,7 @@ int pa__init(pa_module*m) {
 
     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));
@@ -678,7 +704,6 @@ void pa__done(pa_module*m) {
     if (u->autoload_dynarray)
         pa_dynarray_free(u->autoload_dynarray, NULL, NULL);
 
-
     if (u->main_entry_group)
         avahi_entry_group_free(u->main_entry_group);
 

commit 843dcceb1d9884fd677846f0a556671e9417235c
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Aug 16 18:26:35 2007 +0000

    only suspend device when server is local
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1675 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/utils/pasuspender.c b/src/utils/pasuspender.c
index 9ffd6d6..a546f9a 100644
--- a/src/utils/pasuspender.c
+++ b/src/utils/pasuspender.c
@@ -143,8 +143,12 @@ static void context_state_callback(pa_context *c, void *userdata) {
             break;
 
         case PA_CONTEXT_READY:
-            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));
+            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:
@@ -193,9 +197,12 @@ static void sigchld_callback(pa_mainloop_api *m, pa_signal_event *e, int sig, vo
     }
 
     if (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));
+        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);

commit d5cbf4fed9f695cceebfbe17b35313622540befe
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Aug 16 19:44:51 2007 +0000

    Keep CAP_SYS_NICE not only in PERMITTED but also in EFFECTIVE capset
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1676 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/daemon/caps.c b/src/daemon/caps.c
index f92db74..5b4008a 100644
--- a/src/daemon/caps.c
+++ b/src/daemon/caps.c
@@ -26,11 +26,11 @@
 #include <config.h>
 #endif
 
-#include <assert.h>
 #include <unistd.h>
 #include <errno.h>
 #include <string.h>
 #include <sys/types.h>
+#include <pulsecore/macro.h>
 
 #ifdef HAVE_SYS_CAPABILITY_H
 #include <sys/capability.h>
@@ -60,7 +60,7 @@ void pa_drop_root(void) {
     if (uid == 0 || geteuid() != 0)
         return;
 
-    pa_log_info("dropping root rights.");
+    pa_log_info("Dropping root priviliges.");
 
 #if defined(HAVE_SETRESUID)
     setresuid(uid, uid, uid);
@@ -88,8 +88,9 @@ int pa_limit_caps(void) {
     cap_value_t nice_cap = CAP_SYS_NICE;
 
     caps = cap_init();
-    assert(caps);
+    pa_assert(caps);
     cap_clear(caps);
+    cap_set_flag(caps, CAP_EFFECTIVE, 1, &nice_cap, CAP_SET);
     cap_set_flag(caps, CAP_PERMITTED, 1, &nice_cap, CAP_SET);
 
     if (cap_set_proc(caps) < 0)
@@ -98,7 +99,7 @@ int pa_limit_caps(void) {
     if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) < 0)
         goto fail;
 
-    pa_log_info("dropped capabilities successfully.");
+    pa_log_info("Dropped capabilities successfully.");
 
     r = 1;
 
@@ -114,14 +115,14 @@ int pa_drop_caps(void) {
     int r = -1;
 
     caps = cap_init();
-    assert(caps);
+    pa_assert(caps);
 
     cap_clear(caps);
 
     prctl(PR_SET_KEEPCAPS, 0, 0, 0, 0);
 
     if (cap_set_proc(caps) < 0) {
-        pa_log("failed to drop capabilities: %s", pa_cstrerror(errno));
+        pa_log("Failed to drop capabilities: %s", pa_cstrerror(errno));
         goto fail;
     }
 

commit 5e93816e1b96463865b2951abad68b235f149a4e
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Aug 16 19:46:11 2007 +0000

    seperately get high nice level and acquire realtime sched
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1677 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/core-util.c b/src/pulsecore/core-util.c
index 9d846c6..2c5a32e 100644
--- a/src/pulsecore/core-util.c
+++ b/src/pulsecore/core-util.c
@@ -355,8 +355,7 @@ 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;
 
@@ -483,28 +482,37 @@ char *pa_strlcpy(char *b, const char *s, size_t l) {
     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)
@@ -513,62 +521,21 @@ 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
diff --git a/src/pulsecore/core-util.h b/src/pulsecore/core-util.h
index 88ed23f..cb78d32 100644
--- a/src/pulsecore/core-util.h
+++ b/src/pulsecore/core-util.h
@@ -55,6 +55,7 @@ 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);
 

commit 876e682ad8ef324e80c6ef1ec296715dc086fa04
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Aug 16 19:48:49 2007 +0000

    never stay root after startup, even if we don't have capabilites
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1678 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/daemon/main.c b/src/daemon/main.c
index eac470b..cf2e628 100644
--- a/src/daemon/main.c
+++ b/src/daemon/main.c
@@ -336,10 +336,19 @@ 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, "");
@@ -386,7 +395,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) {
         pa_drop_caps();
         pa_drop_root();
     }

commit 2d292befabf5b0a87bc1d6493ef471725de88d41
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Aug 16 19:50:11 2007 +0000

    use realtime scheduling for ALSA and OSS driver threads
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1679 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-alsa-sink.c b/src/modules/module-alsa-sink.c
index cf999a9..f1031b6 100644
--- a/src/modules/module-alsa-sink.c
+++ b/src/modules/module-alsa-sink.c
@@ -527,6 +527,8 @@ static void thread_func(void *userdata) {
 
     pa_log_debug("Thread starting up");
 
+    pa_make_realtime();
+
     pa_thread_mq_install(&u->thread_mq);
     
     if (build_pollfd(u) < 0)
diff --git a/src/modules/module-alsa-source.c b/src/modules/module-alsa-source.c
index 8ff074d..a1de2f2 100644
--- a/src/modules/module-alsa-source.c
+++ b/src/modules/module-alsa-source.c
@@ -516,6 +516,8 @@ static void thread_func(void *userdata) {
 
     pa_log_debug("Thread starting up");
 
+    pa_make_realtime();
+
     pa_thread_mq_install(&u->thread_mq);
     
     if (build_pollfd(u) < 0)
diff --git a/src/modules/module-oss.c b/src/modules/module-oss.c
index d9b5b96..346ccbd 100644
--- a/src/modules/module-oss.c
+++ b/src/modules/module-oss.c
@@ -791,6 +791,8 @@ static void thread_func(void *userdata) {
 
     pa_log_debug("Thread starting up");
 
+    pa_make_realtime();
+
     pa_thread_mq_install(&u->thread_mq);
 
     trigger(u, 0);

commit fa7fc315bd62deb8375194d48e688c808e2919fb
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Aug 22 00:18:04 2007 +0000

    modernizations
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1681 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulse/timeval.c b/src/pulse/timeval.c
index 78ece06..ba1128c 100644
--- a/src/pulse/timeval.c
+++ b/src/pulse/timeval.c
@@ -26,7 +26,6 @@
 #include <config.h>
 #endif
 
-#include <assert.h>
 #include <stddef.h>
 #include <sys/time.h>
 
@@ -34,15 +33,17 @@
 #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).
@@ -54,12 +55,12 @@ struct timeval *pa_gettimeofday(struct timeval *tv) {
 #else
 #define EPOCHFILETIME (116444736000000000LL)
 #endif
-
+    
     FILETIME        ft;
     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,10 @@ 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);
+    pa_assert(a);
+    pa_assert(b);
 
-    /* Check which whan is the earlier time and swap the two arguments if reuqired. */
+    /* 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 +91,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 +103,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,25 +123,25 @@ 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;
diff --git a/src/pulse/timeval.h b/src/pulse/timeval.h
index 1e5627e..dbf4319 100644
--- a/src/pulse/timeval.h
+++ b/src/pulse/timeval.h
@@ -33,6 +33,10 @@
 
 PA_C_DECL_BEGIN
 
+#define PA_MSEC_PER_SEC 1000
+#define PA_USEC_PER_SEC 1000000
+#define PA_NSEC_PER_SEC 1000000000
+
 struct timeval;
 
 /** Return the current timestamp, just like UNIX gettimeofday() */

commit b0b06b0002fc9eb14f2a151796d547543bec6b9b
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Aug 22 00:18:58 2007 +0000

    add more PA_PTR_TO_XXX macros
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1682 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/macro.h b/src/pulsecore/macro.h
index fe944ae..efd0f5e 100644
--- a/src/pulsecore/macro.h
+++ b/src/pulsecore/macro.h
@@ -76,7 +76,14 @@ static inline size_t pa_align(size_t l) {
 
 #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)
+#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)
 
 #endif

commit a0ad42a35f73a9bdc0751cbb902f01da2c3c4b05
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Aug 22 00:19:33 2007 +0000

    add macro for creating static TLS objects
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1683 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/thread.h b/src/pulsecore/thread.h
index ca1fe4d..44b80a0 100644
--- a/src/pulsecore/thread.h
+++ b/src/pulsecore/thread.h
@@ -48,4 +48,30 @@ void pa_tls_free(pa_tls *t);
 void * pa_tls_get(pa_tls *t);
 void *pa_tls_set(pa_tls *t, void *userdata);
 
+/* To make use of the static TLS stuff you have to include once.h, as well */
+
+#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_get(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) {                           \
+        if (name##_tls.tls)                                             \
+            pa_tls_free(name##_tls.tls);                                \
+    }                                                                   \
+    struct __stupid_useless_struct_to_allow_trailing_semicolon
+
+#define PA_STATIC_TLS_GET(name) (name##_tls_get())
+
 #endif

commit b7b119ae00090074ec0bc48da7a0c4b689efa55c
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Aug 22 00:20:13 2007 +0000

    add pa_is_power_of_two() and pa_make_power_of_two() functions
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1684 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/core-util.c b/src/pulsecore/core-util.c
index 2c5a32e..0005e22 100644
--- a/src/pulsecore/core-util.c
+++ b/src/pulsecore/core-util.c
@@ -1208,3 +1208,21 @@ char *pa_truncate_utf8(char *c, size_t l) {
     
     return c;
 }
+
+int pa_is_power_of_two(unsigned n) {
+    return !(n & (n - 1));
+}
+
+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;
+}
diff --git a/src/pulsecore/core-util.h b/src/pulsecore/core-util.h
index cb78d32..29dc2fb 100644
--- a/src/pulsecore/core-util.h
+++ b/src/pulsecore/core-util.h
@@ -97,4 +97,7 @@ int pa_snprintf(char *str, size_t size, const char *format, ...);
 
 char *pa_truncate_utf8(char *c, size_t l);
 
+int pa_is_power_of_two(unsigned n);
+unsigned pa_make_power_of_two(unsigned n);
+
 #endif

commit 531cc3cfaffaeac5f46fc808e20711001b8fc1db
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Aug 22 00:21:00 2007 +0000

    make use of new public function pa_is_power_of_two()
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1685 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/flist.c b/src/pulsecore/flist.c
index 022010b..b0f3228 100644
--- a/src/pulsecore/flist.c
+++ b/src/pulsecore/flist.c
@@ -104,17 +104,13 @@ struct pa_flist {
 
 #define PA_FLIST_CELLS(x) ((struct cell*) ((uint8_t*) (x) + PA_ALIGN(sizeof(struct pa_flist))))
 
-static int is_power_of_two(unsigned size) {
-    return !(size & (size - 1));
-}
-
 pa_flist *pa_flist_new(unsigned size) {
     pa_flist *l;
 
     if (!size)
         size = FLIST_SIZE;
 
-    assert(is_power_of_two(size));
+    assert(pa_is_power_of_two(size));
 
     l = pa_xmalloc0(PA_ALIGN(sizeof(pa_flist)) + (sizeof(struct cell) * size));
 

commit 6bfeef18187ff56b92875e2dd926bf32c3a6c720
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Aug 22 00:21:28 2007 +0000

    rename a few things in a macro to make name collisions less likely
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1686 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/flist.h b/src/pulsecore/flist.h
index 69b9c74..daf0fec 100644
--- a/src/pulsecore/flist.h
+++ b/src/pulsecore/flist.h
@@ -44,25 +44,25 @@ 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, destroy_cb)                 \
+#define PA_STATIC_FLIST_DECLARE(name, size, free_cb)                    \
     static struct {                                                     \
         pa_flist *flist;                                                \
         pa_once once;                                                   \
-    } name##_static_flist = { NULL, PA_ONCE_INIT };                     \
-    static void name##_init(void) {                                     \
-        name##_static_flist.flist = pa_flist_new(size);                 \
+    } name##_flist = { NULL, PA_ONCE_INIT };                            \
+    static void name##_flist_init(void) {                               \
+        name##_flist.flist = pa_flist_new(size);                        \
     }                                                                   \
-    static inline pa_flist* name##_get(void) {                          \
-        pa_run_once(&name##_static_flist.once, name##_init);            \
-        return name##_static_flist.flist;                               \
+    static inline pa_flist* name##_flist_get(void) {                    \
+        pa_run_once(&name##_flist.once, name##_flist_init);             \
+        return name##_flist.flist;                                      \
     }                                                                   \
-    static void name##_destructor(void) PA_GCC_DESTRUCTOR;              \
-    static void name##_destructor(void) {                               \
-        if (name##_static_flist.flist)                                  \
-            pa_flist_free(name##_static_flist.flist, destroy_cb);       \
+    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##_get())
+#define PA_STATIC_FLIST_GET(name) (name##_flist_get())
 
 #endif

commit ef2bc41b875332e7a0bf641b5ecdbe9906ae378c
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Aug 22 00:22:51 2007 +0000

    add monotonic clock abstraction pa_rtclock
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1687 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/rtclock.c b/src/pulsecore/rtclock.c
new file mode 100644
index 0000000..507b899
--- /dev/null
+++ b/src/pulsecore/rtclock.c
@@ -0,0 +1,153 @@
+/* $Id$ */
+
+/***
+  This file is part of PulseAudio.
+
+  Copyright 2004-2006 Lennart Poettering
+  Copyright 2006 Pierre Ossman <ossman at 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 <sys/time.h>
+
+#include <pulse/timeval.h>
+#include <pulsecore/macro.h>
+
+#include "rtclock.h"
+
+struct timespec *pa_timespec_store(struct timespec *a, pa_usec_t u) {
+    pa_assert(a);
+
+    a->tv_sec = u / PA_USEC_PER_SEC;
+
+    u -= (pa_usec_t) a->tv_sec * PA_USEC_PER_SEC;
+    
+    a->tv_nsec = u * 1000;
+
+    return a;
+}
+
+pa_usec_t pa_timespec_load(struct timespec *ts) {
+    pa_assert(ts);
+    
+    return (pa_usec_t) ts->tv_sec * PA_USEC_PER_SEC + (pa_usec_t) (ts->tv_nsec / 1000);
+}
+
+pa_usec_t pa_timespec_diff(const struct timespec *a, const struct timespec *b) {
+    pa_usec_t r;
+    
+    pa_assert(a);
+    pa_assert(b);
+
+    /* Check which whan is the earlier time and swap the two arguments if required. */
+    if (pa_timespec_cmp(a, b) < 0) {
+        const struct timespec *c;
+        c = a;
+        a = b;
+        b = c;
+    }
+
+    /* Calculate the second difference*/
+    r = ((pa_usec_t) a->tv_sec - b->tv_sec) * PA_USEC_PER_SEC;
+
+    /* Calculate the microsecond difference */
+    if (a->tv_nsec > b->tv_nsec)
+        r += (pa_usec_t) ((a->tv_nsec - b->tv_nsec) / 1000);
+    else if (a->tv_nsec < b->tv_nsec)
+        r -= (pa_usec_t) ((b->tv_nsec - a->tv_nsec) / 1000);
+
+    return r;
+}
+
+int pa_timespec_cmp(const struct timespec *a, const struct timespec *b) {
+    pa_assert(a);
+    pa_assert(b);
+
+    if (a->tv_sec < b->tv_sec)
+        return -1;
+
+    if (a->tv_sec > b->tv_sec)
+        return 1;
+
+    if (a->tv_nsec < b->tv_nsec)
+        return -1;
+
+    if (a->tv_nsec > b->tv_nsec)
+        return 1;
+
+    return 0;
+}
+
+struct timespec* pa_timespec_add(struct timespec *ts, pa_usec_t v) {
+    unsigned long secs;
+    pa_assert(ts);
+
+    secs = (unsigned long) (v/PA_USEC_PER_SEC);
+    ts->tv_sec += secs;
+    v -= ((pa_usec_t) secs) * PA_USEC_PER_SEC;
+
+    ts->tv_nsec += (long) (v*1000);
+
+    /* Normalize */
+    while (ts->tv_nsec >= PA_NSEC_PER_SEC) {
+        ts->tv_sec++;
+        ts->tv_nsec -= PA_NSEC_PER_SEC;
+    }
+
+    return ts;
+}
+
+pa_usec_t pa_rtclock_age(const struct timespec *ts) {
+    struct timespec now;
+    pa_assert(ts);
+
+    return pa_timespec_diff(pa_rtclock_get(&now), ts);
+}
+
+struct timespec *pa_rtclock_get(struct timespec *ts) {
+    static int no_monotonic = 0;
+
+    /* No locking or atomic ops for no_monotonic here */
+    
+    pa_assert(ts);
+
+    if (!no_monotonic) {
+        if (clock_gettime(CLOCK_MONOTONIC, ts) >= 0)
+            return ts;
+        
+        no_monotonic = 1;
+    }
+
+    pa_assert_se(clock_gettime(CLOCK_REALTIME, ts) == 0);
+    return ts;
+}
+
+int pa_rtclock_hrtimer(void) {
+    struct timespec ts;
+    
+    if (clock_getres(CLOCK_MONOTONIC, &ts) >= 0)
+        return ts.tv_sec == 0 && ts.tv_nsec <= PA_HRTIMER_THRESHOLD_USEC*1000;
+
+    pa_assert_se(clock_getres(CLOCK_REALTIME, &ts) == 0);
+    return ts.tv_sec == 0 && ts.tv_nsec <= PA_HRTIMER_THRESHOLD_USEC*1000;
+}
+
diff --git a/src/pulsecore/rtclock.h b/src/pulsecore/rtclock.h
new file mode 100644
index 0000000..145533c
--- /dev/null
+++ b/src/pulsecore/rtclock.h
@@ -0,0 +1,48 @@
+#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 <sys/types.h>
+#include <time.h>
+
+#include <pulse/sample.h>
+
+/* Something like pulse/timeval.h but based on CLOCK_MONOTONIC and
+ * timespec instead of timeval */
+
+struct timespec *pa_rtclock_get(struct timespec *ts);
+pa_usec_t pa_rtclock_age(const struct timespec *tv);
+int pa_rtclock_hrtimer(void);
+
+struct timespec *pa_timespec_store(struct timespec *a, pa_usec_t u);
+pa_usec_t pa_timespec_load(struct timespec *tv);
+struct timespec *pa_timespec_add(struct timespec *tv, pa_usec_t t);
+pa_usec_t pa_timespec_diff(const struct timespec *a, const struct timespec *b);
+int pa_timespec_cmp(const struct timespec *a, const struct timespec *b);
+
+/* timer with a resolution better than this are considered high-resolution */
+#define PA_HRTIMER_THRESHOLD_USEC 10
+
+#endif

commit 8972d06bc78ec61792a4c423f19df18f8f8a5838
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Aug 22 00:23:33 2007 +0000

    add facility for managing realtime signals
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1688 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/rtsig.c b/src/pulsecore/rtsig.c
new file mode 100644
index 0000000..1b8cdaa
--- /dev/null
+++ b/src/pulsecore/rtsig.c
@@ -0,0 +1,111 @@
+/* $Id$ */
+
+/***
+  This file is part of PulseAudio.
+
+  Copyright 2004-2006 Lennart Poettering
+  Copyright 2006 Pierre Ossman <ossman at 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 "rtsig.h"
+
+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_inc(&rtsig_current);
+
+    pa_assert(sig >= SIGRTMIN);
+    pa_assert(sig >= rtsig_start);
+    
+    if (sig > rtsig_end) {
+        pa_atomic_dec(&rtsig_current);
+        return -1;
+    }
+
+    return sig;
+}
+
+int pa_rtsig_get_for_thread(void) {
+    int sig;
+    void *p;
+
+    if ((p = pa_tls_get(PA_STATIC_TLS_GET(rtsig_tls))))
+        return PA_PTR_TO_INT(p);
+    
+    if ((sig = pa_rtsig_get()) < 0)
+        return -1;
+
+    pa_tls_set(PA_STATIC_TLS_GET(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);
+    
+    pa_atomic_store(&rtsig_current, rtsig_start);
+}
diff --git a/src/pulsecore/rtsig.h b/src/pulsecore/rtsig.h
new file mode 100644
index 0000000..48f5f05
--- /dev/null
+++ b/src/pulsecore/rtsig.h
@@ -0,0 +1,44 @@
+#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.
+***/
+
+#include <poll.h>
+#include <sys/types.h>
+
+/* 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

commit 78c362c5d92cf56c3e7d87f4fdc2dca84af2f224
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Aug 22 00:24:12 2007 +0000

    add new realtime event loop abstraction which precise time keeping by using hrtimers on Linux, if they are available
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1689 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/rtpoll.c b/src/pulsecore/rtpoll.c
new file mode 100644
index 0000000..36549b5
--- /dev/null
+++ b/src/pulsecore/rtpoll.c
@@ -0,0 +1,454 @@
+/* $Id$ */
+
+/***
+  This file is part of PulseAudio.
+
+  Copyright 2004-2006 Lennart Poettering
+  Copyright 2006 Pierre Ossman <ossman at 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/utsname.h>
+#include <sys/types.h>
+#include <stdio.h>
+#include <signal.h>
+#include <string.h>
+#include <errno.h>
+
+#include <pulse/xmalloc.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 "rtpoll.h"
+
+struct pa_rtpoll {
+
+    struct pollfd *pollfd, *pollfd2;
+    unsigned n_pollfd_alloc, n_pollfd_used;
+
+    pa_usec_t interval;
+
+    int scan_for_dead;
+    int running, installed, rebuild_needed;
+
+#ifdef HAVE_PPOLL
+    int rtsig;
+    sigset_t sigset_unblocked;
+    struct timespec interval_timespec;
+    timer_t timer;
+#ifdef __linux__
+    int dont_use_ppoll;
+#endif    
+#endif
+    
+    PA_LLIST_HEAD(pa_rtpoll_item, items);
+};
+
+struct pa_rtpoll_item {
+    pa_rtpoll *rtpoll;
+    int dead;
+
+    struct pollfd *pollfd;
+    unsigned n_pollfd;
+
+    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 = 0;
+
+    {
+        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 = 1;
+    }
+
+#endif
+
+    p->rtsig = -1;
+    sigemptyset(&p->sigset_unblocked);
+    memset(&p->interval_timespec, 0, sizeof(p->interval_timespec));
+    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->interval = 0;
+
+    p->running = 0;
+    p->installed = 0;
+    p->scan_for_dead = 0;
+    p->rebuild_needed = 0;
+    
+    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 SIGRTMIN+%i", p->rtsig - SIGRTMIN);
+
+    {
+        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 = 0;
+
+    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 = 1;
+}
+
+void pa_rtpoll_free(pa_rtpoll *p) {
+    pa_assert(p);
+
+    pa_assert(!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);
+}
+
+int pa_rtpoll_run(pa_rtpoll *p) {
+    pa_rtpoll_item *i;
+    int r = 0;
+    
+    pa_assert(p);
+    pa_assert(!p->running);
+    pa_assert(p->installed);
+    
+    p->running = 1;
+
+    for (i = p->items; i; i = i->next) {
+
+        if (i->dead)
+            continue;
+        
+        if (!i->before_cb)
+            continue;
+
+        if (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);
+            }
+            
+            goto finish;
+        }
+    }
+
+    if (p->rebuild_needed)
+        rtpoll_rebuild(p);
+    
+    /* OK, now let's sleep */
+#ifdef HAVE_PPOLL
+
+#ifdef __linux__
+    if (!p->dont_use_ppoll)
+#endif
+        r = ppoll(p->pollfd, p->n_pollfd_used, p->interval > 0  ? &p->interval_timespec : NULL, p->rtsig < 0 ? NULL : &p->sigset_unblocked);
+#ifdef __linux__
+    else
+#endif
+
+#else
+        r = poll(p->pollfd, p->n_pollfd_used, p->interval > 0 ? p->interval / 1000 : -1);
+#endif
+
+    if (r < 0 && (errno == EAGAIN || errno == EINTR))
+        r = 0;
+
+    for (i = p->items; i; i = i->next) {
+
+        if (i->dead)
+            continue;
+
+        if (!i->after_cb)
+            continue;
+
+        i->after_cb(i);
+    }
+
+finish:
+
+    p->running = 0;
+        
+    if (p->scan_for_dead) {
+        pa_rtpoll_item *n;
+
+        p->scan_for_dead = 0;
+        
+        for (i = p->items; i; i = n) {
+            n = i->next;
+
+            if (i->dead)
+                rtpoll_item_destroy(i);
+        }
+    }
+
+    return r;
+}
+
+void pa_rtpoll_set_itimer(pa_rtpoll *p, pa_usec_t usec) {
+    pa_assert(p);
+
+    p->interval = usec;
+
+#ifdef HAVE_PPOLL
+    pa_timespec_store(&p->interval_timespec, usec);
+
+#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));
+            pa_timespec_store(&its.it_value, usec);
+            pa_timespec_store(&its.it_interval, usec);
+
+            assert(timer_settime(p->timer, 0, &its, NULL) == 0);
+        }
+
+#ifdef __linux__
+    }
+#endif
+    
+#endif
+}
+
+pa_rtpoll_item *pa_rtpoll_item_new(pa_rtpoll *p, unsigned n_fds) {
+    pa_rtpoll_item *i;
+    
+    pa_assert(p);
+    pa_assert(n_fds > 0);
+
+    if (!(i = pa_flist_pop(PA_STATIC_FLIST_GET(items))))
+        i = pa_xnew(pa_rtpoll_item, 1);
+
+    i->rtpoll = p;
+    i->dead = 0;
+    i->n_pollfd = n_fds;
+    i->pollfd = NULL;
+
+    i->userdata = NULL;
+    i->before_cb = NULL;
+    i->after_cb = NULL;
+    
+    PA_LLIST_PREPEND(pa_rtpoll_item, p->items, i);
+
+    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 = 1;
+        i->rtpoll->scan_for_dead = 1;
+        return;
+    }
+
+    rtpoll_item_destroy(i);
+}
+
+struct pollfd *pa_rtpoll_item_get_pollfd(pa_rtpoll_item *i, unsigned *n_fds) {
+    pa_assert(i);
+
+    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);
+
+    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);
+
+    i->after_cb = after_cb;
+}
+
+void pa_rtpoll_item_set_userdata(pa_rtpoll_item *i, void *userdata) {
+    pa_assert(i);
+
+    i->userdata = userdata;
+}
diff --git a/src/pulsecore/rtpoll.h b/src/pulsecore/rtpoll.h
new file mode 100644
index 0000000..5e508e1
--- /dev/null
+++ b/src/pulsecore/rtpoll.h
@@ -0,0 +1,71 @@
+#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 <poll.h>
+#include <sys/types.h>
+
+#include <pulse/sample.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;
+
+pa_rtpoll *pa_rtpoll_new(void);
+void pa_rtpoll_free(pa_rtpoll *p);
+
+void pa_rtpoll_install(pa_rtpoll *p);
+
+int pa_rtpoll_run(pa_rtpoll *f);
+void pa_rtpoll_set_itimer(pa_rtpoll *p, pa_usec_t usec);
+
+pa_rtpoll_item *pa_rtpoll_item_new(pa_rtpoll *p, unsigned n_fds);
+void pa_rtpoll_item_free(pa_rtpoll_item *i);
+
+struct pollfd *pa_rtpoll_item_get_pollfd(pa_rtpoll_item *i, unsigned *n_fds);
+
+void pa_rtpoll_item_set_before_callback(pa_rtpoll_item *i, int (*before_cb)(pa_rtpoll_item *i));
+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);
+
+#endif

commit dc9d80326e29d20d42fbfc6055963c66c378b596
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Aug 22 00:24:31 2007 +0000

    add test program for pa_rtpoll
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1690 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/tests/rtpoll-test.c b/src/tests/rtpoll-test.c
new file mode 100644
index 0000000..29f2e92
--- /dev/null
+++ b/src/tests/rtpoll-test.c
@@ -0,0 +1,80 @@
+/* $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 <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");
+}
+
+int main(int argc, char *argv[]) {
+    pa_rtpoll *p;
+    pa_rtpoll_item *i;
+    struct pollfd *pollfd;
+
+    pa_rtsig_configure(SIGRTMIN+10, SIGRTMAX);
+    
+    p = pa_rtpoll_new();
+
+    i = pa_rtpoll_item_new(p, 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_install(p);
+    pa_rtpoll_set_itimer(p, 10000000); /* 10 s */
+
+    pa_rtpoll_run(p);
+    
+    pa_rtpoll_item_free(i);
+    
+    i = pa_rtpoll_item_new(p, 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);
+
+    pa_rtpoll_item_free(i);
+    
+    pa_rtpoll_free(p);
+
+    return 0;
+}

commit 8568f7038cc855b98d0959c60efe7acb912b4e77
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Aug 22 00:25:03 2007 +0000

    add rtpoll, rtclock, rtsig to Makefile
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1691 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/Makefile.am b/src/Makefile.am
index a711de2..9b843a4 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -238,7 +238,8 @@ noinst_PROGRAMS = \
 		flist-test \
 		asyncq-test \
 		asyncmsgq-test \
-		queue-test
+		queue-test \
+		rtpoll-test
 
 if HAVE_SIGXCPU
 noinst_PROGRAMS += \
@@ -313,6 +314,11 @@ 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
@@ -680,6 +686,9 @@ libpulsecore_la_SOURCES += \
 		pulsecore/fdsem.c pulsecore/fdsem.h \
 		pulsecore/object.c pulsecore/object.h \
 		pulsecore/msgobject.c pulsecore/msgobject.h \
+		pulsecore/rtsig.c pulsecore/rtsog.h \
+		pulsecore/rtpoll.c pulsecore/rtpoll.h \
+		pulsecore/rtclock.c pulsecore/rtclock.h \
 		pulsecore/macro.h \
 		$(PA_THREAD_OBJS)
 

commit 35461981c68ce656b194faf30d892fa35a9ed9b7
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Aug 22 00:25:29 2007 +0000

    add check for ppoll()
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1692 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/configure.ac b/configure.ac
index b037b89..d998330 100644
--- a/configure.ac
+++ b/configure.ac
@@ -255,7 +255,7 @@ 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])
 
 #### POSIX threads ####
 

commit b3029464a4cc0348649beeeea76e459b384addd5
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Aug 22 00:26:43 2007 +0000

    add new option to pa_core stating whether we are running as high prio process
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1693 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/core.c b/src/pulsecore/core.c
index 2e9d96b..7ca2e75 100644
--- a/src/pulsecore/core.c
+++ b/src/pulsecore/core.c
@@ -127,8 +127,6 @@ 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;
@@ -138,6 +136,9 @@ pa_core* pa_core_new(pa_mainloop_api *m, int shared) {
     c->resample_method = PA_RESAMPLER_SRC_SINC_FASTEST;
 
     c->is_system_instance = 0;
+    c->disallow_module_loading = 0;
+    c->high_priority = 0;
+
 
     for (j = 0; j < PA_CORE_HOOK_MAX; j++)
         pa_hook_init(&c->hooks[j], c);
diff --git a/src/pulsecore/core.h b/src/pulsecore/core.h
index 4d92960..61cb47d 100644
--- a/src/pulsecore/core.h
+++ b/src/pulsecore/core.h
@@ -101,16 +101,16 @@ 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 hooks[PA_CORE_HOOK_MAX];

commit 7fca89034f9822c51c2ccea2fb3df126dbd12aea
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Aug 22 00:27:25 2007 +0000

    check pa_core::high_priority before becoming rt thread
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1694 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-alsa-sink.c b/src/modules/module-alsa-sink.c
index f1031b6..5546657 100644
--- a/src/modules/module-alsa-sink.c
+++ b/src/modules/module-alsa-sink.c
@@ -527,7 +527,8 @@ static void thread_func(void *userdata) {
 
     pa_log_debug("Thread starting up");
 
-    pa_make_realtime();
+    if (u->core->high_priority)
+        pa_make_realtime();
 
     pa_thread_mq_install(&u->thread_mq);
     
diff --git a/src/modules/module-alsa-source.c b/src/modules/module-alsa-source.c
index a1de2f2..58e7cb4 100644
--- a/src/modules/module-alsa-source.c
+++ b/src/modules/module-alsa-source.c
@@ -516,7 +516,8 @@ static void thread_func(void *userdata) {
 
     pa_log_debug("Thread starting up");
 
-    pa_make_realtime();
+    if (u->core->high_priority)
+        pa_make_realtime();
 
     pa_thread_mq_install(&u->thread_mq);
     
diff --git a/src/modules/module-oss.c b/src/modules/module-oss.c
index 346ccbd..f445481 100644
--- a/src/modules/module-oss.c
+++ b/src/modules/module-oss.c
@@ -791,7 +791,8 @@ static void thread_func(void *userdata) {
 
     pa_log_debug("Thread starting up");
 
-    pa_make_realtime();
+    if (u->core->high_priority)
+        pa_make_realtime();
 
     pa_thread_mq_install(&u->thread_mq);
 

commit 0da65cf3df16b6e9249be40beb0e2ac94cd7f00c
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Aug 22 00:29:15 2007 +0000

    add message about hrtimers, and initialize pa_core::high_priority
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1696 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/daemon/main.c b/src/daemon/main.c
index cf2e628..76adb10 100644
--- a/src/daemon/main.c
+++ b/src/daemon/main.c
@@ -78,6 +78,7 @@
 #include <pulsecore/pid.h>
 #include <pulsecore/namereg.h>
 #include <pulsecore/random.h>
+#include <pulsecore/rtsig.h>
 
 #include "cmdline.h"
 #include "cpulimit.h"
@@ -395,7 +396,7 @@ int main(int argc, char *argv[]) {
     if (conf->high_priority && conf->cmd == PA_CMD_DAEMON)
         pa_raise_priority();
 
-    if (suid_root && conf->cmd != PA_CMD_DAEMON) {
+    if (suid_root && (conf->cmd != PA_CMD_DAEMON || !conf->high_priority)) {
         pa_drop_caps();
         pa_drop_root();
     }
@@ -543,7 +544,7 @@ int main(int argc, char *argv[]) {
 #endif
     }
 
-    chdir("/");
+    pa_assert(chdir("/") == 0);
     umask(0022);
 
     if (conf->system_instance) {
@@ -573,21 +574,28 @@ int main(int argc, char *argv[]) {
     signal(SIGPIPE, SIG_IGN);
 #endif
 
+    if (!pa_rtclock_hrtimer())
+        pa_log_debug("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!");
+    
+    pa_rtsig_configure(SIGRTMIN+10, SIGRTMAX);
+
     mainloop = pa_mainloop_new();
     assert(mainloop);
 
     if (!(c = pa_core_new(pa_mainloop_get_api(mainloop), !conf->disable_shm))) {
-            pa_log("pa_core_new() failed.");
+        pa_log("pa_core_new() failed.");
         goto finish;
     }
 
     c->is_system_instance = !!conf->system_instance;
+    c->high_priority = !!conf->high_priority;
     c->default_sample_spec = conf->default_sample_spec;
     c->default_n_fragments = conf->default_n_fragments;
     c->default_fragment_size_msec = conf->default_fragment_size_msec;
 
-    r = pa_signal_init(pa_mainloop_get_api(mainloop));
-    assert(r == 0);
+    pa_assert_se(pa_signal_init(pa_mainloop_get_api(mainloop)) == 0);
     pa_signal_new(SIGINT, signal_callback, c);
     pa_signal_new(SIGTERM, signal_callback, c);
 

commit 190648a3ed1267896083a24dbb27d7552104ca00
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Aug 22 17:05:07 2007 +0000

    add missing #include
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1697 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/flist.c b/src/pulsecore/flist.c
index b0f3228..ada0d57 100644
--- a/src/pulsecore/flist.c
+++ b/src/pulsecore/flist.c
@@ -31,6 +31,7 @@
 #include <pulsecore/log.h>
 #include <pulsecore/thread.h>
 #include <pulsecore/macro.h>
+#include <pulsecore/core-util.h>
 #include <pulse/xmalloc.h>
 
 #include "flist.h"

commit 044996685258c69e120de7198b3cfbb96faa50ba
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Aug 22 17:05:41 2007 +0000

    make pa_make_power_of_two() and pa_is_power_of_two() inline functions
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1698 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/core-util.c b/src/pulsecore/core-util.c
index 0005e22..2c5a32e 100644
--- a/src/pulsecore/core-util.c
+++ b/src/pulsecore/core-util.c
@@ -1208,21 +1208,3 @@ char *pa_truncate_utf8(char *c, size_t l) {
     
     return c;
 }
-
-int pa_is_power_of_two(unsigned n) {
-    return !(n & (n - 1));
-}
-
-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;
-}
diff --git a/src/pulsecore/core-util.h b/src/pulsecore/core-util.h
index 29dc2fb..ea571e7 100644
--- a/src/pulsecore/core-util.h
+++ b/src/pulsecore/core-util.h
@@ -97,7 +97,22 @@ int pa_snprintf(char *str, size_t size, const char *format, ...);
 
 char *pa_truncate_utf8(char *c, size_t l);
 
-int pa_is_power_of_two(unsigned n);
-unsigned pa_make_power_of_two(unsigned n);
+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;
+}
 
 #endif

commit 7490977a84bf9b451bfee406b1e3f7925b669afa
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Aug 22 17:06:04 2007 +0000

    add missing include
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1699 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/rtsig.c b/src/pulsecore/rtsig.c
index 1b8cdaa..a3226a0 100644
--- a/src/pulsecore/rtsig.c
+++ b/src/pulsecore/rtsig.c
@@ -32,6 +32,7 @@
 #include <pulsecore/flist.h>
 #include <pulsecore/once.h>
 #include <pulsecore/thread.h>
+#include <pulsecore/core-util.h>
 
 #include "rtsig.h"
 

commit b937009bcd4f4bb6e6f012c90d27ac667592588a
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Aug 22 17:11:26 2007 +0000

    add convenience functions to hook up pa_fdsem and pa_asyncmsgq to an pa_rtpoll; add pa_rtpoll_item_get_userdata(), on EINTR/EAGAIN, reset revents; automatically destory left over items
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1700 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/rtpoll.c b/src/pulsecore/rtpoll.c
index 36549b5..4f39c68 100644
--- a/src/pulsecore/rtpoll.c
+++ b/src/pulsecore/rtpoll.c
@@ -241,7 +241,9 @@ static void rtpoll_item_destroy(pa_rtpoll_item *i) {
 void pa_rtpoll_free(pa_rtpoll *p) {
     pa_assert(p);
 
-    pa_assert(!p->items);
+    while (p->items)
+        rtpoll_item_destroy(p->items);
+    
     pa_xfree(p->pollfd);
     pa_xfree(p->pollfd2);
 
@@ -256,6 +258,8 @@ void pa_rtpoll_free(pa_rtpoll *p) {
 int pa_rtpoll_run(pa_rtpoll *p) {
     pa_rtpoll_item *i;
     int r = 0;
+    int no_events = 0;
+    int saved_errno;
     
     pa_assert(p);
     pa_assert(!p->running);
@@ -308,8 +312,12 @@ int pa_rtpoll_run(pa_rtpoll *p) {
         r = poll(p->pollfd, p->n_pollfd_used, p->interval > 0 ? p->interval / 1000 : -1);
 #endif
 
-    if (r < 0 && (errno == EAGAIN || errno == EINTR))
+    saved_errno = errno;
+    
+    if (r < 0 && (errno == EAGAIN || errno == EINTR)) {
         r = 0;
+        no_events = 1;
+    }
 
     for (i = p->items; i; i = i->next) {
 
@@ -319,6 +327,13 @@ int pa_rtpoll_run(pa_rtpoll *p) {
         if (!i->after_cb)
             continue;
 
+        if (no_events) {
+            unsigned j;
+
+            for (j = 0; j < i->n_pollfd; j++)
+                i->pollfd[j].revents = 0;
+        }
+        
         i->after_cb(i);
     }
 
@@ -339,6 +354,8 @@ finish:
         }
     }
 
+    errno = saved_errno;
+
     return r;
 }
 
@@ -452,3 +469,68 @@ void pa_rtpoll_item_set_userdata(pa_rtpoll_item *i, void *userdata) {
 
     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) {
+    return pa_fdsem_before_poll(i->userdata);
+}
+
+static void fdsem_after(pa_rtpoll_item *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_fdsem *f) {
+    pa_rtpoll_item *i;
+    struct pollfd *pollfd;
+    
+    pa_assert(p);
+    pa_assert(f);
+
+    i = pa_rtpoll_item_new(p, 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) {
+    return pa_asyncmsgq_before_poll(i->userdata);
+}
+
+static void asyncmsgq_after(pa_rtpoll_item *i) {
+    pa_assert((i->pollfd[0].revents & ~POLLIN) == 0);
+    pa_asyncmsgq_after_poll(i->userdata);
+}
+
+pa_rtpoll_item *pa_rtpoll_item_new_asyncmsgq(pa_rtpoll *p, pa_asyncmsgq *q) {
+    pa_rtpoll_item *i;
+    struct pollfd *pollfd;
+    
+    pa_assert(p);
+    pa_assert(q);
+
+    i = pa_rtpoll_item_new(p, 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->userdata = q;
+
+    return i;
+}
diff --git a/src/pulsecore/rtpoll.h b/src/pulsecore/rtpoll.h
index 5e508e1..bed3ae3 100644
--- a/src/pulsecore/rtpoll.h
+++ b/src/pulsecore/rtpoll.h
@@ -28,6 +28,8 @@
 #include <sys/types.h>
 
 #include <pulse/sample.h>
+#include <pulsecore/asyncmsgq.h>
+#include <pulsecore/fdsem.h>
 
 /* An implementation of a "real-time" poll loop. Basically, this is
  * yet another wrapper around poll(). However it has certain
@@ -67,5 +69,10 @@ struct pollfd *pa_rtpoll_item_get_pollfd(pa_rtpoll_item *i, unsigned *n_fds);
 void pa_rtpoll_item_set_before_callback(pa_rtpoll_item *i, int (*before_cb)(pa_rtpoll_item *i));
 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_fdsem *s);
+pa_rtpoll_item *pa_rtpoll_item_new_asyncmsgq(pa_rtpoll *p, pa_asyncmsgq *q);
+
 
 #endif

commit 79d3dddecdb979e8275dc15b015075a8f6037095
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Aug 22 17:11:54 2007 +0000

    reverse hrtimer check, add missing #include
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1701 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/daemon/main.c b/src/daemon/main.c
index 76adb10..15d3592 100644
--- a/src/daemon/main.c
+++ b/src/daemon/main.c
@@ -79,6 +79,7 @@
 #include <pulsecore/namereg.h>
 #include <pulsecore/random.h>
 #include <pulsecore/rtsig.h>
+#include <pulsecore/rtclock.h>
 
 #include "cmdline.h"
 #include "cpulimit.h"
@@ -574,7 +575,7 @@ int main(int argc, char *argv[]) {
     signal(SIGPIPE, SIG_IGN);
 #endif
 
-    if (!pa_rtclock_hrtimer())
+    if (pa_rtclock_hrtimer())
         pa_log_debug("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!");

commit 53b872c07067a606515d5946b709d02657337086
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Aug 22 17:13:07 2007 +0000

    port alsa driver to make use of new pa_rtpoll object
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1702 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-alsa-sink.c b/src/modules/module-alsa-sink.c
index 5546657..3e52148 100644
--- a/src/modules/module-alsa-sink.c
+++ b/src/modules/module-alsa-sink.c
@@ -51,6 +51,7 @@
 #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"
@@ -75,8 +76,10 @@ 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;
 
@@ -95,13 +98,7 @@ struct userdata {
 
     int first;
 
-    struct pollfd *pollfd;
-    int n_alsa_fds;
-};
-
-enum {
-    POLLFD_ASYNCQ,
-    POLLFD_ALSA_BASE
+    pa_rtpoll_item *alsa_rtpoll_item;
 };
 
 static const char* const valid_modargs[] = {
@@ -118,18 +115,18 @@ static const char* const valid_modargs[] = {
 };
 
 static int mmap_write(struct userdata *u) {
-    snd_pcm_sframes_t n;
-    int err;
-    const snd_pcm_channel_area_t *areas;
-    snd_pcm_uframes_t offset, frames;
     int work_done = 0;
     
     pa_assert(u);
-    pa_assert(u->sink);
+    pa_sink_assert_ref(u->sink);
 
     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) {
 
@@ -211,10 +208,85 @@ static int mmap_write(struct userdata *u) {
 
         work_done = 1;
 
+        if (frames >= (snd_pcm_uframes_t) n)
+            return work_done;
+        
 /*         pa_log("wrote %i samples", (int) frames); */
     }
 }
 
+static int unix_write(struct userdata *u) {
+    snd_pcm_status_t *status;
+    int work_done = 0;
+
+    snd_pcm_status_alloca(&status);
+    
+    pa_assert(u);
+    pa_sink_assert_ref(u->sink);
+
+    for (;;) {
+        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(t));
+            return -1;
+        }
+
+        if (snd_pcm_status_get_avail_max(status)*u->frame_size >= u->hwbuf_size)
+            pa_log_debug("Buffer underrun!");
+                    
+        l = snd_pcm_status_get_avail(status) * u->frame_size;
+
+/*                     pa_log("%u bytes to write", l); */
+                    
+        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);
+                    
+        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;
+            }
+        }
+                        
+        u->memchunk.index += t * u->frame_size;
+        u->memchunk.length -= t * u->frame_size;
+                    
+        if (u->memchunk.length <= 0) {
+            pa_memblock_unref(u->memchunk.memblock);
+            pa_memchunk_reset(&u->memchunk);
+        }
+
+        work_done = 1;
+
+        if (t * u->frame_size >= (unsigned) l)
+            return work_done;
+    } 
+}
+
 static pa_usec_t sink_get_latency(struct userdata *u) {
     pa_usec_t r = 0;
     snd_pcm_status_t *status;
@@ -224,6 +296,7 @@ static pa_usec_t sink_get_latency(struct userdata *u) {
     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));
@@ -241,22 +314,24 @@ static pa_usec_t sink_get_latency(struct userdata *u) {
 
 static int build_pollfd(struct userdata *u) {
     int err;
+    struct pollfd *pollfd;
+    int n;
     
     pa_assert(u);
     pa_assert(u->pcm_handle);
 
-    if ((u->n_alsa_fds = snd_pcm_poll_descriptors_count(u->pcm_handle)) < 0) {
-        pa_log("snd_pcm_poll_descriptors_count() failed: %s", snd_strerror(u->n_alsa_fds));
+    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;
     }
 
-    pa_xfree(u->pollfd);
-    u->pollfd = pa_xnew0(struct pollfd, POLLFD_ALSA_BASE + u->n_alsa_fds);
+    if (u->alsa_rtpoll_item)
+        pa_rtpoll_item_free(u->alsa_rtpoll_item);
 
-    u->pollfd[POLLFD_ASYNCQ].fd = pa_asyncmsgq_get_fd(u->thread_mq.inq);
-    u->pollfd[POLLFD_ASYNCQ].events = POLLIN;
+    u->alsa_rtpoll_item = pa_rtpoll_item_new(u->rtpoll, n);
+    pollfd = pa_rtpoll_item_get_pollfd(u->alsa_rtpoll_item, NULL);
 
-    if ((err = snd_pcm_poll_descriptors(u->pcm_handle, u->pollfd+POLLFD_ALSA_BASE, u->n_alsa_fds)) < 0) {
+    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;
     }
@@ -272,6 +347,11 @@ static int suspend(struct userdata *u) {
     snd_pcm_close(u->pcm_handle);
     u->pcm_handle = NULL;
 
+    if (u->alsa_rtpoll_item) {
+        pa_rtpoll_item_free(u->alsa_rtpoll_item);
+        u->alsa_rtpoll_item = NULL;
+    }
+    
     pa_log_debug("Device suspended...");
     
     return 0;
@@ -516,14 +596,9 @@ static int sink_set_mute_cb(pa_sink *s) {
 }
 
 static void thread_func(void *userdata) {
-
     struct userdata *u = userdata;
-    unsigned short revents = 0;
-    snd_pcm_status_t *status;
-    int err;
     
     pa_assert(u);
-    snd_pcm_status_alloca(&status);
 
     pa_log_debug("Thread starting up");
 
@@ -531,6 +606,7 @@ static void thread_func(void *userdata) {
         pa_make_realtime();
 
     pa_thread_mq_install(&u->thread_mq);
+    pa_rtpoll_install(u->rtpoll);
     
     if (build_pollfd(u) < 0)
         goto fail;
@@ -541,142 +617,64 @@ static void thread_func(void *userdata) {
         void *data;
         pa_memchunk chunk;
         int64_t offset;
-        int r;
 
 /*         pa_log("loop");      */
         
-        /* Check whether there is a message for us to process */
-        if (pa_asyncmsgq_get(u->thread_mq.inq, &object, &code, &data, &offset, &chunk, 0) == 0) {
-            int ret;
-
-/*             pa_log("processing msg");  */
-
-            if (!object && code == PA_MESSAGE_SHUTDOWN) {
-                pa_asyncmsgq_done(u->thread_mq.inq, 0);
-                goto finish;
-            }
-
-            ret = pa_asyncmsgq_dispatch(object, code, data, offset, &chunk);
-            pa_asyncmsgq_done(u->thread_mq.inq, ret);
-            continue;
-        } 
-
-/*         pa_log("loop2"); */
-
         /* Render some data and write it to the dsp */
-
-        if (PA_SINK_OPENED(u->sink->thread_info.state) && ((revents & POLLOUT) || u->first == 1)) {
+        if (PA_SINK_OPENED(u->sink->thread_info.state)) {
             int work_done = 0;
+            
             pa_assert(u->pcm_handle);
 
             if (u->use_mmap) {
-
                 if ((work_done = mmap_write(u)) < 0)
                     goto fail;
-
             } else {
-                
-                for (;;) {
-                    void *p;
-                    snd_pcm_sframes_t t;
-                    ssize_t l;
-                
-                    if ((err = snd_pcm_status(u->pcm_handle, status)) < 0) {
-                        pa_log("Failed to query DSP status data: %s", snd_strerror(t));
-                        goto fail;
-                    }
-
-                    if (snd_pcm_status_get_avail_max(status)*u->frame_size >= u->hwbuf_size)
-                        pa_log_debug("Buffer underrun!");
-                    
-                    l = snd_pcm_status_get_avail(status) * u->frame_size;
-
-/*                     pa_log("%u bytes to write", l); */
-                    
-                    if (l <= 0)
-                        break;
-                    
-                    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 = 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");
-                            break;
-                        } else {
-                            pa_log("Failed to write data to DSP: %s", snd_strerror(t));
-                            goto fail;
-                        }
-                    }
-                        
-                    u->memchunk.index += t * u->frame_size;
-                    u->memchunk.length -= t * u->frame_size;
-                    
-                    if (u->memchunk.length <= 0) {
-                        pa_memblock_unref(u->memchunk.memblock);
-                        pa_memchunk_reset(&u->memchunk);
-                    }
-
-                    work_done = 1;
-
-                    if (t * u->frame_size >= (unsigned) l)
-                        break;
-                } 
+                if ((work_done = unix_write(u)) < 0)
+                    goto fail;
             }
 
-            revents &= ~POLLOUT;
-            
-            if (work_done) {
-
-                if (u->first) {
-                    pa_log_info("Starting playback.");
-                    snd_pcm_start(u->pcm_handle);
-                    u->first = 0;
-                }
-            
+            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 (pa_asyncmsgq_before_poll(u->thread_mq.inq) < 0)
-            continue;
+/*         pa_log("loop2"); */
 
-/*         pa_log("polling for %i", POLLFD_ALSA_BASE + (PA_SINK_OPENED(u->sink->thread_info.state) ? u->n_alsa_fds : 0));    */
-        r = poll(u->pollfd, POLLFD_ALSA_BASE + (PA_SINK_OPENED(u->sink->thread_info.state) ? u->n_alsa_fds : 0), -1);
-/*         pa_log("poll end"); */
+        /* Check whether there is a message for us to process */
+        if (pa_asyncmsgq_get(u->thread_mq.inq, &object, &code, &data, &offset, &chunk, 0) == 0) {
+            int ret;
 
-        pa_asyncmsgq_after_poll(u->thread_mq.inq);
+/*             pa_log("processing msg");  */
 
-        if (r < 0) {
-            if (errno == EINTR) {
-                u->pollfd[POLLFD_ASYNCQ].revents = 0;
-                revents = 0;
-                continue;
+            if (!object && code == PA_MESSAGE_SHUTDOWN) {
+                pa_asyncmsgq_done(u->thread_mq.inq, 0);
+                goto finish;
             }
 
+            ret = pa_asyncmsgq_dispatch(object, code, data, offset, &chunk);
+            pa_asyncmsgq_done(u->thread_mq.inq, ret);
+            continue;
+        } 
+
+        /* Hmm, nothing to do. Let's sleep */
+        if (pa_rtpoll_run(u->rtpoll) < 0) {
             pa_log("poll() failed: %s", pa_cstrerror(errno));
             goto fail;
         }
 
-        pa_assert(r > 0);
-
         if (PA_SINK_OPENED(u->sink->thread_info.state)) {
-            if ((err = snd_pcm_poll_descriptors_revents(u->pcm_handle, u->pollfd + POLLFD_ALSA_BASE, u->n_alsa_fds, &revents)) < 0) {
+            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;
             }
@@ -692,10 +690,8 @@ static void thread_func(void *userdata) {
                 goto fail;
             }
 /*             pa_log("got alsa event"); */
-        } else
-            revents = 0;
+        }
         
-        pa_assert((u->pollfd[POLLFD_ASYNCQ].revents & ~POLLIN) == 0);
     }
 
 fail:
@@ -764,9 +760,10 @@ int pa__init(pa_module*m) {
     m->userdata = u;
     u->use_mmap = use_mmap;
     u->first = 1;
-    u->n_alsa_fds = 0;
-    u->pollfd = NULL;
     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, 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) {
@@ -943,13 +940,19 @@ void pa__done(pa_module*m) {
     }
 
     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->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);
     
@@ -961,7 +964,6 @@ void pa__done(pa_module*m) {
         snd_pcm_close(u->pcm_handle);
     }
 
-    pa_xfree(u->pollfd);
     pa_xfree(u->device_name);
     pa_xfree(u);
     

commit 0ff2afd8a65517c6f0458dc936108bd64ad9afa1
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Aug 22 22:26:30 2007 +0000

    support absolute, relative and periodic timers in pa_rtpoll
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1703 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/rtpoll.c b/src/pulsecore/rtpoll.c
index 4f39c68..0f09c7d 100644
--- a/src/pulsecore/rtpoll.c
+++ b/src/pulsecore/rtpoll.c
@@ -49,7 +49,9 @@ struct pa_rtpoll {
     struct pollfd *pollfd, *pollfd2;
     unsigned n_pollfd_alloc, n_pollfd_used;
 
-    pa_usec_t interval;
+    int timer_enabled;
+    struct timespec next_elapse;
+    pa_usec_t period;
 
     int scan_for_dead;
     int running, installed, rebuild_needed;
@@ -57,7 +59,6 @@ struct pa_rtpoll {
 #ifdef HAVE_PPOLL
     int rtsig;
     sigset_t sigset_unblocked;
-    struct timespec interval_timespec;
     timer_t timer;
 #ifdef __linux__
     int dont_use_ppoll;
@@ -115,7 +116,6 @@ pa_rtpoll *pa_rtpoll_new(void) {
 
     p->rtsig = -1;
     sigemptyset(&p->sigset_unblocked);
-    memset(&p->interval_timespec, 0, sizeof(p->interval_timespec));
     p->timer = (timer_t) -1;
         
 #endif
@@ -125,7 +125,9 @@ pa_rtpoll *pa_rtpoll_new(void) {
     p->pollfd2 = pa_xnew(struct pollfd, p->n_pollfd_alloc);
     p->n_pollfd_used = 0;
 
-    p->interval = 0;
+    p->period = 0;
+    memset(&p->next_elapse, 0, sizeof(p->next_elapse));
+    p->timer_enabled = 0;
 
     p->running = 0;
     p->installed = 0;
@@ -260,6 +262,7 @@ int pa_rtpoll_run(pa_rtpoll *p) {
     int r = 0;
     int no_events = 0;
     int saved_errno;
+    struct timespec timeout;
     
     pa_assert(p);
     pa_assert(!p->running);
@@ -296,6 +299,17 @@ int pa_rtpoll_run(pa_rtpoll *p) {
 
     if (p->rebuild_needed)
         rtpoll_rebuild(p);
+
+    /* Calculate timeout */
+    if (p->timer_enabled) {
+        struct timespec now;
+        pa_rtclock_get(&now);
+
+        if (pa_timespec_cmp(&p->next_elapse, &now) <= 0)
+            memset(&timeout, 0, sizeof(timeout));
+        else
+            pa_timespec_store(&timeout, pa_timespec_diff(&p->next_elapse, &now));
+    }
     
     /* OK, now let's sleep */
 #ifdef HAVE_PPOLL
@@ -303,18 +317,33 @@ int pa_rtpoll_run(pa_rtpoll *p) {
 #ifdef __linux__
     if (!p->dont_use_ppoll)
 #endif
-        r = ppoll(p->pollfd, p->n_pollfd_used, p->interval > 0  ? &p->interval_timespec : NULL, p->rtsig < 0 ? NULL : &p->sigset_unblocked);
+        r = ppoll(p->pollfd, p->n_pollfd_used, p->timer_enabled > 0  ? &timeout : NULL, p->rtsig < 0 ? NULL : &p->sigset_unblocked);
 #ifdef __linux__
     else
 #endif
 
 #else
-        r = poll(p->pollfd, p->n_pollfd_used, p->interval > 0 ? p->interval / 1000 : -1);
+        r = poll(p->pollfd, p->n_pollfd_used, p->timer_enabled > 0 ? (timeout.tv_sec*1000) + (timeout.tv_nsec / 1000000) : -1);
 #endif
 
     saved_errno = errno;
+
+    if (p->timer_enabled) {
+        if (p->period > 0) {
+            struct timespec now;
+            pa_rtclock_get(&now);
+
+            pa_timespec_add(&p->next_elapse, p->period);
+
+            /* Guarantee that the next timeout will happen in the future */
+            if (pa_timespec_cmp(&p->next_elapse, &now) < 0)
+                pa_timespec_add(&p->next_elapse, (pa_timespec_diff(&now, &p->next_elapse) / p->period + 1)  * p->period);
+
+        } else
+            p->timer_enabled = 0;
+    }
     
-    if (r < 0 && (errno == EAGAIN || errno == EINTR)) {
+    if (r == 0 || (r < 0 && (errno == EAGAIN || errno == EINTR))) {
         r = 0;
         no_events = 1;
     }
@@ -359,13 +388,10 @@ finish:
     return r;
 }
 
-void pa_rtpoll_set_itimer(pa_rtpoll *p, pa_usec_t usec) {
+static void update_timer(pa_rtpoll *p) {
     pa_assert(p);
 
-    p->interval = usec;
-
 #ifdef HAVE_PPOLL
-    pa_timespec_store(&p->interval_timespec, usec);
 
 #ifdef __linux__
     if (!p->dont_use_ppoll) {
@@ -387,12 +413,21 @@ void pa_rtpoll_set_itimer(pa_rtpoll *p, pa_usec_t usec) {
 
         if (p->timer != (timer_t) -1) {
             struct itimerspec its;
-
             memset(&its, 0, sizeof(its));
-            pa_timespec_store(&its.it_value, usec);
-            pa_timespec_store(&its.it_interval, usec);
 
-            assert(timer_settime(p->timer, 0, &its, NULL) == 0);
+            if (p->timer_enabled) {
+                its.it_value = p->next_elapse;
+
+                /* 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)
+                    pa_timespec_store(&its.it_interval, p->period);
+            }
+
+            pa_assert_se(timer_settime(p->timer, TIMER_ABSTIME, &its, NULL) == 0);
         }
 
 #ifdef __linux__
@@ -402,6 +437,49 @@ void pa_rtpoll_set_itimer(pa_rtpoll *p, pa_usec_t usec) {
 #endif
 }
 
+void pa_rtpoll_set_timer_absolute(pa_rtpoll *p, const struct timespec *ts) {
+    pa_assert(p);
+    pa_assert(ts);
+    
+    p->next_elapse = *ts;
+    p->period = 0;
+    p->timer_enabled = 1;
+    
+    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_timespec_add(&p->next_elapse, usec);
+    p->timer_enabled = 1;
+
+    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_timespec_add(&p->next_elapse, usec);
+    p->timer_enabled = 1;
+
+    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 = 0;
+
+    update_timer(p);
+}
+
 pa_rtpoll_item *pa_rtpoll_item_new(pa_rtpoll *p, unsigned n_fds) {
     pa_rtpoll_item *i;
     
diff --git a/src/pulsecore/rtpoll.h b/src/pulsecore/rtpoll.h
index bed3ae3..7fe5cb3 100644
--- a/src/pulsecore/rtpoll.h
+++ b/src/pulsecore/rtpoll.h
@@ -59,11 +59,18 @@ void pa_rtpoll_free(pa_rtpoll *p);
 void pa_rtpoll_install(pa_rtpoll *p);
 
 int pa_rtpoll_run(pa_rtpoll *f);
-void pa_rtpoll_set_itimer(pa_rtpoll *p, pa_usec_t usec);
+
+void pa_rtpoll_set_timer_absolute(pa_rtpoll *p, const struct timespec *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);
 
 pa_rtpoll_item *pa_rtpoll_item_new(pa_rtpoll *p, 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);
 
 void pa_rtpoll_item_set_before_callback(pa_rtpoll_item *i, int (*before_cb)(pa_rtpoll_item *i));
@@ -74,5 +81,4 @@ void* pa_rtpoll_item_get_userdata(pa_rtpoll_item *i);
 pa_rtpoll_item *pa_rtpoll_item_new_fdsem(pa_rtpoll *p, pa_fdsem *s);
 pa_rtpoll_item *pa_rtpoll_item_new_asyncmsgq(pa_rtpoll *p, pa_asyncmsgq *q);
 
-
 #endif
diff --git a/src/tests/rtpoll-test.c b/src/tests/rtpoll-test.c
index 29f2e92..2a90684 100644
--- a/src/tests/rtpoll-test.c
+++ b/src/tests/rtpoll-test.c
@@ -56,7 +56,7 @@ int main(int argc, char *argv[]) {
     pollfd->events = POLLIN;
 
     pa_rtpoll_install(p);
-    pa_rtpoll_set_itimer(p, 10000000); /* 10 s */
+    pa_rtpoll_set_timer_periodic(p, 10000000); /* 10 s */
 
     pa_rtpoll_run(p);
     

commit 1bfa1802d48149cbd699e36cf80989b9c062341b
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Aug 22 22:27:07 2007 +0000

    minor cleanups
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1704 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-alsa-sink.c b/src/modules/module-alsa-sink.c
index 3e52148..a805845 100644
--- a/src/modules/module-alsa-sink.c
+++ b/src/modules/module-alsa-sink.c
@@ -28,12 +28,6 @@
 
 #include <stdio.h>
 
-#ifdef HAVE_SYS_POLL_H
-#include <sys/poll.h>
-#else
-#include "poll.h"
-#endif
-
 #include <asoundlib.h>
 
 #include <pulse/xmalloc.h>
@@ -343,7 +337,8 @@ static int suspend(struct userdata *u) {
     pa_assert(u);
     pa_assert(u->pcm_handle);
 
-    snd_pcm_drain(u->pcm_handle);    /* Let's suspend */
+    /* Let's suspend */
+    snd_pcm_drain(u->pcm_handle);    
     snd_pcm_close(u->pcm_handle);
     u->pcm_handle = NULL;
 
@@ -624,8 +619,6 @@ static void thread_func(void *userdata) {
         if (PA_SINK_OPENED(u->sink->thread_info.state)) {
             int work_done = 0;
             
-            pa_assert(u->pcm_handle);
-
             if (u->use_mmap) {
                 if ((work_done = mmap_write(u)) < 0)
                     goto fail;
@@ -648,8 +641,6 @@ static void thread_func(void *userdata) {
         if (pa_asyncmsgq_get(u->thread_mq.inq, &object, &code, &data, &offset, &chunk, 0) == 0) {
             int ret;
 
-/*             pa_log("processing msg");  */
-
             if (!object && code == PA_MESSAGE_SHUTDOWN) {
                 pa_asyncmsgq_done(u->thread_mq.inq, 0);
                 goto finish;
@@ -707,7 +698,6 @@ finish:
 int pa__init(pa_module*m) {
     
     pa_modargs *ma = NULL;
-    int ret = -1;
     struct userdata *u = NULL;
     const char *dev;
     pa_sample_spec ss;
@@ -723,6 +713,8 @@ int pa__init(pa_module*m) {
     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))) {
@@ -773,8 +765,7 @@ int pa__init(pa_module*m) {
 
     u->device_name = pa_xstrdup(dev);
 
-    if ((err = snd_pcm_info_malloc(&pcm_info)) < 0 ||
-        (err = snd_pcm_info(u->pcm_handle, pcm_info)) < 0) {
+    if ((err = snd_pcm_info(u->pcm_handle, pcm_info)) < 0) {
         pa_log("Error fetching PCM info: %s", snd_strerror(err));
         goto fail;
     }
@@ -903,24 +894,18 @@ int pa__init(pa_module*m) {
     if (u->sink->get_mute)
         u->sink->get_mute(u->sink);
 
-    ret = 0;
-
-finish:
-
-     if (ma)
-         pa_modargs_free(ma);
-     
-     if (pcm_info)
-         snd_pcm_info_free(pcm_info);
-
-    return ret;
-
+    pa_modargs_free(ma);
+    
+    return 0;
+    
 fail:
 
-    if (u)
-        pa__done(m);
+    if (ma)
+        pa_modargs_free(ma);
+
+    pa__done(m);
 
-    goto finish;
+    return -1;
 }
 
 void pa__done(pa_module*m) {

commit 9d381599be89f5cb99da60f83e086e476f50a72f
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Aug 22 22:27:53 2007 +0000

    port remaining sinks to pa_rtpoll
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1705 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-alsa-source.c b/src/modules/module-alsa-source.c
index 58e7cb4..6ea99ec 100644
--- a/src/modules/module-alsa-source.c
+++ b/src/modules/module-alsa-source.c
@@ -29,15 +29,10 @@
 #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>
@@ -52,6 +47,7 @@
 #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"
@@ -76,8 +72,10 @@ 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;
 
@@ -93,13 +91,7 @@ struct userdata {
 
     int use_mmap;
 
-    struct pollfd *pollfd;
-    int n_alsa_fds;
-};
-
-enum {
-    POLLFD_ASYNCQ,
-    POLLFD_ALSA_BASE
+    pa_rtpoll_item *alsa_rtpoll_item;
 };
 
 static const char* const valid_modargs[] = {
@@ -116,16 +108,16 @@ static const char* const valid_modargs[] = {
 };
 
 static int mmap_read(struct userdata *u) {
-    snd_pcm_sframes_t n;
-    int err;
-    const snd_pcm_channel_area_t *areas;
-    snd_pcm_uframes_t offset, frames;
     int work_done = 0;
     
     pa_assert(u);
-    pa_assert(u->source);
+    pa_source_assert_ref(u->source);
 
     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;
         
@@ -207,6 +199,73 @@ static int mmap_read(struct userdata *u) {
     }
 }
 
+static int unix_read(struct userdata *u) {
+    snd_pcm_status_t *status;
+    int work_done = 0;
+
+    snd_pcm_status_alloca(&status);
+
+    pa_assert(u);
+    pa_source_assert_ref(u->source);
+
+    for (;;) {
+        void *p;
+        snd_pcm_sframes_t t;
+        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(t));
+            return -1;
+        }
+
+        if (snd_pcm_status_get_avail_max(status)*u->frame_size >= u->hwbuf_size)
+            pa_log_debug("Buffer overrun!");
+                    
+        l = snd_pcm_status_get_avail(status) * u->frame_size;
+
+        if (l <= 0)
+            return work_done;
+                    
+        chunk.memblock = pa_memblock_new(u->core->mempool, l);
+
+        p = pa_memblock_acquire(chunk.memblock);
+        t = snd_pcm_readi(u->pcm_handle, (uint8_t*) p, l / 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;
+            }
+        } 
+                        
+        chunk.index = 0;
+        chunk.length = t * u->frame_size;
+
+        pa_source_post(u->source, &chunk);
+        pa_memblock_unref(chunk.memblock);
+                    
+        work_done = 1;
+
+        if (t * u->frame_size >= (unsigned) l)
+            return work_done;
+    }
+}
+
 static pa_usec_t source_get_latency(struct userdata *u) {
     pa_usec_t r = 0;
     snd_pcm_status_t *status;
@@ -216,6 +275,7 @@ static pa_usec_t source_get_latency(struct userdata *u) {
     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));
@@ -230,22 +290,24 @@ static pa_usec_t source_get_latency(struct userdata *u) {
 
 static int build_pollfd(struct userdata *u) {
     int err;
+    struct pollfd *pollfd;
+    int n;
     
     pa_assert(u);
     pa_assert(u->pcm_handle);
 
-    if ((u->n_alsa_fds = snd_pcm_poll_descriptors_count(u->pcm_handle)) < 0) {
-        pa_log("snd_pcm_poll_descriptors_count() failed: %s", snd_strerror(u->n_alsa_fds));
+    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;
     }
 
-    pa_xfree(u->pollfd);
-    u->pollfd = pa_xnew0(struct pollfd, POLLFD_ALSA_BASE + u->n_alsa_fds);
-
-    u->pollfd[POLLFD_ASYNCQ].fd = pa_asyncmsgq_get_fd(u->thread_mq.inq);
-    u->pollfd[POLLFD_ASYNCQ].events = POLLIN;
+    if (u->alsa_rtpoll_item)
+        pa_rtpoll_item_free(u->alsa_rtpoll_item);
 
-    if ((err = snd_pcm_poll_descriptors(u->pcm_handle, u->pollfd+POLLFD_ALSA_BASE, u->n_alsa_fds)) < 0) {
+    u->alsa_rtpoll_item = pa_rtpoll_item_new(u->rtpoll, 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;
     }
@@ -261,6 +323,11 @@ static int suspend(struct userdata *u) {
     snd_pcm_close(u->pcm_handle);
     u->pcm_handle = NULL;
 
+    if (u->alsa_rtpoll_item) {
+        pa_rtpoll_item_free(u->alsa_rtpoll_item);
+        u->alsa_rtpoll_item = NULL;
+    }
+    
     pa_log_debug("Device suspended...");
     
     return 0;
@@ -505,14 +572,9 @@ static int source_set_mute_cb(pa_source *s) {
 }
 
 static void thread_func(void *userdata) {
-
     struct userdata *u = userdata;
-    int err;
-    unsigned short revents = 0;
-    snd_pcm_status_t *status;
 
     pa_assert(u);
-    snd_pcm_status_alloca(&status);
 
     pa_log_debug("Thread starting up");
 
@@ -520,20 +582,37 @@ static void thread_func(void *userdata) {
         pa_make_realtime();
 
     pa_thread_mq_install(&u->thread_mq);
+    pa_rtpoll_install(u->rtpoll);
     
     if (build_pollfd(u) < 0)
         goto fail;
 
+    snd_pcm_start(u->pcm_handle);
+    
     for (;;) {
         pa_msgobject *object;
         int code;
         void *data;
-        int r;
         int64_t offset;
         pa_memchunk chunk;
 
 /*         pa_log("loop");     */
         
+        /* Render some data and write it to the dsp */
+        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;
+            }
+        }
+
+/*         pa_log("loop2"); */
+        
         /* Check whether there is a message for us to process */
         if (pa_asyncmsgq_get(u->thread_mq.inq, &object, &code, &data, &offset, &chunk, 0) == 0) {
             int ret;
@@ -550,109 +629,20 @@ static void thread_func(void *userdata) {
             continue;
         } 
 
-/*         pa_log("loop2"); */
-
-        /* Render some data and write it to the dsp */
-
-        if (PA_SOURCE_OPENED(u->source->thread_info.state) && (revents & POLLIN)) {
-            int work_done = 0;
-            pa_assert(u->pcm_handle);
-
-            if (u->use_mmap) {
-
-                if ((work_done = mmap_read(u)) < 0)
-                    goto fail;
-
-            } else {
-
-                for (;;) {
-                    void *p;
-                    snd_pcm_sframes_t t;
-                    ssize_t l;
-
-                    if ((err = snd_pcm_status(u->pcm_handle, status)) < 0) {
-                        pa_log("Failed to query DSP status data: %s", snd_strerror(t));
-                        goto fail;
-                    }
-
-                    if (snd_pcm_status_get_avail_max(status)*u->frame_size >= u->hwbuf_size)
-                        pa_log_debug("Buffer overrun!");
-                    
-                    l = snd_pcm_status_get_avail(status) * u->frame_size;
-
-                    if (l <= 0)
-                        break;
-                    
-                    chunk.memblock = pa_memblock_new(u->core->mempool, l);
-
-                    p = pa_memblock_acquire(chunk.memblock);
-                    t = snd_pcm_readi(u->pcm_handle, (uint8_t*) p, l / 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");
-                            break;
-                        } else {
-                            pa_log("Failed to read data from DSP: %s", snd_strerror(t));
-                            goto fail;
-                        }
-                        
-                    } 
-                        
-                    chunk.index = 0;
-                    chunk.length = t * u->frame_size;
-
-                    pa_source_post(u->source, &chunk);
-                    pa_memblock_unref(chunk.memblock);
-                    
-                    work_done = 1;
-
-                    if (t * u->frame_size >= (unsigned) l)
-                        break;
-                } 
-            }
-
-            revents &= ~POLLIN;
-            
-            if (work_done)
-                continue;
-        }
-
-        /* Hmm, nothing to do. Let's sleep */
-        if (pa_asyncmsgq_before_poll(u->thread_mq.inq) < 0)
-            continue;
-
-/*         pa_log("polling for %i", POLLFD_ALSA_BASE + (PA_SOURCE_OPENED(u->source->thread_info.state) ? n_alsa_fds : 0));   */
-        r = poll(u->pollfd, POLLFD_ALSA_BASE + (PA_SOURCE_OPENED(u->source->thread_info.state) ? u->n_alsa_fds : 0), -1);
-/*         pa_log("poll end"); */
-
-        pa_asyncmsgq_after_poll(u->thread_mq.inq);
-
-        if (r < 0) {
-            if (errno == EINTR) {
-                u->pollfd[POLLFD_ASYNCQ].revents = 0;
-                revents = 0;
-                continue;
-            }
-
+        if (pa_rtpoll_run(u->rtpoll) < 0) {
             pa_log("poll() failed: %s", pa_cstrerror(errno));
             goto fail;
         }
 
-        pa_assert(r > 0);
-
         if (PA_SOURCE_OPENED(u->source->thread_info.state)) {
-            if ((err = snd_pcm_poll_descriptors_revents(u->pcm_handle, u->pollfd + POLLFD_ALSA_BASE, u->n_alsa_fds, &revents)) < 0) {
+            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;
             }
@@ -668,10 +658,7 @@ static void thread_func(void *userdata) {
                 goto fail;
             }
 /*             pa_log("got alsa event"); */
-        } else
-            revents = 0;
-        
-        pa_assert((u->pollfd[POLLFD_ASYNCQ].revents & ~POLLIN) == 0);
+        }
     }
 
 fail:
@@ -687,7 +674,6 @@ finish:
 int pa__init(pa_module*m) {
     
     pa_modargs *ma = NULL;
-    int ret = -1;
     struct userdata *u = NULL;
     const char *dev;
     pa_sample_spec ss;
@@ -703,6 +689,8 @@ int pa__init(pa_module*m) {
     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))) {
@@ -739,9 +727,10 @@ int pa__init(pa_module*m) {
     u->module = m;
     m->userdata = u;
     u->use_mmap = use_mmap;
-    u->n_alsa_fds = 0;
-    u->pollfd = NULL;
     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, 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) {
@@ -751,8 +740,7 @@ int pa__init(pa_module*m) {
 
     u->device_name = pa_xstrdup(dev);
 
-    if ((err = snd_pcm_info_malloc(&pcm_info)) < 0 ||
-        (err = snd_pcm_info(u->pcm_handle, pcm_info)) < 0) {
+    if ((err = snd_pcm_info(u->pcm_handle, pcm_info)) < 0) {
         pa_log("Error fetching PCM info: %s", snd_strerror(err));
         goto fail;
     }
@@ -875,26 +863,18 @@ int pa__init(pa_module*m) {
     if (u->source->get_mute)
         u->source->get_mute(u->source);
 
-    snd_pcm_start(u->pcm_handle);
+    pa_modargs_free(ma);
     
-    ret = 0;
-
-finish:
-
-    if (ma)
-        pa_modargs_free(ma);
+    return 0;
     
-    if (pcm_info)
-        snd_pcm_info_free(pcm_info);
-
-    return ret;
-
 fail:
 
-    if (u)
-        pa__done(m);
+    if (ma)
+        pa_modargs_free(ma);
 
-    goto finish;
+    pa__done(m);
+    
+    return -1;
 }
 
 void pa__done(pa_module*m) {
@@ -918,6 +898,12 @@ void pa__done(pa_module*m) {
     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);
 
@@ -929,7 +915,6 @@ void pa__done(pa_module*m) {
         snd_pcm_close(u->pcm_handle);
     }
 
-    pa_xfree(u->pollfd);
     pa_xfree(u->device_name);
     pa_xfree(u);
 
diff --git a/src/modules/module-null-sink.c b/src/modules/module-null-sink.c
index 8b17b59..3b51237 100644
--- a/src/modules/module-null-sink.c
+++ b/src/modules/module-null-sink.c
@@ -33,7 +33,6 @@
 #include <fcntl.h>
 #include <unistd.h>
 #include <limits.h>
-#include <sys/poll.h>
 
 #include <pulse/timeval.h>
 #include <pulse/xmalloc.h>
@@ -47,6 +46,8 @@
 #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"
 
@@ -67,11 +68,14 @@ struct userdata {
     pa_core *core;
     pa_module *module;
     pa_sink *sink;
+
     pa_thread *thread;
     pa_thread_mq thread_mq;
+    pa_rtpoll *rtpoll;
+
     size_t block_size;
     
-    struct timeval timestamp;
+    struct timespec timestamp;
 };
 
 static const char* const valid_modargs[] = {
@@ -91,19 +95,19 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
         case PA_SINK_MESSAGE_SET_STATE:
 
             if (PA_PTR_TO_UINT(data) == PA_SINK_RUNNING)
-                pa_gettimeofday(&u->timestamp);
+                pa_rtclock_get(&u->timestamp);
             
             break;
             
         case PA_SINK_MESSAGE_GET_LATENCY: {
-            struct timeval now;
+            struct timespec now;
     
-            pa_gettimeofday(&now);
+            pa_rtclock_get(&now);
             
-            if (pa_timeval_cmp(&u->timestamp, &now) > 0)
+            if (pa_timespec_cmp(&u->timestamp, &now) > 0)
                 *((pa_usec_t*) data) = 0;
             else
-                *((pa_usec_t*) data) = pa_timeval_diff(&u->timestamp, &now);
+                *((pa_usec_t*) data) = pa_timespec_diff(&u->timestamp, &now);
             break;
         }
     }
@@ -113,29 +117,41 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
 
 static void thread_func(void *userdata) {
     struct userdata *u = userdata;
-    struct pollfd pollfd;
 
     pa_assert(u);
 
     pa_log_debug("Thread starting up");
 
     pa_thread_mq_install(&u->thread_mq);
+    pa_rtpoll_install(u->rtpoll);
 
-    pa_gettimeofday(&u->timestamp);
-
-    memset(&pollfd, 0, sizeof(pollfd));
-    pollfd.fd = pa_asyncmsgq_get_fd(u->thread_mq.inq);
-    pollfd.events = POLLIN;
+    pa_rtclock_get(&u->timestamp);
 
     for (;;) {
         pa_msgobject *object;
         int code;
         void *data;
         pa_memchunk chunk;
-        int r, timeout;
-        struct timeval now;
         int64_t offset;
 
+        /* Render some data and drop it immediately */
+        if (u->sink->thread_info.state == PA_SINK_RUNNING) {
+            struct timespec now;
+            
+            pa_rtclock_get(&now);
+
+            if (pa_timespec_cmp(&u->timestamp, &now) <= 0) {
+
+                pa_sink_render(u->sink, u->block_size, &chunk);
+                pa_memblock_unref(chunk.memblock);
+
+                pa_timespec_add(&u->timestamp, pa_bytes_to_usec(chunk.length, &u->sink->sample_spec));
+            }
+
+            pa_rtpoll_set_timer_absolute(u->rtpoll, &u->timestamp);
+        } else
+            pa_rtpoll_set_timer_disabled(u->rtpoll);
+
         /* Check whether there is a message for us to process */
         if (pa_asyncmsgq_get(u->thread_mq.inq, &object, &code, &data, &offset, &chunk, 0) == 0) {
             int ret;
@@ -150,45 +166,11 @@ static void thread_func(void *userdata) {
             continue;
         }
 
-        /* Render some data and drop it immediately */
-        if (u->sink->thread_info.state == PA_SINK_RUNNING) {
-            pa_gettimeofday(&now);
-
-            if (pa_timeval_cmp(&u->timestamp, &now) <= 0) {
-
-                pa_sink_render(u->sink, u->block_size, &chunk);
-                pa_memblock_unref(chunk.memblock);
-
-                pa_timeval_add(&u->timestamp, pa_bytes_to_usec(chunk.length, &u->sink->sample_spec));
-                continue;
-            }
-
-            timeout = pa_timeval_diff(&u->timestamp, &now)/1000;
-
-            if (timeout < 1)
-                timeout = 1;
-        } else
-            timeout = -1;
-
         /* Hmm, nothing to do. Let's sleep */
-
-        if (pa_asyncmsgq_before_poll(u->thread_mq.inq) < 0)
-            continue;
-
-        r = poll(&pollfd, 1, timeout);
-        pa_asyncmsgq_after_poll(u->thread_mq.inq);
-
-        if (r < 0) {
-            if (errno == EINTR) {
-                pollfd.revents = 0;
-                continue;
-            }
-
+        if (pa_rtpoll_run(u->rtpoll) < 0) {
             pa_log("poll() failed: %s", pa_cstrerror(errno));
             goto fail;
         }
-
-        pa_assert(r == 0 || pollfd.revents == POLLIN);
     }
 
 fail:
@@ -224,8 +206,9 @@ int pa__init(pa_module*m) {
     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, u->thread_mq.inq);
     
     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.");
@@ -282,5 +265,8 @@ void pa__done(pa_module*m) {
     if (u->sink)
         pa_sink_unref(u->sink);
 
+    if (u->rtpoll)
+        pa_rtpoll_free(u->rtpoll);
+    
     pa_xfree(u);
 }
diff --git a/src/modules/module-oss.c b/src/modules/module-oss.c
index f445481..85fdd9c 100644
--- a/src/modules/module-oss.c
+++ b/src/modules/module-oss.c
@@ -32,9 +32,7 @@
  *   the device. If none is avilable from the inputs, we write silence
  *   instead.
  *
- *   If power should be saved on IDLE this should be implemented in a
- *   special suspend-on-idle module that will put us into SUSPEND mode
- *   as soon and we're idle for too long.
+ *   If power should be saved on IDLE module-suspend-on-idle should be used.
  *
  */
 
@@ -48,12 +46,6 @@
 #include <sys/mman.h>
 #endif
 
-#ifdef HAVE_SYS_POLL_H
-#include <sys/poll.h>
-#else
-#include "poll.h"
-#endif
-
 #include <sys/soundcard.h>
 #include <sys/ioctl.h>
 #include <stdlib.h>
@@ -80,6 +72,7 @@
 #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"
@@ -108,8 +101,10 @@ struct userdata {
     pa_module *module;
     pa_sink *sink;
     pa_source *source;
+    
     pa_thread *thread;
     pa_thread_mq thread_mq;
+    pa_rtpoll *rtpoll;
 
     char *device_name;
     
@@ -135,6 +130,8 @@ struct userdata {
     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[] = {
@@ -156,10 +153,12 @@ static const char* const valid_modargs[] = {
 static void trigger(struct userdata *u, int quick) {
     int enable_bits = 0, zero = 0;
 
+    pa_assert(u);
+    
     if (u->fd < 0)
         return;
 
-    pa_log_debug("trigger"); 
+/*     pa_log_debug("trigger");  */
 
     if (u->source && PA_SOURCE_OPENED(u->source->thread_info.state))
         enable_bits |= PCM_ENABLE_INPUT;
@@ -479,6 +478,11 @@ static int suspend(struct userdata *u) {
     close(u->fd);
     u->fd = -1;
 
+    if (u->rtpoll_item) {
+        pa_rtpoll_item_free(u->rtpoll_item);
+        u->rtpoll_item = NULL;
+    }
+    
     pa_log_debug("Device suspended...");
     
     return 0;
@@ -490,6 +494,7 @@ static int unsuspend(struct userdata *u) {
     int frag_size, in_frag_size, out_frag_size;
     int in_nfrags, out_nfrags;
     struct audio_buf_info info;
+    struct pollfd *pollfd;
 
     pa_assert(u);
     pa_assert(u->fd < 0);
@@ -568,7 +573,15 @@ static int unsuspend(struct userdata *u) {
 
     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);
     
+    u->rtpoll_item = pa_rtpoll_item_new(u->rtpoll, 1);
+    pollfd = pa_rtpoll_item_get_pollfd(u->rtpoll_item, NULL);
+    pollfd->fd = u->fd;
+    pollfd->events = 0;
+    pollfd->revents = 0;
+
     pa_log_debug("Resumed successfully...");
 
     return 0;
@@ -777,15 +790,9 @@ static int source_process_msg(pa_msgobject *o, int code, void *data, int64_t off
 }
 
 static void thread_func(void *userdata) {
-    enum {
-        POLLFD_ASYNCQ,
-        POLLFD_DSP,
-        POLLFD_MAX,
-    };
-
     struct userdata *u = userdata;
-    struct pollfd pollfd[POLLFD_MAX];
     int write_type = 0, read_type = 0;
+    unsigned short revents = 0;
 
     pa_assert(u);
 
@@ -795,46 +802,22 @@ static void thread_func(void *userdata) {
         pa_make_realtime();
 
     pa_thread_mq_install(&u->thread_mq);
+    pa_rtpoll_install(u->rtpoll);
 
     trigger(u, 0);
     
-    memset(&pollfd, 0, sizeof(pollfd));
-
-    pollfd[POLLFD_ASYNCQ].fd = pa_asyncmsgq_get_fd(u->thread_mq.inq);
-    pollfd[POLLFD_ASYNCQ].events = POLLIN;
-    pollfd[POLLFD_DSP].fd = u->fd;
-
     for (;;) {
         pa_msgobject *object;
         int code;
         void *data;
         pa_memchunk chunk;
-        int r;
         int64_t offset;
 
 /*        pa_log("loop");    */
         
-        /* Check whether there is a message for us to process */
-        if (pa_asyncmsgq_get(u->thread_mq.inq, &object, &code, &data, &offset, &chunk, 0) == 0) {
-            int ret;
-
-/*             pa_log("processing msg"); */
-
-            if (!object && code == PA_MESSAGE_SHUTDOWN) {
-                pa_asyncmsgq_done(u->thread_mq.inq, 0);
-                goto finish;
-            }
-
-            ret = pa_asyncmsgq_dispatch(object, code, data, offset, &chunk);
-            pa_asyncmsgq_done(u->thread_mq.inq, ret);
-            continue;
-        } 
-
-/*         pa_log("loop2"); */
-
         /* Render some data and write it to the dsp */
 
-        if (u->sink && u->sink->thread_info.state != PA_SINK_DISCONNECTED && u->fd >= 0 && (pollfd[POLLFD_DSP].revents & POLLOUT)) {
+        if (u->sink && u->sink->thread_info.state != PA_SINK_DISCONNECTED && u->fd >= 0 && (revents & POLLOUT)) {
 
             if (u->use_mmap) {
                 int ret;
@@ -842,7 +825,7 @@ static void thread_func(void *userdata) {
                 if ((ret = mmap_write(u)) < 0)
                     goto fail;
 
-                pollfd[POLLFD_DSP].revents &= ~POLLOUT;
+                revents &= ~POLLOUT;
                 
                 if (ret > 0)
                     continue;
@@ -894,7 +877,7 @@ static void thread_func(void *userdata) {
                         else if (errno == EAGAIN) {
                             pa_log_debug("EAGAIN"); 
                             
-                            pollfd[POLLFD_DSP].revents &= ~POLLOUT;
+                            revents &= ~POLLOUT;
                             break;
                             
                         } else {
@@ -914,7 +897,7 @@ static void thread_func(void *userdata) {
                         
                         l -= t;
                         
-                        pollfd[POLLFD_DSP].revents &= ~POLLOUT;
+                        revents &= ~POLLOUT;
                     }
                     
                 } while (loop && l > 0);
@@ -925,7 +908,7 @@ static void thread_func(void *userdata) {
 
         /* Try to read some data and pass it on to the source driver */
 
-        if (u->source && u->source->thread_info.state != PA_SOURCE_DISCONNECTED && u->fd >= 0 && ((pollfd[POLLFD_DSP].revents & POLLIN))) {
+        if (u->source && u->source->thread_info.state != PA_SOURCE_DISCONNECTED && u->fd >= 0 && ((revents & POLLIN))) {
 
             if (u->use_mmap) {
                 int ret;
@@ -933,7 +916,7 @@ static void thread_func(void *userdata) {
                 if ((ret = mmap_read(u)) < 0)
                     goto fail;
 
-                pollfd[POLLFD_DSP].revents &= ~POLLIN;
+                revents &= ~POLLIN;
                 
                 if (ret > 0)
                     continue;
@@ -985,7 +968,7 @@ static void thread_func(void *userdata) {
                         else if (errno == EAGAIN) {
                             pa_log_debug("EAGAIN"); 
 
-                            pollfd[POLLFD_DSP].revents &= ~POLLIN;
+                            revents &= ~POLLIN;
                             break;
 
                         } else {
@@ -1002,7 +985,7 @@ static void thread_func(void *userdata) {
 
                         l -= t;
 
-                        pollfd[POLLFD_DSP].revents &= ~POLLIN;
+                        revents &= ~POLLIN;
                     }
                 } while (loop && l > 0);
 
@@ -1010,46 +993,53 @@ static void thread_func(void *userdata) {
             }
         }
 
-        if (u->fd >= 0) {
-            pollfd[POLLFD_DSP].fd = u->fd;
-            pollfd[POLLFD_DSP].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 */
+/*         pa_log("loop2"); */
 
-        if (pa_asyncmsgq_before_poll(u->thread_mq.inq) < 0)
+        /* Check whether there is a message for us to process */
+        if (pa_asyncmsgq_get(u->thread_mq.inq, &object, &code, &data, &offset, &chunk, 0) == 0) {
+            int ret;
+
+/*             pa_log("processing msg"); */
+
+            if (!object && code == PA_MESSAGE_SHUTDOWN) {
+                pa_asyncmsgq_done(u->thread_mq.inq, 0);
+                goto finish;
+            }
+
+            ret = pa_asyncmsgq_dispatch(object, code, data, offset, &chunk);
+            pa_asyncmsgq_done(u->thread_mq.inq, ret);
             continue;
+        } 
 
-/*         pa_log("polling for %i (legend: %i=POLLIN, %i=POLLOUT)", u->fd >= 0 ? pollfd[POLLFD_DSP].events : -1, POLLIN, POLLOUT); */
-        r = poll(pollfd, u->fd >= 0 ? POLLFD_MAX : POLLFD_DSP, -1);
-/*         pa_log("polling got dsp=%i amq=%i (%i)", r > 0 ? pollfd[POLLFD_DSP].revents : 0, r > 0 ? pollfd[POLLFD_ASYNCQ].revents : 0, r); */
+        if (u->fd >= 0) {
+            struct pollfd *pollfd;
 
-        pa_asyncmsgq_after_poll(u->thread_mq.inq);
+            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);
+        }
 
-        if (u->fd < 0)
-            pollfd[POLLFD_DSP].revents = 0;
         
-        if (r < 0) {
-            if (errno == EINTR) {
-                pollfd[POLLFD_ASYNCQ].revents = 0;
-                pollfd[POLLFD_DSP].revents = 0;
-                continue;
-            }
-
+        /* Hmm, nothing to do. Let's sleep */
+        if (pa_rtpoll_run(u->rtpoll) < 0) {
             pa_log("poll() failed: %s", pa_cstrerror(errno));
             goto fail;
         }
 
-        pa_assert(r > 0);
-
-        if (pollfd[POLLFD_DSP].revents & ~(POLLOUT|POLLIN)) {
-            pa_log("DSP shutdown.");
-            goto fail;
-        }
+        if (u->fd >= 0) {
+            struct pollfd *pollfd;
+            
+            pollfd = pa_rtpoll_item_get_pollfd(u->rtpoll_item, NULL);
+            
+            if (pollfd->revents & ~(POLLOUT|POLLIN)) {
+                pa_log("DSP shutdown.");
+                goto fail;
+            }
 
-        pa_assert((pollfd[POLLFD_ASYNCQ].revents & ~POLLIN) == 0);
+            revents = pollfd->revents;
+        } else
+            revents = 0;
     }
 
 fail:
@@ -1077,6 +1067,7 @@ int pa__init(pa_module*m) {
     char hwdesc[64], *t;
     const char *name;
     int namereg_fail;
+    struct pollfd *pollfd;
 
     pa_assert(m);
 
@@ -1165,7 +1156,14 @@ int pa__init(pa_module*m) {
     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, u->thread_mq.inq);
+    u->rtpoll_item = pa_rtpoll_item_new(u->rtpoll, 1);
+    pollfd = pa_rtpoll_item_get_pollfd(u->rtpoll_item, NULL);
+    pollfd->fd = fd;
+    pollfd->events = 0;
+    pollfd->revents = 0;
+    
     if (ioctl(fd, SNDCTL_DSP_GETISPACE, &info) >= 0) {
         pa_log_info("Input -- %u fragments of size %u.", info.fragstotal, info.fragsize);
         u->in_fragment_size = info.fragsize;
@@ -1294,14 +1292,14 @@ go_on:
         goto fail;
     }
 
-    pa_modargs_free(ma);
-
     /* Read mixer settings */
     if (u->source)
         pa_asyncmsgq_post(u->thread_mq.inq, PA_MSGOBJECT(u->source), PA_SOURCE_MESSAGE_GET_VOLUME, &u->source->volume, 0, NULL, NULL);
     if (u->sink)
         pa_asyncmsgq_post(u->thread_mq.inq, PA_MSGOBJECT(u->sink), PA_SINK_MESSAGE_GET_VOLUME, &u->sink->volume, 0, NULL, NULL);
 
+    pa_modargs_free(ma);
+
     return 0;
 
 fail:
@@ -1343,10 +1341,16 @@ void pa__done(pa_module*m) {
 
     if (u->source)
         pa_source_unref(u->source);
-
+    
     if (u->memchunk.memblock)
         pa_memblock_unref(u->memchunk.memblock);
 
+    if (u->rtpoll_item)
+        pa_rtpoll_item_free(u->rtpoll_item);
+    
+    if (u->rtpoll)
+        pa_rtpoll_free(u->rtpoll);
+    
     if (u->out_mmap_memblocks) {
         unsigned i;
         for (i = 0; i < u->out_nfrags; i++)
diff --git a/src/modules/module-pipe-sink.c b/src/modules/module-pipe-sink.c
index 2f82cae..a1101ab 100644
--- a/src/modules/module-pipe-sink.c
+++ b/src/modules/module-pipe-sink.c
@@ -34,7 +34,6 @@
 #include <unistd.h>
 #include <limits.h>
 #include <sys/ioctl.h>
-#include <sys/poll.h>
 
 #include <pulse/xmalloc.h>
 
@@ -46,6 +45,7 @@
 #include <pulsecore/log.h>
 #include <pulsecore/thread.h>
 #include <pulsecore/thread-mq.h>
+#include <pulsecore/rtpoll.h>
 
 #include "module-pipe-sink-symdef.h"
 
@@ -67,12 +67,17 @@ struct userdata {
     pa_core *core;
     pa_module *module;
     pa_sink *sink;
+    
     pa_thread *thread;
     pa_thread_mq thread_mq;
+    pa_rtpoll *rtpoll;
+    
     char *filename;
     int fd;
 
     pa_memchunk memchunk;
+
+    pa_rtpoll_item *rtpoll_item;
 };
 
 static const char* const valid_modargs[] = {
@@ -108,14 +113,7 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
 }
 
 static void thread_func(void *userdata) {
-    enum {
-        POLLFD_ASYNCQ,
-        POLLFD_FIFO,
-        POLLFD_MAX,
-    };
-    
     struct userdata *u = userdata;
-    struct pollfd pollfd[POLLFD_MAX];
     int write_type = 0;
 
     pa_assert(u);
@@ -123,38 +121,21 @@ static void thread_func(void *userdata) {
     pa_log_debug("Thread starting up");
 
     pa_thread_mq_install(&u->thread_mq);
-
-    memset(&pollfd, 0, sizeof(pollfd));
-    
-    pollfd[POLLFD_ASYNCQ].fd = pa_asyncmsgq_get_fd(u->thread_mq.inq);
-    pollfd[POLLFD_ASYNCQ].events = POLLIN;
-    pollfd[POLLFD_FIFO].fd = u->fd;
+    pa_rtpoll_install(u->rtpoll);
 
     for (;;) {
         pa_msgobject *object;
         int code;
         void *data;
         pa_memchunk chunk;
-        int r;
         int64_t offset;
-
-        /* Check whether there is a message for us to process */
-        if (pa_asyncmsgq_get(u->thread_mq.inq, &object, &code, &data, &offset, &chunk, 0) == 0) {
-            int ret;
-
-            if (!object && code == PA_MESSAGE_SHUTDOWN) {
-                pa_asyncmsgq_done(u->thread_mq.inq, 0);
-                goto finish;
-            }
-
-            ret = pa_asyncmsgq_dispatch(object, code, data, offset, &chunk);
-            pa_asyncmsgq_done(u->thread_mq.inq, ret);
-            continue;
-        }
+        struct pollfd *pollfd;
 
         /* Render some data and write it to the fifo */
 
-        if (u->sink->thread_info.state == PA_SINK_RUNNING && pollfd[POLLFD_FIFO].revents) {
+        pollfd = pa_rtpoll_item_get_pollfd(u->rtpoll_item, NULL);
+        
+        if (u->sink->thread_info.state == PA_SINK_RUNNING && pollfd->revents) {
             ssize_t l;
             void *p;
 
@@ -188,41 +169,37 @@ static void thread_func(void *userdata) {
                     pa_memchunk_reset(&u->memchunk);
                 }
 
-                pollfd[POLLFD_FIFO].revents = 0;
-                continue;
+                pollfd->revents = 0;
             }
         }
 
-        pollfd[POLLFD_FIFO].events = u->sink->thread_info.state == PA_SINK_RUNNING ? POLLOUT : 0;
+        /* Check whether there is a message for us to process */
+        if (pa_asyncmsgq_get(u->thread_mq.inq, &object, &code, &data, &offset, &chunk, 0) == 0) {
+            int ret;
 
-        /* Hmm, nothing to do. Let's sleep */
+            if (!object && code == PA_MESSAGE_SHUTDOWN) {
+                pa_asyncmsgq_done(u->thread_mq.inq, 0);
+                goto finish;
+            }
 
-        if (pa_asyncmsgq_before_poll(u->thread_mq.inq) < 0)
+            ret = pa_asyncmsgq_dispatch(object, code, data, offset, &chunk);
+            pa_asyncmsgq_done(u->thread_mq.inq, ret);
             continue;
+        }
+        
+        /* Hmm, nothing to do. Let's sleep */
+        pollfd->events = u->sink->thread_info.state == PA_SINK_RUNNING ? POLLOUT : 0;
 
-/*         pa_log("polling for %u", pollfd[POLLFD_FIFO].events);  */
-        r = poll(pollfd, POLLFD_MAX, -1);
-/*         pa_log("polling got %u", r > 0 ? pollfd[POLLFD_FIFO].revents : 0);  */
-
-        pa_asyncmsgq_after_poll(u->thread_mq.inq);
-
-        if (r < 0) {
-            if (errno == EINTR) {
-                pollfd[POLLFD_ASYNCQ].revents = 0;
-                pollfd[POLLFD_FIFO].revents = 0;
-                continue;
-            }
-
+        if (pa_rtpoll_run(u->rtpoll) < 0) {
             pa_log("poll() failed: %s", pa_cstrerror(errno));
             goto fail;
         }
 
-        if (pollfd[POLLFD_FIFO].revents & ~POLLOUT) {
+        pollfd = pa_rtpoll_item_get_pollfd(u->rtpoll_item, NULL);
+        if (pollfd->revents & ~POLLOUT) {
             pa_log("FIFO shutdown.");
             goto fail;
         }
-
-        pa_assert((pollfd[POLLFD_ASYNCQ].revents & ~POLLIN) == 0);
     }
 
 fail:
@@ -242,6 +219,7 @@ int pa__init(pa_module*m) {
     pa_channel_map map;
     pa_modargs *ma;
     char *t;
+    struct pollfd *pollfd;
 
     pa_assert(m);
 
@@ -262,6 +240,8 @@ int pa__init(pa_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, u->thread_mq.inq);
     
     u->filename = pa_xstrdup(pa_modargs_get_value(ma, "file", DEFAULT_FILE_NAME));
 
@@ -297,6 +277,11 @@ int pa__init(pa_module*m) {
     pa_sink_set_description(u->sink, t = pa_sprintf_malloc("Unix FIFO sink '%s'", u->filename));
     pa_xfree(t);
 
+    u->rtpoll_item = pa_rtpoll_item_new(u->rtpoll, 1);
+    pollfd = pa_rtpoll_item_get_pollfd(u->rtpoll_item, NULL);
+    pollfd->fd = u->fd;
+    pollfd->events = pollfd->revents = 0;
+   
     if (!(u->thread = pa_thread_new(thread_func, u))) {
         pa_log("Failed to create thread.");
         goto fail;
@@ -339,6 +324,12 @@ void pa__done(pa_module*m) {
     if (u->memchunk.memblock)
        pa_memblock_unref(u->memchunk.memblock);
 
+    if (u->rtpoll_item)
+        pa_rtpoll_item_free(u->rtpoll_item);
+    
+    if (u->rtpoll)
+        pa_rtpoll_free(u->rtpoll);
+
     if (u->filename) {
         unlink(u->filename);
         pa_xfree(u->filename);

commit b3b382d8ef6393eff49da97e3822a721468a6bed
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Aug 22 22:36:39 2007 +0000

    fix minor typo
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1706 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/libltdl/config.h b/libltdl/config.h
index 0fe3124..195d214 100644
--- a/libltdl/config.h
+++ b/libltdl/config.h
@@ -160,7 +160,7 @@
 #define LTDL_SHLIB_EXT ".so"
 
 /* Define to the system default library search path. */
-#define LTDL_SYSSEARCHPATH "/usr/lib:/lib:/usr/lib/qt-3.3/lib"
+#define LTDL_SYSSEARCHPATH "/usr/lib:/lib:/usr/local/lib:/usr/lib/qt-3.3/lib"
 
 /* Define if dlsym() requires a leading underscore in symbol names. */
 /* #undef NEED_USCORE */
diff --git a/src/Makefile.am b/src/Makefile.am
index 9b843a4..04e5766 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -686,7 +686,7 @@ libpulsecore_la_SOURCES += \
 		pulsecore/fdsem.c pulsecore/fdsem.h \
 		pulsecore/object.c pulsecore/object.h \
 		pulsecore/msgobject.c pulsecore/msgobject.h \
-		pulsecore/rtsig.c pulsecore/rtsog.h \
+		pulsecore/rtsig.c pulsecore/rtsig.h \
 		pulsecore/rtpoll.c pulsecore/rtpoll.h \
 		pulsecore/rtclock.c pulsecore/rtclock.h \
 		pulsecore/macro.h \

commit 5ff891c15652849399c7bd832fa56b7674620395
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Aug 23 22:31:01 2007 +0000

    add a copy of the speex resampler to our sources
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1707 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/speex/arch.h b/src/pulsecore/speex/arch.h
new file mode 100644
index 0000000..e2d731a
--- /dev/null
+++ b/src/pulsecore/speex/arch.h
@@ -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
index 0000000..2948177
--- /dev/null
+++ b/src/pulsecore/speex/fixed_generic.h
@@ -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
index 0000000..1cc4d49
--- /dev/null
+++ b/src/pulsecore/speex/resample.c
@@ -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
index 0000000..c44fbcd
--- /dev/null
+++ b/src/pulsecore/speex/speex_resampler.h
@@ -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

commit fdead579b7666f22816ff6712603a989400ecea2
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Aug 23 22:31:51 2007 +0000

    build speex resampler tiwce, once for fixed point, one for floating point
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1708 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/Makefile.am b/src/Makefile.am
index 04e5766..097b083 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -556,9 +556,22 @@ libpulsedsp_la_LIBADD = $(AM_LIBADD) libpulse.la
 libpulsedsp_la_LDFLAGS = -avoid-version
 
 ###################################
+#      Speex Resampler            #
+###################################
+
+noinst_LTLIBRARIES = libspeex-resampler-fixed.la libspeex-resampler-float.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
+
+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
+
+###################################
 #      Daemon core library        #
 ###################################
 
+
 pulsecoreinclude_HEADERS = \
 		pulsecore/autoload.h \
 		pulsecore/atomic.h \
@@ -699,7 +712,7 @@ 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
 
 ###################################
 #   Plug-in support libraries     #
@@ -1384,4 +1397,10 @@ 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
+
 .PHONY: utils/padsp

commit c72d4c6b9eeeb07e6c3ff6ff4574653b84d963c5
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Aug 23 22:32:58 2007 +0000

    add a small speex wrapper so that we can include both the fp and the fixed-point resampler in the same binary
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1709 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/speexwrap.h b/src/pulsecore/speexwrap.h
new file mode 100644
index 0000000..c0d5c0c
--- /dev/null
+++ b/src/pulsecore/speexwrap.h
@@ -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 at 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

commit c1cdcfde7cd1efa9c37a8e12b50ccfca944e0abe
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Aug 23 22:34:10 2007 +0000

    a couple of modernizations; parse RE sample types properly
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1710 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulse/sample.c b/src/pulse/sample.c
index 3d449f5..327e8e5 100644
--- a/src/pulse/sample.c
+++ b/src/pulse/sample.c
@@ -27,58 +27,58 @@
 #endif
 
 #include <stdio.h>
-#include <assert.h>
 #include <math.h>
 #include <string.h>
 
 #include <pulsecore/core-util.h>
+#include <pulsecore/macro.h>
+
 #include "sample.h"
 
 size_t pa_sample_size(const pa_sample_spec *spec) {
-    assert(spec);
-
-    switch (spec->format) {
-        case PA_SAMPLE_U8:
-        case PA_SAMPLE_ULAW:
-        case PA_SAMPLE_ALAW:
-            return 1;
-        case PA_SAMPLE_S16LE:
-        case PA_SAMPLE_S16BE:
-            return 2;
-        case PA_SAMPLE_FLOAT32LE:
-        case PA_SAMPLE_FLOAT32BE:
-            return 4;
-        default:
-            assert(0);
-            return 0;
-    }
+    
+    static const size_t table[] = {
+        [PA_SAMPLE_U8] = 1,
+        [PA_SAMPLE_ULAW] = 1,
+        [PA_SAMPLE_ALAW] = 1,
+        [PA_SAMPLE_S16LE] = 2,
+        [PA_SAMPLE_S16BE] = 2,
+        [PA_SAMPLE_FLOAT32LE] = 4,
+        [PA_SAMPLE_FLOAT32BE] = 4
+    };
+
+    pa_assert(spec);
+    pa_assert(spec->format >= 0);
+    pa_assert(spec->format < PA_SAMPLE_MAX);
+    
+    return table[spec->format];
 }
 
 size_t pa_frame_size(const pa_sample_spec *spec) {
-    assert(spec);
+    pa_assert(spec);
 
     return pa_sample_size(spec) * spec->channels;
 }
 
 size_t pa_bytes_per_second(const pa_sample_spec *spec) {
-    assert(spec);
+    pa_assert(spec);
     return spec->rate*pa_frame_size(spec);
 }
 
 pa_usec_t pa_bytes_to_usec(uint64_t length, const pa_sample_spec *spec) {
-    assert(spec);
+    pa_assert(spec);
 
     return (pa_usec_t) (((double) length/pa_frame_size(spec)*1000000)/spec->rate);
 }
 
 size_t pa_usec_to_bytes(pa_usec_t t, const pa_sample_spec *spec) {
-    assert(spec);
+    pa_assert(spec);
 
     return (size_t) (((double) t * spec->rate / 1000000))*pa_frame_size(spec);
 }
 
 int pa_sample_spec_valid(const pa_sample_spec *spec) {
-    assert(spec);
+    pa_assert(spec);
 
     if (spec->rate <= 0 ||
         spec->rate > PA_RATE_MAX ||
@@ -92,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);
 }
@@ -108,14 +109,16 @@ 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))
         pa_snprintf(s, l, "Invalid");
@@ -126,6 +129,8 @@ char *pa_sample_spec_snprint(char *s, size_t l, const pa_sample_spec *spec) {
 }
 
 char* pa_bytes_snprint(char *s, size_t l, unsigned v) {
+    pa_assert(s);
+    
     if (v >= ((unsigned) 1024)*1024*1024)
         pa_snprintf(s, l, "%0.1f GiB", ((double) v)/1024/1024/1024);
     else if (v >= ((unsigned) 1024)*1024)
@@ -139,6 +144,7 @@ char* pa_bytes_snprint(char *s, size_t l, unsigned v) {
 }
 
 pa_sample_format_t pa_parse_sample_format(const char *format) {
+    pa_assert(format);
 
     if (strcasecmp(format, "s16le") == 0)
         return PA_SAMPLE_S16LE;
@@ -146,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;

commit 4eb9bb074653a6ebbb925c701c69d2b101098142
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Aug 23 22:34:49 2007 +0000

    fix a bad memory access when destructing pa_memimports
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1711 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/memblock.c b/src/pulsecore/memblock.c
index da99609..914e429 100644
--- a/src/pulsecore/memblock.c
+++ b/src/pulsecore/memblock.c
@@ -608,10 +608,11 @@ 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);
-
-    pa_mutex_unlock(seg->import->mutex);
+    } else 
+        pa_mutex_unlock(seg->import->mutex);
 }
 
 pa_mempool* pa_mempool_new(int shared) {

commit ed4dc16b95ce73862540a9669c273b9d0b888100
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Aug 23 22:35:40 2007 +0000

    big resampler rework: support integer-only resampling, support speex resampler
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1712 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/resampler.c b/src/pulsecore/resampler.c
index 1405d7e..57de0d1 100644
--- a/src/pulsecore/resampler.c
+++ b/src/pulsecore/resampler.c
@@ -28,6 +28,7 @@
 #include <string.h>
 
 #include <samplerate.h>
+
 #include <liboil/liboilfuncs.h>
 #include <liboil/liboil.h>
 
@@ -36,41 +37,93 @@
 #include <pulsecore/log.h>
 #include <pulsecore/macro.h>
 
+#include "speexwrap.h"
+
 #include "resampler.h"
 
 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_update_output_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_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;
+
+    struct { /* data specific to libsamplerate */
+        SRC_STATE *state;
+    } src;
+
+    struct { /* data specific to speex */
+        SpeexResamplerState* state;
+    } speex;
 };
 
 static int libsamplerate_init(pa_resampler*r);
 static int trivial_init(pa_resampler*r);
+static int speex_init(pa_resampler*r);
+
+static void calc_map_table(pa_resampler *r);
+
+static int (* const init_table[])(pa_resampler*r) = {
+    [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,
+    [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_AUTO]                    = NULL,
+};
+
+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,
@@ -87,16 +140,25 @@ pa_resampler* pa_resampler_new(
     pa_assert(b);
     pa_assert(pa_sample_spec_valid(a));
     pa_assert(pa_sample_spec_valid(b));
-    pa_assert(resample_method != PA_RESAMPLER_INVALID);
-
+    pa_assert(resample_method >= 0);
+    pa_assert(resample_method < PA_RESAMPLER_MAX);
+
+    /* Fix method */
+    if (resample_method == PA_RESAMPLER_AUTO) {
+        if (a->format == PA_SAMPLE_FLOAT32LE || a->format == PA_SAMPLE_FLOAT32BE ||
+            b->format == PA_SAMPLE_FLOAT32LE || b->format == PA_SAMPLE_FLOAT32BE)
+            resample_method = PA_RESAMPLER_SPEEX_FLOAT_BASE + 0;
+        else
+            resample_method = PA_RESAMPLER_SPEEX_FIXED_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;
@@ -115,25 +177,62 @@ 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;
 
-        /* Use the libsamplerate based resampler for the complicated cases */
-        if (resample_method == PA_RESAMPLER_TRIVIAL)
-            r->resample_method = PA_RESAMPLER_SRC_ZERO_ORDER_HOLD;
+    calc_map_table(r);
 
-        if (libsamplerate_init(r) < 0)
+    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)
+        r->work_format = PA_SAMPLE_S16NE;
+    else if (resample_method == PA_RESAMPLER_TRIVIAL) {
+
+        if (r->map_required || a->format != b->format) {
+
+            if (a->format == PA_SAMPLE_FLOAT32NE || a->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;
+
+    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:
@@ -149,6 +248,15 @@ void pa_resampler_free(pa_resampler *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);
 }
 
@@ -160,9 +268,7 @@ void pa_resampler_set_input_rate(pa_resampler *r, uint32_t 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_set_output_rate(pa_resampler *r, uint32_t rate) {
@@ -173,15 +279,7 @@ void pa_resampler_set_output_rate(pa_resampler *r, uint32_t rate) {
         return;
 
     r->o_ss.rate = rate;
-
-    if (r->impl_update_output_rate)
-        r->impl_update_output_rate(r, rate);
-}
-
-void pa_resampler_run(pa_resampler *r, const pa_memchunk *in, pa_memchunk *out) {
-    pa_assert(r && in && out && r->impl_run);
-
-    r->impl_run(r, in, out);
+    r->impl_update_rates(r);
 }
 
 size_t pa_resampler_request(pa_resampler *r, size_t out_length) {
@@ -192,6 +290,7 @@ size_t pa_resampler_request(pa_resampler *r, size_t out_length) {
 
 pa_resample_method_t pa_resampler_get_method(pa_resampler *r) {
     pa_assert(r);
+    
     return r->resample_method;
 }
 
@@ -201,7 +300,30 @@ 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",
+    "auto"
 };
 
 const char *pa_resample_method_to_string(pa_resample_method_t m) {
@@ -221,44 +343,21 @@ pa_resample_method_t pa_parse_resample_method(const char *string) {
         if (!strcmp(string, resample_methods[m]))
             return m;
 
-    return PA_RESAMPLER_INVALID;
-}
-
+    if (!strcmp(string, "speex-fixed"))
+        return PA_RESAMPLER_SPEEX_FIXED_BASE + 0;
 
-/*** libsamplerate based implementation ***/
+    if (!strcmp(string, "speex-float"))
+        return PA_RESAMPLER_SPEEX_FLOAT_BASE + 0;
 
-static void libsamplerate_free(pa_resampler *r) {
-    struct impl_libsamplerate *u;
-
-    pa_assert(r);
-    pa_assert(r->impl_data);
-
-    u = r->impl_data;
-
-    if (u->src_state)
-        src_delete(u->src_state);
-
-    if (u->buf1.memblock)
-        pa_memblock_unref(u->buf1.memblock);
-    if (u->buf2.memblock)
-        pa_memblock_unref(u->buf2.memblock);
-    if (u->buf3.memblock)
-        pa_memblock_unref(u->buf3.memblock);
-    if (u->buf4.memblock)
-        pa_memblock_unref(u->buf4.memblock);
-    pa_xfree(u);
+    return PA_RESAMPLER_INVALID;
 }
 
 static void calc_map_table(pa_resampler *r) {
-    struct impl_libsamplerate *u;
     unsigned oc;
     
     pa_assert(r);
-    pa_assert(r->impl_data);
-
-    u = r->impl_data;
 
-    if (!(u->map_required = (r->i_ss.channels != r->o_ss.channels || !pa_channel_map_equal(&r->i_cm, &r->o_cm))))
+    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++) {
@@ -276,17 +375,16 @@ 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 pa_memchunk* convert_to_float(pa_resampler *r, pa_memchunk *input) {
-    struct impl_libsamplerate *u;
+static pa_memchunk* convert_to_work_format(pa_resampler *r, pa_memchunk *input) {
     unsigned n_samples;
     void *src, *dst;
 
@@ -294,192 +392,193 @@ static pa_memchunk* convert_to_float(pa_resampler *r, pa_memchunk *input) {
     pa_assert(input);
     pa_assert(input->memblock);
 
-    pa_assert(r->impl_data);
-    u = r->impl_data;
-
-    /* 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 || !input->length)
+    if (!r->to_work_format_func || !input->length)
         return input;
 
     n_samples = (input->length / r->i_fz) * r->i_ss.channels;
 
-    if (!u->buf1.memblock || u->buf1_samples < n_samples) {
-        if (u->buf1.memblock)
-            pa_memblock_unref(u->buf1.memblock);
+    r->buf1.index = 0;
+    r->buf1.length = r->w_sz * n_samples;
+    
+    if (!r->buf1.memblock || r->buf1_samples < n_samples) {
+        if (r->buf1.memblock)
+            pa_memblock_unref(r->buf1.memblock);
 
-        u->buf1_samples = n_samples;
-        u->buf1.memblock = pa_memblock_new(r->mempool, u->buf1.length = sizeof(float) * n_samples);
-        u->buf1.index = 0;
+        r->buf1_samples = n_samples;
+        r->buf1.memblock = pa_memblock_new(r->mempool, r->buf1.length);
     }
 
     src = (uint8_t*) pa_memblock_acquire(input->memblock) + input->index;
-    dst = (uint8_t*) pa_memblock_acquire(u->buf1.memblock);
+    dst = (uint8_t*) pa_memblock_acquire(r->buf1.memblock);
 
-    u->to_float32ne_func(n_samples, src, dst);
+    r->to_work_format_func(n_samples, src, dst);
 
     pa_memblock_release(input->memblock);
-    pa_memblock_release(u->buf1.memblock);
-
-    u->buf1.length = sizeof(float) * n_samples;
+    pa_memblock_release(r->buf1.memblock);
 
-    return &u->buf1;
+    return &r->buf1;
 }
 
 static pa_memchunk *remap_channels(pa_resampler *r, pa_memchunk *input) {
-    struct impl_libsamplerate *u;
     unsigned in_n_samples, out_n_samples, n_frames;
     int i_skip, o_skip;
     unsigned oc;
-    float *src, *dst;
+    void *src, *dst;
 
     pa_assert(r);
     pa_assert(input);
     pa_assert(input->memblock);
 
-    pa_assert(r->impl_data);
-    u = r->impl_data;
-
     /* Remap channels and place the result int buf2 */
 
-    if (!u->map_required || !input->length)
+    if (!r->map_required || !input->length)
         return input;
 
-    in_n_samples = input->length / sizeof(float);
+    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;
 
-    if (!u->buf2.memblock || u->buf2_samples < out_n_samples) {
-        if (u->buf2.memblock)
-            pa_memblock_unref(u->buf2.memblock);
+    r->buf2.index = 0;
+    r->buf2.length = r->w_sz * out_n_samples;
+    
+    if (!r->buf2.memblock || r->buf2_samples < out_n_samples) {
+        if (r->buf2.memblock)
+            pa_memblock_unref(r->buf2.memblock);
 
-        u->buf2_samples = out_n_samples;
-        u->buf2.memblock = pa_memblock_new(r->mempool, u->buf2.length = sizeof(float) * out_n_samples);
-        u->buf2.index = 0;
+        r->buf2_samples = out_n_samples;
+        r->buf2.memblock = pa_memblock_new(r->mempool, r->buf2.length);
     }
 
-    src = (float*) ((uint8_t*) pa_memblock_acquire(input->memblock) + input->index);
-    dst = (float*) pa_memblock_acquire(u->buf2.memblock);
-
-    memset(dst, 0, u->buf2.length);
-
-    o_skip = sizeof(float) * r->o_ss.channels;
-    i_skip = sizeof(float) * r->i_ss.channels;
-
-    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(
-                dst + oc, o_skip,
-                dst + oc, o_skip,
-                src + u->map_table[oc][i], i_skip,
-                n_frames,
-                &one, &one);
+    src = ((uint8_t*) pa_memblock_acquire(input->memblock) + input->index);
+    dst = pa_memblock_acquire(r->buf2.memblock);
+
+    memset(dst, 0, r->buf2.length);
+
+    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();
     }
 
     pa_memblock_release(input->memblock);
-    pa_memblock_release(u->buf2.memblock);
+    pa_memblock_release(r->buf2.memblock);
 
-    u->buf2.length = out_n_samples * sizeof(float);
+    r->buf2.length = out_n_samples * r->w_sz;
 
-    return &u->buf2;
+    return &r->buf2;
 }
 
 static pa_memchunk *resample(pa_resampler *r, pa_memchunk *input) {
-    struct impl_libsamplerate *u;
-    SRC_DATA data;
     unsigned in_n_frames, in_n_samples;
     unsigned out_n_frames, out_n_samples;
-    int ret;
 
     pa_assert(r);
     pa_assert(input);
-    pa_assert(r->impl_data);
-    u = r->impl_data;
 
     /* Resample the data and place the result in buf3 */
 
-    if (!u->src_state || !input->length)
+    if (!r->impl_resample || !input->length)
         return input;
 
-    in_n_samples = input->length / sizeof(float);
+    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)+1024;
     out_n_samples = out_n_frames * r->o_ss.channels;
 
-    if (!u->buf3.memblock || u->buf3_samples < out_n_samples) {
-        if (u->buf3.memblock)
-            pa_memblock_unref(u->buf3.memblock);
+    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.memblock = pa_memblock_new(r->mempool, u->buf3.length = sizeof(float) * out_n_samples);
-        u->buf3.index = 0;
+        r->buf3_samples = out_n_samples;
+        r->buf3.memblock = pa_memblock_new(r->mempool, r->buf3.length);
     }
 
-    data.data_in = (float*) ((uint8_t*) pa_memblock_acquire(input->memblock) + input->index);
-    data.input_frames = in_n_frames;
-
-    data.data_out = (float*) pa_memblock_acquire(u->buf3.memblock);
-    data.output_frames = out_n_frames;
-
-    data.src_ratio = (double) r->o_ss.rate / r->i_ss.rate;
-    data.end_of_input = 0;
-
-    ret = src_process(u->src_state, &data);
-    pa_assert(ret == 0);
-    pa_assert((unsigned) data.input_frames_used == in_n_frames);
-
-    pa_memblock_release(input->memblock);
-    pa_memblock_release(u->buf3.memblock);
-
-    u->buf3.length = data.output_frames_gen * sizeof(float) * r->o_ss.channels;
-
-    return &u->buf3;
+    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;
+    
+    return &r->buf3;
 }
 
-static pa_memchunk *convert_from_float(pa_resampler *r, pa_memchunk *input) {
-    struct impl_libsamplerate *u;
+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);
-    pa_assert(r->impl_data);
-    u = r->impl_data;
 
     /* Convert the data into the correct sample type and place the result in buf4 */
 
-    if (!u->from_float32ne_func || !input->length)
+    if (!r->from_work_format_func || !input->length)
         return input;
 
-    n_frames = input->length / sizeof(float) / r->o_ss.channels;
-    n_samples = n_frames * r->o_ss.channels;
+    n_samples = input->length / r->w_sz;
+    n_frames =  n_samples / r->o_ss.channels;
 
-    if (!u->buf4.memblock || u->buf4_samples < n_samples) {
-        if (u->buf4.memblock)
-            pa_memblock_unref(u->buf4.memblock);
+    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);
 
-        u->buf4_samples = n_samples;
-        u->buf4.memblock = pa_memblock_new(r->mempool, u->buf4.length = r->o_fz * n_frames);
-        u->buf4.index = 0;
+        r->buf4_samples = n_samples;
+        r->buf4.memblock = pa_memblock_new(r->mempool, r->buf4.length);
     }
 
     src = (uint8_t*) pa_memblock_acquire(input->memblock) + input->index;
-    dst = pa_memblock_acquire(u->buf4.memblock);
-    u->from_float32ne_func(n_samples, src, dst);
+    dst = pa_memblock_acquire(r->buf4.memblock);
+    r->from_work_format_func(n_samples, src, dst);
     pa_memblock_release(input->memblock);
-    pa_memblock_release(u->buf4.memblock);
+    pa_memblock_release(r->buf4.memblock);
 
-    u->buf4.length = r->o_fz * n_frames;
+    r->buf4.length = r->o_fz * n_frames;
 
-    return &u->buf4;
+    return &r->buf4;
 }
 
-static void libsamplerate_run(pa_resampler *r, const pa_memchunk *in, pa_memchunk *out) {
-    struct impl_libsamplerate *u;
+void pa_resampler_run(pa_resampler *r, const pa_memchunk *in, pa_memchunk *out) {
     pa_memchunk *buf;
 
     pa_assert(r);
@@ -488,19 +587,16 @@ static void libsamplerate_run(pa_resampler *r, const pa_memchunk *in, pa_memchun
     pa_assert(in->length);
     pa_assert(in->memblock);
     pa_assert(in->length % r->i_fz == 0);
-    pa_assert(r->impl_data);
-
-    u = r->impl_data;
 
     buf = (pa_memchunk*) in;
-    buf = convert_to_float(r, buf);
+    buf = convert_to_work_format(r, buf);
     buf = remap_channels(r, buf);
     buf = resample(r, buf);
 
     if (buf->length) {
-        buf = convert_from_float(r, buf);
+        buf = convert_from_work_format(r, buf);
         *out = *buf;
-
+        
         if (buf == in)
             pa_memblock_ref(buf->memblock);
         else
@@ -509,188 +605,222 @@ static void libsamplerate_run(pa_resampler *r, const pa_memchunk *in, pa_memchun
         pa_memchunk_reset(out);
 }
 
-static void libsamplerate_update_input_rate(pa_resampler *r, uint32_t rate) {
-    struct impl_libsamplerate *u;
+/*** libsamplerate based implementation ***/
 
+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;
+    
     pa_assert(r);
-    pa_assert(rate > 0);
-    pa_assert(r->impl_data);
-    u = r->impl_data;
+    pa_assert(input);
+    pa_assert(output);
+    pa_assert(out_n_frames);
+    
+    memset(&data, 0, sizeof(data));
+    
+    data.data_in = (float*) ((uint8_t*) pa_memblock_acquire(input->memblock) + input->index);
+    data.input_frames = in_n_frames;
 
-    if (!u->src_state) {
-        int err;
-        u->src_state = src_new(r->resample_method, r->o_ss.channels, &err);
-        pa_assert(u->src_state);
-    } else {
-        int ret = src_set_ratio(u->src_state, (double) r->o_ss.rate / rate);
-        pa_assert(ret == 0);
-    }
-}
+    data.data_out = (float*) ((uint8_t*) pa_memblock_acquire(output->memblock) + output->index);
+    data.output_frames = *out_n_frames;
 
-static void libsamplerate_update_output_rate(pa_resampler *r, uint32_t rate) {
-    struct impl_libsamplerate *u;
+    data.src_ratio = (double) r->o_ss.rate / r->i_ss.rate;
+    data.end_of_input = 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_rates(pa_resampler *r) {
     pa_assert(r);
-    pa_assert(rate > 0);
-    pa_assert(r->impl_data);
-    u = r->impl_data;
 
-    if (!u->src_state) {
-        int err;
-        u->src_state = src_new(r->resample_method, r->o_ss.channels, &err);
-        pa_assert(u->src_state);
-    } else {
-        int ret = src_set_ratio(u->src_state, (double) rate / r->i_ss.rate);
-        pa_assert(ret == 0);
-    }
+    pa_assert_se(src_set_ratio(r->src.state, (double) r->o_ss.rate / r->i_ss.rate) == 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;
+    
+    pa_assert(r);
+    
+    if (!(r->src.state = src_new(r->resample_method, r->o_ss.channels, &err)))
+        return -1;
 
-    r->impl_data = u = pa_xnew(struct impl_libsamplerate, 1);
-
-    pa_memchunk_reset(&u->buf1);
-    pa_memchunk_reset(&u->buf2);
-    pa_memchunk_reset(&u->buf3);
-    pa_memchunk_reset(&u->buf4);
-    u->buf1_samples = u->buf2_samples = u->buf3_samples = u->buf4_samples = 0;
+    r->impl_free = libsamplerate_free;
+    r->impl_update_rates = libsamplerate_update_rates;
+    r->impl_resample = libsamplerate_resample;
 
-    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;
+    return 0;
+}
 
-    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;
+/*** speex based implementation ***/
 
-    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;
+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;
 
-    r->impl_free = libsamplerate_free;
-    r->impl_update_input_rate = libsamplerate_update_input_rate;
-    r->impl_update_output_rate = libsamplerate_update_output_rate;
-    r->impl_run = libsamplerate_run;
+    pa_assert(r);
+    pa_assert(input);
+    pa_assert(output);
+    pa_assert(out_n_frames);
+    
+    in = (float*) ((uint8_t*) pa_memblock_acquire(input->memblock) + input->index);
+    out = (float*) ((uint8_t*) pa_memblock_acquire(output->memblock) + output->index);
 
-    calc_map_table(r);
+    pa_assert_se(paspfl_resampler_process_interleaved_float(r->speex.state, in, &inf, out, &outf) == 0);
 
-    return 0;
+    pa_memblock_release(input->memblock);
+    pa_memblock_release(output->memblock);
 
-fail:
-    pa_xfree(u);
-    return -1;
+    pa_assert(inf == in_n_frames);
+    *out_n_frames = outf;
 }
 
-/* Trivial implementation */
-
-static void trivial_run(pa_resampler *r, const pa_memchunk *in, pa_memchunk *out) {
-    size_t fz;
-    unsigned  n_frames;
-    struct impl_trivial *u;
+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;
 
     pa_assert(r);
-    pa_assert(in);
-    pa_assert(out);
-    pa_assert(r->impl_data);
-
-    u = r->impl_data;
-
-    fz = r->i_fz;
-    pa_assert(fz == r->o_fz);
+    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);
 
-    n_frames = in->length/fz;
+    pa_assert_se(paspfx_resampler_process_interleaved_int(r->speex.state, in, &inf, out, &outf) == 0);
 
-    if (r->i_ss.rate == r->o_ss.rate) {
+    pa_memblock_release(input->memblock);
+    pa_memblock_release(output->memblock);
 
-        /* In case there's no diefference in sample types, do nothing */
-        *out = *in;
-        pa_memblock_ref(out->memblock);
+    pa_assert(inf == in_n_frames);
+    *out_n_frames = outf;
+}
 
-        u->o_counter += n_frames;
-    } else {
-        /* Do real resampling */
-        size_t l;
-        unsigned o_index;
-        void *src, *dst;
+static void speex_update_rates(pa_resampler *r) {
+    pa_assert(r);
 
-        /* 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->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);
+    }
+}
 
-        out->index = 0;
-        out->memblock = pa_memblock_new(r->mempool, l);
+static void speex_free(pa_resampler *r) {
+    pa_assert(r);
+    
+    if (r->speex.state) {
+        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);
+        }
+    }
+}
 
-        src = (uint8_t*) pa_memblock_acquire(in->memblock) + in->index;
-        dst = pa_memblock_acquire(out->memblock);
+static int speex_init(pa_resampler *r) {
+    int q, err;
+    
+    pa_assert(r);
 
-        for (o_index = 0;; o_index++, u->o_counter++) {
-            unsigned j;
+    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;
+        r->impl_resample = speex_resample_int;
 
-            j = (u->o_counter * r->i_ss.rate / r->o_ss.rate);
-            j = j > u->i_counter ? j - u->i_counter : 0;
+        if (!(r->speex.state = paspfx_resampler_init(r->o_ss.channels, r->i_ss.rate, r->o_ss.rate, q, &err)))
+            return -1;
 
-            if (j >= n_frames)
-                break;
+    } else {
+        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;
+        r->impl_resample = speex_resample_float;
 
-            pa_assert(o_index*fz < pa_memblock_get_length(out->memblock));
+        if (!(r->speex.state = paspfl_resampler_init(r->o_ss.channels, r->i_ss.rate, r->o_ss.rate, q, &err)))
+            return -1;
+    }
+    
 
-            memcpy((uint8_t*) dst + fz*o_index,
-                   (uint8_t*) src + fz*j, fz);
+    return 0;
+}
 
-        }
+/* Trivial implementation */
 
-        pa_memblock_release(in->memblock);
-        pa_memblock_release(out->memblock);
+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;
+    
+    pa_assert(r);
+    pa_assert(input);
+    pa_assert(output);
+    pa_assert(out_n_frames);
 
-        out->length = o_index*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;
+        
+        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);   
     }
+    
+    pa_memblock_release(input->memblock);
+    pa_memblock_release(output->memblock);
+    
+    *out_n_frames = o_index;
 
-    u->i_counter += n_frames;
+    r->trivial.i_counter += in_n_frames;
 
     /* Normalize counters */
-    while (u->i_counter >= r->i_ss.rate) {
-        u->i_counter -= r->i_ss.rate;
-        pa_assert(u->o_counter >= r->o_ss.rate);
-        u->o_counter -= r->o_ss.rate;
-    }
-}
-
-static void trivial_free(pa_resampler *r) {
-    pa_assert(r);
+    while (r->trivial.i_counter >= r->i_ss.rate) {
+        pa_assert(r->trivial.o_counter >= r->o_ss.rate);
 
-    pa_xfree(r->impl_data);
+        r->trivial.i_counter -= r->i_ss.rate;
+        r->trivial.o_counter -= r->o_ss.rate;
+    }
 }
 
-static void trivial_update_rate(pa_resampler *r, uint32_t rate) {
-    struct impl_trivial *u;
-
+static void trivial_update_rates(pa_resampler *r) {
     pa_assert(r);
-    pa_assert(rate > 0);
-    pa_assert(r->impl_data);
 
-    u = r->impl_data;
-    u->i_counter = 0;
-    u->o_counter = 0;
+    r->trivial.i_counter = 0;
+    r->trivial.o_counter = 0;
 }
 
 static int trivial_init(pa_resampler*r) {
-    struct impl_trivial *u;
-
     pa_assert(r);
-    pa_assert(r->i_ss.format == r->o_ss.format);
-    pa_assert(r->i_ss.channels == r->o_ss.channels);
 
-    r->impl_data = u = pa_xnew(struct impl_trivial, 1);
-    u->o_counter = u->i_counter = 0;
+    r->trivial.o_counter = r->trivial.i_counter = 0;
 
-    r->impl_run = trivial_run;
-    r->impl_free = trivial_free;
-    r->impl_update_input_rate = trivial_update_rate;
-    r->impl_update_output_rate = trivial_update_rate;
+    r->impl_resample = trivial_resample;
+    r->impl_update_rates = trivial_update_rates;
 
     return 0;
 }
diff --git a/src/pulsecore/resampler.h b/src/pulsecore/resampler.h
index ada293e..35f53db 100644
--- a/src/pulsecore/resampler.h
+++ b/src/pulsecore/resampler.h
@@ -41,6 +41,11 @@ typedef enum pa_resample_method {
     PA_RESAMPLER_SRC_ZERO_ORDER_HOLD     = SRC_ZERO_ORDER_HOLD,
     PA_RESAMPLER_SRC_LINEAR              = 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_AUTO, /* automatic select based on sample format */
     PA_RESAMPLER_MAX
 } pa_resample_method_t;
 
diff --git a/src/pulsecore/sconv-s16be.c b/src/pulsecore/sconv-s16be.c
index c530e79..658b3f5 100644
--- a/src/pulsecore/sconv-s16be.c
+++ b/src/pulsecore/sconv-s16be.c
@@ -33,6 +33,9 @@
 #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
diff --git a/src/pulsecore/sconv-s16be.h b/src/pulsecore/sconv-s16be.h
index 6b736f6..ad03448 100644
--- a/src/pulsecore/sconv-s16be.h
+++ b/src/pulsecore/sconv-s16be.h
@@ -24,7 +24,18 @@
   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
diff --git a/src/pulsecore/sconv-s16le.c b/src/pulsecore/sconv-s16le.c
index 5f45ef6..c82708c 100644
--- a/src/pulsecore/sconv-s16le.c
+++ b/src/pulsecore/sconv-s16le.c
@@ -25,12 +25,12 @@
 #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"
@@ -53,32 +53,28 @@
 #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
 
@@ -93,13 +89,55 @@ void pa_sconv_s16le_from_float32ne(unsigned n, const float *a, void *b) {
             v = -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);
+
+#if SWAP_WORDS == 1
+
+    for (; n > 0; n--) {
+        int16_t s = *(a++);
+        float k = ((float) INT16_FROM(s))/0x7FFF;
+        uint32_t *j = (uint32_t*) &k;
+        *j = UINT32_SWAP(*j);
+        *(b++) = k;
+    }
+
+#endif
+}
+
+void pa_sconv_s16le_from_float32re(unsigned n, const float *a, int16_t *b) {
+    pa_assert(a);
+    pa_assert(b);
+
+#if SWAP_WORDS == 1
+
+    for (; n > 0; n--) {
+        int16_t s;
+        float v = *(a++);
+        uint32_t *j = (uint32_t*) &v;
+        *j = UINT32_SWAP(*j);
+
+        if (v > 1)
+            v = 1;
+
+        if (v < -1)
+            v = -1;
+
+        s = (int16_t) (v * 0x7FFF);
+        *(b++) = INT16_TO(s);
+    }
+
 #endif
 }
diff --git a/src/pulsecore/sconv-s16le.h b/src/pulsecore/sconv-s16le.h
index c4e4911..4203315 100644
--- a/src/pulsecore/sconv-s16le.h
+++ b/src/pulsecore/sconv-s16le.h
@@ -24,7 +24,18 @@
   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
diff --git a/src/pulsecore/sconv.c b/src/pulsecore/sconv.c
index d15cec8..4986ba7 100644
--- a/src/pulsecore/sconv.c
+++ b/src/pulsecore/sconv.c
@@ -28,12 +28,12 @@
 
 #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"
@@ -41,71 +41,92 @@
 
 #include "sconv.h"
 
-static void u8_to_float32ne(unsigned n, const void *a, float *b) {
-    const uint8_t *ca = a;
+/* u8 */
+static void u8_to_float32ne(unsigned n, const uint8_t *a, float *b) {
     static const double add = -128.0/127.0, factor = 1.0/127.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 void u8_from_float32ne(unsigned n, const float *a, uint8_t *b) {
     static const double add = 128.0, 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 = -128, 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 ++, a++)
+        *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);
 
-    while (n-- > 0)
-        ((uint32_t *)b)[n] = UINT32_SWAP (((uint32_t *)a)[n]);
+    for (; n > 0; n--, a++, b++)
+        *((uint32_t *) b) = UINT32_SWAP(*((uint32_t *) a));
 }
 
-static void float32re_from_float32ne(unsigned n, const float *a, void *b) {
-    assert(a);
-    assert(b);
+/* 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 ulaw_to_float32ne(unsigned n, const void *a, float *b) {
-    const uint8_t *ca = a;
+static void s16re_to_s16ne(unsigned n, const int16_t *a, int16_t *b) {
+    pa_assert(a);
+    pa_assert(b);
+
+    for (; n > 0; n--, a++, b++)
+        *b = UINT16_SWAP(*a);
+}
 
-    assert(a);
-    assert(b);
+/* ulaw */
+
+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++) = st_ulaw2linear16(*(a++)) * 1.0F / 0x7FFF;
 }
 
-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++);
@@ -116,28 +137,42 @@ static void ulaw_from_float32ne(unsigned n, const float *a, void *b) {
         if (v < -1)
             v = -1;
 
-        *(cb++) = st_14linear2ulaw((int16_t) (v * 0x1FFF));
+        *(b++) = st_14linear2ulaw((int16_t) (v * 0x1FFF));
     }
 }
 
-static void alaw_to_float32ne(unsigned n, const void *a, float *b) {
-    const uint8_t *ca = a;
+static void ulaw_to_s16ne(unsigned n, const uint8_t *a, int16_t *b) {
+    pa_assert(a);
+    pa_assert(b);
 
-    assert(a);
-    assert(b);
+    for (; n > 0; n--, a++, b++)
+        *b = st_ulaw2linear16(*a);
+}
 
-    for (; n > 0; n--)
-        *(b++) = st_alaw2linear16(*(ca++)) * 1.0F / 0x7FFF;
+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);
 }
 
-static void alaw_from_float32ne(unsigned n, const float *a, void *b) {
-    uint8_t *cb = b;
+/* alaw */
 
-    assert(a);
-    assert(b);
+static void alaw_to_float32ne(unsigned n, const uint8_t *a, float *b) {
+    pa_assert(a);
+    pa_assert(b);
 
-    for (; n > 0; n--) {
-        float v = *(a++);
+    for (; n > 0; n--, a++, b++)
+        *b = st_alaw2linear16(*a) * 1.0F / 0x7FFF;
+}
+
+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;
 
         if (v > 1)
             v = 1;
@@ -145,48 +180,94 @@ static void alaw_from_float32ne(unsigned n, const float *a, void *b) {
         if (v < -1)
             v = -1;
 
-        *(cb++) = st_13linear2alaw((int16_t) (v * 0xFFF));
+        *b = st_13linear2alaw((int16_t) (v * 0xFFF));
     }
 }
 
-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;
-    }
+static void alaw_to_s16ne(unsigned n, const int8_t *a, int16_t *b) {
+    pa_assert(a);
+    pa_assert(b);
+
+    for (; n > 0; n--, a++, b++)
+        *b = st_alaw2linear16(*a);
 }
 
-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;
-    }
+static void alaw_from_s16ne(unsigned n, const int16_t *a, uint8_t *b) {
+    pa_assert(a);
+    pa_assert(b);
+
+    for (; n > 0; n--)
+        *b = st_13linear2alaw(*a >> 3);
+}
+
+pa_convert_func_t pa_get_convert_to_float32ne_function(pa_sample_format_t f) {
+
+    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,
+    };
+
+    pa_assert(f >= 0);
+    pa_assert(f < PA_SAMPLE_MAX);
+
+    return table[f];
+}
+
+pa_convert_func_t pa_get_convert_from_float32ne_function(pa_sample_format_t f) {
+
+    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_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_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];
 }
diff --git a/src/pulsecore/sconv.h b/src/pulsecore/sconv.h
index 1e97aad..5e8fa68 100644
--- a/src/pulsecore/sconv.h
+++ b/src/pulsecore/sconv.h
@@ -27,10 +27,12 @@
 
 #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_convert_func_t pa_get_convert_from_float32ne_function(pa_sample_format_t f);
+
+pa_convert_func_t pa_get_convert_to_s16ne_function(pa_sample_format_t f);
+pa_convert_func_t pa_get_convert_from_s16ne_function(pa_sample_format_t f);
 
 #endif

commit f754a24cd24670c580d045584b1c5c4874b239c5
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Aug 23 22:35:58 2007 +0000

    make speex resampler the default
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1713 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/daemon/daemon-conf.c b/src/daemon/daemon-conf.c
index b6e8d54..e3ad8b3 100644
--- a/src/daemon/daemon-conf.c
+++ b/src/daemon/daemon-conf.c
@@ -72,7 +72,7 @@ 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,

commit 640ae04589286fa3de8da7155397b7196df07ce9
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Aug 24 00:23:22 2007 +0000

    Copy resampler from ffmpeg into our sources
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1714 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/ffmpeg/avcodec.h b/src/pulsecore/ffmpeg/avcodec.h
new file mode 100644
index 0000000..775ec96
--- /dev/null
+++ b/src/pulsecore/ffmpeg/avcodec.h
@@ -0,0 +1,71 @@
+/*
+ * 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 */
+
+#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);
+
+#endif /* AVCODEC_H */
diff --git a/src/pulsecore/ffmpeg/dsputil.h b/src/pulsecore/ffmpeg/dsputil.h
new file mode 100644
index 0000000..8da742d
--- /dev/null
+++ b/src/pulsecore/ffmpeg/dsputil.h
@@ -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
index 0000000..da1443d
--- /dev/null
+++ b/src/pulsecore/ffmpeg/resample2.c
@@ -0,0 +1,324 @@
+/*
+ * audio resampling
+ * Copyright (c) 2004 Michael Niedermayer <michaelni at 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 at 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;
+}

commit f0dbbe966ff321997e57c5e47308b1e18d962781
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Aug 24 00:23:48 2007 +0000

    add makefiles to speex/ and ffmpeg/ to easy compilation from emacs
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1715 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/ffmpeg/Makefile b/src/pulsecore/ffmpeg/Makefile
new file mode 100644
index 0000000..316beb7
--- /dev/null
+++ b/src/pulsecore/ffmpeg/Makefile
@@ -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/resampler.c b/src/pulsecore/resampler.c
index 57de0d1..47a5eac 100644
--- a/src/pulsecore/resampler.c
+++ b/src/pulsecore/resampler.c
@@ -39,6 +39,8 @@
 
 #include "speexwrap.h"
 
+#include "ffmpeg/avcodec.h"
+
 #include "resampler.h"
 
 struct pa_resampler {
@@ -75,11 +77,17 @@ struct pa_resampler {
     struct { /* data specific to speex */
         SpeexResamplerState* state;
     } speex;
+
+    struct { /* data specific to ffmpeg */
+        struct AVResampleContext *state;
+        unsigned initial_i_rate, initial_o_rate;
+    } ffmpeg;
 };
 
 static int libsamplerate_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);
 
 static void calc_map_table(pa_resampler *r);
 
@@ -112,6 +120,7 @@ static int (* const init_table[])(pa_resampler*r) = {
     [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,
 };
 
@@ -131,7 +140,8 @@ 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;
 
@@ -144,6 +154,12 @@ pa_resampler* pa_resampler_new(
     pa_assert(resample_method < PA_RESAMPLER_MAX);
 
     /* Fix method */
+
+    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_AUTO) {
         if (a->format == PA_SAMPLE_FLOAT32LE || a->format == PA_SAMPLE_FLOAT32BE ||
             b->format == PA_SAMPLE_FLOAT32LE || b->format == PA_SAMPLE_FLOAT32BE)
@@ -151,7 +167,7 @@ pa_resampler* pa_resampler_new(
         else
             resample_method = PA_RESAMPLER_SPEEX_FIXED_BASE + 0;
     }
-    
+
     r = pa_xnew(pa_resampler, 1);
     r->mempool = pool;
     r->resample_method = resample_method;
@@ -188,7 +204,8 @@ pa_resampler* pa_resampler_new(
 
     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)
+    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) {
 
@@ -268,6 +285,7 @@ void pa_resampler_set_input_rate(pa_resampler *r, uint32_t rate) {
         return;
 
     r->i_ss.rate = rate;
+
     r->impl_update_rates(r);
 }
 
@@ -279,6 +297,7 @@ void pa_resampler_set_output_rate(pa_resampler *r, uint32_t rate) {
         return;
 
     r->o_ss.rate = rate;
+
     r->impl_update_rates(r);
 }
 
@@ -323,6 +342,7 @@ static const char * const resample_methods[] = {
     "speex-fixed-8",
     "speex-fixed-9",
     "speex-fixed-10",
+    "ffmpeg",
     "auto"
 };
 
@@ -825,4 +845,56 @@ static int trivial_init(pa_resampler*r) {
     return 0;
 }
 
+/*** 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) {
+    short *src, *dst;
+    int consumed;
+    int c;
+    
+    pa_assert(r);
+    pa_assert(input);
+    pa_assert(output);
+    pa_assert(out_n_frames);
+    
+    src = (short*) ((uint8_t*) pa_memblock_acquire(input->memblock) + input->index);
+    dst = (short*) ((uint8_t*) pa_memblock_acquire(output->memblock) + output->index);
+
+    for (c = 0; c < r->o_ss.channels; c++) 
+        *out_n_frames = av_resample(r->ffmpeg.state,
+                                    dst + r->w_sz*c,
+                                    src + r->w_sz*c,
+                                    &consumed,
+                                    in_n_frames, *out_n_frames,
+                                    c >= r->o_ss.channels-1);
+
+    pa_assert(*out_n_frames > 0);
+    pa_assert(consumed == in_n_frames);
+    
+    pa_memblock_release(input->memblock);
+    pa_memblock_release(output->memblock);
+}
+
+static void ffmpeg_free(pa_resampler *r) {
+    pa_assert(r);
+    
+    if (r->ffmpeg.state)
+        av_resample_close(r->ffmpeg.state);
+}
+
+static int ffmpeg_init(pa_resampler *r) {
+    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;
 
+    return 0;
+}
diff --git a/src/pulsecore/resampler.h b/src/pulsecore/resampler.h
index 35f53db..2a943e3 100644
--- a/src/pulsecore/resampler.h
+++ b/src/pulsecore/resampler.h
@@ -45,6 +45,7 @@ typedef enum pa_resample_method {
     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_MAX
 } pa_resample_method_t;
@@ -55,7 +56,8 @@ 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);
 
diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c
index 8bec5d5..0cdcbc0 100644
--- a/src/pulsecore/sink-input.c
+++ b/src/pulsecore/sink-input.c
@@ -153,7 +153,8 @@ pa_sink_input* pa_sink_input_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;
         }
@@ -639,8 +640,8 @@ int pa_sink_input_move_to(pa_sink_input *i, pa_sink *dest, int immediately) {
         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 */
 
@@ -648,7 +649,8 @@ 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;
         }
diff --git a/src/pulsecore/source-output.c b/src/pulsecore/source-output.c
index ce81fcc..2532246 100644
--- a/src/pulsecore/source-output.c
+++ b/src/pulsecore/source-output.c
@@ -121,7 +121,8 @@ pa_source_output* pa_source_output_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;
         }
@@ -351,8 +352,9 @@ int pa_source_output_move_to(pa_source_output *o, pa_source *dest) {
         /* Try to reuse the old resampler if possible */
         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 source */
 
@@ -360,7 +362,8 @@ int pa_source_output_move_to(pa_source_output *o, pa_source *dest) {
                       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;
         }
diff --git a/src/pulsecore/speex/Makefile b/src/pulsecore/speex/Makefile
new file mode 100644
index 0000000..316beb7
--- /dev/null
+++ b/src/pulsecore/speex/Makefile
@@ -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

commit 9439e81de18928ea6c373c18eebf048d51801c3a
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sat Aug 25 22:26:59 2007 +0000

    make ffmpeg resampler actually work
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1717 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/resampler.c b/src/pulsecore/resampler.c
index 47a5eac..dd379b8 100644
--- a/src/pulsecore/resampler.c
+++ b/src/pulsecore/resampler.c
@@ -80,7 +80,7 @@ struct pa_resampler {
 
     struct { /* data specific to ffmpeg */
         struct AVResampleContext *state;
-        unsigned initial_i_rate, initial_o_rate;
+        pa_memchunk buf[PA_CHANNELS_MAX];
     } ffmpeg;
 };
 
@@ -848,41 +848,100 @@ static int trivial_init(pa_resampler*r) {
 /*** 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) {
-    short *src, *dst;
-    int consumed;
-    int c;
+    unsigned used_frames = 0, c;
     
     pa_assert(r);
     pa_assert(input);
     pa_assert(output);
     pa_assert(out_n_frames);
-    
-    src = (short*) ((uint8_t*) pa_memblock_acquire(input->memblock) + input->index);
-    dst = (short*) ((uint8_t*) pa_memblock_acquire(output->memblock) + output->index);
 
-    for (c = 0; c < r->o_ss.channels; c++) 
-        *out_n_frames = av_resample(r->ffmpeg.state,
-                                    dst + r->w_sz*c,
-                                    src + r->w_sz*c,
-                                    &consumed,
-                                    in_n_frames, *out_n_frames,
-                                    c >= r->o_ss.channels-1);
+    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]);
+        }
 
-    pa_assert(*out_n_frames > 0);
-    pa_assert(consumed == in_n_frames);
-    
-    pa_memblock_release(input->memblock);
-    pa_memblock_release(output->memblock);
+        /* 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;
+    
     pa_assert(r);
     
     if (r->ffmpeg.state)
         av_resample_close(r->ffmpeg.state);
+
+    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
@@ -896,5 +955,8 @@ static int ffmpeg_init(pa_resampler *r) {
     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;
 }

commit f4e2d2331afb48b304ca6b1402b43f1727343aa2
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sat Aug 25 22:27:24 2007 +0000

    include ffmpeg resampler in build
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1718 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/Makefile.am b/src/Makefile.am
index 097b083..0bdc3f7 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -559,7 +559,7 @@ libpulsedsp_la_LDFLAGS = -avoid-version
 #      Speex Resampler            #
 ###################################
 
-noinst_LTLIBRARIES = libspeex-resampler-fixed.la libspeex-resampler-float.la
+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
@@ -567,6 +567,9 @@ libspeex_resampler_fixed_la_SOURCES = pulsecore/speex/resample.c pulsecore/speex
 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
+
 ###################################
 #      Daemon core library        #
 ###################################
@@ -712,7 +715,7 @@ 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) libspeex-resampler-fixed.la libspeex-resampler-float.la
+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     #
@@ -1403,4 +1406,7 @@ update-speex:
 	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

commit f82067f6de5ecabf7c0e062b6a376651e5e829f5
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sat Aug 25 22:27:51 2007 +0000

    lower suspend timeout to 1s
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1719 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-suspend-on-idle.c b/src/modules/module-suspend-on-idle.c
index d2f9b7d..e9226ca 100644
--- a/src/modules/module-suspend-on-idle.c
+++ b/src/modules/module-suspend-on-idle.c
@@ -323,7 +323,7 @@ static pa_hook_result_t device_state_changed_hook_cb(pa_core *c, pa_object *o, s
 int pa__init(pa_module*m) {
     pa_modargs *ma = NULL;
     struct userdata *u;
-    uint32_t timeout = 5;
+    uint32_t timeout = 1;
     uint32_t idx;
     pa_sink *sink;
     pa_source *source;

commit 89fcd51b7b458d7c541a0f08cfffcc67df73acf6
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sat Aug 25 23:32:37 2007 +0000

    enable -ffast-math for gcc
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1720 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/configure.ac b/configure.ac
index d998330..718ebbf 100644
--- a/configure.ac
+++ b/configure.ac
@@ -93,7 +93,7 @@ if test "x$GCC" = "xyes" ; then
 
     # We use gnu99 instead of c99 because many have interpreted the standard
     # in a way that int64_t isn't defined on non-64 bit platforms.
-    DESIRED_FLAGS="-std=gnu99 -Wall -W -Wextra -pedantic -pipe -Wformat -Wold-style-definition -Wdeclaration-after-statement -Wfloat-equal -Wmissing-declarations -Wmissing-prototypes -Wstrict-prototypes -Wredundant-decls -Wmissing-noreturn -Wshadow -Wendif-labels -Wpointer-arith -Wcast-align -Wwrite-strings -Winline -Wno-unused-parameter"
+    DESIRED_FLAGS="-std=gnu99 -Wall -W -Wextra -pedantic -pipe -Wformat -Wold-style-definition -Wdeclaration-after-statement -Wfloat-equal -Wmissing-declarations -Wmissing-prototypes -Wstrict-prototypes -Wredundant-decls -Wmissing-noreturn -Wshadow -Wendif-labels -Wpointer-arith -Wcast-align -Wwrite-strings -Winline -Wno-unused-parameter -ffast-math"
 
     for flag in $DESIRED_FLAGS ; do
         AC_MSG_CHECKING([whether $CC accepts $flag])
diff --git a/src/pulsecore/resampler.c b/src/pulsecore/resampler.c
index dd379b8..c1af401 100644
--- a/src/pulsecore/resampler.c
+++ b/src/pulsecore/resampler.c
@@ -741,13 +741,14 @@ static void speex_update_rates(pa_resampler *r) {
 static void speex_free(pa_resampler *r) {
     pa_assert(r);
     
-    if (r->speex.state) {
-        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);
-        }
+    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);
     }
 }
 
@@ -761,20 +762,24 @@ static int speex_init(pa_resampler *r) {
     
     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;
-        r->impl_resample = speex_resample_int;
 
+        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 {
         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;
-        r->impl_resample = speex_resample_float;
 
+        pa_log_info("Choosing speex quality setting %i.", q);
+        
         if (!(r->speex.state = paspfl_resampler_init(r->o_ss.channels, r->i_ss.rate, r->o_ss.rate, q, &err)))
             return -1;
+
+        r->impl_resample = speex_resample_float;
     }
-    
 
     return 0;
 }

commit 782d5a53d9fcf37cc8a26496ce5e00965a6913a9
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sat Aug 25 23:40:16 2007 +0000

    make floating point speex resampler the default
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1721 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/resampler.c b/src/pulsecore/resampler.c
index c1af401..d98d482 100644
--- a/src/pulsecore/resampler.c
+++ b/src/pulsecore/resampler.c
@@ -160,13 +160,8 @@ pa_resampler* pa_resampler_new(
         resample_method = PA_RESAMPLER_AUTO;
     }
 
-    if (resample_method == PA_RESAMPLER_AUTO) {
-        if (a->format == PA_SAMPLE_FLOAT32LE || a->format == PA_SAMPLE_FLOAT32BE ||
-            b->format == PA_SAMPLE_FLOAT32LE || b->format == PA_SAMPLE_FLOAT32BE)
-            resample_method = PA_RESAMPLER_SPEEX_FLOAT_BASE + 0;
-        else
-            resample_method = PA_RESAMPLER_SPEEX_FIXED_BASE + 0;
-    }
+    if (resample_method == PA_RESAMPLER_AUTO)
+        resample_method = PA_RESAMPLER_SPEEX_FLOAT_BASE + 0;
 
     r = pa_xnew(pa_resampler, 1);
     r->mempool = pool;

commit 0362350fa81bbaa8c48bc864ab386fb6be72520b
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sat Aug 25 23:49:11 2007 +0000

    Add option --dump-resample-methods to list available resampler implementations
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1722 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/daemon/cmdline.c b/src/daemon/cmdline.c
index dc757c9..705115e 100644
--- a/src/daemon/cmdline.c
+++ b/src/daemon/cmdline.c
@@ -63,6 +63,7 @@ enum {
     ARG_CHECK,
     ARG_NO_CPU_LIMIT,
     ARG_DISABLE_SHM,
+    ARG_DUMP_RESAMPLE_METHODS,
     ARG_SYSTEM
 };
 
@@ -92,6 +93,7 @@ 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},
     {NULL, 0, 0, 0}
 };
 
@@ -109,6 +111,7 @@ 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"
            "  -k  --kill                            Kill a running daemon\n"
            "      --check                           Check for a running daemon\n\n"
 
@@ -131,9 +134,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"
@@ -178,6 +180,10 @@ 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 'k':
             case ARG_KILL:
                 conf->cmd = PA_CMD_KILL;
diff --git a/src/daemon/daemon-conf.h b/src/daemon/daemon-conf.h
index cb717ec..7633427 100644
--- a/src/daemon/daemon-conf.h
+++ b/src/daemon/daemon-conf.h
@@ -40,7 +40,8 @@ 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_daemon_conf_cmd_t;
 
 #ifdef HAVE_SYS_RESOURCE_H
diff --git a/src/daemon/main.c b/src/daemon/main.c
index 15d3592..7d1cf6c 100644
--- a/src/daemon/main.c
+++ b/src/daemon/main.c
@@ -419,6 +419,15 @@ int main(int argc, char *argv[]) {
             goto finish;
         }
 
+        case PA_CMD_DUMP_RESAMPLE_METHODS: {
+            int i;
+
+            for (i = 0; i < PA_RESAMPLER_MAX; i++)
+                printf("%s\n", pa_resample_method_to_string(i));
+                       
+            goto finish;
+        }
+            
         case PA_CMD_HELP :
             pa_cmdline_help(argv[0]);
             retval = 0;

commit d88514c58c2084639fd98f1070171a819b15c048
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sun Aug 26 01:10:55 2007 +0000

    drop check for gid < 500, since this isn't really a security improvement, re: #111
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1723 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/daemon/main.c b/src/daemon/main.c
index 7d1cf6c..e17e25f 100644
--- a/src/daemon/main.c
+++ b/src/daemon/main.c
@@ -355,7 +355,7 @@ int main(int argc, char *argv[]) {
 
     setlocale(LC_ALL, "");
 
-    if (suid_root && (pa_own_uid_in_group(PA_REALTIME_GROUP, &gid) <= 0 || gid >= 1000)) {
+    if (suid_root && (pa_own_uid_in_group(PA_REALTIME_GROUP, &gid) <= 0)) {
         pa_log_warn("WARNING: called SUID root, but not in group '"PA_REALTIME_GROUP"'.");
         pa_drop_caps();
         pa_drop_root();

commit ee97c4295aa1b75c2ad37a32a152fa3c15aa59db
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Aug 30 22:38:57 2007 +0000

    add new PA_SINK_CAN_SUSPEND/PA_SOURCE_CAN_SUSPEND flag
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1724 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulse/def.h b/src/pulse/def.h
index c281623..4102ba6 100644
--- a/src/pulse/def.h
+++ b/src/pulse/def.h
@@ -300,14 +300,16 @@ typedef enum pa_seek_mode {
 typedef enum pa_sink_flags {
     PA_SINK_HW_VOLUME_CTRL = 1,   /**< Supports hardware volume control */
     PA_SINK_LATENCY = 2,          /**< Supports latency querying */
-    PA_SINK_HARDWARE = 4          /**< Is a hardware sink of some kind, in contrast to "virtual"/software sinks \since 0.9.3 */
+    PA_SINK_HARDWARE = 4,         /**< Is a hardware sink of some kind, in contrast to "virtual"/software sinks \since 0.9.3 */
+    PA_SINK_CAN_SUSPEND = 8       /**< Can suspend \since 0.9.7 */
 } pa_sink_flags_t;
 
 /** Special source flags. \since 0.8  */
 typedef enum pa_source_flags {
     PA_SOURCE_HW_VOLUME_CTRL = 1,  /**< Supports hardware volume control */
     PA_SOURCE_LATENCY = 2,         /**< Supports latency querying */
-    PA_SOURCE_HARDWARE = 4         /**< Is a hardware source of some kind, in contrast to "virtual"/software source \since 0.9.3 */
+    PA_SOURCE_HARDWARE = 4,        /**< Is a hardware source of some kind, in contrast to "virtual"/software source \since 0.9.3 */
+    PA_SOURCE_CAN_SUSPEND = 8      /**< Can suspend \since 0.9.7 */
 } pa_source_flags_t;
 
 /** A generic free() like callback prototype */

commit 747b01be9430f82ffec0d4e726d64bb83ded3f77
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Aug 30 22:39:24 2007 +0000

    make passing a code pointer to pa_asyncmsgq_get() optional
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1725 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/asyncmsgq.c b/src/pulsecore/asyncmsgq.c
index cc57d3a..e3a1ba9 100644
--- a/src/pulsecore/asyncmsgq.c
+++ b/src/pulsecore/asyncmsgq.c
@@ -169,7 +169,6 @@ int pa_asyncmsgq_send(pa_asyncmsgq *a, pa_msgobject *object, int code, const voi
 
 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(code);
     pa_assert(!a->current);
 
     if (!(a->current = pa_asyncq_pop(a->asyncq, wait))) {
@@ -179,7 +178,8 @@ int pa_asyncmsgq_get(pa_asyncmsgq *a, pa_msgobject **object, int *code, void **u
 
 /*     pa_log("success"); */
 
-    *code = a->current->code;
+    if (code)
+        *code = a->current->code;
     if (userdata)
         *userdata = a->current->userdata;
     if (offset)
@@ -191,7 +191,7 @@ int pa_asyncmsgq_get(pa_asyncmsgq *a, pa_msgobject **object, int *code, void **u
     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);
+/*     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;
 }

commit 681798711620ce23ae17b08673fbe14355338f83
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Aug 30 22:39:47 2007 +0000

    add pa_timespec_reset()
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1726 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/rtclock.c b/src/pulsecore/rtclock.c
index 507b899..a4e9875 100644
--- a/src/pulsecore/rtclock.c
+++ b/src/pulsecore/rtclock.c
@@ -46,6 +46,13 @@ struct timespec *pa_timespec_store(struct timespec *a, pa_usec_t u) {
     return a;
 }
 
+struct timespec *pa_timespec_reset(struct timespec *a) {
+    pa_assert(a);
+
+    a->tv_sec = a->tv_nsec = 0;
+    return a;
+}
+
 pa_usec_t pa_timespec_load(struct timespec *ts) {
     pa_assert(ts);
     
diff --git a/src/pulsecore/rtclock.h b/src/pulsecore/rtclock.h
index 145533c..cfc968f 100644
--- a/src/pulsecore/rtclock.h
+++ b/src/pulsecore/rtclock.h
@@ -37,6 +37,7 @@ pa_usec_t pa_rtclock_age(const struct timespec *tv);
 int pa_rtclock_hrtimer(void);
 
 struct timespec *pa_timespec_store(struct timespec *a, pa_usec_t u);
+struct timespec *pa_timespec_reset(struct timespec *a);
 pa_usec_t pa_timespec_load(struct timespec *tv);
 struct timespec *pa_timespec_add(struct timespec *tv, pa_usec_t t);
 pa_usec_t pa_timespec_diff(const struct timespec *a, const struct timespec *b);

commit bfe69cebf334a3df337ebab32b15a8d82654fb5d
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Aug 30 22:40:11 2007 +0000

    add an assert()
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1727 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/fdsem.c b/src/pulsecore/fdsem.c
index 20d262e..5a358e2 100644
--- a/src/pulsecore/fdsem.c
+++ b/src/pulsecore/fdsem.c
@@ -137,7 +137,7 @@ void pa_fdsem_wait(pa_fdsem *f) {
         pa_atomic_sub(&f->in_pipe, r);
     }
 
-    pa_atomic_dec(&f->waiting);
+    pa_assert_se(pa_atomic_dec(&f->waiting) >= 1);
 }
 
 int pa_fdsem_try(pa_fdsem *f) {

commit c2e4328c53ee32f0a49c259371945c1b19539794
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Aug 30 22:41:33 2007 +0000

    fix pa_memchunk_make_writable(), make memchunk functions return the memchunk they modify
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1728 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/memchunk.c b/src/pulsecore/memchunk.c
index f00cc9e..20ddb11 100644
--- a/src/pulsecore/memchunk.c
+++ b/src/pulsecore/memchunk.c
@@ -34,7 +34,7 @@
 
 #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;
@@ -42,9 +42,10 @@ void pa_memchunk_make_writable(pa_memchunk *c, size_t min) {
     assert(c);
     assert(c->memblock);
 
-    if (pa_memblock_is_read_only(c->memblock) &&
+    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;
+        return c;
 
     l = c->length;
     if (l < min)
@@ -59,11 +60,15 @@ void pa_memchunk_make_writable(pa_memchunk *c, size_t min) {
     pa_memblock_unref(c->memblock);
     c->memblock = n;
     c->index = 0;
+
+    return c;
 }
 
-void pa_memchunk_reset(pa_memchunk *c) {
+pa_memchunk* pa_memchunk_reset(pa_memchunk *c) {
     assert(c);
 
     c->memblock = NULL;
     c->length = c->index = 0;
+
+    return c;
 }
diff --git a/src/pulsecore/memchunk.h b/src/pulsecore/memchunk.h
index 0b982b6..10cab2b 100644
--- a/src/pulsecore/memchunk.h
+++ b/src/pulsecore/memchunk.h
@@ -38,10 +38,10 @@ 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);
+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);
 
 #endif

commit 687f1f15fc3fcd99ce79cc402c48ec6a469f0333
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Aug 30 22:42:02 2007 +0000

    add new function pa_memblock_ref_is_one()
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1729 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/memblock.c b/src/pulsecore/memblock.c
index 914e429..3e2b006 100644
--- a/src/pulsecore/memblock.c
+++ b/src/pulsecore/memblock.c
@@ -385,6 +385,18 @@ int pa_memblock_is_read_only(pa_memblock *b) {
 }
 
 /* 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);
diff --git a/src/pulsecore/memblock.h b/src/pulsecore/memblock.h
index 6f8bbef..7fa6627 100644
--- a/src/pulsecore/memblock.h
+++ b/src/pulsecore/memblock.h
@@ -107,6 +107,7 @@ 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);

commit 821eb8e29589baed2564e52fa956d34e6f2ce4d3
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Aug 30 22:42:47 2007 +0000

    move queue processing code into pa_thread_mq
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1730 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/thread-mq.c b/src/pulsecore/thread-mq.c
index 513409d..3c466ce 100644
--- a/src/pulsecore/thread-mq.c
+++ b/src/pulsecore/thread-mq.c
@@ -117,3 +117,27 @@ pa_thread_mq *pa_thread_mq_get(void) {
     return pa_tls_get(tls);
 }
 
+int pa_thread_mq_process(pa_thread_mq *q) {
+    pa_msgobject *object;
+    int code;
+    void *data;
+    pa_memchunk chunk;
+    int64_t offset;
+
+    pa_assert(q);
+
+    if (pa_asyncmsgq_get(q->inq, &object, &code, &data, &offset, &chunk, 0) == 0) {
+        int ret;
+        
+        if (!object && code == PA_MESSAGE_SHUTDOWN) {
+            pa_asyncmsgq_done(q->inq, 0);
+            return -1;
+        }
+
+        ret = pa_asyncmsgq_dispatch(object, code, data, offset, &chunk);
+        pa_asyncmsgq_done(q->inq, ret);
+        return 1;
+    } 
+
+    return 0;
+}
diff --git a/src/pulsecore/thread-mq.h b/src/pulsecore/thread-mq.h
index 13b6e01..2b1fd68 100644
--- a/src/pulsecore/thread-mq.h
+++ b/src/pulsecore/thread-mq.h
@@ -43,6 +43,9 @@ 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);
 
+/* Dispatched queued events on the thread side. */
+int pa_thread_mq_process(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);
 

commit ca72adf100fc88de0fc418955310e3c5a87a7ca3
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Aug 30 22:43:35 2007 +0000

    modernize and make use of a static flist for allocating idxset entries
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1731 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/idxset.c b/src/pulsecore/idxset.c
index e683ead..773d7d3 100644
--- a/src/pulsecore/idxset.c
+++ b/src/pulsecore/idxset.c
@@ -27,33 +27,35 @@
 #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;
@@ -83,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;
@@ -96,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);
@@ -112,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;
@@ -125,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;
@@ -136,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];
@@ -148,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;
 
@@ -160,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;
@@ -176,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;
@@ -191,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;
@@ -216,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;
@@ -230,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;
+    
+    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)))
         return NULL;
 
@@ -246,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 */
@@ -275,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;
@@ -300,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;
 
@@ -321,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;
@@ -338,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;
@@ -349,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;
@@ -366,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);
 
@@ -389,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;
 }
 

commit b552541dd1f65646a5963e7a8c8ec43e4ea416c8
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Aug 30 22:44:19 2007 +0000

    reorder initialization of pa_core variables
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1732 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/daemon/main.c b/src/daemon/main.c
index e17e25f..7bdf65c 100644
--- a/src/daemon/main.c
+++ b/src/daemon/main.c
@@ -604,6 +604,11 @@ int main(int argc, char *argv[]) {
     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);
@@ -634,7 +639,7 @@ int main(int argc, char *argv[]) {
         r = pa_cpu_limit_init(pa_mainloop_get_api(mainloop));
         assert(r == 0);
     }
-
+    
     buf = pa_strbuf_new();
     if (conf->default_script_file)
         r = pa_cli_command_execute_file(c, conf->default_script_file, buf, &conf->fail);
@@ -664,12 +669,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);

commit 4d623f0d4442148f20f2ffdc85cf95e54ef83721
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Aug 30 22:57:53 2007 +0000

    Lots of assorted minor cleanups and fixes:
    * s/disconnect/unlink/ at many places where it makes sense
    * make "start_corked" a normal pa_sink_input/pa_source_output flag instead of a seperate boolean variable
    * add generic process() function to pa_sink_input/pa_source_output vtable that can be used by streams to do some arbitrary processing in each rt loop iteration even the sink/source is suspended
    * add detach()/attach() functions to pa_sink_input/pa_source_output vtable that are called when ever the rtpoll object of the event thread changes
    * add suspend() functions to pa_sink_input/pa_source_output vtable which are called whenever the sink/source they are attached to suspends/resumes
    * add PA_SINK_INIT/PA_SOURCE_INIT/PA_SINK_INPUT_INIT/PA_SINK_OUTPUT_INIT states to state machines which is active between _new() and _put()
    * seperate _put() from _new() for pa_sink/pa_source
    * add PA_SOURCE_OUTPUT_DONT_MOVE/PA_SINK_INPUT_DONT_MOVE flags
    * make the pa_rtpoll object a property of pa_sink/pa_source to allow streams attached to them make use of it
    * fix skipping over move_silence
    * update module-pipe-source to make use of pa_rtpoll
    * add pa_sink_skip() as optimization in cases where the actualy data returned by pa_sink_render() doesn't matter
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1733 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-alsa-sink.c b/src/modules/module-alsa-sink.c
index a805845..24765a0 100644
--- a/src/modules/module-alsa-sink.c
+++ b/src/modules/module-alsa-sink.c
@@ -347,7 +347,7 @@ static int suspend(struct userdata *u) {
         u->alsa_rtpoll_item = NULL;
     }
     
-    pa_log_debug("Device suspended...");
+    pa_log_info("Device suspended...");
     
     return 0;
 }
@@ -361,7 +361,7 @@ static int unsuspend(struct userdata *u) {
     pa_assert(u);
     pa_assert(!u->pcm_handle);
 
-    pa_log_debug("Trying resume...");
+    pa_log_info("Trying resume...");
 
     snd_config_update_free_global();
     if ((err = snd_pcm_open(&u->pcm_handle, u->device_name, SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK)) < 0) {
@@ -406,7 +406,7 @@ static int unsuspend(struct userdata *u) {
     
     u->first = 1;
                 
-    pa_log_debug("Resumed successfully...");
+    pa_log_info("Resumed successfully...");
 
     return 0;
 
@@ -457,7 +457,8 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
                     
                     break;
 
-                case PA_SINK_DISCONNECTED:
+                case PA_SINK_UNLINKED:
+                case PA_SINK_INIT:
                     ;
             }
             
@@ -607,13 +608,7 @@ static void thread_func(void *userdata) {
         goto fail;
 
     for (;;) {
-        pa_msgobject *object;
-        int code;
-        void *data;
-        pa_memchunk chunk;
-        int64_t offset;
-
-/*         pa_log("loop");      */
+        int ret;
         
         /* Render some data and write it to the dsp */
         if (PA_SINK_OPENED(u->sink->thread_info.state)) {
@@ -635,28 +630,25 @@ static void thread_func(void *userdata) {
             }
         }
 
-/*         pa_log("loop2"); */
+        /* Now give the sink inputs some to time to process their data */
+        if ((ret = pa_sink_process_inputs(u->sink)) < 0)
+            goto fail;
+        if (ret > 0)
+            continue;
 
         /* Check whether there is a message for us to process */
-        if (pa_asyncmsgq_get(u->thread_mq.inq, &object, &code, &data, &offset, &chunk, 0) == 0) {
-            int ret;
-
-            if (!object && code == PA_MESSAGE_SHUTDOWN) {
-                pa_asyncmsgq_done(u->thread_mq.inq, 0);
-                goto finish;
-            }
-
-            ret = pa_asyncmsgq_dispatch(object, code, data, offset, &chunk);
-            pa_asyncmsgq_done(u->thread_mq.inq, ret);
+        if ((ret = pa_thread_mq_process(&u->thread_mq) < 0))
+            goto finish;
+        if (ret > 0)
             continue;
-        } 
-
+        
         /* Hmm, nothing to do. Let's sleep */
         if (pa_rtpoll_run(u->rtpoll) < 0) {
             pa_log("poll() failed: %s", pa_cstrerror(errno));
             goto fail;
         }
 
+        /* Tell ALSA about this and process its response */
         if (PA_SINK_OPENED(u->sink->thread_info.state)) {
             struct pollfd *pollfd;
             unsigned short revents = 0;
@@ -680,9 +672,7 @@ static void thread_func(void *userdata) {
 
                 goto fail;
             }
-/*             pa_log("got alsa event"); */
         }
-        
     }
 
 fail:
@@ -828,6 +818,7 @@ int pa__init(pa_module*m) {
 
     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,
@@ -835,7 +826,7 @@ int pa__init(pa_module*m) {
                                     use_mmap ? " via DMA" : ""));
     pa_xfree(t);
     
-    u->sink->is_hardware = 1;
+    u->sink->flags = PA_SINK_HARDWARE|PA_SINK_CAN_SUSPEND|PA_SINK_HW_VOLUME_CTRL|PA_SINK_LATENCY;
 
     u->frame_size = frame_size;
     u->fragment_size = frag_size = period_size * frame_size;
@@ -894,6 +885,8 @@ int pa__init(pa_module*m) {
     if (u->sink->get_mute)
         u->sink->get_mute(u->sink);
 
+    pa_sink_put(u->sink);
+    
     pa_modargs_free(ma);
     
     return 0;
@@ -917,7 +910,7 @@ void pa__done(pa_module*m) {
         return;
 
     if (u->sink)
-        pa_sink_disconnect(u->sink);
+        pa_sink_unlink(u->sink);
 
     if (u->thread) {
         pa_asyncmsgq_send(u->thread_mq.inq, NULL, PA_MESSAGE_SHUTDOWN, NULL, 0, NULL);
diff --git a/src/modules/module-alsa-source.c b/src/modules/module-alsa-source.c
index 6ea99ec..0d76cab 100644
--- a/src/modules/module-alsa-source.c
+++ b/src/modules/module-alsa-source.c
@@ -328,7 +328,7 @@ static int suspend(struct userdata *u) {
         u->alsa_rtpoll_item = NULL;
     }
     
-    pa_log_debug("Device suspended...");
+    pa_log_info("Device suspended...");
     
     return 0;
 }
@@ -342,7 +342,7 @@ static int unsuspend(struct userdata *u) {
     pa_assert(u);
     pa_assert(!u->pcm_handle);
 
-    pa_log_debug("Trying resume...");
+    pa_log_info("Trying resume...");
 
     snd_config_update_free_global();
     if ((err = snd_pcm_open(&u->pcm_handle, u->device_name, SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK)) < 0) {
@@ -387,7 +387,7 @@ static int unsuspend(struct userdata *u) {
     
     /* FIXME: We need to reload the volume somehow */
                 
-    pa_log_debug("Resumed successfully...");
+    pa_log_info("Resumed successfully...");
 
     return 0;
 
@@ -438,7 +438,8 @@ static int source_process_msg(pa_msgobject *o, int code, void *data, int64_t off
                     
                     break;
 
-                case PA_SOURCE_DISCONNECTED:
+                case PA_SOURCE_UNLINKED:
+                case PA_SOURCE_INIT:
                     ;
             }
             
@@ -590,15 +591,9 @@ static void thread_func(void *userdata) {
     snd_pcm_start(u->pcm_handle);
     
     for (;;) {
-        pa_msgobject *object;
-        int code;
-        void *data;
-        int64_t offset;
-        pa_memchunk chunk;
+        int ret;
 
-/*         pa_log("loop");     */
-        
-        /* Render some data and write it to the dsp */
+        /* Read some data and pass it to the sources */
         if (PA_SOURCE_OPENED(u->source->thread_info.state)) {
             
             if (u->use_mmap) {
@@ -611,29 +606,25 @@ static void thread_func(void *userdata) {
             }
         }
 
-/*         pa_log("loop2"); */
+        /* Now give the source outputs some to time to process their data */
+        if ((ret = pa_source_process_outputs(u->source)) < 0)
+            goto fail;
+        if (ret > 0)
+            continue;
         
         /* Check whether there is a message for us to process */
-        if (pa_asyncmsgq_get(u->thread_mq.inq, &object, &code, &data, &offset, &chunk, 0) == 0) {
-            int ret;
-
-/*             pa_log("processing msg"); */
-
-            if (!object && code == PA_MESSAGE_SHUTDOWN) {
-                pa_asyncmsgq_done(u->thread_mq.inq, 0);
-                goto finish;
-            }
-
-            ret = pa_asyncmsgq_dispatch(object, code, data, offset, &chunk);
-            pa_asyncmsgq_done(u->thread_mq.inq, ret);
+        if ((ret = pa_thread_mq_process(&u->thread_mq) < 0))
+            goto finish;
+        if (ret > 0)
             continue;
-        } 
 
+        /* Hmm, nothing to do. Let's sleep */
         if (pa_rtpoll_run(u->rtpoll) < 0) {
             pa_log("poll() failed: %s", pa_cstrerror(errno));
             goto fail;
         }
 
+        /* Tell ALSA about this and process its response */
         if (PA_SOURCE_OPENED(u->source->thread_info.state)) {
             struct pollfd *pollfd;
             unsigned short revents = 0;
@@ -657,7 +648,6 @@ static void thread_func(void *userdata) {
 
                 goto fail;
             }
-/*             pa_log("got alsa event"); */
         }
     }
 
@@ -802,6 +792,7 @@ int pa__init(pa_module*m) {
 
     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,
@@ -809,7 +800,7 @@ int pa__init(pa_module*m) {
                                       use_mmap ? " via DMA" : ""));
     pa_xfree(t);
 
-    u->source->is_hardware = 1;
+    u->source->flags = PA_SOURCE_HARDWARE|PA_SOURCE_CAN_SUSPEND|PA_SOURCE_LATENCY|PA_SOURCE_HW_VOLUME_CTRL;
 
     u->frame_size = frame_size;
     u->fragment_size = frag_size = period_size * frame_size;
@@ -863,6 +854,8 @@ int pa__init(pa_module*m) {
     if (u->source->get_mute)
         u->source->get_mute(u->source);
 
+    pa_source_put(u->source);    
+    
     pa_modargs_free(ma);
     
     return 0;
@@ -886,7 +879,7 @@ void pa__done(pa_module*m) {
         return;
 
     if (u->source)
-        pa_source_disconnect(u->source);
+        pa_source_unlink(u->source);
 
     if (u->thread) {
         pa_asyncmsgq_send(u->thread_mq.inq, NULL, PA_MESSAGE_SHUTDOWN, NULL, 0, NULL);
diff --git a/src/modules/module-null-sink.c b/src/modules/module-null-sink.c
index 3b51237..78d99ce 100644
--- a/src/modules/module-null-sink.c
+++ b/src/modules/module-null-sink.c
@@ -128,11 +128,7 @@ static void thread_func(void *userdata) {
     pa_rtclock_get(&u->timestamp);
 
     for (;;) {
-        pa_msgobject *object;
-        int code;
-        void *data;
-        pa_memchunk chunk;
-        int64_t offset;
+        int ret;
 
         /* Render some data and drop it immediately */
         if (u->sink->thread_info.state == PA_SINK_RUNNING) {
@@ -141,30 +137,25 @@ static void thread_func(void *userdata) {
             pa_rtclock_get(&now);
 
             if (pa_timespec_cmp(&u->timestamp, &now) <= 0) {
-
-                pa_sink_render(u->sink, u->block_size, &chunk);
-                pa_memblock_unref(chunk.memblock);
-
-                pa_timespec_add(&u->timestamp, pa_bytes_to_usec(chunk.length, &u->sink->sample_spec));
+                pa_sink_skip(u->sink, u->block_size);
+                pa_timespec_add(&u->timestamp, pa_bytes_to_usec(u->block_size, &u->sink->sample_spec));
             }
 
             pa_rtpoll_set_timer_absolute(u->rtpoll, &u->timestamp);
         } else
             pa_rtpoll_set_timer_disabled(u->rtpoll);
 
-        /* Check whether there is a message for us to process */
-        if (pa_asyncmsgq_get(u->thread_mq.inq, &object, &code, &data, &offset, &chunk, 0) == 0) {
-            int ret;
-
-            if (!object && code == PA_MESSAGE_SHUTDOWN) {
-                pa_asyncmsgq_done(u->thread_mq.inq, 0);
-                goto finish;
-            }
+        /* Now give the sink inputs some to time to process their data */
+        if ((ret = pa_sink_process_inputs(u->sink)) < 0)
+            goto fail;
+        if (ret > 0)
+            continue;
 
-            ret = pa_asyncmsgq_dispatch(object, code, data, offset, &chunk);
-            pa_asyncmsgq_done(u->thread_mq.inq, ret);
+        /* Check whether there is a message for us to process */
+        if ((ret = pa_thread_mq_process(&u->thread_mq) < 0))
+            goto finish;
+        if (ret > 0)
             continue;
-        }
 
         /* Hmm, nothing to do. Let's sleep */
         if (pa_rtpoll_run(u->rtpoll) < 0) {
@@ -217,9 +208,11 @@ int pa__init(pa_module*m) {
 
     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);
     pa_sink_set_description(u->sink, pa_modargs_get_value(ma, "description", "NULL sink"));
 
     u->block_size = pa_bytes_per_second(&ss) / 20; /* 50 ms */
@@ -231,6 +224,8 @@ int pa__init(pa_module*m) {
         goto fail;
     }
 
+    pa_sink_put(u->sink);
+    
     pa_modargs_free(ma);
 
     return 0;
@@ -253,7 +248,7 @@ void pa__done(pa_module*m) {
         return;
 
     if (u->sink)
-        pa_sink_disconnect(u->sink);
+        pa_sink_unlink(u->sink);
 
     if (u->thread) {
         pa_asyncmsgq_send(u->thread_mq.inq, NULL, PA_MESSAGE_SHUTDOWN, NULL, 0, NULL);
diff --git a/src/modules/module-oss.c b/src/modules/module-oss.c
index 85fdd9c..bbb1e0d 100644
--- a/src/modules/module-oss.c
+++ b/src/modules/module-oss.c
@@ -443,7 +443,7 @@ static int suspend(struct userdata *u) {
     pa_assert(u);
     pa_assert(u->fd >= 0);
 
-    pa_log_debug("Suspending...");
+    pa_log_info("Suspending...");
     
     if (u->out_mmap_memblocks) {
         unsigned i;
@@ -483,7 +483,7 @@ static int suspend(struct userdata *u) {
         u->rtpoll_item = NULL;
     }
     
-    pa_log_debug("Device suspended...");
+    pa_log_info("Device suspended...");
     
     return 0;
 }
@@ -501,7 +501,7 @@ static int unsuspend(struct userdata *u) {
 
     m = u->mode;
 
-    pa_log_debug("Trying resume...");
+    pa_log_info("Trying resume...");
 
     if ((u->fd = pa_oss_open(u->device_name, &m, NULL)) < 0) {
         pa_log_warn("Resume failed, device busy (%s)", pa_cstrerror(errno));
@@ -582,7 +582,7 @@ static int unsuspend(struct userdata *u) {
     pollfd->events = 0;
     pollfd->revents = 0;
 
-    pa_log_debug("Resumed successfully...");
+    pa_log_info("Resumed successfully...");
 
     return 0;
 
@@ -651,7 +651,8 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
 
                     break;
 
-                case PA_SINK_DISCONNECTED:
+                case PA_SINK_UNLINKED:
+                case PA_SINK_INIT:
                     ;
             }
             
@@ -748,7 +749,8 @@ static int source_process_msg(pa_msgobject *o, int code, void *data, int64_t off
                     }
                     break;
 
-                case PA_SOURCE_DISCONNECTED:
+                case PA_SOURCE_UNLINKED:
+                case PA_SOURCE_INIT:
                     ;
 
             }
@@ -807,20 +809,15 @@ static void thread_func(void *userdata) {
     trigger(u, 0);
     
     for (;;) {
-        pa_msgobject *object;
-        int code;
-        void *data;
-        pa_memchunk chunk;
-        int64_t offset;
+        int ret;
 
 /*        pa_log("loop");    */
         
         /* Render some data and write it to the dsp */
 
-        if (u->sink && u->sink->thread_info.state != PA_SINK_DISCONNECTED && u->fd >= 0 && (revents & POLLOUT)) {
+        if (u->sink && u->sink->thread_info.state != PA_SINK_UNLINKED && u->fd >= 0 && (revents & POLLOUT)) {
 
             if (u->use_mmap) {
-                int ret;
 
                 if ((ret = mmap_write(u)) < 0)
                     goto fail;
@@ -908,10 +905,9 @@ static void thread_func(void *userdata) {
 
         /* Try to read some data and pass it on to the source driver */
 
-        if (u->source && u->source->thread_info.state != PA_SOURCE_DISCONNECTED && u->fd >= 0 && ((revents & POLLIN))) {
+        if (u->source && u->source->thread_info.state != PA_SOURCE_UNLINKED && u->fd >= 0 && ((revents & POLLIN))) {
 
             if (u->use_mmap) {
-                int ret;
 
                 if ((ret = mmap_read(u)) < 0)
                     goto fail;
@@ -995,21 +991,23 @@ static void thread_func(void *userdata) {
 
 /*         pa_log("loop2"); */
 
-        /* Check whether there is a message for us to process */
-        if (pa_asyncmsgq_get(u->thread_mq.inq, &object, &code, &data, &offset, &chunk, 0) == 0) {
-            int ret;
-
-/*             pa_log("processing msg"); */
-
-            if (!object && code == PA_MESSAGE_SHUTDOWN) {
-                pa_asyncmsgq_done(u->thread_mq.inq, 0);
-                goto finish;
-            }
+        /* Now give the sink inputs some to time to process their data */
+        if ((ret = pa_sink_process_inputs(u->sink)) < 0)
+            goto fail;
+        if (ret > 0)
+            continue;
 
-            ret = pa_asyncmsgq_dispatch(object, code, data, offset, &chunk);
-            pa_asyncmsgq_done(u->thread_mq.inq, ret);
+        /* Now give the source outputs some to time to process their data */
+        if ((ret = pa_source_process_outputs(u->source)) < 0)
+            goto fail;
+        if (ret > 0)
+            continue;
+        
+        /* Check whether there is a message for us to process */
+        if ((ret = pa_thread_mq_process(&u->thread_mq) < 0))
+            goto finish;
+        if (ret > 0)
             continue;
-        } 
 
         if (u->fd >= 0) {
             struct pollfd *pollfd;
@@ -1019,7 +1017,6 @@ static void thread_func(void *userdata) {
                 ((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 (pa_rtpoll_run(u->rtpoll) < 0) {
@@ -1212,6 +1209,7 @@ int pa__init(pa_module*m) {
 
         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,
@@ -1220,7 +1218,7 @@ int pa__init(pa_module*m) {
                                           hwdesc[0] ? ")" : "",
                                           use_mmap ? " via DMA" : ""));
         pa_xfree(t);
-        u->source->is_hardware = 1;
+        u->source->flags = PA_SOURCE_HARDWARE|PA_SOURCE_CAN_SUSPEND|PA_SOURCE_LATENCY|PA_SOURCE_HW_VOLUME_CTRL;
         u->source->refresh_volume = 1;
 
         if (use_mmap)
@@ -1266,6 +1264,7 @@ int pa__init(pa_module*m) {
         
         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,
@@ -1274,7 +1273,7 @@ int pa__init(pa_module*m) {
                                         hwdesc[0] ? ")" : "",
                                         use_mmap ? " via DMA" : ""));
         pa_xfree(t);
-        u->sink->is_hardware = 1;
+        u->sink->flags = PA_SINK_HARDWARE|PA_SINK_CAN_SUSPEND|PA_SINK_LATENCY|PA_SINK_HW_VOLUME_CTRL;
         u->sink->refresh_volume = 1;
 
         if (use_mmap)
@@ -1298,6 +1297,11 @@ go_on:
     if (u->sink)
         pa_asyncmsgq_post(u->thread_mq.inq, PA_MSGOBJECT(u->sink), PA_SINK_MESSAGE_GET_VOLUME, &u->sink->volume, 0, NULL, NULL);
 
+    if (u->sink)
+        pa_sink_put(u->sink);
+    if (u->source)
+        pa_source_put(u->source);
+    
     pa_modargs_free(ma);
 
     return 0;
@@ -1324,10 +1328,10 @@ void pa__done(pa_module*m) {
         return;
 
     if (u->sink)
-        pa_sink_disconnect(u->sink);
+        pa_sink_unlink(u->sink);
 
     if (u->source)
-        pa_source_disconnect(u->source);
+        pa_source_unlink(u->source);
 
     if (u->thread) {
         pa_asyncmsgq_send(u->thread_mq.inq, NULL, PA_MESSAGE_SHUTDOWN, NULL, 0, NULL);
diff --git a/src/modules/module-pipe-sink.c b/src/modules/module-pipe-sink.c
index a1101ab..d5ef194 100644
--- a/src/modules/module-pipe-sink.c
+++ b/src/modules/module-pipe-sink.c
@@ -124,17 +124,12 @@ static void thread_func(void *userdata) {
     pa_rtpoll_install(u->rtpoll);
 
     for (;;) {
-        pa_msgobject *object;
-        int code;
-        void *data;
-        pa_memchunk chunk;
-        int64_t offset;
+        int ret;
         struct pollfd *pollfd;
 
-        /* Render some data and write it to the fifo */
-
         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;
@@ -173,19 +168,17 @@ static void thread_func(void *userdata) {
             }
         }
 
-        /* Check whether there is a message for us to process */
-        if (pa_asyncmsgq_get(u->thread_mq.inq, &object, &code, &data, &offset, &chunk, 0) == 0) {
-            int ret;
-
-            if (!object && code == PA_MESSAGE_SHUTDOWN) {
-                pa_asyncmsgq_done(u->thread_mq.inq, 0);
-                goto finish;
-            }
+        /* Now give the sink inputs some to time to process their data */
+        if ((ret = pa_sink_process_inputs(u->sink)) < 0)
+            goto fail;
+        if (ret > 0)
+            continue;
 
-            ret = pa_asyncmsgq_dispatch(object, code, data, offset, &chunk);
-            pa_asyncmsgq_done(u->thread_mq.inq, ret);
+        /* Check whether there is a message for us to process */
+        if ((ret = pa_thread_mq_process(&u->thread_mq) < 0))
+            goto finish;
+        if (ret > 0)
             continue;
-        }
         
         /* Hmm, nothing to do. Let's sleep */
         pollfd->events = u->sink->thread_info.state == PA_SINK_RUNNING ? POLLOUT : 0;
@@ -271,9 +264,11 @@ int pa__init(pa_module*m) {
 
     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);
     pa_sink_set_description(u->sink, t = pa_sprintf_malloc("Unix FIFO sink '%s'", u->filename));
     pa_xfree(t);
 
@@ -281,12 +276,14 @@ int pa__init(pa_module*m) {
     pollfd = pa_rtpoll_item_get_pollfd(u->rtpoll_item, NULL);
     pollfd->fd = u->fd;
     pollfd->events = pollfd->revents = 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);
 
     return 0;
@@ -309,7 +306,7 @@ void pa__done(pa_module*m) {
         return;
 
     if (u->sink)
-        pa_sink_disconnect(u->sink);
+        pa_sink_unlink(u->sink);
 
     if (u->thread) {
         pa_asyncmsgq_send(u->thread_mq.inq, NULL, PA_MESSAGE_SHUTDOWN, NULL, 0, NULL);
diff --git a/src/modules/module-pipe-source.c b/src/modules/module-pipe-source.c
index 2209d1e..6dc9464 100644
--- a/src/modules/module-pipe-source.c
+++ b/src/modules/module-pipe-source.c
@@ -45,6 +45,7 @@
 #include <pulsecore/log.h>
 #include <pulsecore/thread.h>
 #include <pulsecore/thread-mq.h>
+#include <pulsecore/rtpoll.h>
 
 #include "module-pipe-source-symdef.h"
 
@@ -66,13 +67,17 @@ 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_memchunk memchunk;
+
+    pa_rtpoll_item *rtpoll_item;
 };
 
 static const char* const valid_modargs[] = {
@@ -86,14 +91,7 @@ static const char* const valid_modargs[] = {
 };
 
 static void thread_func(void *userdata) {
-    enum {
-        POLLFD_ASYNCQ,
-        POLLFD_FIFO,
-        POLLFD_MAX,
-    };
-    
     struct userdata *u = userdata;
-    struct pollfd pollfd[POLLFD_MAX];
     int read_type = 0;
 
     pa_assert(u);
@@ -101,40 +99,18 @@ static void thread_func(void *userdata) {
     pa_log_debug("Thread starting up");
 
     pa_thread_mq_install(&u->thread_mq);
-
-    memset(&pollfd, 0, sizeof(pollfd));
+    pa_rtpoll_install(u->rtpoll);
     
-    pollfd[POLLFD_ASYNCQ].fd = pa_asyncmsgq_get_fd(u->thread_mq.inq);
-    pollfd[POLLFD_ASYNCQ].events = POLLIN;
-    pollfd[POLLFD_FIFO].fd = u->fd;
-
     for (;;) {
-        pa_msgobject *object;
-        int code;
-        void *data;
-        pa_memchunk chunk;
-        int r;
-        int64_t offset;
-
-        /* Check whether there is a message for us to process */
-        if (pa_asyncmsgq_get(u->thread_mq.inq, &object, &code, &data, &offset, &chunk, 0) == 0) {
-            int ret;
-
-            if (!object && code == PA_MESSAGE_SHUTDOWN) {
-                pa_asyncmsgq_done(u->thread_mq.inq, 0);
-                goto finish;
-            }
-
-            ret = pa_asyncmsgq_dispatch(object, code, data, offset, &chunk);
-            pa_asyncmsgq_done(u->thread_mq.inq, ret);
-            continue;
-        }
+        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[POLLFD_FIFO].revents) {
-            void *p;
+        if (u->source->thread_info.state == PA_SOURCE_RUNNING && pollfd->revents) {
             ssize_t l;
+            void *p;
 
             if (!u->memchunk.memblock) {
                 u->memchunk.memblock = pa_memblock_new(u->core->mempool, PIPE_BUF);
@@ -169,38 +145,35 @@ static void thread_func(void *userdata) {
                     pa_memchunk_reset(&u->memchunk);
                 }
 
-                pollfd[POLLFD_FIFO].revents = 0;
-                continue;
+                pollfd->revents = 0;
             }
         }
 
-        pollfd[POLLFD_FIFO].events = u->source->thread_info.state == PA_SOURCE_RUNNING ? POLLIN : 0;
-
-        /* Hmm, nothing to do. Let's sleep */
-
-        if (pa_asyncmsgq_before_poll(u->thread_mq.inq) < 0)
+        /* Now give the source outputs some to time to process their data */
+        if ((ret = pa_source_process_outputs(u->source)) < 0)
+            goto fail;
+        if (ret > 0)
             continue;
 
-/*         pa_log("polling for %i", pollfd[POLLFD_FIFO].events); */
-        r = poll(pollfd, POLLFD_MAX, -1);
-/*         pa_log("polling got %i (r=%i) %i", r > 0 ? pollfd[POLLFD_FIFO].revents : 0, r, r > 0 ? pollfd[POLLFD_ASYNCQ].revents: 0); */
-
-        pa_asyncmsgq_after_poll(u->thread_mq.inq);
+        /* Check whether there is a message for us to process */
+        if ((ret = pa_thread_mq_process(&u->thread_mq) < 0))
+            goto finish;
+        if (ret > 0)
+            continue;
 
-        if (r < 0) {
-            if (errno == EINTR)
-                continue;
+        /* Hmm, nothing to do. Let's sleep */
+        pollfd->events = u->source->thread_info.state == PA_SOURCE_RUNNING ? POLLIN : 0;
 
+        if (pa_rtpoll_run(u->rtpoll) < 0) {
             pa_log("poll() failed: %s", pa_cstrerror(errno));
             goto fail;
         }
 
-        if (pollfd[POLLFD_FIFO].revents & ~POLLIN) {
+        pollfd = pa_rtpoll_item_get_pollfd(u->rtpoll_item, NULL);
+        if (pollfd->revents & ~POLLIN) {
             pa_log("FIFO shutdown.");
             goto fail;
         }
-
-        pa_assert((pollfd[POLLFD_ASYNCQ].revents & ~POLLIN) == 0);
     }
 
 fail:
@@ -220,6 +193,7 @@ int pa__init(pa_module*m) {
     pa_channel_map map;
     pa_modargs *ma;
     char *t;
+    struct pollfd *pollfd;
 
     pa_assert(m);
 
@@ -240,6 +214,8 @@ int pa__init(pa_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, u->thread_mq.inq);
 
     u->filename = pa_xstrdup(pa_modargs_get_value(ma, "file", DEFAULT_FILE_NAME));
     
@@ -268,17 +244,26 @@ int pa__init(pa_module*m) {
     }
 
     u->source->userdata = u;
+    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->rtpoll_item = pa_rtpoll_item_new(u->rtpoll, 1);
+    pollfd = pa_rtpoll_item_get_pollfd(u->rtpoll_item, NULL);
+    pollfd->fd = u->fd;
+    pollfd->events = pollfd->revents = 0;
+    
     if (!(u->thread = pa_thread_new(thread_func, u))) {
         pa_log("Failed to create thread.");
         goto fail;
     }
 
+    pa_source_put(u->source);
+
     pa_modargs_free(ma);
 
     return 0;
@@ -301,7 +286,7 @@ void pa__done(pa_module*m) {
         return;
 
     if (u->source)
-        pa_source_disconnect(u->source);
+        pa_source_unlink(u->source);
 
     if (u->thread) {
         pa_asyncmsgq_send(u->thread_mq.inq, NULL, PA_MESSAGE_SHUTDOWN, NULL, 0, NULL);
@@ -316,6 +301,12 @@ void pa__done(pa_module*m) {
     if (u->memchunk.memblock)
         pa_memblock_unref(u->memchunk.memblock);
 
+    if (u->rtpoll_item)
+        pa_rtpoll_item_free(u->rtpoll_item);
+    
+    if (u->rtpoll)
+        pa_rtpoll_free(u->rtpoll);
+    
     if (u->filename) {
         unlink(u->filename);
         pa_xfree(u->filename);
diff --git a/src/modules/module-rescue-streams.c b/src/modules/module-rescue-streams.c
index e0eed03..24077dc 100644
--- a/src/modules/module-rescue-streams.c
+++ b/src/modules/module-rescue-streams.c
@@ -138,8 +138,8 @@ int pa__init(pa_module*m) {
     }
 
     m->userdata = u = pa_xnew(struct userdata, 1);
-    u->sink_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_DISCONNECT], (pa_hook_cb_t) sink_hook_callback, NULL);
-    u->source_slot = pa_hook_connect(&m->core->hooks[PA_CORE_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;
diff --git a/src/modules/module-sine.c b/src/modules/module-sine.c
index f2830ff..94036f6 100644
--- a/src/modules/module-sine.c
+++ b/src/modules/module-sine.c
@@ -98,7 +98,7 @@ static void sink_input_kill_cb(pa_sink_input *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;
 
@@ -195,7 +195,7 @@ void pa__done(pa_module*m) {
         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);
     }
 
diff --git a/src/modules/module-suspend-on-idle.c b/src/modules/module-suspend-on-idle.c
index e9226ca..79850e7 100644
--- a/src/modules/module-suspend-on-idle.c
+++ b/src/modules/module-suspend-on-idle.c
@@ -53,16 +53,16 @@ struct userdata {
     pa_hook_slot
         *sink_new_slot,
         *source_new_slot,
-        *sink_disconnect_slot,
-        *source_disconnect_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_disconnect_slot,
-        *source_output_disconnect_slot,
+        *sink_input_unlink_slot,
+        *source_output_unlink_slot,
         *sink_input_move_slot,
         *source_output_move_slot,
         *sink_input_move_post_slot,
@@ -139,8 +139,8 @@ static pa_hook_result_t sink_input_new_hook_cb(pa_core *c, pa_sink_input *s, str
     pa_sink_input_assert_ref(s);
     pa_assert(u);
     
-    pa_assert_se((d = pa_hashmap_get(u->device_infos, s->sink)));
-    resume(d);
+    if ((d = pa_hashmap_get(u->device_infos, s->sink)))
+        resume(d);
     
     return PA_HOOK_OK;
 }
@@ -152,35 +152,35 @@ static pa_hook_result_t source_output_new_hook_cb(pa_core *c, pa_source_output *
     pa_source_output_assert_ref(s);
     pa_assert(u);
     
-    pa_assert_se((d = pa_hashmap_get(u->device_infos, s->source)));
-    resume(d);
+    if ((d = pa_hashmap_get(u->device_infos, s->source)))
+        resume(d);
     
     return PA_HOOK_OK;
 }
 
-static pa_hook_result_t sink_input_disconnect_hook_cb(pa_core *c, pa_sink_input *s, struct userdata *u) {
+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;
-        pa_assert_se((d = pa_hashmap_get(u->device_infos, s->sink)));
-        restart(d);
+        if ((d = pa_hashmap_get(u->device_infos, s->sink)))
+            restart(d);
     }
     
     return PA_HOOK_OK;
 }
 
-static pa_hook_result_t source_output_disconnect_hook_cb(pa_core *c, pa_source_output *s, struct userdata *u) {
+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;
-        pa_assert_se((d = pa_hashmap_get(u->device_infos, s->source)));
-        restart(d);
+        if ((d = pa_hashmap_get(u->device_infos, s->source)))
+            restart(d);
     }
     
     return PA_HOOK_OK;
@@ -193,8 +193,8 @@ static pa_hook_result_t sink_input_move_hook_cb(pa_core *c, pa_sink_input *s, st
 
     if (pa_sink_used_by(s->sink) <= 1) {
         struct device_info *d;
-        pa_assert_se((d = pa_hashmap_get(u->device_infos, s->sink)));
-        restart(d);
+        if ((d = pa_hashmap_get(u->device_infos, s->sink)))
+            restart(d);
     }
     
     return PA_HOOK_OK;
@@ -206,8 +206,8 @@ static pa_hook_result_t sink_input_move_post_hook_cb(pa_core *c, pa_sink_input *
     pa_sink_input_assert_ref(s);
     pa_assert(u);
 
-    pa_assert_se((d = pa_hashmap_get(u->device_infos, s->sink)));
-    resume(d);
+    if ((d = pa_hashmap_get(u->device_infos, s->sink)))
+        resume(d);
     
     return PA_HOOK_OK;
 }
@@ -219,8 +219,9 @@ static pa_hook_result_t source_output_move_hook_cb(pa_core *c, pa_source_output
 
     if (pa_source_used_by(s->source) <= 1) {
         struct device_info *d;
-        pa_assert_se((d = pa_hashmap_get(u->device_infos, s->source)));
-        restart(d);
+
+        if ((d = pa_hashmap_get(u->device_infos, s->source)))
+            restart(d);
     }
     
     return PA_HOOK_OK;
@@ -232,24 +233,36 @@ static pa_hook_result_t source_output_move_post_hook_cb(pa_core *c, pa_source_ou
     pa_source_output_assert_ref(s);
     pa_assert(u);
 
-    pa_assert_se((d = pa_hashmap_get(u->device_infos, s->source)));
-    resume(d);
+    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);
+    
+    if (source && !(source->flags & PA_SOURCE_CAN_SUSPEND))
+        return PA_HOOK_OK;
+
+    if (sink && !(sink->flags & PA_SINK_CAN_SUSPEND))
+        return PA_HOOK_OK;
+
     d = pa_xnew(struct device_info, 1);
     d->userdata = u;
-    d->source = pa_source_isinstance(o) ? pa_source_ref(PA_SOURCE(o)) : NULL;
-    d->sink = pa_sink_isinstance(o) ? pa_sink_ref(PA_SINK(o)) : NULL;
-    pa_assert(d->source || d->sink);
+    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);
 
@@ -273,15 +286,15 @@ static void device_info_free(struct device_info *d) {
     pa_xfree(d);
 }
 
-static pa_hook_result_t device_disconnect_hook_cb(pa_core *c, pa_object *o, struct userdata *u) {
+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);
 
-    pa_assert_se((d = pa_hashmap_remove(u->device_infos, o)));
-    device_info_free(d);
+    if ((d = pa_hashmap_remove(u->device_infos, o)))
+        device_info_free(d);
 
     return PA_HOOK_OK;
 }
@@ -353,15 +366,15 @@ int pa__init(pa_module*m) {
 
     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_disconnect_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_DISCONNECT_POST], (pa_hook_cb_t) device_disconnect_hook_cb, u);
-    u->source_disconnect_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_DISCONNECT_POST], (pa_hook_cb_t) device_disconnect_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_disconnect_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_INPUT_DISCONNECT_POST], (pa_hook_cb_t) sink_input_disconnect_hook_cb, u);
-    u->source_output_disconnect_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_DISCONNECT_POST], (pa_hook_cb_t) source_output_disconnect_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);
@@ -392,22 +405,22 @@ void pa__done(pa_module*m) {
     
     if (u->sink_new_slot)
         pa_hook_slot_free(u->sink_new_slot);
-    if (u->sink_disconnect_slot)
-        pa_hook_slot_free(u->sink_disconnect_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_disconnect_slot)
-        pa_hook_slot_free(u->source_disconnect_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_disconnect_slot)
-        pa_hook_slot_free(u->sink_input_disconnect_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)
@@ -415,8 +428,8 @@ void pa__done(pa_module*m) {
 
     if (u->source_output_new_slot)
         pa_hook_slot_free(u->source_output_new_slot);
-    if (u->source_output_disconnect_slot)
-        pa_hook_slot_free(u->source_output_disconnect_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)
diff --git a/src/pulsecore/cli-text.c b/src/pulsecore/cli-text.c
index c919e46..617ae81 100644
--- a/src/pulsecore/cli-text.c
+++ b/src/pulsecore/cli-text.c
@@ -97,7 +97,7 @@ char *pa_sink_list_to_string(pa_core *c) {
         [PA_SINK_RUNNING] = "RUNNING",
         [PA_SINK_SUSPENDED] = "SUSPENDED",
         [PA_SINK_IDLE] = "IDLE",
-        [PA_SINK_DISCONNECTED] = "DISCONNECTED"
+        [PA_SINK_UNLINKED] = "UNLINKED"
     };
     assert(c);
 
@@ -114,7 +114,7 @@ char *pa_sink_list_to_string(pa_core *c) {
             "  %c index: %u\n"
             "\tname: <%s>\n"
             "\tdriver: <%s>\n"
-            "\tis hardware: <%i>\n"
+            "\tflags: %s%s%s%s\n"
             "\tstate: %s\n"
             "\tvolume: <%s>\n"
             "\tmute: <%i>\n"
@@ -127,7 +127,10 @@ char *pa_sink_list_to_string(pa_core *c) {
             sink->index,
             sink->name,
             sink->driver,
-            !!sink->is_hardware,
+            sink->flags & PA_SINK_HW_VOLUME_CTRL ? "HW_VOLUME_CTRL " : "",
+            sink->flags & PA_SINK_LATENCY ? "LATENCY " : "",
+            sink->flags & PA_SINK_HARDWARE ? "HARDWARE " : "",
+            sink->flags & PA_SINK_CAN_SUSPEND ? "CAN_SUSPEND " : "",
             state_table[pa_sink_get_state(sink)],
             pa_cvolume_snprint(cv, sizeof(cv), pa_sink_get_volume(sink)),
             !!pa_sink_get_mute(sink),
@@ -154,7 +157,7 @@ char *pa_source_list_to_string(pa_core *c) {
         [PA_SOURCE_RUNNING] = "RUNNING",
         [PA_SOURCE_SUSPENDED] = "SUSPENDED",
         [PA_SOURCE_IDLE] = "IDLE",
-        [PA_SOURCE_DISCONNECTED] = "DISCONNECTED"
+        [PA_SOURCE_UNLINKED] = "UNLINKED"
     };
     assert(c);
 
@@ -172,7 +175,7 @@ char *pa_source_list_to_string(pa_core *c) {
             "  %c index: %u\n"
             "\tname: <%s>\n"
             "\tdriver: <%s>\n"
-            "\tis hardware: <%i>\n"
+            "\tflags: %s%s%s%s\n"
             "\tstate: %s\n"
             "\tvolume: <%s>\n"
             "\tmute: <%u>\n"
@@ -184,7 +187,10 @@ char *pa_source_list_to_string(pa_core *c) {
             source->index,
             source->name,
             source->driver,
-            !!source->is_hardware,
+            source->flags & PA_SOURCE_HW_VOLUME_CTRL ? "HW_VOLUME_CTRL " : "",
+            source->flags & PA_SOURCE_LATENCY ? "LATENCY " : "",
+            source->flags & PA_SOURCE_HARDWARE ? "HARDWARE " : "",
+            source->flags & PA_SOURCE_CAN_SUSPEND ? "CAN_SUSPEND " : "",
             state_table[pa_source_get_state(source)],
             pa_cvolume_snprint(cv, sizeof(cv), pa_source_get_volume(source)),
             !!pa_source_get_mute(source),
@@ -212,7 +218,7 @@ char *pa_source_output_list_to_string(pa_core *c) {
     static const char* const state_table[] = {
         [PA_SOURCE_OUTPUT_RUNNING] = "RUNNING",
         [PA_SOURCE_OUTPUT_CORKED] = "CORKED",
-        [PA_SOURCE_OUTPUT_DISCONNECTED] = "DISCONNECTED"
+        [PA_SOURCE_OUTPUT_UNLINKED] = "UNLINKED"
     };
     assert(c);
 
@@ -231,6 +237,7 @@ char *pa_source_output_list_to_string(pa_core *c) {
             "    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"
@@ -240,6 +247,8 @@ char *pa_source_output_list_to_string(pa_core *c) {
             o->index,
             o->name,
             o->driver,
+            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),
@@ -263,7 +272,7 @@ char *pa_sink_input_list_to_string(pa_core *c) {
         [PA_SINK_INPUT_RUNNING] = "RUNNING",
         [PA_SINK_INPUT_DRAINED] = "DRAINED",
         [PA_SINK_INPUT_CORKED] = "CORKED",
-        [PA_SINK_INPUT_DISCONNECTED] = "DISCONNECTED"
+        [PA_SINK_INPUT_UNLINKED] = "UNLINKED"
     };
 
     assert(c);
@@ -282,6 +291,7 @@ char *pa_sink_input_list_to_string(pa_core *c) {
             "    index: %u\n"
             "\tname: <%s>\n"
             "\tdriver: <%s>\n"
+            "\tflags: %s%s\n"
             "\tstate: %s\n"
             "\tsink: <%u> '%s'\n"
             "\tvolume: <%s>\n"
@@ -293,6 +303,8 @@ char *pa_sink_input_list_to_string(pa_core *c) {
             i->index,
             i->name,
             i->driver,
+            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)),
diff --git a/src/pulsecore/core.c b/src/pulsecore/core.c
index 7ca2e75..808bc9a 100644
--- a/src/pulsecore/core.c
+++ b/src/pulsecore/core.c
@@ -133,7 +133,7 @@ pa_core* pa_core_new(pa_mainloop_api *m, int shared) {
     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;
diff --git a/src/pulsecore/core.h b/src/pulsecore/core.h
index 61cb47d..c8d7580 100644
--- a/src/pulsecore/core.h
+++ b/src/pulsecore/core.h
@@ -44,23 +44,23 @@ typedef struct pa_core pa_core;
 
 typedef enum pa_core_hook {
     PA_CORE_HOOK_SINK_NEW_POST,
-    PA_CORE_HOOK_SINK_DISCONNECT,
-    PA_CORE_HOOK_SINK_DISCONNECT_POST,
+    PA_CORE_HOOK_SINK_UNLINK,
+    PA_CORE_HOOK_SINK_UNLINK_POST,
     PA_CORE_HOOK_SINK_STATE_CHANGED,
     PA_CORE_HOOK_SOURCE_NEW_POST,
-    PA_CORE_HOOK_SOURCE_DISCONNECT,
-    PA_CORE_HOOK_SOURCE_DISCONNECT_POST,
+    PA_CORE_HOOK_SOURCE_UNLINK,
+    PA_CORE_HOOK_SOURCE_UNLINK_POST,
     PA_CORE_HOOK_SOURCE_STATE_CHANGED,
     PA_CORE_HOOK_SINK_INPUT_NEW,
     PA_CORE_HOOK_SINK_INPUT_PUT,
-    PA_CORE_HOOK_SINK_INPUT_DISCONNECT,
-    PA_CORE_HOOK_SINK_INPUT_DISCONNECT_POST,
+    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_SOURCE_OUTPUT_NEW,
     PA_CORE_HOOK_SOURCE_OUTPUT_PUT,
-    PA_CORE_HOOK_SOURCE_OUTPUT_DISCONNECT,
-    PA_CORE_HOOK_SOURCE_OUTPUT_DISCONNECT_POST,
+    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_MAX
diff --git a/src/pulsecore/play-memblockq.c b/src/pulsecore/play-memblockq.c
index 0d7efc5..68ce21b 100644
--- a/src/pulsecore/play-memblockq.c
+++ b/src/pulsecore/play-memblockq.c
@@ -58,7 +58,7 @@ static void memblockq_stream_unlink(memblockq_stream *u) {
     if (!u->sink_input)
         return;
 
-    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;
diff --git a/src/pulsecore/play-memchunk.c b/src/pulsecore/play-memchunk.c
index f2925d1..3ebbc14 100644
--- a/src/pulsecore/play-memchunk.c
+++ b/src/pulsecore/play-memchunk.c
@@ -58,7 +58,7 @@ static void memchunk_stream_unlink(memchunk_stream *u) {
     if (!u->sink_input)
         return;
 
-    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;
diff --git a/src/pulsecore/protocol-esound.c b/src/pulsecore/protocol-esound.c
index c5505e5..fc881c8 100644
--- a/src/pulsecore/protocol-esound.c
+++ b/src/pulsecore/protocol-esound.c
@@ -212,13 +212,13 @@ static void connection_unlink(connection *c) {
         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;
     }
diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c
index a0b7066..ea7f43c 100644
--- a/src/pulsecore/protocol-native.c
+++ b/src/pulsecore/protocol-native.c
@@ -387,7 +387,7 @@ static void record_stream_unlink(record_stream *s) {
         return;
 
     if (s->source_output) {
-        pa_source_output_disconnect(s->source_output);
+        pa_source_output_unlink(s->source_output);
         pa_source_output_unref(s->source_output);
         s->source_output = NULL;
     }
@@ -460,11 +460,10 @@ static record_stream* record_stream_new(
     data.source = source;
     data.driver = __FILE__;
     data.name = name;
-    data.start_corked = corked;
     pa_source_output_new_data_set_sample_spec(&data, ss);
     pa_source_output_new_data_set_channel_map(&data, map);
 
-    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_msgobject_new(record_stream);
@@ -504,7 +503,7 @@ static void playback_stream_unlink(playback_stream *s) {
         return;
 
     if (s->sink_input) {
-        pa_sink_input_disconnect(s->sink_input);
+        pa_sink_input_unlink(s->sink_input);
         pa_sink_input_unref(s->sink_input);
         s->sink_input = NULL;
     }
@@ -653,10 +652,9 @@ static playback_stream* playback_stream_new(
     pa_sink_input_new_data_set_volume(&data, volume);
     data.module = c->protocol->module;
     data.client = c->client;
-    data.start_corked = corked;
     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_msgobject_new(playback_stream);
@@ -1729,10 +1727,7 @@ static void sink_fill_tagstruct(pa_tagstruct *t, pa_sink *sink) {
         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_volume ? PA_SINK_HW_VOLUME_CTRL : 0) |  /* FIXME */
-        (sink->get_latency ? PA_SINK_LATENCY : 0) |        /* FIXME */ 
-        (sink->is_hardware ? PA_SINK_HARDWARE : 0),
+        PA_TAG_U32, sink->flags,
         PA_TAG_INVALID);
 }
 
@@ -1754,10 +1749,7 @@ static void source_fill_tagstruct(pa_tagstruct *t, pa_source *source) {
         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_volume ? PA_SOURCE_HW_VOLUME_CTRL : 0) |     /* FIXME */
-        (source->get_latency ? PA_SOURCE_LATENCY : 0) |              /* FIXME */
-        (source->is_hardware ? PA_SOURCE_HARDWARE : 0),
+        PA_TAG_U32, source->flags,
         PA_TAG_INVALID);
 }
 
diff --git a/src/pulsecore/protocol-simple.c b/src/pulsecore/protocol-simple.c
index bc48ac3..db7c9a6 100644
--- a/src/pulsecore/protocol-simple.c
+++ b/src/pulsecore/protocol-simple.c
@@ -110,13 +110,13 @@ static void connection_unlink(connection *c) {
         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;
     }
diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c
index 0cdcbc0..c33d8e7 100644
--- a/src/pulsecore/sink-input.c
+++ b/src/pulsecore/sink-input.c
@@ -108,7 +108,7 @@ pa_sink_input* pa_sink_input_new(
         data->sink = pa_namereg_get(core, NULL, PA_NAMEREG_SINK, 1);
 
     pa_return_null_if_fail(data->sink);
-    pa_return_null_if_fail(pa_sink_get_state(data->sink) != PA_SINK_DISCONNECTED);
+    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)
@@ -167,7 +167,7 @@ pa_sink_input* pa_sink_input_new(
     i->parent.process_msg = pa_sink_input_process_msg;
 
     i->core = core;
-    i->state = data->start_corked ? PA_SINK_INPUT_CORKED : PA_SINK_INPUT_RUNNING;
+    i->state = PA_SINK_INPUT_INIT;
     i->flags = flags;
     i->name = pa_xstrdup(data->name);
     i->driver = pa_xstrdup(data->driver);
@@ -194,9 +194,12 @@ pa_sink_input* pa_sink_input_new(
     
     i->peek = NULL;
     i->drop = NULL;
+    i->process = NULL;
     i->kill = NULL;
     i->get_latency = NULL;
-    i->underrun = NULL;
+    i->attach = NULL;
+    i->detach = NULL;
+    i->suspend = NULL;
     i->userdata = NULL;
 
     i->thread_info.state = i->state;
@@ -245,11 +248,11 @@ static int sink_input_set_state(pa_sink_input *i, pa_sink_input_state_t state) {
     return 0;
 }
 
-void pa_sink_input_disconnect(pa_sink_input *i) {
+void pa_sink_input_unlink(pa_sink_input *i) {
     pa_assert(i);
-    pa_return_if_fail(i->state != PA_SINK_INPUT_DISCONNECTED);
+    pa_assert(PA_SINK_INPUT_LINKED(i->state));
 
-    pa_hook_fire(&i->sink->core->hooks[PA_CORE_HOOK_SINK_INPUT_DISCONNECT], i);
+    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;
@@ -264,16 +267,19 @@ void pa_sink_input_disconnect(pa_sink_input *i) {
 
     pa_subscription_post(i->sink->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_REMOVE, i->index);
 
-    sink_input_set_state(i, PA_SINK_INPUT_DISCONNECTED);
+    sink_input_set_state(i, PA_SINK_INPUT_UNLINKED);
     pa_sink_update_status(i->sink);
     
     i->peek = NULL;
     i->drop = NULL;
+    i->process = NULL;
     i->kill = NULL;
     i->get_latency = NULL;
-    i->underrun = NULL;
+    i->attach = NULL;
+    i->detach = NULL;
+    i->suspend = NULL;
 
-    pa_hook_fire(&i->sink->core->hooks[PA_CORE_HOOK_SINK_INPUT_DISCONNECT_POST], i);
+    pa_hook_fire(&i->sink->core->hooks[PA_CORE_HOOK_SINK_INPUT_UNLINK_POST], i);
     i->sink = NULL;
     pa_sink_input_unref(i);
 }
@@ -284,8 +290,8 @@ static void sink_input_free(pa_object *o) {
     pa_assert(i);
     pa_assert(pa_sink_input_refcnt(i) == 0);
 
-    if (i->state != PA_SINK_INPUT_DISCONNECTED)
-        pa_sink_input_disconnect(i);
+    if (PA_SINK_INPUT_LINKED(i->state))
+        pa_sink_input_unlink(i);
 
     pa_log_info("Freeing output %u \"%s\"", i->index, i->name);
 
@@ -306,6 +312,11 @@ static void sink_input_free(pa_object *o) {
 void pa_sink_input_put(pa_sink_input *i) {
     pa_sink_input_assert_ref(i);
 
+    pa_assert(i->state == PA_SINK_INPUT_INIT);
+    pa_assert(i->peek);
+    pa_assert(i->drop);
+
+    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;
 
@@ -314,10 +325,15 @@ void pa_sink_input_put(pa_sink_input *i) {
 
     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) {
     pa_sink_input_assert_ref(i);
+    pa_assert(PA_SINK_INPUT_LINKED(i->state));
 
     if (i->kill)
         i->kill(i);
@@ -327,6 +343,7 @@ pa_usec_t pa_sink_input_get_latency(pa_sink_input *i) {
     pa_usec_t r = 0;
 
     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;
@@ -344,10 +361,11 @@ int pa_sink_input_peek(pa_sink_input *i, pa_memchunk *chunk, pa_cvolume *volume)
     int volume_is_norm;
 
     pa_sink_input_assert_ref(i);
+    pa_assert(PA_SINK_INPUT_LINKED(i->thread_info.state));
     pa_assert(chunk);
     pa_assert(volume);
 
-    if (!i->peek || !i->drop || i->thread_info.state == PA_SINK_INPUT_DISCONNECTED || i->thread_info.state == PA_SINK_INPUT_CORKED)
+    if (!i->peek || !i->drop || i->thread_info.state == PA_SINK_INPUT_UNLINKED || i->thread_info.state == PA_SINK_INPUT_CORKED)
         goto finish;
 
     pa_assert(i->thread_info.state == PA_SINK_INPUT_RUNNING || i->thread_info.state == PA_SINK_INPUT_DRAINED);
@@ -420,9 +438,6 @@ int pa_sink_input_peek(pa_sink_input *i, pa_memchunk *chunk, pa_cvolume *volume)
 
 finish:
 
-    if (ret < 0 && !pa_atomic_load(&i->thread_info.drained) && i->underrun)
-        i->underrun(i);
-
     if (ret >= 0)
         pa_atomic_store(&i->thread_info.drained, 0);
     else if (ret < 0)
@@ -448,13 +463,18 @@ finish:
 /* 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(length > 0);
 
     if (i->thread_info.move_silence > 0) {
 
-        pa_assert(i->thread_info.move_silence >= length);
-
-        i->thread_info.move_silence -= length;
+        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) {
             pa_assert(i->thread_info.silence_memblock);
@@ -462,7 +482,8 @@ void pa_sink_input_drop(pa_sink_input *i, size_t length) {
             i->thread_info.silence_memblock = NULL;
         }
 
-        return;
+        if (length <= 0)
+            return;
     }
 
     if (i->thread_info.resampled_chunk.memblock) {
@@ -531,6 +552,7 @@ void pa_sink_input_drop(pa_sink_input *i, size_t length) {
 
 void pa_sink_input_set_volume(pa_sink_input *i, const pa_cvolume *volume) {
     pa_sink_input_assert_ref(i);
+    pa_assert(PA_SINK_INPUT_LINKED(i->state));
 
     if (pa_cvolume_equal(&i->volume, volume))
         return;
@@ -543,6 +565,7 @@ 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) {
     pa_sink_input_assert_ref(i);
+    pa_assert(PA_SINK_INPUT_LINKED(i->state));
 
     return &i->volume;
 }
@@ -550,6 +573,7 @@ const pa_cvolume *pa_sink_input_get_volume(pa_sink_input *i) {
 void pa_sink_input_set_mute(pa_sink_input *i, int mute) {
     pa_assert(i);
     pa_sink_input_assert_ref(i);
+    pa_assert(PA_SINK_INPUT_LINKED(i->state));
 
     if (!i->muted == !mute)
         return;
@@ -562,18 +586,21 @@ void pa_sink_input_set_mute(pa_sink_input *i, int mute) {
 
 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;
 }
 
 void pa_sink_input_cork(pa_sink_input *i, int b) {
     pa_sink_input_assert_ref(i);
+    pa_assert(PA_SINK_INPUT_LINKED(i->state));
 
     sink_input_set_state(i, b ? PA_SINK_INPUT_CORKED : PA_SINK_INPUT_RUNNING);
 }
 
 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)
@@ -615,6 +642,7 @@ int pa_sink_input_move_to(pa_sink_input *i, pa_sink *dest, int immediately) {
     pa_sink_input_move_info info;
 
     pa_sink_input_assert_ref(i);
+    pa_assert(PA_SINK_INPUT_LINKED(i->state));
     pa_sink_assert_ref(dest);
 
     origin = i->sink;
@@ -622,6 +650,9 @@ int pa_sink_input_move_to(pa_sink_input *i, pa_sink *dest, int immediately) {
     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;
@@ -714,6 +745,10 @@ int pa_sink_input_move_to(pa_sink_input *i, pa_sink *dest, int immediately) {
 
     if (info.ghost_sink_input) {
         /* Basically, do what pa_sink_input_put() does ...*/
+        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;
+        
         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);
@@ -774,6 +809,7 @@ int pa_sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int64_t
     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:
@@ -841,3 +877,4 @@ pa_sink_input_state_t pa_sink_input_get_state(pa_sink_input *i) {
 
     return i->state;
 }
+
diff --git a/src/pulsecore/sink-input.h b/src/pulsecore/sink-input.h
index d728d46..e1d89ff 100644
--- a/src/pulsecore/sink-input.h
+++ b/src/pulsecore/sink-input.h
@@ -39,14 +39,21 @@ typedef struct pa_sink_input pa_sink_input;
 #include <pulsecore/core.h>
 
 typedef enum pa_sink_input_state {
+    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 int 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_DONT_MOVE = 2,
+    PA_SINK_INPUT_START_CORKED = 4
 } pa_sink_input_flags_t;
 
 struct pa_sink_input {
@@ -75,11 +82,42 @@ struct pa_sink_input {
     pa_cvolume volume;
     int muted;
 
+    /* Returns the chunk of audio data (but doesn't drop it
+     * yet!). Returns -1 on failure. Called from IO thread context. */
     int (*peek) (pa_sink_input *i, 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 in each IO event loop and
+     * can be used to do additional processing even when the device is
+     * suspended and peek() is never called. Should return 1 when
+     * "some work" has been done and the IO event loop should be
+     * reiterated immediately. Called from IO thread context. */
+    int (*process) (pa_sink_input *i);           /* may be NULL */
+
+    /* If non-NULL this function is called when the input is first
+     * connected to a sink. 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 */
 
     pa_resample_method_t resample_method;
 
@@ -138,7 +176,6 @@ typedef struct pa_sink_input_new_data {
 
     pa_resample_method_t resample_method;
 
-    int start_corked;
     pa_sink_input *sync_base;
 } pa_sink_input_new_data;
 
@@ -156,7 +193,7 @@ pa_sink_input* pa_sink_input_new(
         pa_sink_input_flags_t flags);
 
 void pa_sink_input_put(pa_sink_input *i);
-void pa_sink_input_disconnect(pa_sink_input* i);
+void pa_sink_input_unlink(pa_sink_input* i);
 
 void pa_sink_input_set_name(pa_sink_input *i, const char *name);
 
diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c
index 2c7c661..b61a850 100644
--- a/src/pulsecore/sink.c
+++ b/src/pulsecore/sink.c
@@ -92,7 +92,8 @@ pa_sink* pa_sink_new(
     s->parent.process_msg = pa_sink_process_msg;
 
     s->core = core;
-    s->state = PA_SINK_IDLE;
+    s->state = PA_SINK_INIT;
+    s->flags = 0;
     s->name = pa_xstrdup(name);
     s->description = NULL;
     s->driver = pa_xstrdup(driver);
@@ -107,8 +108,6 @@ pa_sink* pa_sink_new(
     s->muted = 0;
     s->refresh_volume = s->refresh_mute = 0;
 
-    s->is_hardware = 0;
-
     s->get_latency = NULL;
     s->set_volume = NULL;
     s->get_volume = NULL;
@@ -118,6 +117,7 @@ pa_sink* pa_sink_new(
     s->userdata = NULL;
 
     s->asyncmsgq = NULL;
+    s->rtpoll = NULL;
     s->silence = NULL;
 
     r = pa_idxset_put(core->sinks, s, &s->index);
@@ -145,11 +145,22 @@ pa_sink* pa_sink_new(
     s->thread_info.soft_muted = s->muted;
     s->thread_info.state = s->state;
 
-    pa_subscription_post(core, PA_SUBSCRIPTION_EVENT_SINK | PA_SUBSCRIPTION_EVENT_NEW, s->index);
+    return s;
+}
 
-    pa_hook_fire(&core->hooks[PA_CORE_HOOK_SINK_NEW_POST], s);
+void pa_sink_put(pa_sink* s) {
+    pa_sink_assert_ref(s);
 
-    return s;
+    pa_assert(s->state == PA_SINK_INIT);
+    pa_assert(s->asyncmsgq);
+    pa_assert(s->rtpoll);
+
+    s->thread_info.state = s->state = PA_SINK_IDLE;
+    
+    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);
 }
 
 static int sink_set_state(pa_sink *s, pa_sink_state_t state) {
@@ -160,6 +171,21 @@ static int sink_set_state(pa_sink *s, pa_sink_state_t state) {
     if (s->state == state)
         return 0;
 
+    if (state == PA_SINK_SUSPENDED && !(s->flags & PA_SINK_CAN_SUSPEND))
+        return -1;
+
+    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;
@@ -168,18 +194,19 @@ static int sink_set_state(pa_sink *s, pa_sink_state_t state) {
         return -1;
 
     s->state = state;
-    
-    pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SINK_STATE_CHANGED], s);
+
+    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_disconnect(pa_sink* s) {
+void pa_sink_unlink(pa_sink* s) {
     pa_sink_input *i, *j = NULL;
 
     pa_assert(s);
-    pa_return_if_fail(s->state != PA_SINK_DISCONNECTED);
+    pa_assert(PA_SINK_LINKED(s->state));
 
-    pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SINK_DISCONNECT], s);
+    pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SINK_UNLINK], s);
     
     pa_namereg_unregister(s->core, s->name);
     pa_idxset_remove_by_data(s->core->sinks, s, NULL);
@@ -191,9 +218,9 @@ void pa_sink_disconnect(pa_sink* s) {
     }
 
     if (s->monitor_source)
-        pa_source_disconnect(s->monitor_source);
+        pa_source_unlink(s->monitor_source);
 
-    sink_set_state(s, PA_SINK_DISCONNECTED);
+    sink_set_state(s, PA_SINK_UNLINKED);
 
     s->get_latency = NULL;
     s->get_volume = NULL;
@@ -204,7 +231,7 @@ void pa_sink_disconnect(pa_sink* s) {
 
     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_DISCONNECT_POST], s);
+    pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SINK_UNLINK_POST], s);
 }
 
 static void sink_free(pa_object *o) {
@@ -214,8 +241,8 @@ static void sink_free(pa_object *o) {
     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("Freeing sink %u \"%s\"", s->index, s->name);
 
@@ -250,8 +277,18 @@ void pa_sink_set_asyncmsgq(pa_sink *s, pa_asyncmsgq *q) {
         pa_source_set_asyncmsgq(s->monitor_source, q);
 }
 
+void pa_sink_set_rtpoll(pa_sink *s, pa_rtpoll *p) {
+    pa_sink_assert_ref(s);
+    pa_assert(p);
+
+    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;
@@ -261,6 +298,7 @@ int pa_sink_update_status(pa_sink*s) {
 
 int pa_sink_suspend(pa_sink *s, int suspend) {
     pa_sink_assert_ref(s);
+    pa_assert(PA_SINK_LINKED(s->state));
 
     if (suspend)
         return sink_set_state(s, PA_SINK_SUSPENDED);
@@ -270,6 +308,7 @@ int pa_sink_suspend(pa_sink *s, int suspend) {
 
 void pa_sink_ping(pa_sink *s) {
     pa_sink_assert_ref(s);
+    pa_assert(PA_SINK_LINKED(s->state));
 
     pa_asyncmsgq_post(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_PING, NULL, 0, NULL, NULL);
 }
@@ -364,6 +403,7 @@ void pa_sink_render(pa_sink*s, size_t length, pa_memchunk *result) {
     unsigned n;
 
     pa_sink_assert_ref(s);
+    pa_assert(PA_SINK_OPENED(s->thread_info.state));
     pa_assert(length);
     pa_assert(result);
 
@@ -429,6 +469,7 @@ void pa_sink_render_into(pa_sink*s, pa_memchunk *target) {
     unsigned n;
 
     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);
@@ -494,6 +535,7 @@ void pa_sink_render_into_full(pa_sink *s, pa_memchunk *target) {
     size_t l, d;
 
     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);
@@ -518,6 +560,7 @@ void pa_sink_render_into_full(pa_sink *s, pa_memchunk *target) {
 
 void pa_sink_render_full(pa_sink *s, size_t length, pa_memchunk *result) {
     pa_sink_assert_ref(s);
+    pa_assert(PA_SINK_OPENED(s->thread_info.state));
     pa_assert(length);
     pa_assert(result);
 
@@ -529,10 +572,46 @@ void pa_sink_render_full(pa_sink *s, size_t length, pa_memchunk *result) {
     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);
+    
+    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) {
     pa_usec_t usec = 0;
 
     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);
@@ -547,6 +626,7 @@ void pa_sink_set_volume(pa_sink *s, const pa_cvolume *volume) {
     int changed;
 
     pa_sink_assert_ref(s);
+    pa_assert(PA_SINK_LINKED(s->state));
     pa_assert(volume);
 
     changed = !pa_cvolume_equal(volume, &s->volume);
@@ -566,6 +646,7 @@ const pa_cvolume *pa_sink_get_volume(pa_sink *s) {
     struct pa_cvolume old_volume;
 
     pa_sink_assert_ref(s);
+    pa_assert(PA_SINK_LINKED(s->state));
 
     old_volume = s->volume;
 
@@ -585,6 +666,7 @@ void pa_sink_set_mute(pa_sink *s, int mute) {
     int changed;
 
     pa_sink_assert_ref(s);
+    pa_assert(PA_SINK_LINKED(s->state));
 
     changed = s->muted != mute;
     s->muted = mute;
@@ -603,6 +685,7 @@ int pa_sink_get_mute(pa_sink *s) {
     int old_muted;
 
     pa_sink_assert_ref(s);
+    pa_assert(PA_SINK_LINKED(s->state));
 
     old_muted = s->muted;
 
@@ -659,6 +742,7 @@ 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);
 
@@ -671,6 +755,7 @@ unsigned pa_sink_used_by(pa_sink *s) {
 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(PA_SINK_LINKED(s->thread_info.state));
 
     switch ((pa_sink_message_t) code) {
         
@@ -694,13 +779,19 @@ int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offse
                 i->thread_info.sync_next->thread_info.sync_prev = i;
             }
 
+            if (i->attach)
+                i->attach(i);
+
             return 0;
         }
 
         case PA_SINK_MESSAGE_REMOVE_INPUT: {
             pa_sink_input *i = PA_SINK_INPUT(userdata);
 
-            /* Since the caller sleeps in pa_sink_input_disconnect(),
+            if (i->detach)
+                i->detach(i);
+            
+            /* Since the caller sleeps in pa_sink_input_unlink(),
              * we can safely access data outside of thread_info even
              * though it is mutable */
 
@@ -833,3 +924,21 @@ int pa_sink_suspend_all(pa_core *c, int suspend) {
 
     return ret;
 }
+
+int pa_sink_process_inputs(pa_sink *s) {
+    pa_sink_input *i;
+    void *state = NULL;
+    int r;
+    
+    pa_sink_assert_ref(s);
+
+    if (!PA_SINK_LINKED(s->thread_info.state))
+        return 0;
+    
+    while ((i = PA_SINK_INPUT(pa_hashmap_iterate(s->thread_info.inputs, &state, NULL))))
+        if (i->process)
+            if ((r = i->process(i)))
+                return r;
+
+    return 0;
+}
diff --git a/src/pulsecore/sink.h b/src/pulsecore/sink.h
index fadc76e..b3fcff4 100644
--- a/src/pulsecore/sink.h
+++ b/src/pulsecore/sink.h
@@ -40,26 +40,36 @@ typedef struct pa_sink pa_sink;
 #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_SUSPENDED,
     PA_SINK_IDLE,
-    PA_SINK_DISCONNECTED
+    PA_SINK_UNLINKED
 } pa_sink_state_t;
 
+static inline int PA_SINK_OPENED(pa_sink_state_t x) {
+    return x == PA_SINK_RUNNING || x == PA_SINK_IDLE;
+}
+
+static inline int PA_SINK_LINKED(pa_sink_state_t x) {
+    return x == PA_SINK_RUNNING || x == PA_SINK_IDLE || x == PA_SINK_SUSPENDED;
+}
+
 struct pa_sink {
     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 *module;                      /* may be NULL */
 
@@ -67,21 +77,22 @@ struct pa_sink {
     pa_channel_map channel_map;
 
     pa_idxset *inputs;
-    pa_source *monitor_source;             /* may be NULL */
+    pa_source *monitor_source;           
 
     pa_cvolume volume;
     int muted;
     int refresh_volume;
     int refresh_mute;
 
-    int (*set_state)(pa_sink *s, pa_sink_state_t state);
-    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 */
+    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 */
@@ -114,7 +125,7 @@ typedef enum pa_sink_message {
     PA_SINK_MESSAGE_MAX
 } pa_sink_message_t;
 
-/* To be used exclusively by the sink driver */
+/* To be called exclusively by the sink driver, from main context */
 
 pa_sink* pa_sink_new(
         pa_core *core,
@@ -124,18 +135,21 @@ pa_sink* pa_sink_new(
         const pa_sample_spec *spec,
         const pa_channel_map *map);
 
-void pa_sink_disconnect(pa_sink* s);
+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);
 
-/* Usable by everyone */
+/* May be called by everyone, from main context */
 
 pa_usec_t pa_sink_get_latency(pa_sink *s);
 
 int pa_sink_update_status(pa_sink*s);
 int pa_sink_suspend(pa_sink *s, int suspend);
+int pa_sink_suspend_all(pa_core *c, int suspend);
 
 /* 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
@@ -150,19 +164,17 @@ int pa_sink_get_mute(pa_sink *sink);
 unsigned pa_sink_used_by(pa_sink *s);
 #define pa_sink_get_state(s) ((s)->state)
 
-/* To be used exclusively by the sink driver thread */
+/* 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);
 
-int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offset, pa_memchunk *chunk);
+void pa_sink_skip(pa_sink *s, size_t length);
 
-static inline int PA_SINK_OPENED(pa_sink_state_t x) {
-    return x == PA_SINK_RUNNING || x == PA_SINK_IDLE;
-}
+int pa_sink_process_inputs(pa_sink *s);
 
-int pa_sink_suspend_all(pa_core *c, int suspend);
+int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offset, pa_memchunk *chunk);
 
 #endif
diff --git a/src/pulsecore/sound-file-stream.c b/src/pulsecore/sound-file-stream.c
index e0d51a7..36c7f03 100644
--- a/src/pulsecore/sound-file-stream.c
+++ b/src/pulsecore/sound-file-stream.c
@@ -69,7 +69,7 @@ static void file_stream_unlink(file_stream *u) {
     if (!u->sink_input)
         return;
     
-    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;
diff --git a/src/pulsecore/source-output.c b/src/pulsecore/source-output.c
index 2532246..ccd968a 100644
--- a/src/pulsecore/source-output.c
+++ b/src/pulsecore/source-output.c
@@ -86,7 +86,7 @@ pa_source_output* pa_source_output_new(
         data->source = pa_namereg_get(core, NULL, PA_NAMEREG_SOURCE, 1);
 
     pa_return_null_if_fail(data->source);
-    pa_return_null_if_fail(pa_source_get_state(data->source) != PA_SOURCE_DISCONNECTED);
+    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;
@@ -135,7 +135,7 @@ pa_source_output* pa_source_output_new(
     o->parent.process_msg = pa_source_output_process_msg;
 
     o->core = core;
-    o->state = data->start_corked ? PA_SOURCE_OUTPUT_CORKED : PA_SOURCE_OUTPUT_RUNNING;
+    o->state = PA_SOURCE_OUTPUT_INIT;
     o->flags = flags;
     o->name = pa_xstrdup(data->name);
     o->driver = pa_xstrdup(data->driver);
@@ -148,8 +148,12 @@ pa_source_output* pa_source_output_new(
     o->channel_map = data->channel_map;
 
     o->push = NULL;
+    o->process = NULL;
     o->kill = NULL;
     o->get_latency = NULL;
+    o->detach = NULL;
+    o->attach = NULL;
+    o->suspend = NULL;
     o->userdata = NULL;
 
     o->thread_info.state = o->state;
@@ -183,11 +187,11 @@ static int source_output_set_state(pa_source_output *o, pa_source_output_state_t
     return 0;
 }
 
-void pa_source_output_disconnect(pa_source_output*o) {
+void pa_source_output_unlink(pa_source_output*o) {
     pa_assert(o);
-    pa_return_if_fail(o->state != PA_SOURCE_OUTPUT_DISCONNECTED);
+    pa_assert(PA_SOURCE_OUTPUT_LINKED(o->state));
 
-    pa_hook_fire(&o->source->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_DISCONNECT], o);
+    pa_hook_fire(&o->source->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_UNLINK], o);
     
     pa_asyncmsgq_send(o->source->asyncmsgq, PA_MSGOBJECT(o->source), PA_SOURCE_MESSAGE_REMOVE_OUTPUT, o, 0, NULL);
 
@@ -196,14 +200,18 @@ void pa_source_output_disconnect(pa_source_output*o) {
 
     pa_subscription_post(o->source->core, PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_REMOVE, o->index);
 
-    source_output_set_state(o, PA_SOURCE_OUTPUT_DISCONNECTED);
+    source_output_set_state(o, PA_SOURCE_OUTPUT_UNLINKED);
     pa_source_update_status(o->source);
 
     o->push = NULL;
+    o->process = NULL;
     o->kill = NULL;
     o->get_latency = NULL;
+    o->attach = NULL;
+    o->detach = NULL;
+    o->suspend = NULL;
 
-    pa_hook_fire(&o->source->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_DISCONNECT_POST], o);
+    pa_hook_fire(&o->source->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_UNLINK_POST], o);
 
     o->source = NULL;
     pa_source_output_unref(o);
@@ -214,8 +222,8 @@ static void source_output_free(pa_object* mo) {
 
     pa_assert(pa_source_output_refcnt(o) == 0);
 
-    if (o->state != PA_SOURCE_OUTPUT_DISCONNECTED)
-        pa_source_output_disconnect(o);
+    if (PA_SOURCE_LINKED(o->state))
+        pa_source_output_unlink(o);
 
     pa_log_info("Freeing output %u \"%s\"", o->index, o->name);
 
@@ -230,6 +238,11 @@ static void source_output_free(pa_object* mo) {
 void pa_source_output_put(pa_source_output *o) {
     pa_source_output_assert_ref(o);
 
+    pa_assert(o->state == PA_SOURCE_OUTPUT_INIT);
+    pa_assert(o->push);
+
+    o->thread_info.state = o->state = o->flags & PA_SOURCE_OUTPUT_START_CORKED ? PA_SOURCE_OUTPUT_CORKED : PA_SOURCE_OUTPUT_RUNNING;
+
     pa_asyncmsgq_send(o->source->asyncmsgq, PA_MSGOBJECT(o->source), PA_SOURCE_MESSAGE_ADD_OUTPUT, o, 0, NULL);
     pa_source_update_status(o->source);
 
@@ -240,7 +253,8 @@ void pa_source_output_put(pa_source_output *o) {
 
 void pa_source_output_kill(pa_source_output*o) {
     pa_source_output_assert_ref(o);
-
+    pa_assert(PA_SOURCE_OUTPUT_LINKED(o->state));
+    
     if (o->kill)
         o->kill(o);
 }
@@ -249,6 +263,7 @@ 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;
@@ -264,10 +279,11 @@ void pa_source_output_push(pa_source_output *o, const pa_memchunk *chunk) {
     pa_memchunk rchunk;
 
     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->push || o->state == PA_SOURCE_OUTPUT_DISCONNECTED || o->state == PA_SOURCE_OUTPUT_CORKED)
+    if (!o->push || o->state == PA_SOURCE_OUTPUT_UNLINKED || o->state == PA_SOURCE_OUTPUT_CORKED)
         return;
 
     pa_assert(o->state == PA_SOURCE_OUTPUT_RUNNING);
@@ -288,12 +304,14 @@ void pa_source_output_push(pa_source_output *o, const pa_memchunk *chunk) {
 
 void pa_source_output_cork(pa_source_output *o, int b) {
     pa_source_output_assert_ref(o);
+    pa_assert(PA_SOURCE_OUTPUT_LINKED(o->state));
 
     source_output_set_state(o, b ? PA_SOURCE_OUTPUT_CORKED : PA_SOURCE_OUTPUT_RUNNING);
 }
 
 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);
 
     if (o->sample_spec.rate == rate)
@@ -333,6 +351,7 @@ int pa_source_output_move_to(pa_source_output *o, pa_source *dest) {
     pa_resampler *new_resampler = NULL;
 
     pa_source_output_assert_ref(o);
+    pa_assert(PA_SOURCE_OUTPUT_LINKED(o->state));
     pa_source_assert_ref(dest);
     
     origin = o->source;
@@ -340,6 +359,9 @@ int pa_source_output_move_to(pa_source_output *o, pa_source *dest) {
     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;
@@ -405,6 +427,7 @@ int pa_source_output_process_msg(pa_msgobject *mo, int code, void *userdata, int
     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) {
 
diff --git a/src/pulsecore/source-output.h b/src/pulsecore/source-output.h
index b17adcb..2027e37 100644
--- a/src/pulsecore/source-output.h
+++ b/src/pulsecore/source-output.h
@@ -36,13 +36,20 @@ typedef struct pa_source_output pa_source_output;
 #include <pulsecore/client.h>
 
 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 int 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_VARIABLE_RATE = 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 {
@@ -62,8 +69,37 @@ struct pa_source_output {
     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 in each IO event loop and
+     * can be used to do additional processing even when the device is
+     * suspended and peek() is never called. Should return 1 when
+     * "some work" has been done and the IO event loop should be
+     * reiterated immediately. Called from IO thread context. */
+    int (*process) (pa_source_output *o);           /* may be NULL */
+
+    /* 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_resample_method_t resample_method;
@@ -102,8 +138,6 @@ typedef struct pa_source_output_new_data {
     int channel_map_is_set;
 
     pa_resample_method_t resample_method;
-
-    int start_corked;
 } pa_source_output_new_data;
 
 pa_source_output_new_data* pa_source_output_new_data_init(pa_source_output_new_data *data);
@@ -119,7 +153,7 @@ pa_source_output* pa_source_output_new(
         pa_source_output_flags_t flags);
 
 void pa_source_output_put(pa_source_output *o);
-void pa_source_output_disconnect(pa_source_output*o);
+void pa_source_output_unlink(pa_source_output*o);
 
 void pa_source_output_set_name(pa_source_output *i, const char *name);
 
diff --git a/src/pulsecore/source.c b/src/pulsecore/source.c
index 30a45cb..ee2203e 100644
--- a/src/pulsecore/source.c
+++ b/src/pulsecore/source.c
@@ -84,7 +84,8 @@ pa_source* pa_source_new(
     s->parent.process_msg = pa_source_process_msg;
 
     s->core = core;
-    s->state = PA_SOURCE_IDLE;
+    s->state = PA_SOURCE_INIT;
+    s->flags = 0;
     s->name = pa_xstrdup(name);
     s->description = NULL;
     s->driver = pa_xstrdup(driver);
@@ -100,8 +101,6 @@ pa_source* pa_source_new(
     s->muted = 0;
     s->refresh_volume = s->refresh_muted = 0;
 
-    s->is_hardware = 0;
-
     s->get_latency = NULL;
     s->set_volume = NULL;
     s->get_volume = NULL;
@@ -111,6 +110,7 @@ pa_source* pa_source_new(
     s->userdata = NULL;
 
     s->asyncmsgq = NULL;
+    s->rtpoll = NULL;
 
     r = pa_idxset_put(core->sources, s, &s->index);
     assert(s->index != PA_IDXSET_INVALID && r >= 0);
@@ -123,13 +123,22 @@ pa_source* pa_source_new(
     s->thread_info.soft_muted = s->muted;
     s->thread_info.state = s->state;
 
-    pa_subscription_post(core, PA_SUBSCRIPTION_EVENT_SOURCE | PA_SUBSCRIPTION_EVENT_NEW, s->index);
-
-    pa_hook_fire(&core->hooks[PA_CORE_HOOK_SOURCE_NEW_POST], s);
-    
     return s;
 }
 
+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);
+
+    s->thread_info.state = s->state = PA_SOURCE_IDLE;
+
+    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);
+}
+
 static int source_set_state(pa_source *s, pa_source_state_t state) {
     int ret;
     
@@ -138,6 +147,21 @@ static int source_set_state(pa_source *s, pa_source_state_t state) {
     if (s->state == state)
         return 0;
 
+    if (state == PA_SOURCE_SUSPENDED && !(s->flags & PA_SOURCE_CAN_SUSPEND))
+        return -1;
+    
+    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;
@@ -146,17 +170,19 @@ static int source_set_state(pa_source *s, pa_source_state_t state) {
         return -1;
 
     s->state = state;
-    pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SOURCE_STATE_CHANGED], s);
+
+    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_disconnect(pa_source *s) {
+void pa_source_unlink(pa_source *s) {
     pa_source_output *o, *j = NULL;
 
     pa_assert(s);
-    pa_return_if_fail(s->state != PA_SOURCE_DISCONNECTED);
+    pa_assert(PA_SOURCE_LINKED(s->state));
 
-    pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SOURCE_DISCONNECT], s);    
+    pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SOURCE_UNLINK], s);    
 
     pa_namereg_unregister(s->core, s->name);
     pa_idxset_remove_by_data(s->core->sources, s, NULL);
@@ -167,7 +193,7 @@ void pa_source_disconnect(pa_source *s) {
         j = o;
     }
 
-    source_set_state(s, PA_SOURCE_DISCONNECTED);
+    source_set_state(s, PA_SOURCE_UNLINKED);
 
     s->get_latency = NULL;
     s->get_volume = NULL;
@@ -178,7 +204,7 @@ void pa_source_disconnect(pa_source *s) {
 
     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_DISCONNECT_POST], s);    
+    pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SOURCE_UNLINK_POST], s);    
 }
 
 static void source_free(pa_object *o) {
@@ -188,8 +214,8 @@ static void source_free(pa_object *o) {
     pa_assert(s);
     pa_assert(pa_source_refcnt(s) == 0);
 
-    if (s->state != PA_SOURCE_DISCONNECTED)
-        pa_source_disconnect(s);
+    if (PA_SOURCE_LINKED(s->state))
+        pa_source_unlink(s);
 
     pa_log_info("Freeing source %u \"%s\"", s->index, s->name);
 
@@ -208,6 +234,7 @@ static void source_free(pa_object *o) {
 
 int pa_source_update_status(pa_source*s) {
     pa_source_assert_ref(s);
+    pa_assert(PA_SOURCE_LINKED(s->state));
 
     if (s->state == PA_SOURCE_SUSPENDED)
         return 0;
@@ -217,6 +244,7 @@ int pa_source_update_status(pa_source*s) {
 
 int pa_source_suspend(pa_source *s, int suspend) {
     pa_source_assert_ref(s);
+    pa_assert(PA_SOURCE_LINKED(s->state));
 
     if (suspend)
         return source_set_state(s, PA_SOURCE_SUSPENDED);
@@ -226,6 +254,7 @@ int pa_source_suspend(pa_source *s, int suspend) {
 
 void pa_source_ping(pa_source *s) {
     pa_source_assert_ref(s);
+    pa_assert(PA_SOURCE_LINKED(s->state));
 
     pa_asyncmsgq_post(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_PING, NULL, 0, NULL, NULL);
 }
@@ -235,6 +264,7 @@ void pa_source_post(pa_source*s, const pa_memchunk *chunk) {
     void *state = NULL;
 
     pa_source_assert_ref(s);
+    pa_assert(PA_SOURCE_OPENED(s->thread_info.state));
     pa_assert(chunk);
 
     if (s->thread_info.state != PA_SOURCE_RUNNING)
@@ -267,6 +297,10 @@ pa_usec_t pa_source_get_latency(pa_source *s) {
     pa_usec_t usec;
 
     pa_source_assert_ref(s);
+    pa_assert(PA_SOURCE_LINKED(s->state));
+
+    if (!PA_SOURCE_OPENED(s->state))
+        return 0;
 
     if (s->get_latency)
         return s->get_latency(s);
@@ -281,6 +315,7 @@ void pa_source_set_volume(pa_source *s, const pa_cvolume *volume) {
     int changed;
 
     pa_source_assert_ref(s);
+    pa_assert(PA_SOURCE_LINKED(s->state));
     pa_assert(volume);
 
     changed = !pa_cvolume_equal(volume, &s->volume);
@@ -298,7 +333,9 @@ void pa_source_set_volume(pa_source *s, const pa_cvolume *volume) {
 
 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;
 
@@ -318,6 +355,7 @@ void pa_source_set_mute(pa_source *s, int mute) {
     int changed;
 
     pa_source_assert_ref(s);
+    pa_assert(PA_SOURCE_LINKED(s->state));
 
     changed = s->muted != mute;
     s->muted = mute;
@@ -336,6 +374,7 @@ int pa_source_get_mute(pa_source *s) {
     int old_muted;
 
     pa_source_assert_ref(s);
+    pa_assert(PA_SOURCE_LINKED(s->state));
 
     old_muted = s->muted;
 
@@ -384,8 +423,16 @@ void pa_source_set_asyncmsgq(pa_source *s, pa_asyncmsgq *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_used_by(pa_source *s) {
     pa_source_assert_ref(s);
+    pa_assert(PA_SOURCE_LINKED(s->state));
 
     return pa_idxset_size(s->outputs);
 }
@@ -393,19 +440,28 @@ unsigned pa_source_used_by(pa_source *s) {
 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(PA_SOURCE_LINKED(s->thread_info.state));
 
     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));
+
+            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);
+
             if (pa_hashmap_remove(s->thread_info.outputs, PA_UINT32_TO_PTR(o->index)))
                 pa_source_output_unref(o);
-            
+
             return 0;
         }
 
@@ -452,3 +508,21 @@ int pa_source_suspend_all(pa_core *c, int suspend) {
 
     return ret;
 }
+
+int pa_source_process_outputs(pa_source *s) {
+    pa_source_output *o;
+    void *state = NULL;
+    int r;
+    
+    pa_source_assert_ref(s);
+
+    if (!PA_SOURCE_LINKED(s->state))
+        return 0;
+    
+    while ((o = pa_hashmap_iterate(s->thread_info.outputs, &state, NULL)))
+        if (o->process)
+            if ((r = o->process(o)))
+                return r;
+
+    return 0;
+}
diff --git a/src/pulsecore/source.h b/src/pulsecore/source.h
index ffe5107..ddc6615 100644
--- a/src/pulsecore/source.h
+++ b/src/pulsecore/source.h
@@ -42,26 +42,36 @@ typedef struct pa_source pa_source;
 #include <pulsecore/module.h>
 #include <pulsecore/asyncmsgq.h>
 #include <pulsecore/msgobject.h>
+#include <pulsecore/rtpoll.h>
 
 #define PA_MAX_OUTPUTS_PER_SOURCE 32
 
 typedef enum pa_source_state {
+    PA_SOURCE_INIT,
     PA_SOURCE_RUNNING,
     PA_SOURCE_SUSPENDED,
     PA_SOURCE_IDLE,
-    PA_SOURCE_DISCONNECTED
+    PA_SOURCE_UNLINKED
 } pa_source_state_t;
 
+static inline int PA_SOURCE_OPENED(pa_source_state_t x) {
+    return x == PA_SOURCE_RUNNING || x == PA_SOURCE_IDLE;
+}
+
+static inline int PA_SOURCE_LINKED(pa_source_state_t x) {
+    return x == PA_SOURCE_RUNNING || x == PA_SOURCE_IDLE || x == PA_SOURCE_SUSPENDED;
+}
+
 struct pa_source {
     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 */
-    int is_hardware;
 
     pa_module *module;                        /* may be NULL */
 
@@ -76,7 +86,7 @@ struct pa_source {
     int refresh_volume;
     int refresh_muted;
 
-    int (*set_state)(pa_source*source, pa_source_state_t state);          /* 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 */
@@ -84,7 +94,10 @@ struct pa_source {
     pa_usec_t (*get_latency)(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;
@@ -111,7 +124,7 @@ typedef enum pa_source_message {
     PA_SOURCE_MESSAGE_MAX
 } pa_source_message_t;
 
-/* To be used exclusively by the source driver */
+/* To be called exclusively by the source driver, from main context */
 
 pa_source* pa_source_new(
         pa_core *core,
@@ -121,18 +134,22 @@ pa_source* pa_source_new(
         const pa_sample_spec *spec,
         const pa_channel_map *map);
 
-void pa_source_disconnect(pa_source *s);
+void pa_source_put(pa_source *s);
+void pa_source_unlink(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);
 
-/* Callable by everyone */
+/* May be called by everyone, from main context */
 
 pa_usec_t pa_source_get_latency(pa_source *s);
 
 int pa_source_update_status(pa_source*s);
 int pa_source_suspend(pa_source *s, int suspend);
+int pa_source_suspend_all(pa_core *c, int suspend);
+
 void pa_source_ping(pa_source *s);
 
 void pa_source_set_volume(pa_source *source, const pa_cvolume *volume);
@@ -143,15 +160,12 @@ int pa_source_get_mute(pa_source *source);
 unsigned pa_source_used_by(pa_source *s);
 #define pa_source_get_state(s) ((pa_source_state_t) (s)->state)
 
-/* To be used exclusively by the source driver thread */
+/* 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);
 
-static inline int PA_SOURCE_OPENED(pa_source_state_t x) {
-    return x == PA_SOURCE_RUNNING || x == PA_SOURCE_IDLE;
-}
+int pa_source_process_outputs(pa_source *o);
 
-int pa_source_suspend_all(pa_core *c, int suspend);
+int pa_source_process_msg(pa_msgobject *o, int code, void *userdata, int64_t, pa_memchunk *chunk);
 
 #endif

commit 241ad047c889755d4b0003f8d149e8aed4639ae9
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Aug 30 22:58:12 2007 +0000

    port module-combine to new core
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1734 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/Makefile.am b/src/Makefile.am
index 0bdc3f7..079610a 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -930,8 +930,8 @@ modlibexec_LTLIBRARIES += \
 		module-sine.la \
 		module-native-protocol-tcp.la \
 		module-native-protocol-fd.la \
-		module-esound-protocol-tcp.la
-#		module-combine.la \
+		module-esound-protocol-tcp.la \
+		module-combine.la
 #		module-tunnel-sink.la \
 #		module-tunnel-source.la \
 #		module-esound-sink.la
@@ -1192,9 +1192,9 @@ module_null_sink_la_LIBADD = $(AM_LIBADD) libpulsecore.la
 
 # Couplings
 
-#module_combine_la_SOURCES = modules/module-combine.c
-#module_combine_la_LDFLAGS = -module -avoid-version
-#module_combine_la_LIBADD = $(AM_LIBADD) libpulsecore.la
+module_combine_la_SOURCES = modules/module-combine.c
+module_combine_la_LDFLAGS = -module -avoid-version
+module_combine_la_LIBADD = $(AM_LIBADD) libpulsecore.la
 
 module_match_la_SOURCES = modules/module-match.c
 module_match_la_LDFLAGS = -module -avoid-version
diff --git a/src/modules/module-combine.c b/src/modules/module-combine.c
index b6d718d..c4fab45 100644
--- a/src/modules/module-combine.c
+++ b/src/modules/module-combine.c
@@ -25,12 +25,13 @@
 #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>
@@ -40,6 +41,12 @@
 #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,95 +84,135 @@ static const char* const valid_modargs[] = {
 
 struct output {
     struct userdata *userdata;
+    pa_sink *sink;
     pa_sink_input *sink_input;
-    size_t counter;
+
+    pa_asyncmsgq *asyncmsgq;
+    pa_rtpoll_item *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;
+
+    pa_thread *thread;
+    pa_thread_mq thread_mq;
+    pa_rtpoll *rtpoll;
+
+    pa_mutex *mutex;
+    
     struct output *master;
-    pa_time_event *time_event;
-    uint32_t adjust_time;
 
-    PA_LLIST_HEAD(struct output, outputs);
+    pa_time_event *time_event; 
+    uint32_t adjust_time; 
+
+    int automatic;
+    size_t block_size;
+
+    struct timespec timestamp;
+
+    pa_hook_slot *sink_new_slot, *sink_unlink_slot, *sink_state_changed_slot;
+
+    pa_resample_method_t resample_method;
+
+    struct timespec adjust_timestamp;
+    
+    pa_idxset* outputs; /* managed in main context */
+
+    struct {
+        PA_LLIST_HEAD(struct output, outputs); /* managed in IO thread context */
+        struct output *master;
+    } thread_info;
 };
 
-static void output_free(struct output *o);
-static void clear_up(struct userdata *u);
+enum {
+    SINK_MESSAGE_DETACH = PA_SINK_MESSAGE_MAX,
+    SINK_MESSAGE_ATTACH,
+    SINK_MESSAGE_ADD_OUTPUT,
+    SINK_MESSAGE_REMOVE_OUTPUT
+};
 
-static void update_usage(struct userdata *u) {
-    pa_module_set_used(u->module, u->sink ? pa_sink_used_by(u->sink) : 0);
-}
+static void output_free(struct output *o);
+static int output_create_sink_input(struct userdata *u, struct output *o);
+static int update_master(struct userdata *u, struct output *o);
+static int pick_master(struct userdata *u);
 
 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);
 
-        o->total_latency = sink_latency + pa_sink_input_get_latency(o->sink_input);
+    if (pa_idxset_size(u->outputs) <= 0)
+        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)) {
+        uint32_t sink_latency;
+
+        if (!o->sink_input || !PA_SINK_OPENED(pa_sink_get_state(o->sink)))
+            continue;
 
+        sink_latency = o->sink_input->sink ? pa_sink_get_latency(o->sink_input->sink) : 0;
+        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)
             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 is %s", u->sink->name, u->master->sink->description);
+        
     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);
         else if (o->total_latency > target_latency)
             r += (uint32_t) (((((double) o->total_latency - target_latency))/u->adjust_time)*r/ 1000000);
-
-        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);
-
-    update_usage(u);
-
-    if (pa_sink_render(u->sink, RENDER_SIZE, &chunk) < 0)
-        return;
-
-    for (o = u->outputs; o; o = o->next)
-        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) {
+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;
-    assert(u && a && u->time_event == e);
+    
+    pa_assert(u);
+    pa_assert(a);
+    pa_assert(u->time_event == e);
 
     adjust_rates(u);
 
@@ -175,166 +221,735 @@ static void time_callback(pa_mainloop_api*a, pa_time_event* e, PA_GCC_UNUSED con
     u->sink->core->mainloop->time_restart(e, &n);
 }
 
+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);
+
+    /* This is only run when were are in NULL mode, to make sure that
+     * playback doesn't stop. In all other cases we hook our stuff
+     * into the master sink. */
+    
+    for (;;) {
+        int ret;
+
+        /* Render some data and drop it immediately */
+        if (u->sink->thread_info.state == PA_SINK_RUNNING) {
+            struct timespec now;
+            
+            pa_rtclock_get(&now);
+
+            if (pa_timespec_cmp(&u->timestamp, &now) <= 0) {
+                pa_sink_skip(u->sink, u->block_size);
+                pa_timespec_add(&u->timestamp, pa_bytes_to_usec(u->block_size, &u->sink->sample_spec));
+            }
+
+            pa_rtpoll_set_timer_absolute(u->rtpoll, &u->timestamp);
+        } else
+            pa_rtpoll_set_timer_disabled(u->rtpoll);
+
+        /* Now give the sink inputs some to time to process their data */
+        if ((ret = pa_sink_process_inputs(u->sink)) < 0)
+            goto fail;
+        if (ret > 0)
+            continue;
+
+        /* Check whether there is a message for us to process */
+        if ((ret = pa_thread_mq_process(&u->thread_mq) < 0))
+            goto finish;
+        if (ret > 0)
+            continue;
+
+        /* Hmm, nothing to do. Let's sleep */
+        if (pa_rtpoll_run(u->rtpoll) < 0) {
+            pa_log("poll() failed: %s", pa_cstrerror(errno));
+            goto fail;
+        }
+    }
+
+fail:
+    /* We have to continue processing messages until we receive the
+     * SHUTDOWN message */
+    pa_asyncmsgq_post(u->thread_mq.outq, PA_MSGOBJECT(u->core), PA_CORE_MESSAGE_UNLOAD_MODULE, u->module, 0, NULL, NULL);
+    pa_asyncmsgq_wait_for(u->thread_mq.inq, PA_MESSAGE_SHUTDOWN);
+
+finish:
+    pa_log_debug("Thread shutting down");
+}
+
+static void request_memblock(struct output *o) {
+    pa_memchunk chunk;
+    
+    pa_assert(o);
+    pa_sink_input_assert_ref(o->sink_input);
+    pa_sink_assert_ref(o->userdata->sink);
+    
+    /* If another thread already prepared some data we received
+     * the data over the asyncmsgq, hence let's first process
+     * it. */
+    while (pa_asyncmsgq_get(o->asyncmsgq, NULL, NULL, NULL, NULL, &chunk, 0) == 0) {
+        pa_memblockq_push_align(o->memblockq, &chunk);
+        pa_asyncmsgq_done(o->asyncmsgq, 0);
+    }
+    
+    /* Check whether we're now readable */
+    if (pa_memblockq_is_readable(o->memblockq))
+        return;
+    
+    /* OK, we need to prepare new data */
+    pa_mutex_lock(o->userdata->mutex);
+
+    if (PA_SINK_OPENED(o->userdata->sink->thread_info.state)) {
+    
+        /* Maybe there's some data now? */
+        while (pa_asyncmsgq_get(o->asyncmsgq, NULL, NULL, NULL, NULL, &chunk, 0) == 0) {
+            pa_memblockq_push_align(o->memblockq, &chunk);
+            pa_asyncmsgq_done(o->asyncmsgq, 0);
+        }
+        
+        /* Ok, now let's prepare some data if we really have to */
+        while (!pa_memblockq_is_readable(o->memblockq)) {
+            struct output *j;
+            
+            /* Do it! */
+            pa_sink_render(o->userdata->sink, o->userdata->block_size, &chunk);
+            
+            /* OK, let's send this data to the other threads */
+            for (j = o->userdata->thread_info.outputs; j; j = j->next)
+                if (j != o && j->sink_input)
+                    pa_asyncmsgq_post(j->asyncmsgq, NULL, 0, NULL, 0, &chunk, NULL);
+            
+            /* And push it into our own queue */
+            pa_memblockq_push_align(o->memblockq, &chunk);
+            pa_memblock_unref(chunk.memblock);
+        }
+    }
+    
+    pa_mutex_unlock(o->userdata->mutex);
+}
+
+/* Called from I/O trhead context */
 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);
+    struct output *o;
 
-    if (pa_memblockq_peek(o->memblockq, chunk) >= 0)
-        return 0;
+    pa_sink_input_assert_ref(i);
+    o = i->userdata;
+    pa_assert(o);
 
-    /* Try harder */
-    request_memblock(o->userdata);
+    /* If necessary, get some new data */
+    request_memblock(o);
 
-    return pa_memblockq_peek(o->memblockq, chunk);
+    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);
+    o = i->userdata;
+    pa_assert(o);
 
-    pa_memblockq_drop(o->memblockq, chunk, length);
-    o->counter += length;
+    pa_memblockq_drop(o->memblockq, length);
 }
 
+/* Called from I/O thread context */
+static int sink_input_process_cb(pa_sink_input *i) {
+    struct output *o;
+    pa_memchunk chunk;
+    int r = 0;
+    
+    pa_sink_input_assert_ref(i);
+    o = i->userdata;
+    pa_assert(o);
+
+    /* Move all data in the asyncmsgq into our memblockq */
+    
+    while (pa_asyncmsgq_get(o->asyncmsgq, NULL, NULL, NULL, NULL, &chunk, 0) == 0) {
+        if (PA_SINK_OPENED(i->sink->thread_info.state))
+            pa_memblockq_push_align(o->memblockq, &chunk);
+        pa_asyncmsgq_done(o->asyncmsgq, 0);
+    }
+
+    /* If the sink is suspended, flush our queue */
+    if (!PA_SINK_OPENED(i->sink->thread_info.state))
+        pa_memblockq_flush(o->memblockq);
+
+    if (o == o->userdata->thread_info.master) {
+        pa_mutex_lock(o->userdata->mutex);
+        r = pa_sink_process_inputs(o->userdata->sink);
+        pa_mutex_unlock(o->userdata->mutex);
+    }
+    
+    return r;
+}
+
+/* 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);
+    o = i->userdata;
+    pa_assert(o);
+
+    pa_assert(!o->rtpoll_item);
+    o->rtpoll_item = pa_rtpoll_item_new_asyncmsgq(i->sink->rtpoll, o->asyncmsgq);
+}
+
+/* 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);
+    o = i->userdata;
+    pa_assert(o);
+
+    pa_assert(o->rtpoll_item);
+    pa_rtpoll_item_free(o->rtpoll_item);
+    o->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);
+    o = i->userdata;
+    pa_assert(o);
+
+    pa_sink_input_unlink(o->sink_input);
+    pa_sink_input_unref(o->sink_input);
+    o->sink_input = NULL;
+    
     pa_module_unload_request(o->userdata->module);
-    clear_up(o->userdata);
 }
 
-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 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;
+        }
 
-    return pa_bytes_to_usec(pa_memblockq_get_length(o->memblockq), &i->sample_spec);
+    }
+    
+    return pa_sink_input_process_msg(obj, code, data, offset, chunk);
 }
 
-static pa_usec_t sink_get_latency_cb(pa_sink *s) {
-    struct userdata *u = s->userdata;
-    assert(s && u && u->sink && u->master);
+static int 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)) {
+        pa_sink_input_unlink(o->sink_input);
+        pa_sink_input_unref(o->sink_input);
+        o->sink_input = NULL;
+    }
 
-    return
-        pa_sink_input_get_latency(u->master->sink_input) +
-        pa_sink_get_latency(u->master->sink_input->sink);
+    if (pick_master(u) < 0)
+        pa_module_unload_request(u->module);
+
+    pa_log_info("Device suspended...");
+    
+    return 0;
 }
 
-static void sink_notify(pa_sink *s) {
-    struct userdata *u;
+static int 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)) {
+            
+        if (output_create_sink_input(u, o) < 0)
+            output_free(o);
+        else
+            pa_sink_input_put(o->sink_input);
+    }
+
+    if (pick_master(u) < 0)
+        pa_module_unload_request(u->module);
+    
+    pa_log_info("Resumed successfully...");
+    return 0;
+}
+
+static int sink_set_state(pa_sink *sink, pa_sink_state_t state) {
+    struct userdata *u;
+    
+    pa_sink_assert_ref(sink);
+    u = sink->userdata;
+    pa_assert(u);
+
+    /* 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)));
+            
+            if (suspend(u) < 0)
+                return -1;
+
+            break;
+
+        case PA_SINK_IDLE:
+        case PA_SINK_RUNNING:
+
+            if (pa_sink_get_state(u->sink) == PA_SINK_SUSPENDED) {
+                if (unsuspend(u) < 0)
+                    return -1;
+            }
+                    
+            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:
+
+            if ((pa_sink_state_t) PA_PTR_TO_UINT(data) == PA_SINK_RUNNING) {
+                /* Only useful when running in NULL mode, i.e. when no
+                 * master sink is attached */       
+                pa_rtclock_get(&u->timestamp);
+            }
+            
+            break;
+            
+        case PA_SINK_MESSAGE_GET_LATENCY: {
+            struct timespec now;
+
+            /* This code will only be called when running in NULL
+             * mode, i.e. when no master sink is attached. See
+             * sink_get_latency_cb() below */
+            pa_rtclock_get(&now);
+            
+            if (pa_timespec_cmp(&u->timestamp, &now) > 0)
+                *((pa_usec_t*) data) = 0;
+            else
+                *((pa_usec_t*) data) = pa_timespec_diff(&u->timestamp, &now);
+            break;
+        }
+
+        case SINK_MESSAGE_DETACH: {
+            pa_sink_input *i;
+            void *state = NULL;
+
+            /* We're detaching all our input streams artificially, so
+             * that we can driver our sink from a different sink */
+
+            while ((i = pa_hashmap_iterate(u->sink->thread_info.inputs, &state, NULL)))
+                if (i->detach)
+                    i->detach(i);
+
+            u->thread_info.master = NULL;
+            
+            break;
+        }
 
-    assert(s);
+        case SINK_MESSAGE_ATTACH: {
+            pa_sink_input *i;
+            void *state = NULL;
+
+            /* We're attached all our input streams artificially again */
+
+            while ((i = pa_hashmap_iterate(u->sink->thread_info.inputs, &state, NULL)))
+                if (i->attach)
+                    i->attach(i);
+
+            u->thread_info.master = data;
+            
+            break;
+        }
+
+        case SINK_MESSAGE_ADD_OUTPUT:
+            PA_LLIST_PREPEND(struct output, u->thread_info.outputs, (struct output*) data);
+            break;
+
+        case SINK_MESSAGE_REMOVE_OUTPUT:
+            PA_LLIST_REMOVE(struct output, u->thread_info.outputs, (struct output*) data);
+            break;
+    }
+    
+    return pa_sink_process_msg(o, code, data, offset, chunk);
+}
+
+/* Called from main context */
+static pa_usec_t sink_get_latency_cb(pa_sink *s) {
+    struct userdata *u;
+
+    pa_sink_assert_ref(s);
     u = s->userdata;
-    assert(u);
+    pa_assert(u);
+
+    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_input->sink);
+        
+    } else {
+        pa_usec_t usec;
+
+        /* 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);
 
-    for (o = u->outputs; o; o = o->next)
-        pa_sink_notify(o->sink_input->sink);
+    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 struct output *output_new(struct userdata *u, pa_sink *sink, int resample_method) {
-    struct output *o = NULL;
-    char t[256];
-    pa_sink_input_new_data data;
+static int update_master(struct userdata *u, struct output *o) {
+    pa_assert(u);
 
-    assert(u && sink && u->sink);
+    /* Make sure everything is detached from the old thread before we move our stuff to a new thread */
+    if (u->sink && PA_SINK_LINKED(pa_sink_get_state(u->sink)))
+        pa_asyncmsgq_send(u->sink->asyncmsgq, PA_MSGOBJECT(u->sink), SINK_MESSAGE_DETACH, NULL, 0, NULL);
+    
+    if (o) {
+        /* If we have a master sink we run our own sink in its thread */
+
+        pa_assert(o->sink_input);
+        pa_assert(PA_SINK_OPENED(pa_sink_get_state(o->sink)));
+        
+        if (u->thread) {
+            /* If we previously were in NULL mode, let's kill the thread */
+            pa_asyncmsgq_send(u->thread_mq.inq, NULL, PA_MESSAGE_SHUTDOWN, NULL, 0, NULL);
+            pa_thread_free(u->thread);
+            u->thread = NULL;
+
+            pa_assert(u->rtpoll);
+            pa_rtpoll_free(u->rtpoll);
+            u->rtpoll = NULL;
+        }
 
-    o = pa_xmalloc(sizeof(struct output));
-    o->userdata = u;
+        pa_sink_set_asyncmsgq(u->sink, o->sink->asyncmsgq);
+        pa_sink_set_rtpoll(u->sink, o->sink->rtpoll);
+        u->master = o;
 
-    o->counter = 0;
-    o->memblockq = pa_memblockq_new(
-            0,
-            MEMBLOCKQ_MAXLENGTH,
-            MEMBLOCKQ_MAXLENGTH,
-            pa_frame_size(&u->sink->sample_spec),
-            1,
-            0,
-            NULL);
+        pa_log_info("Master sink is now '%s'", o->sink_input->sink->name);
 
-    pa_snprintf(t, sizeof(t), "Output stream #%u of sink %s", u->n_outputs+1, u->sink->name);
+    } else {
 
+        /* We have no master sink, let's create our own thread */
+        
+        pa_sink_set_asyncmsgq(u->sink, u->thread_mq.inq);
+        u->master = NULL;
+
+        if (!u->thread) {
+            pa_assert(!u->rtpoll);
+            
+            u->rtpoll = pa_rtpoll_new();
+            pa_rtpoll_item_new_asyncmsgq(u->rtpoll, u->thread_mq.inq);
+
+            pa_sink_set_rtpoll(u->sink, u->rtpoll);
+            
+            if (!(u->thread = pa_thread_new(thread_func, u))) {
+                pa_log("Failed to create thread.");
+                return -1;
+            }
+        }
+        
+        pa_log_info("No suitable master sink found, going to NULL mode\n");
+    }
+
+    /* Now attach everything again */
+    if (u->sink && PA_SINK_LINKED(pa_sink_get_state(u->sink)))
+        pa_asyncmsgq_send(u->sink->asyncmsgq, PA_MSGOBJECT(u->sink), SINK_MESSAGE_ATTACH, u->master, 0, NULL);
+
+    return 0;
+}
+
+static int pick_master(struct userdata *u) {
+    struct output *o;
+    uint32_t idx;
+    pa_assert(u);
+
+    if (u->master && u->master->sink_input && PA_SINK_OPENED(pa_sink_get_state(u->master->sink)))
+        return update_master(u, u->master);
+
+    for (o = pa_idxset_first(u->outputs, &idx); o; o = pa_idxset_next(u->outputs, &idx))
+        if (o->sink_input && PA_SINK_OPENED(pa_sink_get_state(o->sink)))
+            return update_master(u, o);
+
+    return update_master(u, NULL);
+}
+
+static int output_create_sink_input(struct userdata *u, struct output *o) {
+    pa_sink_input_new_data data;
+    char *t;
+    
+    pa_assert(u);
+    pa_assert(!o->sink_input);
+
+    t = pa_sprintf_malloc("Simultaneous output on %s", o->sink->description);
+    
     pa_sink_input_new_data_init(&data);
-    data.sink = sink;
+    data.sink = o->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 (!(o->sink_input = pa_sink_input_new(u->core, &data, PA_SINK_INPUT_VARIABLE_RATE)))
-        goto fail;
+    o->sink_input = pa_sink_input_new(u->core, &data, PA_SINK_INPUT_VARIABLE_RATE|PA_SINK_INPUT_DONT_MOVE);
 
-    o->sink_input->get_latency = sink_input_get_latency_cb;
+    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->process = sink_input_process_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, int resample_method) {
+    struct output *o;
+
+    pa_assert(u);
+    pa_assert(sink);
+    pa_assert(u->sink);
+
+    o = pa_xnew(struct output, 1);
+    o->userdata = u;
+    o->asyncmsgq = pa_asyncmsgq_new(0);
+    o->rtpoll_item = NULL;
+    o->sink = sink;
+    o->sink_input = NULL;
+    o->memblockq = pa_memblockq_new(
+            0,
+            MEMBLOCKQ_MAXLENGTH,
+            MEMBLOCKQ_MAXLENGTH,
+            pa_frame_size(&u->sink->sample_spec),
+            1,
+            0,
+            NULL);
+
+
+    update_description(u);
+
+    pa_assert_se(pa_idxset_put(u->outputs, o, NULL) == 0);
+    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
+        PA_LLIST_PREPEND(struct output, u->thread_info.outputs, o);
+
+    if (PA_SINK_OPENED(pa_sink_get_state(sink)))
+        if (output_create_sink_input(u, o) < 0)
+            goto fail;
 
-    PA_LLIST_PREPEND(struct output, u->outputs, o);
-    u->n_outputs++;
     return o;
 
 fail:
 
     if (o) {
         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->asyncmsgq)
+            pa_asyncmsgq_unref(o->asyncmsgq);
+
         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, u->resample_method))) {
+        pa_log("Failed to create sink input on sink '%s'.", s->name);
+        return PA_HOOK_OK;
+    }
+
+    if (pick_master(u) < 0)
+        pa_module_unload_request(u->module);
+    
+    if (o->sink_input)
+        pa_sink_input_put(o->sink_input);
+        
+    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;
+    
+    pa_assert(c);
+    pa_sink_assert_ref(s);
+    pa_assert(u);
+
+    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;
+
+    pa_log_info("Unconfiguring sink: %s", s->name);
+    
+    output_free(o);
+
+    if (pick_master(u) < 0)
+        pa_module_unload_request(u->module);
+    
+    return PA_HOOK_OK;
+}
 
-    if (u->time_event) {
-        u->core->mainloop->time_free(u->time_event);
-        u->time_event = NULL;
-    }
+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;
 
-    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;
+
+    state = pa_sink_get_state(s);
+    
+    if (PA_SINK_OPENED(state) && !o->sink_input) {
+        output_create_sink_input(u, o);
+
+        if (pick_master(u) < 0)
+            pa_module_unload_request(u->module);
+
+        if (o->sink_input)
+            pa_sink_input_put(o->sink_input);
     }
+        
+    if (state == PA_SINK_SUSPENDED && o->sink_input) {
+        pa_sink_input_unlink(o->sink_input);
+        pa_sink_input_unref(o->sink_input);
+        o->sink_input = NULL;
+
+        pa_memblockq_flush(o->memblockq);
+
+        if (pick_master(u) < 0)
+            pa_module_unload_request(u->module);
+    }
+
+    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;
+    pa_sink *master_sink = NULL;
     int resample_method = -1;
     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,115 +964,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);
-
+    u->thread_info.master = u->master = NULL;
+    u->time_event = NULL; 
+    u->adjust_time = DEFAULT_ADJUST_TIME; 
+    u->mutex = pa_mutex_new(0);
+    pa_thread_mq_init(&u->thread_mq, m->core->mainloop);
+    u->rtpoll = NULL;
+    u->thread = NULL;
+    PA_LLIST_HEAD_INIT(struct output, u->thread_info.outputs);
+    u->resample_method = resample_method;
+    u->outputs = pa_idxset_new(NULL, NULL);
+    pa_timespec_reset(&u->adjust_timestamp);
+    
     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 = 0;
+    } else {
+        master_sink = NULL;
+        ss = m->core->default_sample_spec;
+        u->automatic = 1;
     }
 
-    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.");
+        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;
-    }
-
-    split_state = NULL;
-    while ((n = pa_split(slaves, ",", &split_state))) {
-        pa_sink *slave_sink;
-
-        if (!(slave_sink = pa_namereg_get(c, n, PA_NAMEREG_SINK, 1))) {
-            pa_log("invalid slave sink '%s'", n);
+    u->sink->flags = PA_SINK_CAN_SUSPEND|PA_SINK_LATENCY;
+    pa_sink_set_module(u->sink, m);
+    pa_sink_set_description(u->sink, "Simultaneous output");
+
+    u->block_size = pa_bytes_per_second(&ss) / 20; /* 50 ms */
+    if (u->block_size <= 0)
+        u->block_size = pa_frame_size(&ss);
+    
+    if (!u->automatic) {
+        const char*split_state;
+        char *n = NULL;
+        pa_assert(slaves);
+
+        /* The master and slaves have been specified manually */
+        
+        if (!(u->master = output_new(u, master_sink, resample_method))) {
+            pa_log("Failed to create master sink input on sink '%s'.", master_sink->name);
             goto fail;
         }
+    
+        split_state = NULL;
+        while ((n = pa_split(slaves, ",", &split_state))) {
+            pa_sink *slave_sink;
+            
+            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, resample_method)) {
+                pa_log("Failed to create slave sink input on sink '%s'.", slave_sink->name);
+                goto fail;
+            }
+        }
 
-        pa_xfree(n);
+        if (pa_idxset_size(u->outputs) <= 1)
+            pa_log_warn("WARNING: No slave sinks specified.");
 
-        if (!output_new(u, slave_sink, resample_method)) {
-            pa_log("failed to create slave sink input on sink '%s'.", slave_sink->name);
-            goto fail;
+        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, resample_method)) {
+                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);
+    
+    if (pick_master(u) < 0)
+        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))
+        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);
+
+    if (o->userdata) {
+        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_REMOVE_OUTPUT, o, 0, NULL);
+        else
+            PA_LLIST_REMOVE(struct output, o->userdata->thread_info.outputs, o);
+    }
+
+    pa_assert_se(pa_idxset_remove_by_data(o->userdata->outputs, o, NULL));
+
+    if (o->userdata->master == o) {
+        /* Make sure the master points to a different output */
+        o->userdata->master = NULL;
+        pick_master(o->userdata);
+    }
+    
+    update_description(o->userdata);
+    
+    if (o->sink_input) {
+        pa_sink_input_unlink(o->sink_input);
+        pa_sink_input_unref(o->sink_input);
+    }
+
+    if (o->rtpoll_item)
+        pa_rtpoll_item_free(o->rtpoll_item);
+
+    if (o->memblockq)
+        pa_memblockq_free(o->memblockq);
+
+    if (o->asyncmsgq)
+        pa_asyncmsgq_unref(o->asyncmsgq);
+    
+    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);
+    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->sink)
+        pa_sink_unlink(u->sink);
+
+    if (u->outputs) {
+        while ((o = pa_idxset_first(u->outputs, NULL)))
+            output_free(o);
+        
+        pa_idxset_free(u->outputs, NULL, NULL);
+    }
+
+    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_mutex_free(u->mutex);
+        
     pa_xfree(u);
 }
 

commit f59dd18fe62de0549fb2cffbd14d0da928c0b118
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Aug 31 00:22:31 2007 +0000

    - fix suspend handling
    - set sink description properly
    - honour resample_method setting
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1735 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-combine.c b/src/modules/module-combine.c
index c4fab45..3e56bc6 100644
--- a/src/modules/module-combine.c
+++ b/src/modules/module-combine.c
@@ -462,9 +462,12 @@ static int suspend(struct userdata *u) {
     /* Let's suspend by unlinking all streams */
     
     for (o = pa_idxset_first(u->outputs, &idx); o; o = pa_idxset_next(u->outputs, &idx)) {
-        pa_sink_input_unlink(o->sink_input);
-        pa_sink_input_unref(o->sink_input);
-        o->sink_input = NULL;
+
+        if (o->sink_input) {
+            pa_sink_input_unlink(o->sink_input);
+            pa_sink_input_unref(o->sink_input);
+            o->sink_input = NULL;
+        }
     }
 
     if (pick_master(u) < 0)
@@ -484,11 +487,15 @@ static int unsuspend(struct userdata *u) {
     /* Let's resume */
     
     for (o = pa_idxset_first(u->outputs, &idx); o; o = pa_idxset_next(u->outputs, &idx)) {
-            
-        if (output_create_sink_input(u, o) < 0)
-            output_free(o);
-        else
-            pa_sink_input_put(o->sink_input);
+
+        pa_sink_suspend(o->sink, 0);
+        
+        if (PA_SINK_OPENED(pa_sink_get_state(o->sink))) {
+            if (output_create_sink_input(u, o) < 0)
+                output_free(o);
+            else
+                pa_sink_input_put(o->sink_input);
+        }
     }
 
     if (pick_master(u) < 0)
@@ -765,7 +772,8 @@ static int output_create_sink_input(struct userdata *u, struct output *o) {
     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;
-
+    data.resample_method = u->resample_method;
+    
     o->sink_input = pa_sink_input_new(u->core, &data, PA_SINK_INPUT_VARIABLE_RATE|PA_SINK_INPUT_DONT_MOVE);
 
     pa_xfree(t);
@@ -785,7 +793,7 @@ static int output_create_sink_input(struct userdata *u, struct output *o) {
     return 0;
 }
 
-static struct output *output_new(struct userdata *u, pa_sink *sink, int resample_method) {
+static struct output *output_new(struct userdata *u, pa_sink *sink) {
     struct output *o;
 
     pa_assert(u);
@@ -808,17 +816,22 @@ static struct output *output_new(struct userdata *u, pa_sink *sink, int resample
             NULL);
 
 
+    pa_assert_se(pa_idxset_put(u->outputs, o, NULL) == 0);
+
     update_description(u);
 
-    pa_assert_se(pa_idxset_put(u->outputs, o, NULL) == 0);
     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
         PA_LLIST_PREPEND(struct output, u->thread_info.outputs, o);
 
-    if (PA_SINK_OPENED(pa_sink_get_state(sink)))
-        if (output_create_sink_input(u, o) < 0)
-            goto fail;
+    if (PA_SINK_OPENED(pa_sink_get_state(u->sink)) || pa_sink_get_state(u->sink) == PA_SINK_INIT) {
+        pa_sink_suspend(sink, 0);
+    
+        if (PA_SINK_OPENED(pa_sink_get_state(sink)))
+            if (output_create_sink_input(u, o) < 0)
+                goto fail;
+    }
 
     return o;
 
@@ -855,7 +868,7 @@ static pa_hook_result_t sink_new_hook_cb(pa_core *c, pa_sink *s, struct userdata
 
     pa_log_info("Configuring new sink: %s", s->name);
     
-    if (!(o = output_new(u, s, u->resample_method))) {
+    if (!(o = output_new(u, s))) {
         pa_log("Failed to create sink input on sink '%s'.", s->name);
         return PA_HOOK_OK;
     }
@@ -914,7 +927,7 @@ static pa_hook_result_t sink_state_changed_hook_cb(pa_core *c, pa_sink *s, struc
 
     state = pa_sink_get_state(s);
     
-    if (PA_SINK_OPENED(state) && !o->sink_input) {
+    if (PA_SINK_OPENED(state) && PA_SINK_OPENED(pa_sink_get_state(u->sink)) && !o->sink_input) {
         output_create_sink_input(u, o);
 
         if (pick_master(u) < 0)
@@ -943,7 +956,7 @@ int pa__init(pa_module*m) {
     pa_modargs *ma = NULL;
     const char *master_name, *slaves, *rm;
     pa_sink *master_sink = NULL;
-    int resample_method = -1;
+    int resample_method = PA_RESAMPLER_TRIVIAL;
     pa_sample_spec ss;
     pa_channel_map map;
     struct output *o;
@@ -1051,7 +1064,7 @@ int pa__init(pa_module*m) {
 
         /* The master and slaves have been specified manually */
         
-        if (!(u->master = output_new(u, master_sink, resample_method))) {
+        if (!(u->master = output_new(u, master_sink))) {
             pa_log("Failed to create master sink input on sink '%s'.", master_sink->name);
             goto fail;
         }
@@ -1068,7 +1081,7 @@ int pa__init(pa_module*m) {
             
             pa_xfree(n);
             
-            if (!output_new(u, slave_sink, resample_method)) {
+            if (!output_new(u, slave_sink)) {
                 pa_log("Failed to create slave sink input on sink '%s'.", slave_sink->name);
                 goto fail;
             }
@@ -1090,7 +1103,7 @@ int pa__init(pa_module*m) {
             if (!(s->flags & PA_SINK_HARDWARE) || s == u->sink)
                 continue;
 
-            if (!output_new(u, s, resample_method)) {
+            if (!output_new(u, s)) {
                 pa_log("Failed to create sink input on sink '%s'.", s->name);
                 goto fail;
             }
@@ -1104,12 +1117,14 @@ int pa__init(pa_module*m) {
     
     if (pick_master(u) < 0)
         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))
-        pa_sink_input_put(o->sink_input);
     
+    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);

commit c627871fdb379761a3c75e8d191cc5b63e63be63
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Aug 31 00:22:58 2007 +0000

    replace a pa_assert() by an pa_assert_se()
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1736 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/daemon/main.c b/src/daemon/main.c
index 7bdf65c..b927b2a 100644
--- a/src/daemon/main.c
+++ b/src/daemon/main.c
@@ -554,7 +554,7 @@ int main(int argc, char *argv[]) {
 #endif
     }
 
-    pa_assert(chdir("/") == 0);
+    pa_assert_se(chdir("/") == 0);
     umask(0022);
 
     if (conf->system_instance) {

commit 6eb2f88c5dc4c74634774aa242961b1630c0419c
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Aug 31 00:51:01 2007 +0000

    add two new functions pa_make_path_absolute()/pa_getcwd()
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1737 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/core-util.c b/src/pulsecore/core-util.c
index 2c5a32e..82c0ea3 100644
--- a/src/pulsecore/core-util.c
+++ b/src/pulsecore/core-util.c
@@ -1208,3 +1208,36 @@ char *pa_truncate_utf8(char *c, size_t l) {
     
     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;
+}
diff --git a/src/pulsecore/core-util.h b/src/pulsecore/core-util.h
index ea571e7..5474928 100644
--- a/src/pulsecore/core-util.h
+++ b/src/pulsecore/core-util.h
@@ -97,6 +97,9 @@ 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);
+
 static inline int pa_is_power_of_two(unsigned n) {
     return !(n & (n - 1));
 }

commit a1322269d5e1ea76eae07cd62ea0b70ff384e9c5
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Aug 31 00:51:26 2007 +0000

    minor reformatting
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1738 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/cli-command.c b/src/pulsecore/cli-command.c
index 7440e74..0cd1f48 100644
--- a/src/pulsecore/cli-command.c
+++ b/src/pulsecore/cli-command.c
@@ -1131,9 +1131,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);

commit 02811bfc0fff316dada8c543326720dbabe0904a
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Aug 31 00:52:42 2007 +0000

    make sure that we make include paths absolute before calling chdir()
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1739 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/daemon/cmdline.c b/src/daemon/cmdline.c
index 705115e..384dde3 100644
--- a/src/daemon/cmdline.c
+++ b/src/daemon/cmdline.c
@@ -199,9 +199,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");

commit 718b1d2a56e7010c1454bc480aa52b0e4717fe29
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Aug 31 10:45:16 2007 +0000

    add pa_channel_position_to_pretty_string() for usage in pavucontrol/pavumeter
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1740 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulse/channelmap.c b/src/pulse/channelmap.c
index 5f1fa95..c53626f 100644
--- a/src/pulse/channelmap.c
+++ b/src/pulse/channelmap.c
@@ -90,13 +90,76 @@ 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) {
@@ -342,6 +405,13 @@ 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;
 

commit 1df817cb0a7dfbcb6588df1b1b08786f825b7138
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Aug 31 10:45:49 2007 +0000

    add pa_channel_position_to_pretty_string() to header
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1741 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulse/channelmap.h b/src/pulse/channelmap.h
index f0c8f47..bb8ce95 100644
--- a/src/pulse/channelmap.h
+++ b/src/pulse/channelmap.h
@@ -174,6 +174,9 @@ pa_channel_map* pa_channel_map_init_auto(pa_channel_map *m, unsigned channels, p
 /** Return a text label for the specified channel position */
 const char* pa_channel_position_to_string(pa_channel_position_t pos);
 
+/** 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
 

commit fe1f55b877909a831f69497b53f2a64b952cd47d
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sun Sep 2 20:34:57 2007 +0000

    add a couple of macros for memory page alignment
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1742 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/macro.h b/src/pulsecore/macro.h
index efd0f5e..53e52fd 100644
--- a/src/pulsecore/macro.h
+++ b/src/pulsecore/macro.h
@@ -25,15 +25,39 @@
 ***/
 
 #include <sys/types.h>
+#include <unistd.h>
 #include <assert.h>
+#include <limits.h>
+#include <unistd.h>  
+
 #include <pulsecore/log.h>
 
+#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]))
 
 #define SA_MAX(a, b) ((a) > (b) ? (a) : (b))

commit b54e71a96a250783979dd5abe30e4f818f36e062
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sun Sep 2 20:35:36 2007 +0000

    make use of new memory page alignment macros, reindent
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1743 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/shm.c b/src/pulsecore/shm.c
index 8ef02f6..38187dd 100644
--- a/src/pulsecore/shm.c
+++ b/src/pulsecore/shm.c
@@ -43,6 +43,7 @@
 #include <pulsecore/log.h>
 #include <pulsecore/random.h>
 #include <pulsecore/core-util.h>
+#include <pulsecore/macro.h>
 #include <pulse/xmalloc.h>
 
 #include "shm.h"
@@ -80,7 +81,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;
             }
@@ -140,42 +141,43 @@ void pa_shm_free(pa_shm *m) {
     assert(m->size > 0);
 
 #ifdef MAP_FAILED
-        assert(m->ptr != MAP_FAILED);
+    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 (m->do_unlink) {
-                    char fn[32];
-
-                    segment_name(fn, sizeof(fn), m->id);
-
-                    if (shm_unlink(fn) < 0)
-                        pa_log(" shm_unlink(%s) failed: %s", fn, 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];
+            
+            segment_name(fn, sizeof(fn), m->id);
+            
+            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);
@@ -183,28 +185,21 @@ void pa_shm_punch(pa_shm *m, size_t offset, size_t size) {
     assert(offset+size <= m->size);
 
 #ifdef MAP_FAILED
-        assert(m->ptr != MAP_FAILED);
+    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)
@@ -217,7 +212,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
 }
 

commit 8cf822a3d9d73f3c273ac64976995b8d3fc1fa47
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sun Sep 2 20:36:00 2007 +0000

    make use of new PA_PAGE_SIZE macro
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1744 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-solaris.c b/src/modules/module-solaris.c
index a50f1ec..c8ff770 100644
--- a/src/modules/module-solaris.c
+++ b/src/modules/module-solaris.c
@@ -602,7 +602,7 @@ int pa__init(pa_core *c, pa_module*m) {
     u->memchunk.length = 0;
 
     /* 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;

commit 2f7b6fead11e781e6071df09ea1c3ae2cadb845c
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sun Sep 2 20:36:32 2007 +0000

    add new pa_will_need() API for paging in memory
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1745 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/core-util.c b/src/pulsecore/core-util.c
index 82c0ea3..d231b65 100644
--- a/src/pulsecore/core-util.c
+++ b/src/pulsecore/core-util.c
@@ -54,6 +54,10 @@
 #include <sys/capability.h>
 #endif
 
+#ifdef HAVE_SYS_MMAN_H
+#include <sys/mman.h>
+#endif
+
 #ifdef HAVE_PTHREAD
 #include <pthread.h>
 #endif
@@ -1241,3 +1245,69 @@ char *pa_make_path_absolute(const char *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;
+    
+    if ((r = posix_madvise((void*) a, size, POSIX_MADV_WILLNEED)) == 0) {
+        pa_log_debug("posix_madvise() worked fine!");
+        return (void*) p;
+    }
+    
+    /* 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, 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, trying mlock(): %s", pa_cstrerror(r));
+
+    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;
+    }
+
+    if (bs <= 0)
+        pa_log_debug("mlock() failed too, giving up: %s", pa_cstrerror(errno));
+    else
+        pa_log_debug("mlock() worked fine!");
+
+    return (void*) p;
+}
diff --git a/src/pulsecore/core-util.h b/src/pulsecore/core-util.h
index 5474928..fcafe63 100644
--- a/src/pulsecore/core-util.h
+++ b/src/pulsecore/core-util.h
@@ -100,6 +100,8 @@ 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));
 }

commit f36ca797160c7eddaacf5cc18d366a74dbee229a
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sun Sep 2 20:37:17 2007 +0000

    add new API pa_memblock_will_need() and make use of PA_PAGE_SIZE macro
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1746 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/memblock.c b/src/pulsecore/memblock.c
index 3e2b006..479c74f 100644
--- a/src/pulsecore/memblock.c
+++ b/src/pulsecore/memblock.c
@@ -32,6 +32,7 @@
 #include <string.h>
 #include <unistd.h>
 #include <signal.h>
+#include <errno.h>
 
 #include <pulse/xmalloc.h>
 #include <pulse/def.h>
@@ -42,6 +43,7 @@
 #include <pulsecore/semaphore.h>
 #include <pulsecore/macro.h>
 #include <pulsecore/flist.h>
+#include <pulsecore/core-util.h>
 
 #include "memblock.h"
 
@@ -596,6 +598,20 @@ 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;
@@ -628,7 +644,6 @@ static void memblock_replace_import(pa_memblock *b) {
 }
 
 pa_mempool* pa_mempool_new(int shared) {
-    size_t ps;
     pa_mempool *p;
 
     p = pa_xnew(pa_mempool, 1);
@@ -636,18 +651,9 @@ pa_mempool* pa_mempool_new(int shared) {
     p->mutex = pa_mutex_new(1);
     p->semaphore = pa_semaphore_new(0);
 
-#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;
-
-    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;
 
diff --git a/src/pulsecore/memblock.h b/src/pulsecore/memblock.h
index 7fa6627..9bf7d8a 100644
--- a/src/pulsecore/memblock.h
+++ b/src/pulsecore/memblock.h
@@ -113,6 +113,8 @@ 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);

commit 7dbabc47bbfe517cd85e8b25b360413e511b3aec
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sun Sep 2 20:37:55 2007 +0000

    add new pa_memchunk_will_need() API, similar to pa_memblock_will_need()
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1747 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/memchunk.c b/src/pulsecore/memchunk.c
index 20ddb11..319767f 100644
--- a/src/pulsecore/memchunk.c
+++ b/src/pulsecore/memchunk.c
@@ -29,8 +29,11 @@
 #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"
 
@@ -72,3 +75,19 @@ pa_memchunk* pa_memchunk_reset(pa_memchunk *c) {
 
     return c;
 }
+
+pa_memchunk *pa_memchunk_will_need(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 c;
+}
diff --git a/src/pulsecore/memchunk.h b/src/pulsecore/memchunk.h
index 10cab2b..17e5f75 100644
--- a/src/pulsecore/memchunk.h
+++ b/src/pulsecore/memchunk.h
@@ -44,4 +44,7 @@ pa_memchunk* pa_memchunk_make_writable(pa_memchunk *c, size_t min);
  * but sets all members to zero. */
 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(pa_memchunk *c);
+
 #endif

commit 3e188b192c6470a0749bed4b01aad99faca4478a
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sun Sep 2 20:38:57 2007 +0000

    make use of pa_memchunk_will_need() before handing sample cache audio to the RT threads
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1748 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/play-memchunk.c b/src/pulsecore/play-memchunk.c
index 3ebbc14..f60f706 100644
--- a/src/pulsecore/play-memchunk.c
+++ b/src/pulsecore/play-memchunk.c
@@ -155,6 +155,8 @@ int pa_play_memchunk(
     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;

commit ca059ab9ef18918dd486e899482327ce157eb629
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sun Sep 2 20:39:45 2007 +0000

    Don't set RLIMIT_MEMBLOCK to 0 on startup. Retain 4 pages
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1749 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/daemon/daemon-conf.c b/src/daemon/daemon-conf.c
index e3ad8b3..7b503f8 100644
--- a/src/daemon/daemon-conf.c
+++ b/src/daemon/daemon-conf.c
@@ -86,13 +86,13 @@ static const pa_daemon_conf default_conf = {
     .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
 };
diff --git a/src/daemon/daemon.conf.in b/src/daemon/daemon.conf.in
index 9bd5cba..2132bf3 100644
--- a/src/daemon/daemon.conf.in
+++ b/src/daemon/daemon.conf.in
@@ -92,10 +92,10 @@
 ; 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
diff --git a/src/daemon/main.c b/src/daemon/main.c
index b927b2a..639d6dc 100644
--- a/src/daemon/main.c
+++ b/src/daemon/main.c
@@ -80,6 +80,7 @@
 #include <pulsecore/random.h>
 #include <pulsecore/rtsig.h>
 #include <pulsecore/rtclock.h>
+#include <pulsecore/macro.h>
 
 #include "cmdline.h"
 #include "cpulimit.h"
@@ -584,8 +585,10 @@ int main(int argc, char *argv[]) {
     signal(SIGPIPE, SIG_IGN);
 #endif
 
+    pa_log_info("Page size is %lu bytes", (unsigned long) PA_PAGE_SIZE);
+    
     if (pa_rtclock_hrtimer())
-        pa_log_debug("Fresh high-resolution timers available! Bon appetit!");
+        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!");
     

commit 68981e5e97684875f5e3b796d15b90b0f948577d
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sun Sep 2 20:51:25 2007 +0000

    fix build for dbus < 1.1.1, re #126, patch from Marc-Andre Lureau
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1750 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/dbus-util.c b/src/modules/dbus-util.c
index 24936fa..0a794fe 100644
--- a/src/modules/dbus-util.c
+++ b/src/modules/dbus-util.c
@@ -96,7 +96,11 @@ static void handle_io_event(PA_GCC_UNUSED pa_mainloop_api *ea, pa_io_event *e, i
     unsigned int flags = 0;
     DBusWatch *watch = userdata;
 
+#if (DBUS_VERSION_MAJOR == 1 && DBUS_VERSION_MINOR == 1 && DBUS_VERSION_MICRO >= 1) || (DBUS_VERSION_MAJOR == 1 && DBUS_VERSION_MAJOR > 1) || (DBUS_VERSION_MAJOR > 1) 
     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);
@@ -137,7 +141,13 @@ static dbus_bool_t add_watch(DBusWatch *watch, void *data) {
     pa_assert(watch);
     pa_assert(c);
 
-    ev = c->mainloop->io_new(c->mainloop, dbus_watch_get_unix_fd(watch), get_watch_flags(watch), handle_io_event, watch);
+    ev = c->mainloop->io_new(c->mainloop, 
+#if (DBUS_VERSION_MAJOR == 1 && DBUS_VERSION_MINOR == 1 && DBUS_VERSION_MICRO >= 1) || (DBUS_VERSION_MAJOR == 1 && DBUS_VERSION_MAJOR > 1) || (DBUS_VERSION_MAJOR > 1) 
+			     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);
 

commit 011dfa509bea2a799338f48018ebde09abcd7629
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sun Sep 2 21:13:17 2007 +0000

    make argument to pa_memchunk_will_need() const
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1751 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/memchunk.c b/src/pulsecore/memchunk.c
index 319767f..36df9f6 100644
--- a/src/pulsecore/memchunk.c
+++ b/src/pulsecore/memchunk.c
@@ -76,7 +76,7 @@ pa_memchunk* pa_memchunk_reset(pa_memchunk *c) {
     return c;
 }
 
-pa_memchunk *pa_memchunk_will_need(pa_memchunk *c) {
+pa_memchunk *pa_memchunk_will_need(const pa_memchunk *c) {
     void *p;
 
     pa_assert(c);
@@ -89,5 +89,5 @@ pa_memchunk *pa_memchunk_will_need(pa_memchunk *c) {
     pa_will_need(p, c->length);
     pa_memblock_release(c->memblock);
 
-    return c;
+    return (pa_memchunk*) c;
 }
diff --git a/src/pulsecore/memchunk.h b/src/pulsecore/memchunk.h
index 17e5f75..99498d0 100644
--- a/src/pulsecore/memchunk.h
+++ b/src/pulsecore/memchunk.h
@@ -45,6 +45,6 @@ pa_memchunk* pa_memchunk_make_writable(pa_memchunk *c, size_t min);
 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(pa_memchunk *c);
+pa_memchunk *pa_memchunk_will_need(const pa_memchunk *c);
 
 #endif

commit cc8c4998757702aee7c7d154fb7170d6cb7cbfbd
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sun Sep 2 21:18:46 2007 +0000

    fix dbus version check for dbus_watch_get_unix_fd()
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1752 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/dbus-util.c b/src/modules/dbus-util.c
index 0a794fe..360f782 100644
--- a/src/modules/dbus-util.c
+++ b/src/modules/dbus-util.c
@@ -96,7 +96,7 @@ static void handle_io_event(PA_GCC_UNUSED pa_mainloop_api *ea, pa_io_event *e, i
     unsigned int flags = 0;
     DBusWatch *watch = userdata;
 
-#if (DBUS_VERSION_MAJOR == 1 && DBUS_VERSION_MINOR == 1 && DBUS_VERSION_MICRO >= 1) || (DBUS_VERSION_MAJOR == 1 && DBUS_VERSION_MAJOR > 1) || (DBUS_VERSION_MAJOR > 1) 
+#if (DBUS_VERSION_MAJOR == 1 && DBUS_VERSION_MINOR == 1 && DBUS_VERSION_MICRO >= 1) || (DBUS_VERSION_MAJOR == 1 && DBUS_VERSION_MINOR > 1) || (DBUS_VERSION_MAJOR > 1) 
     pa_assert(fd == dbus_watch_get_unix_fd(watch));
 #else
     pa_assert(fd == dbus_watch_get_fd(watch));

commit 2e8244b4bcaae3f7b1cb45ceb503d3b13f539d25
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sun Sep 2 21:20:57 2007 +0000

    Allow compilation without libsamplerate; based on patch from Marc-Andre Lureau; re #125
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1753 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/core-util.c b/src/pulsecore/core-util.c
index d231b65..67d33e7 100644
--- a/src/pulsecore/core-util.c
+++ b/src/pulsecore/core-util.c
@@ -78,7 +78,9 @@
 #include <grp.h>
 #endif
 
+#ifdef HAVE_LIBSAMPLERATE
 #include <samplerate.h>
+#endif
 
 #include <pulse/xmalloc.h>
 #include <pulse/util.h>
diff --git a/src/pulsecore/resampler.c b/src/pulsecore/resampler.c
index d98d482..3e14c0e 100644
--- a/src/pulsecore/resampler.c
+++ b/src/pulsecore/resampler.c
@@ -27,7 +27,9 @@
 
 #include <string.h>
 
+#if HAVE_LIBSAMPLERATE
 #include <samplerate.h>
+#endif 
 
 #include <liboil/liboilfuncs.h>
 #include <liboil/liboil.h>
@@ -70,9 +72,11 @@ struct pa_resampler {
         unsigned i_counter;
     } trivial;
 
+#ifdef HAVE_LIBSAMPLERATE
     struct { /* data specific to libsamplerate */
         SRC_STATE *state;
     } src;
+#endif
 
     struct { /* data specific to speex */
         SpeexResamplerState* state;
@@ -84,7 +88,6 @@ struct pa_resampler {
     } ffmpeg;
 };
 
-static int libsamplerate_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);
@@ -92,11 +95,19 @@ static int ffmpeg_init(pa_resampler*r);
 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,
@@ -622,6 +633,7 @@ void pa_resampler_run(pa_resampler *r, const pa_memchunk *in, pa_memchunk *out)
 
 /*** libsamplerate based implementation ***/
 
+#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;
     
@@ -677,6 +689,7 @@ static int libsamplerate_init(pa_resampler *r) {
 
     return 0;
 }
+#endif
 
 /*** speex based implementation ***/
 
diff --git a/src/pulsecore/resampler.h b/src/pulsecore/resampler.h
index 2a943e3..711f9c6 100644
--- a/src/pulsecore/resampler.h
+++ b/src/pulsecore/resampler.h
@@ -24,8 +24,6 @@
   USA.
 ***/
 
-#include <samplerate.h>
-
 #include <pulse/sample.h>
 #include <pulse/channelmap.h>
 #include <pulsecore/memblock.h>
@@ -35,11 +33,11 @@ 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,

commit b6bfaa9249619cb4b71f05aa583c3cc34bbc6b36
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sun Sep 2 21:22:30 2007 +0000

    add missing configure.ac part of the libsamplerate patch from r1753, re #125
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1754 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/configure.ac b/configure.ac
index 718ebbf..e0453aa 100644
--- a/configure.ac
+++ b/configure.ac
@@ -323,12 +323,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 ])
@@ -346,6 +340,37 @@ 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
+
+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], 
@@ -844,6 +869,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 }---
 
@@ -865,6 +895,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}

commit b2c4779db493f9a1a52ba8147cb71c511d16042e
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sun Sep 2 22:08:30 2007 +0000

    make libpulse-core a noinst lib, because it does not have yet a stable API and won't get one anytime. Also, don't install its header files
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1755 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/Makefile.am b/src/Makefile.am
index 079610a..18e06ce 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -574,8 +574,8 @@ libffmpeg_resampler_la_SOURCES = pulsecore/ffmpeg/resample2.c
 #      Daemon core library        #
 ###################################
 
-
-pulsecoreinclude_HEADERS = \
+#pulsecoreinclude_HEADERS =
+noinst_HEADERS = \
 		pulsecore/autoload.h \
 		pulsecore/atomic.h \
 		pulsecore/cli-command.h \
@@ -627,7 +627,7 @@ pulsecoreinclude_HEADERS = \
 		pulsecore/semaphore.h \
 		pulsecore/once.h
 
-lib_LTLIBRARIES += libpulsecore.la
+noinst_LTLIBRARIES += libpulsecore.la
 
 # Some public stuff is used even in the core
 libpulsecore_la_SOURCES = \
@@ -721,7 +721,8 @@ libpulsecore_la_LIBADD = $(AM_LIBADD) $(LIBLTDL) $(LIBSAMPLERATE_LIBS) $(LIBSNDF
 #   Plug-in support libraries     #
 ###################################
 
-pulsecoreinclude_HEADERS += \
+#pulsecoreinclude_HEADERS +=
+noinst_HEADERS += \
 		pulsecore/socket-util.h \
 		pulsecore/iochannel.h \
 		pulsecore/socket-server.h \
@@ -781,7 +782,8 @@ modlibexec_LTLIBRARIES += \
 endif
 
 if HAVE_X11
-pulsecoreinclude_HEADERS += \
+#pulsecoreinclude_HEADERS +=
+noinst_HEADERS += \
 		pulsecore/x11wrap.h \
 		pulsecore/x11prop.h
 
@@ -791,7 +793,8 @@ modlibexec_LTLIBRARIES += \
 endif
 
 if HAVE_AVAHI
-pulsecoreinclude_HEADERS += \
+#pulsecoreinclude_HEADERS +=
+noinst_HEADERS += \
 		pulsecore/avahi-wrap.h
 
 modlibexec_LTLIBRARIES += \
@@ -1312,15 +1315,15 @@ 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_CFLAGS = $(AM_CFLAGS)
-
-module_rtp_recv_la_SOURCES = modules/rtp/module-rtp-recv.c
-module_rtp_recv_la_LDFLAGS = -module -avoid-version
-module_rtp_recv_la_LIBADD = $(AM_LIBADD) libpulsecore.la librtp.la
-module_rtp_recv_la_CFLAGS = $(AM_CFLAGS)
+#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_CFLAGS = $(AM_CFLAGS)
+
+#module_rtp_recv_la_SOURCES = modules/rtp/module-rtp-recv.c
+#module_rtp_recv_la_LDFLAGS = -module -avoid-version
+#module_rtp_recv_la_LIBADD = $(AM_LIBADD) libpulsecore.la librtp.la
+#module_rtp_recv_la_CFLAGS = $(AM_CFLAGS)
 
 # JACK
 

commit 5bc1221d40553f4c0e19cc7dfd606ff164d49cef
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Sep 3 20:39:55 2007 +0000

    actually define HAVE_LIBSAMPLERATE with AC_DEFINE
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1756 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/configure.ac b/configure.ac
index e0453aa..3485808 100644
--- a/configure.ac
+++ b/configure.ac
@@ -366,6 +366,10 @@ 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)

commit c9a0df361794750cc075c3f0bf7835028db64ead
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Sep 3 20:50:03 2007 +0000

    add new API function pa_resample_method_supported() which tests whether a resampling method is supported. Fix building with libsamplerate enabled
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1757 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/resampler.c b/src/pulsecore/resampler.c
index 3e14c0e..7493eef 100644
--- a/src/pulsecore/resampler.c
+++ b/src/pulsecore/resampler.c
@@ -91,6 +91,9 @@ struct pa_resampler {
 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);
 
@@ -166,6 +169,11 @@ pa_resampler* pa_resampler_new(
 
     /* Fix method */
 
+    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;
@@ -360,6 +368,19 @@ const char *pa_resample_method_to_string(pa_resample_method_t m) {
     return resample_methods[m];
 }
 
+int pa_resample_method_supported(pa_resample_method_t m) {
+
+    if (m < 0 || m >= PA_RESAMPLER_MAX)
+        return 0;
+
+#ifndef HAVE_LIBSAMPLERATE
+    if (m <= PA_RESAMPLER_SRC_LINEAR)
+        return 0;
+#endif
+        
+    return 1;
+}
+
 pa_resample_method_t pa_parse_resample_method(const char *string) {
     pa_resample_method_t m;
 
diff --git a/src/pulsecore/resampler.h b/src/pulsecore/resampler.h
index 711f9c6..fed4d89 100644
--- a/src/pulsecore/resampler.h
+++ b/src/pulsecore/resampler.h
@@ -80,4 +80,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

commit 104feb0aac38734b59973954ff62475869a05582
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Sep 3 20:50:55 2007 +0000

    only list supported resampling methods when --dump-resample-methods is executed
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1758 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/daemon/main.c b/src/daemon/main.c
index 639d6dc..77487dc 100644
--- a/src/daemon/main.c
+++ b/src/daemon/main.c
@@ -365,8 +365,7 @@ int main(int argc, char *argv[]) {
 
     LTDL_SET_PRELOADED_SYMBOLS();
 
-    r = lt_dlinit();
-    assert(r == 0);
+    pa_assert_se(lt_dlinit() == 0);
 
 #ifdef OS_IS_WIN32
     {
@@ -424,7 +423,8 @@ int main(int argc, char *argv[]) {
             int i;
 
             for (i = 0; i < PA_RESAMPLER_MAX; i++)
-                printf("%s\n", pa_resample_method_to_string(i));
+                if (pa_resample_method_supported(i))
+                    printf("%s\n", pa_resample_method_to_string(i));
                        
             goto finish;
         }

commit 1d3e70c7d3b9cbf45177c84989a68b7a2992386e
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Sep 3 20:51:17 2007 +0000

    header file cleanup
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1759 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-volume-restore.c b/src/modules/module-volume-restore.c
index 8c916c3..77e6174 100644
--- a/src/modules/module-volume-restore.c
+++ b/src/modules/module-volume-restore.c
@@ -34,6 +34,7 @@
 #include <ctype.h>
 
 #include <pulse/xmalloc.h>
+#include <pulse/volume.h>
 
 #include <pulsecore/core-error.h>
 #include <pulsecore/module.h>
@@ -43,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"
 

commit 11bf38042f83369e0077512e0c2aefadc3b47705
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Sep 3 20:53:07 2007 +0000

    add a new module module-default-device-restore which automatically saves and restores the selected default device. Enable it by default.
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1760 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/Makefile.am b/src/Makefile.am
index 18e06ce..a0563ec 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -927,6 +927,7 @@ modlibexec_LTLIBRARIES += \
 		module-null-sink.la \
 		module-detect.la \
 		module-volume-restore.la \
+		module-default-device-restore.la \
 		module-rescue-streams.la \
 		module-suspend-on-idle.la \
 		module-http-protocol-tcp.la \
@@ -1080,6 +1081,7 @@ 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 \
@@ -1302,6 +1304,12 @@ 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
diff --git a/src/daemon/default.pa.in b/src/daemon/default.pa.in
index 6ece607..fb90aa6 100755
--- a/src/daemon/default.pa.in
+++ b/src/daemon/default.pa.in
@@ -63,6 +63,9 @@ 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

commit c02903816450d79e4dbd708bdc7102088dc45a4b
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Sep 3 20:53:44 2007 +0000

    actually add source code of module-default-device-restore
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1761 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-default-device-restore.c b/src/modules/module-default-device-restore.c
new file mode 100644
index 0000000..71e19e6
--- /dev/null
+++ b/src/modules/module-default-device-restore.c
@@ -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);
+    }    
+}
+
+
+

commit 65ac0ea99aa340aa1afd38277186443c5c5eb4eb
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Sep 4 01:37:34 2007 +0000

    When in PA_STREAM_AUTO_TIMING_UPDATE mode, delay completion of initialization until we have the first timing data
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1762 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulse/stream.c b/src/pulse/stream.c
index f18a5dd..07a041a 100644
--- a/src/pulse/stream.c
+++ b/src/pulse/stream.c
@@ -38,6 +38,7 @@
 #include <pulsecore/pstream-util.h>
 #include <pulsecore/log.h>
 #include <pulsecore/hashmap.h>
+#include <pulsecore/macro.h>
 
 #include "internal.h"
 
@@ -218,6 +219,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);
@@ -321,7 +329,6 @@ 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);
 
     if (!(s->flags & PA_STREAM_AUTO_TIMING_UPDATE))
@@ -339,9 +346,12 @@ 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) {
@@ -387,6 +397,24 @@ 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(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 */
+        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;
 
@@ -450,23 +478,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);
-    }
-
-    if (s->requested_bytes > 0 && s->ref > 1 && s->write_callback)
-        s->write_callback(s, s->requested_bytes, s->write_userdata);
+        s->state = PA_STREAM_CREATING;
+        
+    } else
+        create_stream_complete(s);
 
 finish:
     pa_stream_unref(s);
@@ -886,6 +907,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);
 

commit d1927c7f37ad4481b54469b963bf783c208afb72
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Sep 4 02:25:44 2007 +0000

    initialize libltdl for multi-thread support
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1763 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/daemon/main.c b/src/daemon/main.c
index 77487dc..b754ee7 100644
--- a/src/daemon/main.c
+++ b/src/daemon/main.c
@@ -81,6 +81,9 @@
 #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 "cmdline.h"
 #include "cpulimit.h"
@@ -311,6 +314,39 @@ static void set_all_rlimits(const pa_daemon_conf *conf) {
 }
 #endif
 
+static pa_mutex *libtool_mutex = NULL;
+        
+static void libtool_lock(void) {
+    pa_mutex_lock(libtool_mutex);
+}
+
+static void libtool_unlock(void) {
+    pa_mutex_unlock(libtool_mutex);
+}
+
+PA_STATIC_TLS_DECLARE(libtool_tls, NULL);
+
+static void libtool_set_error(const char * error) {
+    pa_tls_set(PA_STATIC_TLS_GET(libtool_tls), (char*) error);
+}
+
+static const char *libtool_get_error(void) {
+    return pa_tls_get(PA_STATIC_TLS_GET(libtool_tls));
+}
+
+static void libtool_init(void)  {
+    pa_assert_se(libtool_mutex = pa_mutex_new(1));
+    libtool_lock(); /* Hmm, somehow libtool expects this mutex to be initialized in locking state! */
+    pa_assert_se(lt_dlmutex_register(libtool_lock, libtool_unlock, libtool_set_error, libtool_get_error) == 0);
+    pa_assert_se(lt_dlinit() == 0);
+}
+
+static void libtool_done(void) {
+    pa_assert_se(lt_dlexit() == 0);
+    pa_mutex_free(libtool_mutex);
+    libtool_mutex = NULL;
+}
+
 int main(int argc, char *argv[]) {
     pa_core *c = NULL;
     pa_strbuf *buf = NULL;
@@ -365,7 +401,7 @@ int main(int argc, char *argv[]) {
 
     LTDL_SET_PRELOADED_SYMBOLS();
 
-    pa_assert_se(lt_dlinit() == 0);
+    libtool_init();
 
 #ifdef OS_IS_WIN32
     {
@@ -714,7 +750,7 @@ finish:
     WSACleanup();
 #endif
 
-    lt_dlexit();
+    libtool_done();
 
     return retval;
 }

commit 738f7d7cd6e5cd58ea5d6e6bde07b467d761c5f4
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Sep 4 02:31:15 2007 +0000

    drop initial libtool_lock() call since this is a debian-specific borkage
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1764 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/daemon/main.c b/src/daemon/main.c
index b754ee7..1409761 100644
--- a/src/daemon/main.c
+++ b/src/daemon/main.c
@@ -336,7 +336,6 @@ static const char *libtool_get_error(void) {
 
 static void libtool_init(void)  {
     pa_assert_se(libtool_mutex = pa_mutex_new(1));
-    libtool_lock(); /* Hmm, somehow libtool expects this mutex to be initialized in locking state! */
     pa_assert_se(lt_dlmutex_register(libtool_lock, libtool_unlock, libtool_set_error, libtool_get_error) == 0);
     pa_assert_se(lt_dlinit() == 0);
 }

commit ac5f9781ba2f73a67d9c1b0662d61b2496bdffa7
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Sep 4 02:41:15 2007 +0000

    add a few missing files for make dist
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1765 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/Makefile.am b/src/Makefile.am
index a0563ec..51be9d0 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -562,13 +562,13 @@ libpulsedsp_la_LDFLAGS = -avoid-version
 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
+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
+libffmpeg_resampler_la_SOURCES = pulsecore/ffmpeg/resample2.c pulsecore/ffmpeg/avcodec.h pulsecore/ffmpeg/dsputil.h
 
 ###################################
 #      Daemon core library        #

commit 31c04a9047e609764a374ebacbadfaaa470aaa3e
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Sep 4 16:19:07 2007 +0000

    create config.rpath to fix build on fedora
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1766 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/bootstrap.sh b/bootstrap.sh
index b8db16f..f23acbf 100755
--- a/bootstrap.sh
+++ b/bootstrap.sh
@@ -48,6 +48,7 @@ else
     rm -rf autom4te.cache
     rm -f config.cache
 
+    touch config.rpath
     test "x$LIBTOOLIZE" = "x" && LIBTOOLIZE=libtoolize
 
     "$LIBTOOLIZE" -c --force --ltdl

commit 2dbe137daf8c74feca75ead33d5f8fbc84544af1
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Sep 4 20:00:19 2007 +0000

    if available, use native gcc atomicity builtins
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1767 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/atomic.h b/src/pulsecore/atomic.h
index 9a024f9..b5c1ad9 100644
--- a/src/pulsecore/atomic.h
+++ b/src/pulsecore/atomic.h
@@ -24,22 +24,95 @@
   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
+ */
+
+#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1))
+
+/* gcc based implementation */
 
 typedef struct pa_atomic {
-    volatile AO_t value;
+    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 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 = (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);
+}
+
+#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);
@@ -88,3 +161,5 @@ static inline int pa_atomic_ptr_cmpxchg(pa_atomic_ptr_t *a, void *old_p, void* n
 }
 
 #endif
+
+#endif

commit 4c31ff9b452eee995e621bd877f321eea974fc7e
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Sep 4 20:01:19 2007 +0000

    fix a couple of compiler warnings
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1768 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-alsa-sink.c b/src/modules/module-alsa-sink.c
index 24765a0..c75f195 100644
--- a/src/modules/module-alsa-sink.c
+++ b/src/modules/module-alsa-sink.c
@@ -135,7 +135,7 @@ static int mmap_write(struct userdata *u) {
             if (err == -EAGAIN)
                 return work_done;
             
-            pa_log("snd_pcm_avail_update: %s", snd_strerror(n));
+            pa_log("snd_pcm_avail_update: %s", snd_strerror(err));
             return -1;
         }
 
@@ -225,7 +225,7 @@ static int unix_write(struct userdata *u) {
         int err;
                 
         if ((err = snd_pcm_status(u->pcm_handle, status)) < 0) {
-            pa_log("Failed to query DSP status data: %s", snd_strerror(t));
+            pa_log("Failed to query DSP status data: %s", snd_strerror(err));
             return -1;
         }
 
diff --git a/src/modules/module-alsa-source.c b/src/modules/module-alsa-source.c
index 0d76cab..9922668 100644
--- a/src/modules/module-alsa-source.c
+++ b/src/modules/module-alsa-source.c
@@ -132,7 +132,7 @@ static int mmap_read(struct userdata *u) {
             if (err == -EAGAIN)
                 return work_done;
             
-            pa_log("snd_pcm_avail_update: %s", snd_strerror(n));
+            pa_log("snd_pcm_avail_update: %s", snd_strerror(err));
             return -1;
         }
 
@@ -216,7 +216,7 @@ static int unix_read(struct userdata *u) {
         pa_memchunk chunk;
         
         if ((err = snd_pcm_status(u->pcm_handle, status)) < 0) {
-            pa_log("Failed to query DSP status data: %s", snd_strerror(t));
+            pa_log("Failed to query DSP status data: %s", snd_strerror(err));
             return -1;
         }
 
diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c
index ea7f43c..a4983a0 100644
--- a/src/pulsecore/protocol-native.c
+++ b/src/pulsecore/protocol-native.c
@@ -439,8 +439,8 @@ static record_stream* record_stream_new(
         const pa_sample_spec *ss,
         const pa_channel_map *map,
         const char *name,
-        size_t *maxlength,
-        size_t fragment_size,
+        uint32_t *maxlength,
+        uint32_t fragment_size,
         int corked) {
 
     record_stream *s;
diff --git a/src/pulsecore/rtpoll.c b/src/pulsecore/rtpoll.c
index 0f09c7d..e43ec61 100644
--- a/src/pulsecore/rtpoll.c
+++ b/src/pulsecore/rtpoll.c
@@ -383,7 +383,8 @@ finish:
         }
     }
 
-    errno = saved_errno;
+    if (r < 0)
+        errno = saved_errno;
 
     return r;
 }
diff --git a/src/pulsecore/sound-file.c b/src/pulsecore/sound-file.c
index 7c8b597..ef43eef 100644
--- a/src/pulsecore/sound-file.c
+++ b/src/pulsecore/sound-file.c
@@ -126,7 +126,7 @@ int pa_sound_file_load(
     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) != l)) {
+        (!readf_function && sf_read_raw(sf, ptr, l) != (sf_count_t) l)) {
         pa_log("Premature file end");
         goto finish;
     }
diff --git a/src/tests/interpol-test.c b/src/tests/interpol-test.c
index 3953043..85a509d 100644
--- a/src/tests/interpol-test.c
+++ b/src/tests/interpol-test.c
@@ -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;
         }
diff --git a/src/utils/paplay.c b/src/utils/paplay.c
index 2c779a7..e7076d2 100644
--- a/src/utils/paplay.c
+++ b/src/utils/paplay.c
@@ -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));

commit 984ef82e52822abdf6492ed13b016b6b115414b4
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Sep 4 21:24:45 2007 +0000

    detect whether gcc atomic builtins are available
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1769 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/configure.ac b/configure.ac
index 3485808..626a1ce 100644
--- a/configure.ac
+++ b/configure.ac
@@ -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
@@ -106,6 +106,18 @@ if test "x$GCC" = "xyes" ; then
     done 
 fi
 
+AC_MSG_CHECKING([whether $CC knows __sync_bool_compare_and_swap()])
+AC_LANG_CONFTEST([int main() { int a = 4; __sync_bool_compare_and_swap(&a, 4, 5); }])
+$CC conftest.c $CFLAGS -o conftest > /dev/null 2> /dev/null
+ret=$?
+rm -f conftest.o conftest
+if test $ret -eq 0 ; then
+    AC_DEFINE([HAVE_ATOMIC_BUILTINS], 1, [Have __sync_bool_compare_and_swap() and friends.])
+    AC_MSG_RESULT([yes])
+else
+    AC_MSG_RESULT([no])
+fi
+
 #### libtool stuff ####
 
 AC_LTDL_ENABLE_INSTALL

commit a4757a1dd90db5d6f1115205b452a232e4af58d3
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Sep 4 21:25:26 2007 +0000

    add native amd64 atomic int implementation
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1770 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/atomic.h b/src/pulsecore/atomic.h
index b5c1ad9..6e33c99 100644
--- a/src/pulsecore/atomic.h
+++ b/src/pulsecore/atomic.h
@@ -37,9 +37,14 @@
  * libatomic_ops
  */
 
-#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1))
+/* We have to include config.h here, which sucks */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef HAVE_ATOMIC_BUILTINS
 
-/* gcc based implementation */
+/* __sync based implementation */
 
 typedef struct pa_atomic {
     volatile int value;
@@ -83,7 +88,7 @@ static inline int pa_atomic_cmpxchg(pa_atomic_t *a, int old_i, int new_i) {
 }
 
 typedef struct pa_atomic_ptr {
-    volatile long value;
+    volatile unsigned long value;
 } pa_atomic_ptr_t;
 
 #define PA_ATOMIC_PTR_INIT(v) { .value = (long) (v) }
@@ -94,7 +99,7 @@ static inline void* pa_atomic_ptr_load(const pa_atomic_ptr_t *a) {
 }
 
 static inline void pa_atomic_ptr_store(pa_atomic_ptr_t *a, void *p) {
-    a->value = (long) p;
+    a->value = (unsigned long) p;
     __sync_synchronize();
 }
 
@@ -102,6 +107,80 @@ static inline int pa_atomic_ptr_cmpxchg(pa_atomic_ptr_t *a, void *old_p, void* n
     return __sync_bool_compare_and_swap(&a->value, (long) old_p, (long) new_p);
 }
 
+#elif defined(__GNUC__) && (defined(__amd64__) || defined(__x86_64__))
+
+/* 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_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 */

commit a0d19c0d13e61d1f713637cba445911cb8cfef68
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Sep 4 21:34:04 2007 +0000

    update libltdl copy
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1771 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/libltdl/acinclude.m4 b/libltdl/acinclude.m4
index 3f1dd40..79d9486 100644
--- a/libltdl/acinclude.m4
+++ b/libltdl/acinclude.m4
@@ -7,7 +7,7 @@
 ## unlimited permission to copy and/or distribute it, with or without
 ## modifications, as long as this notice is preserved.
 
-# serial 51 AC_PROG_LIBTOOL
+# serial 51 Debian 1.5.24-1 AC_PROG_LIBTOOL
 
 
 # AC_PROVIDE_IFELSE(MACRO-NAME, IF-PROVIDED, IF-NOT-PROVIDED)
@@ -559,7 +559,6 @@ s390*-*linux*|sparc*-*linux*)
       esac
       ;;
     *64-bit*)
-      libsuff=64
       case $host in
         x86_64-*kfreebsd*-gnu)
           LD="${LD-ld} -m elf_x86_64_fbsd"
@@ -1618,13 +1617,11 @@ linux* | k*bsd*-gnu)
   # Some rework will be needed to allow for fast_install
   # before this can be enabled.
   hardcode_into_libs=yes
-  sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}"
-  sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}"
 
   # 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="$sys_lib_dlsearch_path_spec $lt_ld_extra"
+    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
@@ -1636,6 +1633,18 @@ linux* | k*bsd*-gnu)
   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
@@ -2410,7 +2419,7 @@ linux* | k*bsd*-gnu)
   lt_cv_deplibs_check_method=pass_all
   ;;
 
-netbsd*)
+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
@@ -3448,7 +3457,7 @@ case $host_os in
 	;;
     esac
     ;;
-  netbsd*)
+  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=
@@ -5137,7 +5146,7 @@ AC_MSG_CHECKING([for $compiler option to produce PIC])
 	    ;;
 	esac
 	;;
-      netbsd*)
+      netbsd* | netbsdelf*-gnu)
 	;;
       osf3* | osf4* | osf5*)
 	case $cc_basename in
@@ -5512,6 +5521,9 @@ ifelse([$1],[CXX],[
   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'
   ;;
@@ -5717,12 +5729,13 @@ EOF
   $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*)
+    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=
@@ -6154,7 +6167,7 @@ _LT_EOF
       _LT_AC_TAGVAR(link_all_deplibs, $1)=yes
       ;;
 
-    netbsd*)
+    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
@@ -6738,7 +6751,7 @@ AC_CACHE_CHECK([whether deplibs are loaded by dlopen],
     # at 6.2 and later dlopen does load deplibs.
     libltdl_cv_sys_dlopen_deplibs=yes
     ;;
-  netbsd*)
+  netbsd* | netbsdelf*-gnu)
     libltdl_cv_sys_dlopen_deplibs=yes
     ;;
   openbsd*)
diff --git a/libltdl/config.guess b/libltdl/config.guess
index 951383e..0f0fe71 100755
--- a/libltdl/config.guess
+++ b/libltdl/config.guess
@@ -4,7 +4,7 @@
 #   2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation,
 #   Inc.
 
-timestamp='2007-05-17'
+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
@@ -330,7 +330,7 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
     sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
 	echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
 	exit ;;
-    i86pc:SunOS:5.*:* | ix86xen:SunOS:5.*:*)
+    i86pc:SunOS:5.*:*)
 	echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
 	exit ;;
     sun4*:SunOS:6*:*)
diff --git a/libltdl/config.h b/libltdl/config.h
index 195d214..a04820a 100644
--- a/libltdl/config.h
+++ b/libltdl/config.h
@@ -160,7 +160,7 @@
 #define LTDL_SHLIB_EXT ".so"
 
 /* Define to the system default library search path. */
-#define LTDL_SYSSEARCHPATH "/usr/lib:/lib:/usr/local/lib:/usr/lib/qt-3.3/lib"
+#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 */
diff --git a/libltdl/config.sub b/libltdl/config.sub
index c060f44..5defff6 100755
--- a/libltdl/config.sub
+++ b/libltdl/config.sub
@@ -4,7 +4,7 @@
 #   2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation,
 #   Inc.
 
-timestamp='2007-04-29'
+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
@@ -683,10 +683,6 @@ case $basic_machine in
 		basic_machine=i386-pc
 		os=-mingw32
 		;;
-	mingw32ce)
-		basic_machine=arm-unknown
-		os=-mingw32ce
-		;;
 	miniframe)
 		basic_machine=m68000-convergent
 		;;
diff --git a/libltdl/configure b/libltdl/configure
index 62dface..aa2994e 100755
--- a/libltdl/configure
+++ b/libltdl/configure
@@ -4408,7 +4408,7 @@ linux* | k*bsd*-gnu)
   lt_cv_deplibs_check_method=pass_all
   ;;
 
-netbsd*)
+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
@@ -4593,7 +4593,6 @@ s390*-*linux*|sparc*-*linux*)
       esac
       ;;
     *64-bit*)
-      libsuff=64
       case $host in
         x86_64-*kfreebsd*-gnu)
           LD="${LD-ld} -m elf_x86_64_fbsd"
@@ -7565,11 +7564,11 @@ else
    -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:7568: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:7567: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>conftest.err)
    ac_status=$?
    cat conftest.err >&5
-   echo "$as_me:7572: \$? = $ac_status" >&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.
@@ -7855,11 +7854,11 @@ else
    -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:7858: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:7857: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>conftest.err)
    ac_status=$?
    cat conftest.err >&5
-   echo "$as_me:7862: \$? = $ac_status" >&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.
@@ -7959,11 +7958,11 @@ else
    -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:7962: $lt_compile\"" >&5)
+   (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:7966: \$? = $ac_status" >&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
@@ -8223,12 +8222,13 @@ EOF
   $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*)
+    netbsd* | netbsdelf*-gnu)
       if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
 	archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib'
 	wlarc=
@@ -8772,7 +8772,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
       link_all_deplibs=yes
       ;;
 
-    netbsd*)
+    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
@@ -9467,13 +9467,11 @@ linux* | k*bsd*-gnu)
   # Some rework will be needed to allow for fast_install
   # before this can be enabled.
   hardcode_into_libs=yes
-  sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}"
-  sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}"
 
   # 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="$sys_lib_dlsearch_path_spec $lt_ld_extra"
+    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
@@ -9485,6 +9483,18 @@ linux* | k*bsd*-gnu)
   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
@@ -10310,7 +10320,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<EOF
-#line 10313 "configure"
+#line 10323 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -10410,7 +10420,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<EOF
-#line 10413 "configure"
+#line 10423 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -12020,7 +12030,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
 	;;
     esac
     ;;
-  netbsd*)
+  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=
@@ -12725,7 +12735,7 @@ echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6; }
 	    ;;
 	esac
 	;;
-      netbsd*)
+      netbsd* | netbsdelf*-gnu)
 	;;
       osf3* | osf4* | osf5*)
 	case $cc_basename in
@@ -12834,11 +12844,11 @@ else
    -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:12837: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:12847: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>conftest.err)
    ac_status=$?
    cat conftest.err >&5
-   echo "$as_me:12841: \$? = $ac_status" >&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.
@@ -12938,11 +12948,11 @@ else
    -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:12941: $lt_compile\"" >&5)
+   (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:12945: \$? = $ac_status" >&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
@@ -13010,6 +13020,9 @@ echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared librar
   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'
   ;;
@@ -13439,13 +13452,11 @@ linux* | k*bsd*-gnu)
   # Some rework will be needed to allow for fast_install
   # before this can be enabled.
   hardcode_into_libs=yes
-  sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}"
-  sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}"
 
   # 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="$sys_lib_dlsearch_path_spec $lt_ld_extra"
+    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
@@ -13457,6 +13468,18 @@ linux* | k*bsd*-gnu)
   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
@@ -14502,11 +14525,11 @@ else
    -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:14505: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:14528: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>conftest.err)
    ac_status=$?
    cat conftest.err >&5
-   echo "$as_me:14509: \$? = $ac_status" >&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.
@@ -14606,11 +14629,11 @@ else
    -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:14609: $lt_compile\"" >&5)
+   (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:14613: \$? = $ac_status" >&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
@@ -14870,12 +14893,13 @@ EOF
   $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*)
+    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=
@@ -15399,7 +15423,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
       link_all_deplibs_F77=yes
       ;;
 
-    netbsd*)
+    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
@@ -16042,13 +16066,11 @@ linux* | k*bsd*-gnu)
   # Some rework will be needed to allow for fast_install
   # before this can be enabled.
   hardcode_into_libs=yes
-  sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}"
-  sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}"
 
   # 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="$sys_lib_dlsearch_path_spec $lt_ld_extra"
+    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
@@ -16060,6 +16082,18 @@ linux* | k*bsd*-gnu)
   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
@@ -16799,11 +16833,11 @@ else
    -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:16802: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:16836: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>conftest.err)
    ac_status=$?
    cat conftest.err >&5
-   echo "$as_me:16806: \$? = $ac_status" >&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.
@@ -17089,11 +17123,11 @@ else
    -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:17092: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:17126: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>conftest.err)
    ac_status=$?
    cat conftest.err >&5
-   echo "$as_me:17096: \$? = $ac_status" >&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.
@@ -17193,11 +17227,11 @@ else
    -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:17196: $lt_compile\"" >&5)
+   (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:17200: \$? = $ac_status" >&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
@@ -17457,12 +17491,13 @@ EOF
   $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*)
+    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=
@@ -18006,7 +18041,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
       link_all_deplibs_GCJ=yes
       ;;
 
-    netbsd*)
+    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
@@ -18649,13 +18684,11 @@ linux* | k*bsd*-gnu)
   # Some rework will be needed to allow for fast_install
   # before this can be enabled.
   hardcode_into_libs=yes
-  sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}"
-  sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}"
 
   # 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="$sys_lib_dlsearch_path_spec $lt_ld_extra"
+    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
@@ -18667,6 +18700,18 @@ linux* | k*bsd*-gnu)
   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
@@ -20929,7 +20974,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<EOF
-#line 20932 "configure"
+#line 20977 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -21075,7 +21120,7 @@ else
     # at 6.2 and later dlopen does load deplibs.
     libltdl_cv_sys_dlopen_deplibs=yes
     ;;
-  netbsd*)
+  netbsd* | netbsdelf*-gnu)
     libltdl_cv_sys_dlopen_deplibs=yes
     ;;
   openbsd*)
diff --git a/libltdl/ltdl.c b/libltdl/ltdl.c
index 5f56fbb..409e5be 100644
--- a/libltdl/ltdl.c
+++ b/libltdl/ltdl.c
@@ -1068,17 +1068,6 @@ lt_estrdup (str)
 #  include <sys/dl.h>
 #endif
 
-#ifdef RTLD_GLOBAL
-#  define LT_GLOBAL		RTLD_GLOBAL
-#else
-#  ifdef DL_GLOBAL
-#    define LT_GLOBAL		DL_GLOBAL
-#  endif
-#endif /* !RTLD_GLOBAL */
-#ifndef LT_GLOBAL
-#  define LT_GLOBAL		0
-#endif /* !LT_GLOBAL */
-
 /* 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
@@ -1114,7 +1103,7 @@ sys_dl_open (loader_data, filename)
      lt_user_data loader_data;
      const char *filename;
 {
-  lt_module   module   = dlopen (filename, LT_GLOBAL | LT_LAZY_OR_NOW);
+  lt_module   module   = dlopen (filename, LT_LAZY_OR_NOW);
 
   if (!module)
     {
@@ -3225,9 +3214,7 @@ try_dlopen (phandle, filename)
 	}
       if (!file)
 	{
-	  /* don't open .la files in current directory, root might get tricked to run a binary in a prepared directory */
-	  if(!strncmp((filename + strlen(filename) - 3), LTDL_ARCHIVE_EXT,3) || strstr(filename,"/"))
-	    file = fopen (filename, LT_READTEXT_MODE);
+	  file = fopen (filename, LT_READTEXT_MODE);
 	}
 
       /* If we didn't find the file by now, it really isn't there.  Set
diff --git a/libltdl/ltmain.sh b/libltdl/ltmain.sh
index 8e5a930..f924d30 100644
--- a/libltdl/ltmain.sh
+++ b/libltdl/ltmain.sh
@@ -43,7 +43,7 @@ EXIT_FAILURE=1
 
 PROGRAM=ltmain.sh
 PACKAGE=libtool
-VERSION=1.5.24
+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).
@@ -2122,7 +2122,10 @@ EOF
 	case $pass in
 	dlopen) libs="$dlfiles" ;;
 	dlpreopen) libs="$dlprefiles" ;;
-	link) libs="$deplibs %DEPLIBS% $dependency_libs" ;;
+	link)
+	  libs="$deplibs %DEPLIBS%"
+	  test "X$link_all_deplibs" != Xno && libs="$libs $dependency_libs"
+	  ;;
 	esac
       fi
       if test "$pass" = dlopen; then
@@ -3244,6 +3247,11 @@ EOF
 	    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)

commit b1fd53b20ba77dab903eb4d83e2b9d1a8d99f2b6
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Sep 6 20:06:02 2007 +0000

    explicitly test for the availability of dbus_watch_get_unix_fd() before using it. The previous version-based check didn't work anyway since the constants checked for weren't set.
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1772 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/configure.ac b/configure.ac
index 626a1ce..71e95b8 100644
--- a/configure.ac
+++ b/configure.ac
@@ -713,7 +713,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,
@@ -732,6 +731,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"
+        
+        ],
+        [
+            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)]))
diff --git a/src/modules/dbus-util.c b/src/modules/dbus-util.c
index 360f782..9078ec7 100644
--- a/src/modules/dbus-util.c
+++ b/src/modules/dbus-util.c
@@ -96,7 +96,7 @@ static void handle_io_event(PA_GCC_UNUSED pa_mainloop_api *ea, pa_io_event *e, i
     unsigned int flags = 0;
     DBusWatch *watch = userdata;
 
-#if (DBUS_VERSION_MAJOR == 1 && DBUS_VERSION_MINOR == 1 && DBUS_VERSION_MICRO >= 1) || (DBUS_VERSION_MAJOR == 1 && DBUS_VERSION_MINOR > 1) || (DBUS_VERSION_MAJOR > 1) 
+#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));
@@ -141,14 +141,15 @@ static dbus_bool_t add_watch(DBusWatch *watch, void *data) {
     pa_assert(watch);
     pa_assert(c);
 
-    ev = c->mainloop->io_new(c->mainloop, 
-#if (DBUS_VERSION_MAJOR == 1 && DBUS_VERSION_MINOR == 1 && DBUS_VERSION_MICRO >= 1) || (DBUS_VERSION_MAJOR == 1 && DBUS_VERSION_MAJOR > 1) || (DBUS_VERSION_MAJOR > 1) 
-			     dbus_watch_get_unix_fd(watch), 
+    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), 
+            dbus_watch_get_fd(watch), 
 #endif
-			     get_watch_flags(watch), handle_io_event, watch);
-
+            get_watch_flags(watch), handle_io_event, watch);
+    
     dbus_watch_set_data(watch, ev, NULL);
 
     return TRUE;

commit 3b2cf1ade56d90c28ace819cf82c88b7d1989182
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Sep 6 20:38:10 2007 +0000

    update default config:
    - check for existance of modules before loading them
    - disable all event sounds except hotplug by default
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1773 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/Makefile.am b/src/Makefile.am
index 51be9d0..b0b3bb2 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1392,8 +1392,8 @@ default.pa: daemon/default.pa.win32
 else
 default.pa: daemon/default.pa.in Makefile
 	sed -e 's, at PA_BINARY\@,$(PA_BINARY),g' \
-	    -e 's, at HAVE_HAL_TRUE\@, at HAVE_HAL_TRUE@,g' \
-	    -e 's, at HAVE_HAL_FALSE\@, at HAVE_HAL_FALSE@,g' < $< > $@
+            -e 's, at PA_DLSEARCHPATH\@,$(modlibexecdir),g' \
+	    -e 's, at PA_SOEXT\@,.so,g' < $< > $@
 endif
 
 daemon.conf: daemon/daemon.conf.in Makefile
diff --git a/src/daemon/default.pa.in b/src/daemon/default.pa.in
index fb90aa6..597993c 100755
--- a/src/daemon/default.pa.in
+++ b/src/daemon/default.pa.in
@@ -19,10 +19,10 @@
 .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/email.wav
-load-sample-lazy pulse-coldplug /usr/share/sounds/startup3.wav
-load-sample-lazy pulse-access /usr/share/sounds/generic.wav
+#load-sample-lazy x11-bell /usr/share/sounds/gtk-events/activate.wav
+load-sample-lazy pulse-hotplug /usr/share/sounds/startup3.wav
+#load-sample-lazy pulse-coldplug /usr/share/sounds/startup3.wav
+#load-sample-lazy pulse-access /usr/share/sounds/generic.wav
 
 .fail
 
@@ -37,11 +37,13 @@ load-sample-lazy pulse-access /usr/share/sounds/generic.wav
 #load-module module-pipe-sink
 
 ### Automatically load driver modules depending on the hardware available
- at HAVE_HAL_TRUE@load-module module-hal-detect
-
+.ifexists @PA_DLSEARCHPATH@/module-hal-detect at PA_SOEXT@
+load-module module-hal-detect
+.else
 ### Alternatively use the static hardware detection module (for systems that
 ### lack HAL support)
- at HAVE_HAL_FALSE@load-module module-detect
+load-module module-detect
+.endif
 
 ### Load several protocols
 load-module module-esound-protocol-unix
@@ -74,10 +76,12 @@ load-module module-rescue-streams
 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 at 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
@@ -87,7 +91,9 @@ load-module module-x11-publish
 ### 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 at PA_SOEXT@
 load-module module-gconf
+.endif
 
 ### Make some devices default
 #set-default-sink output
diff --git a/src/pulsecore/cli-command.c b/src/pulsecore/cli-command.c
index 0cd1f48..79b52d4 100644
--- a/src/pulsecore/cli-command.c
+++ b/src/pulsecore/cli-command.c
@@ -1145,6 +1145,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);

commit 45ba7117dc25c5d5db783356c51c71a81d51e662
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Sep 6 20:45:43 2007 +0000

    downgrade realtime group membership warning to 'info' at be a little bit more elaborate
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1774 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/daemon/main.c b/src/daemon/main.c
index 1409761..135a9ab 100644
--- a/src/daemon/main.c
+++ b/src/daemon/main.c
@@ -392,7 +392,8 @@ int main(int argc, char *argv[]) {
     setlocale(LC_ALL, "");
 
     if (suid_root && (pa_own_uid_in_group(PA_REALTIME_GROUP, &gid) <= 0)) {
-        pa_log_warn("WARNING: called SUID root, but not in group '"PA_REALTIME_GROUP"'.");
+        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;

commit e4eefb8ce0d8e9ecc0e2ea40ee0c8b41e7e4adbc
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Sep 6 23:10:34 2007 +0000

    fix copynpaste error
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1775 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/source-output.c b/src/pulsecore/source-output.c
index ccd968a..1a9bf96 100644
--- a/src/pulsecore/source-output.c
+++ b/src/pulsecore/source-output.c
@@ -222,7 +222,7 @@ static void source_output_free(pa_object* mo) {
 
     pa_assert(pa_source_output_refcnt(o) == 0);
 
-    if (PA_SOURCE_LINKED(o->state))
+    if (PA_SOURCE_OUTPUT_LINKED(o->state))
         pa_source_output_unlink(o);
 
     pa_log_info("Freeing output %u \"%s\"", o->index, o->name);

commit d60940dbe4a6bf3acf0b458d321a1f4d449b7a01
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Sep 6 23:11:22 2007 +0000

    install libpulsecore again, since libtool otherwise links it statically into every single module
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1776 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/Makefile.am b/src/Makefile.am
index b0b3bb2..1dfe3c2 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -627,7 +627,7 @@ noinst_HEADERS = \
 		pulsecore/semaphore.h \
 		pulsecore/once.h
 
-noinst_LTLIBRARIES += libpulsecore.la
+lib_LTLIBRARIES += libpulsecore.la
 
 # Some public stuff is used even in the core
 libpulsecore_la_SOURCES = \

commit b41dbfd28d6f940004f412f3ef16a1419240786f
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Sep 6 23:29:16 2007 +0000

    fix an assert when runnig module-oss in record only-mode. optimize allocation of memblocks on playback
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1777 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-alsa-source.c b/src/modules/module-alsa-source.c
index 9922668..365f6ab 100644
--- a/src/modules/module-alsa-source.c
+++ b/src/modules/module-alsa-source.c
@@ -210,7 +210,7 @@ static int unix_read(struct userdata *u) {
 
     for (;;) {
         void *p;
-        snd_pcm_sframes_t t;
+        snd_pcm_sframes_t t, k;
         ssize_t l;
         int err;
         pa_memchunk chunk;
@@ -228,10 +228,17 @@ static int unix_read(struct userdata *u) {
         if (l <= 0)
             return work_done;
                     
-        chunk.memblock = pa_memblock_new(u->core->mempool, l);
+        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;
 
         p = pa_memblock_acquire(chunk.memblock);
-        t = snd_pcm_readi(u->pcm_handle, (uint8_t*) p, l / u->frame_size);
+        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);   */
diff --git a/src/modules/module-oss.c b/src/modules/module-oss.c
index bbb1e0d..f36f21f 100644
--- a/src/modules/module-oss.c
+++ b/src/modules/module-oss.c
@@ -110,6 +110,7 @@ struct userdata {
     
     pa_memchunk memchunk;
 
+    size_t frame_size;
     uint32_t in_fragment_size, out_fragment_size, in_nfrags, out_nfrags, in_hwbuf_size, out_hwbuf_size;
     int use_getospace, use_getispace;
     int use_getodelay;
@@ -941,14 +942,21 @@ static void thread_func(void *userdata) {
                 }
 
                 do {
-                    ssize_t t;
+                    ssize_t t, k;
 
                     pa_assert(l > 0);
 
-                    memchunk.memblock = pa_memblock_new(u->core->mempool, l);
+                    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, l, &read_type);
+                    t = pa_read(u->fd, p, k, &read_type);
                     pa_memblock_release(memchunk.memblock);
 
                     pa_assert(t != 0); /* EOF cannot happen */
@@ -992,16 +1000,20 @@ static void thread_func(void *userdata) {
 /*         pa_log("loop2"); */
 
         /* Now give the sink inputs some to time to process their data */
-        if ((ret = pa_sink_process_inputs(u->sink)) < 0)
-            goto fail;
-        if (ret > 0)
-            continue;
+        if (u->sink) {
+            if ((ret = pa_sink_process_inputs(u->sink)) < 0)
+                goto fail;
+            if (ret > 0)
+                continue;
+        }
 
         /* Now give the source outputs some to time to process their data */
-        if ((ret = pa_source_process_outputs(u->source)) < 0)
-            goto fail;
-        if (ret > 0)
-            continue;
+        if (u->source) {
+            if ((ret = pa_source_process_outputs(u->source)) < 0)
+                goto fail;
+            if (ret > 0)
+                continue;
+        }
         
         /* Check whether there is a message for us to process */
         if ((ret = pa_thread_mq_process(&u->thread_mq) < 0))
@@ -1148,6 +1160,7 @@ int pa__init(pa_module*m) {
     u->use_getodelay = 1;
     u->use_input_volume = u->use_pcm_volume = 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;
diff --git a/src/pulsecore/memblock.c b/src/pulsecore/memblock.c
index 479c74f..53c6087 100644
--- a/src/pulsecore/memblock.c
+++ b/src/pulsecore/memblock.c
@@ -218,6 +218,11 @@ static pa_memblock *memblock_new_appended(pa_mempool *p, size_t length) {
     pa_assert(p);
     pa_assert(length > 0);
 
+    /* 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;
@@ -261,7 +266,7 @@ static struct mempool_slot* mempool_allocate_slot(pa_mempool *p) {
 static void* mempool_slot_data(struct mempool_slot *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 */
@@ -292,16 +297,22 @@ pa_memblock *pa_memblock_new_pool(pa_mempool *p, size_t length) {
     pa_assert(p);
     pa_assert(length > 0);
 
-    if (p->block_size - sizeof(struct mempool_slot) >= sizeof(pa_memblock) + length) {
+    /* 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 (length == (size_t) -1)
+        length = p->block_size - PA_ALIGN(sizeof(struct mempool_slot)) - PA_ALIGN(sizeof(pa_memblock));
+    
+    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;
-        pa_atomic_ptr_store(&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;
@@ -313,7 +324,7 @@ pa_memblock *pa_memblock_new_pool(pa_mempool *p, size_t length) {
         pa_atomic_ptr_store(&b->data, mempool_slot_data(slot));
 
     } else {
-        pa_log_debug("Memory block too large for pool: %lu > %lu", (unsigned long) length, (unsigned long) (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;
     }
@@ -335,6 +346,7 @@ pa_memblock *pa_memblock_new_fixed(pa_mempool *p, void *d, size_t length, int re
 
     pa_assert(p);
     pa_assert(d);
+    pa_assert(length != (size_t) -1);
     pa_assert(length > 0);
 
     if (!(b = pa_flist_pop(PA_STATIC_FLIST_GET(unused_memblocks))))
@@ -359,6 +371,7 @@ pa_memblock *pa_memblock_new_user(pa_mempool *p, void *d, size_t length, void (*
     pa_assert(p);
     pa_assert(d);
     pa_assert(length > 0);
+    pa_assert(length != (size_t) -1);
     pa_assert(free_cb);
 
     if (!(b = pa_flist_pop(PA_STATIC_FLIST_GET(unused_memblocks))))
@@ -555,7 +568,7 @@ static void memblock_make_local(pa_memblock *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))) {
@@ -657,7 +670,7 @@ pa_mempool* pa_mempool_new(int shared) {
 
     p->n_blocks = PA_MEMPOOL_SLOTS_MAX;
 
-    pa_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);
@@ -725,8 +738,8 @@ void pa_mempool_vacuum(pa_mempool *p) {
 
     while ((slot = pa_flist_pop(list))) {
         pa_shm_punch(&p->memory,
-                     (uint8_t*) slot - (uint8_t*) p->memory.ptr + sizeof(struct mempool_slot),
-                     p->block_size - sizeof(struct mempool_slot));
+                     (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))
             ;

commit dfdf1d7d9f41144231ab40b1f6eec18f834bba1d
Author: Tanu Kaskinen <tanuk at iki.fi>
Date:   Sun Sep 9 09:39:26 2007 +0000

    Changed PA_SAMPLE_S16_NE to PA_SAMPLE_S16NE in the example code in the Simple API Doxygen documentation.
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1778 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulse/simple.h b/src/pulse/simple.h
index 128d271..f76c1d6 100644
--- a/src/pulse/simple.h
+++ b/src/pulse/simple.h
@@ -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;
  *

commit 717b1641614ed7a47c2b0188496dd39be806975c
Author: Pierre Ossman <ossman at cendio.se>
Date:   Mon Sep 10 11:19:53 2007 +0000

    POSIX realtime clock functions are in time.h so make sure to include it.
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1779 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/rtclock.c b/src/pulsecore/rtclock.c
index a4e9875..02abde3 100644
--- a/src/pulsecore/rtclock.c
+++ b/src/pulsecore/rtclock.c
@@ -27,6 +27,7 @@
 #endif
 
 #include <stddef.h>
+#include <time.h>
 #include <sys/time.h>
 
 #include <pulse/timeval.h>

commit e1766011ca68582324802aa3e9e820c3ec899aae
Author: Pierre Ossman <ossman at cendio.se>
Date:   Mon Sep 10 11:27:56 2007 +0000

    Monotonic clock is optional so treat is as such.
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1780 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/rtclock.c b/src/pulsecore/rtclock.c
index 02abde3..7dd83b3 100644
--- a/src/pulsecore/rtclock.c
+++ b/src/pulsecore/rtclock.c
@@ -139,9 +139,11 @@ struct timespec *pa_rtclock_get(struct timespec *ts) {
     pa_assert(ts);
 
     if (!no_monotonic) {
+#ifdef CLOCK_MONOTONIC
         if (clock_gettime(CLOCK_MONOTONIC, ts) >= 0)
             return ts;
-        
+#endif        
+
         no_monotonic = 1;
     }
 
@@ -152,8 +154,10 @@ struct timespec *pa_rtclock_get(struct timespec *ts) {
 int pa_rtclock_hrtimer(void) {
     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;

commit 028632fd57f84a81a0f9b70cb0b7b5ac35d789df
Author: Pierre Ossman <ossman at cendio.se>
Date:   Mon Sep 10 11:33:47 2007 +0000

    TIOCINQ isn't present on all systems.
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1781 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-pipe-sink.c b/src/modules/module-pipe-sink.c
index d5ef194..55a4e0c 100644
--- a/src/modules/module-pipe-sink.c
+++ b/src/modules/module-pipe-sink.c
@@ -98,9 +98,11 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
         case PA_SINK_MESSAGE_GET_LATENCY: {
             size_t n = 0;
             int l;
-            
+
+#ifdef TIOCINQ            
             if (ioctl(u->fd, TIOCINQ, &l) >= 0 && l > 0)
                 n = (size_t) l;
+#endif
             
             n += u->memchunk.length;
             

commit 9630e8df575ff35cab9bc95151fcbb3d56fb29fd
Author: Pierre Ossman <ossman at cendio.se>
Date:   Mon Sep 10 11:34:35 2007 +0000

    Remove mkdir_p again...
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1782 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/Makefile.am b/src/Makefile.am
index 1dfe3c2..52fa4b8 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1091,7 +1091,9 @@ EXTRA_DIST += $(SYMDEF_FILES)
 BUILT_SOURCES += $(SYMDEF_FILES)
 
 $(SYMDEF_FILES): modules/module-defs.h.m4
-	$(mkdir_p) modules modules/gconf modules/rtp
+	-mkdir modules
+	-mkdir modules/gconf
+	-mkdir modules/rtp
 	$(M4) -Dfname="$@" $< > $@
 
 # Simple protocol

commit d9b3c0eef2ba256b4e1e694c3828d1f4713ebf68
Author: Pierre Ossman <ossman at cendio.se>
Date:   Mon Sep 10 11:35:30 2007 +0000

    posix_madvise and posix_fadvise aren't present on all systems.
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1783 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/configure.ac b/configure.ac
index 71e95b8..c4f26c4 100644
--- a/configure.ac
+++ b/configure.ac
@@ -247,8 +247,8 @@ 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])
+    getuid inet_ntop inet_pton 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")
diff --git a/src/pulsecore/core-util.c b/src/pulsecore/core-util.c
index 67d33e7..13a7252 100644
--- a/src/pulsecore/core-util.c
+++ b/src/pulsecore/core-util.c
@@ -1262,11 +1262,13 @@ void *pa_will_need(const void *p, size_t l) {
 
     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
@@ -1279,7 +1281,7 @@ void *pa_will_need(const void *p, size_t l) {
     pa_assert_se(getrlimit(RLIMIT_MEMLOCK, &rlim) == 0);
     
     if (rlim.rlim_cur < PA_PAGE_SIZE) {
-        pa_log_debug("posix_madvise() failed, resource limits don't allow mlock(), can't page in data: %s", pa_cstrerror(r));
+        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;
     }
     
@@ -1288,7 +1290,7 @@ void *pa_will_need(const void *p, size_t l) {
     bs = PA_PAGE_SIZE*4;
 #endif
         
-    pa_log_debug("posix_madvise() failed, trying mlock(): %s", pa_cstrerror(r));
+    pa_log_debug("posix_madvise() failed (or doesn't exist), trying mlock(): %s", pa_cstrerror(r));
 
     while (size > 0 && bs > 0) {
 
diff --git a/src/pulsecore/sound-file-stream.c b/src/pulsecore/sound-file-stream.c
index 36c7f03..d5523a6 100644
--- a/src/pulsecore/sound-file-stream.c
+++ b/src/pulsecore/sound-file-stream.c
@@ -255,6 +255,7 @@ int pa_play_file(
      * 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;
@@ -266,6 +267,7 @@ int pa_play_file(
         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);
diff --git a/src/pulsecore/sound-file.c b/src/pulsecore/sound-file.c
index ef43eef..8727ba1 100644
--- a/src/pulsecore/sound-file.c
+++ b/src/pulsecore/sound-file.c
@@ -67,11 +67,13 @@ int pa_sound_file_load(
         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);

commit 06db9219a0445c026e57945aabc3e6dd4be52d2e
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Sep 10 14:23:00 2007 +0000

    don't call pa_source_process_msg() for PA_SOURCE_MESSAGE_GET_LATENCY, since it makes querying the latency always fail
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1784 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-oss.c b/src/modules/module-oss.c
index f36f21f..ccbb183 100644
--- a/src/modules/module-oss.c
+++ b/src/modules/module-oss.c
@@ -711,7 +711,7 @@ static int source_process_msg(pa_msgobject *o, int code, void *data, int64_t off
             }
             
             *((pa_usec_t*) data) = r;
-            break;
+            return 0;
         }
 
         case PA_SOURCE_MESSAGE_SET_STATE:

commit 27c3bd497d931afd30668955fd39c24c030d27ab
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Sep 10 18:55:36 2007 +0000

    document that the native amd64 atomic ops implementation is incomplete
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1785 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/atomic.h b/src/pulsecore/atomic.h
index 6e33c99..6fb85f0 100644
--- a/src/pulsecore/atomic.h
+++ b/src/pulsecore/atomic.h
@@ -109,6 +109,8 @@ static inline int pa_atomic_ptr_cmpxchg(pa_atomic_ptr_t *a, void *old_p, void* n
 
 #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 {

commit 44e514c51f821863ad8efe84454a0886c4dcda2a
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Sep 10 19:01:09 2007 +0000

    update todo file a little
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1787 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/todo b/todo
index 7b4ce78..f579beb 100644
--- 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

commit 69ece668ec99e5889be3c4d9a91ef78e199f0d0d
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Sep 10 19:01:33 2007 +0000

    add pulseaudio logo with text
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1788 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/pulseaudio-text.svg b/pulseaudio-text.svg
new file mode 100644
index 0000000..0e12613
--- /dev/null
+++ b/pulseaudio-text.svg
@@ -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 at 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>

commit 98f9bd62a6aab266495ef02aa49b0903f0989896
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Sep 10 20:55:01 2007 +0000

    make sure that the device volume is properly read before we call pa_sink_put() and thus make the pa_sink available
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1789 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-oss.c b/src/modules/module-oss.c
index ccbb183..1e524fc 100644
--- a/src/modules/module-oss.c
+++ b/src/modules/module-oss.c
@@ -1306,9 +1306,9 @@ go_on:
 
     /* Read mixer settings */
     if (u->source)
-        pa_asyncmsgq_post(u->thread_mq.inq, PA_MSGOBJECT(u->source), PA_SOURCE_MESSAGE_GET_VOLUME, &u->source->volume, 0, NULL, NULL);
+        pa_asyncmsgq_send(u->thread_mq.inq, PA_MSGOBJECT(u->source), PA_SOURCE_MESSAGE_GET_VOLUME, &u->source->volume, 0, NULL);
     if (u->sink)
-        pa_asyncmsgq_post(u->thread_mq.inq, PA_MSGOBJECT(u->sink), PA_SINK_MESSAGE_GET_VOLUME, &u->sink->volume, 0, NULL, NULL);
+        pa_asyncmsgq_send(u->thread_mq.inq, PA_MSGOBJECT(u->sink), PA_SINK_MESSAGE_GET_VOLUME, &u->sink->volume, 0, NULL);
 
     if (u->sink)
         pa_sink_put(u->sink);

commit 841fcb4557fcb22d569733648be4dcf035a1fa9a
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Sep 10 20:55:46 2007 +0000

    beef up comment
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1790 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/memchunk.h b/src/pulsecore/memchunk.h
index 99498d0..e6105ac 100644
--- a/src/pulsecore/memchunk.h
+++ b/src/pulsecore/memchunk.h
@@ -37,7 +37,9 @@ 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. */
+ * 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,

commit a77158e67a216168064b7552ebe0e38ad750f73b
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Sep 10 20:56:13 2007 +0000

    make the memchunk writeable before silencing it
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1791 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/sample-util.c b/src/pulsecore/sample-util.c
index 4603f7e..a1361f4 100644
--- a/src/pulsecore/sample-util.c
+++ b/src/pulsecore/sample-util.c
@@ -82,6 +82,7 @@ void pa_silence_memchunk(pa_memchunk *c, const pa_sample_spec *spec) {
     pa_assert(c->memblock);
     pa_assert(spec);
 
+    pa_memchunk_make_writable(c, 0);
     data = pa_memblock_acquire(c->memblock);
     pa_silence_memory((uint8_t*) data+c->index, c->length, spec);
     pa_memblock_release(c->memblock);

commit d5caa0205f0b81c7bfcce3bc244fd11a7231754d
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Sep 10 20:56:36 2007 +0000

    minor cleanup
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1792 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/source-output.c b/src/pulsecore/source-output.c
index 1a9bf96..4267234 100644
--- a/src/pulsecore/source-output.c
+++ b/src/pulsecore/source-output.c
@@ -283,7 +283,7 @@ void pa_source_output_push(pa_source_output *o, const pa_memchunk *chunk) {
     pa_assert(chunk);
     pa_assert(chunk->length);
 
-    if (!o->push || o->state == PA_SOURCE_OUTPUT_UNLINKED || o->state == PA_SOURCE_OUTPUT_CORKED)
+    if (!o->push || o->state == PA_SOURCE_OUTPUT_CORKED)
         return;
 
     pa_assert(o->state == PA_SOURCE_OUTPUT_RUNNING);
diff --git a/src/pulsecore/source.c b/src/pulsecore/source.c
index ee2203e..f33240e 100644
--- a/src/pulsecore/source.c
+++ b/src/pulsecore/source.c
@@ -289,7 +289,6 @@ void pa_source_post(pa_source*s, const pa_memchunk *chunk) {
 
         while ((o = pa_hashmap_iterate(s->thread_info.outputs, &state, NULL)))
             pa_source_output_push(o, chunk);
-
     }
 }
 

commit 662988650a020c72e626702b6282ce4df7b6d082
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Sep 10 20:57:17 2007 +0000

    make sure we send each memblock only once when recording, not twice
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1793 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c
index a4983a0..52cec09 100644
--- a/src/pulsecore/protocol-native.c
+++ b/src/pulsecore/protocol-native.c
@@ -425,8 +425,7 @@ static int record_stream_process_msg(pa_msgobject *o, int code, void*userdata, i
 
             if (!pa_pstream_is_pending(s->connection->pstream))
                 send_memblock(s->connection);
-            
-            pa_pstream_send_memblock(s->connection->pstream, s->index, 0, PA_SEEK_RELATIVE, chunk);
+
             break;
     }
 

commit a6f8b813aee1b387f45ff791d75d99580eab574d
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Sep 10 21:48:45 2007 +0000

    simple modernizations: s/assert/pa_assert
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1794 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulse/thread-mainloop.c b/src/pulse/thread-mainloop.c
index 4f3cacc..0ed5483 100644
--- a/src/pulse/thread-mainloop.c
+++ b/src/pulse/thread-mainloop.c
@@ -26,24 +26,24 @@
 #include <config.h>
 #endif
 
-#include <assert.h>
 #include <signal.h>
 #include <stdio.h>
 
 #ifdef HAVE_SYS_POLL_H
 #include <sys/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. */
@@ -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,36 @@ 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);
 }
diff --git a/src/pulse/timeval.c b/src/pulse/timeval.c
index ba1128c..44d74c9 100644
--- a/src/pulse/timeval.c
+++ b/src/pulse/timeval.c
@@ -79,6 +79,7 @@ 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;
+    
     pa_assert(a);
     pa_assert(b);
 
diff --git a/src/pulse/utf8.c b/src/pulse/utf8.c
index a179b3f..a02c5d1 100644
--- a/src/pulse/utf8.c
+++ b/src/pulse/utf8.c
@@ -59,14 +59,15 @@
 #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 */
@@ -75,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;
 }
 
@@ -96,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) {
@@ -179,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);
 }
 
@@ -196,18 +200,21 @@ 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);
+    new_str = pa_xnew(char, len);
 
     for (;;) {
         inbuf = (ICONV_CONST char*) str; /* Brain dead prototype for iconv() */
@@ -248,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;
 }
 
diff --git a/src/pulse/utf8.h b/src/pulse/utf8.h
index ff8dc21..ea08840 100644
--- a/src/pulse/utf8.h
+++ b/src/pulse/utf8.h
@@ -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);
 
 /** 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);
diff --git a/src/pulse/util.c b/src/pulse/util.c
index c4f2cf7..879b7bf 100644
--- a/src/pulse/util.c
+++ b/src/pulse/util.c
@@ -56,11 +56,11 @@
 #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"
 
@@ -78,7 +78,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
@@ -113,11 +114,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 +135,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 +165,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 +177,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 +212,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;
 
+    pa_assert(p);
+
     if ((fn = strrchr(p, PATH_SEP)))
         return fn+1;
 
-    return (const char*) p;
+    return (char*) p;
 }
 
 char *pa_get_fqdn(char *s, size_t l) {
@@ -221,6 +229,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;
 
diff --git a/src/pulse/util.h b/src/pulse/util.h
index 95bd86f..764678e 100644
--- a/src/pulse/util.h
+++ b/src/pulse/util.h
@@ -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);
diff --git a/src/pulse/volume.c b/src/pulse/volume.c
index 8bba834..3688b84 100644
--- a/src/pulse/volume.c
+++ b/src/pulse/volume.c
@@ -25,17 +25,18 @@
 #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;
@@ -50,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;
 
@@ -65,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];
@@ -119,9 +120,9 @@ 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;
 
@@ -141,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)
@@ -153,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++) {
 
@@ -170,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;
diff --git a/src/pulse/xmalloc.c b/src/pulse/xmalloc.c
index 1f0734c..5348dda 100644
--- a/src/pulse/xmalloc.c
+++ b/src/pulse/xmalloc.c
@@ -27,12 +27,12 @@
 
 #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();

commit de21b54bd1f1d2caa5c20da4be0dc118b0ab7c34
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Sep 10 21:58:01 2007 +0000

    add new API pa_threaded_mainloop_in_thread(), update test case for it
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1795 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulse/thread-mainloop.c b/src/pulse/thread-mainloop.c
index 0ed5483..29769e2 100644
--- a/src/pulse/thread-mainloop.c
+++ b/src/pulse/thread-mainloop.c
@@ -223,3 +223,9 @@ pa_mainloop_api* pa_threaded_mainloop_get_api(pa_threaded_mainloop*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;
+}
diff --git a/src/pulse/thread-mainloop.h b/src/pulse/thread-mainloop.h
index b78c158..ea08f72 100644
--- a/src/pulse/thread-mainloop.h
+++ b/src/pulse/thread-mainloop.h
@@ -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
diff --git a/src/tests/thread-mainloop-test.c b/src/tests/thread-mainloop-test.c
index 9d0e5de..be1f1ec 100644
--- a/src/tests/thread-mainloop-test.c
+++ b/src/tests/thread-mainloop-test.c
@@ -23,18 +23,19 @@
 #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);

commit 3d122d0fee2e3d853ea1a1de297b249f2c125f73
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Sep 10 22:17:30 2007 +0000

    s/assert/pa_assert/ modernizations
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1796 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulse/mainloop-signal.c b/src/pulse/mainloop-signal.c
index 28ddec4..18fd86f 100644
--- a/src/pulse/mainloop-signal.c
+++ b/src/pulse/mainloop-signal.c
@@ -27,7 +27,6 @@
 #endif
 
 #include <stdio.h>
-#include <assert.h>
 #include <signal.h>
 #include <errno.h>
 #include <stdlib.h>
@@ -39,12 +38,13 @@
 #include <windows.h>
 #endif
 
-#include <pulsecore/core-error.h>
 #include <pulse/xmalloc.h>
 
+#include <pulsecore/core-error.h>
 #include <pulsecore/core-util.h>
 #include <pulsecore/log.h>
 #include <pulsecore/gccmacro.h>
+#include <pulsecore/macro.h>
 
 #include "mainloop-signal.h"
 
@@ -74,11 +74,11 @@ static void signal_handler(int sig) {
 }
 
 static void dispatch(pa_mainloop_api*a, int sig) {
-    pa_signal_event*s;
+    pa_signal_event *s;
 
     for (s = signals; s; s = s->next)
         if (s->sig == sig) {
-            assert(s->callback);
+            pa_assert(s->callback);
             s->callback(a, s, sig, s->userdata);
             break;
         }
@@ -87,7 +87,12 @@ static void dispatch(pa_mainloop_api*a, int sig) {
 static void callback(pa_mainloop_api*a, pa_io_event*e, int fd, pa_io_event_flags_t f, PA_GCC_UNUSED void *userdata) {
     ssize_t r;
     int sig;
-    assert(a && e && f == PA_IO_EVENT_INPUT && e == io_event && fd == signal_pipe[0]);
+    
+    pa_assert(a);
+    pa_assert(e);
+    pa_assert(f == PA_IO_EVENT_INPUT);
+    pa_assert(e == io_event);
+    pa_assert(fd == signal_pipe[0]);
 
     if ((r = pa_read(signal_pipe[0], &sig, sizeof(sig), NULL)) < 0) {
         if (errno == EAGAIN)
@@ -107,7 +112,11 @@ 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));
@@ -116,19 +125,21 @@ int pa_signal_init(pa_mainloop_api *a) {
 
     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_assert_se(pa_fd_set_cloexec(signal_pipe[0], 1) == 0);
+    pa_assert_se(pa_fd_set_cloexec(signal_pipe[1], 1) == 0);
 
     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,8 +147,8 @@ void pa_signal_done(void) {
     api->io_free(io_event);
     io_event = NULL;
 
-    close(signal_pipe[0]);
-    close(signal_pipe[1]);
+    pa_assert_se(close(signal_pipe[0]) == 0);
+    pa_assert_se(close(signal_pipe[1]) == 0);
     signal_pipe[0] = signal_pipe[1] = -1;
 
     api = NULL;
@@ -150,13 +161,13 @@ 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 && _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 +197,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 +207,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 +219,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;
 }

commit 9b0ab39b1c443744bb7b09b03e62e51d78aab527
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Sep 10 23:57:10 2007 +0000

    unify static TLS support, make use of gcc __thread attribute if available
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1797 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/configure.ac b/configure.ac
index c4f26c4..7c8f388 100644
--- a/configure.ac
+++ b/configure.ac
@@ -118,6 +118,18 @@ 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
+
 #### libtool stuff ####
 
 AC_LTDL_ENABLE_INSTALL
diff --git a/src/daemon/main.c b/src/daemon/main.c
index 135a9ab..ed5aa44 100644
--- a/src/daemon/main.c
+++ b/src/daemon/main.c
@@ -324,14 +324,14 @@ static void libtool_unlock(void) {
     pa_mutex_unlock(libtool_mutex);
 }
 
-PA_STATIC_TLS_DECLARE(libtool_tls, NULL);
+PA_STATIC_TLS_DECLARE_NO_FREE(libtool_tls);
 
 static void libtool_set_error(const char * error) {
-    pa_tls_set(PA_STATIC_TLS_GET(libtool_tls), (char*) error);
+    PA_STATIC_TLS_SET(libtool_tls, (char*) error);
 }
 
 static const char *libtool_get_error(void) {
-    return pa_tls_get(PA_STATIC_TLS_GET(libtool_tls));
+    return PA_STATIC_TLS_GET(libtool_tls);
 }
 
 static void libtool_init(void)  {
diff --git a/src/pulsecore/atomic.h b/src/pulsecore/atomic.h
index 6fb85f0..0e3bfb9 100644
--- a/src/pulsecore/atomic.h
+++ b/src/pulsecore/atomic.h
@@ -37,7 +37,7 @@
  * libatomic_ops
  */
 
-/* We have to include config.h here, which sucks */
+/* We have to include config.h here (for the __sync stuff), which sucks */
 #ifdef HAVE_CONFIG_H
 #include <config.h>
 #endif
diff --git a/src/pulsecore/rtsig.c b/src/pulsecore/rtsig.c
index a3226a0..3513bed 100644
--- a/src/pulsecore/rtsig.c
+++ b/src/pulsecore/rtsig.c
@@ -71,13 +71,13 @@ int pa_rtsig_get_for_thread(void) {
     int sig;
     void *p;
 
-    if ((p = pa_tls_get(PA_STATIC_TLS_GET(rtsig_tls))))
+    if ((p = PA_STATIC_TLS_GET(rtsig_tls)))
         return PA_PTR_TO_INT(p);
     
     if ((sig = pa_rtsig_get()) < 0)
         return -1;
 
-    pa_tls_set(PA_STATIC_TLS_GET(rtsig_tls), PA_INT_TO_PTR(sig));
+    PA_STATIC_TLS_SET(rtsig_tls, PA_INT_TO_PTR(sig));
     return sig;
 }
 
diff --git a/src/pulsecore/thread-mq.c b/src/pulsecore/thread-mq.c
index 3c466ce..3000246 100644
--- a/src/pulsecore/thread-mq.c
+++ b/src/pulsecore/thread-mq.c
@@ -41,8 +41,7 @@
 
 #include "thread-mq.h"
 
-static pa_once once = PA_ONCE_INIT;
-static pa_tls *tls;
+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;
@@ -101,20 +100,15 @@ void pa_thread_mq_done(pa_thread_mq *q) {
     q->mainloop = NULL;
 }
 
-static void init_tls(void) {
-    tls = pa_tls_new(NULL);
-}
-
 void pa_thread_mq_install(pa_thread_mq *q) {
     pa_assert(q);
 
-    pa_run_once(&once, init_tls);
-    pa_tls_set(tls, q);
+    pa_assert(!(PA_STATIC_TLS_GET(thread_mq)));
+    PA_STATIC_TLS_SET(thread_mq, q);
 }
 
 pa_thread_mq *pa_thread_mq_get(void) {
-    pa_run_once(&once, init_tls);
-    return pa_tls_get(tls);
+    return PA_STATIC_TLS_GET(thread_mq);
 }
 
 int pa_thread_mq_process(pa_thread_mq *q) {
diff --git a/src/pulsecore/thread-posix.c b/src/pulsecore/thread-posix.c
index 6ad5ac4..3c69adf 100644
--- a/src/pulsecore/thread-posix.c
+++ b/src/pulsecore/thread-posix.c
@@ -49,9 +49,6 @@ struct pa_tls {
     pthread_key_t key;
 };
 
-static pthread_key_t thread_key;
-static pthread_once_t thread_once = PTHREAD_ONCE_INIT;
-
 static void thread_free_cb(void *p) {
     pa_thread *t = p;
 
@@ -62,9 +59,7 @@ static void thread_free_cb(void *p) {
         pa_xfree(t);
 }
 
-static void thread_once_func(void) {
-    pa_assert_se(pthread_key_create(&thread_key, thread_free_cb) == 0);
-}
+PA_STATIC_TLS_DECLARE(current_thread, thread_free_cb);
 
 static void* internal_thread_func(void *userdata) {
     pa_thread *t = userdata;
@@ -72,8 +67,7 @@ static void* internal_thread_func(void *userdata) {
 
     t->id = pthread_self();
 
-    pthread_once(&thread_once, thread_once_func);
-    pthread_setspecific(thread_key, t);
+    PA_STATIC_TLS_SET(current_thread, t);
 
     pa_atomic_inc(&t->running);
     t->thread_func(t->userdata);
@@ -130,11 +124,9 @@ int pa_thread_join(pa_thread *t) {
 pa_thread* pa_thread_self(void) {
     pa_thread *t;
 
-    pthread_once(&thread_once, thread_once_func);
-
-    if ((t = pthread_getspecific(thread_key)))
+    if ((t = PA_STATIC_TLS_GET(current_thread)))
         return t;
-
+        
     /* This is a foreign thread, let's create a pthread structure to
      * make sure that we can always return a sensible pointer */
 
@@ -144,7 +136,7 @@ pa_thread* pa_thread_self(void) {
     t->userdata = NULL;
     pa_atomic_store(&t->running, 2);
 
-    pthread_setspecific(thread_key, t);
+    PA_STATIC_TLS_SET(current_thread, t);
 
     return t;
 }
diff --git a/src/pulsecore/thread.h b/src/pulsecore/thread.h
index 44b80a0..a0e331b 100644
--- a/src/pulsecore/thread.h
+++ b/src/pulsecore/thread.h
@@ -26,6 +26,12 @@
 ***/
 
 #include <pulse/def.h>
+#include <pulsecore/once.h>
+
+/* We have to include config.h here (for the __tls stuff), which sucks */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
 
 typedef struct pa_thread pa_thread;
 
@@ -48,8 +54,6 @@ void pa_tls_free(pa_tls *t);
 void * pa_tls_get(pa_tls *t);
 void *pa_tls_set(pa_tls *t, void *userdata);
 
-/* To make use of the static TLS stuff you have to include once.h, as well */
-
 #define PA_STATIC_TLS_DECLARE(name, free_cb)                            \
     static struct {                                                     \
         pa_once once;                                                   \
@@ -61,7 +65,7 @@ void *pa_tls_set(pa_tls *t, void *userdata);
     static void name##_tls_init(void) {                                 \
         name##_tls.tls = pa_tls_new(free_cb);                           \
     }                                                                   \
-    static inline pa_tls* name##_tls_get(void) {                        \
+    static inline pa_tls* name##_tls_obj(void) {                        \
         pa_run_once(&name##_tls.once, name##_tls_init);                 \
         return name##_tls.tls;                                          \
     }                                                                   \
@@ -70,8 +74,33 @@ void *pa_tls_set(pa_tls *t, void *userdata);
         if (name##_tls.tls)                                             \
             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;                                   \
+    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

commit 848a4d7487bdce14f8231698666fb24d5397e091
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Sep 11 00:24:10 2007 +0000

    more s/assert/pa_assert/ modernizations
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1798 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulse/channelmap.c b/src/pulse/channelmap.c
index c53626f..2b8ef2b 100644
--- a/src/pulse/channelmap.c
+++ b/src/pulse/channelmap.c
@@ -27,12 +27,12 @@
 #endif
 
 #include <stdlib.h>
-#include <assert.h>
 #include <stdio.h>
 #include <string.h>
 
 #include <pulse/xmalloc.h>
 #include <pulsecore/core-util.h>
+#include <pulsecore/macro.h>
 
 #include "channelmap.h"
 
@@ -164,7 +164,7 @@ const char *const pretty_table[] = {
 
 pa_channel_map* pa_channel_map_init(pa_channel_map *m) {
     unsigned c;
-    assert(m);
+    pa_assert(m);
 
     m->channels = 0;
 
@@ -175,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);
 
@@ -185,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);
 
@@ -196,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);
 
@@ -415,8 +415,8 @@ const char* pa_channel_position_to_pretty_string(pa_channel_position_t 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;
@@ -433,9 +433,9 @@ 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;
 
@@ -456,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));
 
@@ -517,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;
diff --git a/src/pulse/client-conf-x11.c b/src/pulse/client-conf-x11.c
index e8de955..e240ba8 100644
--- a/src/pulse/client-conf-x11.c
+++ b/src/pulse/client-conf-x11.c
@@ -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;
diff --git a/src/pulse/client-conf.c b/src/pulse/client-conf.c
index bb91233..d1e9969 100644
--- a/src/pulse/client-conf.c
+++ b/src/pulse/client-conf.c
@@ -27,14 +27,14 @@
 #endif
 
 #include <stdlib.h>
-#include <assert.h>
 #include <unistd.h>
 #include <errno.h>
 #include <string.h>
 
-#include <pulsecore/core-error.h>
 #include <pulse/xmalloc.h>
 
+#include <pulsecore/macro.h>
+#include <pulsecore/core-error.h>
 #include <pulsecore/log.h>
 #include <pulsecore/conf-parser.h>
 #include <pulsecore/core-util.h>
@@ -81,7 +81,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 +90,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 +123,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("WARNING: failed to open configuration file '%s': %s", fn, pa_cstrerror(errno));
         goto finish;
     }
 
@@ -175,7 +176,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;
 
diff --git a/src/pulse/mainloop-api.c b/src/pulse/mainloop-api.c
index 001ff31..989a5cc 100644
--- a/src/pulse/mainloop-api.c
+++ b/src/pulse/mainloop-api.c
@@ -25,12 +25,12 @@
 #include <config.h>
 #endif
 
-#include <assert.h>
 #include <stdlib.h>
 
 #include <pulse/xmalloc.h>
 
 #include <pulsecore/gccmacro.h>
+#include <pulsecore/macro.h>
 
 #include "mainloop-api.h"
 
@@ -41,32 +41,38 @@ struct once_info {
 
 static void once_callback(pa_mainloop_api *m, pa_defer_event *e, void *userdata) {
     struct once_info *i = userdata;
-    assert(m && i && i->callback);
-
+    
+    pa_assert(m);
+    pa_assert(i);
+    
+    pa_assert(i->callback);
     i->callback(m, i->userdata);
 
-    assert(m->defer_free);
+    pa_assert(m->defer_free);
     m->defer_free(e);
 }
 
 static void free_callback(pa_mainloop_api *m, PA_GCC_UNUSED pa_defer_event *e, void *userdata) {
     struct once_info *i = userdata;
-    assert(m && i);
+
+    pa_assert(m);
+    pa_assert(i);
     pa_xfree(i);
 }
 
 void pa_mainloop_api_once(pa_mainloop_api* m, void (*callback)(pa_mainloop_api *m, void *userdata), void *userdata) {
     struct once_info *i;
     pa_defer_event *e;
-    assert(m && callback);
+
+    pa_assert(m);
+    pa_assert(callback);
 
     i = pa_xnew(struct once_info, 1);
     i->callback = callback;
     i->userdata = userdata;
 
-    assert(m->defer_new);
-    e = m->defer_new(m, once_callback, i);
-    assert(e);
+    pa_assert(m->defer_new);
+    pa_assert_se(e = m->defer_new(m, once_callback, i));
     m->defer_set_destroy(e, free_callback);
 }
 
diff --git a/src/pulse/mainloop.c b/src/pulse/mainloop.c
index 0dd0e11..a5304ff 100644
--- a/src/pulse/mainloop.c
+++ b/src/pulse/mainloop.c
@@ -31,29 +31,28 @@
 #include <unistd.h>
 #include <stdlib.h>
 #include <string.h>
-#include <assert.h>
 #include <fcntl.h>
 #include <errno.h>
 
 #ifdef HAVE_SYS_POLL_H
 #include <sys/poll.h>
 #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;
@@ -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,22 +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;
 }
@@ -326,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;
@@ -343,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;
@@ -363,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++;
@@ -378,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;
@@ -387,14 +386,14 @@ 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;
     }
@@ -406,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;
 }
@@ -417,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);
 }
@@ -506,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--;
             }
 
@@ -521,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) {
@@ -538,12 +537,12 @@ 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;
             }
@@ -557,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) {
@@ -574,12 +573,12 @@ 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;
             }
@@ -593,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);
@@ -615,7 +614,7 @@ void pa_mainloop_free(pa_mainloop* m) {
 }
 
 static void scan_dead(pa_mainloop *m) {
-    assert(m);
+    pa_assert(m);
 
     if (m->io_events_please_scan)
         cleanup_io_events(m, 0);
@@ -672,13 +671,13 @@ 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 && e->callback);
         e->callback(&m->api, e, e->fd, map_flags_from_libc(e->pollfd->revents), e->userdata);
         e->pollfd->revents = 0;
         r++;
@@ -700,7 +699,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++;
     }
@@ -710,7 +709,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;
@@ -742,7 +741,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;
@@ -760,7 +759,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;
@@ -773,7 +772,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);
@@ -789,7 +788,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);
@@ -800,7 +799,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;
@@ -812,8 +811,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);
@@ -839,8 +838,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;
@@ -850,7 +849,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);
@@ -876,8 +875,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;
@@ -908,13 +907,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;
@@ -948,7 +947,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;
@@ -956,12 +955,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;
diff --git a/src/pulse/operation.c b/src/pulse/operation.c
index f23def5..9ea4e63 100644
--- a/src/pulse/operation.c
+++ b/src/pulse/operation.c
@@ -25,16 +25,15 @@
 #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;
@@ -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(o->ref >= 1);
 
     o->ref++;
     return o;
 }
 
 void pa_operation_unref(pa_operation *o) {
-    assert(o);
-    assert(o->ref >= 1);
+    pa_assert(o);
+    pa_assert(o->ref >= 1);
 
     if ((--(o->ref)) == 0) {
-        assert(!o->context);
-        assert(!o->stream);
+        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(o->ref >= 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(o->ref >= 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(o->ref >= 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(o->ref >= 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(o->ref >= 1);
 
     return o->state;
 }

commit e2e2ce79e2697ecbd36e2cf00249dc8c59af232d
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Sep 11 00:30:53 2007 +0000

    Instead of including config.h from header files, check whether PACKAGE is defined and if not, fail (thus using PACKAGE as a check for inclusion of config.h)
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1799 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/atomic.h b/src/pulsecore/atomic.h
index 0e3bfb9..25d600c 100644
--- a/src/pulsecore/atomic.h
+++ b/src/pulsecore/atomic.h
@@ -37,9 +37,8 @@
  * libatomic_ops
  */
 
-/* We have to include config.h here (for the __sync stuff), which sucks */
-#ifdef HAVE_CONFIG_H
-#include <config.h>
+#ifndef PACKAGE
+#error "Please include config.h before including this file!"
 #endif
 
 #ifdef HAVE_ATOMIC_BUILTINS
diff --git a/src/pulsecore/creds.h b/src/pulsecore/creds.h
index e0a025b..51dfc33 100644
--- a/src/pulsecore/creds.h
+++ b/src/pulsecore/creds.h
@@ -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>
diff --git a/src/pulsecore/endianmacros.h b/src/pulsecore/endianmacros.h
index c0c3a6d..a29699b 100644
--- a/src/pulsecore/endianmacros.h
+++ b/src/pulsecore/endianmacros.h
@@ -27,8 +27,8 @@
 
 #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) ) )
diff --git a/src/pulsecore/macro.h b/src/pulsecore/macro.h
index 53e52fd..c1bdb14 100644
--- a/src/pulsecore/macro.h
+++ b/src/pulsecore/macro.h
@@ -32,6 +32,10 @@
 
 #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)
diff --git a/src/pulsecore/thread.h b/src/pulsecore/thread.h
index a0e331b..4e5425d 100644
--- a/src/pulsecore/thread.h
+++ b/src/pulsecore/thread.h
@@ -28,9 +28,8 @@
 #include <pulse/def.h>
 #include <pulsecore/once.h>
 
-/* We have to include config.h here (for the __tls stuff), which sucks */
-#ifdef HAVE_CONFIG_H
-#include <config.h>
+#ifndef PACKAGE
+#error "Please include config.h before including this file!"
 #endif
 
 typedef struct pa_thread pa_thread;

commit 6ac66e453f9c2007e9b1c6f3776c55eca0cd9140
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Sep 11 00:56:21 2007 +0000

    add missing config.h includes
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1800 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/authkey-prop.c b/src/pulsecore/authkey-prop.c
index 3b8304b..146d7ca 100644
--- a/src/pulsecore/authkey-prop.c
+++ b/src/pulsecore/authkey-prop.c
@@ -21,6 +21,10 @@
   USA.
 ***/
 
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
 #include <assert.h>
 #include <string.h>
 
diff --git a/src/pulsecore/props.c b/src/pulsecore/props.c
index 4a39f0f..37e7419 100644
--- a/src/pulsecore/props.c
+++ b/src/pulsecore/props.c
@@ -21,6 +21,10 @@
   USA.
 ***/
 
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
 #include <assert.h>
 
 #include <pulse/xmalloc.h>
diff --git a/src/pulsecore/x11wrap.c b/src/pulsecore/x11wrap.c
index 067b7df..1bcbcd4 100644
--- a/src/pulsecore/x11wrap.c
+++ b/src/pulsecore/x11wrap.c
@@ -21,6 +21,10 @@
   USA.
 ***/
 
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
 #include <assert.h>
 #include <stdio.h>
 

commit 55d9fcb126247041a8934a060e1a441a26b2be8d
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Sep 11 01:00:33 2007 +0000

    add globally defined PA_PATH_SEP macro, replacing private per-file macros
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1801 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/daemon/daemon-conf.c b/src/daemon/daemon-conf.c
index 7b503f8..ff62816 100644
--- a/src/daemon/daemon-conf.c
+++ b/src/daemon/daemon-conf.c
@@ -42,16 +42,10 @@
 
 #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"
diff --git a/src/pulse/client-conf.c b/src/pulse/client-conf.c
index d1e9969..447d185 100644
--- a/src/pulse/client-conf.c
+++ b/src/pulse/client-conf.c
@@ -42,13 +42,7 @@
 
 #include "client-conf.h"
 
-#ifndef OS_IS_WIN32
-# define PATH_SEP "/"
-#else
-# define PATH_SEP "\\"
-#endif
-
-#define DEFAULT_CLIENT_CONFIG_FILE PA_DEFAULT_CONFIG_DIR PATH_SEP "client.conf"
+#define DEFAULT_CLIENT_CONFIG_FILE PA_DEFAULT_CONFIG_DIR PA_PATH_SEP "client.conf"
 #define DEFAULT_CLIENT_CONFIG_FILE_USER "client.conf"
 
 #define ENV_CLIENT_CONFIG_FILE "PULSE_CLIENTCONFIG"
diff --git a/src/pulse/util.c b/src/pulse/util.c
index 879b7bf..32f4137 100644
--- a/src/pulse/util.c
+++ b/src/pulse/util.c
@@ -64,12 +64,6 @@
 
 #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];
@@ -217,7 +211,7 @@ char *pa_path_get_filename(const char *p) {
 
     pa_assert(p);
 
-    if ((fn = strrchr(p, PATH_SEP)))
+    if ((fn = strrchr(p, PA_PATH_SEP_CHAR)))
         return fn+1;
 
     return (char*) p;
diff --git a/src/pulsecore/core-util.c b/src/pulsecore/core-util.c
index 13a7252..d37a11c 100644
--- a/src/pulsecore/core-util.c
+++ b/src/pulsecore/core-util.c
@@ -100,10 +100,8 @@
 
 #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
@@ -118,7 +116,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';
 
@@ -1123,7 +1121,7 @@ char *pa_runtime_path(const char *fn, char *s, size_t l) {
     if ((e = getenv("PULSE_RUNTIME_PATH"))) {
 
         if (fn)
-            pa_snprintf(s, l, "%s%c%s", e, PATH_SEP, fn);
+            pa_snprintf(s, l, "%s%c%s", e, PA_PATH_SEP_CHAR, fn);
         else
             pa_snprintf(s, l, "%s", e);
 
@@ -1131,7 +1129,7 @@ char *pa_runtime_path(const char *fn, char *s, size_t l) {
         char u[256];
 
         if (fn)
-            pa_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
             pa_snprintf(s, l, "%s%s", PA_USER_RUNTIME_PATH_PREFIX, pa_get_user_name(u, sizeof(u)));
     }
diff --git a/src/pulsecore/macro.h b/src/pulsecore/macro.h
index c1bdb14..c46ae52 100644
--- a/src/pulsecore/macro.h
+++ b/src/pulsecore/macro.h
@@ -114,4 +114,12 @@ static inline size_t pa_page_align(size_t l) {
 #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

commit 597a1c4e82f2bb84e983d0cbb9be7e79c5607c00
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Sep 11 12:42:17 2007 +0000

    port client libs to refcnt.h
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1802 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulse/context.c b/src/pulse/context.c
index 8125c64..c168502 100644
--- a/src/pulse/context.c
+++ b/src/pulse/context.c
@@ -110,7 +110,7 @@ pa_context *pa_context_new(pa_mainloop_api *mainloop, const char *name) {
     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;
@@ -207,23 +207,23 @@ static void context_free(pa_context *c) {
 
 pa_context* pa_context_ref(pa_context *c) {
     assert(c);
-    assert(c->ref >= 1);
+    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);
+    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);
+    assert(PA_REFCNT_VALUE(c) >= 1);
 
     if (c->state == st)
         return;
@@ -265,7 +265,7 @@ 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);
+    assert(PA_REFCNT_VALUE(c) >= 1);
 
     pa_context_set_error(c, error);
     pa_context_set_state(c, PA_CONTEXT_FAILED);
@@ -314,7 +314,7 @@ static void pstream_memblock_callback(pa_pstream *p, uint32_t channel, int64_t o
     assert(chunk->memblock);
     assert(chunk->length);
     assert(c);
-    assert(c->ref >= 1);
+    assert(PA_REFCNT_VALUE(c) >= 1);
 
     pa_context_ref(c);
 
@@ -338,7 +338,7 @@ 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);
+    assert(PA_REFCNT_VALUE(c) >= 1);
 
     if (command == PA_COMMAND_ERROR) {
         assert(t);
@@ -684,7 +684,7 @@ int pa_context_connect(
     int r = -1;
 
     assert(c);
-    assert(c->ref >= 1);
+    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);
@@ -756,28 +756,28 @@ finish:
 
 void pa_context_disconnect(pa_context *c) {
     assert(c);
-    assert(c->ref >= 1);
+    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);
+    assert(PA_REFCNT_VALUE(c) >= 1);
 
     return c->state;
 }
 
 int pa_context_errno(pa_context *c) {
     assert(c);
-    assert(c->ref >= 1);
+    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);
+    assert(PA_REFCNT_VALUE(c) >= 1);
 
     c->state_callback = cb;
     c->state_userdata = userdata;
@@ -785,7 +785,7 @@ void pa_context_set_state_callback(pa_context *c, pa_context_notify_cb_t cb, voi
 
 int pa_context_is_pending(pa_context *c) {
     assert(c);
-    assert(c->ref >= 1);
+    assert(PA_REFCNT_VALUE(c) >= 1);
 
     PA_CHECK_VALIDITY(c,
                       c->state == PA_CONTEXT_CONNECTING ||
@@ -812,9 +812,9 @@ static void set_dispatch_callbacks(pa_operation *o) {
     int done = 1;
 
     assert(o);
-    assert(o->ref >= 1);
+    assert(PA_REFCNT_VALUE(o) >= 1);
     assert(o->context);
-    assert(o->context->ref >= 1);
+    assert(PA_REFCNT_VALUE(o->context) >= 1);
     assert(o->context->state == PA_CONTEXT_READY);
 
     pa_pstream_set_drain_callback(o->context->pstream, NULL, NULL);
@@ -845,7 +845,7 @@ pa_operation* pa_context_drain(pa_context *c, pa_context_notify_cb_t cb, void *u
     pa_operation *o;
 
     assert(c);
-    assert(c->ref >= 1);
+    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);
@@ -862,7 +862,7 @@ void pa_context_simple_ack_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_U
 
     assert(pd);
     assert(o);
-    assert(o->ref >= 1);
+    assert(PA_REFCNT_VALUE(o) >= 1);
 
     if (!o->context)
         goto finish;
@@ -893,7 +893,7 @@ pa_operation* pa_context_exit_daemon(pa_context *c, pa_context_success_cb_t cb,
     uint32_t tag;
 
     assert(c);
-    assert(c->ref >= 1);
+    assert(PA_REFCNT_VALUE(c) >= 1);
 
     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
 
@@ -912,7 +912,7 @@ pa_operation* pa_context_send_simple_command(pa_context *c, uint32_t command, pa
     uint32_t tag;
 
     assert(c);
-    assert(c->ref >= 1);
+    assert(PA_REFCNT_VALUE(c) >= 1);
 
     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
 
@@ -931,7 +931,7 @@ pa_operation* pa_context_set_default_sink(pa_context *c, const char *name, pa_co
     uint32_t tag;
 
     assert(c);
-    assert(c->ref >= 1);
+    assert(PA_REFCNT_VALUE(c) >= 1);
 
     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
 
@@ -951,7 +951,7 @@ pa_operation* pa_context_set_default_source(pa_context *c, const char *name, pa_
     uint32_t tag;
 
     assert(c);
-    assert(c->ref >= 1);
+    assert(PA_REFCNT_VALUE(c) >= 1);
 
     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
 
@@ -977,7 +977,7 @@ pa_operation* pa_context_set_name(pa_context *c, const char *name, pa_context_su
     uint32_t tag;
 
     assert(c);
-    assert(c->ref >= 1);
+    assert(PA_REFCNT_VALUE(c) >= 1);
     assert(name);
 
     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
@@ -998,7 +998,7 @@ const char* pa_get_library_version(void) {
 
 const char* pa_context_get_server(pa_context *c) {
     assert(c);
-    assert(c->ref >= 1);
+    assert(PA_REFCNT_VALUE(c) >= 1);
 
     if (!c->server)
         return NULL;
@@ -1017,7 +1017,7 @@ 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);
+    assert(PA_REFCNT_VALUE(c) >= 1);
 
     return c->version;
 }
diff --git a/src/pulse/internal.h b/src/pulse/internal.h
index e5c9ef1..95593ad 100644
--- a/src/pulse/internal.h
+++ b/src/pulse/internal.h
@@ -41,13 +41,14 @@
 #include <pulsecore/mcalign.h>
 #include <pulsecore/memblockq.h>
 #include <pulsecore/hashmap.h>
+#include <pulsecore/refcnt.h>
 
 #include "client-conf.h"
 
 #define DEFAULT_TIMEOUT (30)
 
 struct pa_context {
-    int ref;
+    PA_REFCNT_DECLARE;
 
     char *name;
     pa_mainloop_api* mainloop;
@@ -96,7 +97,7 @@ typedef struct pa_index_correction {
 } pa_index_correction;
 
 struct pa_stream {
-    int ref;
+    PA_REFCNT_DECLARE;
     pa_context *context;
     pa_mainloop_api *mainloop;
     PA_LLIST_FIELDS(pa_stream);
@@ -161,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;
 
diff --git a/src/pulse/introspect.c b/src/pulse/introspect.c
index 568749d..1d2f52e 100644
--- a/src/pulse/introspect.c
+++ b/src/pulse/introspect.c
@@ -45,7 +45,7 @@ static void context_stat_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNU
 
     assert(pd);
     assert(o);
-    assert(o->ref >= 1);
+    assert(PA_REFCNT_VALUE(o) >= 1);
 
     memset(&i, 0, sizeof(i));
     
@@ -88,7 +88,7 @@ static void context_get_server_info_callback(pa_pdispatch *pd, uint32_t command,
 
     assert(pd);
     assert(o);
-    assert(o->ref >= 1);
+    assert(PA_REFCNT_VALUE(o) >= 1);
 
     memset(&i, 0, sizeof(i));
     
@@ -135,7 +135,7 @@ static void context_get_sink_info_callback(pa_pdispatch *pd, uint32_t command, P
 
     assert(pd);
     assert(o);
-    assert(o->ref >= 1);
+    assert(PA_REFCNT_VALUE(o) >= 1);
 
     if (!o->context)
         goto finish;
@@ -199,7 +199,7 @@ pa_operation* pa_context_get_sink_info_by_index(pa_context *c, uint32_t idx, pa_
     uint32_t tag;
 
     assert(c);
-    assert(c->ref >= 1);
+    assert(PA_REFCNT_VALUE(c) >= 1);
     assert(cb);
 
     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
@@ -221,7 +221,7 @@ pa_operation* pa_context_get_sink_info_by_name(pa_context *c, const char *name,
     uint32_t tag;
 
     assert(c);
-    assert(c->ref >= 1);
+    assert(PA_REFCNT_VALUE(c) >= 1);
     assert(cb);
 
     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
@@ -246,7 +246,7 @@ static void context_get_source_info_callback(pa_pdispatch *pd, uint32_t command,
 
     assert(pd);
     assert(o);
-    assert(o->ref >= 1);
+    assert(PA_REFCNT_VALUE(o) >= 1);
 
     if (!o->context)
         goto finish;
@@ -310,7 +310,7 @@ pa_operation* pa_context_get_source_info_by_index(pa_context *c, uint32_t idx, p
     uint32_t tag;
 
     assert(c);
-    assert(c->ref >= 1);
+    assert(PA_REFCNT_VALUE(c) >= 1);
     assert(cb);
 
     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
@@ -332,7 +332,7 @@ pa_operation* pa_context_get_source_info_by_name(pa_context *c, const char *name
     uint32_t tag;
 
     assert(c);
-    assert(c->ref >= 1);
+    assert(PA_REFCNT_VALUE(c) >= 1);
     assert(cb);
 
     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
@@ -357,7 +357,7 @@ static void context_get_client_info_callback(pa_pdispatch *pd, uint32_t command,
 
     assert(pd);
     assert(o);
-    assert(o->ref >= 1);
+    assert(PA_REFCNT_VALUE(o) >= 1);
 
     if (!o->context)
         goto finish;
@@ -404,7 +404,7 @@ pa_operation* pa_context_get_client_info(pa_context *c, uint32_t idx, pa_client_
     uint32_t tag;
 
     assert(c);
-    assert(c->ref >= 1);
+    assert(PA_REFCNT_VALUE(c) >= 1);
     assert(cb);
 
     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
@@ -432,7 +432,7 @@ static void context_get_module_info_callback(pa_pdispatch *pd, uint32_t command,
 
     assert(pd);
     assert(o);
-    assert(o->ref >= 1);
+    assert(PA_REFCNT_VALUE(o) >= 1);
 
     if (!o->context)
         goto finish;
@@ -480,7 +480,7 @@ pa_operation* pa_context_get_module_info(pa_context *c, uint32_t idx, pa_module_
     uint32_t tag;
 
     assert(c);
-    assert(c->ref >= 1);
+    assert(PA_REFCNT_VALUE(c) >= 1);
     assert(cb);
 
     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
@@ -508,7 +508,7 @@ static void context_get_sink_input_info_callback(pa_pdispatch *pd, uint32_t comm
 
     assert(pd);
     assert(o);
-    assert(o->ref >= 1);
+    assert(PA_REFCNT_VALUE(o) >= 1);
 
     if (!o->context)
         goto finish;
@@ -565,7 +565,7 @@ pa_operation* pa_context_get_sink_input_info(pa_context *c, uint32_t idx, pa_sin
     uint32_t tag;
 
     assert(c);
-    assert(c->ref >= 1);
+    assert(PA_REFCNT_VALUE(c) >= 1);
     assert(cb);
 
     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
@@ -593,7 +593,7 @@ static void context_get_source_output_info_callback(pa_pdispatch *pd, uint32_t c
 
     assert(pd);
     assert(o);
-    assert(o->ref >= 1);
+    assert(PA_REFCNT_VALUE(o) >= 1);
 
     if (!o->context)
         goto finish;
@@ -649,7 +649,7 @@ pa_operation* pa_context_get_source_output_info(pa_context *c, uint32_t idx, pa_
     uint32_t tag;
 
     assert(c);
-    assert(c->ref >= 1);
+    assert(PA_REFCNT_VALUE(c) >= 1);
     assert(cb);
 
     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
@@ -677,7 +677,7 @@ pa_operation* pa_context_set_sink_volume_by_index(pa_context *c, uint32_t idx, c
     uint32_t tag;
 
     assert(c);
-    assert(c->ref >= 1);
+    assert(PA_REFCNT_VALUE(c) >= 1);
     assert(volume);
 
     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
@@ -701,7 +701,7 @@ pa_operation* pa_context_set_sink_volume_by_name(pa_context *c, const char *name
     uint32_t tag;
 
     assert(c);
-    assert(c->ref >= 1);
+    assert(PA_REFCNT_VALUE(c) >= 1);
     assert(name);
     assert(volume);
 
@@ -727,7 +727,7 @@ pa_operation* pa_context_set_sink_mute_by_index(pa_context *c, uint32_t idx, int
     uint32_t tag;
 
     assert(c);
-    assert(c->ref >= 1);
+    assert(PA_REFCNT_VALUE(c) >= 1);
 
     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
 
@@ -749,7 +749,7 @@ pa_operation* pa_context_set_sink_mute_by_name(pa_context *c, const char *name,
     uint32_t tag;
 
     assert(c);
-    assert(c->ref >= 1);
+    assert(PA_REFCNT_VALUE(c) >= 1);
     assert(name);
 
     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
@@ -773,7 +773,7 @@ pa_operation* pa_context_set_sink_input_volume(pa_context *c, uint32_t idx, cons
     uint32_t tag;
 
     assert(c);
-    assert(c->ref >= 1);
+    assert(PA_REFCNT_VALUE(c) >= 1);
     assert(volume);
 
     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
@@ -797,7 +797,7 @@ pa_operation* pa_context_set_sink_input_mute(pa_context *c, uint32_t idx, int mu
     uint32_t tag;
 
     assert(c);
-    assert(c->ref >= 1);
+    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);
@@ -820,7 +820,7 @@ pa_operation* pa_context_set_source_volume_by_index(pa_context *c, uint32_t idx,
     uint32_t tag;
 
     assert(c);
-    assert(c->ref >= 1);
+    assert(PA_REFCNT_VALUE(c) >= 1);
     assert(volume);
 
     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
@@ -844,7 +844,7 @@ pa_operation* pa_context_set_source_volume_by_name(pa_context *c, const char *na
     uint32_t tag;
 
     assert(c);
-    assert(c->ref >= 1);
+    assert(PA_REFCNT_VALUE(c) >= 1);
     assert(name);
     assert(volume);
 
@@ -870,7 +870,7 @@ pa_operation* pa_context_set_source_mute_by_index(pa_context *c, uint32_t idx, i
     uint32_t tag;
 
     assert(c);
-    assert(c->ref >= 1);
+    assert(PA_REFCNT_VALUE(c) >= 1);
 
     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
 
@@ -892,7 +892,7 @@ pa_operation* pa_context_set_source_mute_by_name(pa_context *c, const char *name
     uint32_t tag;
 
     assert(c);
-    assert(c->ref >= 1);
+    assert(PA_REFCNT_VALUE(c) >= 1);
     assert(name);
 
     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
@@ -918,7 +918,7 @@ static void context_get_sample_info_callback(pa_pdispatch *pd, uint32_t command,
 
     assert(pd);
     assert(o);
-    assert(o->ref >= 1);
+    assert(PA_REFCNT_VALUE(o) >= 1);
 
     if (!o->context)
         goto finish;
@@ -972,7 +972,7 @@ pa_operation* pa_context_get_sample_info_by_name(pa_context *c, const char *name
     uint32_t tag;
 
     assert(c);
-    assert(c->ref >= 1);
+    assert(PA_REFCNT_VALUE(c) >= 1);
     assert(cb);
 
     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
@@ -995,7 +995,7 @@ pa_operation* pa_context_get_sample_info_by_index(pa_context *c, uint32_t idx, p
     uint32_t tag;
 
     assert(c);
-    assert(c->ref >= 1);
+    assert(PA_REFCNT_VALUE(c) >= 1);
     assert(cb);
 
     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
@@ -1022,7 +1022,7 @@ static pa_operation* command_kill(pa_context *c, uint32_t command, uint32_t idx,
     uint32_t tag;
 
     assert(c);
-    assert(c->ref >= 1);
+    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);
@@ -1055,7 +1055,7 @@ static void context_index_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UN
 
     assert(pd);
     assert(o);
-    assert(o->ref >= 1);
+    assert(PA_REFCNT_VALUE(o) >= 1);
 
     if (!o->context)
         goto finish;
@@ -1088,7 +1088,7 @@ pa_operation* pa_context_load_module(pa_context *c, const char*name, const char
     uint32_t tag;
 
     assert(c);
-    assert(c->ref >= 1);
+    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);
@@ -1116,7 +1116,7 @@ static void context_get_autoload_info_callback(pa_pdispatch *pd, uint32_t comman
 
     assert(pd);
     assert(o);
-    assert(o->ref >= 1);
+    assert(PA_REFCNT_VALUE(o) >= 1);
 
     if (!o->context)
         goto finish;
@@ -1165,7 +1165,7 @@ pa_operation* pa_context_get_autoload_info_by_name(pa_context *c, const char *na
     uint32_t tag;
 
     assert(c);
-    assert(c->ref >= 1);
+    assert(PA_REFCNT_VALUE(c) >= 1);
     assert(cb);
 
     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
@@ -1189,7 +1189,7 @@ pa_operation* pa_context_get_autoload_info_by_index(pa_context *c, uint32_t idx,
     uint32_t tag;
 
     assert(c);
-    assert(c->ref >= 1);
+    assert(PA_REFCNT_VALUE(c) >= 1);
     assert(cb);
 
     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
@@ -1215,7 +1215,7 @@ pa_operation* pa_context_add_autoload(pa_context *c, const char *name, pa_autolo
     uint32_t tag;
 
     assert(c);
-    assert(c->ref >= 1);
+    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);
@@ -1241,7 +1241,7 @@ pa_operation* pa_context_remove_autoload_by_name(pa_context *c, const char *name
     uint32_t tag;
 
     assert(c);
-    assert(c->ref >= 1);
+    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);
@@ -1264,7 +1264,7 @@ pa_operation* pa_context_remove_autoload_by_index(pa_context *c, uint32_t idx, p
     uint32_t tag;
 
     assert(c);
-    assert(c->ref >= 1);
+    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);
@@ -1285,7 +1285,7 @@ pa_operation* pa_context_move_sink_input_by_name(pa_context *c, uint32_t idx, ch
     uint32_t tag;
 
     assert(c);
-    assert(c->ref >= 1);
+    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);
@@ -1310,7 +1310,7 @@ pa_operation* pa_context_move_sink_input_by_index(pa_context *c, uint32_t idx, u
     uint32_t tag;
 
     assert(c);
-    assert(c->ref >= 1);
+    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);
@@ -1335,7 +1335,7 @@ pa_operation* pa_context_move_source_output_by_name(pa_context *c, uint32_t idx,
     uint32_t tag;
 
     assert(c);
-    assert(c->ref >= 1);
+    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);
@@ -1360,7 +1360,7 @@ pa_operation* pa_context_move_source_output_by_index(pa_context *c, uint32_t idx
     uint32_t tag;
 
     assert(c);
-    assert(c->ref >= 1);
+    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);
@@ -1385,7 +1385,7 @@ pa_operation* pa_context_suspend_sink_by_name(pa_context *c, char *sink_name, in
     uint32_t tag;
 
     assert(c);
-    assert(c->ref >= 1);
+    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);
@@ -1409,7 +1409,7 @@ pa_operation* pa_context_suspend_sink_by_index(pa_context *c, uint32_t idx, int
     uint32_t tag;
 
     assert(c);
-    assert(c->ref >= 1);
+    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);
@@ -1432,7 +1432,7 @@ pa_operation* pa_context_suspend_source_by_name(pa_context *c, char *source_name
     uint32_t tag;
 
     assert(c);
-    assert(c->ref >= 1);
+    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);
@@ -1456,7 +1456,7 @@ pa_operation* pa_context_suspend_source_by_index(pa_context *c, uint32_t idx, in
     uint32_t tag;
 
     assert(c);
-    assert(c->ref >= 1);
+    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);
diff --git a/src/pulse/operation.c b/src/pulse/operation.c
index 9ea4e63..ed5eb4a 100644
--- a/src/pulse/operation.c
+++ b/src/pulse/operation.c
@@ -36,7 +36,7 @@ pa_operation *pa_operation_new(pa_context *c, pa_stream *s, pa_operation_cb_t cb
     pa_assert(c);
 
     o = pa_xnew(pa_operation, 1);
-    o->ref = 1;
+    PA_REFCNT_INIT(o);
     o->context = c;
     o->stream = s;
 
@@ -53,17 +53,17 @@ pa_operation *pa_operation_new(pa_context *c, pa_stream *s, pa_operation_cb_t cb
 
 pa_operation *pa_operation_ref(pa_operation *o) {
     pa_assert(o);
-    pa_assert(o->ref >= 1);
+    pa_assert(PA_REFCNT_VALUE(o) >= 1);
 
-    o->ref++;
+    PA_REFCNT_INC(o);
     return o;
 }
 
 void pa_operation_unref(pa_operation *o) {
     pa_assert(o);
-    pa_assert(o->ref >= 1);
+    pa_assert(PA_REFCNT_VALUE(o) >= 1);
 
-    if ((--(o->ref)) == 0) {
+    if (PA_REFCNT_DEC(o) <= 0) {
         pa_assert(!o->context);
         pa_assert(!o->stream);
         pa_xfree(o);
@@ -72,7 +72,7 @@ void pa_operation_unref(pa_operation *o) {
 
 static void operation_set_state(pa_operation *o, pa_operation_state_t st) {
     pa_assert(o);
-    pa_assert(o->ref >= 1);
+    pa_assert(PA_REFCNT_VALUE(o) >= 1);
 
     if (st == o->state)
         return;
@@ -84,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) {
-            pa_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,21 +101,21 @@ static void operation_set_state(pa_operation *o, pa_operation_state_t st) {
 
 void pa_operation_cancel(pa_operation *o) {
     pa_assert(o);
-    pa_assert(o->ref >= 1);
+    pa_assert(PA_REFCNT_VALUE(o) >= 1);
 
     operation_set_state(o, PA_OPERATION_CANCELED);
 }
 
 void pa_operation_done(pa_operation *o) {
     pa_assert(o);
-    pa_assert(o->ref >= 1);
+    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) {
     pa_assert(o);
-    pa_assert(o->ref >= 1);
+    pa_assert(PA_REFCNT_VALUE(o) >= 1);
 
     return o->state;
 }
diff --git a/src/pulse/scache.c b/src/pulse/scache.c
index 09bc107..1b8356b 100644
--- a/src/pulse/scache.c
+++ b/src/pulse/scache.c
@@ -88,7 +88,7 @@ pa_operation *pa_context_play_sample(pa_context *c, const char *name, const char
     uint32_t tag;
 
     assert(c);
-    assert(c->ref >= 1);
+    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);
@@ -116,7 +116,7 @@ pa_operation* pa_context_remove_sample(pa_context *c, const char *name, pa_conte
     uint32_t tag;
 
     assert(c);
-    assert(c->ref >= 1);
+    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);
diff --git a/src/pulse/stream.c b/src/pulse/stream.c
index 07a041a..8f5aeb7 100644
--- a/src/pulse/stream.c
+++ b/src/pulse/stream.c
@@ -54,7 +54,7 @@ pa_stream *pa_stream_new(pa_context *c, const char *name, const pa_sample_spec *
     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;
 
@@ -142,37 +142,37 @@ static void stream_free(pa_stream *s) {
 
 void pa_stream_unref(pa_stream *s) {
     assert(s);
-    assert(s->ref >= 1);
+    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);
+    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);
+    assert(PA_REFCNT_VALUE(s) >= 1);
 
     return s->state;
 }
 
 pa_context* pa_stream_get_context(pa_stream *s) {
     assert(s);
-    assert(s->ref >= 1);
+    assert(PA_REFCNT_VALUE(s) >= 1);
 
     return s->context;
 }
 
 uint32_t pa_stream_get_index(pa_stream *s) {
     assert(s);
-    assert(s->ref >= 1);
+    assert(PA_REFCNT_VALUE(s) >= 1);
 
     PA_CHECK_VALIDITY_RETURN_ANY(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE, PA_INVALID_INDEX);
 
@@ -181,7 +181,7 @@ 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);
+    assert(PA_REFCNT_VALUE(s) >= 1);
 
     if (s->state == st)
         return;
@@ -506,7 +506,7 @@ static int create_stream(
     uint32_t tag;
 
     assert(s);
-    assert(s->ref >= 1);
+    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 ?
@@ -591,7 +591,7 @@ int pa_stream_connect_playback(
         pa_stream *sync_stream) {
 
     assert(s);
-    assert(s->ref >= 1);
+    assert(PA_REFCNT_VALUE(s) >= 1);
 
     return create_stream(PA_STREAM_PLAYBACK, s, dev, attr, flags, volume, sync_stream);
 }
@@ -603,7 +603,7 @@ int pa_stream_connect_record(
         pa_stream_flags_t flags) {
 
     assert(s);
-    assert(s->ref >= 1);
+    assert(PA_REFCNT_VALUE(s) >= 1);
 
     return create_stream(PA_STREAM_RECORD, s, dev, attr, flags, NULL, NULL);
 }
@@ -619,7 +619,7 @@ int pa_stream_write(
     pa_memchunk chunk;
 
     assert(s);
-    assert(s->ref >= 1);
+    assert(PA_REFCNT_VALUE(s) >= 1);
     assert(data);
 
     PA_CHECK_VALIDITY(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE);
@@ -689,7 +689,7 @@ int pa_stream_write(
 
 int pa_stream_peek(pa_stream *s, const void **data, size_t *length) {
     assert(s);
-    assert(s->ref >= 1);
+    assert(PA_REFCNT_VALUE(s) >= 1);
     assert(data);
     assert(length);
 
@@ -715,7 +715,7 @@ int pa_stream_peek(pa_stream *s, const void **data, size_t *length) {
 
 int pa_stream_drop(pa_stream *s) {
     assert(s);
-    assert(s->ref >= 1);
+    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);
@@ -739,7 +739,7 @@ int pa_stream_drop(pa_stream *s) {
 
 size_t pa_stream_writable_size(pa_stream *s) {
     assert(s);
-    assert(s->ref >= 1);
+    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);
@@ -749,7 +749,7 @@ size_t pa_stream_writable_size(pa_stream *s) {
 
 size_t pa_stream_readable_size(pa_stream *s) {
     assert(s);
-    assert(s->ref >= 1);
+    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);
@@ -763,7 +763,7 @@ pa_operation * pa_stream_drain(pa_stream *s, pa_stream_success_cb_t cb, void *us
     uint32_t tag;
 
     assert(s);
-    assert(s->ref >= 1);
+    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);
@@ -933,7 +933,7 @@ pa_operation* pa_stream_update_timing_info(pa_stream *s, pa_stream_success_cb_t
     int cidx = 0;
 
     assert(s);
-    assert(s->ref >= 1);
+    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);
@@ -977,7 +977,7 @@ void pa_stream_disconnect_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UN
 
     assert(pd);
     assert(s);
-    assert(s->ref >= 1);
+    assert(PA_REFCNT_VALUE(s) >= 1);
 
     pa_stream_ref(s);
 
@@ -1003,7 +1003,7 @@ int pa_stream_disconnect(pa_stream *s) {
     uint32_t tag;
 
     assert(s);
-    assert(s->ref >= 1);
+    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);
@@ -1025,7 +1025,7 @@ 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);
+    assert(PA_REFCNT_VALUE(s) >= 1);
 
     s->read_callback = cb;
     s->read_userdata = userdata;
@@ -1033,7 +1033,7 @@ void pa_stream_set_read_callback(pa_stream *s, pa_stream_request_cb_t cb, void *
 
 void pa_stream_set_write_callback(pa_stream *s, pa_stream_request_cb_t cb, void *userdata) {
     assert(s);
-    assert(s->ref >= 1);
+    assert(PA_REFCNT_VALUE(s) >= 1);
 
     s->write_callback = cb;
     s->write_userdata = userdata;
@@ -1041,7 +1041,7 @@ void pa_stream_set_write_callback(pa_stream *s, pa_stream_request_cb_t cb, void
 
 void pa_stream_set_state_callback(pa_stream *s, pa_stream_notify_cb_t cb, void *userdata) {
     assert(s);
-    assert(s->ref >= 1);
+    assert(PA_REFCNT_VALUE(s) >= 1);
 
     s->state_callback = cb;
     s->state_userdata = userdata;
@@ -1049,7 +1049,7 @@ void pa_stream_set_state_callback(pa_stream *s, pa_stream_notify_cb_t cb, void *
 
 void pa_stream_set_overflow_callback(pa_stream *s, pa_stream_notify_cb_t cb, void *userdata) {
     assert(s);
-    assert(s->ref >= 1);
+    assert(PA_REFCNT_VALUE(s) >= 1);
 
     s->overflow_callback = cb;
     s->overflow_userdata = userdata;
@@ -1057,7 +1057,7 @@ void pa_stream_set_overflow_callback(pa_stream *s, pa_stream_notify_cb_t cb, voi
 
 void pa_stream_set_underflow_callback(pa_stream *s, pa_stream_notify_cb_t cb, void *userdata) {
     assert(s);
-    assert(s->ref >= 1);
+    assert(PA_REFCNT_VALUE(s) >= 1);
 
     s->underflow_callback = cb;
     s->underflow_userdata = userdata;
@@ -1065,7 +1065,7 @@ void pa_stream_set_underflow_callback(pa_stream *s, pa_stream_notify_cb_t cb, vo
 
 void pa_stream_set_latency_update_callback(pa_stream *s, pa_stream_notify_cb_t cb, void *userdata) {
     assert(s);
-    assert(s->ref >= 1);
+    assert(PA_REFCNT_VALUE(s) >= 1);
 
     s->latency_update_callback = cb;
     s->latency_update_userdata = userdata;
@@ -1077,7 +1077,7 @@ void pa_stream_simple_ack_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UN
 
     assert(pd);
     assert(o);
-    assert(o->ref >= 1);
+    assert(PA_REFCNT_VALUE(o) >= 1);
 
     if (!o->context)
         goto finish;
@@ -1108,7 +1108,7 @@ pa_operation* pa_stream_cork(pa_stream *s, int b, pa_stream_success_cb_t cb, voi
     uint32_t tag;
 
     assert(s);
-    assert(s->ref >= 1);
+    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);
@@ -1138,7 +1138,7 @@ static pa_operation* stream_send_simple_command(pa_stream *s, uint32_t command,
     uint32_t tag;
 
     assert(s);
-    assert(s->ref >= 1);
+    assert(PA_REFCNT_VALUE(s) >= 1);
 
     PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE);
 
@@ -1207,7 +1207,7 @@ pa_operation* pa_stream_set_name(pa_stream *s, const char *name, pa_stream_succe
     uint32_t tag;
 
     assert(s);
-    assert(s->ref >= 1);
+    assert(PA_REFCNT_VALUE(s) >= 1);
     assert(name);
 
     PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE);
@@ -1231,7 +1231,7 @@ int pa_stream_get_time(pa_stream *s, pa_usec_t *r_usec) {
     pa_usec_t usec = 0;
 
     assert(s);
-    assert(s->ref >= 1);
+    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);
@@ -1315,7 +1315,7 @@ 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);
+    assert(PA_REFCNT_VALUE(s) >= 1);
 
     if (negative)
         *negative = 0;
@@ -1337,7 +1337,7 @@ int pa_stream_get_latency(pa_stream *s, pa_usec_t *r_usec, int *negative) {
     int64_t cindex;
 
     assert(s);
-    assert(s->ref >= 1);
+    assert(PA_REFCNT_VALUE(s) >= 1);
     assert(r_usec);
 
     PA_CHECK_VALIDITY(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE);
@@ -1369,7 +1369,7 @@ 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);
+    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);
@@ -1380,21 +1380,21 @@ 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);
+    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);
+    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);
+    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);
diff --git a/src/pulse/subscribe.c b/src/pulse/subscribe.c
index 5d8f125..76b9375 100644
--- a/src/pulse/subscribe.c
+++ b/src/pulse/subscribe.c
@@ -68,7 +68,7 @@ pa_operation* pa_context_subscribe(pa_context *c, pa_subscription_mask_t m, pa_c
     uint32_t tag;
 
     assert(c);
-    assert(c->ref >= 1);
+    assert(PA_REFCNT_VALUE(c) >= 1);
 
     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
 
@@ -84,7 +84,7 @@ 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);
+    assert(PA_REFCNT_VALUE(c) >= 1);
 
     c->subscribe_callback = cb;
     c->subscribe_userdata = userdata;

commit 391d09cd6e8d47ad8255736be5cb512b04843ed1
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Sep 11 13:15:39 2007 +0000

    add 'wait' parameter to pa_rtpoll_run(), if zero pa_rtpoll_runn will only update the struct pollfd but not wait for an event
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1803 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-alsa-sink.c b/src/modules/module-alsa-sink.c
index c75f195..bb7392d 100644
--- a/src/modules/module-alsa-sink.c
+++ b/src/modules/module-alsa-sink.c
@@ -643,7 +643,7 @@ static void thread_func(void *userdata) {
             continue;
         
         /* Hmm, nothing to do. Let's sleep */
-        if (pa_rtpoll_run(u->rtpoll) < 0) {
+        if (pa_rtpoll_run(u->rtpoll, 1) < 0) {
             pa_log("poll() failed: %s", pa_cstrerror(errno));
             goto fail;
         }
diff --git a/src/modules/module-alsa-source.c b/src/modules/module-alsa-source.c
index 365f6ab..fef7b01 100644
--- a/src/modules/module-alsa-source.c
+++ b/src/modules/module-alsa-source.c
@@ -626,7 +626,7 @@ static void thread_func(void *userdata) {
             continue;
 
         /* Hmm, nothing to do. Let's sleep */
-        if (pa_rtpoll_run(u->rtpoll) < 0) {
+        if (pa_rtpoll_run(u->rtpoll, 1) < 0) {
             pa_log("poll() failed: %s", pa_cstrerror(errno));
             goto fail;
         }
diff --git a/src/modules/module-combine.c b/src/modules/module-combine.c
index 3e56bc6..390b6e5 100644
--- a/src/modules/module-combine.c
+++ b/src/modules/module-combine.c
@@ -268,7 +268,7 @@ static void thread_func(void *userdata) {
             continue;
 
         /* Hmm, nothing to do. Let's sleep */
-        if (pa_rtpoll_run(u->rtpoll) < 0) {
+        if (pa_rtpoll_run(u->rtpoll, 1) < 0) {
             pa_log("poll() failed: %s", pa_cstrerror(errno));
             goto fail;
         }
diff --git a/src/modules/module-null-sink.c b/src/modules/module-null-sink.c
index 78d99ce..2fe541f 100644
--- a/src/modules/module-null-sink.c
+++ b/src/modules/module-null-sink.c
@@ -158,7 +158,7 @@ static void thread_func(void *userdata) {
             continue;
 
         /* Hmm, nothing to do. Let's sleep */
-        if (pa_rtpoll_run(u->rtpoll) < 0) {
+        if (pa_rtpoll_run(u->rtpoll, 1) < 0) {
             pa_log("poll() failed: %s", pa_cstrerror(errno));
             goto fail;
         }
diff --git a/src/modules/module-oss.c b/src/modules/module-oss.c
index 1e524fc..9273a39 100644
--- a/src/modules/module-oss.c
+++ b/src/modules/module-oss.c
@@ -1031,7 +1031,7 @@ static void thread_func(void *userdata) {
         }
         
         /* Hmm, nothing to do. Let's sleep */
-        if (pa_rtpoll_run(u->rtpoll) < 0) {
+        if (pa_rtpoll_run(u->rtpoll, 1) < 0) {
             pa_log("poll() failed: %s", pa_cstrerror(errno));
             goto fail;
         }
diff --git a/src/modules/module-pipe-sink.c b/src/modules/module-pipe-sink.c
index 55a4e0c..5cafaad 100644
--- a/src/modules/module-pipe-sink.c
+++ b/src/modules/module-pipe-sink.c
@@ -185,7 +185,7 @@ static void thread_func(void *userdata) {
         /* Hmm, nothing to do. Let's sleep */
         pollfd->events = u->sink->thread_info.state == PA_SINK_RUNNING ? POLLOUT : 0;
 
-        if (pa_rtpoll_run(u->rtpoll) < 0) {
+        if (pa_rtpoll_run(u->rtpoll, 1) < 0) {
             pa_log("poll() failed: %s", pa_cstrerror(errno));
             goto fail;
         }
diff --git a/src/modules/module-pipe-source.c b/src/modules/module-pipe-source.c
index 6dc9464..291010e 100644
--- a/src/modules/module-pipe-source.c
+++ b/src/modules/module-pipe-source.c
@@ -164,7 +164,7 @@ static void thread_func(void *userdata) {
         /* Hmm, nothing to do. Let's sleep */
         pollfd->events = u->source->thread_info.state == PA_SOURCE_RUNNING ? POLLIN : 0;
 
-        if (pa_rtpoll_run(u->rtpoll) < 0) {
+        if (pa_rtpoll_run(u->rtpoll, 1) < 0) {
             pa_log("poll() failed: %s", pa_cstrerror(errno));
             goto fail;
         }
diff --git a/src/pulsecore/rtpoll.c b/src/pulsecore/rtpoll.c
index e43ec61..be1c83c 100644
--- a/src/pulsecore/rtpoll.c
+++ b/src/pulsecore/rtpoll.c
@@ -257,7 +257,7 @@ void pa_rtpoll_free(pa_rtpoll *p) {
     pa_xfree(p);
 }
 
-int pa_rtpoll_run(pa_rtpoll *p) {
+int pa_rtpoll_run(pa_rtpoll *p, int wait) {
     pa_rtpoll_item *i;
     int r = 0;
     int no_events = 0;
@@ -301,7 +301,10 @@ int pa_rtpoll_run(pa_rtpoll *p) {
         rtpoll_rebuild(p);
 
     /* Calculate timeout */
-    if (p->timer_enabled) {
+    if (!wait) {
+        timeout.tv_sec = 0;
+        timeout.tv_nsec = 0;
+    } else if (p->timer_enabled) {
         struct timespec now;
         pa_rtclock_get(&now);
 
diff --git a/src/pulsecore/rtpoll.h b/src/pulsecore/rtpoll.h
index 7fe5cb3..f393f91 100644
--- a/src/pulsecore/rtpoll.h
+++ b/src/pulsecore/rtpoll.h
@@ -58,7 +58,10 @@ void pa_rtpoll_free(pa_rtpoll *p);
 
 void pa_rtpoll_install(pa_rtpoll *p);
 
-int pa_rtpoll_run(pa_rtpoll *f);
+/* 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. */
+int pa_rtpoll_run(pa_rtpoll *f, int wait);
 
 void pa_rtpoll_set_timer_absolute(pa_rtpoll *p, const struct timespec *ts);
 void pa_rtpoll_set_timer_periodic(pa_rtpoll *p, pa_usec_t usec);
diff --git a/src/tests/rtpoll-test.c b/src/tests/rtpoll-test.c
index 2a90684..20913e7 100644
--- a/src/tests/rtpoll-test.c
+++ b/src/tests/rtpoll-test.c
@@ -58,7 +58,7 @@ int main(int argc, char *argv[]) {
     pa_rtpoll_install(p);
     pa_rtpoll_set_timer_periodic(p, 10000000); /* 10 s */
 
-    pa_rtpoll_run(p);
+    pa_rtpoll_run(p, 1);
     
     pa_rtpoll_item_free(i);
     
@@ -70,7 +70,7 @@ int main(int argc, char *argv[]) {
     pollfd->fd = 0;
     pollfd->events = POLLIN;
     
-    pa_rtpoll_run(p);
+    pa_rtpoll_run(p, 1);
 
     pa_rtpoll_item_free(i);
     

commit 038e560152b7765d85cc399bcf26fe982b395dab
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Sep 11 14:04:38 2007 +0000

    More s/assert/pa_assert/ modernizations
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1804 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulse/introspect.c b/src/pulse/introspect.c
index 1d2f52e..d2b48f0 100644
--- a/src/pulse/introspect.c
+++ b/src/pulse/introspect.c
@@ -26,11 +26,10 @@
 #include <config.h>
 #endif
 
-#include <assert.h>
-
 #include <pulse/context.h>
 
 #include <pulsecore/gccmacro.h>
+#include <pulsecore/macro.h>
 #include <pulsecore/pstream-util.h>
 
 #include "internal.h"
@@ -43,9 +42,9 @@ 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(PA_REFCNT_VALUE(o) >= 1);
+    pa_assert(pd);
+    pa_assert(o);
+    pa_assert(PA_REFCNT_VALUE(o) >= 1);
 
     memset(&i, 0, sizeof(i));
     
@@ -86,9 +85,9 @@ 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(PA_REFCNT_VALUE(o) >= 1);
+    pa_assert(pd);
+    pa_assert(o);
+    pa_assert(PA_REFCNT_VALUE(o) >= 1);
 
     memset(&i, 0, sizeof(i));
     
@@ -133,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(PA_REFCNT_VALUE(o) >= 1);
+    pa_assert(pd);
+    pa_assert(o);
+    pa_assert(PA_REFCNT_VALUE(o) >= 1);
 
     if (!o->context)
         goto finish;
@@ -198,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(PA_REFCNT_VALUE(c) >= 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);
 
@@ -220,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(PA_REFCNT_VALUE(c) >= 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);
@@ -244,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(PA_REFCNT_VALUE(o) >= 1);
+    pa_assert(pd);
+    pa_assert(o);
+    pa_assert(PA_REFCNT_VALUE(o) >= 1);
 
     if (!o->context)
         goto finish;
@@ -309,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(PA_REFCNT_VALUE(c) >= 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);
 
@@ -331,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(PA_REFCNT_VALUE(c) >= 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);
@@ -355,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(PA_REFCNT_VALUE(o) >= 1);
+    pa_assert(pd);
+    pa_assert(o);
+    pa_assert(PA_REFCNT_VALUE(o) >= 1);
 
     if (!o->context)
         goto finish;
@@ -403,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(PA_REFCNT_VALUE(c) >= 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);
@@ -430,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(PA_REFCNT_VALUE(o) >= 1);
+    pa_assert(pd);
+    pa_assert(o);
+    pa_assert(PA_REFCNT_VALUE(o) >= 1);
 
     if (!o->context)
         goto finish;
@@ -479,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(PA_REFCNT_VALUE(c) >= 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);
@@ -506,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(PA_REFCNT_VALUE(o) >= 1);
+    pa_assert(pd);
+    pa_assert(o);
+    pa_assert(PA_REFCNT_VALUE(o) >= 1);
 
     if (!o->context)
         goto finish;
@@ -564,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(PA_REFCNT_VALUE(c) >= 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);
@@ -591,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(PA_REFCNT_VALUE(o) >= 1);
+    pa_assert(pd);
+    pa_assert(o);
+    pa_assert(PA_REFCNT_VALUE(o) >= 1);
 
     if (!o->context)
         goto finish;
@@ -648,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(PA_REFCNT_VALUE(c) >= 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);
@@ -676,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(PA_REFCNT_VALUE(c) >= 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);
@@ -700,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(PA_REFCNT_VALUE(c) >= 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);
@@ -726,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(PA_REFCNT_VALUE(c) >= 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);
 
@@ -748,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(PA_REFCNT_VALUE(c) >= 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);
@@ -772,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(PA_REFCNT_VALUE(c) >= 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);
@@ -796,8 +795,8 @@ pa_operation* pa_context_set_sink_input_mute(pa_context *c, uint32_t idx, int mu
     pa_tagstruct *t;
     uint32_t tag;
 
-    assert(c);
-    assert(PA_REFCNT_VALUE(c) >= 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);
@@ -819,9 +818,9 @@ pa_operation* pa_context_set_source_volume_by_index(pa_context *c, uint32_t idx,
     pa_tagstruct *t;
     uint32_t tag;
 
-    assert(c);
-    assert(PA_REFCNT_VALUE(c) >= 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);
@@ -843,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(PA_REFCNT_VALUE(c) >= 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);
@@ -869,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(PA_REFCNT_VALUE(c) >= 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);
 
@@ -891,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(PA_REFCNT_VALUE(c) >= 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);
@@ -916,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(PA_REFCNT_VALUE(o) >= 1);
+    pa_assert(pd);
+    pa_assert(o);
+    pa_assert(PA_REFCNT_VALUE(o) >= 1);
 
     if (!o->context)
         goto finish;
@@ -971,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(PA_REFCNT_VALUE(c) >= 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);
@@ -994,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(PA_REFCNT_VALUE(c) >= 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);
@@ -1021,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(PA_REFCNT_VALUE(c) >= 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);
@@ -1053,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(PA_REFCNT_VALUE(o) >= 1);
+    pa_assert(pd);
+    pa_assert(o);
+    pa_assert(PA_REFCNT_VALUE(o) >= 1);
 
     if (!o->context)
         goto finish;
@@ -1087,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(PA_REFCNT_VALUE(c) >= 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);
@@ -1114,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(PA_REFCNT_VALUE(o) >= 1);
+    pa_assert(pd);
+    pa_assert(o);
+    pa_assert(PA_REFCNT_VALUE(o) >= 1);
 
     if (!o->context)
         goto finish;
@@ -1164,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(PA_REFCNT_VALUE(c) >= 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);
@@ -1188,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(PA_REFCNT_VALUE(c) >= 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);
@@ -1214,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(PA_REFCNT_VALUE(c) >= 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);
@@ -1240,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(PA_REFCNT_VALUE(c) >= 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);
@@ -1263,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(PA_REFCNT_VALUE(c) >= 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);
@@ -1284,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(PA_REFCNT_VALUE(c) >= 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);
@@ -1309,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(PA_REFCNT_VALUE(c) >= 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);
@@ -1334,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(PA_REFCNT_VALUE(c) >= 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);
@@ -1359,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(PA_REFCNT_VALUE(c) >= 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);
@@ -1384,8 +1383,8 @@ pa_operation* pa_context_suspend_sink_by_name(pa_context *c, char *sink_name, in
     pa_tagstruct *t;
     uint32_t tag;
 
-    assert(c);
-    assert(PA_REFCNT_VALUE(c) >= 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 >= 11, PA_ERR_NOTSUPPORTED);
@@ -1408,8 +1407,8 @@ pa_operation* pa_context_suspend_sink_by_index(pa_context *c, uint32_t idx, int
     pa_tagstruct *t;
     uint32_t tag;
 
-    assert(c);
-    assert(PA_REFCNT_VALUE(c) >= 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 >= 11, PA_ERR_NOTSUPPORTED);
@@ -1431,8 +1430,8 @@ pa_operation* pa_context_suspend_source_by_name(pa_context *c, char *source_name
     pa_tagstruct *t;
     uint32_t tag;
 
-    assert(c);
-    assert(PA_REFCNT_VALUE(c) >= 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 >= 11, PA_ERR_NOTSUPPORTED);
@@ -1455,8 +1454,8 @@ pa_operation* pa_context_suspend_source_by_index(pa_context *c, uint32_t idx, in
     pa_tagstruct *t;
     uint32_t tag;
 
-    assert(c);
-    assert(PA_REFCNT_VALUE(c) >= 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 >= 11, PA_ERR_NOTSUPPORTED);
diff --git a/src/pulse/scache.c b/src/pulse/scache.c
index 1b8356b..a4a7244 100644
--- a/src/pulse/scache.c
+++ b/src/pulse/scache.c
@@ -25,12 +25,12 @@
 #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(PA_REFCNT_VALUE(c) >= 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(PA_REFCNT_VALUE(c) >= 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);
diff --git a/src/pulse/stream.c b/src/pulse/stream.c
index 8f5aeb7..6d14a70 100644
--- a/src/pulse/stream.c
+++ b/src/pulse/stream.c
@@ -26,7 +26,6 @@
 #include <config.h>
 #endif
 
-#include <assert.h>
 #include <string.h>
 #include <stdio.h>
 #include <string.h>
@@ -48,7 +47,8 @@ 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);
@@ -120,10 +120,12 @@ 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);
     }
 
@@ -141,38 +143,38 @@ static void stream_free(pa_stream *s) {
 }
 
 void pa_stream_unref(pa_stream *s) {
-    assert(s);
-    assert(PA_REFCNT_VALUE(s) >= 1);
+    pa_assert(s);
+    pa_assert(PA_REFCNT_VALUE(s) >= 1);
 
     if (PA_REFCNT_DEC(s) <= 0)
         stream_free(s);
 }
 
 pa_stream* pa_stream_ref(pa_stream *s) {
-    assert(s);
-    assert(PA_REFCNT_VALUE(s) >= 1);
+    pa_assert(s);
+    pa_assert(PA_REFCNT_VALUE(s) >= 1);
 
     PA_REFCNT_INC(s);
     return s;
 }
 
 pa_stream_state_t pa_stream_get_state(pa_stream *s) {
-    assert(s);
-    assert(PA_REFCNT_VALUE(s) >= 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(PA_REFCNT_VALUE(s) >= 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(PA_REFCNT_VALUE(s) >= 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);
 
@@ -180,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(PA_REFCNT_VALUE(s) >= 1);
+    pa_assert(s);
+    pa_assert(PA_REFCNT_VALUE(s) >= 1);
 
     if (s->state == st)
         return;
@@ -236,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);
 
@@ -264,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);
 
@@ -297,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);
 
@@ -329,7 +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) {
-    assert(s);
+    pa_assert(s);
+    pa_assert(PA_REFCNT_VALUE(s) >= 1);
 
     if (!(s->flags & PA_STREAM_AUTO_TIMING_UPDATE))
         return;
@@ -355,7 +361,8 @@ static void request_auto_timing_update(pa_stream *s, int force) {
 }
 
 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); */
 
@@ -390,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);
@@ -399,6 +409,7 @@ static void auto_timing_update_callback(PA_GCC_UNUSED pa_mainloop_api *m, PA_GCC
 
 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);
@@ -410,7 +421,7 @@ static void create_stream_complete(pa_stream *s) {
         struct timeval tv;
         pa_gettimeofday(&tv);
         tv.tv_usec += LATENCY_IPOL_INTERVAL_USEC; /* every 100 ms */
-        assert(!s->auto_timing_update_event);
+        pa_assert(!s->auto_timing_update_event);
         s->auto_timing_update_event = s->mainloop->time_new(s->mainloop, &tv, &auto_timing_update_callback, s);
     }    
 }
@@ -418,9 +429,10 @@ static void create_stream_complete(pa_stream *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);
 
@@ -463,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,
@@ -505,8 +517,8 @@ static int create_stream(
     pa_tagstruct *t;
     uint32_t tag;
 
-    assert(s);
-    assert(PA_REFCNT_VALUE(s) >= 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 ?
@@ -590,8 +602,8 @@ int pa_stream_connect_playback(
         pa_cvolume *volume,
         pa_stream *sync_stream) {
 
-    assert(s);
-    assert(PA_REFCNT_VALUE(s) >= 1);
+    pa_assert(s);
+    pa_assert(PA_REFCNT_VALUE(s) >= 1);
 
     return create_stream(PA_STREAM_PLAYBACK, s, dev, attr, flags, volume, sync_stream);
 }
@@ -602,8 +614,8 @@ int pa_stream_connect_record(
         const pa_buffer_attr *attr,
         pa_stream_flags_t flags) {
 
-    assert(s);
-    assert(PA_REFCNT_VALUE(s) >= 1);
+    pa_assert(s);
+    pa_assert(PA_REFCNT_VALUE(s) >= 1);
 
     return create_stream(PA_STREAM_RECORD, s, dev, attr, flags, NULL, NULL);
 }
@@ -618,9 +630,9 @@ int pa_stream_write(
 
     pa_memchunk chunk;
 
-    assert(s);
-    assert(PA_REFCNT_VALUE(s) >= 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);
@@ -688,10 +700,10 @@ int pa_stream_write(
 }
 
 int pa_stream_peek(pa_stream *s, const void **data, size_t *length) {
-    assert(s);
-    assert(PA_REFCNT_VALUE(s) >= 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);
@@ -707,15 +719,15 @@ int pa_stream_peek(pa_stream *s, const void **data, size_t *length) {
         s->peek_data = pa_memblock_acquire(s->peek_memchunk.memblock);
     }
 
-    assert(s->peek_data);
+    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(PA_REFCNT_VALUE(s) >= 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);
@@ -727,7 +739,7 @@ int pa_stream_drop(pa_stream *s) {
     if (s->timing_info_valid && !s->timing_info.read_index_corrupt)
         s->timing_info.read_index += s->peek_memchunk.length;
 
-    assert(s->peek_data);
+    pa_assert(s->peek_data);
     pa_memblock_release(s->peek_memchunk.memblock);
     pa_memblock_unref(s->peek_memchunk.memblock);
     s->peek_memchunk.length = 0;
@@ -738,8 +750,8 @@ int pa_stream_drop(pa_stream *s) {
 }
 
 size_t pa_stream_writable_size(pa_stream *s) {
-    assert(s);
-    assert(PA_REFCNT_VALUE(s) >= 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);
@@ -748,8 +760,8 @@ size_t pa_stream_writable_size(pa_stream *s) {
 }
 
 size_t pa_stream_readable_size(pa_stream *s) {
-    assert(s);
-    assert(PA_REFCNT_VALUE(s) >= 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);
@@ -762,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(PA_REFCNT_VALUE(s) >= 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);
@@ -783,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;
@@ -932,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(PA_REFCNT_VALUE(s) >= 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);
@@ -975,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(PA_REFCNT_VALUE(s) >= 1);
+    pa_assert(pd);
+    pa_assert(s);
+    pa_assert(PA_REFCNT_VALUE(s) >= 1);
 
     pa_stream_ref(s);
 
@@ -1002,8 +1015,8 @@ int pa_stream_disconnect(pa_stream *s) {
     pa_tagstruct *t;
     uint32_t tag;
 
-    assert(s);
-    assert(PA_REFCNT_VALUE(s) >= 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);
@@ -1024,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(PA_REFCNT_VALUE(s) >= 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(PA_REFCNT_VALUE(s) >= 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(PA_REFCNT_VALUE(s) >= 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(PA_REFCNT_VALUE(s) >= 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(PA_REFCNT_VALUE(s) >= 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(PA_REFCNT_VALUE(s) >= 1);
+    pa_assert(s);
+    pa_assert(PA_REFCNT_VALUE(s) >= 1);
 
     s->latency_update_callback = cb;
     s->latency_update_userdata = userdata;
@@ -1075,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(PA_REFCNT_VALUE(o) >= 1);
+    pa_assert(pd);
+    pa_assert(o);
+    pa_assert(PA_REFCNT_VALUE(o) >= 1);
 
     if (!o->context)
         goto finish;
@@ -1107,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(PA_REFCNT_VALUE(s) >= 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);
@@ -1137,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(PA_REFCNT_VALUE(s) >= 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);
 
@@ -1155,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))) {
@@ -1180,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);
 
@@ -1192,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);
 
@@ -1206,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(PA_REFCNT_VALUE(s) >= 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);
@@ -1230,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(PA_REFCNT_VALUE(s) >= 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);
@@ -1314,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(PA_REFCNT_VALUE(s) >= 1);
+    pa_assert(s);
+    pa_assert(PA_REFCNT_VALUE(s) >= 1);
 
     if (negative)
         *negative = 0;
@@ -1336,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(PA_REFCNT_VALUE(s) >= 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);
@@ -1368,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(PA_REFCNT_VALUE(s) >= 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);
@@ -1379,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(PA_REFCNT_VALUE(s) >= 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(PA_REFCNT_VALUE(s) >= 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(PA_REFCNT_VALUE(s) >= 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);
diff --git a/src/pulse/subscribe.c b/src/pulse/subscribe.c
index 76b9375..31b7636 100644
--- a/src/pulse/subscribe.c
+++ b/src/pulse/subscribe.c
@@ -29,6 +29,7 @@
 #include <stdio.h>
 
 #include <pulsecore/gccmacro.h>
+#include <pulsecore/macro.h>
 #include <pulsecore/pstream-util.h>
 
 #include "internal.h"
@@ -40,10 +41,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 +69,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(PA_REFCNT_VALUE(c) >= 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 +85,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(PA_REFCNT_VALUE(c) >= 1);
+    pa_assert(c);
+    pa_assert(PA_REFCNT_VALUE(c) >= 1);
 
     c->subscribe_callback = cb;
     c->subscribe_userdata = userdata;

commit 27f13b3853c0d613c2edfb0ae11cffa72004ebf0
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Sep 11 14:23:38 2007 +0000

    finish modernizations in pulse/, s/assert/pa_assert/g
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1805 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulse/browser.c b/src/pulse/browser.c
index a35fe81..af56e47 100644
--- a/src/pulse/browser.c
+++ b/src/pulse/browser.c
@@ -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,12 +112,12 @@ 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)
         pa_snprintf(a, sizeof(a), "tcp:%s:%u", avahi_address_snprint(ip, sizeof(ip), aa), port);
     else {
-        assert(aa->proto == AVAHI_PROTO_INET6);
+        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;
diff --git a/src/pulse/context.c b/src/pulse/context.c
index c168502..ab06aeb 100644
--- a/src/pulse/context.c
+++ b/src/pulse/context.c
@@ -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,8 +106,8 @@ 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);
     PA_REFCNT_INIT(c);
@@ -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);
 
@@ -206,24 +206,24 @@ static void context_free(pa_context *c) {
 }
 
 pa_context* pa_context_ref(pa_context *c) {
-    assert(c);
-    assert(PA_REFCNT_VALUE(c) >= 1);
+    pa_assert(c);
+    pa_assert(PA_REFCNT_VALUE(c) >= 1);
 
     PA_REFCNT_INC(c);
     return c;
 }
 
 void pa_context_unref(pa_context *c) {
-    assert(c);
-    assert(PA_REFCNT_VALUE(c) >= 1);
+    pa_assert(c);
+    pa_assert(PA_REFCNT_VALUE(c) >= 1);
 
     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(PA_REFCNT_VALUE(c) >= 1);
+    pa_assert(c);
+    pa_assert(PA_REFCNT_VALUE(c) >= 1);
 
     if (c->state == st)
         return;
@@ -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(PA_REFCNT_VALUE(c) >= 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(PA_REFCNT_VALUE(c) >= 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(PA_REFCNT_VALUE(c) >= 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)
@@ -602,8 +603,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 +649,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 +684,8 @@ int pa_context_connect(
 
     int r = -1;
 
-    assert(c);
-    assert(PA_REFCNT_VALUE(c) >= 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 +696,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 +736,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 +756,37 @@ finish:
 }
 
 void pa_context_disconnect(pa_context *c) {
-    assert(c);
-    assert(PA_REFCNT_VALUE(c) >= 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(PA_REFCNT_VALUE(c) >= 1);
+    pa_assert(c);
+    pa_assert(PA_REFCNT_VALUE(c) >= 1);
 
     return c->state;
 }
 
 int pa_context_errno(pa_context *c) {
-    assert(c);
-    assert(PA_REFCNT_VALUE(c) >= 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(PA_REFCNT_VALUE(c) >= 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(PA_REFCNT_VALUE(c) >= 1);
+    pa_assert(c);
+    pa_assert(PA_REFCNT_VALUE(c) >= 1);
 
     PA_CHECK_VALIDITY(c,
                       c->state == PA_CONTEXT_CONNECTING ||
@@ -811,11 +812,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(PA_REFCNT_VALUE(o) >= 1);
-    assert(o->context);
-    assert(PA_REFCNT_VALUE(o->context) >= 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 +845,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(PA_REFCNT_VALUE(c) >= 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 +861,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(PA_REFCNT_VALUE(o) >= 1);
+    pa_assert(pd);
+    pa_assert(o);
+    pa_assert(PA_REFCNT_VALUE(o) >= 1);
 
     if (!o->context)
         goto finish;
@@ -892,8 +893,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(PA_REFCNT_VALUE(c) >= 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 +912,8 @@ pa_operation* pa_context_send_simple_command(pa_context *c, uint32_t command, pa
     pa_operation *o;
     uint32_t tag;
 
-    assert(c);
-    assert(PA_REFCNT_VALUE(c) >= 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 +931,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(PA_REFCNT_VALUE(c) >= 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 +951,8 @@ pa_operation* pa_context_set_default_source(pa_context *c, const char *name, pa_
     pa_operation *o;
     uint32_t tag;
 
-    assert(c);
-    assert(PA_REFCNT_VALUE(c) >= 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 +967,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 +977,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(PA_REFCNT_VALUE(c) >= 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 +998,8 @@ const char* pa_get_library_version(void) {
 }
 
 const char* pa_context_get_server(pa_context *c) {
-    assert(c);
-    assert(PA_REFCNT_VALUE(c) >= 1);
+    pa_assert(c);
+    pa_assert(PA_REFCNT_VALUE(c) >= 1);
 
     if (!c->server)
         return NULL;
@@ -1016,8 +1017,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(PA_REFCNT_VALUE(c) >= 1);
+    pa_assert(c);
+    pa_assert(PA_REFCNT_VALUE(c) >= 1);
 
     return c->version;
 }
@@ -1025,8 +1026,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);
diff --git a/src/pulse/mainloop-signal.c b/src/pulse/mainloop-signal.c
index 18fd86f..d2d42d9 100644
--- a/src/pulse/mainloop-signal.c
+++ b/src/pulse/mainloop-signal.c
@@ -161,7 +161,8 @@ pa_signal_event* pa_signal_new(int sig, void (*_callback) (pa_mainloop_api *api,
     struct sigaction sa;
 #endif
 
-    pa_assert(sig > 0 && _callback);
+    pa_assert(sig > 0);
+    pa_assert(_callback);
 
     for (e = signals; e; e = e->next)
         if (e->sig == sig)
diff --git a/src/pulse/mainloop.c b/src/pulse/mainloop.c
index a5304ff..419b74d 100644
--- a/src/pulse/mainloop.c
+++ b/src/pulse/mainloop.c
@@ -677,7 +677,8 @@ static int dispatch_pollfds(pa_mainloop *m) {
         if (e->dead || !e->pollfd || !e->pollfd->revents)
             continue;
 
-        pa_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++;
diff --git a/src/pulse/simple.c b/src/pulse/simple.c
index 3cf862d..1072fb4 100644
--- a/src/pulse/simple.c
+++ b/src/pulse/simple.c
@@ -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);
 

commit 9c523e060749d1a762c264025a653803a246894e
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Sep 11 14:58:25 2007 +0000

    more modernizations, s/assert/pa_assert/g
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1806 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/authkey-prop.c b/src/pulsecore/authkey-prop.c
index 146d7ca..35b62d4 100644
--- a/src/pulsecore/authkey-prop.c
+++ b/src/pulsecore/authkey-prop.c
@@ -25,44 +25,53 @@
 #include <config.h>
 #endif
 
-#include <assert.h>
 #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 {
+    PA_REFCNT_DECLARE;
     int ref;
     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);
 
@@ -71,22 +80,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);
     }
diff --git a/src/pulsecore/autoload.c b/src/pulsecore/autoload.c
index 6f88852..0caaa29 100644
--- a/src/pulsecore/autoload.c
+++ b/src/pulsecore/autoload.c
@@ -26,7 +26,6 @@
 #include <config.h>
 #endif
 
-#include <assert.h>
 #include <stdlib.h>
 #include <string.h>
 
@@ -36,13 +35,14 @@
 #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;
diff --git a/src/pulsecore/avahi-wrap.c b/src/pulsecore/avahi-wrap.c
index 855ed56..fae5481 100644
--- a/src/pulsecore/avahi-wrap.c
+++ b/src/pulsecore/avahi-wrap.c
@@ -21,11 +21,14 @@
   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);
 }
diff --git a/src/pulsecore/cli-command.c b/src/pulsecore/cli-command.c
index 79b52d4..3a1ce5a 100644
--- a/src/pulsecore/cli-command.c
+++ b/src/pulsecore/cli-command.c
@@ -182,15 +182,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");
 
@@ -200,67 +208,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;
@@ -275,8 +307,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);
 
@@ -320,7 +354,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);
@@ -333,10 +371,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");
@@ -351,12 +393,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");
@@ -373,12 +419,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;
@@ -404,13 +455,18 @@ static int pa_cli_command_sink_volume(pa_core *c, pa_tokenizer *t, pa_strbuf *bu
     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;
@@ -441,12 +497,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;
@@ -472,11 +533,16 @@ static int pa_cli_command_source_volume(pa_core *c, pa_tokenizer *t, pa_strbuf *
     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;
@@ -501,11 +567,16 @@ static int pa_cli_command_sink_mute(pa_core *c, pa_tokenizer *t, pa_strbuf *buf,
     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;
@@ -530,12 +601,17 @@ static int pa_cli_command_source_mute(pa_core *c, pa_tokenizer *t, pa_strbuf *bu
     return 0;
 }
 
-static int pa_cli_command_sink_input_mute(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;
@@ -565,9 +641,13 @@ static int pa_cli_command_sink_input_mute(pa_core *c, pa_tokenizer *t, pa_strbuf
     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_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");
@@ -578,9 +658,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");
@@ -591,11 +675,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");
@@ -616,11 +704,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");
@@ -641,11 +733,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");
@@ -666,20 +762,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");
@@ -701,7 +806,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");
@@ -719,7 +828,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");
@@ -739,7 +852,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");
@@ -757,7 +874,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");
@@ -775,7 +896,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");
@@ -789,7 +914,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");
@@ -804,25 +933,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);
 
@@ -835,6 +975,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;
@@ -873,6 +1018,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;
@@ -910,6 +1060,11 @@ static int pa_cli_command_suspend_sink(pa_core *c, pa_tokenizer *t, pa_strbuf *b
     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;
@@ -939,6 +1094,11 @@ static int pa_cli_command_suspend_source(pa_core *c, pa_tokenizer *t, pa_strbuf
     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;
@@ -968,6 +1128,11 @@ static int pa_cli_command_suspend(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, i
     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;
@@ -988,7 +1153,7 @@ static int pa_cli_command_suspend(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, i
     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_dump(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) {
     pa_module *m;
     pa_sink *sink;
     pa_source *source;
@@ -1000,7 +1165,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);
 
@@ -1097,6 +1265,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)
@@ -1160,14 +1332,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;
@@ -1198,9 +1369,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));
@@ -1230,9 +1401,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) {
diff --git a/src/pulsecore/cli-text.c b/src/pulsecore/cli-text.c
index 617ae81..bac61dc 100644
--- a/src/pulsecore/cli-text.c
+++ b/src/pulsecore/cli-text.c
@@ -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));
 
@@ -99,10 +97,9 @@ char *pa_sink_list_to_string(pa_core *c) {
         [PA_SINK_IDLE] = "IDLE",
         [PA_SINK_UNLINKED] = "UNLINKED"
     };
-    assert(c);
+    pa_assert(c);
 
     s = pa_strbuf_new();
-    assert(s);
 
     pa_strbuf_printf(s, "%u sink(s) available.\n", pa_idxset_size(c->sinks));
 
@@ -159,10 +156,9 @@ char *pa_source_list_to_string(pa_core *c) {
         [PA_SOURCE_IDLE] = "IDLE",
         [PA_SOURCE_UNLINKED] = "UNLINKED"
     };
-    assert(c);
+    pa_assert(c);
 
     s = pa_strbuf_new();
-    assert(s);
 
     pa_strbuf_printf(s, "%u source(s) available.\n", pa_idxset_size(c->sources));
 
@@ -220,17 +216,16 @@ char *pa_source_output_list_to_string(pa_core *c) {
         [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,
@@ -275,16 +270,15 @@ char *pa_sink_input_list_to_string(pa_core *c) {
         [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,
@@ -325,10 +319,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);
 
@@ -374,10 +367,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);
 
diff --git a/src/pulsecore/cli.c b/src/pulsecore/cli.c
index ee05d7f..bb80e90 100644
--- a/src/pulsecore/cli.c
+++ b/src/pulsecore/cli.c
@@ -45,6 +45,7 @@
 #include <pulsecore/cli-text.h>
 #include <pulsecore/cli-command.h>
 #include <pulsecore/log.h>
+#include <pulsecore/macro.h>
 
 #include "cli.h"
 
@@ -68,19 +69,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 +93,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 +103,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 +120,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 +132,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 +147,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;
 }
diff --git a/src/pulsecore/client.c b/src/pulsecore/client.c
index 0d792bb..99cbeb8 100644
--- a/src/pulsecore/client.c
+++ b/src/pulsecore/client.c
@@ -27,7 +27,6 @@
 #endif
 
 #include <stdio.h>
-#include <assert.h>
 #include <stdlib.h>
 #include <string.h>
 
@@ -35,15 +34,16 @@
 
 #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);
+    
+    pa_core_assert_ref(core);
 
-    c = pa_xmalloc(sizeof(pa_client));
+    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);
diff --git a/src/pulsecore/core.c b/src/pulsecore/core.c
index 808bc9a..c538652 100644
--- a/src/pulsecore/core.c
+++ b/src/pulsecore/core.c
@@ -27,7 +27,6 @@
 #endif
 
 #include <stdlib.h>
-#include <assert.h>
 #include <stdio.h>
 #include <signal.h>
 
@@ -160,21 +159,21 @@ static void core_free(pa_object *o) {
     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);
@@ -200,7 +199,7 @@ static void core_free(pa_object *o) {
 
 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;
-    pa_assert(c->quit_event = e);
+    pa_assert(c->quit_event == e);
 
     m->quit(m, 0);
 }
diff --git a/src/pulsecore/strbuf.c b/src/pulsecore/strbuf.c
index ca88c59..122343f 100644
--- a/src/pulsecore/strbuf.c
+++ b/src/pulsecore/strbuf.c
@@ -50,8 +50,9 @@ struct pa_strbuf {
 };
 
 pa_strbuf *pa_strbuf_new(void) {
-    
-    pa_strbuf *sb = pa_xnew(pa_strbuf, 1);
+    pa_strbuf *sb;
+
+    sb = pa_xnew(pa_strbuf, 1);
     sb->length = 0;
     sb->head = sb->tail = NULL;
     

commit abb18d9c4c684c8513bc1a8d897dd04fc82ed1e7
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Sep 11 15:14:46 2007 +0000

    explcitly initialize tls memory to NULL
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1807 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/thread.h b/src/pulsecore/thread.h
index 4e5425d..4a2b1bb 100644
--- a/src/pulsecore/thread.h
+++ b/src/pulsecore/thread.h
@@ -85,7 +85,7 @@ void *pa_tls_set(pa_tls *t, void *userdata);
 /* 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;                                   \
+    static __thread void *name##_tls = NULL;                            \
     static inline void* name##_tls_get(void) {                          \
         return name##_tls;                                              \
     }                                                                   \

commit 2988c3d9fbe52ba0429b4962446273bceda391f6
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Sep 11 15:27:32 2007 +0000

    Rework core-error.c on top of PA_STATIC_TLS_DECLARE, the windows specific parts need to be moved to thread-win32.c
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1808 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/core-error.c b/src/pulsecore/core-error.c
index 044bea1..6446413 100644
--- a/src/pulsecore/core-error.c
+++ b/src/pulsecore/core-error.c
@@ -31,178 +31,50 @@
 #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;
 
-    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 ((t = PA_STATIC_TLS_GET(cstrerror)))
+        pa_xfree(t);
+    
+#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;
 }

commit d5bedbcd98c10ef187f1daa326b32c6f3ba8d3af
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Sep 11 20:48:33 2007 +0000

    remaining s/assert/pa_assert/ and refcnt.h modernizations
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1809 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/daemon/cmdline.c b/src/daemon/cmdline.c
index 384dde3..a3f1ff0 100644
--- a/src/daemon/cmdline.c
+++ b/src/daemon/cmdline.c
@@ -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"
 
@@ -100,6 +100,8 @@ static struct option long_options[] = {
 void pa_cmdline_help(const char *argv0) {
     const char *e;
 
+    pa_assert(argv0);
+    
     if ((e = strrchr(argv0, '/')))
         e++;
     else
@@ -154,7 +156,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();
 
diff --git a/src/daemon/cpulimit.c b/src/daemon/cpulimit.c
index 6536f46..37f7976 100644
--- a/src/daemon/cpulimit.c
+++ b/src/daemon/cpulimit.c
@@ -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;
@@ -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);
 
@@ -208,10 +214,9 @@ 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;
@@ -224,8 +229,7 @@ void pa_cpu_limit_done(void) {
     the_pipe[0] = the_pipe[1] = -1;
 
     if (installed) {
-        r = sigaction(SIGXCPU, &sigaction_prev, NULL);
-        assert(r >= 0);
+        pa_assert_se(sigaction(SIGXCPU, &sigaction_prev, NULL) >= 0);
         installed = 0;
     }
 }
diff --git a/src/daemon/dumpmodules.c b/src/daemon/dumpmodules.c
index cbbf94f..01547a3 100644
--- a/src/daemon/dumpmodules.c
+++ b/src/daemon/dumpmodules.c
@@ -28,7 +28,6 @@
 
 #include <string.h>
 #include <getopt.h>
-#include <assert.h>
 #include <stdio.h>
 #include <ltdl.h>
 
@@ -36,19 +35,23 @@
 
 #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");
@@ -77,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);
@@ -122,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++)
diff --git a/src/daemon/main.c b/src/daemon/main.c
index ed5aa44..87f3f01 100644
--- a/src/daemon/main.c
+++ b/src/daemon/main.c
@@ -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>
@@ -287,7 +286,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;
@@ -498,7 +497,7 @@ int main(int argc, char *argv[]) {
             goto finish;
 
         default:
-            assert(conf->cmd == PA_CMD_DAEMON);
+            pa_assert(conf->cmd == PA_CMD_DAEMON);
     }
 
     if (real_root && !conf->system_instance) {
@@ -630,8 +629,7 @@ int main(int argc, char *argv[]) {
     
     pa_rtsig_configure(SIGRTMIN+10, SIGRTMAX);
 
-    mainloop = pa_mainloop_new();
-    assert(mainloop);
+    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.");
@@ -664,9 +662,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)
@@ -674,10 +670,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)
diff --git a/src/modules/alsa-util.c b/src/modules/alsa-util.c
index 5d49a3c..ee2dfdb 100644
--- a/src/modules/alsa-util.c
+++ b/src/modules/alsa-util.c
@@ -88,7 +88,7 @@ static void io_cb(pa_mainloop_api*a, pa_io_event* e, PA_GCC_UNUSED int fd, pa_io
         }
     }
 
-    assert(i != fdl->num_fds);
+    pa_assert(i != fdl->num_fds);
 
     if ((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));
diff --git a/src/modules/module-alsa-source.c b/src/modules/module-alsa-source.c
index fef7b01..e4a6ed0 100644
--- a/src/modules/module-alsa-source.c
+++ b/src/modules/module-alsa-source.c
@@ -26,7 +26,6 @@
 #include <config.h>
 #endif
 
-#include <assert.h>
 #include <stdio.h>
 
 #include <asoundlib.h>
@@ -817,7 +816,7 @@ int pa__init(pa_module*m) {
     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;
diff --git a/src/modules/module-cli.c b/src/modules/module-cli.c
index fd180bc..8412521 100644
--- a/src/modules/module-cli.c
+++ b/src/modules/module-cli.c
@@ -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,8 +60,8 @@ 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);
 }
@@ -71,7 +71,7 @@ int pa__init(pa_module*m) {
     pa_modargs *ma;
     int exit_on_eof = 0;
 
-    assert(m);
+    pa_assert(m);
 
     if (m->core->running_as_daemon) {
         pa_log_info("Running as daemon, refusing to load this module.");
@@ -113,7 +113,7 @@ fail:
 }
 
 void pa__done(pa_module*m) {
-    assert(m);
+    pa_assert(m);
 
     if (m->core->running_as_daemon == 0) {
         pa_cli_free(m->userdata);
diff --git a/src/modules/module-detect.c b/src/modules/module-detect.c
index 858147e..7dc2524 100644
--- a/src/modules/module-detect.c
+++ b/src/modules/module-detect.c
@@ -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"
 
diff --git a/src/modules/module-lirc.c b/src/modules/module-lirc.c
index 6f4e98d..401763b 100644
--- a/src/modules/module-lirc.c
+++ b/src/modules/module-lirc.c
@@ -26,12 +26,12 @@
 #endif
 
 #include <stdio.h>
-#include <assert.h>
 #include <unistd.h>
 #include <string.h>
-#include <lirc/lirc_client.h>
 #include <stdlib.h>
 
+#include <lirc/lirc_client.h>
+
 #include <pulse/xmalloc.h>
 
 #include <pulsecore/module.h>
@@ -39,6 +39,7 @@
 #include <pulsecore/namereg.h>
 #include <pulsecore/sink.h>
 #include <pulsecore/modargs.h>
+#include <pulsecore/macro.h>
 
 #include "module-lirc-symdef.h"
 
diff --git a/src/modules/module-sine.c b/src/modules/module-sine.c
index 94036f6..f48cb09 100644
--- a/src/modules/module-sine.c
+++ b/src/modules/module-sine.c
@@ -26,7 +26,6 @@
 #endif
 
 #include <stdio.h>
-#include <assert.h>
 #include <math.h>
 
 #include <pulse/xmalloc.h>
diff --git a/src/modules/module-zeroconf-publish.c b/src/modules/module-zeroconf-publish.c
index 1cdde84..8b62ffb 100644
--- a/src/modules/module-zeroconf-publish.c
+++ b/src/modules/module-zeroconf-publish.c
@@ -26,7 +26,6 @@
 #endif
 
 #include <stdio.h>
-#include <assert.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
diff --git a/src/pulse/glib-mainloop.c b/src/pulse/glib-mainloop.c
index 5b399aa..b7a7537 100644
--- a/src/pulse/glib-mainloop.c
+++ b/src/pulse/glib-mainloop.c
@@ -25,8 +25,6 @@
 #include <config.h>
 #endif
 
-#include <assert.h>
-
 #include <pulse/xmalloc.h>
 #include <pulse/timeval.h>
 
diff --git a/src/pulse/subscribe.c b/src/pulse/subscribe.c
index 31b7636..580038c 100644
--- a/src/pulse/subscribe.c
+++ b/src/pulse/subscribe.c
@@ -25,7 +25,6 @@
 #include <config.h>
 #endif
 
-#include <assert.h>
 #include <stdio.h>
 
 #include <pulsecore/gccmacro.h>
diff --git a/src/pulse/util.c b/src/pulse/util.c
index 32f4137..a5f0e8e 100644
--- a/src/pulse/util.c
+++ b/src/pulse/util.c
@@ -26,7 +26,6 @@
 #include <config.h>
 #endif
 
-#include <assert.h>
 #include <errno.h>
 #include <limits.h>
 #include <stdio.h>
diff --git a/src/pulsecore/authkey-prop.c b/src/pulsecore/authkey-prop.c
index 35b62d4..179c16c 100644
--- a/src/pulsecore/authkey-prop.c
+++ b/src/pulsecore/authkey-prop.c
@@ -38,7 +38,6 @@
 
 struct authkey_data {
     PA_REFCNT_DECLARE;
-    int ref;
     size_t length;
 };
 
diff --git a/src/pulsecore/cli-command.c b/src/pulsecore/cli-command.c
index 3a1ce5a..2e674cc 100644
--- a/src/pulsecore/cli-command.c
+++ b/src/pulsecore/cli-command.c
@@ -28,7 +28,6 @@
 
 #include <stdio.h>
 #include <string.h>
-#include <assert.h>
 #include <stdlib.h>
 #include <errno.h>
 #include <unistd.h>
diff --git a/src/pulsecore/cli.c b/src/pulsecore/cli.c
index bb80e90..9fff734 100644
--- a/src/pulsecore/cli.c
+++ b/src/pulsecore/cli.c
@@ -27,7 +27,6 @@
 
 #include <stdio.h>
 #include <string.h>
-#include <assert.h>
 #include <stdlib.h>
 
 #include <pulse/xmalloc.h>
diff --git a/src/pulsecore/core-scache.c b/src/pulsecore/core-scache.c
index 6176dcb..1cd24aa 100644
--- a/src/pulsecore/core-scache.c
+++ b/src/pulsecore/core-scache.c
@@ -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"
 
@@ -68,7 +68,10 @@
 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), %lu bytes with sample spec %s",
+    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));
+                 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);
 
@@ -318,7 +335,9 @@ int pa_scache_play_item_by_name(pa_core *c, const char *name, const char*sink_na
 
 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;
@@ -328,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;
@@ -339,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;
@@ -355,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;
@@ -382,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) {
@@ -397,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))) {
diff --git a/src/pulsecore/core-subscribe.c b/src/pulsecore/core-subscribe.c
index 288d107..06c5a4a 100644
--- a/src/pulsecore/core-subscribe.c
+++ b/src/pulsecore/core-subscribe.c
@@ -26,12 +26,12 @@
 #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,11 +196,11 @@ 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);
@@ -209,7 +209,7 @@ static void sched_event(pa_core *c) {
 /* 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 idx) {
     pa_subscription_event *e;
-    assert(c);
+    pa_assert(c);
 
     /* No need for queuing subscriptions of noone is listening */
     if (!c->subscriptions)
diff --git a/src/pulsecore/core-util.c b/src/pulsecore/core-util.c
index d37a11c..c0dd0d6 100644
--- a/src/pulsecore/core-util.c
+++ b/src/pulsecore/core-util.c
@@ -132,7 +132,7 @@ int pa_set_root(HANDLE handle) {
 void pa_make_nonblock_fd(int fd) {
 #ifdef O_NONBLOCK
     int v;
-    assert(fd >= 0);
+    pa_assert(fd >= 0);
 
     if ((v = fcntl(fd, F_GETFL)) >= 0)
         if (!(v & O_NONBLOCK))
@@ -153,7 +153,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);
@@ -300,9 +300,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;
@@ -331,9 +331,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;
@@ -423,7 +423,7 @@ char *pa_sprintf_malloc(const char *format, ...) {
     int  size = 100;
     char *c = NULL;
 
-    assert(format);
+    pa_assert(format);
 
     for(;;) {
         int r;
@@ -453,7 +453,7 @@ char *pa_vsprintf_malloc(const char *format, va_list ap) {
     int  size = 100;
     char *c = NULL;
 
-    assert(format);
+    pa_assert(format);
 
     for(;;) {
         int r;
@@ -479,7 +479,9 @@ 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;
@@ -550,7 +552,7 @@ int pa_fd_set_cloexec(int fd, int b) {
 
 #ifdef FD_CLOEXEC
     int v;
-    assert(fd >= 0);
+    pa_assert(fd >= 0);
 
     if ((v = fcntl(fd, F_GETFD, 0)) < 0)
         return -1;
@@ -690,7 +692,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);
 
@@ -856,7 +858,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;
@@ -865,7 +867,7 @@ 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;
@@ -916,7 +918,8 @@ 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",
@@ -1026,7 +1029,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];
@@ -1057,7 +1063,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;
@@ -1084,8 +1092,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);
 
@@ -1096,8 +1104,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);
@@ -1150,7 +1158,9 @@ 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);
 
     l = strtol(s, &x, 0);
 
@@ -1166,7 +1176,9 @@ 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);
 
     l = strtoul(s, &x, 0);
 
diff --git a/src/pulsecore/dynarray.c b/src/pulsecore/dynarray.c
index 944e357..f5e73ed 100644
--- a/src/pulsecore/dynarray.c
+++ b/src/pulsecore/dynarray.c
@@ -26,10 +26,10 @@
 #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;
 }
diff --git a/src/pulsecore/flist.c b/src/pulsecore/flist.c
index ada0d57..680a9f7 100644
--- a/src/pulsecore/flist.c
+++ b/src/pulsecore/flist.c
@@ -25,14 +25,14 @@
 #include <config.h>
 #endif
 
-#include <assert.h>
+#include <pulse/xmalloc.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 <pulsecore/macro.h>
 
 #include "flist.h"
 
@@ -111,7 +111,7 @@ pa_flist *pa_flist_new(unsigned size) {
     if (!size)
         size = FLIST_SIZE;
 
-    assert(pa_is_power_of_two(size));
+    pa_assert(pa_is_power_of_two(size));
 
     l = pa_xmalloc0(PA_ALIGN(sizeof(pa_flist)) + (sizeof(struct cell) * size));
 
@@ -129,7 +129,7 @@ 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;
@@ -156,8 +156,8 @@ int pa_flist_push(pa_flist*l, void *p) {
     int idx, len, n;
     struct cell *cells;
 
-    assert(l);
-    assert(p);
+    pa_assert(l);
+    pa_assert(p);
 
     cells = PA_FLIST_CELLS(l);
 
@@ -196,7 +196,7 @@ void* pa_flist_pop(pa_flist*l) {
     int idx, len, n;
     struct cell *cells;
 
-    assert(l);
+    pa_assert(l);
 
     cells = PA_FLIST_CELLS(l);
 
diff --git a/src/pulsecore/hashmap.c b/src/pulsecore/hashmap.c
index 57be818..8366181 100644
--- a/src/pulsecore/hashmap.c
+++ b/src/pulsecore/hashmap.c
@@ -26,7 +26,6 @@
 #endif
 
 #include <stdlib.h>
-#include <assert.h>
 #include <string.h>
 
 #include <pulse/xmalloc.h>
@@ -34,6 +33,7 @@
 #include <pulsecore/idxset.h>
 #include <pulsecore/log.h>
 #include <pulsecore/flist.h>
+#include <pulsecore/macro.h>
 
 #include "hashmap.h"
 
@@ -72,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;
@@ -87,7 +87,7 @@ 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;
     }
 
@@ -98,7 +98,7 @@ static void remove(pa_hashmap *h, struct hashmap_entry *e) {
 }
 
 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)
@@ -112,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)
@@ -125,7 +125,7 @@ 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;
 
@@ -159,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;
 
@@ -174,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;
 
@@ -191,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;
@@ -214,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;
@@ -225,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;
diff --git a/src/pulsecore/hook-list.c b/src/pulsecore/hook-list.c
index 4f88418..3a6874c 100644
--- a/src/pulsecore/hook-list.c
+++ b/src/pulsecore/hook-list.c
@@ -21,10 +21,16 @@
   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 ++;
 
diff --git a/src/pulsecore/iochannel.c b/src/pulsecore/iochannel.c
index 6f58ae7..2f586cb 100644
--- a/src/pulsecore/iochannel.c
+++ b/src/pulsecore/iochannel.c
@@ -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"
 
@@ -68,11 +68,11 @@ struct pa_iochannel {
 };
 
 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;
@@ -92,10 +92,10 @@ static void callback(pa_mainloop_api* m, pa_io_event *e, int fd, pa_io_event_fla
     pa_iochannel *io = userdata;
     int changed = 0;
 
-    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;
@@ -105,13 +105,13 @@ static void callback(pa_mainloop_api* m, pa_io_event *e, int fd, pa_io_event_fla
     if ((f & PA_IO_EVENT_INPUT) && !io->readable) {
         io->readable = 1;
         changed = 1;
-        assert(e == io->input_event);
+        pa_assert(e == io->input_event);
     }
 
     if ((f & PA_IO_EVENT_OUTPUT) && !io->writable) {
         io->writable = 1;
         changed = 1;
-        assert(e == io->output_event);
+        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;
@@ -144,7 +144,7 @@ pa_iochannel* pa_iochannel_new(pa_mainloop_api*m, int ifd, int ofd) {
     io->input_event = io->output_event = NULL;
 
     if (ifd == ofd) {
-        assert(ifd >= 0);
+        pa_assert(ifd >= 0);
         pa_make_nonblock_fd(io->ifd);
         io->input_event = io->output_event = m->io_new(m, ifd, PA_IO_EVENT_INPUT|PA_IO_EVENT_OUTPUT, callback, io);
     } else {
@@ -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);
@@ -183,19 +183,19 @@ void pa_iochannel_free(pa_iochannel*io) {
 }
 
 int pa_iochannel_is_readable(pa_iochannel*io) {
-    assert(io);
+    pa_assert(io);
 
     return io->readable || io->hungup;
 }
 
 int pa_iochannel_is_writable(pa_iochannel*io) {
-    assert(io);
+    pa_assert(io);
 
     return io->writable && !io->hungup;
 }
 
 int pa_iochannel_is_hungup(pa_iochannel*io) {
-    assert(io);
+    pa_assert(io);
 
     return io->hungup;
 }
@@ -203,10 +203,10 @@ 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) {
@@ -220,9 +220,9 @@ 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) {
@@ -239,9 +239,9 @@ int 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 +254,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 +273,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;
@@ -322,12 +322,12 @@ ssize_t pa_iochannel_read_with_creds(pa_iochannel*io, void*data, size_t l, pa_cr
     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,7 +353,7 @@ 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;
@@ -373,46 +373,46 @@ 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);
+    pa_assert(io);
 
     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;
 }
diff --git a/src/pulsecore/iochannel.h b/src/pulsecore/iochannel.h
index c22fefd..90eb963 100644
--- a/src/pulsecore/iochannel.h
+++ b/src/pulsecore/iochannel.h
@@ -25,6 +25,10 @@
   USA.
 ***/
 
+#ifndef PACKAGE
+#error "Please include config.h before including this file!"
+#endif
+
 #include <sys/types.h>
 
 #include <pulse/mainloop-api.h>
diff --git a/src/pulsecore/ioline.c b/src/pulsecore/ioline.c
index 23a90a7..a362700 100644
--- a/src/pulsecore/ioline.c
+++ b/src/pulsecore/ioline.c
@@ -27,7 +27,6 @@
 
 #include <errno.h>
 #include <stdio.h>
-#include <assert.h>
 #include <stdlib.h>
 #include <string.h>
 
@@ -35,6 +34,8 @@
 
 #include <pulsecore/core-error.h>
 #include <pulsecore/log.h>
+#include <pulsecore/macro.h>
+#include <pulsecore/refcnt.h>
 
 #include "ioline.h"
 
@@ -42,10 +43,11 @@
 #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 +67,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 +82,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 +96,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 +110,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 +148,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 +160,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 +180,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 +191,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 +222,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 +259,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,7 +294,7 @@ 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) {
@@ -314,7 +319,9 @@ 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) {
 
@@ -341,8 +348,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);
 
@@ -362,21 +369,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;
 
@@ -388,8 +402,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);
diff --git a/src/pulsecore/ipacl.c b/src/pulsecore/ipacl.c
index a240d2a..8a8eac7 100644
--- a/src/pulsecore/ipacl.c
+++ b/src/pulsecore/ipacl.c
@@ -46,13 +46,13 @@
 #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,7 +102,7 @@ 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;
             }
 
@@ -116,7 +116,7 @@ pa_ip_acl* pa_ip_acl_new(const char *s) {
             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;
@@ -142,7 +142,7 @@ pa_ip_acl* pa_ip_acl_new(const char *s) {
             }
 
         } 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)
diff --git a/src/pulsecore/mcalign.c b/src/pulsecore/mcalign.c
index 9761643..8ca7c96 100644
--- a/src/pulsecore/mcalign.c
+++ b/src/pulsecore/mcalign.c
@@ -27,10 +27,10 @@
 
 #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) {
@@ -94,7 +94,7 @@ void pa_mcalign_push(pa_mcalign *m, const pa_memchunk *c) {
             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)
@@ -110,8 +110,8 @@ void pa_mcalign_push(pa_mcalign *m, const pa_memchunk *c) {
             pa_memblock_release(c->memblock);
             m->leftover.length += l;
 
-            assert(m->leftover.length <= m->base);
-            assert(m->leftover.length <= pa_memblock_get_length(m->leftover.memblock));
+            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 */
@@ -134,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)
@@ -161,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;
@@ -175,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;
 
@@ -184,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;
         }
@@ -200,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;
diff --git a/src/pulsecore/memblock.c b/src/pulsecore/memblock.c
index 53c6087..cded2df 100644
--- a/src/pulsecore/memblock.c
+++ b/src/pulsecore/memblock.c
@@ -28,7 +28,6 @@
 
 #include <stdio.h>
 #include <stdlib.h>
-#include <assert.h>
 #include <string.h>
 #include <unistd.h>
 #include <signal.h>
diff --git a/src/pulsecore/memchunk.c b/src/pulsecore/memchunk.c
index 36df9f6..4e73b63 100644
--- a/src/pulsecore/memchunk.c
+++ b/src/pulsecore/memchunk.c
@@ -27,7 +27,6 @@
 
 #include <stdio.h>
 #include <stdlib.h>
-#include <assert.h>
 #include <string.h>
 #include <errno.h>
 
@@ -42,8 +41,8 @@ pa_memchunk* pa_memchunk_make_writable(pa_memchunk *c, size_t min) {
     size_t l;
     void *tdata, *sdata;
 
-    assert(c);
-    assert(c->memblock);
+    pa_assert(c);
+    pa_assert(c->memblock);
 
     if (pa_memblock_ref_is_one(c->memblock) &&
         !pa_memblock_is_read_only(c->memblock) &&
@@ -68,7 +67,7 @@ pa_memchunk* pa_memchunk_make_writable(pa_memchunk *c, size_t min) {
 }
 
 pa_memchunk* pa_memchunk_reset(pa_memchunk *c) {
-    assert(c);
+    pa_assert(c);
 
     c->memblock = NULL;
     c->length = c->index = 0;
diff --git a/src/pulsecore/modargs.c b/src/pulsecore/modargs.c
index 3733f65..41e8008 100644
--- a/src/pulsecore/modargs.c
+++ b/src/pulsecore/modargs.c
@@ -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)
@@ -267,8 +279,8 @@ int pa_modargs_get_channel_map(pa_modargs *ma, pa_channel_map *rmap) {
     pa_channel_map map;
     const char *cm;
 
-    assert(ma);
-    assert(rmap);
+    pa_assert(ma);
+    pa_assert(rmap);
 
     map = *rmap;
 
@@ -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;
 
diff --git a/src/pulsecore/modinfo.c b/src/pulsecore/modinfo.c
index 79baef8..9f53887 100644
--- a/src/pulsecore/modinfo.c
+++ b/src/pulsecore/modinfo.c
@@ -82,7 +82,7 @@ pa_modinfo *pa_modinfo_get_by_name(const char *name) {
 }
 
 void pa_modinfo_free(pa_modinfo *i) {
-    assert(i);
+    pa_assert(i);
     
     pa_xfree(i->author);
     pa_xfree(i->description);
diff --git a/src/pulsecore/module.c b/src/pulsecore/module.c
index bd56554..e6d7fca 100644
--- a/src/pulsecore/module.c
+++ b/src/pulsecore/module.c
@@ -157,7 +157,8 @@ static void pa_module_free(pa_module *m) {
 }
 
 void pa_module_unload(pa_core *c, pa_module *m) {
-    pa_assert(c && m);
+    pa_assert(c);
+    pa_assert(m);
 
     pa_assert(c->modules);
     if (!(m = pa_idxset_remove_by_data(c->modules, m, NULL)))
diff --git a/src/pulsecore/mutex-posix.c b/src/pulsecore/mutex-posix.c
index a66950e..64f466d 100644
--- a/src/pulsecore/mutex-posix.c
+++ b/src/pulsecore/mutex-posix.c
@@ -25,18 +25,13 @@
 #include <config.h>
 #endif
 
-#include <assert.h>
 #include <pthread.h>
 
 #include <pulse/xmalloc.h>
+#include <pulsecore/macro.h>
 
 #include "mutex.h"
 
-#define ASSERT_SUCCESS(x) do { \
-    int _r = (x); \
-    assert(_r == 0); \
-} while(0)
-
 struct pa_mutex {
     pthread_mutex_t mutex;
 };
@@ -52,61 +47,59 @@ pa_mutex* pa_mutex_new(int recursive) {
     pthread_mutexattr_init(&attr);
 
     if (recursive)
-        ASSERT_SUCCESS(pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE));
+        pa_assert_se(pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE) == 0);
 
     m = pa_xnew(pa_mutex, 1);
-
-    ASSERT_SUCCESS(pthread_mutex_init(&m->mutex, &attr));
+    pa_assert_se(pthread_mutex_init(&m->mutex, &attr) == 0);
     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);
 }
diff --git a/src/pulsecore/namereg.c b/src/pulsecore/namereg.c
index 5fae3fc..fe2be46 100644
--- a/src/pulsecore/namereg.c
+++ b/src/pulsecore/namereg.c
@@ -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;
@@ -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;
diff --git a/src/pulsecore/packet.c b/src/pulsecore/packet.c
index ce57cb3..2706efe 100644
--- a/src/pulsecore/packet.c
+++ b/src/pulsecore/packet.c
@@ -25,22 +25,22 @@
 #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);
diff --git a/src/pulsecore/packet.h b/src/pulsecore/packet.h
index 842582c..bcac4a7 100644
--- a/src/pulsecore/packet.h
+++ b/src/pulsecore/packet.h
@@ -27,9 +27,11 @@
 #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;
diff --git a/src/pulsecore/parseaddr.c b/src/pulsecore/parseaddr.c
index a49a09e..0df37f4 100644
--- a/src/pulsecore/parseaddr.c
+++ b/src/pulsecore/parseaddr.c
@@ -26,13 +26,13 @@
 #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;
 }
diff --git a/src/pulsecore/pdispatch.c b/src/pulsecore/pdispatch.c
index f5ec1c0..737b1b9 100644
--- a/src/pulsecore/pdispatch.c
+++ b/src/pulsecore/pdispatch.c
@@ -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)
@@ -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;
 }
diff --git a/src/pulsecore/pid.c b/src/pulsecore/pid.c
index efb6e64..22ceae8 100644
--- a/src/pulsecore/pid.c
+++ b/src/pulsecore/pid.c
@@ -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,7 +57,8 @@ 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",
@@ -73,7 +74,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("WARNING: failed to parse PID file '%s'", fn);
         return (pid_t) -1;
     }
 
@@ -83,6 +84,8 @@ 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;
 
@@ -238,7 +241,7 @@ fail:
 
     if (fd >= 0) {
         pa_lock_fd(fd, 0);
-        close(fd);
+        pa_assert_se(close(fd) == 0);
     }
 
     return ret;
@@ -280,7 +283,7 @@ fail:
 
     if (fd >= 0) {
         pa_lock_fd(fd, 0);
-        close(fd);
+        pa_assert_se(close(fd) == 0);
     }
 
     return ret;
diff --git a/src/pulsecore/props.c b/src/pulsecore/props.c
index 37e7419..fc3dce9 100644
--- a/src/pulsecore/props.c
+++ b/src/pulsecore/props.c
@@ -25,11 +25,9 @@
 #include <config.h>
 #endif
 
-#include <assert.h>
-
 #include <pulse/xmalloc.h>
-
 #include <pulsecore/log.h>
+#include <pulsecore/macro.h>
 
 #include "props.h"
 
@@ -41,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);
+    
+    pa_assert(name);
+    pa_assert(data);
 
-    p = pa_xmalloc(sizeof(pa_property));
+    p = pa_xnew(pa_property, 1);
     p->name = pa_xstrdup(name);
     p->data = data;
 
@@ -52,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);
@@ -60,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;
@@ -70,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;
@@ -82,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;
@@ -92,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;
@@ -113,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);
diff --git a/src/pulsecore/protocol-cli.c b/src/pulsecore/protocol-cli.c
index 1d543ae..d9d0073 100644
--- a/src/pulsecore/protocol-cli.c
+++ b/src/pulsecore/protocol-cli.c
@@ -25,13 +25,13 @@
 #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);
diff --git a/src/pulsecore/protocol-http.c b/src/pulsecore/protocol-http.c
index eb5bda0..4a2836e 100644
--- a/src/pulsecore/protocol-http.c
+++ b/src/pulsecore/protocol-http.c
@@ -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,9 +65,10 @@ 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);
+    
+    pa_assert(c);
+    pa_assert(msg);
+    pa_assert(mime);
 
     pa_snprintf(s, sizeof(s),
              "HTTP/1.0 %i %s\n"
@@ -83,7 +84,7 @@ 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");
 
@@ -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);
+    
+    pa_core_assert_ref(core);
+    pa_assert(server);
 
-    p = pa_xmalloc(sizeof(pa_protocol_http));
+    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);
diff --git a/src/pulsecore/pstream-util.c b/src/pulsecore/pstream-util.c
index fae1e49..1b51378 100644
--- a/src/pulsecore/pstream-util.c
+++ b/src/pulsecore/pstream-util.c
@@ -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);
diff --git a/src/pulsecore/queue.c b/src/pulsecore/queue.c
index b095481..a88876f 100644
--- a/src/pulsecore/queue.c
+++ b/src/pulsecore/queue.c
@@ -72,6 +72,9 @@ 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;
 
+    pa_assert(q);
+    pa_assert(p);
+    
     if (!(e = pa_flist_pop(PA_STATIC_FLIST_GET(entries))))
         e = pa_xnew(struct queue_entry, 1);
     
diff --git a/src/pulsecore/random.c b/src/pulsecore/random.c
index 3f59191..b0b4926 100644
--- a/src/pulsecore/random.c
+++ b/src/pulsecore/random.c
@@ -31,21 +31,22 @@
 #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;
 
@@ -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--)
diff --git a/src/pulsecore/shm.c b/src/pulsecore/shm.c
index 38187dd..78b968e 100644
--- a/src/pulsecore/shm.c
+++ b/src/pulsecore/shm.c
@@ -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 at cendio.se> for Cendio AB
+    Copyright 2006 Lennart Poettering
+    Copyright 2006 Pierre Ossman <ossman at 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>
@@ -63,10 +62,10 @@ 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);
 
     if (!shared) {
         m->id = 0;
@@ -115,7 +114,7 @@ int pa_shm_create_rw(pa_shm *m, size_t size, int shared, mode_t mode) {
         close(fd);
         m->do_unlink = 1;
 #else
-                return -1;
+        return -1;
 #endif
     }
 
@@ -128,7 +127,7 @@ fail:
 #ifdef HAVE_SHM_OPEN
     if (fd >= 0) {
         shm_unlink(fn);
-        close(fd);
+        pa_assert_se(close(fd) >= 0);
     }
 #endif
 
@@ -136,12 +135,12 @@ 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) {
@@ -179,13 +178,13 @@ 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
@@ -225,7 +224,7 @@ 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);
 
@@ -254,13 +253,13 @@ int pa_shm_attach_ro(pa_shm *m, unsigned id) {
     m->do_unlink = 0;
     m->shared = 1;
 
-    close(fd);
+    pa_assert_se(close(fd) >= 0);
 
     return 0;
 
 fail:
     if (fd >= 0)
-        close(fd);
+        pa_assert_se(close(fd) >= 0);
 
     return -1;
 }
@@ -268,7 +267,7 @@ fail:
 #else /* HAVE_SHM_OPEN */
 
 int pa_shm_attach_ro(pa_shm *m, unsigned id) {
-        return -1;
+    return -1;
 }
 
 #endif /* HAVE_SHM_OPEN */
diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c
index b61a850..aac4a2f 100644
--- a/src/pulsecore/sink.c
+++ b/src/pulsecore/sink.c
@@ -27,7 +27,6 @@
 #endif
 
 #include <stdlib.h>
-#include <assert.h>
 #include <string.h>
 #include <stdio.h>
 
@@ -64,7 +63,6 @@ pa_sink* pa_sink_new(
     pa_sink *s;
     char *n = NULL;
     char st[256];
-    int r;
     pa_channel_map tmap;
 
     pa_assert(core);
@@ -120,8 +118,7 @@ pa_sink* pa_sink_new(
     s->rtpoll = NULL;
     s->silence = NULL;
 
-    r = pa_idxset_put(core->sinks, s, &s->index);
-    pa_assert(s->index != PA_IDXSET_INVALID && r >= 0);
+    pa_assert_se(pa_idxset_put(core->sinks, s, &s->index) >= 0);
 
     pa_sample_spec_snprint(st, sizeof(st), spec);
     pa_log_info("Created sink %u \"%s\" with sample spec \"%s\"", s->index, s->name, st);
diff --git a/src/pulsecore/sioman.c b/src/pulsecore/sioman.c
index d3d7538..8d4c6fa 100644
--- a/src/pulsecore/sioman.c
+++ b/src/pulsecore/sioman.c
@@ -25,21 +25,17 @@
 #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));
 }
diff --git a/src/pulsecore/socket-client.c b/src/pulsecore/socket-client.c
index 9e7280d..0922a94 100644
--- a/src/pulsecore/socket-client.c
+++ b/src/pulsecore/socket-client.c
@@ -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 at cendio.se> for Cendio AB
+    Copyright 2004-2006 Lennart Poettering
+    Copyright 2006-2007 Pierre Ossman <ossman at 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
@@ -55,23 +54,24 @@
 #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);
 
@@ -159,7 +162,7 @@ static void do_call(pa_socket_client *c) {
     }
 
     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,19 +179,34 @@ 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_assert(c);
+    pa_assert(PA_REFCNT_VALUE(c) >= 1);
+    pa_assert(sa);
+    pa_assert(len > 0);
 
     pa_make_nonblock_fd(c->fd);
 
@@ -203,25 +221,24 @@ 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;
     sa.sin_port = htons(port);
     sa.sin_addr.s_addr = htonl(address);
-
+    
     return pa_socket_client_new_sockaddr(m, (struct sockaddr*) &sa, sizeof(sa));
 }
 
@@ -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:
@@ -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 */
@@ -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;
 }
diff --git a/src/pulsecore/socket-server.c b/src/pulsecore/socket-server.c
index c900ff3..21c5115 100644
--- a/src/pulsecore/socket-server.c
+++ b/src/pulsecore/socket-server.c
@@ -27,7 +27,6 @@
 #endif
 
 #include <stdlib.h>
-#include <assert.h>
 #include <errno.h>
 #include <string.h>
 #include <sys/types.h>
@@ -72,12 +71,14 @@
 #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);
 
@@ -133,8 +141,7 @@ static void callback(pa_mainloop_api *mainloop, pa_io_event *e, int fd, PA_GCC_U
     else
         pa_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);
+    
+    pa_assert(m);
+    pa_assert(fd >= 0);
 
-    s = pa_xmalloc(sizeof(pa_socket_server));
-    s->ref = 1;
+    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,7 +185,8 @@ 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));
@@ -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,7 +245,8 @@ 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));
@@ -286,7 +297,8 @@ 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));
@@ -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))
         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: {
diff --git a/src/pulsecore/socket-util.c b/src/pulsecore/socket-util.c
index 511f12e..4026b9b 100644
--- a/src/pulsecore/socket-util.c
+++ b/src/pulsecore/socket-util.c
@@ -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>
@@ -75,19 +74,19 @@
 #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) {
-        pa_snprintf(c, l, "Invalid client fd");
-        return;
-    }
+    pa_assert_se(fstat(fd, &st) == 0);
 #endif
 
 #ifndef OS_IS_WIN32
@@ -109,11 +108,11 @@ void pa_socket_peer_to_string(int fd, char *c, size_t l) {
                 uint32_t ip = ntohl(sa.in.sin_addr.s_addr);
 
                 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));
+                            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];
@@ -147,7 +146,7 @@ void pa_socket_peer_to_string(int fd, char *c, size_t l) {
 int pa_socket_low_delay(int fd) {
 #ifdef SO_PRIORITY
     int priority;
-    assert(fd >= 0);
+    pa_assert(fd >= 0);
 
     priority = 7;
     if (setsockopt(fd, SOL_SOCKET, SO_PRIORITY, (void*)&priority, sizeof(priority)) < 0)
@@ -160,7 +159,7 @@ int pa_socket_low_delay(int fd) {
 int pa_socket_tcp_low_delay(int fd) {
     int ret, tos, on;
 
-    assert(fd >= 0);
+    pa_assert(fd >= 0);
 
     ret = pa_socket_low_delay(fd);
 
@@ -176,8 +175,7 @@ int pa_socket_tcp_low_delay(int fd) {
         ret = -1;
 #endif
 
-#if defined(IPTOS_LOWDELAY) && defined(IP_TOS) && (defined(SOL_IP) || \
-        defined(IPPROTO_IP))
+#if defined(IPTOS_LOWDELAY) && defined(IP_TOS) && (defined(SOL_IP) || defined(IPPROTO_IP))
     tos = IPTOS_LOWDELAY;
 #ifdef SOL_IP
     if (setsockopt(fd, SOL_IP, IP_TOS, (void*)&tos, sizeof(tos)) < 0)
@@ -188,27 +186,26 @@ int pa_socket_tcp_low_delay(int fd) {
 #endif
 
     return ret;
-
 }
 
 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 +216,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 +243,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;
 
diff --git a/src/pulsecore/source.c b/src/pulsecore/source.c
index f33240e..2f1a5a5 100644
--- a/src/pulsecore/source.c
+++ b/src/pulsecore/source.c
@@ -27,7 +27,6 @@
 #endif
 
 #include <stdio.h>
-#include <assert.h>
 #include <stdlib.h>
 #include <string.h>
 
@@ -56,12 +55,11 @@ 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);
 
     pa_return_null_if_fail(pa_sample_spec_valid(spec));
 
@@ -112,8 +110,7 @@ pa_source* pa_source_new(
     s->asyncmsgq = NULL;
     s->rtpoll = NULL;
 
-    r = pa_idxset_put(core->sources, s, &s->index);
-    assert(s->index != PA_IDXSET_INVALID && r >= 0);
+    pa_assert_se(pa_idxset_put(core->sources, s, &s->index) >= 0);
 
     pa_sample_spec_snprint(st, sizeof(st), spec);
     pa_log_info("Created source %u \"%s\" with sample spec \"%s\"", s->index, s->name, st);
diff --git a/src/pulsecore/strbuf.c b/src/pulsecore/strbuf.c
index 122343f..ea8389f 100644
--- a/src/pulsecore/strbuf.c
+++ b/src/pulsecore/strbuf.c
@@ -82,7 +82,7 @@ char *pa_strbuf_tostring(pa_strbuf *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;
     }
@@ -90,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;
 }
diff --git a/src/pulsecore/tagstruct.c b/src/pulsecore/tagstruct.c
index ac7ae1a..8cf542b 100644
--- a/src/pulsecore/tagstruct.c
+++ b/src/pulsecore/tagstruct.c
@@ -29,19 +29,18 @@
 #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,19 +365,24 @@ 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/tokenizer.c b/src/pulsecore/tokenizer.c
index 117c7f8..ed54a86 100644
--- a/src/pulsecore/tokenizer.c
+++ b/src/pulsecore/tokenizer.c
@@ -26,20 +26,16 @@
 #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);
 }
diff --git a/src/pulsecore/x11prop.c b/src/pulsecore/x11prop.c
index 5b85ea4..a740e39 100644
--- a/src/pulsecore/x11prop.c
+++ b/src/pulsecore/x11prop.c
@@ -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);
diff --git a/src/pulsecore/x11wrap.c b/src/pulsecore/x11wrap.c
index 1bcbcd4..1cb1ce8 100644
--- a/src/pulsecore/x11wrap.c
+++ b/src/pulsecore/x11wrap.c
@@ -25,7 +25,6 @@
 #include <config.h>
 #endif
 
-#include <assert.h>
 #include <stdio.h>
 
 #include <pulse/xmalloc.h>
@@ -34,6 +33,7 @@
 #include <pulsecore/log.h>
 #include <pulsecore/props.h>
 #include <pulsecore/core-util.h>
+#include <pulsecore/macro.h>
 
 #include "x11wrap.h"
 
@@ -47,8 +47,8 @@ struct pa_x11_internal {
 };
 
 struct pa_x11_wrapper {
+    PA_REFCNT_DECLARE;
     pa_core *core;
-    int ref;
 
     char *property_name;
     Display *display;
@@ -69,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;
@@ -77,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;
         }
@@ -87,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);
 
@@ -104,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);
 
@@ -114,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;
@@ -128,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);
@@ -138,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);
@@ -149,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;
 
@@ -170,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);
@@ -201,7 +215,8 @@ 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);
+    
+    pa_core_assert_ref(c);
 
     pa_snprintf(t, sizeof(t), "x11-wrapper%s%s", name ? "-" : "", name ? name : "");
     if ((w = pa_property_get(c, t)))
@@ -211,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);
@@ -234,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);
+    
+    pa_assert(w);
+    pa_assert(PA_REFCNT_VALUE(w) >= 1);
 
-    c = pa_xmalloc(sizeof(pa_x11_client));
+    c = pa_xnew(pa_x11_client, 1);
     c->wrapper = w;
     c->callback = cb;
     c->userdata = userdata;
@@ -247,8 +268,10 @@ 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);
 }

commit 54506ab44a9ac61e79b3a5c632db56bde41beded
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Sep 11 23:12:24 2007 +0000

    on systems where we know that POSIX shm is mapped to /dev/shm, add the ability to cleanup stale SHM segments. (Right now only Linux)
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1810 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/daemon/cmdline.c b/src/daemon/cmdline.c
index a3f1ff0..d14002f 100644
--- a/src/daemon/cmdline.c
+++ b/src/daemon/cmdline.c
@@ -64,7 +64,8 @@ enum {
     ARG_NO_CPU_LIMIT,
     ARG_DISABLE_SHM,
     ARG_DUMP_RESAMPLE_METHODS,
-    ARG_SYSTEM
+    ARG_SYSTEM,
+    ARG_CLEANUP_SHM
 };
 
 /* Tabel for getopt_long() */
@@ -94,6 +95,7 @@ static struct option long_options[] = {
     {"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}
 };
 
@@ -114,6 +116,7 @@ void pa_cmdline_help(const char *argv0) {
            "      --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"
 
@@ -188,6 +191,10 @@ int pa_cmdline_parse(pa_daemon_conf *conf, int argc, char *const argv [], int *d
             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:
diff --git a/src/daemon/daemon-conf.h b/src/daemon/daemon-conf.h
index 7633427..4d37861 100644
--- a/src/daemon/daemon-conf.h
+++ b/src/daemon/daemon-conf.h
@@ -41,7 +41,8 @@ typedef enum pa_daemon_conf_cmd {
     PA_CMD_DUMP_MODULES,
     PA_CMD_KILL,
     PA_CMD_CHECK,
-    PA_CMD_DUMP_RESAMPLE_METHODS
+    PA_CMD_DUMP_RESAMPLE_METHODS,
+    PA_CMD_CLEANUP_SHM
 } pa_daemon_conf_cmd_t;
 
 #ifdef HAVE_SYS_RESOURCE_H
diff --git a/src/daemon/main.c b/src/daemon/main.c
index 87f3f01..4509e7f 100644
--- a/src/daemon/main.c
+++ b/src/daemon/main.c
@@ -58,13 +58,12 @@
 #include <tcpd.h>
 #endif
 
-#include "../pulsecore/winsock.h"
-
 #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>
@@ -83,6 +82,7 @@
 #include <pulsecore/mutex.h>
 #include <pulsecore/thread.h>
 #include <pulsecore/once.h>
+#include <pulsecore/shm.h>
 
 #include "cmdline.h"
 #include "cpulimit.h"
@@ -496,6 +496,13 @@ int main(int argc, char *argv[]) {
 
             goto finish;
 
+        case PA_CMD_CLEANUP_SHM:
+
+            if (pa_shm_cleanup() >= 0)
+                retval = 0;
+
+            goto finish;
+            
         default:
             pa_assert(conf->cmd == PA_CMD_DAEMON);
     }
diff --git a/src/pulsecore/shm.c b/src/pulsecore/shm.c
index 78b968e..f17d946 100644
--- a/src/pulsecore/shm.c
+++ b/src/pulsecore/shm.c
@@ -33,17 +33,22 @@
 #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 <pulsecore/core-util.h>
 #include <pulsecore/macro.h>
-#include <pulse/xmalloc.h>
+#include <pulsecore/atomic.h>
 
 #include "shm.h"
 
@@ -51,8 +56,29 @@
 #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) {
     pa_snprintf(fn, l, "/pulse-shm-%u", id);
     return fn;
@@ -67,6 +93,13 @@ int pa_shm_create_rw(pa_shm *m, size_t size, int shared, mode_t mode) {
     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;
         m->size = size;
@@ -93,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);
 
@@ -101,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;
         }
@@ -111,6 +148,12 @@ int pa_shm_create_rw(pa_shm *m, size_t size, int shared, mode_t mode) {
             goto fail;
         }
 
+        /* 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);
+        
         close(fd);
         m->do_unlink = 1;
 #else
@@ -229,7 +272,8 @@ int pa_shm_attach_ro(pa_shm *m, unsigned id) {
     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;
     }
 
@@ -238,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;
     }
@@ -271,3 +315,67 @@ int pa_shm_attach_ro(pa_shm *m, unsigned id) {
 }
 
 #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;
+}
diff --git a/src/pulsecore/shm.h b/src/pulsecore/shm.h
index e695a2a..270591d 100644
--- a/src/pulsecore/shm.h
+++ b/src/pulsecore/shm.h
@@ -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

commit 7f92542420ef6085b6f090954052266cc70af8a1
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Sep 12 00:04:21 2007 +0000

    consolidate close() calls to pa_close(), and make sure on every occasion that we handle failures of close() sensibly
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1811 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/daemon/cpulimit.c b/src/daemon/cpulimit.c
index 37f7976..4f0adc0 100644
--- a/src/daemon/cpulimit.c
+++ b/src/daemon/cpulimit.c
@@ -223,9 +223,9 @@ void pa_cpu_limit_done(void) {
     }
 
     if (the_pipe[0] >= 0)
-        close(the_pipe[0]);
+        pa_assert_se(pa_close(the_pipe[0]) == 0);
     if (the_pipe[1] >= 0)
-        close(the_pipe[1]);
+        pa_assert_se(pa_close(the_pipe[1]) == 0);
     the_pipe[0] = the_pipe[1] = -1;
 
     if (installed) {
diff --git a/src/daemon/main.c b/src/daemon/main.c
index 4509e7f..0bbddff 100644
--- a/src/daemon/main.c
+++ b/src/daemon/main.c
@@ -160,9 +160,9 @@ 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]);
+        pa_assert_se(pa_close(p[0]) == 0);
     if (p[1] != -1)
-        close(p[1]);
+        pa_assert_se(pa_close(p[1]) == 0);
     p[0] = p[1] = -1;
 }
 
@@ -537,7 +537,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)) {
@@ -553,7 +553,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
 
@@ -568,9 +568,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);
@@ -592,7 +592,7 @@ 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
     }
diff --git a/src/modules/module-esound-compat-spawnfd.c b/src/modules/module-esound-compat-spawnfd.c
index 890ebb1..46235c0 100644
--- a/src/modules/module-esound-compat-spawnfd.c
+++ b/src/modules/module-esound-compat-spawnfd.c
@@ -65,7 +65,7 @@ int pa__init(pa_module*m) {
     if (pa_loop_write(fd, &x, sizeof(x), NULL) != sizeof(x))
         pa_log_warn("WARNING: write(%u, 1, 1) failed: %s", fd, pa_cstrerror(errno));
 
-    close(fd);
+    pa_assert_se(pa_close(fd) == 0);
 
     pa_module_unload_request(m);
 
diff --git a/src/modules/module-mmkbd-evdev.c b/src/modules/module-mmkbd-evdev.c
index 03394c0..dc0b1c1 100644
--- a/src/modules/module-mmkbd-evdev.c
+++ b/src/modules/module-mmkbd-evdev.c
@@ -254,7 +254,7 @@ void pa__done(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);
diff --git a/src/modules/module-oss.c b/src/modules/module-oss.c
index 9273a39..ffecd39 100644
--- a/src/modules/module-oss.c
+++ b/src/modules/module-oss.c
@@ -476,7 +476,7 @@ static int suspend(struct userdata *u) {
 
     /* Let's suspend */
     ioctl(u->fd, SNDCTL_DSP_SYNC, NULL);
-    close(u->fd);
+    pa_close(u->fd);
     u->fd = -1;
 
     if (u->rtpoll_item) {
@@ -588,7 +588,7 @@ static int unsuspend(struct userdata *u) {
     return 0;
 
 fail:
-    close(u->fd);
+    pa_close(u->fd);
     u->fd = -1;
     return -1;
 }
@@ -1324,7 +1324,7 @@ fail:
     if (u)
         pa__done(m);
     else if (fd >= 0)
-        close(fd);
+        pa_close(fd);
 
     if (ma)
         pa_modargs_free(ma);
@@ -1391,7 +1391,7 @@ void pa__done(pa_module*m) {
         munmap(u->out_mmap, u->out_hwbuf_size);
     
     if (u->fd >= 0)
-        close(u->fd);
+        pa_close(u->fd);
 
     pa_xfree(u->device_name);
     
diff --git a/src/modules/module-pipe-sink.c b/src/modules/module-pipe-sink.c
index 5cafaad..6145426 100644
--- a/src/modules/module-pipe-sink.c
+++ b/src/modules/module-pipe-sink.c
@@ -335,7 +335,7 @@ void pa__done(pa_module*m) {
     }
 
     if (u->fd >= 0)
-        close(u->fd);
+        pa_assert_se(pa_close(u->fd) == 0);
 
     pa_xfree(u);
 }
diff --git a/src/modules/module-pipe-source.c b/src/modules/module-pipe-source.c
index 291010e..68c89a0 100644
--- a/src/modules/module-pipe-source.c
+++ b/src/modules/module-pipe-source.c
@@ -313,7 +313,7 @@ void pa__done(pa_module*m) {
     }
 
     if (u->fd >= 0)
-        close(u->fd);
+        pa_assert_se(pa_close(u->fd) == 0);
 
     pa_xfree(u);
 }
diff --git a/src/modules/oss-util.c b/src/modules/oss-util.c
index 5a939cf..3649880 100644
--- a/src/modules/oss-util.c
+++ b/src/modules/oss-util.c
@@ -68,7 +68,7 @@ int pa_oss_open(const char *device, int *mode, int* pcaps) {
 
             pa_log_warn("'%s' doesn't support full duplex", device);
 
-            close(fd);
+            pa_close(fd);
         }
 
         if ((fd = open(device, (*mode = O_WRONLY)|O_NDELAY|O_NOCTTY)) < 0) {
@@ -147,7 +147,7 @@ success:
 
 fail:
     if (fd >= 0)
-        close(fd);
+        pa_close(fd);
     return -1;
 }
 
diff --git a/src/pulse/context.c b/src/pulse/context.c
index ab06aeb..1ed250f 100644
--- a/src/pulse/context.c
+++ b/src/pulse/context.c
@@ -524,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();
@@ -571,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;
 
@@ -586,9 +586,9 @@ static int context_connect_spawn(pa_context *c) {
 
 fail:
     if (fds[0] != -1)
-        close(fds[0]);
+        pa_assert_se(pa_close(fds[0]) == 0);
     if (fds[1] != -1)
-        close(fds[1]);
+        pa_assert_se(pa_close(fds[1]) == 0);
 
     unlock_autospawn_lock_file(c);
 
diff --git a/src/pulse/mainloop.c b/src/pulse/mainloop.c
index 419b74d..fc373d9 100644
--- a/src/pulse/mainloop.c
+++ b/src/pulse/mainloop.c
@@ -606,9 +606,9 @@ void pa_mainloop_free(pa_mainloop* m) {
     pa_xfree(m->pollfds);
 
     if (m->wakeup_pipe[0] >= 0)
-        close(m->wakeup_pipe[0]);
+        pa_assert_se(pa_close(m->wakeup_pipe[0]) == 0);
     if (m->wakeup_pipe[1] >= 0)
-        close(m->wakeup_pipe[1]);
+        pa_assert_se(pa_close(m->wakeup_pipe[1]) == 0);
 
     pa_xfree(m);
 }
diff --git a/src/pulsecore/authkey.c b/src/pulsecore/authkey.c
index d805624..4d9bfd3 100644
--- a/src/pulsecore/authkey.c
+++ b/src/pulsecore/authkey.c
@@ -120,7 +120,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;
@@ -221,7 +224,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;
diff --git a/src/pulsecore/core-util.c b/src/pulsecore/core-util.c
index c0dd0d6..62a6376 100644
--- a/src/pulsecore/core-util.c
+++ b/src/pulsecore/core-util.c
@@ -360,11 +360,11 @@ 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) {
+
 #ifdef OS_IS_WIN32
     int ret;
 
-    ret = closesocket(fd);
-    if (ret == 0)
+    if ((ret = closesocket(fd)) == 0)
         return 0;
 
     if (WSAGetLastError() != WSAENOTSOCK) {
@@ -838,8 +838,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
@@ -873,32 +872,33 @@ int pa_lock_lockfile(const char *fn) {
         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));
+            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;
         }
 
@@ -910,7 +910,7 @@ int pa_lock_lockfile(const char *fn) {
 fail:
 
     if (fd >= 0)
-        close(fd);
+        pa_close(fd);
 
     return -1;
 }
@@ -922,19 +922,17 @@ int pa_unlock_lockfile(const char *fn, int fd) {
     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;
     }
 
diff --git a/src/pulsecore/fdsem.c b/src/pulsecore/fdsem.c
index 5a358e2..710a74f 100644
--- a/src/pulsecore/fdsem.c
+++ b/src/pulsecore/fdsem.c
@@ -67,8 +67,8 @@ pa_fdsem *pa_fdsem_new(void) {
 void pa_fdsem_free(pa_fdsem *f) {
     pa_assert(f);
 
-    close(f->fds[0]);
-    close(f->fds[1]);
+    pa_assert_se(pa_close(f->fds[0]) == 0);
+    pa_assert_se(pa_close(f->fds[1]) == 0);
 
     pa_xfree(f);
 }
diff --git a/src/pulsecore/pid.c b/src/pulsecore/pid.c
index 22ceae8..6bc9f06 100644
--- a/src/pulsecore/pid.c
+++ b/src/pulsecore/pid.c
@@ -61,8 +61,7 @@ static pid_t read_pid(const char *fn, int fd) {
     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;
     }
 
@@ -74,7 +73,7 @@ static pid_t read_pid(const char *fn, int fd) {
         *e = 0;
 
     if (pa_atou(t, &pid) < 0) {
-        pa_log_warn("WARNING: failed to parse PID file '%s'", fn);
+        pa_log_warn("Failed to parse PID file '%s'", fn);
         return (pid_t) -1;
     }
 
@@ -91,8 +90,7 @@ static int open_pid_file(const char *fn, int mode) {
 
         if ((fd = open(fn, mode, 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("WARNING: failed to open PID file '%s': %s", fn, pa_cstrerror(errno));
             goto fail;
         }
 
@@ -101,8 +99,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;
         }
 
@@ -113,9 +110,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;
         }
 
@@ -128,7 +125,7 @@ fail:
 
     if (fd >= 0) {
         pa_lock_fd(fd, 0);
-        close(fd);
+        pa_close(fd);
     }
 
     return -1;
@@ -153,7 +150,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) {
@@ -161,17 +158,16 @@ 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;
     }
 
@@ -179,7 +175,7 @@ int pa_pid_file_create(void) {
     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;
     }
 
@@ -188,7 +184,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;
@@ -213,13 +213,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;
     }
 
@@ -230,8 +229,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;
     }
 
@@ -241,7 +239,11 @@ fail:
 
     if (fd >= 0) {
         pa_lock_fd(fd, 0);
-        pa_assert_se(close(fd) == 0);
+
+        if (pa_close(fd) < 0) {
+            pa_log_warn("Failed to close PID file '%s': %s", fn, pa_cstrerror(errno));
+            ret = -1;
+        }
     }
 
     return ret;
@@ -283,7 +285,7 @@ fail:
 
     if (fd >= 0) {
         pa_lock_fd(fd, 0);
-        pa_assert_se(close(fd) == 0);
+        pa_close(fd);
     }
 
     return ret;
diff --git a/src/pulsecore/random.c b/src/pulsecore/random.c
index b0b4926..87afebf 100644
--- a/src/pulsecore/random.c
+++ b/src/pulsecore/random.c
@@ -69,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;
 
diff --git a/src/pulsecore/shm.c b/src/pulsecore/shm.c
index f17d946..02f6a7b 100644
--- a/src/pulsecore/shm.c
+++ b/src/pulsecore/shm.c
@@ -154,7 +154,7 @@ int pa_shm_create_rw(pa_shm *m, size_t size, int shared, mode_t mode) {
         pa_atomic_store(&marker->pid, (int) getpid());
         pa_atomic_store(&marker->marker, SHM_MARKER);
         
-        close(fd);
+        pa_assert_se(close(fd) == 0);
         m->do_unlink = 1;
 #else
         return -1;
@@ -170,7 +170,7 @@ fail:
 #ifdef HAVE_SHM_OPEN
     if (fd >= 0) {
         shm_unlink(fn);
-        pa_assert_se(close(fd) >= 0);
+        pa_close(fd);
     }
 #endif
 
@@ -297,13 +297,13 @@ int pa_shm_attach_ro(pa_shm *m, unsigned id) {
     m->do_unlink = 0;
     m->shared = 1;
 
-    pa_assert_se(close(fd) >= 0);
+    pa_assert_se(pa_close(fd) == 0);
 
     return 0;
 
 fail:
     if (fd >= 0)
-        pa_assert_se(close(fd) >= 0);
+        pa_close(fd);
 
     return -1;
 }
diff --git a/src/pulsecore/sound-file-stream.c b/src/pulsecore/sound-file-stream.c
index d5523a6..8a04b82 100644
--- a/src/pulsecore/sound-file-stream.c
+++ b/src/pulsecore/sound-file-stream.c
@@ -40,6 +40,7 @@
 #include <pulsecore/sink-input.h>
 #include <pulsecore/log.h>
 #include <pulsecore/thread-mq.h>
+#include <pulsecore/core-util.h>
 
 #include "sound-file-stream.h"
 
@@ -271,7 +272,7 @@ int pa_play_file(
     
     if (!(u->sndfile = sf_open_fd(fd, SFM_READ, &sfinfo, 1))) {
         pa_log("Failed to open file %s", fname);
-        close(fd);
+        pa_close(fd);
         goto fail;
     }
 
diff --git a/src/pulsecore/sound-file.c b/src/pulsecore/sound-file.c
index 8727ba1..b1c509f 100644
--- a/src/pulsecore/sound-file.c
+++ b/src/pulsecore/sound-file.c
@@ -36,6 +36,7 @@
 #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"
@@ -77,7 +78,7 @@ int pa_sound_file_load(
     
     if (!(sf = sf_open_fd(fd, SFM_READ, &sfinfo, 1))) {
         pa_log("Failed to open file %s", fname);
-        close(fd);
+        pa_close(fd);
         goto finish;
     }
 

commit d9c4c9509d34ba89db06ff1252f3da18c6fd623b
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Sep 12 00:17:51 2007 +0000

    add new pa_pipe_close() API to close two fds at the same time
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1812 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/daemon/cpulimit.c b/src/daemon/cpulimit.c
index 4f0adc0..0fe11ea 100644
--- a/src/daemon/cpulimit.c
+++ b/src/daemon/cpulimit.c
@@ -222,11 +222,7 @@ void pa_cpu_limit_done(void) {
         api = NULL;
     }
 
-    if (the_pipe[0] >= 0)
-        pa_assert_se(pa_close(the_pipe[0]) == 0);
-    if (the_pipe[1] >= 0)
-        pa_assert_se(pa_close(the_pipe[1]) == 0);
-    the_pipe[0] = the_pipe[1] = -1;
+    pa_close_pipe(the_pipe);
 
     if (installed) {
         pa_assert_se(sigaction(SIGXCPU, &sigaction_prev, NULL) >= 0);
diff --git a/src/daemon/main.c b/src/daemon/main.c
index 0bbddff..93d4eb6 100644
--- a/src/daemon/main.c
+++ b/src/daemon/main.c
@@ -158,14 +158,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)
-        pa_assert_se(pa_close(p[0]) == 0);
-    if (p[1] != -1)
-        pa_assert_se(pa_close(p[1]) == 0);
-    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)
@@ -745,7 +737,7 @@ finish:
     if (valid_pid_file)
         pa_pid_file_remove();
 
-    close_pipe(daemon_pipe);
+    pa_close_pipe(daemon_pipe);
 
 #ifdef OS_IS_WIN32
     WSACleanup();
diff --git a/src/pulse/context.c b/src/pulse/context.c
index 1ed250f..a39646d 100644
--- a/src/pulse/context.c
+++ b/src/pulse/context.c
@@ -585,10 +585,7 @@ static int context_connect_spawn(pa_context *c) {
     return 0;
 
 fail:
-    if (fds[0] != -1)
-        pa_assert_se(pa_close(fds[0]) == 0);
-    if (fds[1] != -1)
-        pa_assert_se(pa_close(fds[1]) == 0);
+    pa_close_pipe(fds);
 
     unlock_autospawn_lock_file(c);
 
diff --git a/src/pulse/mainloop-signal.c b/src/pulse/mainloop-signal.c
index d2d42d9..b6414c4 100644
--- a/src/pulse/mainloop-signal.c
+++ b/src/pulse/mainloop-signal.c
@@ -147,9 +147,7 @@ void pa_signal_done(void) {
     api->io_free(io_event);
     io_event = NULL;
 
-    pa_assert_se(close(signal_pipe[0]) == 0);
-    pa_assert_se(close(signal_pipe[1]) == 0);
-    signal_pipe[0] = signal_pipe[1] = -1;
+    pa_close_pipe(signal_pipe);
 
     api = NULL;
 }
diff --git a/src/pulse/mainloop.c b/src/pulse/mainloop.c
index fc373d9..641eded 100644
--- a/src/pulse/mainloop.c
+++ b/src/pulse/mainloop.c
@@ -605,10 +605,7 @@ void pa_mainloop_free(pa_mainloop* m) {
 
     pa_xfree(m->pollfds);
 
-    if (m->wakeup_pipe[0] >= 0)
-        pa_assert_se(pa_close(m->wakeup_pipe[0]) == 0);
-    if (m->wakeup_pipe[1] >= 0)
-        pa_assert_se(pa_close(m->wakeup_pipe[1]) == 0);
+    pa_close_pipe(m->wakeup_pipe);
 
     pa_xfree(m);
 }
diff --git a/src/pulsecore/core-util.c b/src/pulsecore/core-util.c
index 62a6376..5becdef 100644
--- a/src/pulsecore/core-util.c
+++ b/src/pulsecore/core-util.c
@@ -1323,3 +1323,16 @@ void *pa_will_need(const void *p, size_t l) {
 
     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;
+}
+
diff --git a/src/pulsecore/core-util.h b/src/pulsecore/core-util.h
index fcafe63..efd19f4 100644
--- a/src/pulsecore/core-util.h
+++ b/src/pulsecore/core-util.h
@@ -120,4 +120,6 @@ static inline unsigned pa_make_power_of_two(unsigned n) {
     return n + 1;
 }
 
+void pa_close_pipe(int fds[2]);
+
 #endif
diff --git a/src/pulsecore/fdsem.c b/src/pulsecore/fdsem.c
index 710a74f..68207a7 100644
--- a/src/pulsecore/fdsem.c
+++ b/src/pulsecore/fdsem.c
@@ -67,8 +67,7 @@ pa_fdsem *pa_fdsem_new(void) {
 void pa_fdsem_free(pa_fdsem *f) {
     pa_assert(f);
 
-    pa_assert_se(pa_close(f->fds[0]) == 0);
-    pa_assert_se(pa_close(f->fds[1]) == 0);
+    pa_close_pipe(f->fds);
 
     pa_xfree(f);
 }

commit 41378658153585c82eebca83d280b25f684e90c4
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Sep 12 20:12:13 2007 +0000

    change pa_modargs_get_channel_map() to take an extra argument for specifying the name of the modargs attribute to parse
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1813 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-combine.c b/src/modules/module-combine.c
index 390b6e5..dcdc954 100644
--- a/src/modules/module-combine.c
+++ b/src/modules/module-combine.c
@@ -233,7 +233,7 @@ static void thread_func(void *userdata) {
 
     pa_rtclock_get(&u->timestamp);
 
-    /* This is only run when were are in NULL mode, to make sure that
+    /* This is only run when we are in NULL mode, to make sure that
      * playback doesn't stop. In all other cases we hook our stuff
      * into the master sink. */
     
@@ -1029,7 +1029,7 @@ int pa__init(pa_module*m) {
     else
         pa_channel_map_init_auto(&map, ss.channels, PA_CHANNEL_MAP_DEFAULT);
 
-    if ((pa_modargs_get_channel_map(ma, &map) < 0)) {
+    if ((pa_modargs_get_channel_map(ma, NULL, &map) < 0)) {
         pa_log("Invalid channel map.");
         goto fail;
     }
diff --git a/src/pulsecore/modargs.c b/src/pulsecore/modargs.c
index 41e8008..7ce3dd0 100644
--- a/src/pulsecore/modargs.c
+++ b/src/pulsecore/modargs.c
@@ -275,7 +275,7 @@ 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;
 
@@ -284,7 +284,7 @@ int pa_modargs_get_channel_map(pa_modargs *ma, pa_channel_map *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;
 
@@ -311,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)
diff --git a/src/pulsecore/modargs.h b/src/pulsecore/modargs.h
index 77262e1..aa17588 100644
--- a/src/pulsecore/modargs.h
+++ b/src/pulsecore/modargs.h
@@ -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

commit 03f311a464fcf7cb295b996a4cda48e90941bef0
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Sep 12 22:50:44 2007 +0000

    reindent, and s/assert/pa_assert/g
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1814 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/llist.h b/src/pulsecore/llist.h
index 8fc8e22..e62f15b 100644
--- a/src/pulsecore/llist.h
+++ b/src/pulsecore/llist.h
@@ -24,77 +24,86 @@
   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

commit cf3e9da9dd8c2d69ffdbfcaafa354e9e85a9f871
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Sep 12 22:54:22 2007 +0000

    add missing config.h inclusion
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1815 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/tests/hook-list-test.c b/src/tests/hook-list-test.c
index 6879eae..8628f52 100644
--- a/src/tests/hook-list-test.c
+++ b/src/tests/hook-list-test.c
@@ -1,5 +1,9 @@
 /* $Id$ */
 
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
 #include <pulsecore/hook-list.h>
 #include <pulsecore/log.h>
 

commit ef83a195251271f59feda68dba20b53d1634402f
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Sep 12 22:57:29 2007 +0000

    extend rtpoll API to allow registration of arbitray functions to be executed in the event loop. Add priority system for specifying the order of these functions.
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1816 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-alsa-sink.c b/src/modules/module-alsa-sink.c
index bb7392d..26c24c8 100644
--- a/src/modules/module-alsa-sink.c
+++ b/src/modules/module-alsa-sink.c
@@ -322,7 +322,7 @@ static int build_pollfd(struct userdata *u) {
     if (u->alsa_rtpoll_item)
         pa_rtpoll_item_free(u->alsa_rtpoll_item);
 
-    u->alsa_rtpoll_item = pa_rtpoll_item_new(u->rtpoll, n);
+    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) {
@@ -745,7 +745,7 @@ int pa__init(pa_module*m) {
     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, u->thread_mq.inq);
+    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) {
diff --git a/src/modules/module-alsa-source.c b/src/modules/module-alsa-source.c
index e4a6ed0..9e03729 100644
--- a/src/modules/module-alsa-source.c
+++ b/src/modules/module-alsa-source.c
@@ -310,7 +310,7 @@ static int build_pollfd(struct userdata *u) {
     if (u->alsa_rtpoll_item)
         pa_rtpoll_item_free(u->alsa_rtpoll_item);
 
-    u->alsa_rtpoll_item = pa_rtpoll_item_new(u->rtpoll, n);
+    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) {
@@ -726,7 +726,7 @@ int pa__init(pa_module*m) {
     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, u->thread_mq.inq);
+    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) {
diff --git a/src/modules/module-combine.c b/src/modules/module-combine.c
index dcdc954..11707b1 100644
--- a/src/modules/module-combine.c
+++ b/src/modules/module-combine.c
@@ -401,7 +401,7 @@ static void sink_input_attach_cb(pa_sink_input *i) {
     pa_assert(o);
 
     pa_assert(!o->rtpoll_item);
-    o->rtpoll_item = pa_rtpoll_item_new_asyncmsgq(i->sink->rtpoll, o->asyncmsgq);
+    o->rtpoll_item = pa_rtpoll_item_new_asyncmsgq(i->sink->rtpoll, PA_RTPOLL_NORMAL, o->asyncmsgq);
 }
 
 /* Called from I/O thread context */
@@ -721,7 +721,7 @@ static int update_master(struct userdata *u, struct output *o) {
             pa_assert(!u->rtpoll);
             
             u->rtpoll = pa_rtpoll_new();
-            pa_rtpoll_item_new_asyncmsgq(u->rtpoll, u->thread_mq.inq);
+            pa_rtpoll_item_new_asyncmsgq(u->rtpoll, PA_RTPOLL_EARLY, u->thread_mq.inq);
 
             pa_sink_set_rtpoll(u->sink, u->rtpoll);
             
diff --git a/src/modules/module-null-sink.c b/src/modules/module-null-sink.c
index 2fe541f..ba2ae6f 100644
--- a/src/modules/module-null-sink.c
+++ b/src/modules/module-null-sink.c
@@ -199,7 +199,7 @@ int pa__init(pa_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, u->thread_mq.inq);
+    pa_rtpoll_item_new_asyncmsgq(u->rtpoll, PA_RTPOLL_EARLY, u->thread_mq.inq);
     
     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.");
diff --git a/src/modules/module-oss.c b/src/modules/module-oss.c
index ffecd39..1fd8d2e 100644
--- a/src/modules/module-oss.c
+++ b/src/modules/module-oss.c
@@ -577,7 +577,7 @@ static int unsuspend(struct userdata *u) {
 
     pa_assert(!u->rtpoll_item);
     
-    u->rtpoll_item = pa_rtpoll_item_new(u->rtpoll, 1);
+    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;
@@ -1167,8 +1167,8 @@ int pa__init(pa_module*m) {
     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, u->thread_mq.inq);
-    u->rtpoll_item = pa_rtpoll_item_new(u->rtpoll, 1);
+    pa_rtpoll_item_new_asyncmsgq(u->rtpoll, PA_RTPOLL_EARLY, u->thread_mq.inq);
+    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;
diff --git a/src/modules/module-pipe-sink.c b/src/modules/module-pipe-sink.c
index 6145426..9594a68 100644
--- a/src/modules/module-pipe-sink.c
+++ b/src/modules/module-pipe-sink.c
@@ -236,7 +236,7 @@ int pa__init(pa_module*m) {
     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, u->thread_mq.inq);
+    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));
 
@@ -274,7 +274,7 @@ int pa__init(pa_module*m) {
     pa_sink_set_description(u->sink, t = pa_sprintf_malloc("Unix FIFO sink '%s'", u->filename));
     pa_xfree(t);
 
-    u->rtpoll_item = pa_rtpoll_item_new(u->rtpoll, 1);
+    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;
diff --git a/src/modules/module-pipe-source.c b/src/modules/module-pipe-source.c
index 68c89a0..1b42fcf 100644
--- a/src/modules/module-pipe-source.c
+++ b/src/modules/module-pipe-source.c
@@ -215,7 +215,7 @@ int pa__init(pa_module*m) {
     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, u->thread_mq.inq);
+    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));
     
@@ -252,7 +252,7 @@ int pa__init(pa_module*m) {
     pa_source_set_description(u->source, t = pa_sprintf_malloc("Unix FIFO source '%s'", u->filename));
     pa_xfree(t);
 
-    u->rtpoll_item = pa_rtpoll_item_new(u->rtpoll, 1);
+    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;
diff --git a/src/pulsecore/rtpoll.c b/src/pulsecore/rtpoll.c
index be1c83c..659e538 100644
--- a/src/pulsecore/rtpoll.c
+++ b/src/pulsecore/rtpoll.c
@@ -45,7 +45,6 @@
 #include "rtpoll.h"
 
 struct pa_rtpoll {
-
     struct pollfd *pollfd, *pollfd2;
     unsigned n_pollfd_alloc, n_pollfd_used;
 
@@ -72,6 +71,8 @@ struct pa_rtpoll_item {
     pa_rtpoll *rtpoll;
     int dead;
 
+    pa_rtpoll_priority_t priority;
+
     struct pollfd *pollfd;
     unsigned n_pollfd;
 
@@ -245,7 +246,7 @@ void pa_rtpoll_free(pa_rtpoll *p) {
 
     while (p->items)
         rtpoll_item_destroy(p->items);
-    
+
     pa_xfree(p->pollfd);
     pa_xfree(p->pollfd2);
 
@@ -257,11 +258,37 @@ void pa_rtpoll_free(pa_rtpoll *p) {
     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, int wait) {
     pa_rtpoll_item *i;
     int r = 0;
-    int no_events = 0;
-    int saved_errno;
+    int saved_errno = 0;
     struct timespec timeout;
     
     pa_assert(p);
@@ -270,20 +297,23 @@ int pa_rtpoll_run(pa_rtpoll *p, int wait) {
     
     p->running = 1;
 
-    for (i = p->items; i; i = i->next) {
-
+    for (i = p->items; i && i->priority < PA_RTPOLL_NEVER; i = i->next) {
+        int k;
+        
         if (i->dead)
             continue;
         
         if (!i->before_cb)
             continue;
 
-        if (i->before_cb(i) < 0) {
+        if ((k = i->before_cb(i)) != 0) {
 
             /* Hmm, this one doesn't let us enter the poll, so rewind everything */
 
+            reset_all_revents(p);
+            
             for (i = i->prev; i; i = i->prev) {
-
+                
                 if (i->dead)
                     continue;
                 
@@ -292,6 +322,9 @@ int pa_rtpoll_run(pa_rtpoll *p, int wait) {
 
                 i->after_cb(i);
             }
+
+            if (k < 0)
+                r = k;
             
             goto finish;
         }
@@ -329,7 +362,13 @@ int pa_rtpoll_run(pa_rtpoll *p, int wait) {
         r = poll(p->pollfd, p->n_pollfd_used, p->timer_enabled > 0 ? (timeout.tv_sec*1000) + (timeout.tv_nsec / 1000000) : -1);
 #endif
 
-    saved_errno = errno;
+    if (r < 0)
+        reset_all_revents(p);
+    
+    if (r < 0 && (errno == EAGAIN || errno == EINTR))
+        r = 0;
+
+    saved_errno = r < 0 ? errno : 0;
 
     if (p->timer_enabled) {
         if (p->period > 0) {
@@ -340,18 +379,13 @@ int pa_rtpoll_run(pa_rtpoll *p, int wait) {
 
             /* Guarantee that the next timeout will happen in the future */
             if (pa_timespec_cmp(&p->next_elapse, &now) < 0)
-                pa_timespec_add(&p->next_elapse, (pa_timespec_diff(&now, &p->next_elapse) / p->period + 1)  * p->period);
+                pa_timespec_add(&p->next_elapse, (pa_timespec_diff(&now, &p->next_elapse) / p->period + 1) * p->period);
 
         } else
             p->timer_enabled = 0;
     }
-    
-    if (r == 0 || (r < 0 && (errno == EAGAIN || errno == EINTR))) {
-        r = 0;
-        no_events = 1;
-    }
 
-    for (i = p->items; i; i = i->next) {
+    for (i = p->items; i && i->priority < PA_RTPOLL_NEVER; i = i->next) {
 
         if (i->dead)
             continue;
@@ -359,13 +393,6 @@ int pa_rtpoll_run(pa_rtpoll *p, int wait) {
         if (!i->after_cb)
             continue;
 
-        if (no_events) {
-            unsigned j;
-
-            for (j = 0; j < i->n_pollfd; j++)
-                i->pollfd[j].revents = 0;
-        }
-        
         i->after_cb(i);
     }
 
@@ -386,7 +413,7 @@ finish:
         }
     }
 
-    if (r < 0)
+    if (saved_errno != 0)
         errno = saved_errno;
 
     return r;
@@ -484,11 +511,10 @@ void pa_rtpoll_set_timer_disabled(pa_rtpoll *p) {
     update_timer(p);
 }
 
-pa_rtpoll_item *pa_rtpoll_item_new(pa_rtpoll *p, unsigned n_fds) {
-    pa_rtpoll_item *i;
+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);
-    pa_assert(n_fds > 0);
 
     if (!(i = pa_flist_pop(PA_STATIC_FLIST_GET(items))))
         i = pa_xnew(pa_rtpoll_item, 1);
@@ -497,15 +523,25 @@ pa_rtpoll_item *pa_rtpoll_item_new(pa_rtpoll *p, unsigned n_fds) {
     i->dead = 0;
     i->n_pollfd = n_fds;
     i->pollfd = NULL;
+    i->priority = prio;
 
     i->userdata = NULL;
     i->before_cb = NULL;
     i->after_cb = NULL;
-    
-    PA_LLIST_PREPEND(pa_rtpoll_item, p->items, i);
 
-    p->rebuild_needed = 1;
-    p->n_pollfd_used += n_fds;
+    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;
 }
@@ -525,8 +561,9 @@ void pa_rtpoll_item_free(pa_rtpoll_item *i) {
 struct pollfd *pa_rtpoll_item_get_pollfd(pa_rtpoll_item *i, unsigned *n_fds) {
     pa_assert(i);
 
-    if (i->rtpoll->rebuild_needed)
-        rtpoll_rebuild(i->rtpoll);
+    if (i->n_pollfd > 0) 
+        if (i->rtpoll->rebuild_needed)
+            rtpoll_rebuild(i->rtpoll);
     
     if (n_fds)
         *n_fds = i->n_pollfd;
@@ -536,12 +573,14 @@ struct pollfd *pa_rtpoll_item_get_pollfd(pa_rtpoll_item *i, unsigned *n_fds) {
 
 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;
 }
@@ -559,22 +598,28 @@ void* pa_rtpoll_item_get_userdata(pa_rtpoll_item *i) {
 }
 
 static int fdsem_before(pa_rtpoll_item *i) {
-    return pa_fdsem_before_poll(i->userdata);
+
+    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_fdsem *f) {
+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, 1);
+    i = pa_rtpoll_item_new(p, prio, 1);
 
     pollfd = pa_rtpoll_item_get_pollfd(i, NULL);
 
@@ -589,22 +634,29 @@ pa_rtpoll_item *pa_rtpoll_item_new_fdsem(pa_rtpoll *p, pa_fdsem *f) {
 }
 
 static int asyncmsgq_before(pa_rtpoll_item *i) {
-    return pa_asyncmsgq_before_poll(i->userdata);
+    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);
 }
 
-pa_rtpoll_item *pa_rtpoll_item_new_asyncmsgq(pa_rtpoll *p, pa_asyncmsgq *q) {
+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, 1);
+    i = pa_rtpoll_item_new(p, prio, 1);
 
     pollfd = pa_rtpoll_item_get_pollfd(i, NULL);
     pollfd->fd = pa_asyncmsgq_get_fd(q);
diff --git a/src/pulsecore/rtpoll.h b/src/pulsecore/rtpoll.h
index f393f91..bef9eed 100644
--- a/src/pulsecore/rtpoll.h
+++ b/src/pulsecore/rtpoll.h
@@ -26,6 +26,7 @@
 
 #include <poll.h>
 #include <sys/types.h>
+#include <limits.h>
 
 #include <pulse/sample.h>
 #include <pulsecore/asyncmsgq.h>
@@ -53,9 +54,17 @@
 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
@@ -68,7 +77,8 @@ 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);
 
-pa_rtpoll_item *pa_rtpoll_item_new(pa_rtpoll *p, unsigned n_fds);
+/* 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
@@ -76,12 +86,18 @@ void pa_rtpoll_item_free(pa_rtpoll_item *i);
  * 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 immediately before entering
+ * the sleeping poll: If the callback returns a negative value, the
+ * poll is skipped. */
 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_fdsem *s);
-pa_rtpoll_item *pa_rtpoll_item_new_asyncmsgq(pa_rtpoll *p, pa_asyncmsgq *q);
+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);
 
 #endif
diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c
index aac4a2f..b009bc7 100644
--- a/src/pulsecore/sink.c
+++ b/src/pulsecore/sink.c
@@ -126,7 +126,7 @@ pa_sink* pa_sink_new(
     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;
diff --git a/src/tests/rtpoll-test.c b/src/tests/rtpoll-test.c
index 20913e7..bad8e7d 100644
--- a/src/tests/rtpoll-test.c
+++ b/src/tests/rtpoll-test.c
@@ -38,16 +38,21 @@ 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;
+    pa_rtpoll_item *i, *w;
     struct pollfd *pollfd;
 
     pa_rtsig_configure(SIGRTMIN+10, SIGRTMAX);
     
     p = pa_rtpoll_new();
 
-    i = pa_rtpoll_item_new(p, 1);
+    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);
 
@@ -55,6 +60,9 @@ int main(int argc, char *argv[]) {
     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 */
 
@@ -62,7 +70,7 @@ int main(int argc, char *argv[]) {
     
     pa_rtpoll_item_free(i);
     
-    i = pa_rtpoll_item_new(p, 1);
+    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);
 
@@ -73,6 +81,8 @@ int main(int argc, char *argv[]) {
     pa_rtpoll_run(p, 1);
 
     pa_rtpoll_item_free(i);
+
+    pa_rtpoll_item_free(w);
     
     pa_rtpoll_free(p);
 

commit 9be0d70ea7fa2cc63e4995b57706a41714033cb9
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Sep 14 17:12:25 2007 +0000

    make newer gcc shut up
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1817 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/object.c b/src/pulsecore/object.c
index 23a4575..6680d07 100644
--- a/src/pulsecore/object.c
+++ b/src/pulsecore/object.c
@@ -68,5 +68,5 @@ void pa_object_unref(pa_object *o) {
 int pa_object_check_type(const char *type_name) {
     pa_assert(type_name);
     
-    return type_name == "pa_object" || strcmp(type_name, "pa_object") == 0;
+    return strcmp(type_name, "pa_object") == 0;
 }
diff --git a/src/pulsecore/object.h b/src/pulsecore/object.h
index 9c62f74..562fd11 100644
--- a/src/pulsecore/object.h
+++ b/src/pulsecore/object.h
@@ -96,8 +96,7 @@ static inline pa_object* pa_object_cast(void *o) {
 #define PA_DEFINE_CHECK_TYPE(c, parent)                                 \
     int c##_check_type(const char *type) {                              \
         pa_assert(type);                                                \
-        if (type == #c ||                                               \
-            strcmp(type, #c) == 0)                                      \
+        if (strcmp(type, #c) == 0)                                      \
             return 1;                                                   \
         return parent##_check_type(type);                               \
     }                                                                   \

commit 87753092340fc099dee86f94633da97104fbf5dc
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Sep 14 21:01:00 2007 +0000

    fix two typos in reference count handling
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1818 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/socket-client.c b/src/pulsecore/socket-client.c
index 0922a94..360a0b4 100644
--- a/src/pulsecore/socket-client.c
+++ b/src/pulsecore/socket-client.c
@@ -349,7 +349,7 @@ void pa_socket_client_unref(pa_socket_client *c) {
     pa_assert(c);
     pa_assert(PA_REFCNT_VALUE(c) >= 1);
 
-    if (PA_REFCNT_DEC(c) < 0)
+    if (PA_REFCNT_DEC(c) <= 0)
         socket_client_free(c);
 }
 
diff --git a/src/pulsecore/socket-server.c b/src/pulsecore/socket-server.c
index 21c5115..502005d 100644
--- a/src/pulsecore/socket-server.c
+++ b/src/pulsecore/socket-server.c
@@ -422,7 +422,7 @@ void pa_socket_server_unref(pa_socket_server *s) {
     pa_assert(s);
     pa_assert(PA_REFCNT_VALUE(s) >= 1);
 
-    if (PA_REFCNT_DEC(s))
+    if (PA_REFCNT_DEC(s) <= 0)
         socket_server_free(s);
 }
 

commit 04ed0f9536f8b211d68d7df381f0fb4dd04dc0ff
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Sep 14 21:02:18 2007 +0000

    call dbus_shutdown() before exiting, to make valgrind output more useful
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1819 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/configure.ac b/configure.ac
index 7c8f388..cb68f57 100644
--- a/configure.ac
+++ b/configure.ac
@@ -769,7 +769,7 @@ if test "x${dbus}" != xno ; then
             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
diff --git a/src/Makefile.am b/src/Makefile.am
index 52fa4b8..a04a91a 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -135,10 +135,9 @@ pulseaudio_SOURCES = \
 		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)
 
diff --git a/src/daemon/main.c b/src/daemon/main.c
index 93d4eb6..e01bb23 100644
--- a/src/daemon/main.c
+++ b/src/daemon/main.c
@@ -58,6 +58,10 @@
 #include <tcpd.h>
 #endif
 
+#ifdef HAVE_DBUS
+#include <dbus/dbus.h>
+#endif
+
 #include <pulse/mainloop.h>
 #include <pulse/mainloop-signal.h>
 #include <pulse/timeval.h>
@@ -745,5 +749,9 @@ finish:
 
     libtool_done();
 
+#ifdef HAVE_DBUS
+    dbus_shutdown();
+#endif
+    
     return retval;
 }
diff --git a/src/modules/dbus-util.c b/src/modules/dbus-util.c
index 9078ec7..ccc658b 100644
--- a/src/modules/dbus-util.c
+++ b/src/modules/dbus-util.c
@@ -26,10 +26,10 @@
 #include <config.h>
 #endif
 
-#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"
 

commit bf274cb617d92e55d18fa7e2f6b1cf139b96a413
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Sep 14 21:04:08 2007 +0000

    add two new macros PA_ONCE_BEGIN and PA_ONCE_END which allow usage of pa_once without declaring a function to be called
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1820 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/once-posix.c b/src/pulsecore/once-posix.c
index fd6288f..fba0ddf 100644
--- a/src/pulsecore/once-posix.c
+++ b/src/pulsecore/once-posix.c
@@ -32,18 +32,20 @@
 
 #include "once.h"
 
-/* Not reentrant -- how could it be? */
-void pa_run_once(pa_once *control, pa_once_func_t func) {
+int pa_once_begin(pa_once *control) {
     pa_mutex *m;
 
     pa_assert(control);
-    pa_assert(func);
 
     if (pa_atomic_load(&control->done))
-        return;
+        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))) {
@@ -51,33 +53,46 @@ void pa_run_once(pa_once *control, pa_once_func_t func) {
             /* The mutex is stored in locked state, hence let's just
              * wait until it is unlocked */
             pa_mutex_lock(m);
-            pa_mutex_unlock(m);
-            break;
+
+            pa_once_end(control);
+            return 0;
         }
 
         pa_assert_se(m = pa_mutex_new(0));
         pa_mutex_lock(m);
 
-        if (pa_atomic_ptr_cmpxchg(&control->mutex, NULL, m)) {
-            func();
-            pa_atomic_store(&control->done, 1);
-            pa_mutex_unlock(m);
-
-            break;
-        }
+        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_assert(pa_atomic_load(&control->done));
+    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(pa_atomic_ptr_cmpxchg(&control->mutex, m, NULL));
+        pa_assert_se(pa_atomic_ptr_cmpxchg(&control->mutex, m, NULL));
         pa_mutex_free(m);
     }
+}
 
-    /* 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. */
+/* 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);
+    }
 }
+
diff --git a/src/pulsecore/once.h b/src/pulsecore/once.h
index d9372d8..a4a0b23 100644
--- a/src/pulsecore/once.h
+++ b/src/pulsecore/once.h
@@ -39,8 +39,38 @@ typedef struct pa_once {
         .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() {
+ 
+      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

commit f0b9dce32e4c5d77f57364ccdc7795f828f7f6a0
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Sep 14 21:05:47 2007 +0000

    explicitly destory TLS data before destroying TLS
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1821 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/thread.h b/src/pulsecore/thread.h
index 4a2b1bb..0c6c859 100644
--- a/src/pulsecore/thread.h
+++ b/src/pulsecore/thread.h
@@ -70,8 +70,14 @@ void *pa_tls_set(pa_tls *t, void *userdata);
     }                                                                   \
     static void name##_tls_destructor(void) PA_GCC_DESTRUCTOR;          \
     static void name##_tls_destructor(void) {                           \
-        if (name##_tls.tls)                                             \
-            pa_tls_free(name##_tls.tls);                                \
+        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());                            \

commit 3396b65f15a06ff312e318bc05e502ba402c564e
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Sep 14 21:51:05 2007 +0000

    simplify rt loops a bit by moving more code into pa_rtpoll. It is now possible to attach "work" functions to a pa_rtpoll_item, which will be called in each loop iteration. This allows us to hide the message processing in the RT loops and to drop the seperate sink_input->process hooks. Basically, only the driver-specific code remains in the RT loops.
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1822 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-alsa-sink.c b/src/modules/module-alsa-sink.c
index 26c24c8..1bcb30c 100644
--- a/src/modules/module-alsa-sink.c
+++ b/src/modules/module-alsa-sink.c
@@ -630,24 +630,13 @@ static void thread_func(void *userdata) {
             }
         }
 
-        /* Now give the sink inputs some to time to process their data */
-        if ((ret = pa_sink_process_inputs(u->sink)) < 0)
+        /* Hmm, nothing to do. Let's sleep */
+        if ((ret = pa_rtpoll_run(u->rtpoll, 1)) < 0)
             goto fail;
-        if (ret > 0)
-            continue;
 
-        /* Check whether there is a message for us to process */
-        if ((ret = pa_thread_mq_process(&u->thread_mq) < 0))
+        if (ret == 0)
             goto finish;
-        if (ret > 0)
-            continue;
         
-        /* Hmm, nothing to do. Let's sleep */
-        if (pa_rtpoll_run(u->rtpoll, 1) < 0) {
-            pa_log("poll() failed: %s", pa_cstrerror(errno));
-            goto fail;
-        }
-
         /* Tell ALSA about this and process its response */
         if (PA_SINK_OPENED(u->sink->thread_info.state)) {
             struct pollfd *pollfd;
@@ -676,8 +665,8 @@ static void thread_func(void *userdata) {
     }
 
 fail:
-    /* We have to continue processing messages until we receive the
-     * SHUTDOWN message */
+    /* 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);
 
diff --git a/src/modules/module-alsa-source.c b/src/modules/module-alsa-source.c
index 9e03729..870f204 100644
--- a/src/modules/module-alsa-source.c
+++ b/src/modules/module-alsa-source.c
@@ -612,24 +612,13 @@ static void thread_func(void *userdata) {
             }
         }
 
-        /* Now give the source outputs some to time to process their data */
-        if ((ret = pa_source_process_outputs(u->source)) < 0)
-            goto fail;
-        if (ret > 0)
-            continue;
-        
-        /* Check whether there is a message for us to process */
-        if ((ret = pa_thread_mq_process(&u->thread_mq) < 0))
-            goto finish;
-        if (ret > 0)
-            continue;
-
         /* Hmm, nothing to do. Let's sleep */
-        if (pa_rtpoll_run(u->rtpoll, 1) < 0) {
-            pa_log("poll() failed: %s", pa_cstrerror(errno));
+        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;
@@ -658,8 +647,8 @@ static void thread_func(void *userdata) {
     }
 
 fail:
-    /* We have to continue processing messages until we receive the
-     * SHUTDOWN message */
+    /* 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);
 
diff --git a/src/modules/module-combine.c b/src/modules/module-combine.c
index 11707b1..7df04ec 100644
--- a/src/modules/module-combine.c
+++ b/src/modules/module-combine.c
@@ -139,6 +139,10 @@ enum {
     SINK_MESSAGE_REMOVE_OUTPUT
 };
 
+enum {
+    SINK_INPUT_MESSAGE_POST = PA_SINK_INPUT_MESSAGE_MAX
+};
+
 static void output_free(struct output *o);
 static int output_create_sink_input(struct userdata *u, struct output *o);
 static int update_master(struct userdata *u, struct output *o);
@@ -255,28 +259,17 @@ static void thread_func(void *userdata) {
         } else
             pa_rtpoll_set_timer_disabled(u->rtpoll);
 
-        /* Now give the sink inputs some to time to process their data */
-        if ((ret = pa_sink_process_inputs(u->sink)) < 0)
+        /* Hmm, nothing to do. Let's sleep */
+        if ((ret = pa_rtpoll_run(u->rtpoll, 1)) < 0)
             goto fail;
-        if (ret > 0)
-            continue;
 
-        /* Check whether there is a message for us to process */
-        if ((ret = pa_thread_mq_process(&u->thread_mq) < 0))
+        if (ret == 0)
             goto finish;
-        if (ret > 0)
-            continue;
-
-        /* Hmm, nothing to do. Let's sleep */
-        if (pa_rtpoll_run(u->rtpoll, 1) < 0) {
-            pa_log("poll() failed: %s", pa_cstrerror(errno));
-            goto fail;
-        }
     }
 
 fail:
-    /* We have to continue processing messages until we receive the
-     * SHUTDOWN message */
+    /* 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);
 
@@ -294,10 +287,8 @@ static void request_memblock(struct output *o) {
     /* If another thread already prepared some data we received
      * the data over the asyncmsgq, hence let's first process
      * it. */
-    while (pa_asyncmsgq_get(o->asyncmsgq, NULL, NULL, NULL, NULL, &chunk, 0) == 0) {
-        pa_memblockq_push_align(o->memblockq, &chunk);
-        pa_asyncmsgq_done(o->asyncmsgq, 0);
-    }
+    while (pa_asyncmsgq_process_one(o->asyncmsgq) > 0)
+        ;
     
     /* Check whether we're now readable */
     if (pa_memblockq_is_readable(o->memblockq))
@@ -309,10 +300,8 @@ static void request_memblock(struct output *o) {
     if (PA_SINK_OPENED(o->userdata->sink->thread_info.state)) {
     
         /* Maybe there's some data now? */
-        while (pa_asyncmsgq_get(o->asyncmsgq, NULL, NULL, NULL, NULL, &chunk, 0) == 0) {
-            pa_memblockq_push_align(o->memblockq, &chunk);
-            pa_asyncmsgq_done(o->asyncmsgq, 0);
-        }
+        while (pa_asyncmsgq_process_one(o->asyncmsgq) > 0)
+            ;
         
         /* Ok, now let's prepare some data if we really have to */
         while (!pa_memblockq_is_readable(o->memblockq)) {
@@ -324,7 +313,7 @@ static void request_memblock(struct output *o) {
             /* OK, let's send this data to the other threads */
             for (j = o->userdata->thread_info.outputs; j; j = j->next)
                 if (j != o && j->sink_input)
-                    pa_asyncmsgq_post(j->asyncmsgq, NULL, 0, NULL, 0, &chunk, NULL);
+                    pa_asyncmsgq_post(j->asyncmsgq, PA_MSGOBJECT(j->sink_input), SINK_INPUT_MESSAGE_POST, NULL, 0, &chunk, NULL);
             
             /* And push it into our own queue */
             pa_memblockq_push_align(o->memblockq, &chunk);
@@ -362,37 +351,6 @@ static void sink_input_drop_cb(pa_sink_input *i, size_t length) {
 }
 
 /* Called from I/O thread context */
-static int sink_input_process_cb(pa_sink_input *i) {
-    struct output *o;
-    pa_memchunk chunk;
-    int r = 0;
-    
-    pa_sink_input_assert_ref(i);
-    o = i->userdata;
-    pa_assert(o);
-
-    /* Move all data in the asyncmsgq into our memblockq */
-    
-    while (pa_asyncmsgq_get(o->asyncmsgq, NULL, NULL, NULL, NULL, &chunk, 0) == 0) {
-        if (PA_SINK_OPENED(i->sink->thread_info.state))
-            pa_memblockq_push_align(o->memblockq, &chunk);
-        pa_asyncmsgq_done(o->asyncmsgq, 0);
-    }
-
-    /* If the sink is suspended, flush our queue */
-    if (!PA_SINK_OPENED(i->sink->thread_info.state))
-        pa_memblockq_flush(o->memblockq);
-
-    if (o == o->userdata->thread_info.master) {
-        pa_mutex_lock(o->userdata->mutex);
-        r = pa_sink_process_inputs(o->userdata->sink);
-        pa_mutex_unlock(o->userdata->mutex);
-    }
-    
-    return r;
-}
-
-/* Called from I/O thread context */
 static void sink_input_attach_cb(pa_sink_input *i) {
     struct output *o;
 
@@ -401,7 +359,10 @@ static void sink_input_attach_cb(pa_sink_input *i) {
     pa_assert(o);
 
     pa_assert(!o->rtpoll_item);
-    o->rtpoll_item = pa_rtpoll_item_new_asyncmsgq(i->sink->rtpoll, PA_RTPOLL_NORMAL, o->asyncmsgq);
+    o->rtpoll_item = pa_rtpoll_item_new_asyncmsgq(
+            i->sink->rtpoll,
+            PA_RTPOLL_NORMAL,  /* This one has a lower priority than the normal message handling */
+            o->asyncmsgq);
 }
 
 /* Called from I/O thread context */
@@ -448,6 +409,15 @@ static int sink_input_process_msg(pa_msgobject *obj, int code, void *data, int64
             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);
@@ -784,7 +754,6 @@ static int output_create_sink_input(struct userdata *u, struct output *o) {
     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->process = sink_input_process_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;
diff --git a/src/modules/module-null-sink.c b/src/modules/module-null-sink.c
index ba2ae6f..04df239 100644
--- a/src/modules/module-null-sink.c
+++ b/src/modules/module-null-sink.c
@@ -145,28 +145,17 @@ static void thread_func(void *userdata) {
         } else
             pa_rtpoll_set_timer_disabled(u->rtpoll);
 
-        /* Now give the sink inputs some to time to process their data */
-        if ((ret = pa_sink_process_inputs(u->sink)) < 0)
-            goto fail;
-        if (ret > 0)
-            continue;
-
-        /* Check whether there is a message for us to process */
-        if ((ret = pa_thread_mq_process(&u->thread_mq) < 0))
-            goto finish;
-        if (ret > 0)
-            continue;
-
         /* Hmm, nothing to do. Let's sleep */
-        if (pa_rtpoll_run(u->rtpoll, 1) < 0) {
-            pa_log("poll() failed: %s", pa_cstrerror(errno));
+        if ((ret = pa_rtpoll_run(u->rtpoll, 1)) < 0)
             goto fail;
-        }
+        
+        if (ret == 0)
+            goto finish;
     }
 
 fail:
-    /* We have to continue processing messages until we receive the
-     * SHUTDOWN message */
+    /* 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);
 
diff --git a/src/modules/module-oss.c b/src/modules/module-oss.c
index 1fd8d2e..037c401 100644
--- a/src/modules/module-oss.c
+++ b/src/modules/module-oss.c
@@ -999,28 +999,6 @@ static void thread_func(void *userdata) {
 
 /*         pa_log("loop2"); */
 
-        /* Now give the sink inputs some to time to process their data */
-        if (u->sink) {
-            if ((ret = pa_sink_process_inputs(u->sink)) < 0)
-                goto fail;
-            if (ret > 0)
-                continue;
-        }
-
-        /* Now give the source outputs some to time to process their data */
-        if (u->source) {
-            if ((ret = pa_source_process_outputs(u->source)) < 0)
-                goto fail;
-            if (ret > 0)
-                continue;
-        }
-        
-        /* Check whether there is a message for us to process */
-        if ((ret = pa_thread_mq_process(&u->thread_mq) < 0))
-            goto finish;
-        if (ret > 0)
-            continue;
-
         if (u->fd >= 0) {
             struct pollfd *pollfd;
 
@@ -1031,11 +1009,12 @@ static void thread_func(void *userdata) {
         }
         
         /* Hmm, nothing to do. Let's sleep */
-        if (pa_rtpoll_run(u->rtpoll, 1) < 0) {
-            pa_log("poll() failed: %s", pa_cstrerror(errno));
+        if ((ret = pa_rtpoll_run(u->rtpoll, 1)) < 0)
             goto fail;
-        }
 
+        if (ret == 0)
+            goto finish;
+        
         if (u->fd >= 0) {
             struct pollfd *pollfd;
             
@@ -1052,8 +1031,8 @@ static void thread_func(void *userdata) {
     }
 
 fail:
-    /* We have to continue processing messages until we receive the
-     * SHUTDOWN message */
+    /* 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);
 
diff --git a/src/modules/module-pipe-sink.c b/src/modules/module-pipe-sink.c
index 9594a68..a1bdc8f 100644
--- a/src/modules/module-pipe-sink.c
+++ b/src/modules/module-pipe-sink.c
@@ -126,8 +126,8 @@ static void thread_func(void *userdata) {
     pa_rtpoll_install(u->rtpoll);
 
     for (;;) {
-        int ret;
         struct pollfd *pollfd;
+        int ret;
 
         pollfd = pa_rtpoll_item_get_pollfd(u->rtpoll_item, NULL);
 
@@ -170,36 +170,26 @@ static void thread_func(void *userdata) {
             }
         }
 
-        /* Now give the sink inputs some to time to process their data */
-        if ((ret = pa_sink_process_inputs(u->sink)) < 0)
-            goto fail;
-        if (ret > 0)
-            continue;
-
-        /* Check whether there is a message for us to process */
-        if ((ret = pa_thread_mq_process(&u->thread_mq) < 0))
-            goto finish;
-        if (ret > 0)
-            continue;
-        
         /* Hmm, nothing to do. Let's sleep */
         pollfd->events = u->sink->thread_info.state == PA_SINK_RUNNING ? POLLOUT : 0;
 
-        if (pa_rtpoll_run(u->rtpoll, 1) < 0) {
-            pa_log("poll() failed: %s", pa_cstrerror(errno));
+        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 & ~POLLOUT) {
             pa_log("FIFO shutdown.");
             goto fail;
         }
-    }
+    } 
 
 fail:
-    /* We have to continue processing messages until we receive the
-     * SHUTDOWN message */
+    /* 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);
 
diff --git a/src/modules/module-pipe-source.c b/src/modules/module-pipe-source.c
index 1b42fcf..382da8f 100644
--- a/src/modules/module-pipe-source.c
+++ b/src/modules/module-pipe-source.c
@@ -149,26 +149,15 @@ static void thread_func(void *userdata) {
             }
         }
 
-        /* Now give the source outputs some to time to process their data */
-        if ((ret = pa_source_process_outputs(u->source)) < 0)
-            goto fail;
-        if (ret > 0)
-            continue;
-
-        /* Check whether there is a message for us to process */
-        if ((ret = pa_thread_mq_process(&u->thread_mq) < 0))
-            goto finish;
-        if (ret > 0)
-            continue;
-
         /* Hmm, nothing to do. Let's sleep */
         pollfd->events = u->source->thread_info.state == PA_SOURCE_RUNNING ? POLLIN : 0;
 
-        if (pa_rtpoll_run(u->rtpoll, 1) < 0) {
-            pa_log("poll() failed: %s", pa_cstrerror(errno));
+        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.");
@@ -177,8 +166,8 @@ static void thread_func(void *userdata) {
     }
 
 fail:
-    /* We have to continue processing messages until we receive the
-     * SHUTDOWN message */
+    /* 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);
 
diff --git a/src/pulsecore/asyncmsgq.c b/src/pulsecore/asyncmsgq.c
index e3a1ba9..b365446 100644
--- a/src/pulsecore/asyncmsgq.c
+++ b/src/pulsecore/asyncmsgq.c
@@ -248,6 +248,27 @@ int pa_asyncmsgq_wait_for(pa_asyncmsgq *a, int code) {
     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);
 
diff --git a/src/pulsecore/asyncmsgq.h b/src/pulsecore/asyncmsgq.h
index 55812c6..393bb0b 100644
--- a/src/pulsecore/asyncmsgq.h
+++ b/src/pulsecore/asyncmsgq.h
@@ -65,6 +65,7 @@ int pa_asyncmsgq_get(pa_asyncmsgq *q, pa_msgobject **object, int *code, void **u
 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);
diff --git a/src/pulsecore/rtpoll.c b/src/pulsecore/rtpoll.c
index 659e538..0de8d0c 100644
--- a/src/pulsecore/rtpoll.c
+++ b/src/pulsecore/rtpoll.c
@@ -53,7 +53,7 @@ struct pa_rtpoll {
     pa_usec_t period;
 
     int scan_for_dead;
-    int running, installed, rebuild_needed;
+    int running, installed, rebuild_needed, quit;
 
 #ifdef HAVE_PPOLL
     int rtsig;
@@ -76,6 +76,7 @@ struct pa_rtpoll_item {
     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;
@@ -134,6 +135,7 @@ pa_rtpoll *pa_rtpoll_new(void) {
     p->installed = 0;
     p->scan_for_dead = 0;
     p->rebuild_needed = 0;
+    p->quit = 0;
     
     PA_LLIST_HEAD_INIT(pa_rtpoll_item, p->items);
 
@@ -288,7 +290,6 @@ static void reset_all_revents(pa_rtpoll *p) {
 int pa_rtpoll_run(pa_rtpoll *p, int wait) {
     pa_rtpoll_item *i;
     int r = 0;
-    int saved_errno = 0;
     struct timespec timeout;
     
     pa_assert(p);
@@ -297,6 +298,7 @@ int pa_rtpoll_run(pa_rtpoll *p, int wait) {
     
     p->running = 1;
 
+    /* First, let's do some work */
     for (i = p->items; i && i->priority < PA_RTPOLL_NEVER; i = i->next) {
         int k;
         
@@ -306,12 +308,31 @@ int pa_rtpoll_run(pa_rtpoll *p, int wait) {
         if (!i->before_cb)
             continue;
 
-        if ((k = i->before_cb(i)) != 0) {
+        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 */
 
-            reset_all_revents(p);
-            
             for (i = i->prev; i; i = i->prev) {
                 
                 if (i->dead)
@@ -334,7 +355,7 @@ int pa_rtpoll_run(pa_rtpoll *p, int wait) {
         rtpoll_rebuild(p);
 
     /* Calculate timeout */
-    if (!wait) {
+    if (!wait || p->quit) {
         timeout.tv_sec = 0;
         timeout.tv_nsec = 0;
     } else if (p->timer_enabled) {
@@ -362,13 +383,14 @@ int pa_rtpoll_run(pa_rtpoll *p, int wait) {
         r = poll(p->pollfd, p->n_pollfd_used, p->timer_enabled > 0 ? (timeout.tv_sec*1000) + (timeout.tv_nsec / 1000000) : -1);
 #endif
 
-    if (r < 0)
+    if (r < 0) {
         reset_all_revents(p);
     
-    if (r < 0 && (errno == EAGAIN || errno == EINTR))
-        r = 0;
-
-    saved_errno = r < 0 ? errno : 0;
+        if (errno == EAGAIN || errno == EINTR)
+            r = 0;
+        else
+            pa_log_error("poll(): %s", pa_cstrerror(errno));
+    }
 
     if (p->timer_enabled) {
         if (p->period > 0) {
@@ -385,6 +407,7 @@ int pa_rtpoll_run(pa_rtpoll *p, int wait) {
             p->timer_enabled = 0;
     }
 
+    /* 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)
@@ -413,10 +436,7 @@ finish:
         }
     }
 
-    if (saved_errno != 0)
-        errno = saved_errno;
-
-    return r;
+    return r < 0 ? r : !p->quit;
 }
 
 static void update_timer(pa_rtpoll *p) {
@@ -528,6 +548,7 @@ pa_rtpoll_item *pa_rtpoll_item_new(pa_rtpoll *p, pa_rtpoll_priority_t prio, unsi
     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)
@@ -585,6 +606,13 @@ void pa_rtpoll_item_set_after_callback(pa_rtpoll_item *i, void (*after_cb)(pa_rt
     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);
 
@@ -649,6 +677,32 @@ static void asyncmsgq_after(pa_rtpoll_item *i) {
     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;
@@ -664,7 +718,14 @@ pa_rtpoll_item *pa_rtpoll_item_new_asyncmsgq(pa_rtpoll *p, pa_rtpoll_priority_t
     
     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 = 1;
+}
diff --git a/src/pulsecore/rtpoll.h b/src/pulsecore/rtpoll.h
index bef9eed..9a368d3 100644
--- a/src/pulsecore/rtpoll.h
+++ b/src/pulsecore/rtpoll.h
@@ -69,7 +69,9 @@ 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. */
+ * 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, int wait);
 
 void pa_rtpoll_set_timer_absolute(pa_rtpoll *p, const struct timespec *ts);
@@ -86,18 +88,30 @@ void pa_rtpoll_item_free(pa_rtpoll_item *i);
  * 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 negative value, the
- * poll is skipped. */
+ * 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/sink-input.c b/src/pulsecore/sink-input.c
index c33d8e7..2687cfa 100644
--- a/src/pulsecore/sink-input.c
+++ b/src/pulsecore/sink-input.c
@@ -194,7 +194,6 @@ pa_sink_input* pa_sink_input_new(
     
     i->peek = NULL;
     i->drop = NULL;
-    i->process = NULL;
     i->kill = NULL;
     i->get_latency = NULL;
     i->attach = NULL;
@@ -272,7 +271,6 @@ void pa_sink_input_unlink(pa_sink_input *i) {
     
     i->peek = NULL;
     i->drop = NULL;
-    i->process = NULL;
     i->kill = NULL;
     i->get_latency = NULL;
     i->attach = NULL;
diff --git a/src/pulsecore/sink-input.h b/src/pulsecore/sink-input.h
index e1d89ff..c4e65b5 100644
--- a/src/pulsecore/sink-input.h
+++ b/src/pulsecore/sink-input.h
@@ -90,13 +90,6 @@ struct pa_sink_input {
      * 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 in each IO event loop and
-     * can be used to do additional processing even when the device is
-     * suspended and peek() is never called. Should return 1 when
-     * "some work" has been done and the IO event loop should be
-     * reiterated immediately. Called from IO thread context. */
-    int (*process) (pa_sink_input *i);           /* may be NULL */
-
     /* If non-NULL this function is called when the input is first
      * connected to a sink. Called from IO thread context */
     void (*attach) (pa_sink_input *i);           /* may be NULL */ 
diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c
index b009bc7..a7ed5a4 100644
--- a/src/pulsecore/sink.c
+++ b/src/pulsecore/sink.c
@@ -922,20 +922,3 @@ int pa_sink_suspend_all(pa_core *c, int suspend) {
     return ret;
 }
 
-int pa_sink_process_inputs(pa_sink *s) {
-    pa_sink_input *i;
-    void *state = NULL;
-    int r;
-    
-    pa_sink_assert_ref(s);
-
-    if (!PA_SINK_LINKED(s->thread_info.state))
-        return 0;
-    
-    while ((i = PA_SINK_INPUT(pa_hashmap_iterate(s->thread_info.inputs, &state, NULL))))
-        if (i->process)
-            if ((r = i->process(i)))
-                return r;
-
-    return 0;
-}
diff --git a/src/pulsecore/source-output.c b/src/pulsecore/source-output.c
index 4267234..b77a4ae 100644
--- a/src/pulsecore/source-output.c
+++ b/src/pulsecore/source-output.c
@@ -148,7 +148,6 @@ pa_source_output* pa_source_output_new(
     o->channel_map = data->channel_map;
 
     o->push = NULL;
-    o->process = NULL;
     o->kill = NULL;
     o->get_latency = NULL;
     o->detach = NULL;
@@ -204,7 +203,6 @@ void pa_source_output_unlink(pa_source_output*o) {
     pa_source_update_status(o->source);
 
     o->push = NULL;
-    o->process = NULL;
     o->kill = NULL;
     o->get_latency = NULL;
     o->attach = NULL;
diff --git a/src/pulsecore/source-output.h b/src/pulsecore/source-output.h
index 2027e37..5059c46 100644
--- a/src/pulsecore/source-output.h
+++ b/src/pulsecore/source-output.h
@@ -73,13 +73,6 @@ struct pa_source_output {
      * context. */
     void (*push)(pa_source_output *o, const pa_memchunk *chunk);
 
-    /* If non-NULL this function is called in each IO event loop and
-     * can be used to do additional processing even when the device is
-     * suspended and peek() is never called. Should return 1 when
-     * "some work" has been done and the IO event loop should be
-     * reiterated immediately. Called from IO thread context. */
-    int (*process) (pa_source_output *o);           /* may be NULL */
-
     /* 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 */ 
diff --git a/src/pulsecore/source.c b/src/pulsecore/source.c
index 2f1a5a5..34e023d 100644
--- a/src/pulsecore/source.c
+++ b/src/pulsecore/source.c
@@ -504,21 +504,3 @@ int pa_source_suspend_all(pa_core *c, int suspend) {
 
     return ret;
 }
-
-int pa_source_process_outputs(pa_source *s) {
-    pa_source_output *o;
-    void *state = NULL;
-    int r;
-    
-    pa_source_assert_ref(s);
-
-    if (!PA_SOURCE_LINKED(s->state))
-        return 0;
-    
-    while ((o = pa_hashmap_iterate(s->thread_info.outputs, &state, NULL)))
-        if (o->process)
-            if ((r = o->process(o)))
-                return r;
-
-    return 0;
-}
diff --git a/src/pulsecore/thread-mq.c b/src/pulsecore/thread-mq.c
index 3000246..d572f6e 100644
--- a/src/pulsecore/thread-mq.c
+++ b/src/pulsecore/thread-mq.c
@@ -110,28 +110,3 @@ void pa_thread_mq_install(pa_thread_mq *q) {
 pa_thread_mq *pa_thread_mq_get(void) {
     return PA_STATIC_TLS_GET(thread_mq);
 }
-
-int pa_thread_mq_process(pa_thread_mq *q) {
-    pa_msgobject *object;
-    int code;
-    void *data;
-    pa_memchunk chunk;
-    int64_t offset;
-
-    pa_assert(q);
-
-    if (pa_asyncmsgq_get(q->inq, &object, &code, &data, &offset, &chunk, 0) == 0) {
-        int ret;
-        
-        if (!object && code == PA_MESSAGE_SHUTDOWN) {
-            pa_asyncmsgq_done(q->inq, 0);
-            return -1;
-        }
-
-        ret = pa_asyncmsgq_dispatch(object, code, data, offset, &chunk);
-        pa_asyncmsgq_done(q->inq, ret);
-        return 1;
-    } 
-
-    return 0;
-}
diff --git a/src/pulsecore/thread-mq.h b/src/pulsecore/thread-mq.h
index 2b1fd68..13b6e01 100644
--- a/src/pulsecore/thread-mq.h
+++ b/src/pulsecore/thread-mq.h
@@ -43,9 +43,6 @@ 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);
 
-/* Dispatched queued events on the thread side. */
-int pa_thread_mq_process(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);
 

commit 5ae4eed52e911fb3e9712e1cd7d6095427515cd1
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Sep 14 23:26:17 2007 +0000

    Move attaching/detaching from a pa_rtpoll into pa_sink proper, remove it from module-combine
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1823 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-combine.c b/src/modules/module-combine.c
index 7df04ec..91561ee 100644
--- a/src/modules/module-combine.c
+++ b/src/modules/module-combine.c
@@ -133,9 +133,7 @@ struct userdata {
 };
 
 enum {
-    SINK_MESSAGE_DETACH = PA_SINK_MESSAGE_MAX,
-    SINK_MESSAGE_ATTACH,
-    SINK_MESSAGE_ADD_OUTPUT,
+    SINK_MESSAGE_ADD_OUTPUT = PA_SINK_MESSAGE_MAX,
     SINK_MESSAGE_REMOVE_OUTPUT
 };
 
@@ -358,6 +356,15 @@ static void sink_input_attach_cb(pa_sink_input *i) {
     o = i->userdata;
     pa_assert(o);
 
+    if (o->userdata->master == o) {
+        /* Calling these two functions here is safe, because both
+         * threads that might access this sink input are known to be
+         * waiting for us. */
+        pa_sink_set_asyncmsgq(o->userdata->sink, i->sink->asyncmsgq);
+        pa_sink_set_rtpoll(o->userdata->sink, i->sink->rtpoll);
+        pa_sink_attach_within_thread(o->userdata->sink);
+    }
+    
     pa_assert(!o->rtpoll_item);
     o->rtpoll_item = pa_rtpoll_item_new_asyncmsgq(
             i->sink->rtpoll,
@@ -376,6 +383,9 @@ static void sink_input_detach_cb(pa_sink_input *i) {
     pa_assert(o->rtpoll_item);
     pa_rtpoll_item_free(o->rtpoll_item);
     o->rtpoll_item = NULL;
+
+    if (o->userdata->master == o)
+        pa_sink_detach_from_thread(o->userdata->sink);
 }
 
 /* Called from main context */
@@ -543,36 +553,20 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
             break;
         }
 
-        case SINK_MESSAGE_DETACH: {
-            pa_sink_input *i;
-            void *state = NULL;
+        case PA_SINK_MESSAGE_DETACH:
 
             /* We're detaching all our input streams artificially, so
-             * that we can driver our sink from a different sink */
-
-            while ((i = pa_hashmap_iterate(u->sink->thread_info.inputs, &state, NULL)))
-                if (i->detach)
-                    i->detach(i);
+             * that we can drive our sink from a different sink */
 
             u->thread_info.master = NULL;
-            
             break;
-        }
 
-        case SINK_MESSAGE_ATTACH: {
-            pa_sink_input *i;
-            void *state = NULL;
+        case PA_SINK_MESSAGE_ATTACH:
 
             /* We're attached all our input streams artificially again */
-
-            while ((i = pa_hashmap_iterate(u->sink->thread_info.inputs, &state, NULL)))
-                if (i->attach)
-                    i->attach(i);
-
-            u->thread_info.master = data;
             
+            u->thread_info.master = data;
             break;
-        }
 
         case SINK_MESSAGE_ADD_OUTPUT:
             PA_LLIST_PREPEND(struct output, u->thread_info.outputs, (struct output*) data);
@@ -655,7 +649,7 @@ static int update_master(struct userdata *u, struct output *o) {
 
     /* Make sure everything is detached from the old thread before we move our stuff to a new thread */
     if (u->sink && PA_SINK_LINKED(pa_sink_get_state(u->sink)))
-        pa_asyncmsgq_send(u->sink->asyncmsgq, PA_MSGOBJECT(u->sink), SINK_MESSAGE_DETACH, NULL, 0, NULL);
+        pa_sink_detach(u->sink);
     
     if (o) {
         /* If we have a master sink we run our own sink in its thread */
@@ -706,7 +700,7 @@ static int update_master(struct userdata *u, struct output *o) {
 
     /* Now attach everything again */
     if (u->sink && PA_SINK_LINKED(pa_sink_get_state(u->sink)))
-        pa_asyncmsgq_send(u->sink->asyncmsgq, PA_MSGOBJECT(u->sink), SINK_MESSAGE_ATTACH, u->master, 0, NULL);
+        pa_sink_attach(u->sink);
 
     return 0;
 }
diff --git a/src/pulsecore/sink-input.h b/src/pulsecore/sink-input.h
index c4e65b5..a101828 100644
--- a/src/pulsecore/sink-input.h
+++ b/src/pulsecore/sink-input.h
@@ -91,7 +91,10 @@ struct pa_sink_input {
     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. Called from IO thread context */
+     * 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
diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c
index a7ed5a4..9b19188 100644
--- a/src/pulsecore/sink.c
+++ b/src/pulsecore/sink.c
@@ -901,6 +901,20 @@ int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offse
             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:
             ;
@@ -922,3 +936,47 @@ int pa_sink_suspend_all(pa_core *c, int suspend) {
     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);
+}
+
diff --git a/src/pulsecore/sink.h b/src/pulsecore/sink.h
index b3fcff4..be883ed 100644
--- a/src/pulsecore/sink.h
+++ b/src/pulsecore/sink.h
@@ -122,6 +122,8 @@ typedef enum pa_sink_message {
     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;
 
@@ -143,6 +145,9 @@ 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);
@@ -173,8 +178,9 @@ 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_inputs(pa_sink *s);
-
 int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offset, pa_memchunk *chunk);
 
+void pa_sink_attach_within_thread(pa_sink *s);
+void pa_sink_detach_within_thread(pa_sink *s);
+
 #endif
diff --git a/src/pulsecore/source.c b/src/pulsecore/source.c
index 34e023d..63ff9d7 100644
--- a/src/pulsecore/source.c
+++ b/src/pulsecore/source.c
@@ -483,6 +483,20 @@ int pa_source_process_msg(pa_msgobject *object, int code, void *userdata, int64_
         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:
@@ -504,3 +518,42 @@ int pa_source_suspend_all(pa_core *c, int suspend) {
 
     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);
+
+}
diff --git a/src/pulsecore/source.h b/src/pulsecore/source.h
index ddc6615..0fd1486 100644
--- a/src/pulsecore/source.h
+++ b/src/pulsecore/source.h
@@ -121,6 +121,8 @@ typedef enum pa_source_message {
     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;
 
@@ -142,6 +144,9 @@ 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);
+
 /* May be called by everyone, from main context */
 
 pa_usec_t pa_source_get_latency(pa_source *s);
@@ -164,8 +169,9 @@ unsigned pa_source_used_by(pa_source *s);
 
 void pa_source_post(pa_source*s, const pa_memchunk *b);
 
-int pa_source_process_outputs(pa_source *o);
-
 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);
+
 #endif

commit 8389264d6560d32b3912c60474497742807efbde
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sat Sep 15 14:21:05 2007 +0000

    count corked streams per sink/source and make pa_sink_used_by() return only the number of streams that are not corked. Introduce pa_sink_linked_by() returning the number of streams connected at all. This will allow suspending of sinks/sources when all streams connected to a sink are corked.
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1824 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-combine.c b/src/modules/module-combine.c
index 91561ee..86ae0b1 100644
--- a/src/modules/module-combine.c
+++ b/src/modules/module-combine.c
@@ -385,7 +385,7 @@ static void sink_input_detach_cb(pa_sink_input *i) {
     o->rtpoll_item = NULL;
 
     if (o->userdata->master == o)
-        pa_sink_detach_from_thread(o->userdata->sink);
+        pa_sink_detach_within_thread(o->userdata->sink);
 }
 
 /* Called from main context */
diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c
index 2687cfa..009000e 100644
--- a/src/pulsecore/sink-input.c
+++ b/src/pulsecore/sink-input.c
@@ -225,6 +225,15 @@ pa_sink_input* pa_sink_input_new(
     return i;
 }
 
+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++;
+}
+
 static int sink_input_set_state(pa_sink_input *i, pa_sink_input_state_t state) {
     pa_sink_input *ssync;
     pa_assert(i);
@@ -238,11 +247,17 @@ static int sink_input_set_state(pa_sink_input *i, pa_sink_input_state_t state) {
     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)
+    
+    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)
+    }
+    for (ssync = i->sync_next; ssync; ssync = ssync->sync_next) {
+        update_n_corked(ssync, state);
         ssync->state = state;
+    }
     
     return 0;
 }
diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c
index 9b19188..318b191 100644
--- a/src/pulsecore/sink.c
+++ b/src/pulsecore/sink.c
@@ -101,6 +101,7 @@ pa_sink* pa_sink_new(
     s->channel_map = *map;
 
     s->inputs = pa_idxset_new(NULL, NULL);
+    s->n_corked = 0;
 
     pa_cvolume_reset(&s->volume, spec->channels);
     s->muted = 0;
@@ -735,6 +736,20 @@ void pa_sink_set_description(pa_sink *s, const char *description) {
     pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
 }
 
+unsigned pa_sink_linked_by(pa_sink *s) {
+    unsigned ret;
+
+    pa_sink_assert_ref(s);
+    pa_assert(PA_SINK_LINKED(s->state));
+
+    ret = pa_idxset_size(s->inputs);
+
+    if (s->monitor_source)
+        ret += pa_source_used_by(s->monitor_source);
+
+    return ret;
+}
+
 unsigned pa_sink_used_by(pa_sink *s) {
     unsigned ret;
 
@@ -743,6 +758,10 @@ unsigned pa_sink_used_by(pa_sink *s) {
 
     ret = pa_idxset_size(s->inputs);
 
+    pa_assert(ret >= s->n_corked);
+
+    ret -= s->n_corked;
+
     if (s->monitor_source)
         ret += pa_source_used_by(s->monitor_source);
 
diff --git a/src/pulsecore/sink.h b/src/pulsecore/sink.h
index be883ed..537e9cb 100644
--- a/src/pulsecore/sink.h
+++ b/src/pulsecore/sink.h
@@ -77,7 +77,8 @@ struct pa_sink {
     pa_channel_map channel_map;
 
     pa_idxset *inputs;
-    pa_source *monitor_source;           
+    unsigned n_corked;
+    pa_source *monitor_source;
 
     pa_cvolume volume;
     int muted;
@@ -166,7 +167,8 @@ const pa_cvolume *pa_sink_get_volume(pa_sink *sink);
 void pa_sink_set_mute(pa_sink *sink, int mute);
 int pa_sink_get_mute(pa_sink *sink);
 
-unsigned pa_sink_used_by(pa_sink *s);
+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 */
diff --git a/src/pulsecore/source-output.c b/src/pulsecore/source-output.c
index b77a4ae..8650e53 100644
--- a/src/pulsecore/source-output.c
+++ b/src/pulsecore/source-output.c
@@ -182,7 +182,13 @@ static int source_output_set_state(pa_source_output *o, pa_source_output_state_t
     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++;
+    
     o->state = state;
+    
     return 0;
 }
 
diff --git a/src/pulsecore/source.c b/src/pulsecore/source.c
index 63ff9d7..d72349f 100644
--- a/src/pulsecore/source.c
+++ b/src/pulsecore/source.c
@@ -93,6 +93,7 @@ pa_source* pa_source_new(
     s->channel_map = *map;
 
     s->outputs = pa_idxset_new(NULL, NULL);
+    s->n_corked = 0;
     s->monitor_of = NULL;
 
     pa_cvolume_reset(&s->volume, spec->channels);
@@ -426,13 +427,25 @@ void pa_source_set_rtpoll(pa_source *s, pa_rtpoll *p) {
     s->rtpoll = p;
 }
 
-unsigned pa_source_used_by(pa_source *s) {
+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);
diff --git a/src/pulsecore/source.h b/src/pulsecore/source.h
index 0fd1486..4e488a7 100644
--- a/src/pulsecore/source.h
+++ b/src/pulsecore/source.h
@@ -79,6 +79,7 @@ struct pa_source {
     pa_channel_map channel_map;
 
     pa_idxset *outputs;
+    unsigned n_corked;
     pa_sink *monitor_of;                     /* may be NULL */
 
     pa_cvolume volume;
@@ -162,7 +163,8 @@ const pa_cvolume *pa_source_get_volume(pa_source *source);
 void pa_source_set_mute(pa_source *source, int mute);
 int pa_source_get_mute(pa_source *source);
 
-unsigned pa_source_used_by(pa_source *s);
+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 */

commit 298d2392f9b5e586977ddb7e31b45ec322998602
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sat Sep 15 14:57:18 2007 +0000

    trivial typo
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1825 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-combine.c b/src/modules/module-combine.c
index 86ae0b1..f2633ab 100644
--- a/src/modules/module-combine.c
+++ b/src/modules/module-combine.c
@@ -322,7 +322,7 @@ static void request_memblock(struct output *o) {
     pa_mutex_unlock(o->userdata->mutex);
 }
 
-/* Called from I/O trhead context */
+/* Called from I/O thread context */
 static int sink_input_peek_cb(pa_sink_input *i, pa_memchunk *chunk) {
     struct output *o;
 

commit 0469c8436655cb4cc422216ab8a13849080f14c0
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sun Sep 16 15:05:26 2007 +0000

    add frame alignment APIs; don't require memory to be writable when silencing it (required of the mmap modes drivers where the hw data needs to be silenced, although it is not writable to others)
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1826 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/sample-util.c b/src/pulsecore/sample-util.c
index a1361f4..add6608 100644
--- a/src/pulsecore/sample-util.c
+++ b/src/pulsecore/sample-util.c
@@ -38,7 +38,7 @@
 #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;
@@ -82,7 +82,6 @@ void pa_silence_memchunk(pa_memchunk *c, const pa_sample_spec *spec) {
     pa_assert(c->memblock);
     pa_assert(spec);
 
-    pa_memchunk_make_writable(c, 0);
     data = pa_memblock_acquire(c->memblock);
     pa_silence_memory((uint8_t*) data+c->index, c->length, spec);
     pa_memblock_release(c->memblock);
@@ -474,3 +473,23 @@ void pa_volume_memchunk(
     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;
+}
+

commit e17fbf0606200c4fa08bda5d00c9706503dde313
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sun Sep 16 15:09:45 2007 +0000

    be a little bit more elaborate on the reason why we drop to software volume control if hw is not featureful enough for us
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1827 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-alsa-sink.c b/src/modules/module-alsa-sink.c
index 1bcb30c..70685e4 100644
--- a/src/modules/module-alsa-sink.c
+++ b/src/modules/module-alsa-sink.c
@@ -234,7 +234,7 @@ static int unix_write(struct userdata *u) {
                     
         l = snd_pcm_status_get_avail(status) * u->frame_size;
 
-/*                     pa_log("%u bytes to write", l); */
+/*         pa_log("%u bytes to write", l); */
                     
         if (l <= 0)
             return work_done;
@@ -248,7 +248,7 @@ static int unix_write(struct userdata *u) {
         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_log("wrote %i bytes of %u (%u)", t*u->frame_size, u->memchunk.length, l); */
                     
         pa_assert(t != 0);
                     
@@ -834,16 +834,17 @@ int pa__init(pa_module*m) {
         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) {
+                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)) {

commit 87795b09737c0428bec4d1fcec23bfa1df5f92be
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sun Sep 16 15:10:16 2007 +0000

    add missing header file changes for frame alignment apis
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1828 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/sample-util.h b/src/pulsecore/sample-util.h
index 2b11ad3..0d4924b 100644
--- a/src/pulsecore/sample-util.h
+++ b/src/pulsecore/sample-util.h
@@ -56,4 +56,8 @@ 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);
+
+int pa_frame_aligned(size_t l, const pa_sample_spec *ss);
+
 #endif

commit d079b4863b2e0c758e81d117df4cdc967c342c22
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sun Sep 16 21:54:12 2007 +0000

    properly define MAX/MIN macros
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1829 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/macro.h b/src/pulsecore/macro.h
index c46ae52..ec45154 100644
--- a/src/pulsecore/macro.h
+++ b/src/pulsecore/macro.h
@@ -64,8 +64,13 @@ static inline size_t pa_page_align(size_t l) {
 
 #define PA_ELEMENTSOF(x) (sizeof(x)/sizeof((x)[0]))
 
-#define SA_MAX(a, b) ((a) > (b) ? (a) : (b))
-#define SA_MIN(a, b) ((a) < (b) ? (a) : (b))
+#ifndef MAX
+#define MAX(a, b) ((a) > (b) ? (a) : (b))
+#endif
+
+#ifndef MIN
+#define MIN(a, b) ((a) < (b) ? (a) : (b))
+#endif
 
 #ifdef __GNUC__
 #define PA_PRETTY_FUNCTION __PRETTY_FUNCTION__

commit fce85071796577ceb59fc0ff413c5188c2e385c1
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sun Sep 16 21:56:38 2007 +0000

    * add a new resampler "copy" which is does not change sample rates but copies data unmodified from input to output.
    * add a new API pa_resampler_max_block_size() which can be used to determine the maximum input buffer size for the resampler so that the bounce buffers don't grow larger then the mempool tile size
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1830 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/resampler.c b/src/pulsecore/resampler.c
index 7493eef..c4b8179 100644
--- a/src/pulsecore/resampler.c
+++ b/src/pulsecore/resampler.c
@@ -45,6 +45,9 @@
 
 #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;
@@ -88,6 +91,7 @@ struct pa_resampler {
     } ffmpeg;
 };
 
+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);
@@ -136,6 +140,7 @@ static int (* const init_table[])(pa_resampler*r) = {
     [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) {
@@ -169,13 +174,23 @@ pa_resampler* pa_resampler_new(
 
     /* 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'." );
+        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;
     }
 
@@ -321,6 +336,35 @@ size_t pa_resampler_request(pa_resampler *r, size_t out_length) {
     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) {
     pa_assert(r);
     
@@ -357,7 +401,8 @@ static const char * const resample_methods[] = {
     "speex-fixed-9",
     "speex-fixed-10",
     "ffmpeg",
-    "auto"
+    "auto",
+    "copy"
 };
 
 const char *pa_resample_method_to_string(pa_resample_method_t m) {
@@ -568,7 +613,7 @@ static pa_memchunk *resample(pa_resampler *r, pa_memchunk *input) {
     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)+1024;
+    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;
 
     r->buf3.index = 0;
@@ -875,6 +920,7 @@ static int trivial_init(pa_resampler*r) {
 
     r->impl_resample = trivial_resample;
     r->impl_update_rates = trivial_update_rates;
+    r->impl_free = NULL;
 
     return 0;
 }
@@ -994,3 +1040,17 @@ static int ffmpeg_init(pa_resampler *r) {
 
     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;
+}
diff --git a/src/pulsecore/resampler.h b/src/pulsecore/resampler.h
index fed4d89..8de8ad7 100644
--- a/src/pulsecore/resampler.h
+++ b/src/pulsecore/resampler.h
@@ -45,6 +45,7 @@ typedef enum pa_resample_method {
     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;
 
@@ -62,6 +63,9 @@ 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);
 
+/* Requires 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);
 

commit ac1ee4e6754f3aa287bb4e3ede03c59d1369cd50
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sun Sep 16 21:57:15 2007 +0000

    add new API pa_mempool_block_size_max() to query the maximum tile size
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1831 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/memblock.c b/src/pulsecore/memblock.c
index cded2df..05fc34d 100644
--- a/src/pulsecore/memblock.c
+++ b/src/pulsecore/memblock.c
@@ -300,7 +300,7 @@ pa_memblock *pa_memblock_new_pool(pa_mempool *p, size_t length) {
      * take the largest size that fits in one of our slots. */
     
     if (length == (size_t) -1)
-        length = p->block_size - PA_ALIGN(sizeof(struct mempool_slot)) - PA_ALIGN(sizeof(pa_memblock));
+        length = pa_mempool_block_size_max(p);
     
     if (p->block_size - PA_ALIGN(sizeof(struct mempool_slot)) >= PA_ALIGN(sizeof(pa_memblock)) + length) {
 
@@ -723,6 +723,13 @@ const pa_mempool_stat* pa_mempool_get_stat(pa_mempool *p) {
 }
 
 /* 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;
diff --git a/src/pulsecore/memblock.h b/src/pulsecore/memblock.h
index 9bf7d8a..c704014 100644
--- a/src/pulsecore/memblock.h
+++ b/src/pulsecore/memblock.h
@@ -122,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);

commit 5df7a85473f1c06a8baf6a4d81433bde18f86714
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sun Sep 16 21:58:04 2007 +0000

    split memblocks into multiples of the mempool tile size
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1832 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/pstream.c b/src/pulsecore/pstream.c
index 33bc520..333012c 100644
--- a/src/pulsecore/pstream.c
+++ b/src/pulsecore/pstream.c
@@ -40,16 +40,17 @@
 #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/refcnt.h>
 #include <pulsecore/flist.h>
+#include <pulsecore/macro.h>
 
 #include "pstream.h"
 
@@ -83,7 +84,6 @@ 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);
 
@@ -351,6 +351,7 @@ void pa_pstream_send_packet(pa_pstream*p, pa_packet *packet, const pa_creds *cre
 
 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;
 
     pa_assert(p);
     pa_assert(PA_REFCNT_VALUE(p) > 0);
@@ -362,6 +363,8 @@ void pa_pstream_send_memblock(pa_pstream*p, uint32_t channel, int64_t offset, pa
 
     idx = 0;
     length = chunk->length;
+
+    bsm = pa_mempool_block_size_max(p->mempool);
     
     while (length > 0) {
         struct item_info *i;
@@ -371,7 +374,7 @@ void pa_pstream_send_memblock(pa_pstream*p, uint32_t channel, int64_t offset, pa
             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);

commit 1d1eda60595622a79e598e7c986cc3c23e6a5c34
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sun Sep 16 22:00:38 2007 +0000

    add a "length" argument to the seek functions, as an optimization to request a certain block size if any data needs to be generated. this is merely a hint.
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1833 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-combine.c b/src/modules/module-combine.c
index f2633ab..235e04e 100644
--- a/src/modules/module-combine.c
+++ b/src/modules/module-combine.c
@@ -275,7 +275,7 @@ finish:
     pa_log_debug("Thread shutting down");
 }
 
-static void request_memblock(struct output *o) {
+static void request_memblock(struct output *o, size_t length) {
     pa_memchunk chunk;
     
     pa_assert(o);
@@ -306,7 +306,7 @@ static void request_memblock(struct output *o) {
             struct output *j;
             
             /* Do it! */
-            pa_sink_render(o->userdata->sink, o->userdata->block_size, &chunk);
+            pa_sink_render(o->userdata->sink, length, &chunk);
             
             /* OK, let's send this data to the other threads */
             for (j = o->userdata->thread_info.outputs; j; j = j->next)
@@ -323,7 +323,7 @@ static void request_memblock(struct output *o) {
 }
 
 /* Called from I/O thread context */
-static int sink_input_peek_cb(pa_sink_input *i, pa_memchunk *chunk) {
+static int sink_input_peek_cb(pa_sink_input *i, size_t length, pa_memchunk *chunk) {
     struct output *o;
 
     pa_sink_input_assert_ref(i);
@@ -331,7 +331,7 @@ static int sink_input_peek_cb(pa_sink_input *i, pa_memchunk *chunk) {
     pa_assert(o);
 
     /* If necessary, get some new data */
-    request_memblock(o);
+    request_memblock(o, length);
 
     return  pa_memblockq_peek(o->memblockq, chunk);
 }
diff --git a/src/modules/module-sine.c b/src/modules/module-sine.c
index f48cb09..5684f94 100644
--- a/src/modules/module-sine.c
+++ b/src/modules/module-sine.c
@@ -58,7 +58,7 @@ static const char* const valid_modargs[] = {
     NULL,
 };
 
-static int sink_input_peek_cb(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;
     
     pa_assert(i);
diff --git a/src/pulsecore/play-memblockq.c b/src/pulsecore/play-memblockq.c
index 68ce21b..5652ac2 100644
--- a/src/pulsecore/play-memblockq.c
+++ b/src/pulsecore/play-memblockq.c
@@ -97,7 +97,7 @@ static void sink_input_kill_cb(pa_sink_input *i) {
     memblockq_stream_unlink(MEMBLOCKQ_STREAM(i->userdata));
 }
 
-static int sink_input_peek_cb(pa_sink_input *i, pa_memchunk *chunk) {
+static int sink_input_peek_cb(pa_sink_input *i, size_t length, pa_memchunk *chunk) {
     memblockq_stream *u;
 
     pa_assert(i);
diff --git a/src/pulsecore/play-memchunk.c b/src/pulsecore/play-memchunk.c
index f60f706..fd931a2 100644
--- a/src/pulsecore/play-memchunk.c
+++ b/src/pulsecore/play-memchunk.c
@@ -97,7 +97,7 @@ static void sink_input_kill_cb(pa_sink_input *i) {
     memchunk_stream_unlink(MEMCHUNK_STREAM(i->userdata));
 }
 
-static int sink_input_peek_cb(pa_sink_input *i, pa_memchunk *chunk) {
+static int sink_input_peek_cb(pa_sink_input *i, size_t length, pa_memchunk *chunk) {
     memchunk_stream *u;
 
     pa_assert(i);
diff --git a/src/pulsecore/protocol-esound.c b/src/pulsecore/protocol-esound.c
index fc881c8..b694363 100644
--- a/src/pulsecore/protocol-esound.c
+++ b/src/pulsecore/protocol-esound.c
@@ -150,7 +150,7 @@ typedef struct proto_handler {
 } esd_proto_handler_info_t;
 
 static void sink_input_drop_cb(pa_sink_input *i, size_t length);
-static int sink_input_peek_cb(pa_sink_input *i, pa_memchunk *chunk);
+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 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);
@@ -1237,7 +1237,7 @@ static int sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int
 }
 
 /* Called from thread context */
-static int sink_input_peek_cb(pa_sink_input *i, pa_memchunk *chunk) {
+static int sink_input_peek_cb(pa_sink_input *i, size_t length, pa_memchunk *chunk) {
     connection*c;
     int r;
     
diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c
index 52cec09..24f5997 100644
--- a/src/pulsecore/protocol-native.c
+++ b/src/pulsecore/protocol-native.c
@@ -199,7 +199,7 @@ enum {
     CONNECTION_MESSAGE_REVOKE
 };
 
-static int sink_input_peek_cb(pa_sink_input *i, pa_memchunk *chunk);
+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);
 
@@ -973,7 +973,7 @@ static int sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int
 }
 
 /* Called from thread context */
-static int sink_input_peek_cb(pa_sink_input *i, pa_memchunk *chunk) {
+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);
diff --git a/src/pulsecore/protocol-simple.c b/src/pulsecore/protocol-simple.c
index db7c9a6..da5f24e 100644
--- a/src/pulsecore/protocol-simple.c
+++ b/src/pulsecore/protocol-simple.c
@@ -343,7 +343,7 @@ static int sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int
 }
 
 /* Called from thread context */
-static int sink_input_peek_cb(pa_sink_input *i, pa_memchunk *chunk) {
+static int sink_input_peek_cb(pa_sink_input *i, size_t length, pa_memchunk *chunk) {
     connection *c;
     int r;
 
diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c
index 009000e..f2855fc 100644
--- a/src/pulsecore/sink-input.c
+++ b/src/pulsecore/sink-input.c
@@ -41,9 +41,9 @@
 
 #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)
 
 static PA_DEFINE_CHECK_TYPE(pa_sink_input, pa_msgobject);
 
@@ -368,13 +368,15 @@ pa_usec_t pa_sink_input_get_latency(pa_sink_input *i) {
 }
 
 /* Called from thread context */
-int pa_sink_input_peek(pa_sink_input *i, pa_memchunk *chunk, pa_cvolume *volume) {
+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;
 
     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);
 
@@ -383,6 +385,15 @@ int pa_sink_input_peek(pa_sink_input *i, pa_memchunk *chunk, pa_cvolume *volume)
 
     pa_assert(i->thread_info.state == PA_SINK_INPUT_RUNNING || i->thread_info.state == PA_SINK_INPUT_DRAINED);
 
+    /* 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;
 
@@ -390,7 +401,10 @@ int pa_sink_input_peek(pa_sink_input *i, pa_memchunk *chunk, pa_cvolume *volume)
          * while until the old sink has drained its playback buffer */
 
         if (!i->thread_info.silence_memblock)
-            i->thread_info.silence_memblock = pa_silence_memblock_new(i->sink->core->mempool, &i->sink->sample_spec, SILENCE_BUFFER_LENGTH);
+            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->thread_info.silence_memblock);
         chunk->index = 0;
@@ -404,7 +418,7 @@ int pa_sink_input_peek(pa_sink_input *i, pa_memchunk *chunk, pa_cvolume *volume)
 
     if (!i->thread_info.resampler) {
         do_volume_adj_here = 0; /* FIXME??? */
-        ret = i->peek(i, chunk);
+        ret = i->peek(i, length, chunk);
         goto finish;
     }
 
@@ -413,15 +427,22 @@ int pa_sink_input_peek(pa_sink_input *i, pa_memchunk *chunk, pa_cvolume *volume)
 
     while (!i->thread_info.resampled_chunk.memblock) {
         pa_memchunk tchunk;
-        size_t l;
+        size_t l, rmbs;
 
-        if ((ret = i->peek(i, &tchunk)) < 0)
+        l = pa_resampler_request(i->thread_info.resampler, length);
+
+        if (l <= 0)
+            l = pa_frame_align(CONVERT_BUFFER_LENGTH, &i->sample_spec);
+
+        rmbs = pa_resampler_max_block_size(i->thread_info.resampler);
+        if (l > rmbs)
+            l = rmbs;
+        
+        if ((ret = i->peek(i, l, &tchunk)) < 0)
             goto finish;
 
         pa_assert(tchunk.length > 0);
 
-        l = pa_resampler_request(i->thread_info.resampler, CONVERT_BUFFER_LENGTH);
-
         if (tchunk.length > l)
             tchunk.length = l;
 
@@ -477,6 +498,7 @@ finish:
 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->thread_info.move_silence > 0) {
@@ -527,9 +549,9 @@ void pa_sink_input_drop(pa_sink_input *i, size_t length) {
                 pa_memchunk chunk;
                 pa_cvolume volume;
                 
-                if (pa_sink_input_peek(i, &chunk, &volume) >= 0) {
+                if (pa_sink_input_peek(i, length, &chunk, &volume) >= 0) {
                     size_t l;
-
+                    
                     pa_memblock_unref(chunk.memblock);
 
                     l = chunk.length;
@@ -541,11 +563,13 @@ void pa_sink_input_drop(pa_sink_input *i, size_t length) {
                     
                 } else {
                     size_t l;
-
+                    
+                    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 = pa_resampler_request(i->thread_info.resampler, length)) > 0)
+                    if (l > 0)
                         if (i->drop)
                             i->drop(i, l);
                             
@@ -798,9 +822,9 @@ int pa_sink_input_move_to(pa_sink_input *i, pa_sink *dest, int 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, &i->sample_spec) +
+                pa_bytes_to_usec(i->thread_info.move_silence, &origin->sample_spec) +
                 silence_usec,
-                &i->sample_spec);
+                &dest->sample_spec);
 
     pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i->sink), PA_SINK_MESSAGE_ADD_INPUT, i, 0, NULL);
     
diff --git a/src/pulsecore/sink-input.h b/src/pulsecore/sink-input.h
index a101828..7d40564 100644
--- a/src/pulsecore/sink-input.h
+++ b/src/pulsecore/sink-input.h
@@ -83,8 +83,12 @@ struct pa_sink_input {
     int muted;
 
     /* Returns the chunk of audio data (but doesn't drop it
-     * yet!). Returns -1 on failure. Called from IO thread context. */
-    int (*peek) (pa_sink_input *i, pa_memchunk *chunk);
+     * 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. */
@@ -217,7 +221,7 @@ 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, pa_memchunk *chunk, pa_cvolume *volume);
+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);
 
diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c
index 318b191..45cc96b 100644
--- a/src/pulsecore/sink.c
+++ b/src/pulsecore/sink.c
@@ -46,7 +46,8 @@
 #include "sink.h"
 
 #define MAX_MIX_CHANNELS 32
-#define SILENCE_BUFFER_LENGTH (64*1024)
+#define MIX_BUFFER_LENGTH (PA_PAGE_SIZE)
+#define SILENCE_BUFFER_LENGTH (PA_PAGE_SIZE*12)
 
 static PA_DEFINE_CHECK_TYPE(pa_sink, pa_msgobject);
 
@@ -311,7 +312,7 @@ void pa_sink_ping(pa_sink *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) {
+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;
@@ -322,7 +323,7 @@ static unsigned fill_mix_info(pa_sink *s, pa_mix_info *info, unsigned maxinfo) {
     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)
+        if (pa_sink_input_peek(i, length, &info->chunk, &info->volume) < 0)
             continue;
 
         info->userdata = pa_sink_input_ref(i);
@@ -399,20 +400,32 @@ static void inputs_drop(pa_sink *s, pa_mix_info *info, unsigned n, size_t length
 void pa_sink_render(pa_sink*s, size_t length, pa_memchunk *result) {
     pa_mix_info info[MAX_MIX_CHANNELS];
     unsigned n;
-
+    size_t block_size_max;
+    
     pa_sink_assert_ref(s);
     pa_assert(PA_SINK_OPENED(s->thread_info.state));
-    pa_assert(length);
+    pa_assert(pa_frame_aligned(length, &s->sample_spec));
     pa_assert(result);
 
     pa_sink_ref(s);
 
-    n = s->thread_info.state == PA_SINK_RUNNING ? fill_mix_info(s, info, MAX_MIX_CHANNELS) : 0;
+    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 = SILENCE_BUFFER_LENGTH;
+            length = pa_frame_align(SILENCE_BUFFER_LENGTH, &s->sample_spec);
+
+        pa_assert(length > 0);
 
         if (!s->silence || pa_memblock_get_length(s->silence) < length) {
             if (s->silence)
@@ -470,11 +483,12 @@ void pa_sink_render_into(pa_sink*s, pa_memchunk *target) {
     pa_assert(PA_SINK_OPENED(s->thread_info.state));
     pa_assert(target);
     pa_assert(target->memblock);
-    pa_assert(target->length);
+    pa_assert(target->length > 0);
+    pa_assert(pa_frame_aligned(target->length, &s->sample_spec));
 
     pa_sink_ref(s);
 
-    n = s->thread_info.state == PA_SINK_RUNNING ? fill_mix_info(s, info, MAX_MIX_CHANNELS) : 0;
+    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);
@@ -536,7 +550,8 @@ void pa_sink_render_into_full(pa_sink *s, pa_memchunk *target) {
     pa_assert(PA_SINK_OPENED(s->thread_info.state));
     pa_assert(target);
     pa_assert(target->memblock);
-    pa_assert(target->length);
+    pa_assert(target->length > 0);
+    pa_assert(pa_frame_aligned(target->length, &s->sample_spec));
 
     pa_sink_ref(s);
 
@@ -559,13 +574,15 @@ void pa_sink_render_into_full(pa_sink *s, pa_memchunk *target) {
 void pa_sink_render_full(pa_sink *s, size_t length, pa_memchunk *result) {
     pa_sink_assert_ref(s);
     pa_assert(PA_SINK_OPENED(s->thread_info.state));
-    pa_assert(length);
+    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);
 }
@@ -577,6 +594,7 @@ void pa_sink_skip(pa_sink *s, size_t length) {
     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;
@@ -853,7 +871,7 @@ int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offse
                     pa_cvolume volume;
                     size_t n;
                     
-                    if (pa_sink_input_peek(info->sink_input, &memchunk, &volume) < 0)
+                    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;
diff --git a/src/pulsecore/sound-file-stream.c b/src/pulsecore/sound-file-stream.c
index 8a04b82..6c70c4f 100644
--- a/src/pulsecore/sound-file-stream.c
+++ b/src/pulsecore/sound-file-stream.c
@@ -44,8 +44,6 @@
 
 #include "sound-file-stream.h"
 
-#define BUF_SIZE (1024*16)
-
 typedef struct file_stream {
     pa_msgobject parent;
     pa_core *core;
@@ -113,7 +111,7 @@ static void sink_input_kill_cb(pa_sink_input *i) {
     file_stream_unlink(FILE_STREAM(i->userdata));
 }
 
-static int sink_input_peek_cb(pa_sink_input *i, pa_memchunk *chunk) {
+static int sink_input_peek_cb(pa_sink_input *i, size_t length, pa_memchunk *chunk) {
     file_stream *u;
     
     pa_assert(i);
@@ -128,7 +126,7 @@ static int sink_input_peek_cb(pa_sink_input *i, pa_memchunk *chunk) {
         
         if (!u->memchunk.memblock) {
             
-            u->memchunk.memblock = pa_memblock_new(i->sink->core->mempool, BUF_SIZE);
+            u->memchunk.memblock = pa_memblock_new(i->sink->core->mempool, length);
             u->memchunk.index = 0;
             
             if (u->readf_function) {
@@ -137,7 +135,7 @@ static int sink_input_peek_cb(pa_sink_input *i, pa_memchunk *chunk) {
                 size_t fs = pa_frame_size(&i->sample_spec);
                 
                 p = pa_memblock_acquire(u->memchunk.memblock);
-                n = u->readf_function(u->sndfile, p, BUF_SIZE/fs);
+                n = u->readf_function(u->sndfile, p, length/fs);
                 pa_memblock_release(u->memchunk.memblock);
 
                 if (n <= 0)
@@ -149,7 +147,7 @@ static int sink_input_peek_cb(pa_sink_input *i, pa_memchunk *chunk) {
                 void *p;
 
                 p = pa_memblock_acquire(u->memchunk.memblock);
-                n = sf_read_raw(u->sndfile, p, BUF_SIZE);
+                n = sf_read_raw(u->sndfile, p, length);
                 pa_memblock_release(u->memchunk.memblock);
                 
                 if (n <= 0)

commit 35483eeab7d08bc3e7ab2cd7a91e3d7453dca605
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sun Sep 16 22:03:19 2007 +0000

    add a new module module-remap-sink which can be used to remap the channel maps of an already existant sink. one use case is to create a virtual sink that redirects stereo data to the rear speakers of a surround card.
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1834 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/Makefile.am b/src/Makefile.am
index a04a91a..9914c19 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -934,7 +934,8 @@ modlibexec_LTLIBRARIES += \
 		module-native-protocol-tcp.la \
 		module-native-protocol-fd.la \
 		module-esound-protocol-tcp.la \
-		module-combine.la
+		module-combine.la \
+		module-remap-sink.la
 #		module-tunnel-sink.la \
 #		module-tunnel-source.la \
 #		module-esound-sink.la
@@ -1054,6 +1055,7 @@ 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-esound-compat-spawnfd-symdef.h \
 		modules/module-esound-compat-spawnpid-symdef.h \
 		modules/module-match-symdef.h \
@@ -1202,6 +1204,10 @@ 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_match_la_SOURCES = modules/module-match.c
 module_match_la_LDFLAGS = -module -avoid-version
 module_match_la_LIBADD = $(AM_LIBADD) libpulsecore.la
diff --git a/src/modules/module-remap-sink.c b/src/modules/module-remap-sink.c
new file mode 100644
index 0000000..1d272b1
--- /dev/null
+++ b/src/modules/module-remap-sink.c
@@ -0,0 +1,330 @@
+/* $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>")
+
+#define DEFAULT_SINK_NAME "remapped"
+
+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_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;
+
+    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);
+
+    /* 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_CAN_SUSPEND;
+    
+    pa_sink_set_module(u->sink, m);
+    pa_sink_set_description(u->sink, t = pa_sprintf_malloc("Remapped sink of '%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);
+
+    return 0;
+
+fail:
+    if (ma)
+        pa_modargs_free(ma);
+
+    pa__done(m);
+
+    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);
+}

commit 116ddaaae9267d9f89f3d127cba62763246b441c
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sun Sep 16 22:42:03 2007 +0000

    use gcc const and pure function attributes wherever applicable
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1835 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulse/cdecl.h b/src/pulse/cdecl.h
index 922ad27..e1f23d2 100644
--- a/src/pulse/cdecl.h
+++ b/src/pulse/cdecl.h
@@ -41,4 +41,22 @@
 
 #endif
 
+#ifndef PA_GCC_PURE
+#ifdef __GNUCC__
+#define PA_GCC_PURE __attribute__ ((pure))
+#else
+/** This function's return value depends only the arguments list and global state **/
+#define PA_GCC_PURE
+#endif
+#endif
+
+#ifndef PA_GCC_CONST
+#ifdef __GNUCC__
+#define PA_GCC_CONST __attribute__ ((pure))
+#else
+/** This function's return value depends only the arguments list (stricter version of PA_GCC_CONST) **/
+#define PA_GCC_CONST
+#endif
+#endif
+
 #endif
diff --git a/src/pulse/channelmap.h b/src/pulse/channelmap.h
index bb8ce95..a05e191 100644
--- a/src/pulse/channelmap.h
+++ b/src/pulse/channelmap.h
@@ -172,7 +172,7 @@ 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);
@@ -187,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
 
diff --git a/src/pulse/sample.h b/src/pulse/sample.h
index 683167c..b307621 100644
--- a/src/pulse/sample.h
+++ b/src/pulse/sample.h
@@ -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
diff --git a/src/pulse/timeval.h b/src/pulse/timeval.h
index dbf4319..e90df9f 100644
--- a/src/pulse/timeval.h
+++ b/src/pulse/timeval.h
@@ -44,16 +44,16 @@ 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;
 
 PA_C_DECL_END
 
diff --git a/src/pulse/utf8.h b/src/pulse/utf8.h
index ea08840..1e08047 100644
--- a/src/pulse/utf8.h
+++ b/src/pulse/utf8.h
@@ -34,7 +34,7 @@
 PA_C_DECL_BEGIN
 
 /** Test if the specified strings qualifies as valid UTF8. Return the string if so, otherwise NULL */
-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);
diff --git a/src/pulse/volume.h b/src/pulse/volume.h
index a928ff7..22e5b8a 100644
--- a/src/pulse/volume.h
+++ b/src/pulse/volume.h
@@ -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)
diff --git a/src/pulsecore/core-util.h b/src/pulsecore/core-util.h
index efd19f4..af97e4b 100644
--- a/src/pulsecore/core-util.h
+++ b/src/pulsecore/core-util.h
@@ -61,14 +61,14 @@ 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_strsignal(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);
@@ -85,8 +85,8 @@ 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);
 
diff --git a/src/pulsecore/gccmacro.h b/src/pulsecore/gccmacro.h
index f3ace59..d211c2e 100644
--- a/src/pulsecore/gccmacro.h
+++ b/src/pulsecore/gccmacro.h
@@ -55,7 +55,26 @@
 #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__ ((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
diff --git a/src/pulsecore/sample-util.h b/src/pulsecore/sample-util.h
index 0d4924b..92c6e9f 100644
--- a/src/pulsecore/sample-util.h
+++ b/src/pulsecore/sample-util.h
@@ -56,8 +56,8 @@ 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);
+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);
+int pa_frame_aligned(size_t l, const pa_sample_spec *ss) PA_GCC_PURE;
 
 #endif
diff --git a/src/pulsecore/sconv.h b/src/pulsecore/sconv.h
index 5e8fa68..901f50a 100644
--- a/src/pulsecore/sconv.h
+++ b/src/pulsecore/sconv.h
@@ -29,10 +29,10 @@
 
 typedef void (*pa_convert_func_t)(unsigned n, const void *a, void *b);
 
-pa_convert_func_t pa_get_convert_to_float32ne_function(pa_sample_format_t f);
-pa_convert_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_convert_func_t pa_get_convert_from_s16ne_function(pa_sample_format_t f);
+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

commit 61b90a0951ce709bce09cfa44825498224d92120
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sun Sep 16 23:28:56 2007 +0000

    add proper boolean type pa_bool_t
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1836 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/configure.ac b/configure.ac
index cb68f57..f179827 100644
--- a/configure.ac
+++ b/configure.ac
@@ -130,6 +130,18 @@ 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
diff --git a/src/pulsecore/macro.h b/src/pulsecore/macro.h
index ec45154..d0dff5e 100644
--- a/src/pulsecore/macro.h
+++ b/src/pulsecore/macro.h
@@ -72,6 +72,21 @@ static inline size_t pa_page_align(size_t l) {
 #define MIN(a, b) ((a) < (b) ? (a) : (b))
 #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
diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c
index f2855fc..b8ca5e1 100644
--- a/src/pulsecore/sink-input.c
+++ b/src/pulsecore/sink-input.c
@@ -79,10 +79,10 @@ void pa_sink_input_new_data_set_sample_spec(pa_sink_input_new_data *data, const
         data->sample_spec = *spec;
 }
 
-void pa_sink_input_new_data_set_muted(pa_sink_input_new_data *data, int mute) {
+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 = 1;
+    data->muted_is_set = TRUE;
     data->muted = !!mute;
 }
 
@@ -607,7 +607,7 @@ const pa_cvolume *pa_sink_input_get_volume(pa_sink_input *i) {
     return &i->volume;
 }
 
-void pa_sink_input_set_mute(pa_sink_input *i, int mute) {
+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));
@@ -628,7 +628,7 @@ int pa_sink_input_get_mute(pa_sink_input *i) {
     return !!i->muted;
 }
 
-void pa_sink_input_cork(pa_sink_input *i, int b) {
+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));
 
diff --git a/src/pulsecore/sink-input.h b/src/pulsecore/sink-input.h
index 7d40564..152c24e 100644
--- a/src/pulsecore/sink-input.h
+++ b/src/pulsecore/sink-input.h
@@ -46,7 +46,7 @@ typedef enum pa_sink_input_state {
     PA_SINK_INPUT_UNLINKED      /*< The stream is dead */
 } pa_sink_input_state_t;
 
-static inline int PA_SINK_INPUT_LINKED(pa_sink_input_state_t x) {
+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;
 }
 
@@ -80,7 +80,7 @@ struct pa_sink_input {
     pa_sink_input *sync_prev, *sync_next;
     
     pa_cvolume volume;
-    int muted;
+    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
@@ -139,7 +139,7 @@ struct pa_sink_input {
         pa_sink_input *sync_prev, *sync_next;
         
         pa_cvolume volume;
-        int muted;
+        pa_bool_t muted;
     } thread_info;
 
     void *userdata;
@@ -165,14 +165,14 @@ 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;
-    int muted;
-    int muted_is_set;
+    pa_bool_t volume_is_set;
+    pa_bool_t muted;
+    pa_bool_t muted_is_set;
 
     pa_resample_method_t resample_method;
 
@@ -183,7 +183,7 @@ 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, int mute);
+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 */
 
@@ -206,10 +206,10 @@ pa_usec_t pa_sink_input_get_latency(pa_sink_input *i);
 
 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);
-void pa_sink_input_set_mute(pa_sink_input *i, int mute);
+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);
 
 int pa_sink_input_set_rate(pa_sink_input *i, uint32_t rate);
 
diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c
index 45cc96b..98f117c 100644
--- a/src/pulsecore/sink.c
+++ b/src/pulsecore/sink.c
@@ -105,8 +105,8 @@ pa_sink* pa_sink_new(
     s->n_corked = 0;
 
     pa_cvolume_reset(&s->volume, spec->channels);
-    s->muted = 0;
-    s->refresh_volume = s->refresh_mute = 0;
+    s->muted = FALSE;
+    s->refresh_volume = s->refresh_mute = FALSE;
 
     s->get_latency = NULL;
     s->set_volume = NULL;
@@ -295,7 +295,7 @@ int pa_sink_update_status(pa_sink*s) {
     return sink_set_state(s, pa_sink_used_by(s) ? PA_SINK_RUNNING : PA_SINK_IDLE);
 }
 
-int pa_sink_suspend(pa_sink *s, int suspend) {
+int pa_sink_suspend(pa_sink *s, pa_bool_t suspend) {
     pa_sink_assert_ref(s);
     pa_assert(PA_SINK_LINKED(s->state));
 
@@ -678,7 +678,7 @@ const pa_cvolume *pa_sink_get_volume(pa_sink *s) {
     return &s->volume;
 }
 
-void pa_sink_set_mute(pa_sink *s, int mute) {
+void pa_sink_set_mute(pa_sink *s, pa_bool_t mute) {
     int changed;
 
     pa_sink_assert_ref(s);
@@ -697,8 +697,8 @@ void pa_sink_set_mute(pa_sink *s, int mute) {
         pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
 }
 
-int pa_sink_get_mute(pa_sink *s) {
-    int old_muted;
+pa_bool_t pa_sink_get_mute(pa_sink *s) {
+    pa_bool_t old_muted;
 
     pa_sink_assert_ref(s);
     pa_assert(PA_SINK_LINKED(s->state));
@@ -927,7 +927,7 @@ int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offse
             return 0;
 
         case PA_SINK_MESSAGE_GET_MUTE:
-            *((int*) userdata) = s->thread_info.soft_muted;
+            *((pa_bool_t*) userdata) = s->thread_info.soft_muted;
             return 0;
 
         case PA_SINK_MESSAGE_PING:
@@ -960,7 +960,7 @@ int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offse
     return -1;
 }
 
-int pa_sink_suspend_all(pa_core *c, int suspend) {
+int pa_sink_suspend_all(pa_core *c, pa_bool_t suspend) {
     pa_sink *sink;
     uint32_t idx;
     int ret = 0;
diff --git a/src/pulsecore/sink.h b/src/pulsecore/sink.h
index 537e9cb..ce1d12c 100644
--- a/src/pulsecore/sink.h
+++ b/src/pulsecore/sink.h
@@ -52,11 +52,11 @@ typedef enum pa_sink_state {
     PA_SINK_UNLINKED
 } pa_sink_state_t;
 
-static inline int PA_SINK_OPENED(pa_sink_state_t x) {
+static inline pa_bool_t PA_SINK_OPENED(pa_sink_state_t x) {
     return x == PA_SINK_RUNNING || x == PA_SINK_IDLE;
 }
 
-static inline int PA_SINK_LINKED(pa_sink_state_t x) {
+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;
 }
 
@@ -81,9 +81,9 @@ struct pa_sink {
     pa_source *monitor_source;
 
     pa_cvolume volume;
-    int muted;
-    int refresh_volume;
-    int refresh_mute;
+    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 */
@@ -101,7 +101,7 @@ struct pa_sink {
         pa_sink_state_t state;
         pa_hashmap *inputs;
         pa_cvolume soft_volume;
-        int soft_muted;
+        pa_bool_t soft_muted;
     } thread_info;
 
     pa_memblock *silence;
@@ -154,8 +154,8 @@ void pa_sink_attach(pa_sink *s);
 pa_usec_t pa_sink_get_latency(pa_sink *s);
 
 int pa_sink_update_status(pa_sink*s);
-int pa_sink_suspend(pa_sink *s, int suspend);
-int pa_sink_suspend_all(pa_core *c, int suspend);
+int pa_sink_suspend(pa_sink *s, pa_bool_t suspend);
+int pa_sink_suspend_all(pa_core *c, pa_bool_t suspend);
 
 /* 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
@@ -164,8 +164,8 @@ void pa_sink_ping(pa_sink *s);
 
 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, int mute);
-int pa_sink_get_mute(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);
 
 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 */
diff --git a/src/pulsecore/source-output.c b/src/pulsecore/source-output.c
index 8650e53..df5dc8c 100644
--- a/src/pulsecore/source-output.c
+++ b/src/pulsecore/source-output.c
@@ -306,7 +306,7 @@ void pa_source_output_push(pa_source_output *o, const pa_memchunk *chunk) {
     pa_memblock_unref(rchunk.memblock);
 }
 
-void pa_source_output_cork(pa_source_output *o, int b) {
+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));
 
diff --git a/src/pulsecore/source-output.h b/src/pulsecore/source-output.h
index 5059c46..96ded86 100644
--- a/src/pulsecore/source-output.h
+++ b/src/pulsecore/source-output.h
@@ -42,7 +42,7 @@ typedef enum pa_source_output_state {
     PA_SOURCE_OUTPUT_UNLINKED
 } pa_source_output_state_t;
 
-static inline int PA_SOURCE_OUTPUT_LINKED(pa_source_output_state_t x) {
+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;
 }
 
@@ -126,9 +126,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;
@@ -157,7 +157,7 @@ void pa_source_output_kill(pa_source_output*o);
 
 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);
 
diff --git a/src/pulsecore/source.c b/src/pulsecore/source.c
index d72349f..315c2ce 100644
--- a/src/pulsecore/source.c
+++ b/src/pulsecore/source.c
@@ -97,8 +97,8 @@ pa_source* pa_source_new(
     s->monitor_of = NULL;
 
     pa_cvolume_reset(&s->volume, spec->channels);
-    s->muted = 0;
-    s->refresh_volume = s->refresh_muted = 0;
+    s->muted = FALSE;
+    s->refresh_volume = s->refresh_muted = FALSE;
 
     s->get_latency = NULL;
     s->set_volume = NULL;
@@ -240,7 +240,7 @@ int pa_source_update_status(pa_source*s) {
     return source_set_state(s, pa_source_used_by(s) ? PA_SOURCE_RUNNING : PA_SOURCE_IDLE);
 }
 
-int pa_source_suspend(pa_source *s, int suspend) {
+int pa_source_suspend(pa_source *s, pa_bool_t suspend) {
     pa_source_assert_ref(s);
     pa_assert(PA_SOURCE_LINKED(s->state));
 
@@ -348,7 +348,7 @@ const pa_cvolume *pa_source_get_volume(pa_source *s) {
     return &s->volume;
 }
 
-void pa_source_set_mute(pa_source *s, int mute) {
+void pa_source_set_mute(pa_source *s, pa_bool_t mute) {
     int changed;
 
     pa_source_assert_ref(s);
@@ -367,8 +367,8 @@ void pa_source_set_mute(pa_source *s, int mute) {
         pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
 }
 
-int pa_source_get_mute(pa_source *s) {
-    int old_muted;
+pa_bool_t pa_source_get_mute(pa_source *s) {
+    pa_bool_t old_muted;
 
     pa_source_assert_ref(s);
     pa_assert(PA_SOURCE_LINKED(s->state));
@@ -487,7 +487,7 @@ int pa_source_process_msg(pa_msgobject *object, int code, void *userdata, int64_
             return 0;
 
         case PA_SOURCE_MESSAGE_GET_MUTE:
-            *((int*) userdata) = s->thread_info.soft_muted;
+            *((pa_bool_t*) userdata) = s->thread_info.soft_muted;
             return 0;
 
         case PA_SOURCE_MESSAGE_PING:
@@ -519,7 +519,7 @@ int pa_source_process_msg(pa_msgobject *object, int code, void *userdata, int64_
     return -1;
 }
 
-int pa_source_suspend_all(pa_core *c, int suspend) {
+int pa_source_suspend_all(pa_core *c, pa_bool_t suspend) {
     uint32_t idx;
     pa_source *source;
     int ret = 0;
diff --git a/src/pulsecore/source.h b/src/pulsecore/source.h
index 4e488a7..bd0a912 100644
--- a/src/pulsecore/source.h
+++ b/src/pulsecore/source.h
@@ -54,11 +54,11 @@ typedef enum pa_source_state {
     PA_SOURCE_UNLINKED
 } pa_source_state_t;
 
-static inline int PA_SOURCE_OPENED(pa_source_state_t x) {
+static inline pa_bool_t PA_SOURCE_OPENED(pa_source_state_t x) {
     return x == PA_SOURCE_RUNNING || x == PA_SOURCE_IDLE;
 }
 
-static inline int PA_SOURCE_LINKED(pa_source_state_t x) {
+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;
 }
 
@@ -83,9 +83,9 @@ struct pa_source {
     pa_sink *monitor_of;                     /* may be NULL */
 
     pa_cvolume volume;
-    int muted;
-    int refresh_volume;
-    int refresh_muted;
+    pa_bool_t muted;
+    pa_bool_t refresh_volume;
+    pa_bool_t refresh_muted;
 
     int (*set_state)(pa_source*source, pa_source_state_t state); /* may be NULL */
     int (*set_volume)(pa_source *s);         /* dito */
@@ -103,7 +103,7 @@ struct pa_source {
         pa_source_state_t state;
         pa_hashmap *outputs;
         pa_cvolume soft_volume;
-        int soft_muted;
+        pa_bool_t soft_muted;
     } thread_info;
 
     void *userdata;
@@ -153,15 +153,15 @@ void pa_source_attach(pa_source *s);
 pa_usec_t pa_source_get_latency(pa_source *s);
 
 int pa_source_update_status(pa_source*s);
-int pa_source_suspend(pa_source *s, int suspend);
-int pa_source_suspend_all(pa_core *c, int suspend);
+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_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, int mute);
-int pa_source_get_mute(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 */

commit 2741685d3ad4e78c1c155f77cea34c46c259584e
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Sep 17 00:32:51 2007 +0000

    use priority inheritance on mutexes where applicable
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1837 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/configure.ac b/configure.ac
index f179827..c12cfc0 100644
--- a/configure.ac
+++ b/configure.ac
@@ -297,6 +297,22 @@ AC_CHECK_FUNCS([setresuid setresgid setreuid setregid seteuid setegid ppoll])
 
 ACX_PTHREAD
 
+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) ####
 
 AC_SYS_LARGEFILE
diff --git a/src/daemon/main.c b/src/daemon/main.c
index e01bb23..f34e59e 100644
--- a/src/daemon/main.c
+++ b/src/daemon/main.c
@@ -330,7 +330,7 @@ static const char *libtool_get_error(void) {
 }
 
 static void libtool_init(void)  {
-    pa_assert_se(libtool_mutex = pa_mutex_new(1));
+    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);
     pa_assert_se(lt_dlinit() == 0);
 }
diff --git a/src/modules/module-combine.c b/src/modules/module-combine.c
index 235e04e..7ac7b9a 100644
--- a/src/modules/module-combine.c
+++ b/src/modules/module-combine.c
@@ -947,7 +947,7 @@ int pa__init(pa_module*m) {
     u->thread_info.master = u->master = NULL;
     u->time_event = NULL; 
     u->adjust_time = DEFAULT_ADJUST_TIME; 
-    u->mutex = pa_mutex_new(0);
+    u->mutex = pa_mutex_new(FALSE, TRUE);
     pa_thread_mq_init(&u->thread_mq, m->core->mainloop);
     u->rtpoll = NULL;
     u->thread = NULL;
diff --git a/src/pulse/thread-mainloop.c b/src/pulse/thread-mainloop.c
index 29769e2..3068570 100644
--- a/src/pulse/thread-mainloop.c
+++ b/src/pulse/thread-mainloop.c
@@ -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;
diff --git a/src/pulsecore/asyncmsgq.c b/src/pulsecore/asyncmsgq.c
index b365446..c0917ca 100644
--- a/src/pulsecore/asyncmsgq.c
+++ b/src/pulsecore/asyncmsgq.c
@@ -67,7 +67,7 @@ pa_asyncmsgq *pa_asyncmsgq_new(unsigned size) {
 
     PA_REFCNT_INIT(a);
     pa_assert_se(a->asyncq = pa_asyncq_new(size));
-    pa_assert_se(a->mutex = pa_mutex_new(0));
+    pa_assert_se(a->mutex = pa_mutex_new(FALSE, TRUE));
     a->current = NULL;
 
     return a;
diff --git a/src/pulsecore/memblock.c b/src/pulsecore/memblock.c
index 05fc34d..3827dc0 100644
--- a/src/pulsecore/memblock.c
+++ b/src/pulsecore/memblock.c
@@ -660,7 +660,7 @@ pa_mempool* pa_mempool_new(int shared) {
 
     p = pa_xnew(pa_mempool, 1);
 
-    p->mutex = pa_mutex_new(1);
+    p->mutex = pa_mutex_new(TRUE, TRUE);
     p->semaphore = pa_semaphore_new(0);
 
     p->block_size = PA_PAGE_ALIGN(PA_MEMPOOL_SLOT_SIZE);
@@ -781,7 +781,7 @@ pa_memimport* pa_memimport_new(pa_mempool *p, pa_memimport_release_cb_t cb, void
     pa_assert(cb);
 
     i = pa_xnew(pa_memimport, 1);
-    i->mutex = pa_mutex_new(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);
@@ -909,18 +909,22 @@ finish:
 
 int pa_memimport_process_revoke(pa_memimport *i, uint32_t id) {
     pa_memblock *b;
+    int ret = 0;
     pa_assert(i);
 
     pa_mutex_lock(i->mutex);
 
-    if (!(b = pa_hashmap_get(i->blocks, PA_UINT32_TO_PTR(id))))
-        return -1;
+    if (!(b = pa_hashmap_get(i->blocks, PA_UINT32_TO_PTR(id)))) {
+        ret = -1;
+        goto finish;
+    }
 
     memblock_replace_import(b);
 
+finish:
     pa_mutex_unlock(i->mutex);
 
-    return 0;
+    return ret;
 }
 
 /* For sending blocks to other nodes */
@@ -934,7 +938,7 @@ pa_memexport* pa_memexport_new(pa_mempool *p, pa_memexport_revoke_cb_t cb, void
         return NULL;
 
     e = pa_xnew(pa_memexport, 1);
-    e->mutex = pa_mutex_new(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);
diff --git a/src/pulsecore/mutex-posix.c b/src/pulsecore/mutex-posix.c
index 64f466d..19e095b 100644
--- a/src/pulsecore/mutex-posix.c
+++ b/src/pulsecore/mutex-posix.c
@@ -40,15 +40,20 @@ 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;
 
     pthread_mutexattr_init(&attr);
-
+    
     if (recursive)
         pa_assert_se(pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE) == 0);
 
+#ifdef HAVE_PTHREAD_PRIO_INHERIT
+    if (inherit_priority)
+        pthread_mutexattr_setprotocol(&attr, PTHREAD_PRIO_INHERIT);
+#endif
+
     m = pa_xnew(pa_mutex, 1);
     pa_assert_se(pthread_mutex_init(&m->mutex, &attr) == 0);
     return m;
diff --git a/src/pulsecore/mutex.h b/src/pulsecore/mutex.h
index b2e34c0..72e8878 100644
--- a/src/pulsecore/mutex.h
+++ b/src/pulsecore/mutex.h
@@ -24,9 +24,17 @@
   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);
diff --git a/src/pulsecore/once-posix.c b/src/pulsecore/once-posix.c
index fba0ddf..4f6e5b6 100644
--- a/src/pulsecore/once-posix.c
+++ b/src/pulsecore/once-posix.c
@@ -58,7 +58,7 @@ int pa_once_begin(pa_once *control) {
             return 0;
         }
 
-        pa_assert_se(m = pa_mutex_new(0));
+        pa_assert_se(m = pa_mutex_new(FALSE, FALSE));
         pa_mutex_lock(m);
 
         if (pa_atomic_ptr_cmpxchg(&control->mutex, NULL, m))
diff --git a/src/tests/thread-test.c b/src/tests/thread-test.c
index 0077cde..72dde6c 100644
--- a/src/tests/thread-test.c
+++ b/src/tests/thread-test.c
@@ -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);

commit 061e8068aab4237b31abc1d8763999db1bcbc57f
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Sep 17 12:31:06 2007 +0000

    Add a special ltdl .so loader that avoids lazy frelocations during runtime
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1838 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/configure.ac b/configure.ac
index c12cfc0..869db01 100644
--- a/configure.ac
+++ b/configure.ac
@@ -187,7 +187,7 @@ AC_HEADER_STDC
 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 \
     sys/mman.h sys/resource.h sys/select.h sys/socket.h sys/wait.h \
-    syslog.h])
+    syslog.h sys/dl.h dlfcn.h])
 AC_CHECK_HEADERS([netinet/ip.h], [], [],
 		 [#include <sys/types.h>
 		  #if HAVE_NETINET_IN_H
diff --git a/src/Makefile.am b/src/Makefile.am
index 9914c19..d9933a0 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -132,6 +132,7 @@ 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
 
diff --git a/src/daemon/ltdl-bind-now.c b/src/daemon/ltdl-bind-now.c
new file mode 100644
index 0000000..f5347db
--- /dev/null
+++ b/src/daemon/ltdl-bind-now.c
@@ -0,0 +1,160 @@
+/* $Id$ */
+
+/***
+  This file is part of PulseAudio.
+
+  Copyright 2004-2006 Lennart Poettering
+  Copyright 2006 Pierre Ossman <ossman at 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
index 0000000..e19c7bc
--- /dev/null
+++ b/src/daemon/ltdl-bind-now.h
@@ -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
+
diff --git a/src/daemon/main.c b/src/daemon/main.c
index f34e59e..6c7928e 100644
--- a/src/daemon/main.c
+++ b/src/daemon/main.c
@@ -93,6 +93,7 @@
 #include "daemon-conf.h"
 #include "dumpmodules.h"
 #include "caps.h"
+#include "ltdl-bind-now.h"
 
 #ifdef HAVE_LIBWRAP
 /* Only one instance of these variables */
@@ -309,38 +310,6 @@ static void set_all_rlimits(const pa_daemon_conf *conf) {
 }
 #endif
 
-static pa_mutex *libtool_mutex = NULL;
-        
-static void libtool_lock(void) {
-    pa_mutex_lock(libtool_mutex);
-}
-
-static void libtool_unlock(void) {
-    pa_mutex_unlock(libtool_mutex);
-}
-
-PA_STATIC_TLS_DECLARE_NO_FREE(libtool_tls);
-
-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);
-}
-
-static void libtool_init(void)  {
-    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);
-    pa_assert_se(lt_dlinit() == 0);
-}
-
-static void libtool_done(void) {
-    pa_assert_se(lt_dlexit() == 0);
-    pa_mutex_free(libtool_mutex);
-    libtool_mutex = NULL;
-}
-
 int main(int argc, char *argv[]) {
     pa_core *c = NULL;
     pa_strbuf *buf = NULL;
@@ -396,7 +365,7 @@ int main(int argc, char *argv[]) {
 
     LTDL_SET_PRELOADED_SYMBOLS();
 
-    libtool_init();
+    pa_ltdl_init();
 
 #ifdef OS_IS_WIN32
     {
@@ -747,7 +716,7 @@ finish:
     WSACleanup();
 #endif
 
-    libtool_done();
+    pa_ltdl_done();
 
 #ifdef HAVE_DBUS
     dbus_shutdown();

commit a1526f105dfc642aea213cca84f90635878ba4bd
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Sep 17 13:01:04 2007 +0000

    add missing initialization
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1839 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/daemon/main.c b/src/daemon/main.c
index 6c7928e..43f573e 100644
--- a/src/daemon/main.c
+++ b/src/daemon/main.c
@@ -317,7 +317,7 @@ int main(int argc, char *argv[]) {
     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;

commit 7f9fea74ef4c972ccc7f6cf797f83d1bdbcddde7
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Sep 17 13:32:46 2007 +0000

    on Linu disable lazy binding altogether
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1840 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/daemon/main.c b/src/daemon/main.c
index 43f573e..c446582 100644
--- a/src/daemon/main.c
+++ b/src/daemon/main.c
@@ -315,7 +315,6 @@ int main(int argc, char *argv[]) {
     pa_strbuf *buf = NULL;
     pa_daemon_conf *conf = NULL;
     pa_mainloop *mainloop = NULL;
-
     char *s;
     int r = 0, retval = 1, d = 0;
     int daemon_pipe[2] = { -1, -1 };
@@ -329,6 +328,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;

commit 19eb7ebd4d4b0390b60ecadc57b9aefb3ae94560
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Sep 17 13:50:13 2007 +0000

    once.c is no longer POSIX specific. Since it is now considerably more advanced than it used to be, use it on windows, too
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1841 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/Makefile.am b/src/Makefile.am
index d9933a0..95a0e92 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -77,15 +77,11 @@ 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/semaphore.h
-#pulsecore/semaphore-win32.c pulsecore/semaphore.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/semaphore-posix.c pulsecore/semaphore.h
@@ -496,6 +492,7 @@ libpulse_la_SOURCES += \
 		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
@@ -706,6 +703,7 @@ libpulsecore_la_SOURCES += \
 		pulsecore/rtpoll.c pulsecore/rtpoll.h \
 		pulsecore/rtclock.c pulsecore/rtclock.h \
 		pulsecore/macro.h \
+		pulsecore/once.c pulsecore/once.h \
 		$(PA_THREAD_OBJS)
 
 if OS_IS_WIN32
diff --git a/src/daemon/main.c b/src/daemon/main.c
index c446582..ba2a33d 100644
--- a/src/daemon/main.c
+++ b/src/daemon/main.c
@@ -320,7 +320,6 @@ int main(int argc, char *argv[]) {
     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
diff --git a/src/pulsecore/once-posix.c b/src/pulsecore/once-posix.c
deleted file mode 100644
index 4f6e5b6..0000000
--- a/src/pulsecore/once-posix.c
+++ /dev/null
@@ -1,98 +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 <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);
-    }
-}
-
diff --git a/src/pulsecore/once-win32.c b/src/pulsecore/once-win32.c
deleted file mode 100644
index b30097c..0000000
--- a/src/pulsecore/once-win32.c
+++ /dev/null
@@ -1,69 +0,0 @@
-/* $Id$ */
-
-/***
-  This file is part of PulseAudio.
-
-  Copyright 2006 Pierre Ossman <ossman at 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
index 0000000..4f6e5b6
--- /dev/null
+++ b/src/pulsecore/once.c
@@ -0,0 +1,98 @@
+/* $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 <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);
+    }
+}
+

commit d3b898513c8b289c5cf026493badb1b8865d07a0
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Sep 17 14:03:04 2007 +0000

    drop a couple of WARNING prefixes in log messages, since we have pa_log_warn anyway for marking warnings especially
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1842 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/daemon/daemon-conf.c b/src/daemon/daemon-conf.c
index ff62816..825101c 100644
--- a/src/daemon/daemon-conf.c
+++ b/src/daemon/daemon-conf.c
@@ -426,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;
     }
 
diff --git a/src/modules/module-combine.c b/src/modules/module-combine.c
index 7ac7b9a..feadf4f 100644
--- a/src/modules/module-combine.c
+++ b/src/modules/module-combine.c
@@ -1051,7 +1051,7 @@ int pa__init(pa_module*m) {
         }
 
         if (pa_idxset_size(u->outputs) <= 1)
-            pa_log_warn("WARNING: No slave sinks specified.");
+            pa_log_warn("No slave sinks specified.");
 
         u->sink_new_slot = NULL;
         
diff --git a/src/modules/module-esound-compat-spawnfd.c b/src/modules/module-esound-compat-spawnfd.c
index 46235c0..49dcf3b 100644
--- a/src/modules/module-esound-compat-spawnfd.c
+++ b/src/modules/module-esound-compat-spawnfd.c
@@ -63,7 +63,7 @@ int pa__init(pa_module*m) {
     }
 
     if (pa_loop_write(fd, &x, sizeof(x), NULL) != sizeof(x))
-        pa_log_warn("WARNING: write(%u, 1, 1) failed: %s", fd, pa_cstrerror(errno));
+        pa_log_warn("write(%u, 1, 1) failed: %s", fd, pa_cstrerror(errno));
 
     pa_assert_se(pa_close(fd) == 0);
 
diff --git a/src/modules/module-esound-compat-spawnpid.c b/src/modules/module-esound-compat-spawnpid.c
index 1cc86d2..6ad7db7 100644
--- a/src/modules/module-esound-compat-spawnpid.c
+++ b/src/modules/module-esound-compat-spawnpid.c
@@ -62,7 +62,7 @@ int pa__init(pa_module*m) {
     }
 
     if (kill(pid, SIGUSR1) < 0)
-        pa_log_warn("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);
 
diff --git a/src/modules/module-esound-sink.c b/src/modules/module-esound-sink.c
index 39886d0..faa77a5 100644
--- a/src/modules/module-esound-sink.c
+++ b/src/modules/module-esound-sink.c
@@ -210,7 +210,7 @@ static int handle_response(struct userdata *u) {
             /* 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;
             }
 
diff --git a/src/pulse/client-conf.c b/src/pulse/client-conf.c
index 447d185..abd277a 100644
--- a/src/pulse/client-conf.c
+++ b/src/pulse/client-conf.c
@@ -117,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_warn("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;
     }
 
diff --git a/src/pulse/mainloop.c b/src/pulse/mainloop.c
index 641eded..c69c665 100644
--- a/src/pulse/mainloop.c
+++ b/src/pulse/mainloop.c
@@ -194,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;
         }
     }
diff --git a/src/pulsecore/conf-parser.c b/src/pulsecore/conf-parser.c
index 47ec72c..ee43b05 100644
--- a/src/pulsecore/conf-parser.c
+++ b/src/pulsecore/conf-parser.c
@@ -120,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;
     }
@@ -131,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;
         }
diff --git a/src/pulsecore/core-util.c b/src/pulsecore/core-util.c
index 5becdef..a729cbb 100644
--- a/src/pulsecore/core-util.c
+++ b/src/pulsecore/core-util.c
@@ -141,10 +141,10 @@ void pa_make_nonblock_fd(int fd) {
     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_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
 }
 
@@ -411,9 +411,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_strsignal(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_strsignal(sig));
 #endif
 }
 
@@ -995,10 +995,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);
         }
diff --git a/src/pulsecore/flist.c b/src/pulsecore/flist.c
index 680a9f7..d974077 100644
--- a/src/pulsecore/flist.c
+++ b/src/pulsecore/flist.c
@@ -186,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;
@@ -227,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;
diff --git a/src/pulsecore/ipacl.c b/src/pulsecore/ipacl.c
index 8a8eac7..9b22e8f 100644
--- a/src/pulsecore/ipacl.c
+++ b/src/pulsecore/ipacl.c
@@ -109,7 +109,7 @@ pa_ip_acl* pa_ip_acl_new(const char *s) {
             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) {
 
@@ -138,7 +138,7 @@ 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 {
diff --git a/src/pulsecore/memblock.c b/src/pulsecore/memblock.c
index 3827dc0..e05304b 100644
--- a/src/pulsecore/memblock.c
+++ b/src/pulsecore/memblock.c
@@ -704,7 +704,7 @@ void pa_mempool_free(pa_mempool *p) {
 
     if (pa_atomic_load(&p->stat.n_allocated) > 0) {
 /*         raise(SIGTRAP);  */
-        pa_log_warn("WARNING! Memory pool destroyed but not all memory blocks freed! %u remain.", pa_atomic_load(&p->stat.n_allocated));
+        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);
diff --git a/src/pulsecore/pid.c b/src/pulsecore/pid.c
index 6bc9f06..44f5e84 100644
--- a/src/pulsecore/pid.c
+++ b/src/pulsecore/pid.c
@@ -90,7 +90,7 @@ static int open_pid_file(const char *fn, int mode) {
 
         if ((fd = open(fn, mode, 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;
         }
 
@@ -204,7 +204,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",
+        pa_log_warn("Failed to open PID file '%s': %s",
             fn, pa_cstrerror(errno));
         goto fail;
     }

commit 26a1ae7bbb5f95aa9117cac1f693c79289c8e124
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Sep 17 15:26:18 2007 +0000

    Rename pa_strsignal() to pa_sig2str(), since we return the symbolical signal name, not a human readable string. This follows the Solaris API of sig2str() a bit. Also, add all remaining signals to the list of signal names.
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1843 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/configure.ac b/configure.ac
index 869db01..c166608 100644
--- a/configure.ac
+++ b/configure.ac
@@ -291,7 +291,7 @@ AC_CHECK_FUNCS([lstat])
 
 # Non-standard
 
-AC_CHECK_FUNCS([setresuid setresgid setreuid setregid seteuid setegid ppoll])
+AC_CHECK_FUNCS([setresuid setresgid setreuid setregid seteuid setegid ppoll strsignal sig2str])
 
 #### POSIX threads ####
 
diff --git a/src/Makefile.am b/src/Makefile.am
index 95a0e92..06f061d 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -235,7 +235,8 @@ noinst_PROGRAMS = \
 		asyncq-test \
 		asyncmsgq-test \
 		queue-test \
-		rtpoll-test
+		rtpoll-test \
+		sig2str-test
 
 if HAVE_SIGXCPU
 noinst_PROGRAMS += \
@@ -375,6 +376,11 @@ 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)
+
 ###################################
 #         Client library          #
 ###################################
diff --git a/src/daemon/main.c b/src/daemon/main.c
index ba2a33d..a660ab1 100644
--- a/src/daemon/main.c
+++ b/src/daemon/main.c
@@ -130,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
diff --git a/src/pulsecore/core-util.c b/src/pulsecore/core-util.c
index a729cbb..37e7f18 100644
--- a/src/pulsecore/core-util.c
+++ b/src/pulsecore/core-util.c
@@ -90,6 +90,7 @@
 #include <pulsecore/winsock.h>
 #include <pulsecore/log.h>
 #include <pulsecore/macro.h>
+#include <pulsecore/thread.h>
 
 #include "core-util.h"
 
@@ -411,9 +412,9 @@ void pa_check_signal_is_blocked(int sig) {
     if (sa.sa_handler != SIG_DFL)
         return;
 
-    pa_log_warn("%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_warn("%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
 }
 
@@ -616,31 +617,93 @@ 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 || sig >= _NSIG)
+        goto fail;
+    
+#ifdef HAVE_SIG2STR
+    {
+        char buf[SIG2STR_MAX];
+        
+        if (str2sig(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";
+        case SIGQUIT:   return "SIGQUIT";
+        case SIGILL:    return "SIGULL";
+        case SIGTRAP:   return "SIGTRAP";
+        case SIGABRT:   return "SIGABRT";
+        case SIGBUS:    return "SIGBUS";
+        case SIGFPE:    return "SIGFPE";
+        case SIGKILL:   return "SIGKILL";
 #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
+        case SIGALRM:   return "SIGALRM";
+        case SIGTERM:   return "SIGTERM";
+        case SIGSTKFLT: return "SIGSTKFLT";
 #ifdef SIGCHLD
-        case SIGCHLD: return "SIGCHLD";
+        case SIGCHLD:   return "SIGCHLD";
 #endif
-#ifdef SIGHUP
-        case SIGHUP: return "SIGHUP";
+        case SIGCONT:   return "SIGCONT";
+        case SIGSTOP:   return "SIGSTOP";
+        case SIGTSTP:   return "SIGTSTP";
+        case SIGTTIN:   return "SIGTTIN";
+        case SIGTTOU:   return "SIGTTOU";
+        case SIGURG:    return "SIGURG";
+#ifdef SIGXCPU
+        case SIGXCPU:   return "SIGXCPU";
+#endif
+#ifdef SIGXFSZ
+        case SIGXFSZ:   return "SIGXFSZ";
 #endif
-        default: return "UNKNOWN SIGNAL";
+        case SIGVTALRM: return "SIGVTALRM";
+        case SIGPROF:   return "SIGPROF";
+        case SIGWINCH:  return "SIGWINCH";
+        case SIGIO:     return "SIGIO";
+        case SIGPWR:    return "SIGPWR";
+        case SIGSYS:    return "SIGSYS";
+    }
+
+#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
diff --git a/src/pulsecore/core-util.h b/src/pulsecore/core-util.h
index af97e4b..4429f41 100644
--- a/src/pulsecore/core-util.h
+++ b/src/pulsecore/core-util.h
@@ -68,7 +68,7 @@ char *pa_split_spaces(const char *c, const char **state);
 
 char *pa_strip_nl(char *s);
 
-const char *pa_strsignal(int sig) PA_GCC_PURE;
+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);
diff --git a/src/pulsecore/rtpoll.c b/src/pulsecore/rtpoll.c
index 0de8d0c..e7ccd90 100644
--- a/src/pulsecore/rtpoll.c
+++ b/src/pulsecore/rtpoll.c
@@ -157,7 +157,7 @@ void pa_rtpoll_install(pa_rtpoll *p) {
         return;
     }
 
-    pa_log_debug("Acquired POSIX realtime signal SIGRTMIN+%i", p->rtsig - SIGRTMIN);
+    pa_log_debug("Acquired POSIX realtime signal %s", pa_sig2str(p->rtsig));
 
     {
         sigset_t ss;
diff --git a/src/tests/sig2str-test.c b/src/tests/sig2str-test.c
new file mode 100644
index 0000000..b3cc99d
--- /dev/null
+++ b/src/tests/sig2str-test.c
@@ -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+1; sig++)
+        printf("%i = %s\n", sig, pa_sig2str(sig));
+
+    return 0;
+}

commit 1ae473bd1bb0f9087aa260a57cda869d9609f61f
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Sep 17 17:00:50 2007 +0000

    fall back to plughw: if hw: doesn't work
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1844 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-alsa-sink.c b/src/modules/module-alsa-sink.c
index 70685e4..fb3f926 100644
--- a/src/modules/module-alsa-sink.c
+++ b/src/modules/module-alsa-sink.c
@@ -678,7 +678,7 @@ int pa__init(pa_module*m) {
     
     pa_modargs *ma = NULL;
     struct userdata *u = NULL;
-    const char *dev;
+    char *dev;
     pa_sample_spec ss;
     pa_channel_map map;
     uint32_t nfrags, frag_size;
@@ -737,24 +737,39 @@ int pa__init(pa_module*m) {
     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;
-    }
 
-    u->device_name = pa_xstrdup(dev);
+    dev = pa_xstrdup(pa_modargs_get_value(ma, "device", DEFAULT_DEVICE));
 
-    if ((err = snd_pcm_info(u->pcm_handle, pcm_info)) < 0) {
-        pa_log("Error fetching PCM info: %s", snd_strerror(err));
-        goto fail;
-    }
+    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) {
 
-    b = 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 (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_xfree(dev);
+                    dev = d;
+                    continue;
+                }
+            }
+            
+            pa_log("Failed to set hardware parameters: %s", snd_strerror(err));
+            pa_xfree(dev);
+            goto fail;
+        }
 
+        break;
+    }
+    
     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;
@@ -763,6 +778,13 @@ int pa__init(pa_module*m) {
     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;
+    }
+
+    u->device_name = dev;
+        
     if ((err = pa_alsa_set_sw_params(u->pcm_handle)) < 0) {
         pa_log("Failed to set software parameters: %s", snd_strerror(err));
         goto fail;

commit 8ff7d567d364e60283a73486889876c454566eea
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Sep 17 22:39:51 2007 +0000

    add a locale-independant pa_atof() implementation
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1846 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/configure.ac b/configure.ac
index c166608..5b6c647 100644
--- a/configure.ac
+++ b/configure.ac
@@ -291,7 +291,7 @@ AC_CHECK_FUNCS([lstat])
 
 # Non-standard
 
-AC_CHECK_FUNCS([setresuid setresgid setreuid setregid seteuid setegid ppoll strsignal sig2str])
+AC_CHECK_FUNCS([setresuid setresgid setreuid setregid seteuid setegid ppoll strsignal sig2str strtof_l])
 
 #### POSIX threads ####
 
diff --git a/src/pulsecore/core-util.c b/src/pulsecore/core-util.c
index 37e7f18..aac7629 100644
--- a/src/pulsecore/core-util.c
+++ b/src/pulsecore/core-util.c
@@ -42,6 +42,10 @@
 #include <sys/stat.h>
 #include <sys/time.h>
 
+#ifdef HAVE_STRTOF_L
+#include <locale.h>
+#endif
+
 #ifdef HAVE_SCHED_H
 #include <sched.h>
 #endif
@@ -1221,11 +1225,15 @@ int pa_atoi(const char *s, int32_t *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;
 
     return 0;
@@ -1239,9 +1247,13 @@ int pa_atou(const char *s, uint32_t *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;
@@ -1249,6 +1261,51 @@ int pa_atou(const char *s, uint32_t *ret_u) {
     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;
+        f = strtof(s, &x);
+    }
+
+    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;
diff --git a/src/pulsecore/core-util.h b/src/pulsecore/core-util.h
index 4429f41..b8ef464 100644
--- a/src/pulsecore/core-util.h
+++ b/src/pulsecore/core-util.h
@@ -92,6 +92,7 @@ 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, ...);
 

commit 7b4f981e4fb72b333cc154e5f11bba3d2562bd2d
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Sep 17 22:40:42 2007 +0000

    print a message when we fall back on plughw
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1847 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-alsa-sink.c b/src/modules/module-alsa-sink.c
index fb3f926..84f1d4e 100644
--- a/src/modules/module-alsa-sink.c
+++ b/src/modules/module-alsa-sink.c
@@ -756,6 +756,7 @@ int pa__init(pa_module*m) {
                 
                 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;
                     continue;

commit 4cde5073f034545dd9dc200efe5fe873760a55c0
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Sep 17 22:42:20 2007 +0000

    add LADSPA sink than can be piggy-backed ontop of another sink
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1848 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/Makefile.am b/src/Makefile.am
index 06f061d..c564ff3 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -940,7 +940,8 @@ modlibexec_LTLIBRARIES += \
 		module-native-protocol-fd.la \
 		module-esound-protocol-tcp.la \
 		module-combine.la \
-		module-remap-sink.la
+		module-remap-sink.la \
+		module-ladspa-sink.la
 #		module-tunnel-sink.la \
 #		module-tunnel-source.la \
 #		module-esound-sink.la
@@ -1061,6 +1062,7 @@ SYMDEF_FILES = \
 		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 \
@@ -1213,6 +1215,11 @@ 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) 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
diff --git a/src/modules/ladspa.h b/src/modules/ladspa.h
new file mode 100644
index 0000000..5c30a8a
--- /dev/null
+++ b/src/modules/ladspa.h
@@ -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 */
diff --git a/src/modules/module-ladspa-sink.c b/src/modules/module-ladspa-sink.c
new file mode 100644
index 0000000..0ff0ba3
--- /dev/null
+++ b/src/modules/module-ladspa-sink.c
@@ -0,0 +1,565 @@
+/* $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 <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>")
+
+#define DEFAULT_SINK_NAME "ladspa"
+
+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;
+
+    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_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 = *p;
+
+            u->descriptor->run(u->handle[c], n);
+
+            q = u->output;
+            p = dst + c;
+            for (j = 0; j < n; j++, q++, p += u->channels)
+                *p = *q;
+        }
+
+        pa_memblock_release(tchunk.memblock);
+        pa_memblock_release(u->memchunk.memblock);
+
+        pa_memblock_unref(tchunk.memblock);
+    }
+
+    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_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_log("Cannot handle type of port %s", 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);
+        p = 0;
+        
+        while ((k = pa_split(cdata, ",", &state))) {
+            float f;
+
+            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;
+            }
+
+            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++) {
+                
+            if (!LADSPA_IS_PORT_INPUT(d->PortDescriptors[p]) || !LADSPA_IS_PORT_CONTROL(d->PortDescriptors[p]))
+                continue;
+
+            pa_assert(h < n_control);
+            
+            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]);
+
+    /* 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_CAN_SUSPEND;
+    
+    pa_sink_set_module(u->sink, m);
+    pa_sink_set_description(u->sink, t = pa_sprintf_malloc("LADSPA on '%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 = "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);
+
+    return 0;
+
+fail:
+    if (ma)
+        pa_modargs_free(ma);
+
+    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);
+}

commit df1d34753fd906eb5fce53d5639c45e6d3ee0a89
Author: Pierre Ossman <ossman at cendio.se>
Date:   Tue Sep 18 08:57:54 2007 +0000

    NSIG is not defined by neither C99 nor POSIX so we can't rely on it.
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1849 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/core-util.c b/src/pulsecore/core-util.c
index aac7629..6a0bd0a 100644
--- a/src/pulsecore/core-util.c
+++ b/src/pulsecore/core-util.c
@@ -627,9 +627,14 @@ PA_STATIC_TLS_DECLARE(signame, pa_xfree);
 const char *pa_sig2str(int sig) {
     char *t;
 
-    if (sig <= 0 || sig >= _NSIG)
+    if (sig <= 0)
         goto fail;
-    
+
+#ifdef NSIG
+	if (sig >= NSIG)
+		goto fail;
+#endif
+
 #ifdef HAVE_SIG2STR
     {
         char buf[SIG2STR_MAX];

commit 31dfb317fa0693ad41172befe2360f346d5b9093
Author: Pierre Ossman <ossman at cendio.se>
Date:   Tue Sep 18 10:36:17 2007 +0000

    Make sure the header file is only included on linux (as this is a linux-only
    feature).
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1850 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/utils/pasuspender.c b/src/utils/pasuspender.c
index a546f9a..ad86b94 100644
--- a/src/utils/pasuspender.c
+++ b/src/utils/pasuspender.c
@@ -25,7 +25,6 @@
 #include <config.h>
 #endif
 
-#include <sys/prctl.h>
 #include <sys/types.h>
 #include <sys/wait.h>
 
@@ -41,6 +40,10 @@
 
 #include <sndfile.h>
 
+#ifdef __linux__
+#include <sys/prctl.h>
+#endif
+
 #include <pulse/pulseaudio.h>
 #include <pulsecore/macro.h>
 

commit 03d98639808805d13dbe8915f30dd935d1a11991
Author: Pierre Ossman <ossman at cendio.se>
Date:   Tue Sep 18 10:38:07 2007 +0000

    Emulate lrintf with simple truncation if it isn't available.
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1851 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/configure.ac b/configure.ac
index 5b6c647..5250804 100644
--- a/configure.ac
+++ b/configure.ac
@@ -266,6 +266,9 @@ AC_CHECK_FUNCS([getopt_long], [], [AC_CHECK_LIB([iberty], [getopt_long])])
 
 #### Check for functions ####
 
+# ISO
+AC_CHECK_FUNCS([lrintf])
+
 # POSIX
 AC_FUNC_FORK
 AC_FUNC_GETGROUPS
diff --git a/src/pulsecore/ffmpeg/resample2.c b/src/pulsecore/ffmpeg/resample2.c
index da1443d..dfbd528 100644
--- a/src/pulsecore/ffmpeg/resample2.c
+++ b/src/pulsecore/ffmpeg/resample2.c
@@ -86,6 +86,13 @@ static double bessel(double x){
     return v;
 }
 
+/*
+ * crude lrintf for non-C99 systems.
+ */
+#ifndef HAVE_LFRINTF
+#define lrintf(x) ((long int)(x))
+#endif
+
 /**
  * builds a polyphase filterbank.
  * @param factor resampling factor

commit aff22cfc6276ad33f793081cf4e8bb09cec95aa6
Author: Pierre Ossman <ossman at cendio.se>
Date:   Tue Sep 18 10:45:54 2007 +0000

    NSIG seems to be more common than _NSIG.
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1852 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/tests/sig2str-test.c b/src/tests/sig2str-test.c
index b3cc99d..e8f3629 100644
--- a/src/tests/sig2str-test.c
+++ b/src/tests/sig2str-test.c
@@ -32,7 +32,7 @@
 int main(int argc, char *argv[]) {
     int sig;
     
-    for (sig = -1; sig < _NSIG+1; sig++)
+    for (sig = -1; sig <= NSIG; sig++)
         printf("%i = %s\n", sig, pa_sig2str(sig));
 
     return 0;

commit 4ed41f3dab352757513cb8f5c49485de4bec6d6d
Author: Pierre Ossman <ossman at cendio.se>
Date:   Tue Sep 18 10:47:03 2007 +0000

    strtof() is a rather recent addition to C. Fall back to strtod() if it isn't
    available.
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1853 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/configure.ac b/configure.ac
index 5250804..d03774e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -267,7 +267,7 @@ AC_CHECK_FUNCS([getopt_long], [], [AC_CHECK_LIB([iberty], [getopt_long])])
 #### Check for functions ####
 
 # ISO
-AC_CHECK_FUNCS([lrintf])
+AC_CHECK_FUNCS([lrintf strtof])
 
 # POSIX
 AC_FUNC_FORK
diff --git a/src/pulsecore/core-util.c b/src/pulsecore/core-util.c
index 6a0bd0a..afd89ba 100644
--- a/src/pulsecore/core-util.c
+++ b/src/pulsecore/core-util.c
@@ -1300,7 +1300,11 @@ int pa_atof(const char *s, float *ret_f) {
 #endif
     {
         errno = 0;
+#ifdef HAVE_STRTOF
         f = strtof(s, &x);
+#else
+        f = strtod(s, &x);
+#endif
     }
 
     if (!x || *x || errno != 0)

commit 08d4b237a32f060c173b5bdd9ed04d6541f61971
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Sep 18 12:53:42 2007 +0000

    actually close the alsa device before we try to reopen it as plughw
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1854 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-alsa-sink.c b/src/modules/module-alsa-sink.c
index 84f1d4e..108ed90 100644
--- a/src/modules/module-alsa-sink.c
+++ b/src/modules/module-alsa-sink.c
@@ -759,6 +759,9 @@ int pa__init(pa_module*m) {
                     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;
                 }
             }

commit a558e9312e440bc674fdda627edb31dd989c38a5
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Sep 18 17:41:51 2007 +0000

    port module-rtp-send.c to lock-free core
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1855 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/Makefile.am b/src/Makefile.am
index c564ff3..3e4acd5 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -947,11 +947,11 @@ modlibexec_LTLIBRARIES += \
 #		module-esound-sink.la
 
 # See comment at librtp.la above
-#if !OS_IS_WIN32
-#modlibexec_LTLIBRARIES += \
-#		module-rtp-send.la \
-#		module-rtp-recv.la
-#endif
+if !OS_IS_WIN32
+modlibexec_LTLIBRARIES += \
+		module-rtp-send.la \
+		module-rtp-recv.la
+endif
 
 if HAVE_AF_UNIX
 modlibexec_LTLIBRARIES += \
@@ -1342,15 +1342,15 @@ 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_CFLAGS = $(AM_CFLAGS)
-
-#module_rtp_recv_la_SOURCES = modules/rtp/module-rtp-recv.c
-#module_rtp_recv_la_LDFLAGS = -module -avoid-version
-#module_rtp_recv_la_LIBADD = $(AM_LIBADD) libpulsecore.la librtp.la
-#module_rtp_recv_la_CFLAGS = $(AM_CFLAGS)
+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_CFLAGS = $(AM_CFLAGS)
+
+module_rtp_recv_la_SOURCES = modules/rtp/module-rtp-recv.c
+module_rtp_recv_la_LDFLAGS = -module -avoid-version
+module_rtp_recv_la_LIBADD = $(AM_LIBADD) libpulsecore.la librtp.la
+module_rtp_recv_la_CFLAGS = $(AM_CFLAGS)
 
 # JACK
 
diff --git a/src/modules/rtp/module-rtp-recv.c b/src/modules/rtp/module-rtp-recv.c
index 62ef561..f5e9c3c 100644
--- a/src/modules/rtp/module-rtp-recv.c
+++ b/src/modules/rtp/module-rtp-recv.c
@@ -24,7 +24,6 @@
 #include <config.h>
 #endif
 
-#include <assert.h>
 #include <stdio.h>
 #include <sys/socket.h>
 #include <netinet/in.h>
@@ -47,6 +46,10 @@
 #include <pulsecore/modargs.h>
 #include <pulsecore/namereg.h>
 #include <pulsecore/sample-util.h>
+#include <pulsecore/macro.h>
+#include <pulsecore/atomic.h>
+#include <pulsecore/rtclock.h>
+#include <pulsecore/atomic.h>
 
 #include "module-rtp-recv-symdef.h"
 
@@ -66,7 +69,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 +79,113 @@ 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 timespec now;
+    struct session *s;
 
-    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;
+    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 +211,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);
 
-    assert(m);
-    assert(t);
-    assert(tv);
-    assert(s);
+    p = pa_rtpoll_item_get_pollfd(s->rtpoll_item, NULL);
+    p->fd = s->rtp_context.fd;
+    p->events = POLLIN;
+    p->revents = 0;
+
+    pa_rtpoll_item_set_work_callback(s->rtpoll_item, rtpoll_work_cb);
+    pa_rtpoll_item_set_userdata(s->rtpoll_item, s);
+}
+
+/* Called from I/O thread context */
+static void sink_input_detach(pa_sink_input *i) {
+    struct session *s;
+    pa_sink_input_assert_ref(i);
+    pa_assert_se(s = i->userdata);
 
-    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 +299,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 timespec 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 +343,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,53 +376,43 @@ 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_memblockq_free(s->memblockq);
     pa_sdp_info_destroy(&s->sdp_info);
     pa_rtp_context_destroy(&s->rtp_context);
 
-    assert(s->userdata->n_sessions >= 1);
+    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_xfree(s);
 }
@@ -387,11 +423,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 +438,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 +448,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 timespec 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 timespec now;
+    struct timeval tv;
+
+    pa_assert(m);
+    pa_assert(t);
+    pa_assert(ptv);
+    pa_assert(s);
+
+    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 +497,9 @@ int pa__init(pa_core *c, pa_module*m) {
     socklen_t salen;
     const char *sap_address;
     int fd = -1;
-
-    assert(c);
-    assert(m);
+    struct timeval tv;
+    
+    pa_assert(m);
 
     if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
         pa_log("failed to parse module arguments");
@@ -454,7 +519,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,16 +529,19 @@ 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);
 
     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);
 
     return 0;
@@ -483,27 +551,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);
diff --git a/src/modules/rtp/module-rtp-send.c b/src/modules/rtp/module-rtp-send.c
index 8c9e5f2..7e9168e 100644
--- a/src/modules/rtp/module-rtp-send.c
+++ b/src/modules/rtp/module-rtp-send.c
@@ -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,8 @@
 #include <pulsecore/core-util.h>
 #include <pulsecore/modargs.h>
 #include <pulsecore/namereg.h>
+#include <pulsecore/sample-util.h>
+#include <pulsecore/macro.h>
 
 #include "module-rtp-send-symdef.h"
 
@@ -74,7 +75,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 +91,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 +102,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 +184,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 +205,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 +219,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 +233,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 +248,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 +278,9 @@ int pa__init(pa_core *c, pa_module*m) {
         goto fail;
     }
 
+    /* If the socket queue is full, let's drop packets */
+    pa_make_nonblock_fd(fd);
+
     pa_source_output_new_data_init(&data);
     data.name = "RTP Monitor Stream";
     data.driver = __FILE__;
@@ -276,21 +289,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 +317,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,18 +328,20 @@ 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);
 
     return 0;
@@ -338,31 +351,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 +384,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);
 }
diff --git a/src/modules/rtp/rtp.c b/src/modules/rtp/rtp.c
index 31dec65..e2496c7 100644
--- a/src/modules/rtp/rtp.c
+++ b/src/modules/rtp/rtp.c
@@ -25,7 +25,6 @@
 #include <config.h>
 #endif
 
-#include <assert.h>
 #include <fcntl.h>
 #include <stdlib.h>
 #include <string.h>
@@ -40,12 +39,14 @@
 
 #include <pulsecore/core-error.h>
 #include <pulsecore/log.h>
+#include <pulsecore/macro.h>
+#include <pulsecore/core-util.h>
 
 #include "rtp.h"
 
 pa_rtp_context* pa_rtp_context_init_send(pa_rtp_context *c, int fd, uint32_t ssrc, uint8_t payload, size_t frame_size) {
-    assert(c);
-    assert(fd >= 0);
+    pa_assert(c);
+    pa_assert(fd >= 0);
 
     c->fd = fd;
     c->sequence = (uint16_t) (rand()*rand());
@@ -63,11 +64,11 @@ int pa_rtp_send(pa_rtp_context *c, size_t size, pa_memblockq *q) {
     struct iovec iov[MAX_IOVECS];
     pa_memblock* mb[MAX_IOVECS];
     int iov_idx = 1;
-    size_t n = 0, skip = 0;
+    size_t n = 0;
 
-    assert(c);
-    assert(size > 0);
-    assert(q);
+    pa_assert(c);
+    pa_assert(size > 0);
+    pa_assert(q);
 
     if (pa_memblockq_get_length(q) < size)
         return 0;
@@ -76,24 +77,26 @@ int pa_rtp_send(pa_rtp_context *c, size_t size, pa_memblockq *q) {
         int r;
         pa_memchunk chunk;
 
+        pa_memchunk_reset(&chunk);
+        
         if ((r = pa_memblockq_peek(q, &chunk)) >= 0) {
 
             size_t k = n + chunk.length > size ? size - n : chunk.length;
 
-            if (chunk.memblock) {
-                iov[iov_idx].iov_base = (void*)((uint8_t*) pa_memblock_acquire(chunk.memblock) + chunk.index);
-                iov[iov_idx].iov_len = k;
-                mb[iov_idx] = chunk.memblock;
-                iov_idx ++;
-
-                n += k;
-            }
-
-            skip += k;
+            pa_assert(chunk.memblock);
+            
+            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 ++;
+            
+            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;
@@ -125,10 +128,10 @@ int pa_rtp_send(pa_rtp_context *c, size_t size, pa_memblockq *q) {
             } 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;
             }
@@ -137,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;
         }
     }
@@ -146,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;
@@ -161,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;
 
     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;
     }
 
@@ -188,12 +190,14 @@ int pa_rtp_recv(pa_rtp_context *c, pa_memchunk *chunk, pa_mempool *pool) {
     m.msg_flags = 0;
 
     if ((r = recvmsg(c->fd, &m, 0)) != size) {
-        pa_log("recvmsg() failed: %s", r < 0 ? pa_cstrerror(errno) : "size mismatch");
+        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;
     }
 
@@ -206,17 +210,17 @@ int pa_rtp_recv(pa_rtp_context *c, pa_memchunk *chunk, pa_mempool *pool) {
     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;
     }
 
@@ -225,7 +229,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;
     }
 
@@ -233,7 +237,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;
     }
 
@@ -249,7 +253,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;
@@ -264,7 +268,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:
@@ -299,17 +303,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;
@@ -322,9 +326,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) {
@@ -343,7 +347,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;
diff --git a/src/modules/rtp/sap.c b/src/modules/rtp/sap.c
index 8242180..ed7eb0b 100644
--- a/src/modules/rtp/sap.c
+++ b/src/modules/rtp/sap.c
@@ -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;
     }
 
diff --git a/src/modules/rtp/sdp.c b/src/modules/rtp/sdp.c
index 8b0bd53..983e5c9 100644
--- a/src/modules/rtp/sdp.c
+++ b/src/modules/rtp/sdp.c
@@ -25,7 +25,6 @@
 #include <config.h>
 #endif
 
-#include <assert.h>
 #include <time.h>
 #include <stdlib.h>
 #include <sys/types.h>
@@ -38,33 +37,29 @@
 
 #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 +81,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 +118,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 +253,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);
diff --git a/src/pulsecore/rtpoll.h b/src/pulsecore/rtpoll.h
index 9a368d3..ee6cc06 100644
--- a/src/pulsecore/rtpoll.h
+++ b/src/pulsecore/rtpoll.h
@@ -103,7 +103,6 @@ void pa_rtpoll_item_set_before_callback(pa_rtpoll_item *i, int (*before_cb)(pa_r
  * 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);
 

commit ca717643ee768307475fc36ea29d920a13db0a8e
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Sep 18 19:51:26 2007 +0000

    If PTHREAD_PRIO_INHERIT mutexes are not available fall back to normal mutexes
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1856 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/mutex-posix.c b/src/pulsecore/mutex-posix.c
index 19e095b..805f11d 100644
--- a/src/pulsecore/mutex-posix.c
+++ b/src/pulsecore/mutex-posix.c
@@ -26,9 +26,12 @@
 #endif
 
 #include <pthread.h>
+#include <errno.h>
 
 #include <pulse/xmalloc.h>
 #include <pulsecore/macro.h>
+#include <pulsecore/log.h>
+#include <pulsecore/core-error.h>
 
 #include "mutex.h"
 
@@ -43,19 +46,36 @@ struct pa_cond {
 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)
         pa_assert_se(pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE) == 0);
 
 #ifdef HAVE_PTHREAD_PRIO_INHERIT
     if (inherit_priority)
-        pthread_mutexattr_setprotocol(&attr, PTHREAD_PRIO_INHERIT);
+        pa_assert_se(pthread_mutexattr_setprotocol(&attr, PTHREAD_PRIO_INHERIT) == 0);
 #endif
 
     m = pa_xnew(pa_mutex, 1);
+
+#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;
 }
 

commit 8fdf054e686b7bc488a510029a7b216c6aeaa50b
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Sep 18 19:52:20 2007 +0000

    make sure we don't call pa_source_post() for a monitor source after it was unlinked
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1857 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c
index 98f117c..886d744 100644
--- a/src/pulsecore/sink.c
+++ b/src/pulsecore/sink.c
@@ -216,11 +216,11 @@ void pa_sink_unlink(pa_sink* s) {
         j = i;
     }
 
+    sink_set_state(s, PA_SINK_UNLINKED);
+
     if (s->monitor_source)
         pa_source_unlink(s->monitor_source);
 
-    sink_set_state(s, PA_SINK_UNLINKED);
-
     s->get_latency = NULL;
     s->get_volume = NULL;
     s->set_volume = NULL;

commit eb23601bb7771bce74e6b87a222b174660e86a0d
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Sep 18 19:52:45 2007 +0000

    bug fixes for module-rtp-recv
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1858 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/rtp/module-rtp-recv.c b/src/modules/rtp/module-rtp-recv.c
index f5e9c3c..62be53f 100644
--- a/src/modules/rtp/module-rtp-recv.c
+++ b/src/modules/rtp/module-rtp-recv.c
@@ -163,9 +163,22 @@ static int rtpoll_work_cb(pa_rtpoll_item *i) {
     int64_t k, j, delta;
     struct timespec now;
     struct session *s;
-
+    struct pollfd *p;
+    
     pa_assert_se(s = pa_rtpoll_item_get_userdata(i));
 
+    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;
 
@@ -405,14 +418,14 @@ static void session_free(struct session *s) {
     pa_sink_input_unlink(s->sink_input);
     pa_sink_input_unref(s->sink_input);
 
-    pa_memblockq_free(s->memblockq);
-    pa_sdp_info_destroy(&s->sdp_info);
-    pa_rtp_context_destroy(&s->rtp_context);
-
     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);
 
     pa_xfree(s);
 }
@@ -466,7 +479,7 @@ static void check_death_event_cb(pa_mainloop_api *m, pa_time_event *t, const str
     pa_assert(m);
     pa_assert(t);
     pa_assert(ptv);
-    pa_assert(s);
+    pa_assert(u);
 
     pa_rtclock_get(&now);
 
@@ -530,14 +543,14 @@ int pa__init(pa_module*m) {
     m->userdata = u;
     u->module = m;
     u->sink_name = pa_xstrdup(pa_modargs_get_value(ma, "sink", NULL));
-    u->n_sessions = 0;
 
     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);

commit 6b2fd2328ab715fb5ce4544fc431e545747ca95f
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Sep 18 21:31:21 2007 +0000

    add two missing header file inclusions
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1859 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/rtp/sdp.c b/src/modules/rtp/sdp.c
index 983e5c9..50ac157 100644
--- a/src/modules/rtp/sdp.c
+++ b/src/modules/rtp/sdp.c
@@ -34,6 +34,7 @@
 #include <string.h>
 
 #include <pulse/xmalloc.h>
+#include <pulse/util.h>
 
 #include <pulsecore/core-util.h>
 #include <pulsecore/log.h>
diff --git a/src/pulsecore/rtpoll.c b/src/pulsecore/rtpoll.c
index e7ccd90..e72bf3f 100644
--- a/src/pulsecore/rtpoll.c
+++ b/src/pulsecore/rtpoll.c
@@ -41,6 +41,7 @@
 #include <pulsecore/llist.h>
 #include <pulsecore/rtsig.h>
 #include <pulsecore/flist.h>
+#include <pulsecore/core-util.h>
 
 #include "rtpoll.h"
 

commit f44ddd1052af8026ce3bcb91b377d980a0913445
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Sep 18 22:24:45 2007 +0000

    add new pa_socket_udp_low_delay() API
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1860 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/socket-util.c b/src/pulsecore/socket-util.c
index 4026b9b..cd912bf 100644
--- a/src/pulsecore/socket-util.c
+++ b/src/pulsecore/socket-util.c
@@ -144,13 +144,16 @@ void pa_socket_peer_to_string(int fd, char *c, size_t l) {
 }
 
 int pa_socket_low_delay(int fd) {
+    
 #ifdef SO_PRIORITY
     int priority;
     pa_assert(fd >= 0);
 
     priority = 7;
-    if (setsockopt(fd, SOL_SOCKET, SO_PRIORITY, (void*)&priority, sizeof(priority)) < 0)
+    if (setsockopt(fd, SOL_SOCKET, SO_PRIORITY, (void*)&priority, sizeof(priority)) < 0) {
+        pa_log_warn("SO_PRIORITY failed: %s", pa_cstrerror(errno));
         return -1;
+    }
 #endif
 
     return 0;
@@ -172,9 +175,37 @@ int pa_socket_tcp_low_delay(int fd) {
 #else
     if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (void*)&on, sizeof(on)) < 0)
 #endif
+    {
+        pa_log_warn("TCP_NODELAY failed: %s", pa_cstrerror(errno));
+        ret = -1;
+    }
+#endif
+
+#if defined(IPTOS_LOWDELAY) && defined(IP_TOS) && (defined(SOL_IP) || defined(IPPROTO_IP))
+    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));
         ret = -1;
+    }
 #endif
 
+    return ret;
+}
+
+int pa_socket_udp_low_delay(int fd) {
+    int ret, tos;
+
+    pa_assert(fd >= 0);
+
+    ret = pa_socket_low_delay(fd);
+
+    tos = 0;
+
 #if defined(IPTOS_LOWDELAY) && defined(IP_TOS) && (defined(SOL_IP) || defined(IPPROTO_IP))
     tos = IPTOS_LOWDELAY;
 #ifdef SOL_IP
@@ -182,7 +213,10 @@ int pa_socket_tcp_low_delay(int fd) {
 #else
     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;
diff --git a/src/pulsecore/socket-util.h b/src/pulsecore/socket-util.h
index 616c40a..abe9ce1 100644
--- a/src/pulsecore/socket-util.h
+++ b/src/pulsecore/socket-util.h
@@ -31,6 +31,7 @@ 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);
+int pa_socket_udp_low_delay(int fd);
 
 int pa_socket_set_sndbuf(int fd, size_t l);
 int pa_socket_set_rcvbuf(int fd, size_t l);

commit ef8df4104294a58af643b908077a90c78c4055da
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Sep 18 22:25:18 2007 +0000

    make rtp send socket low delay
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1861 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/Makefile.am b/src/Makefile.am
index 3e4acd5..21136aa 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1344,7 +1344,7 @@ 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
diff --git a/src/modules/rtp/module-rtp-send.c b/src/modules/rtp/module-rtp-send.c
index 7e9168e..8fac44f 100644
--- a/src/modules/rtp/module-rtp-send.c
+++ b/src/modules/rtp/module-rtp-send.c
@@ -49,6 +49,7 @@
 #include <pulsecore/namereg.h>
 #include <pulsecore/sample-util.h>
 #include <pulsecore/macro.h>
+#include <pulsecore/socket-util.h>
 
 #include "module-rtp-send-symdef.h"
 
@@ -280,6 +281,7 @@ int pa__init(pa_module*m) {
 
     /* If the socket queue is full, let's drop packets */
     pa_make_nonblock_fd(fd);
+    pa_socket_udp_low_delay(fd);
 
     pa_source_output_new_data_init(&data);
     data.name = "RTP Monitor Stream";

commit b3093d84055ddc6cf26853a676f04692f748049b
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Sep 18 22:29:24 2007 +0000

    lower SO_PRIORITY priority to 6, since this is the best we get without being root
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1862 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/socket-util.c b/src/pulsecore/socket-util.c
index cd912bf..b7361e9 100644
--- a/src/pulsecore/socket-util.c
+++ b/src/pulsecore/socket-util.c
@@ -149,7 +149,7 @@ int pa_socket_low_delay(int fd) {
     int priority;
     pa_assert(fd >= 0);
 
-    priority = 7;
+    priority = 6;
     if (setsockopt(fd, SOL_SOCKET, SO_PRIORITY, (void*)&priority, sizeof(priority)) < 0) {
         pa_log_warn("SO_PRIORITY failed: %s", pa_cstrerror(errno));
         return -1;

commit 1fd9afdf7d4a46ec324d002b3f23c23eebff1795
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Sep 18 23:21:06 2007 +0000

    make use of pa_bool_t on a few places where applicable; really start work_cb
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1863 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/rtpoll.c b/src/pulsecore/rtpoll.c
index e72bf3f..1b52385 100644
--- a/src/pulsecore/rtpoll.c
+++ b/src/pulsecore/rtpoll.c
@@ -49,19 +49,19 @@ struct pa_rtpoll {
     struct pollfd *pollfd, *pollfd2;
     unsigned n_pollfd_alloc, n_pollfd_used;
 
-    int timer_enabled;
+    pa_bool_t timer_enabled;
     struct timespec next_elapse;
     pa_usec_t period;
 
-    int scan_for_dead;
-    int running, installed, rebuild_needed, quit;
+    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__
-    int dont_use_ppoll;
+    pa_bool_t dont_use_ppoll;
 #endif    
 #endif
     
@@ -70,7 +70,7 @@ struct pa_rtpoll {
 
 struct pa_rtpoll_item {
     pa_rtpoll *rtpoll;
-    int dead;
+    pa_bool_t dead;
 
     pa_rtpoll_priority_t priority;
 
@@ -98,9 +98,8 @@ pa_rtpoll *pa_rtpoll_new(void) {
 
 #ifdef __linux__
     /* ppoll is broken on Linux < 2.6.16 */
+    p->dont_use_ppoll = FALSE;
     
-    p->dont_use_ppoll = 0;
-
     {
         struct utsname u;
         unsigned major, minor, micro;
@@ -112,7 +111,7 @@ pa_rtpoll *pa_rtpoll_new(void) {
             (major == 2 && minor < 6) ||
             (major == 2 && minor == 6 && micro < 16))
 
-            p->dont_use_ppoll = 1;
+            p->dont_use_ppoll = TRUE;
     }
 
 #endif
@@ -130,13 +129,13 @@ pa_rtpoll *pa_rtpoll_new(void) {
 
     p->period = 0;
     memset(&p->next_elapse, 0, sizeof(p->next_elapse));
-    p->timer_enabled = 0;
+    p->timer_enabled = FALSE;
 
-    p->running = 0;
-    p->installed = 0;
-    p->scan_for_dead = 0;
-    p->rebuild_needed = 0;
-    p->quit = 0;
+    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);
 
@@ -189,7 +188,7 @@ static void rtpoll_rebuild(pa_rtpoll *p) {
     
     pa_assert(p);
 
-    p->rebuild_needed = 0;
+    p->rebuild_needed = FALSE;
 
     if (p->n_pollfd_used > p->n_pollfd_alloc) {
         /* Hmm, we have to allocate some more space */
@@ -241,7 +240,7 @@ static void rtpoll_item_destroy(pa_rtpoll_item *i) {
     if (pa_flist_push(PA_STATIC_FLIST_GET(items), i) < 0)
         pa_xfree(i);
 
-    p->rebuild_needed = 1;
+    p->rebuild_needed = TRUE;
 }
 
 void pa_rtpoll_free(pa_rtpoll *p) {
@@ -288,7 +287,7 @@ static void reset_all_revents(pa_rtpoll *p) {
     }
 }
 
-int pa_rtpoll_run(pa_rtpoll *p, int wait) {
+int pa_rtpoll_run(pa_rtpoll *p, pa_bool_t wait) {
     pa_rtpoll_item *i;
     int r = 0;
     struct timespec timeout;
@@ -297,7 +296,7 @@ int pa_rtpoll_run(pa_rtpoll *p, int wait) {
     pa_assert(!p->running);
     pa_assert(p->installed);
     
-    p->running = 1;
+    p->running = TRUE;
 
     /* First, let's do some work */
     for (i = p->items; i && i->priority < PA_RTPOLL_NEVER; i = i->next) {
@@ -306,7 +305,7 @@ int pa_rtpoll_run(pa_rtpoll *p, int wait) {
         if (i->dead)
             continue;
         
-        if (!i->before_cb)
+        if (!i->work_cb)
             continue;
 
         if (p->quit)
@@ -422,12 +421,12 @@ int pa_rtpoll_run(pa_rtpoll *p, int wait) {
 
 finish:
 
-    p->running = 0;
+    p->running = FALSE;
         
     if (p->scan_for_dead) {
         pa_rtpoll_item *n;
 
-        p->scan_for_dead = 0;
+        p->scan_for_dead = FALSE;
         
         for (i = p->items; i; i = n) {
             n = i->next;
@@ -495,7 +494,7 @@ void pa_rtpoll_set_timer_absolute(pa_rtpoll *p, const struct timespec *ts) {
     
     p->next_elapse = *ts;
     p->period = 0;
-    p->timer_enabled = 1;
+    p->timer_enabled = TRUE;
     
     update_timer(p);
 }
@@ -506,7 +505,7 @@ void pa_rtpoll_set_timer_periodic(pa_rtpoll *p, pa_usec_t usec) {
     p->period = usec;
     pa_rtclock_get(&p->next_elapse);
     pa_timespec_add(&p->next_elapse, usec);
-    p->timer_enabled = 1;
+    p->timer_enabled = TRUE;
 
     update_timer(p);
 }
@@ -517,7 +516,7 @@ void pa_rtpoll_set_timer_relative(pa_rtpoll *p, pa_usec_t usec) {
     p->period = 0;
     pa_rtclock_get(&p->next_elapse);
     pa_timespec_add(&p->next_elapse, usec);
-    p->timer_enabled = 1;
+    p->timer_enabled = TRUE;
 
     update_timer(p);
 }
@@ -527,7 +526,7 @@ void pa_rtpoll_set_timer_disabled(pa_rtpoll *p) {
 
     p->period = 0;
     memset(&p->next_elapse, 0, sizeof(p->next_elapse));
-    p->timer_enabled = 0;
+    p->timer_enabled = FALSE;
 
     update_timer(p);
 }
@@ -541,7 +540,7 @@ pa_rtpoll_item *pa_rtpoll_item_new(pa_rtpoll *p, pa_rtpoll_priority_t prio, unsi
         i = pa_xnew(pa_rtpoll_item, 1);
 
     i->rtpoll = p;
-    i->dead = 0;
+    i->dead = FALSE;
     i->n_pollfd = n_fds;
     i->pollfd = NULL;
     i->priority = prio;
@@ -572,8 +571,8 @@ void pa_rtpoll_item_free(pa_rtpoll_item *i) {
     pa_assert(i);
 
     if (i->rtpoll->running) {
-        i->dead = 1;
-        i->rtpoll->scan_for_dead = 1;
+        i->dead = TRUE;
+        i->rtpoll->scan_for_dead = TRUE;
         return;
     }
 
@@ -728,5 +727,5 @@ pa_rtpoll_item *pa_rtpoll_item_new_asyncmsgq(pa_rtpoll *p, pa_rtpoll_priority_t
 void pa_rtpoll_quit(pa_rtpoll *p) {
     pa_assert(p);
 
-    p->quit = 1;
+    p->quit = TRUE;
 }
diff --git a/src/pulsecore/rtpoll.h b/src/pulsecore/rtpoll.h
index ee6cc06..a1242b3 100644
--- a/src/pulsecore/rtpoll.h
+++ b/src/pulsecore/rtpoll.h
@@ -31,6 +31,7 @@
 #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
@@ -72,7 +73,7 @@ void pa_rtpoll_install(pa_rtpoll *p);
  * 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, int wait);
+int pa_rtpoll_run(pa_rtpoll *f, pa_bool_t wait);
 
 void pa_rtpoll_set_timer_absolute(pa_rtpoll *p, const struct timespec *ts);
 void pa_rtpoll_set_timer_periodic(pa_rtpoll *p, pa_usec_t usec);

commit 781cf499cf1cc36bd4774ff7e4a09f6db4e65038
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Sep 18 23:24:13 2007 +0000

    properly release memblock always abd as soon as possible
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1864 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/rtp/rtp.c b/src/modules/rtp/rtp.c
index e2496c7..60df727 100644
--- a/src/modules/rtp/rtp.c
+++ b/src/modules/rtp/rtp.c
@@ -166,7 +166,7 @@ int pa_rtp_recv(pa_rtp_context *c, pa_memchunk *chunk, pa_mempool *pool) {
     pa_assert(c);
     pa_assert(chunk);
 
-    chunk->memblock = NULL;
+    pa_memchunk_reset(chunk);
 
     if (ioctl(c->fd, FIONREAD, &size) < 0) {
         pa_log_warn("FIONREAD failed: %s", pa_cstrerror(errno));
@@ -189,7 +189,10 @@ 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) {
+    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");
         
@@ -244,10 +247,8 @@ int pa_rtp_recv(pa_rtp_context *c, pa_memchunk *chunk, pa_mempool *pool) {
     return 0;
 
 fail:
-    if (chunk->memblock) {
-        pa_memblock_release(chunk->memblock);
+    if (chunk->memblock)
         pa_memblock_unref(chunk->memblock);
-    }
 
     return -1;
 }

commit ac66b6af0837ae3fa1b77c6f335951574c7da150
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Sep 18 23:35:05 2007 +0000

    fall back to plughw:, if hw: doesn't work, in the alsa source, too
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1865 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-alsa-sink.c b/src/modules/module-alsa-sink.c
index 108ed90..4f2e570 100644
--- a/src/modules/module-alsa-sink.c
+++ b/src/modules/module-alsa-sink.c
@@ -774,6 +774,8 @@ int pa__init(pa_module*m) {
         break;
     }
     
+    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;
@@ -787,8 +789,6 @@ int pa__init(pa_module*m) {
         goto fail;
     }
 
-    u->device_name = dev;
-        
     if ((err = pa_alsa_set_sw_params(u->pcm_handle)) < 0) {
         pa_log("Failed to set software parameters: %s", snd_strerror(err));
         goto fail;
diff --git a/src/modules/module-alsa-source.c b/src/modules/module-alsa-source.c
index 870f204..82f66bb 100644
--- a/src/modules/module-alsa-source.c
+++ b/src/modules/module-alsa-source.c
@@ -660,7 +660,7 @@ int pa__init(pa_module*m) {
     
     pa_modargs *ma = NULL;
     struct userdata *u = NULL;
-    const char *dev;
+    char *dev;
     pa_sample_spec ss;
     pa_channel_map map;
     unsigned nfrags, frag_size;
@@ -718,24 +718,45 @@ int pa__init(pa_module*m) {
     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;
-    }
 
-    u->device_name = pa_xstrdup(dev);
+    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;
+        }
 
-    if ((err = snd_pcm_info(u->pcm_handle, pcm_info)) < 0) {
-        pa_log("Error fetching PCM info: %s", snd_strerror(err));
-        goto fail;
-    }
+        b = use_mmap;
+        if ((err = pa_alsa_set_hw_params(u->pcm_handle, &ss, &nfrags, &period_size, &b)) < 0) {
 
-    b = 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 (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;
     }
 
+    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;
@@ -744,6 +765,11 @@ int pa__init(pa_module*m) {
     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_sw_params(u->pcm_handle)) < 0) {
         pa_log("Failed to set software parameters: %s", snd_strerror(err));
         goto fail;

commit 0fcad977828665e46849cc4efe758ebc42450a66
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Sep 19 00:08:40 2007 +0000

    copy free_cb into a temporary variable first, to avoid compiler warning
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1866 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/thread.h b/src/pulsecore/thread.h
index 0c6c859..6aaf8c8 100644
--- a/src/pulsecore/thread.h
+++ b/src/pulsecore/thread.h
@@ -70,9 +70,10 @@ void *pa_tls_set(pa_tls *t, void *userdata);
     }                                                                   \
     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) {                                                  \
+        if (_free_cb) {                                                 \
             void *p;                                                    \
             if ((p = pa_tls_get(name##_tls.tls)))                       \
                 free_cb(p);                                             \

commit 75f799a3d885a5af42c5cb3af49da1299b8425cc
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Sep 19 00:12:01 2007 +0000

    make O_CLOEXEC, O_NONBLOCK and socket low latency fd ops more uniform: always return void, name them similarly, only pass a single fd
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1867 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/daemon/cpulimit.c b/src/daemon/cpulimit.c
index 0fe11ea..a61f43e 100644
--- a/src/daemon/cpulimit.c
+++ b/src/daemon/cpulimit.c
@@ -184,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);
diff --git a/src/modules/module-pipe-sink.c b/src/modules/module-pipe-sink.c
index a1bdc8f..edacf04 100644
--- a/src/modules/module-pipe-sink.c
+++ b/src/modules/module-pipe-sink.c
@@ -236,8 +236,8 @@ int pa__init(pa_module*m) {
         goto fail;
     }
 
-    pa_fd_set_cloexec(u->fd, 1);
-    pa_make_nonblock_fd(u->fd);
+    pa_make_fd_cloexec(u->fd);
+    pa_make_fd_nonblock(u->fd);
 
     if (fstat(u->fd, &st) < 0) {
         pa_log("fstat('%s'): %s", u->filename, pa_cstrerror(errno));
diff --git a/src/modules/module-pipe-source.c b/src/modules/module-pipe-source.c
index 382da8f..2313df6 100644
--- a/src/modules/module-pipe-source.c
+++ b/src/modules/module-pipe-source.c
@@ -214,8 +214,8 @@ int pa__init(pa_module*m) {
         goto fail;
     }
 
-    pa_fd_set_cloexec(u->fd, 1);
-    pa_make_nonblock_fd(u->fd);
+    pa_make_fd_cloexec(u->fd);
+    pa_make_fd_nonblock(u->fd);
 
     if (fstat(u->fd, &st) < 0) {
         pa_log("fstat('%s'): %s",u->filename, pa_cstrerror(errno));
diff --git a/src/modules/oss-util.c b/src/modules/oss-util.c
index 3649880..3bef8a3 100644
--- a/src/modules/oss-util.c
+++ b/src/modules/oss-util.c
@@ -141,7 +141,7 @@ success:
 #endif
                  *pcaps & DSP_CAP_TRIGGER ? " TRIGGER" : "");
 
-    pa_fd_set_cloexec(fd, 1);
+    pa_make_fd_cloexec(fd);
 
     return fd;
 
diff --git a/src/modules/rtp/module-rtp-send.c b/src/modules/rtp/module-rtp-send.c
index 8fac44f..f79867c 100644
--- a/src/modules/rtp/module-rtp-send.c
+++ b/src/modules/rtp/module-rtp-send.c
@@ -280,8 +280,10 @@ int pa__init(pa_module*m) {
     }
 
     /* If the socket queue is full, let's drop packets */
-    pa_make_nonblock_fd(fd);
-    pa_socket_udp_low_delay(fd);
+    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";
diff --git a/src/pulse/context.c b/src/pulse/context.c
index a39646d..805cd44 100644
--- a/src/pulse/context.c
+++ b/src/pulse/context.c
@@ -498,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();
diff --git a/src/pulse/mainloop-signal.c b/src/pulse/mainloop-signal.c
index b6414c4..a986b24 100644
--- a/src/pulse/mainloop-signal.c
+++ b/src/pulse/mainloop-signal.c
@@ -123,10 +123,10 @@ int pa_signal_init(pa_mainloop_api *a) {
         return -1;
     }
 
-    pa_make_nonblock_fd(signal_pipe[0]);
-    pa_make_nonblock_fd(signal_pipe[1]);
-    pa_assert_se(pa_fd_set_cloexec(signal_pipe[0], 1) == 0);
-    pa_assert_se(pa_fd_set_cloexec(signal_pipe[1], 1) == 0);
+    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;
 
diff --git a/src/pulse/mainloop.c b/src/pulse/mainloop.c
index c69c665..bab8eb5 100644
--- a/src/pulse/mainloop.c
+++ b/src/pulse/mainloop.c
@@ -457,10 +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_fd_set_cloexec(m->wakeup_pipe[0], 1);
-    pa_fd_set_cloexec(m->wakeup_pipe[1], 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);
diff --git a/src/pulsecore/core-util.c b/src/pulsecore/core-util.c
index afd89ba..5532c40 100644
--- a/src/pulsecore/core-util.c
+++ b/src/pulsecore/core-util.c
@@ -134,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;
     pa_assert(fd >= 0);
 
-    if ((v = fcntl(fd, F_GETFL)) >= 0)
-        if (!(v & O_NONBLOCK))
-            fcntl(fd, F_SETFL, v|O_NONBLOCK);
+    pa_assert_se((v = fcntl(fd, F_GETFL)) >= 0);
+
+    if (!(v & O_NONBLOCK))
+        pa_assert_se(fcntl(fd, F_SETFL, v|O_NONBLOCK) >= 0);
+    
 #elif defined(OS_IS_WIN32)
     u_long arg = 1;
     if (ioctlsocket(fd, FIONBIO, &arg) < 0) {
-        if (WSAGetLastError() == WSAENOTSOCK)
-            pa_log_warn("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("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 */
@@ -552,25 +571,6 @@ void pa_reset_priority(void) {
 #endif
 }
 
-/* Set the FD_CLOEXEC flag for a fd */
-int pa_fd_set_cloexec(int fd, int b) {
-
-#ifdef FD_CLOEXEC
-    int v;
-    pa_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) {
 
@@ -629,12 +629,12 @@ const char *pa_sig2str(int sig) {
 
     if (sig <= 0)
         goto fail;
-
+ 
 #ifdef NSIG
-	if (sig >= NSIG)
-		goto fail;
+    if (sig >= NSIG)
+        goto fail;
 #endif
-
+        
 #ifdef HAVE_SIG2STR
     {
         char buf[SIG2STR_MAX];
diff --git a/src/pulsecore/core-util.h b/src/pulsecore/core-util.h
index b8ef464..44c7574 100644
--- a/src/pulsecore/core-util.h
+++ b/src/pulsecore/core-util.h
@@ -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);
@@ -59,8 +60,6 @@ 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) PA_GCC_PURE;
 
 char *pa_split(const char *c, const char*delimiters, const char **state);
diff --git a/src/pulsecore/fdsem.c b/src/pulsecore/fdsem.c
index 68207a7..c81797e 100644
--- a/src/pulsecore/fdsem.c
+++ b/src/pulsecore/fdsem.c
@@ -54,8 +54,8 @@ pa_fdsem *pa_fdsem_new(void) {
         return NULL;
     }
 
-    pa_fd_set_cloexec(f->fds[0], 1);
-    pa_fd_set_cloexec(f->fds[1], 1);
+    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);
diff --git a/src/pulsecore/iochannel.c b/src/pulsecore/iochannel.c
index 2f586cb..90136fe 100644
--- a/src/pulsecore/iochannel.c
+++ b/src/pulsecore/iochannel.c
@@ -145,17 +145,17 @@ pa_iochannel* pa_iochannel_new(pa_mainloop_api*m, int ifd, int ofd) {
 
     if (ifd == ofd) {
         pa_assert(ifd >= 0);
-        pa_make_nonblock_fd(io->ifd);
+        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);
         }
     }
diff --git a/src/pulsecore/socket-client.c b/src/pulsecore/socket-client.c
index 360a0b4..6748c28 100644
--- a/src/pulsecore/socket-client.c
+++ b/src/pulsecore/socket-client.c
@@ -208,7 +208,7 @@ static int do_connect(pa_socket_client *c, const struct sockaddr *sa, socklen_t
     pa_assert(sa);
     pa_assert(len > 0);
 
-    pa_make_nonblock_fd(c->fd);
+    pa_make_fd_nonblock(c->fd);
 
     if ((r = connect(c->fd, sa, len)) < 0) {
 #ifdef OS_IS_WIN32
@@ -293,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;
diff --git a/src/pulsecore/socket-server.c b/src/pulsecore/socket-server.c
index 502005d..e0d2f16 100644
--- a/src/pulsecore/socket-server.c
+++ b/src/pulsecore/socket-server.c
@@ -111,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);
@@ -137,9 +137,9 @@ 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);
 
     pa_assert_se(io = pa_iochannel_new(s->mainloop, nfd, nfd));
     s->on_connection(s, io, s->userdata);
@@ -193,13 +193,13 @@ pa_socket_server* pa_socket_server_new_unix(pa_mainloop_api *m, const char *file
         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));
@@ -253,14 +253,14 @@ pa_socket_server* pa_socket_server_new_ipv4(pa_mainloop_api *m, uint32_t address
         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;
@@ -305,7 +305,7 @@ pa_socket_server* pa_socket_server_new_ipv6(pa_mainloop_api *m, const uint8_t ad
         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)
@@ -317,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;
diff --git a/src/pulsecore/socket-util.c b/src/pulsecore/socket-util.c
index b7361e9..085edeb 100644
--- a/src/pulsecore/socket-util.c
+++ b/src/pulsecore/socket-util.c
@@ -143,83 +143,64 @@ void pa_socket_peer_to_string(int fd, char *c, size_t l) {
     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;
     pa_assert(fd >= 0);
 
     priority = 6;
-    if (setsockopt(fd, SOL_SOCKET, SO_PRIORITY, (void*)&priority, sizeof(priority)) < 0) {
+    if (setsockopt(fd, SOL_SOCKET, SO_PRIORITY, (void*)&priority, sizeof(priority)) < 0)
         pa_log_warn("SO_PRIORITY failed: %s", pa_cstrerror(errno));
-        return -1;
-    }
 #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);
-
-    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
-    {
-        pa_log_warn("TCP_NODELAY failed: %s", pa_cstrerror(errno));
-        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;
+    {
+        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
-    {
-        pa_log_warn("IP_TOS failed: %s", pa_cstrerror(errno));
-        ret = -1;
+            pa_log_warn("IP_TOS failed: %s", pa_cstrerror(errno));
     }
 #endif
-
-    return ret;
 }
 
-int pa_socket_udp_low_delay(int fd) {
-    int ret, tos;
-
+void pa_make_udp_socket_low_delay(int fd) {
     pa_assert(fd >= 0);
-
-    ret = pa_socket_low_delay(fd);
-
-    tos = 0;
-
+    
+    pa_make_socket_low_delay(fd);
+    
 #if defined(IPTOS_LOWDELAY) && defined(IP_TOS) && (defined(SOL_IP) || defined(IPPROTO_IP))
-    tos = IPTOS_LOWDELAY;
+    {
+        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));
+            pa_log_warn("IP_TOS failed: %s", pa_cstrerror(errno));
     }
 #endif
-
-    return ret;
 }
 
 int pa_socket_set_rcvbuf(int fd, size_t l) {
diff --git a/src/pulsecore/socket-util.h b/src/pulsecore/socket-util.h
index abe9ce1..a0344c6 100644
--- a/src/pulsecore/socket-util.h
+++ b/src/pulsecore/socket-util.h
@@ -29,9 +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);
-int pa_socket_udp_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);

commit d716e3cd7b73b12e40fed20e9e00ea55fba62eb2
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Sep 19 19:03:38 2007 +0000

    fix check for lrintf, make resample2.c again identical to upstream ffmpeg
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1868 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/ffmpeg/avcodec.h b/src/pulsecore/ffmpeg/avcodec.h
index 775ec96..7e86e7f 100644
--- a/src/pulsecore/ffmpeg/avcodec.h
+++ b/src/pulsecore/ffmpeg/avcodec.h
@@ -25,6 +25,10 @@
  * 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>
@@ -68,4 +72,11 @@ void av_resample_compensate(struct AVResampleContext *c, int sample_delta, int c
 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_LFRINTF
+#define lrintf(x) ((long int)(x))
+#endif
+
 #endif /* AVCODEC_H */
diff --git a/src/pulsecore/ffmpeg/resample2.c b/src/pulsecore/ffmpeg/resample2.c
index dfbd528..da1443d 100644
--- a/src/pulsecore/ffmpeg/resample2.c
+++ b/src/pulsecore/ffmpeg/resample2.c
@@ -86,13 +86,6 @@ static double bessel(double x){
     return v;
 }
 
-/*
- * crude lrintf for non-C99 systems.
- */
-#ifndef HAVE_LFRINTF
-#define lrintf(x) ((long int)(x))
-#endif
-
 /**
  * builds a polyphase filterbank.
  * @param factor resampling factor

commit 42b71ff9656904668d3abcf0016768701148301b
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Sep 19 19:06:25 2007 +0000

    fix trivial typo
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1869 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/ffmpeg/avcodec.h b/src/pulsecore/ffmpeg/avcodec.h
index 7e86e7f..bf8b84e 100644
--- a/src/pulsecore/ffmpeg/avcodec.h
+++ b/src/pulsecore/ffmpeg/avcodec.h
@@ -75,7 +75,7 @@ void av_build_filter(int16_t *filter, double factor, int tap_count, int phase_co
 /*
  * crude lrintf for non-C99 systems.
  */
-#ifndef HAVE_LFRINTF
+#ifndef HAVE_LRINTF
 #define lrintf(x) ((long int)(x))
 #endif
 

commit a8a9ee499d400fd54d4f67340247f78fb4ab2a5c
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Sep 19 21:20:15 2007 +0000

    make sure we initialize thread private data before we move our ghost sink to the rt thread, not after
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1870 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c
index b8ca5e1..3993e33 100644
--- a/src/pulsecore/sink-input.c
+++ b/src/pulsecore/sink-input.c
@@ -774,6 +774,10 @@ int pa_sink_input_move_to(pa_sink_input *i, pa_sink *dest, int immediately) {
                     NULL,
                     NULL);
 
+            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;
+            
             info.buffer = pa_memblockq_new(0, MOVE_BUFFER_LENGTH, 0, pa_frame_size(&origin->sample_spec), 0, 0, NULL);
         }
     }
@@ -782,9 +786,6 @@ int pa_sink_input_move_to(pa_sink_input *i, pa_sink *dest, int immediately) {
 
     if (info.ghost_sink_input) {
         /* Basically, do what pa_sink_input_put() does ...*/
-        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;
         
         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);

commit 75647bc38f8a65f45c6cee23d5b373c6c3b3ecdc
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Sep 19 22:21:55 2007 +0000

    render new data always in the master sink's thread, fixing missing locking
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1871 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-combine.c b/src/modules/module-combine.c
index feadf4f..9923f2e 100644
--- a/src/modules/module-combine.c
+++ b/src/modules/module-combine.c
@@ -87,8 +87,9 @@ struct output {
     pa_sink *sink;
     pa_sink_input *sink_input;
 
-    pa_asyncmsgq *asyncmsgq;
-    pa_rtpoll_item *rtpoll_item;
+    pa_asyncmsgq *inq,    /* Message queue from the master to this sink input */
+                 *outq;   /* Message queue from this sink input to the master */
+    pa_rtpoll_item *inq_rtpoll_item, *outq_rtpoll_item;
     
     pa_memblockq *memblockq;
 
@@ -106,8 +107,6 @@ struct userdata {
     pa_thread_mq thread_mq;
     pa_rtpoll *rtpoll;
 
-    pa_mutex *mutex;
-    
     struct output *master;
 
     pa_time_event *time_event; 
@@ -134,7 +133,8 @@ struct userdata {
 
 enum {
     SINK_MESSAGE_ADD_OUTPUT = PA_SINK_MESSAGE_MAX,
-    SINK_MESSAGE_REMOVE_OUTPUT
+    SINK_MESSAGE_REMOVE_OUTPUT,
+    SINK_MESSAGE_NEED
 };
 
 enum {
@@ -275,9 +275,51 @@ finish:
     pa_log_debug("Thread shutting down");
 }
 
-static void request_memblock(struct output *o, size_t length) {
-    pa_memchunk chunk;
+static void render_memblock(struct userdata *u, struct output *o, size_t length) {
+    pa_assert(u);
+    pa_assert(o);
+
+    if (!PA_SINK_OPENED(u->sink->thread_info.state))
+        return;
+
+    /* We are run by the master output (u->master), possibly on behalf
+     * of another output (o). The other output is waiting for us,
+     * hence it is safe to access its mainblockq directly. */
     
+    /* 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 = o->userdata->thread_info.outputs; j; j = j->next)
+
+            /* Send to other outputs, which are not the requesting
+             * one, and not the master */
+            
+            if (j != o && j != u->master && j->sink_input)
+                pa_asyncmsgq_post(j->inq, PA_MSGOBJECT(j->sink_input), SINK_INPUT_MESSAGE_POST, NULL, 0, &chunk, NULL);
+        
+        /* Now push it into the master queue */
+        pa_memblockq_push_align(u->master->memblockq, &chunk);
+
+        /* And into the requesting output's queue */
+        if (o != u->master)
+            pa_memblockq_push_align(o->memblockq, &chunk);
+        
+        pa_memblock_unref(chunk.memblock);
+    }
+}
+
+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);
@@ -285,7 +327,7 @@ static void request_memblock(struct output *o, size_t length) {
     /* 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->asyncmsgq) > 0)
+    while (pa_asyncmsgq_process_one(o->inq) > 0)
         ;
     
     /* Check whether we're now readable */
@@ -293,33 +335,16 @@ static void request_memblock(struct output *o, size_t length) {
         return;
     
     /* OK, we need to prepare new data */
-    pa_mutex_lock(o->userdata->mutex);
 
-    if (PA_SINK_OPENED(o->userdata->sink->thread_info.state)) {
-    
-        /* Maybe there's some data now? */
-        while (pa_asyncmsgq_process_one(o->asyncmsgq) > 0)
-            ;
-        
-        /* Ok, now let's prepare some data if we really have to */
-        while (!pa_memblockq_is_readable(o->memblockq)) {
-            struct output *j;
-            
-            /* Do it! */
-            pa_sink_render(o->userdata->sink, length, &chunk);
-            
-            /* OK, let's send this data to the other threads */
-            for (j = o->userdata->thread_info.outputs; j; j = j->next)
-                if (j != o && j->sink_input)
-                    pa_asyncmsgq_post(j->asyncmsgq, PA_MSGOBJECT(j->sink_input), SINK_INPUT_MESSAGE_POST, NULL, 0, &chunk, NULL);
-            
-            /* And push it into our own queue */
-            pa_memblockq_push_align(o->memblockq, &chunk);
-            pa_memblock_unref(chunk.memblock);
-        }
-    }
-    
-    pa_mutex_unlock(o->userdata->mutex);
+    if (o == o->userdata->master)
+        /* OK, we're the master, so let's render some data */
+        render_memblock(o->userdata, o, length);
+
+    else
+        /* We're not the master, we need to ask the master to do the
+         * rendering for us */
+
+        pa_asyncmsgq_send(o->outq, PA_MSGOBJECT(o->userdata->sink), SINK_MESSAGE_NEED, o, length, NULL);
 }
 
 /* Called from I/O thread context */
@@ -327,8 +352,7 @@ static int sink_input_peek_cb(pa_sink_input *i, size_t length, pa_memchunk *chun
     struct output *o;
 
     pa_sink_input_assert_ref(i);
-    o = i->userdata;
-    pa_assert(o);
+    pa_assert_se(o = i->userdata);
 
     /* If necessary, get some new data */
     request_memblock(o, length);
@@ -342,8 +366,7 @@ static void sink_input_drop_cb(pa_sink_input *i, size_t length) {
 
     pa_sink_input_assert_ref(i);
     pa_assert(length > 0);
-    o = i->userdata;
-    pa_assert(o);
+    pa_assert_se(o = i->userdata);
 
     pa_memblockq_drop(o->memblockq, length);
 }
@@ -353,23 +376,42 @@ static void sink_input_attach_cb(pa_sink_input *i) {
     struct output *o;
 
     pa_sink_input_assert_ref(i);
-    o = i->userdata;
-    pa_assert(o);
+    pa_assert_se(o = i->userdata);
 
+    pa_assert(!o->inq_rtpoll_item);
+    
     if (o->userdata->master == o) {
+        struct output *k;
+
+        pa_assert(!o->outq_rtpoll_item);
+        
+        /* Set up the queues from the outputs to the master */
+        for (k = o->userdata->thread_info.outputs; k; k = k->next) {
+
+            pa_assert(!k->outq_rtpoll_item);
+
+            if (o == k)
+                continue;
+            
+            k->outq_rtpoll_item = pa_rtpoll_item_new_asyncmsgq(
+                    i->sink->rtpoll,
+                    PA_RTPOLL_EARLY+1,  /* This one has a slightly lower priority than the normal message handling */
+                    k->outq);
+        }
+        
         /* Calling these two functions here is safe, because both
-         * threads that might access this sink input are known to be
+         * threads that might access this sink are known to be
          * waiting for us. */
         pa_sink_set_asyncmsgq(o->userdata->sink, i->sink->asyncmsgq);
         pa_sink_set_rtpoll(o->userdata->sink, i->sink->rtpoll);
         pa_sink_attach_within_thread(o->userdata->sink);
     }
-    
-    pa_assert(!o->rtpoll_item);
-    o->rtpoll_item = pa_rtpoll_item_new_asyncmsgq(
+
+    /* Set up the queues from the inputs to the master */
+    o->inq_rtpoll_item = pa_rtpoll_item_new_asyncmsgq(
             i->sink->rtpoll,
             PA_RTPOLL_NORMAL,  /* This one has a lower priority than the normal message handling */
-            o->asyncmsgq);
+            o->inq);
 }
 
 /* Called from I/O thread context */
@@ -377,15 +419,27 @@ static void sink_input_detach_cb(pa_sink_input *i) {
     struct output *o;
 
     pa_sink_input_assert_ref(i);
-    o = i->userdata;
-    pa_assert(o);
+    pa_assert_se(o = i->userdata);
 
-    pa_assert(o->rtpoll_item);
-    pa_rtpoll_item_free(o->rtpoll_item);
-    o->rtpoll_item = NULL;
+    pa_assert(o->inq_rtpoll_item);
+    pa_rtpoll_item_free(o->inq_rtpoll_item);
+    o->inq_rtpoll_item = NULL;
 
-    if (o->userdata->master == o)
+    if (o->userdata->master == o) {
+        struct output *k;
+        
         pa_sink_detach_within_thread(o->userdata->sink);
+
+        for (k = o->userdata->thread_info.outputs; k; k = k->next) {
+
+            if (o == k)
+                continue;
+
+            pa_assert(k->outq_rtpoll_item);
+            pa_rtpoll_item_free(k->outq_rtpoll_item);
+            k->outq_rtpoll_item = NULL;
+        }
+    }
 }
 
 /* Called from main context */
@@ -433,6 +487,7 @@ static int sink_input_process_msg(pa_msgobject *obj, int code, void *data, int64
     return pa_sink_input_process_msg(obj, code, data, offset, chunk);
 }
 
+/* Called from main context */
 static int suspend(struct userdata *u) {
     struct output *o;
     uint32_t idx;
@@ -458,6 +513,7 @@ static int suspend(struct userdata *u) {
     return 0;
 }
 
+/* Called from main context */
 static int unsuspend(struct userdata *u) {
     struct output *o;
     uint32_t idx;
@@ -485,12 +541,12 @@ static int unsuspend(struct userdata *u) {
     return 0;
 }
 
+/* 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);
-    u = sink->userdata;
-    pa_assert(u);
+    pa_assert_se(u = sink->userdata);
 
     /* Please note that in contrast to the ALSA modules we call
      * suspend/unsuspend from main context here! */
@@ -575,6 +631,10 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
         case SINK_MESSAGE_REMOVE_OUTPUT:
             PA_LLIST_REMOVE(struct output, u->thread_info.outputs, (struct output*) data);
             break;
+
+        case SINK_MESSAGE_NEED:
+            render_memblock(u, data, (size_t) offset);
+            break;
     }
     
     return pa_sink_process_msg(o, code, data, offset, chunk);
@@ -765,8 +825,10 @@ static struct output *output_new(struct userdata *u, pa_sink *sink) {
 
     o = pa_xnew(struct output, 1);
     o->userdata = u;
-    o->asyncmsgq = pa_asyncmsgq_new(0);
-    o->rtpoll_item = NULL;
+    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(
@@ -809,9 +871,12 @@ fail:
         if (o->memblockq)
             pa_memblockq_free(o->memblockq);
 
-        if (o->asyncmsgq)
-            pa_asyncmsgq_unref(o->asyncmsgq);
+        if (o->inq)
+            pa_asyncmsgq_unref(o->inq);
 
+        if (o->outq)
+            pa_asyncmsgq_unref(o->outq);
+        
         pa_xfree(o);
     }
 
@@ -947,7 +1012,6 @@ int pa__init(pa_module*m) {
     u->thread_info.master = u->master = NULL;
     u->time_event = NULL; 
     u->adjust_time = DEFAULT_ADJUST_TIME; 
-    u->mutex = pa_mutex_new(FALSE, TRUE);
     pa_thread_mq_init(&u->thread_mq, m->core->mainloop);
     u->rtpoll = NULL;
     u->thread = NULL;
@@ -1134,14 +1198,20 @@ static void output_free(struct output *o) {
         pa_sink_input_unref(o->sink_input);
     }
 
-    if (o->rtpoll_item)
-        pa_rtpoll_item_free(o->rtpoll_item);
+    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);
-
-    if (o->asyncmsgq)
-        pa_asyncmsgq_unref(o->asyncmsgq);
     
     pa_xfree(o);
 }
@@ -1190,8 +1260,6 @@ void pa__done(pa_module*m) {
     if (u->time_event)
         u->core->mainloop->time_free(u->time_event);
     
-    pa_mutex_free(u->mutex);
-        
     pa_xfree(u);
 }
 

commit c40c1682be62ccccedf626b1d9e335efe7a1101a
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Sep 20 20:30:03 2007 +0000

    maintain the attach status in a boolean variable 'attach' accessible from the IO thread for sink_inputs/source_outputs
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1872 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c
index 3993e33..c06da13 100644
--- a/src/pulsecore/sink-input.c
+++ b/src/pulsecore/sink-input.c
@@ -189,9 +189,9 @@ pa_sink_input* pa_sink_input_new(
         if (data->sync_base->sync_next)
             data->sync_base->sync_next->sync_prev = i;
         data->sync_base->sync_next = i;
-    } else 
+    } else
         i->sync_next = i->sync_prev = NULL;
-    
+
     i->peek = NULL;
     i->drop = NULL;
     i->kill = NULL;
@@ -205,11 +205,12 @@ pa_sink_input* pa_sink_input_new(
     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; 
+    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);
@@ -249,7 +250,7 @@ static int sink_input_set_state(pa_sink_input *i, pa_sink_input_state_t state) {
 
     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;
@@ -258,7 +259,7 @@ static int sink_input_set_state(pa_sink_input *i, pa_sink_input_state_t state) {
         update_n_corked(ssync, state);
         ssync->state = state;
     }
-    
+
     return 0;
 }
 
@@ -267,14 +268,14 @@ void pa_sink_input_unlink(pa_sink_input *i) {
     pa_assert(PA_SINK_INPUT_LINKED(i->state));
 
     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_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i->sink), PA_SINK_MESSAGE_REMOVE_INPUT, i, 0, NULL);
     pa_idxset_remove_by_data(i->sink->core->sink_inputs, i, NULL);
     pa_idxset_remove_by_data(i->sink->inputs, i, NULL);
@@ -283,7 +284,7 @@ void pa_sink_input_unlink(pa_sink_input *i) {
 
     sink_input_set_state(i, PA_SINK_INPUT_UNLINKED);
     pa_sink_update_status(i->sink);
-    
+
     i->peek = NULL;
     i->drop = NULL;
     i->kill = NULL;
@@ -308,6 +309,8 @@ static void sink_input_free(pa_object *o) {
 
     pa_log_info("Freeing output %u \"%s\"", i->index, i->name);
 
+    pa_assert(!i->thread_info.attached);
+
     if (i->thread_info.resampled_chunk.memblock)
         pa_memblock_unref(i->thread_info.resampled_chunk.memblock);
 
@@ -393,7 +396,7 @@ int pa_sink_input_peek(pa_sink_input *i, size_t length, pa_memchunk *chunk, pa_c
     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;
 
@@ -437,7 +440,7 @@ int pa_sink_input_peek(pa_sink_input *i, size_t length, pa_memchunk *chunk, pa_c
         rmbs = pa_resampler_max_block_size(i->thread_info.resampler);
         if (l > rmbs)
             l = rmbs;
-        
+
         if ((ret = i->peek(i, l, &tchunk)) < 0)
             goto finish;
 
@@ -451,7 +454,7 @@ int pa_sink_input_peek(pa_sink_input *i, size_t length, pa_memchunk *chunk, pa_c
         /* It might be necessary to adjust the volume here */
         if (do_volume_adj_here && !volume_is_norm) {
             pa_memchunk_make_writable(&tchunk, 0);
-            
+
             if (i->thread_info.muted)
                 pa_silence_memchunk(&tchunk, &i->thread_info.sample_spec);
             else
@@ -529,7 +532,7 @@ void pa_sink_input_drop(pa_sink_input *i, size_t length) {
 
         i->thread_info.resampled_chunk.index += l;
         i->thread_info.resampled_chunk.length -= l;
-        
+
         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);
@@ -539,7 +542,7 @@ void pa_sink_input_drop(pa_sink_input *i, size_t length) {
     }
 
     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
@@ -548,31 +551,31 @@ void pa_sink_input_drop(pa_sink_input *i, size_t length) {
             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;
-                    
+
                 } else {
                     size_t l;
-                    
+
                     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;
                 }
             }
@@ -728,7 +731,7 @@ int pa_sink_input_move_to(pa_sink_input *i, pa_sink *dest, int immediately) {
 
     memset(&info, 0, sizeof(info));
     info.sink_input = i;
-    
+
     if (!immediately) {
         pa_usec_t old_latency, new_latency;
 
@@ -763,9 +766,9 @@ int pa_sink_input_move_to(pa_sink_input *i, pa_sink *dest, int immediately) {
         }
 
         /* Okey, let's move it */
-        
+
         if (info.buffer_bytes > 0) {
-            
+
             info.ghost_sink_input = pa_memblockq_sink_input_new(
                     origin,
                     "Ghost Stream",
@@ -777,7 +780,7 @@ int pa_sink_input_move_to(pa_sink_input *i, pa_sink *dest, int immediately) {
             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;
-            
+
             info.buffer = pa_memblockq_new(0, MOVE_BUFFER_LENGTH, 0, pa_frame_size(&origin->sample_spec), 0, 0, NULL);
         }
     }
@@ -786,12 +789,12 @@ int pa_sink_input_move_to(pa_sink_input *i, pa_sink *dest, int immediately) {
 
     if (info.ghost_sink_input) {
         /* Basically, do what pa_sink_input_put() does ...*/
-        
+
         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);
     }
-    
+
     pa_idxset_remove_by_data(origin->inputs, i, NULL);
     pa_idxset_put(dest->inputs, i, NULL);
     i->sink = dest;
@@ -828,14 +831,14 @@ int pa_sink_input_move_to(pa_sink_input *i, pa_sink *dest, int immediately) {
                 &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);
 
@@ -864,13 +867,13 @@ int pa_sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int64_t
             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); 
+            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: 
+        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));
@@ -879,11 +882,11 @@ int pa_sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int64_t
 
         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) {
@@ -892,14 +895,14 @@ int pa_sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int64_t
                     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;
         }
     }
@@ -915,4 +918,3 @@ pa_sink_input_state_t pa_sink_input_get_state(pa_sink_input *i) {
 
     return i->state;
 }
-
diff --git a/src/pulsecore/sink-input.h b/src/pulsecore/sink-input.h
index 152c24e..fec431f 100644
--- a/src/pulsecore/sink-input.h
+++ b/src/pulsecore/sink-input.h
@@ -124,6 +124,8 @@ struct pa_sink_input {
     struct {
         pa_sink_input_state_t state;
         pa_atomic_t drained;
+
+        pa_bool_t attached; /* True only between ->attach() and ->detach() calls */
         
         pa_sample_spec sample_spec;
 
diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c
index 886d744..81258e7 100644
--- a/src/pulsecore/sink.c
+++ b/src/pulsecore/sink.c
@@ -155,7 +155,7 @@ void pa_sink_put(pa_sink* s) {
     pa_assert(s->rtpoll);
 
     s->thread_info.state = s->state = PA_SINK_IDLE;
-    
+
     pa_source_put(s->monitor_source);
 
     pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK | PA_SUBSCRIPTION_EVENT_NEW, s->index);
@@ -164,7 +164,7 @@ void pa_sink_put(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)
@@ -177,14 +177,14 @@ static int sink_set_state(pa_sink *s, pa_sink_state_t 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;
@@ -206,7 +206,7 @@ void pa_sink_unlink(pa_sink* s) {
     pa_assert(PA_SINK_LINKED(s->state));
 
     pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SINK_UNLINK], s);
-    
+
     pa_namereg_unregister(s->core, s->name);
     pa_idxset_remove_by_data(s->core->sinks, s, NULL);
 
@@ -254,12 +254,12 @@ static void sink_free(pa_object *o) {
 
     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);
@@ -401,7 +401,7 @@ void pa_sink_render(pa_sink*s, size_t length, pa_memchunk *result) {
     pa_mix_info info[MAX_MIX_CHANNELS];
     unsigned n;
     size_t block_size_max;
-    
+
     pa_sink_assert_ref(s);
     pa_assert(PA_SINK_OPENED(s->thread_info.state));
     pa_assert(pa_frame_aligned(length, &s->sample_spec));
@@ -417,7 +417,7 @@ void pa_sink_render(pa_sink*s, size_t length, pa_memchunk *result) {
         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) {
@@ -595,10 +595,10 @@ void pa_sink_skip(pa_sink *s, size_t length) {
     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 */
 
@@ -609,7 +609,7 @@ void pa_sink_skip(pa_sink *s, size_t length) {
             pa_assert(chunk.length <= length);
             length -= chunk.length;
         }
-        
+
     } else {
         /* Ok, noone cares about the rendered data, so let's not even render it */
 
@@ -792,7 +792,7 @@ int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offse
     pa_assert(PA_SINK_LINKED(s->thread_info.state));
 
     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));
@@ -813,6 +813,9 @@ int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offse
                 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);
 
@@ -824,14 +827,17 @@ int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offse
 
             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;
@@ -841,10 +847,10 @@ int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offse
                 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;
         }
 
@@ -857,37 +863,37 @@ int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offse
             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->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;
                 }
@@ -910,7 +916,7 @@ int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offse
                 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;
             }
-            
+
             return 0;
         }
 
@@ -934,7 +940,7 @@ int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offse
             return 0;
 
         case PA_SINK_MESSAGE_SET_STATE:
-            
+
             s->thread_info.state = PA_PTR_TO_UINT(userdata);
             return 0;
 
@@ -951,7 +957,7 @@ int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offse
             /* Reattach all streams */
             pa_sink_attach_within_thread(s);
             break;
-            
+
         case PA_SINK_MESSAGE_GET_LATENCY:
         case PA_SINK_MESSAGE_MAX:
             ;
@@ -964,7 +970,7 @@ 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)))
@@ -1016,4 +1022,3 @@ void pa_sink_attach_within_thread(pa_sink *s) {
     if (s->monitor_source)
         pa_source_attach_within_thread(s->monitor_source);
 }
-
diff --git a/src/pulsecore/source-output.c b/src/pulsecore/source-output.c
index df5dc8c..34eef8b 100644
--- a/src/pulsecore/source-output.c
+++ b/src/pulsecore/source-output.c
@@ -156,6 +156,7 @@ pa_source_output* pa_source_output_new(
     o->userdata = NULL;
 
     o->thread_info.state = o->state;
+    o->thread_info.attached = FALSE;
     o->thread_info.sample_spec = o->sample_spec;
     o->thread_info.resampler = resampler;
 
@@ -186,9 +187,9 @@ static int source_output_set_state(pa_source_output *o, pa_source_output_state_t
         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++;
-    
+
     o->state = state;
-    
+
     return 0;
 }
 
@@ -197,7 +198,7 @@ void pa_source_output_unlink(pa_source_output*o) {
     pa_assert(PA_SOURCE_OUTPUT_LINKED(o->state));
 
     pa_hook_fire(&o->source->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_UNLINK], o);
-    
+
     pa_asyncmsgq_send(o->source->asyncmsgq, PA_MSGOBJECT(o->source), PA_SOURCE_MESSAGE_REMOVE_OUTPUT, o, 0, NULL);
 
     pa_idxset_remove_by_data(o->source->core->source_outputs, o, NULL);
@@ -231,6 +232,8 @@ static void source_output_free(pa_object* mo) {
 
     pa_log_info("Freeing output %u \"%s\"", o->index, o->name);
 
+    pa_assert(!o->thread_info.attached);
+
     if (o->thread_info.resampler)
         pa_resampler_free(o->thread_info.resampler);
 
@@ -258,7 +261,7 @@ void pa_source_output_put(pa_source_output *o) {
 void pa_source_output_kill(pa_source_output*o) {
     pa_source_output_assert_ref(o);
     pa_assert(PA_SOURCE_OUTPUT_LINKED(o->state));
-    
+
     if (o->kill)
         o->kill(o);
 }
@@ -357,7 +360,7 @@ int pa_source_output_move_to(pa_source_output *o, pa_source *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)
@@ -399,7 +402,7 @@ int pa_source_output_move_to(pa_source_output *o, pa_source *dest) {
 
     /* 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;
@@ -448,7 +451,7 @@ int pa_source_output_process_msg(pa_msgobject *mo, int code, void *userdata, int
 
             return 0;
         }
-            
+
     }
 
     return -1;
diff --git a/src/pulsecore/source-output.h b/src/pulsecore/source-output.h
index 96ded86..60552d4 100644
--- a/src/pulsecore/source-output.h
+++ b/src/pulsecore/source-output.h
@@ -99,6 +99,8 @@ struct pa_source_output {
 
     struct {
         pa_source_output_state_t state;
+
+        pa_bool_t attached; /* True only between ->attach() and ->detach() calls */
         
         pa_sample_spec sample_spec;
 
diff --git a/src/pulsecore/source.c b/src/pulsecore/source.c
index 315c2ce..8f9cbc4 100644
--- a/src/pulsecore/source.c
+++ b/src/pulsecore/source.c
@@ -139,7 +139,7 @@ void pa_source_put(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)
@@ -147,14 +147,14 @@ static int source_set_state(pa_source *s, pa_source_state_t state) {
 
     if (state == PA_SOURCE_SUSPENDED && !(s->flags & PA_SOURCE_CAN_SUSPEND))
         return -1;
-    
+
     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);
@@ -180,7 +180,7 @@ void pa_source_unlink(pa_source *s) {
     pa_assert(s);
     pa_assert(PA_SOURCE_LINKED(s->state));
 
-    pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SOURCE_UNLINK], s);    
+    pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SOURCE_UNLINK], s);
 
     pa_namereg_unregister(s->core, s->name);
     pa_idxset_remove_by_data(s->core->sources, s, NULL);
@@ -202,7 +202,7 @@ void pa_source_unlink(pa_source *s) {
 
     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);    
+    pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SOURCE_UNLINK_POST], s);
 }
 
 static void source_free(pa_object *o) {
@@ -221,7 +221,7 @@ static void source_free(pa_object *o) {
 
     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);
@@ -267,7 +267,7 @@ void pa_source_post(pa_source*s, const pa_memchunk *chunk) {
 
     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;
 
@@ -436,7 +436,7 @@ unsigned pa_source_linked_by(pa_source *s) {
 
 unsigned pa_source_used_by(pa_source *s) {
     unsigned ret;
-    
+
     pa_source_assert_ref(s);
     pa_assert(PA_SOURCE_LINKED(s->state));
 
@@ -456,9 +456,12 @@ int pa_source_process_msg(pa_msgobject *object, int code, void *userdata, int64_
             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;
         }
 
@@ -468,6 +471,9 @@ int pa_source_process_msg(pa_msgobject *object, int code, void *userdata, int64_
             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);
 
@@ -510,7 +516,7 @@ int pa_source_process_msg(pa_msgobject *object, int code, void *userdata, int64_
             /* Reattach all streams */
             pa_source_attach_within_thread(s);
             break;
-            
+
         case PA_SOURCE_MESSAGE_GET_LATENCY:
         case PA_SOURCE_MESSAGE_MAX:
             ;
@@ -523,9 +529,9 @@ 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;
 

commit f3f44dab379f4791a51642d49fcf20284856ec9e
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Sep 20 20:33:34 2007 +0000

    rework module-combine again
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1873 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-combine.c b/src/modules/module-combine.c
index 9923f2e..90433e0 100644
--- a/src/modules/module-combine.c
+++ b/src/modules/module-combine.c
@@ -90,7 +90,7 @@ struct output {
     pa_asyncmsgq *inq,    /* Message queue from the master to this sink input */
                  *outq;   /* Message queue from this sink input to the master */
     pa_rtpoll_item *inq_rtpoll_item, *outq_rtpoll_item;
-    
+
     pa_memblockq *memblockq;
 
     pa_usec_t total_latency;
@@ -109,8 +109,8 @@ struct userdata {
 
     struct output *master;
 
-    pa_time_event *time_event; 
-    uint32_t adjust_time; 
+    pa_time_event *time_event;
+    uint32_t adjust_time;
 
     int automatic;
     size_t block_size;
@@ -122,7 +122,7 @@ struct userdata {
     pa_resample_method_t resample_method;
 
     struct timespec adjust_timestamp;
-    
+
     pa_idxset* outputs; /* managed in main context */
 
     struct {
@@ -134,7 +134,8 @@ struct userdata {
 enum {
     SINK_MESSAGE_ADD_OUTPUT = PA_SINK_MESSAGE_MAX,
     SINK_MESSAGE_REMOVE_OUTPUT,
-    SINK_MESSAGE_NEED
+    SINK_MESSAGE_NEED,
+    SINK_MESSAGE_SET_MASTER
 };
 
 enum {
@@ -144,7 +145,7 @@ enum {
 static void output_free(struct output *o);
 static int output_create_sink_input(struct userdata *u, struct output *o);
 static int update_master(struct userdata *u, struct output *o);
-static int pick_master(struct userdata *u);
+static int pick_master(struct userdata *u, struct output *except);
 
 static void adjust_rates(struct userdata *u) {
     struct output *o;
@@ -160,7 +161,7 @@ static void adjust_rates(struct userdata *u) {
 
     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)) {
         uint32_t sink_latency;
 
@@ -169,35 +170,35 @@ static void adjust_rates(struct userdata *u) {
 
         sink_latency = o->sink_input->sink ? pa_sink_get_latency(o->sink_input->sink) : 0;
         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)
             min_total_latency = o->total_latency;
     }
 
     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 is %s", u->sink->name, u->master->sink->description);
-        
+
     base_rate = u->sink->sample_spec.rate;
-        
+
     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);
         else if (o->total_latency > target_latency)
             r += (uint32_t) (((((double) o->total_latency - target_latency))/u->adjust_time)*r/ 1000000);
-        
+
         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);
             pa_sink_input_set_rate(o->sink_input, base_rate);
@@ -211,7 +212,7 @@ static void adjust_rates(struct userdata *u) {
 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);
@@ -238,14 +239,14 @@ static void thread_func(void *userdata) {
     /* This is only run when we are in NULL mode, to make sure that
      * playback doesn't stop. In all other cases we hook our stuff
      * into the master sink. */
-    
+
     for (;;) {
         int ret;
 
         /* Render some data and drop it immediately */
         if (u->sink->thread_info.state == PA_SINK_RUNNING) {
             struct timespec now;
-            
+
             pa_rtclock_get(&now);
 
             if (pa_timespec_cmp(&u->timestamp, &now) <= 0) {
@@ -275,6 +276,7 @@ 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);
@@ -285,58 +287,59 @@ static void render_memblock(struct userdata *u, struct output *o, size_t length)
     /* We are run by the master output (u->master), possibly on behalf
      * of another output (o). The other output is waiting for us,
      * hence it is safe to access its mainblockq directly. */
-    
+
     /* 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 = o->userdata->thread_info.outputs; j; j = j->next)
 
             /* Send to other outputs, which are not the requesting
              * one, and not the master */
-            
-            if (j != o && j != u->master && j->sink_input)
+
+            if (j != o && j != u->thread_info.master && j->sink_input)
                 pa_asyncmsgq_post(j->inq, PA_MSGOBJECT(j->sink_input), SINK_INPUT_MESSAGE_POST, NULL, 0, &chunk, NULL);
-        
+
         /* Now push it into the master queue */
-        pa_memblockq_push_align(u->master->memblockq, &chunk);
+        pa_memblockq_push_align(u->thread_info.master->memblockq, &chunk);
 
         /* And into the requesting output's queue */
-        if (o != u->master)
+        if (o != u->thread_info.master)
             pa_memblockq_push_align(o->memblockq, &chunk);
-        
+
         pa_memblock_unref(chunk.memblock);
     }
 }
 
+/* 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);
-    
+
     /* 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)
         ;
-    
+
     /* Check whether we're now readable */
     if (pa_memblockq_is_readable(o->memblockq))
         return;
-    
+
     /* OK, we need to prepare new data */
 
-    if (o == o->userdata->master)
+    if (o == o->userdata->thread_info.master)
         /* OK, we're the master, so let's render some data */
         render_memblock(o->userdata, o, length);
 
@@ -371,6 +374,51 @@ static void sink_input_drop_cb(pa_sink_input *i, size_t length) {
     pa_memblockq_drop(o->memblockq, length);
 }
 
+/* Called from I/O thread context for the master */
+static void create_master_rtpolls(struct userdata *u) {
+    struct output *k;
+
+    pa_assert(u);
+
+    pa_assert(!u->master->outq_rtpoll_item);
+
+    /* Set up the queues from the outputs to the master */
+    for (k = u->thread_info.outputs; k; k = k->next) {
+
+        pa_assert(!k->outq_rtpoll_item);
+
+        if (k == u->master)
+            continue;
+
+        k->outq_rtpoll_item = pa_rtpoll_item_new_asyncmsgq(
+                u->master->sink->rtpoll,
+                PA_RTPOLL_EARLY+1,  /* This one has a slightly lower priority than the normal message handling */
+                k->outq);
+
+        pa_log("1: %p now has rptoll item %p", k, k->outq_rtpoll_item);
+    }
+}
+
+/* Called from I/O thread context for the master */
+static void free_master_rtpolls(struct userdata *u) {
+    struct output *k;
+
+    pa_assert(!u->master->outq_rtpoll_item);
+
+    for (k = u->thread_info.outputs; k; k = k->next) {
+
+        if (k == u->master)
+            continue;
+
+        if (k->outq_rtpoll_item) {
+            pa_rtpoll_item_free(k->outq_rtpoll_item);
+            k->outq_rtpoll_item = NULL;
+        }
+
+        pa_assert(!k->outq_rtpoll_item);
+    }
+}
+
 /* Called from I/O thread context */
 static void sink_input_attach_cb(pa_sink_input *i) {
     struct output *o;
@@ -378,27 +426,11 @@ static void sink_input_attach_cb(pa_sink_input *i) {
     pa_sink_input_assert_ref(i);
     pa_assert_se(o = i->userdata);
 
-    pa_assert(!o->inq_rtpoll_item);
-    
-    if (o->userdata->master == o) {
-        struct output *k;
-
-        pa_assert(!o->outq_rtpoll_item);
-        
-        /* Set up the queues from the outputs to the master */
-        for (k = o->userdata->thread_info.outputs; k; k = k->next) {
+    pa_log("attaching %s", i->sink->name);
 
-            pa_assert(!k->outq_rtpoll_item);
+    if (o->userdata->thread_info.master == o) {
+        create_master_rtpolls(o->userdata);
 
-            if (o == k)
-                continue;
-            
-            k->outq_rtpoll_item = pa_rtpoll_item_new_asyncmsgq(
-                    i->sink->rtpoll,
-                    PA_RTPOLL_EARLY+1,  /* This one has a slightly lower priority than the normal message handling */
-                    k->outq);
-        }
-        
         /* Calling these two functions here is safe, because both
          * threads that might access this sink are known to be
          * waiting for us. */
@@ -408,6 +440,7 @@ static void sink_input_attach_cb(pa_sink_input *i) {
     }
 
     /* Set up the queues from the inputs to the master */
+    pa_assert(!o->inq_rtpoll_item);
     o->inq_rtpoll_item = pa_rtpoll_item_new_asyncmsgq(
             i->sink->rtpoll,
             PA_RTPOLL_NORMAL,  /* This one has a lower priority than the normal message handling */
@@ -421,24 +454,15 @@ static void sink_input_detach_cb(pa_sink_input *i) {
     pa_sink_input_assert_ref(i);
     pa_assert_se(o = i->userdata);
 
+    pa_log("detaching %s", i->sink->name);
+
     pa_assert(o->inq_rtpoll_item);
     pa_rtpoll_item_free(o->inq_rtpoll_item);
     o->inq_rtpoll_item = NULL;
 
-    if (o->userdata->master == o) {
-        struct output *k;
-        
+    if (o->userdata->thread_info.master == o) {
         pa_sink_detach_within_thread(o->userdata->sink);
-
-        for (k = o->userdata->thread_info.outputs; k; k = k->next) {
-
-            if (o == k)
-                continue;
-
-            pa_assert(k->outq_rtpoll_item);
-            pa_rtpoll_item_free(k->outq_rtpoll_item);
-            k->outq_rtpoll_item = NULL;
-        }
+        free_master_rtpolls(o->userdata);
     }
 }
 
@@ -453,7 +477,7 @@ static void sink_input_kill_cb(pa_sink_input *i) {
     pa_sink_input_unlink(o->sink_input);
     pa_sink_input_unref(o->sink_input);
     o->sink_input = NULL;
-    
+
     pa_module_unload_request(o->userdata->module);
 }
 
@@ -462,7 +486,7 @@ static int sink_input_process_msg(pa_msgobject *obj, int code, void *data, int64
     struct output *o = PA_SINK_INPUT(obj)->userdata;
 
     switch (code) {
-        
+
         case PA_SINK_INPUT_MESSAGE_GET_LATENCY: {
              pa_usec_t *r = data;
 
@@ -479,11 +503,11 @@ static int sink_input_process_msg(pa_msgobject *obj, int code, void *data, int64
                 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);
 }
 
@@ -491,11 +515,11 @@ static int sink_input_process_msg(pa_msgobject *obj, int code, void *data, int64
 static int 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)) {
 
         if (o->sink_input) {
@@ -505,11 +529,11 @@ static int suspend(struct userdata *u) {
         }
     }
 
-    if (pick_master(u) < 0)
+    if (pick_master(u, NULL) < 0)
         pa_module_unload_request(u->module);
 
     pa_log_info("Device suspended...");
-    
+
     return 0;
 }
 
@@ -519,24 +543,26 @@ static int unsuspend(struct userdata *u) {
     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, 0);
-        
+
         if (PA_SINK_OPENED(pa_sink_get_state(o->sink))) {
             if (output_create_sink_input(u, o) < 0)
                 output_free(o);
-            else
-                pa_sink_input_put(o->sink_input);
         }
     }
 
-    if (pick_master(u) < 0)
+    if (pick_master(u, NULL) < 0)
         pa_module_unload_request(u->module);
-    
+
+    for (o = pa_idxset_first(u->outputs, &idx); o; o = pa_idxset_next(u->outputs, &idx))
+        if (o->sink_input && pa_sink_get_state(o->sink_input) == PA_SINK_INPUT_INIT)
+             pa_sink_input_put(o->sink_input);
+
     pa_log_info("Resumed successfully...");
     return 0;
 }
@@ -544,17 +570,17 @@ static int unsuspend(struct userdata *u) {
 /* 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)));
-            
+
             if (suspend(u) < 0)
                 return -1;
 
@@ -567,7 +593,7 @@ static int sink_set_state(pa_sink *sink, pa_sink_state_t state) {
                 if (unsuspend(u) < 0)
                     return -1;
             }
-                    
+
             break;
 
         case PA_SINK_UNLINKED:
@@ -583,17 +609,17 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
     struct userdata *u = PA_SINK(o)->userdata;
 
     switch (code) {
-        
+
         case PA_SINK_MESSAGE_SET_STATE:
 
             if ((pa_sink_state_t) PA_PTR_TO_UINT(data) == PA_SINK_RUNNING) {
                 /* Only useful when running in NULL mode, i.e. when no
-                 * master sink is attached */       
+                 * master sink is attached */
                 pa_rtclock_get(&u->timestamp);
             }
-            
+
             break;
-            
+
         case PA_SINK_MESSAGE_GET_LATENCY: {
             struct timespec now;
 
@@ -601,7 +627,7 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
              * mode, i.e. when no master sink is attached. See
              * sink_get_latency_cb() below */
             pa_rtclock_get(&now);
-            
+
             if (pa_timespec_cmp(&u->timestamp, &now) > 0)
                 *((pa_usec_t*) data) = 0;
             else
@@ -609,34 +635,69 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
             break;
         }
 
-        case PA_SINK_MESSAGE_DETACH:
+        case SINK_MESSAGE_SET_MASTER:
+            if ((u->thread_info.master = data)) {
 
-            /* We're detaching all our input streams artificially, so
-             * that we can drive our sink from a different sink */
+                /* There's now a master, and we're being executed in
+                 * its thread, let's register the asyncmsgqs from other
+                 * outputs to us */
 
-            u->thread_info.master = NULL;
-            break;
+                if (u->thread_info.master->sink_input->thread_info.attached)
+                    create_master_rtpolls(u);
 
-        case PA_SINK_MESSAGE_ATTACH:
+            } else {
 
-            /* We're attached all our input streams artificially again */
-            
-            u->thread_info.master = data;
-            break;
+                if (u->thread_info.master->sink_input->thread_info.attached)
+                    free_master_rtpolls(u);
 
-        case SINK_MESSAGE_ADD_OUTPUT:
-            PA_LLIST_PREPEND(struct output, u->thread_info.outputs, (struct output*) data);
-            break;
+            }
+            return 0;
 
-        case SINK_MESSAGE_REMOVE_OUTPUT:
-            PA_LLIST_REMOVE(struct output, u->thread_info.outputs, (struct output*) data);
-            break;
+        case SINK_MESSAGE_ADD_OUTPUT: {
+            struct output *op = data;
+
+            PA_LLIST_PREPEND(struct output, u->thread_info.outputs, op);
+
+            pa_assert(!op->outq_rtpoll_item);
+
+            if (op != u->thread_info.master) {
+                /* Create pa_asyncmsgq to master */
+
+                op->outq_rtpoll_item = pa_rtpoll_item_new_asyncmsgq(
+                        u->thread_info.master->sink->rtpoll,
+                        PA_RTPOLL_EARLY+1,  /* This one has a slightly lower priority than the normal message handling */
+                        op->outq);
+
+                pa_log("2: %p now has rptoll item %p", op, op->outq_rtpoll_item);
+            }
+
+            pa_log("Added output %s", op->sink_input->sink->name);
+
+            return 0;
+        }
+
+        case SINK_MESSAGE_REMOVE_OUTPUT: {
+            struct output *op = data;
+
+            pa_log("Remove output %s", op->sink_input->sink->name);
+
+            PA_LLIST_REMOVE(struct output, u->thread_info.outputs, op);
+
+            /* Remove the q that leads from this output to the master output */
+
+            if (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);
-            break;
+            return 0;
     }
-    
+
     return pa_sink_process_msg(o, code, data, offset, chunk);
 }
 
@@ -654,17 +715,17 @@ static pa_usec_t sink_get_latency_cb(pa_sink *s) {
 
         if (!u->master->sink_input)
             return 0;
-        
+
         return
             pa_sink_input_get_latency(u->master->sink_input) +
             pa_sink_get_latency(u->master->sink_input->sink);
-        
+
     } else {
         pa_usec_t usec;
 
         /* 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;
 
@@ -677,7 +738,7 @@ static void update_description(struct userdata *u) {
     char *t;
     struct output *o;
     uint32_t idx;
-    
+
     pa_assert(u);
 
     if (pa_idxset_isempty(u->outputs)) {
@@ -686,20 +747,20 @@ static void update_description(struct userdata *u) {
     }
 
     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);
 }
@@ -708,15 +769,18 @@ static int update_master(struct userdata *u, struct output *o) {
     pa_assert(u);
 
     /* Make sure everything is detached from the old thread before we move our stuff to a new thread */
-    if (u->sink && PA_SINK_LINKED(pa_sink_get_state(u->sink)))
+    if (u->sink && PA_SINK_LINKED(pa_sink_get_state(u->sink))) {
         pa_sink_detach(u->sink);
-    
+        pa_asyncmsgq_send(u->sink->asyncmsgq, PA_MSGOBJECT(u->sink), SINK_MESSAGE_SET_MASTER, NULL, 0, NULL);
+    } else
+        u->thread_info.master = NULL;
+
     if (o) {
         /* If we have a master sink we run our own sink in its thread */
 
         pa_assert(o->sink_input);
         pa_assert(PA_SINK_OPENED(pa_sink_get_state(o->sink)));
-        
+
         if (u->thread) {
             /* If we previously were in NULL mode, let's kill the thread */
             pa_asyncmsgq_send(u->thread_mq.inq, NULL, PA_MESSAGE_SHUTDOWN, NULL, 0, NULL);
@@ -737,44 +801,47 @@ static int update_master(struct userdata *u, struct output *o) {
     } else {
 
         /* We have no master sink, let's create our own thread */
-        
+
         pa_sink_set_asyncmsgq(u->sink, u->thread_mq.inq);
         u->master = NULL;
 
         if (!u->thread) {
             pa_assert(!u->rtpoll);
-            
+
             u->rtpoll = pa_rtpoll_new();
             pa_rtpoll_item_new_asyncmsgq(u->rtpoll, PA_RTPOLL_EARLY, u->thread_mq.inq);
 
             pa_sink_set_rtpoll(u->sink, u->rtpoll);
-            
+
             if (!(u->thread = pa_thread_new(thread_func, u))) {
                 pa_log("Failed to create thread.");
                 return -1;
             }
         }
-        
+
         pa_log_info("No suitable master sink found, going to NULL mode\n");
     }
 
     /* Now attach everything again */
-    if (u->sink && PA_SINK_LINKED(pa_sink_get_state(u->sink)))
+    if (u->sink && PA_SINK_LINKED(pa_sink_get_state(u->sink))) {
+        pa_asyncmsgq_send(u->sink->asyncmsgq, PA_MSGOBJECT(u->sink), SINK_MESSAGE_SET_MASTER, u->master, 0, NULL);
         pa_sink_attach(u->sink);
+    } else
+        u->thread_info.master = u->master;
 
     return 0;
 }
 
-static int pick_master(struct userdata *u) {
+static int pick_master(struct userdata *u, struct output *except) {
     struct output *o;
     uint32_t idx;
     pa_assert(u);
 
-    if (u->master && u->master->sink_input && PA_SINK_OPENED(pa_sink_get_state(u->master->sink)))
+    if (u->master && u->master != except && u->master->sink_input && PA_SINK_OPENED(pa_sink_get_state(u->master->sink)))
         return update_master(u, u->master);
 
     for (o = pa_idxset_first(u->outputs, &idx); o; o = pa_idxset_next(u->outputs, &idx))
-        if (o->sink_input && PA_SINK_OPENED(pa_sink_get_state(o->sink)))
+        if (o != except && o->sink_input && PA_SINK_OPENED(pa_sink_get_state(o->sink)))
             return update_master(u, o);
 
     return update_master(u, NULL);
@@ -783,12 +850,12 @@ static int pick_master(struct userdata *u) {
 static int output_create_sink_input(struct userdata *u, struct output *o) {
     pa_sink_input_new_data data;
     char *t;
-    
+
     pa_assert(u);
     pa_assert(!o->sink_input);
 
     t = pa_sprintf_malloc("Simultaneous output on %s", o->sink->description);
-    
+
     pa_sink_input_new_data_init(&data);
     data.sink = o->sink;
     data.driver = __FILE__;
@@ -797,14 +864,14 @@ static int output_create_sink_input(struct userdata *u, struct output *o) {
     pa_sink_input_new_data_set_channel_map(&data, &u->sink->channel_map);
     data.module = u->module;
     data.resample_method = u->resample_method;
-    
+
     o->sink_input = pa_sink_input_new(u->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;
@@ -812,7 +879,7 @@ static int output_create_sink_input(struct userdata *u, struct output *o) {
     o->sink_input->detach = sink_input_detach_cb;
     o->sink_input->kill = sink_input_kill_cb;
     o->sink_input->userdata = o;
-    
+
     return 0;
 }
 
@@ -852,7 +919,7 @@ static struct output *output_new(struct userdata *u, pa_sink *sink) {
 
     if (PA_SINK_OPENED(pa_sink_get_state(u->sink)) || pa_sink_get_state(u->sink) == PA_SINK_INIT) {
         pa_sink_suspend(sink, 0);
-    
+
         if (PA_SINK_OPENED(pa_sink_get_state(sink)))
             if (output_create_sink_input(u, o) < 0)
                 goto fail;
@@ -876,7 +943,7 @@ fail:
 
         if (o->outq)
             pa_asyncmsgq_unref(o->outq);
-        
+
         pa_xfree(o);
     }
 
@@ -885,7 +952,7 @@ fail:
 
 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);
@@ -895,25 +962,25 @@ static pa_hook_result_t sink_new_hook_cb(pa_core *c, pa_sink *s, struct userdata
         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 (pick_master(u) < 0)
+    if (pick_master(u, NULL) < 0)
         pa_module_unload_request(u->module);
-    
+
     if (o->sink_input)
         pa_sink_input_put(o->sink_input);
-        
+
     return PA_HOOK_OK;
 }
 
 static pa_hook_result_t sink_unlink_hook_cb(pa_core *c, pa_sink *s, struct userdata* u) {
     struct output *o;
     uint32_t idx;
-    
+
     pa_assert(c);
     pa_sink_assert_ref(s);
     pa_assert(u);
@@ -929,12 +996,9 @@ static pa_hook_result_t sink_unlink_hook_cb(pa_core *c, pa_sink *s, struct userd
         return PA_HOOK_OK;
 
     pa_log_info("Unconfiguring sink: %s", s->name);
-    
+
     output_free(o);
 
-    if (pick_master(u) < 0)
-        pa_module_unload_request(u->module);
-    
     return PA_HOOK_OK;
 }
 
@@ -954,17 +1018,17 @@ static pa_hook_result_t sink_state_changed_hook_cb(pa_core *c, pa_sink *s, struc
         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) {
         output_create_sink_input(u, o);
 
-        if (pick_master(u) < 0)
+        if (pick_master(u, NULL) < 0)
             pa_module_unload_request(u->module);
 
         if (o->sink_input)
             pa_sink_input_put(o->sink_input);
     }
-        
+
     if (state == PA_SINK_SUSPENDED && o->sink_input) {
         pa_sink_input_unlink(o->sink_input);
         pa_sink_input_unref(o->sink_input);
@@ -972,7 +1036,7 @@ static pa_hook_result_t sink_state_changed_hook_cb(pa_core *c, pa_sink *s, struc
 
         pa_memblockq_flush(o->memblockq);
 
-        if (pick_master(u) < 0)
+        if (pick_master(u, o) < 0)
             pa_module_unload_request(u->module);
     }
 
@@ -1010,8 +1074,8 @@ int pa__init(pa_module*m) {
     m->userdata = u;
     u->sink = NULL;
     u->thread_info.master = u->master = NULL;
-    u->time_event = NULL; 
-    u->adjust_time = DEFAULT_ADJUST_TIME; 
+    u->time_event = NULL;
+    u->adjust_time = DEFAULT_ADJUST_TIME;
     pa_thread_mq_init(&u->thread_mq, m->core->mainloop);
     u->rtpoll = NULL;
     u->thread = NULL;
@@ -1019,7 +1083,7 @@ int pa__init(pa_module*m) {
     u->resample_method = resample_method;
     u->outputs = pa_idxset_new(NULL, NULL);
     pa_timespec_reset(&u->adjust_timestamp);
-    
+
     if (pa_modargs_get_value_u32(ma, "adjust_time", &u->adjust_time) < 0) {
         pa_log("Failed to parse adjust_time value");
         goto fail;
@@ -1037,7 +1101,7 @@ int pa__init(pa_module*m) {
             pa_log("Invalid master sink '%s'", master_name);
             goto fail;
         }
-        
+
         ss = master_sink->sample_spec;
         u->automatic = 0;
     } else {
@@ -1060,7 +1124,7 @@ int pa__init(pa_module*m) {
         pa_log("Invalid channel map.");
         goto fail;
     }
-    
+
     if (ss.channels != map.channels) {
         pa_log("Channel map and sample specification don't match.");
         goto fail;
@@ -1083,31 +1147,31 @@ int pa__init(pa_module*m) {
     u->block_size = pa_bytes_per_second(&ss) / 20; /* 50 ms */
     if (u->block_size <= 0)
         u->block_size = pa_frame_size(&ss);
-    
+
     if (!u->automatic) {
         const char*split_state;
         char *n = NULL;
         pa_assert(slaves);
 
         /* 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;
         }
-    
+
         split_state = NULL;
         while ((n = pa_split(slaves, ",", &split_state))) {
             pa_sink *slave_sink;
-            
+
             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;
@@ -1118,7 +1182,7 @@ int pa__init(pa_module*m) {
             pa_log_warn("No slave sinks specified.");
 
         u->sink_new_slot = NULL;
-        
+
     } else {
         pa_sink *s;
 
@@ -1141,13 +1205,13 @@ int pa__init(pa_module*m) {
 
     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);
-    
-    if (pick_master(u) < 0)
+
+    if (pick_master(u, NULL) < 0)
         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);
@@ -1160,7 +1224,7 @@ int pa__init(pa_module*m) {
     }
 
     pa_modargs_free(ma);
-    
+
     return 0;
 
 fail:
@@ -1169,35 +1233,31 @@ fail:
         pa_modargs_free(ma);
 
     pa__done(m);
-    
+
     return -1;
 }
 
 static void output_free(struct output *o) {
     pa_assert(o);
 
-    if (o->userdata) {
-        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_REMOVE_OUTPUT, o, 0, NULL);
-        else
-            PA_LLIST_REMOVE(struct output, o->userdata->thread_info.outputs, o);
-    }
+    /* Make sure the master points to a different output */
+    if (pick_master(o->userdata, o) < 0)
+        pa_module_unload_request(o->userdata->module);
+
+    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_REMOVE_OUTPUT, o, 0, NULL);
+    else
+        PA_LLIST_REMOVE(struct output, o->userdata->thread_info.outputs, o);
 
     pa_assert_se(pa_idxset_remove_by_data(o->userdata->outputs, o, NULL));
 
-    if (o->userdata->master == o) {
-        /* Make sure the master points to a different output */
-        o->userdata->master = NULL;
-        pick_master(o->userdata);
-    }
-    
-    update_description(o->userdata);
-    
     if (o->sink_input) {
         pa_sink_input_unlink(o->sink_input);
         pa_sink_input_unref(o->sink_input);
     }
 
+    update_description(o->userdata);
+
     if (o->inq_rtpoll_item)
         pa_rtpoll_item_free(o->inq_rtpoll_item);
 
@@ -1212,14 +1272,14 @@ static void output_free(struct output *o) {
 
     if (o->memblockq)
         pa_memblockq_free(o->memblockq);
-    
+
     pa_xfree(o);
 }
 
 void pa__done(pa_module*m) {
     struct userdata *u;
     struct output *o;
-    
+
     pa_assert(m);
 
     if (!(u = m->userdata))
@@ -1230,7 +1290,7 @@ void pa__done(pa_module*m) {
 
     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);
 
@@ -1240,7 +1300,7 @@ void pa__done(pa_module*m) {
     if (u->outputs) {
         while ((o = pa_idxset_first(u->outputs, NULL)))
             output_free(o);
-        
+
         pa_idxset_free(u->outputs, NULL, NULL);
     }
 
@@ -1250,17 +1310,15 @@ void pa__done(pa_module*m) {
     }
 
     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);
 }
-
-

commit 3b2835d3345bfe74afb3e811967b966aa9058606
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Sep 20 22:01:07 2007 +0000

    properly detach/attach when moving sink inputs
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1874 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c
index 81258e7..409d026 100644
--- a/src/pulsecore/sink.c
+++ b/src/pulsecore/sink.c
@@ -819,12 +819,20 @@ int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offse
             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);
 
@@ -864,6 +872,12 @@ int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offse
             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);
@@ -915,6 +929,12 @@ int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offse
             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;

commit e205bb2555d8c723d0343e97c87c3d82e063c7ff
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Sep 20 22:01:58 2007 +0000

    don't segfault when the master changes
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1875 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-combine.c b/src/modules/module-combine.c
index 90433e0..af5ddb1 100644
--- a/src/modules/module-combine.c
+++ b/src/modules/module-combine.c
@@ -394,8 +394,6 @@ static void create_master_rtpolls(struct userdata *u) {
                 u->master->sink->rtpoll,
                 PA_RTPOLL_EARLY+1,  /* This one has a slightly lower priority than the normal message handling */
                 k->outq);
-
-        pa_log("1: %p now has rptoll item %p", k, k->outq_rtpoll_item);
     }
 }
 
@@ -426,8 +424,6 @@ static void sink_input_attach_cb(pa_sink_input *i) {
     pa_sink_input_assert_ref(i);
     pa_assert_se(o = i->userdata);
 
-    pa_log("attaching %s", i->sink->name);
-
     if (o->userdata->thread_info.master == o) {
         create_master_rtpolls(o->userdata);
 
@@ -636,6 +632,14 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
         }
 
         case SINK_MESSAGE_SET_MASTER:
+
+            if (u->thread_info.master && data != u->thread_info.master) {
+
+                if (u->thread_info.master->sink_input->thread_info.attached)
+                    free_master_rtpolls(u);
+
+            }
+
             if ((u->thread_info.master = data)) {
 
                 /* There's now a master, and we're being executed in
@@ -645,12 +649,8 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
                 if (u->thread_info.master->sink_input->thread_info.attached)
                     create_master_rtpolls(u);
 
-            } else {
-
-                if (u->thread_info.master->sink_input->thread_info.attached)
-                    free_master_rtpolls(u);
-
             }
+
             return 0;
 
         case SINK_MESSAGE_ADD_OUTPUT: {
@@ -667,20 +667,14 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
                         u->thread_info.master->sink->rtpoll,
                         PA_RTPOLL_EARLY+1,  /* This one has a slightly lower priority than the normal message handling */
                         op->outq);
-
-                pa_log("2: %p now has rptoll item %p", op, op->outq_rtpoll_item);
             }
 
-            pa_log("Added output %s", op->sink_input->sink->name);
-
             return 0;
         }
 
         case SINK_MESSAGE_REMOVE_OUTPUT: {
             struct output *op = data;
 
-            pa_log("Remove output %s", op->sink_input->sink->name);
-
             PA_LLIST_REMOVE(struct output, u->thread_info.outputs, op);
 
             /* Remove the q that leads from this output to the master output */

commit 29d25ec8d99a362030b9c4bd4ad3f9c4ad6f95c7
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Sep 21 00:14:20 2007 +0000

    add CLAMP macro
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1876 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/macro.h b/src/pulsecore/macro.h
index d0dff5e..c6bba43 100644
--- a/src/pulsecore/macro.h
+++ b/src/pulsecore/macro.h
@@ -28,7 +28,7 @@
 #include <unistd.h>
 #include <assert.h>
 #include <limits.h>
-#include <unistd.h>  
+#include <unistd.h>
 
 #include <pulsecore/log.h>
 
@@ -72,6 +72,10 @@ static inline size_t pa_page_align(size_t l) {
 #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;

commit 1fc168b02f9f2ee1b16eeaeee7adcf554c42de64
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Sep 21 00:16:34 2007 +0000

    clamp sample data to -1 .. 1, before passing it to the plugin; if a control port data specification is left empty, initialize with the default value of the plugin
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1877 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-ladspa-sink.c b/src/modules/module-ladspa-sink.c
index 0ff0ba3..fb6da94 100644
--- a/src/modules/module-ladspa-sink.c
+++ b/src/modules/module-ladspa-sink.c
@@ -52,7 +52,7 @@ PA_MODULE_USAGE(
         "channels=<number of channels> "
         "rate=<sample rate> "
         "channel_map=<channel map> "
-        "plugin=<ladspa plugin name> " 
+        "plugin=<ladspa plugin name> "
         "label=<ladspa plugin label> "
         "control=<comma seperated list of input control values>")
 
@@ -61,7 +61,7 @@ PA_MODULE_USAGE(
 struct userdata {
     pa_core *core;
     pa_module *module;
-    
+
     pa_sink *sink, *master;
     pa_sink_input *sink_input;
 
@@ -92,7 +92,7 @@ static const char* const valid_modargs[] = {
 /* 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: {
@@ -100,25 +100,25 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
 
             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_cork(u->sink_input, state == PA_SINK_SUSPENDED);
-    
+
     return 0;
 }
 
@@ -157,14 +157,14 @@ static int sink_input_peek_cb(pa_sink_input *i, size_t length, pa_memchunk *chun
         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;
@@ -172,14 +172,14 @@ static int sink_input_peek_cb(pa_sink_input *i, size_t length, pa_memchunk *chun
             p = src + c;
             q = u->input;
             for (j = 0; j < n; j++, p += u->channels, q++)
-                *q = *p;
+                *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 = *q;
+                *p = CLAMP(*q, -1.0, 1.0);
         }
 
         pa_memblock_release(tchunk.memblock);
@@ -188,9 +188,12 @@ static int sink_input_peek_cb(pa_sink_input *i, size_t length, pa_memchunk *chun
         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;
 }
 
@@ -203,13 +206,13 @@ static void sink_input_drop_cb(pa_sink_input *i, size_t length) {
     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);
@@ -238,7 +241,7 @@ static void sink_input_attach_cb(pa_sink_input *i) {
 
     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);
 }
 
@@ -256,7 +259,7 @@ static void sink_input_kill_cb(pa_sink_input *i) {
     pa_sink_unlink(u->sink);
     pa_sink_unref(u->sink);
     u->sink = NULL;
-    
+
     pa_module_unload_request(u->module);
 }
 
@@ -274,11 +277,12 @@ int pa__init(pa_module*m) {
     const LADSPA_Descriptor *d;
     unsigned long input_port, output_port, p, j, n_control;
     unsigned c;
-    
+    pa_bool_t *use_default = 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;
@@ -308,7 +312,7 @@ int pa__init(pa_module*m) {
     }
 
     cdata = pa_modargs_get_value(ma, "control", NULL);
-    
+
     u = pa_xnew0(struct userdata, 1);
     u->core = m->core;
     u->module = m;
@@ -358,7 +362,7 @@ int pa__init(pa_module*m) {
 
     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])) {
@@ -370,7 +374,7 @@ int pa__init(pa_module*m) {
                 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) {
@@ -381,7 +385,7 @@ int pa__init(pa_module*m) {
                 goto fail;
             }
 
-        } else if (LADSPA_IS_PORT_INPUT(d->PortDescriptors[p]) && LADSPA_IS_PORT_CONTROL(d->PortDescriptors[p])) 
+        } else if (LADSPA_IS_PORT_INPUT(d->PortDescriptors[p]) && LADSPA_IS_PORT_CONTROL(d->PortDescriptors[p]))
             n_control++;
         else
             pa_log("Cannot handle type of port %s", d->PortNames[p]);
@@ -401,9 +405,9 @@ int pa__init(pa_module*m) {
         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);
@@ -423,13 +427,20 @@ int pa__init(pa_module*m) {
         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);
@@ -443,6 +454,7 @@ int pa__init(pa_module*m) {
                 goto fail;
             }
 
+            use_default[p] = FALSE;
             u->control[p++] = f;
         }
 
@@ -453,15 +465,89 @@ int pa__init(pa_module*m) {
 
         h = 0;
         for (p = 0; p < d->PortCount; p++) {
-                
+            LADSPA_PortRangeHintDescriptor hint = d->PortRangeHints[p].HintDescriptor;
+
             if (!LADSPA_IS_PORT_INPUT(d->PortDescriptors[p]) || !LADSPA_IS_PORT_CONTROL(d->PortDescriptors[p]))
                 continue;
 
             pa_assert(h < n_control);
-            
+
+            if (use_default[c]) {
+                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++;
         }
 
@@ -482,7 +568,7 @@ int pa__init(pa_module*m) {
     u->sink->set_state = sink_set_state;
     u->sink->userdata = u;
     u->sink->flags = PA_SINK_LATENCY|PA_SINK_CAN_SUSPEND;
-    
+
     pa_sink_set_module(u->sink, m);
     pa_sink_set_description(u->sink, t = pa_sprintf_malloc("LADSPA on '%s'", master->description));
     pa_xfree(t);
@@ -514,12 +600,16 @@ int pa__init(pa_module*m) {
 
     pa_modargs_free(ma);
 
+    pa_xfree(use_default);
+
     return 0;
 
 fail:
     if (ma)
         pa_modargs_free(ma);
 
+    pa_xfree(use_default);
+
     pa__done(m);
 
     return -1;
@@ -528,7 +618,7 @@ fail:
 void pa__done(pa_module*m) {
     struct userdata *u;
     unsigned c;
-    
+
     pa_assert(m);
 
     if (!(u = m->userdata))
@@ -558,8 +648,8 @@ void pa__done(pa_module*m) {
         pa_xfree(u->output);
 
     pa_xfree(u->input);
-    
+
     pa_xfree(u->control);
-    
+
     pa_xfree(u);
 }

commit c34a2635b20cf72f906999c3ccedf4433ddf96ed
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Sep 21 13:32:00 2007 +0000

    allow _unlink() functions to be called as many times as people want, even before _put() was called
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1878 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c
index c06da13..57c6c60 100644
--- a/src/pulsecore/sink-input.c
+++ b/src/pulsecore/sink-input.c
@@ -264,10 +264,18 @@ static int sink_input_set_state(pa_sink_input *i, pa_sink_input_state_t state) {
 }
 
 void pa_sink_input_unlink(pa_sink_input *i) {
+    pa_bool_t linked;
     pa_assert(i);
-    pa_assert(PA_SINK_INPUT_LINKED(i->state));
 
-    pa_hook_fire(&i->sink->core->hooks[PA_CORE_HOOK_SINK_INPUT_UNLINK], 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;
@@ -276,14 +284,16 @@ void pa_sink_input_unlink(pa_sink_input *i) {
 
     i->sync_prev = i->sync_next = NULL;
 
-    pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i->sink), PA_SINK_MESSAGE_REMOVE_INPUT, i, 0, NULL);
     pa_idxset_remove_by_data(i->sink->core->sink_inputs, i, NULL);
-    pa_idxset_remove_by_data(i->sink->inputs, i, NULL);
-
-    pa_subscription_post(i->sink->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_REMOVE, i->index);
+    if (pa_idxset_remove_by_data(i->sink->inputs, i, NULL))
+        pa_sink_input_unref(i);
 
-    sink_input_set_state(i, PA_SINK_INPUT_UNLINKED);
-    pa_sink_update_status(i->sink);
+    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;
@@ -293,7 +303,11 @@ void pa_sink_input_unlink(pa_sink_input *i) {
     i->detach = NULL;
     i->suspend = NULL;
 
-    pa_hook_fire(&i->sink->core->hooks[PA_CORE_HOOK_SINK_INPUT_UNLINK_POST], i);
+    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->sink = NULL;
     pa_sink_input_unref(i);
 }
diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c
index 409d026..b814f83 100644
--- a/src/pulsecore/sink.c
+++ b/src/pulsecore/sink.c
@@ -200,14 +200,26 @@ static int sink_set_state(pa_sink *s, pa_sink_state_t state) {
 }
 
 void pa_sink_unlink(pa_sink* s) {
+    pa_bool_t linked;
     pa_sink_input *i, *j = NULL;
 
     pa_assert(s);
-    pa_assert(PA_SINK_LINKED(s->state));
 
-    pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SINK_UNLINK], 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()! */
+
+    /* All operations here shall be idempotent, i.e. pa_sink_unlink()
+     * may be called multiple times on the same sink without bad
+     * effects. */
+
+    linked = PA_SINK_LINKED(s->state);
 
-    pa_namereg_unregister(s->core, s->name);
+    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))) {
@@ -216,10 +228,10 @@ void pa_sink_unlink(pa_sink* s) {
         j = i;
     }
 
-    sink_set_state(s, PA_SINK_UNLINKED);
-
-    if (s->monitor_source)
-        pa_source_unlink(s->monitor_source);
+    if (linked)
+        sink_set_state(s, PA_SINK_UNLINKED);
+    else
+        s->state = PA_SINK_UNLINKED;
 
     s->get_latency = NULL;
     s->get_volume = NULL;
@@ -228,9 +240,13 @@ void pa_sink_unlink(pa_sink* s) {
     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);
 
-    pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SINK_UNLINK_POST], s);
+    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_object *o) {
diff --git a/src/pulsecore/source-output.c b/src/pulsecore/source-output.c
index 34eef8b..1991613 100644
--- a/src/pulsecore/source-output.c
+++ b/src/pulsecore/source-output.c
@@ -194,20 +194,29 @@ static int source_output_set_state(pa_source_output *o, pa_source_output_state_t
 }
 
 void pa_source_output_unlink(pa_source_output*o) {
+    pa_bool_t linked;
     pa_assert(o);
-    pa_assert(PA_SOURCE_OUTPUT_LINKED(o->state));
 
-    pa_hook_fire(&o->source->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_UNLINK], o);
+    /* See pa_sink_unlink() for a couple of comments how this function
+     * works */
 
-    pa_asyncmsgq_send(o->source->asyncmsgq, PA_MSGOBJECT(o->source), PA_SOURCE_MESSAGE_REMOVE_OUTPUT, o, 0, NULL);
+    pa_source_output_ref(o);
 
-    pa_idxset_remove_by_data(o->source->core->source_outputs, o, NULL);
-    pa_idxset_remove_by_data(o->source->outputs, o, NULL);
+    linked = PA_SOURCE_OUTPUT_LINKED(o->state);
 
-    pa_subscription_post(o->source->core, PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_REMOVE, o->index);
+    if (linked)
+        pa_hook_fire(&o->source->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_UNLINK], o);
 
-    source_output_set_state(o, PA_SOURCE_OUTPUT_UNLINKED);
-    pa_source_update_status(o->source);
+    pa_idxset_remove_by_data(o->source->core->source_outputs, o, NULL);
+    if (pa_idxset_remove_by_data(o->source->outputs, o, NULL))
+        pa_source_output_unref(o);
+
+    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;
@@ -216,7 +225,10 @@ void pa_source_output_unlink(pa_source_output*o) {
     o->detach = NULL;
     o->suspend = NULL;
 
-    pa_hook_fire(&o->source->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_UNLINK_POST], o);
+    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->source = NULL;
     pa_source_output_unref(o);
@@ -451,7 +463,6 @@ int pa_source_output_process_msg(pa_msgobject *mo, int code, void *userdata, int
 
             return 0;
         }
-
     }
 
     return -1;
diff --git a/src/pulsecore/source.c b/src/pulsecore/source.c
index 8f9cbc4..9745a13 100644
--- a/src/pulsecore/source.c
+++ b/src/pulsecore/source.c
@@ -175,14 +175,21 @@ static int source_set_state(pa_source *s, pa_source_state_t state) {
 }
 
 void pa_source_unlink(pa_source *s) {
+    pa_bool_t linked;
     pa_source_output *o, *j = NULL;
 
     pa_assert(s);
-    pa_assert(PA_SOURCE_LINKED(s->state));
 
-    pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SOURCE_UNLINK], s);
+    /* See pa_sink_unlink() for a couple of comments how this function
+     * works. */
+
+    linked = PA_SOURCE_LINKED(s->state);
+
+    if (linked)
+        pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SOURCE_UNLINK], s);
 
-    pa_namereg_unregister(s->core, s->name);
+    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))) {
@@ -191,7 +198,10 @@ void pa_source_unlink(pa_source *s) {
         j = o;
     }
 
-    source_set_state(s, PA_SOURCE_UNLINKED);
+    if (linked)
+        source_set_state(s, PA_SOURCE_UNLINKED);
+    else
+        s->state = PA_SOURCE_UNLINKED;
 
     s->get_latency = NULL;
     s->get_volume = NULL;
@@ -200,9 +210,10 @@ void pa_source_unlink(pa_source *s) {
     s->get_mute = NULL;
     s->set_state = NULL;
 
-    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);
+    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_object *o) {

commit f26de8077d02c8bba2ed96b4dfb0e6d9f9a2485b
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sat Sep 22 00:19:56 2007 +0000

    add test program for the resampler
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1879 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/Makefile.am b/src/Makefile.am
index 21136aa..9b4cb51 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -236,7 +236,8 @@ noinst_PROGRAMS = \
 		asyncmsgq-test \
 		queue-test \
 		rtpoll-test \
-		sig2str-test
+		sig2str-test \
+		resampler-test
 
 if HAVE_SIGXCPU
 noinst_PROGRAMS += \
@@ -381,6 +382,11 @@ 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)
+
 ###################################
 #         Client library          #
 ###################################
@@ -567,10 +573,10 @@ noinst_LTLIBRARIES = libspeex-resampler-fixed.la libspeex-resampler-float.la lib
 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_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_CPPFLAGS = $(AM_CPPFLAGS)
 libffmpeg_resampler_la_SOURCES = pulsecore/ffmpeg/resample2.c pulsecore/ffmpeg/avcodec.h pulsecore/ffmpeg/dsputil.h
 
 ###################################
@@ -959,7 +965,7 @@ modlibexec_LTLIBRARIES += \
 		module-simple-protocol-unix.la \
 		module-http-protocol-unix.la \
 		module-native-protocol-unix.la \
-		module-esound-protocol-unix.la 
+		module-esound-protocol-unix.la
 endif
 
 if HAVE_MKFIFO
diff --git a/src/tests/resampler-test.c b/src/tests/resampler-test.c
new file mode 100644
index 0000000..e2cf1d8
--- /dev/null
+++ b/src/tests/resampler-test.c
@@ -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 = 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;
+}

commit 9db42672d466ceec4f3d69f03e2d72ea18a8d62e
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sat Sep 22 00:21:08 2007 +0000

    make use of byte swap builtins of gcc if they are available
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1880 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/configure.ac b/configure.ac
index d03774e..0da5253 100644
--- a/configure.ac
+++ b/configure.ac
@@ -97,13 +97,13 @@ if test "x$GCC" = "xyes" ; then
 
     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()])
@@ -221,6 +221,7 @@ AC_CHECK_HEADERS([windows.h winsock2.h ws2tcpip.h])
 
 # Other
 AC_CHECK_HEADERS([sys/ioctl.h])
+AC_CHECK_HEADERS([byteswap.h])
 
 #### Typdefs, structures, etc. ####
 
@@ -302,7 +303,7 @@ ACX_PTHREAD
 
 AC_MSG_CHECKING([for PTHREAD_PRIO_INHERIT])
 AC_LANG_CONFTEST([AC_LANG_SOURCE([[
-#include <pthread.h> 
+#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=$?
@@ -397,8 +398,8 @@ fi
 
 #### Libsamplerate support (optional) ####
 
-AC_ARG_ENABLE([samplerate], 
-    AC_HELP_STRING([--disable-samplerate], [Disable optional libsamplerate support]), 
+AC_ARG_ENABLE([samplerate],
+    AC_HELP_STRING([--disable-samplerate], [Disable optional libsamplerate support]),
         [
             case "${enableval}" in
                 yes) samplerate=yes ;;
@@ -432,8 +433,8 @@ 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 ;;
@@ -465,8 +466,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 ;;
@@ -493,14 +494,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 ;;
@@ -531,8 +532,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 ;;
@@ -562,8 +563,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 ;;
@@ -593,8 +594,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 ;;
@@ -630,8 +631,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 ;;
@@ -661,8 +662,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 ;;
@@ -696,8 +697,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 ;;
@@ -720,8 +721,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 ;;
@@ -746,8 +747,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 ;;
@@ -776,8 +777,8 @@ 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]), 
+AC_ARG_ENABLE([dbus],
+    AC_HELP_STRING([--disable-dbus], [Disable optional D-Bus support]),
         [
             case "${enableval}" in
                 yes) dbus=yes ;;
@@ -787,7 +788,7 @@ AC_ARG_ENABLE([dbus],
         ],
         [dbus=auto])
 
-if test "x$HAVE_HAL" = x1 ; then 
+if test "x$HAVE_HAL" = x1 ; then
    dbus=yes
 fi
 
diff --git a/src/pulsecore/endianmacros.h b/src/pulsecore/endianmacros.h
index a29699b..e2801c1 100644
--- a/src/pulsecore/endianmacros.h
+++ b/src/pulsecore/endianmacros.h
@@ -31,10 +31,21 @@
 #error "Please include config.h before including this file!"
 #endif
 
+#ifdef HAVE_BYTESWAP_H
+#include <byteswap.h>
+#endif
+
+#ifdef HAVE_BYTESWAP_H
+#define INT16_SWAP(x) ((int16_t) bswap_16((uint16_t) x))
+#define UINT16_SWAP(x) ((uint16_t) bswap_16((uint16_t) x))
+#define INT32_SWAP(x) ((int32_t) bswap_32((uint32_t) x))
+#define UINT32_SWAP(x) ((uint32_t) bswap_32((uint32_t) x))
+#else
 #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) ) )
+#endif
 
 #define MAYBE_INT32_SWAP(c,x) ((c) ? INT32_SWAP(x) : x)
 #define MAYBE_UINT32_SWAP(c,x) ((c) ? UINT32_SWAP(x) : x)

commit d7a0876d7ffdac7e48b0664c20408fd429b41d06
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sat Sep 22 00:22:36 2007 +0000

    fix selection of working format
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1881 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/resampler.c b/src/pulsecore/resampler.c
index c4b8179..5bbc6bf 100644
--- a/src/pulsecore/resampler.c
+++ b/src/pulsecore/resampler.c
@@ -29,7 +29,7 @@
 
 #if HAVE_LIBSAMPLERATE
 #include <samplerate.h>
-#endif 
+#endif
 
 #include <liboil/liboilfuncs.h>
 #include <liboil/liboil.h>
@@ -59,7 +59,7 @@ struct pa_resampler {
     unsigned buf1_samples, buf2_samples, buf3_samples, buf4_samples;
 
     pa_sample_format_t work_format;
-    
+
     pa_convert_func_t to_work_format_func;
     pa_convert_func_t from_work_format_func;
 
@@ -69,7 +69,7 @@ struct pa_resampler {
     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;
@@ -114,7 +114,7 @@ static int (* const init_table[])(pa_resampler*r) = {
     [PA_RESAMPLER_SRC_SINC_FASTEST]        = NULL,
     [PA_RESAMPLER_SRC_ZERO_ORDER_HOLD]     = NULL,
     [PA_RESAMPLER_SRC_LINEAR]              = NULL,
-#endif    
+#endif
     [PA_RESAMPLER_TRIVIAL]                 = trivial_init,
     [PA_RESAMPLER_SPEEX_FLOAT_BASE+0]      = speex_init,
     [PA_RESAMPLER_SPEEX_FLOAT_BASE+1]      = speex_init,
@@ -178,12 +178,12 @@ pa_resampler* pa_resampler_new(
         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;
@@ -232,27 +232,30 @@ pa_resampler* pa_resampler_new(
     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) {
+    else if (resample_method == PA_RESAMPLER_TRIVIAL || resample_method == PA_RESAMPLER_COPY) {
 
         if (r->map_required || a->format != b->format) {
 
-            if (a->format == PA_SAMPLE_FLOAT32NE || a->format == PA_SAMPLE_FLOAT32RE)
+            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) {
@@ -302,7 +305,7 @@ void pa_resampler_free(pa_resampler *r) {
         pa_memblock_unref(r->buf3.memblock);
     if (r->buf4.memblock)
         pa_memblock_unref(r->buf4.memblock);
-    
+
     pa_xfree(r);
 }
 
@@ -340,7 +343,7 @@ 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);
@@ -352,7 +355,7 @@ size_t pa_resampler_max_block_size(pa_resampler *r) {
         ss.channels = r->o_ss.channels;
 
     /* We silently assume that the format enum is ordered by size */
-    if (r->o_ss.format > ss.format) 
+    if (r->o_ss.format > ss.format)
         ss.format = r->o_ss.format;
     if (r->work_format > ss.format)
         ss.format = r->work_format;
@@ -361,13 +364,13 @@ size_t pa_resampler_max_block_size(pa_resampler *r) {
         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) {
     pa_assert(r);
-    
+
     return r->resample_method;
 }
 
@@ -422,7 +425,7 @@ int pa_resample_method_supported(pa_resample_method_t m) {
     if (m <= PA_RESAMPLER_SRC_LINEAR)
         return 0;
 #endif
-        
+
     return 1;
 }
 
@@ -446,7 +449,7 @@ pa_resample_method_t pa_parse_resample_method(const char *string) {
 
 static void calc_map_table(pa_resampler *r) {
     unsigned oc;
-    
+
     pa_assert(r);
 
     if (!(r->map_required = (r->i_ss.channels != r->o_ss.channels || !pa_channel_map_equal(&r->i_cm, &r->o_cm))))
@@ -493,7 +496,7 @@ static pa_memchunk* convert_to_work_format(pa_resampler *r, pa_memchunk *input)
 
     r->buf1.index = 0;
     r->buf1.length = r->w_sz * n_samples;
-    
+
     if (!r->buf1.memblock || r->buf1_samples < n_samples) {
         if (r->buf1.memblock)
             pa_memblock_unref(r->buf1.memblock);
@@ -534,7 +537,7 @@ static pa_memchunk *remap_channels(pa_resampler *r, pa_memchunk *input) {
 
     r->buf2.index = 0;
     r->buf2.length = r->w_sz * out_n_samples;
-    
+
     if (!r->buf2.memblock || r->buf2_samples < out_n_samples) {
         if (r->buf2.memblock)
             pa_memblock_unref(r->buf2.memblock);
@@ -553,11 +556,11 @@ static pa_memchunk *remap_channels(pa_resampler *r, pa_memchunk *input) {
 
     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,
@@ -574,7 +577,7 @@ static pa_memchunk *remap_channels(pa_resampler *r, pa_memchunk *input) {
             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,
@@ -618,7 +621,7 @@ static pa_memchunk *resample(pa_resampler *r, pa_memchunk *input) {
 
     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);
@@ -629,7 +632,7 @@ static pa_memchunk *resample(pa_resampler *r, pa_memchunk *input) {
 
     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;
-    
+
     return &r->buf3;
 }
 
@@ -650,7 +653,7 @@ static pa_memchunk *convert_from_work_format(pa_resampler *r, pa_memchunk *input
 
     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);
@@ -688,7 +691,7 @@ void pa_resampler_run(pa_resampler *r, const pa_memchunk *in, pa_memchunk *out)
     if (buf->length) {
         buf = convert_from_work_format(r, buf);
         *out = *buf;
-        
+
         if (buf == in)
             pa_memblock_ref(buf->memblock);
         else
@@ -702,14 +705,14 @@ void pa_resampler_run(pa_resampler *r, const pa_memchunk *in, pa_memchunk *out)
 #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;
-    
+
     pa_assert(r);
     pa_assert(input);
     pa_assert(output);
     pa_assert(out_n_frames);
-    
+
     memset(&data, 0, sizeof(data));
-    
+
     data.data_in = (float*) ((uint8_t*) pa_memblock_acquire(input->memblock) + input->index);
     data.input_frames = in_n_frames;
 
@@ -736,16 +739,16 @@ static void libsamplerate_update_rates(pa_resampler *r) {
 
 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) {
     int err;
-    
+
     pa_assert(r);
-    
+
     if (!(r->src.state = src_new(r->resample_method, r->o_ss.channels, &err)))
         return -1;
 
@@ -767,7 +770,7 @@ static void speex_resample_float(pa_resampler *r, const pa_memchunk *input, unsi
     pa_assert(input);
     pa_assert(output);
     pa_assert(out_n_frames);
-    
+
     in = (float*) ((uint8_t*) pa_memblock_acquire(input->memblock) + input->index);
     out = (float*) ((uint8_t*) pa_memblock_acquire(output->memblock) + output->index);
 
@@ -788,7 +791,7 @@ static void speex_resample_int(pa_resampler *r, const pa_memchunk *input, unsign
     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);
 
@@ -804,7 +807,7 @@ static void speex_resample_int(pa_resampler *r, const pa_memchunk *input, unsign
 static void speex_update_rates(pa_resampler *r) {
     pa_assert(r);
 
-    if (r->resample_method >= PA_RESAMPLER_SPEEX_FIXED_BASE && r->resample_method <= PA_RESAMPLER_SPEEX_FIXED_MAX) 
+    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);
@@ -814,11 +817,11 @@ static void speex_update_rates(pa_resampler *r) {
 
 static void speex_free(pa_resampler *r) {
     pa_assert(r);
-    
+
     if (!r->speex.state)
         return;
-    
-    if (r->resample_method >= PA_RESAMPLER_SPEEX_FIXED_BASE && r->resample_method <= PA_RESAMPLER_SPEEX_FIXED_MAX) 
+
+    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);
@@ -828,17 +831,17 @@ static void speex_free(pa_resampler *r) {
 
 static int speex_init(pa_resampler *r) {
     int q, err;
-    
+
     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;
 
@@ -848,7 +851,7 @@ static int speex_init(pa_resampler *r) {
         q = r->resample_method - PA_RESAMPLER_SPEEX_FLOAT_BASE;
 
         pa_log_info("Choosing speex quality setting %i.", q);
-        
+
         if (!(r->speex.state = paspfl_resampler_init(r->o_ss.channels, r->i_ss.rate, r->o_ss.rate, q, &err)))
             return -1;
 
@@ -864,35 +867,35 @@ static void trivial_resample(pa_resampler *r, const pa_memchunk *input, unsigned
     size_t fz;
     unsigned o_index;
     void *src, *dst;
-    
+
     pa_assert(r);
     pa_assert(input);
     pa_assert(output);
     pa_assert(out_n_frames);
 
     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;
-        
+
         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);   
+                   (uint8_t*) src + fz * j, fz);
     }
-    
+
     pa_memblock_release(input->memblock);
     pa_memblock_release(output->memblock);
-    
+
     *out_n_frames = o_index;
 
     r->trivial.i_counter += in_n_frames;
@@ -929,7 +932,7 @@ static int trivial_init(pa_resampler*r) {
 
 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);
@@ -1008,9 +1011,9 @@ static void ffmpeg_resample(pa_resampler *r, const pa_memchunk *input, unsigned
 
 static void ffmpeg_free(pa_resampler *r) {
     unsigned c;
-    
+
     pa_assert(r);
-    
+
     if (r->ffmpeg.state)
         av_resample_close(r->ffmpeg.state);
 
@@ -1021,21 +1024,21 @@ static void ffmpeg_free(pa_resampler *r) {
 
 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++) 
+    for (c = 0; c < PA_ELEMENTSOF(r->ffmpeg.buf); c++)
         pa_memchunk_reset(&r->ffmpeg.buf[c]);
 
     return 0;
@@ -1047,7 +1050,7 @@ 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;

commit 78a9ad336bc9f06f3995dac824fb4e1e724d3cdb
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sat Sep 22 00:25:17 2007 +0000

    - rework volume adjustment code to not require fp
    - don't hit an assert when we cannot do a volume adjustment, instead, print a warning and go on
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1882 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/sample-util.c b/src/pulsecore/sample-util.c
index add6608..248a09b 100644
--- a/src/pulsecore/sample-util.c
+++ b/src/pulsecore/sample-util.c
@@ -57,7 +57,7 @@ pa_memblock *pa_silence_memblock_new(pa_mempool *pool, const pa_sample_spec *spe
 
     if (length <= 0)
         length = 1;
-    
+
     length *= fs;
 
     return pa_silence_memblock(pa_memblock_new(pool, length), spec);
@@ -173,12 +173,10 @@ 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)
@@ -222,12 +220,10 @@ 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) = INT16_SWAP((int16_t) sum);
                 data = (uint8_t*) data + sizeof(int16_t);
 
                 if (++channel >= spec->channels)
@@ -271,9 +267,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);
@@ -368,23 +362,22 @@ void pa_volume_memchunk(
     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]);
+                linear[channel] = (int32_t) (pa_sw_volume_to_linear(volume->values[channel]) * 0x10000);
 
             for (channel = 0, d = (int16_t*) ((uint8_t*) ptr + c->index), n = c->length/sizeof(int16_t); n > 0; d++, n--) {
-                int32_t t = (int32_t)(*d);
-
-                t = (int32_t) (t * linear[channel]);
-
-                if (t < -0x8000) t = -0x8000;
-                if (t > 0x7FFF) t = 0x7FFF;
+                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)
@@ -397,19 +390,17 @@ void pa_volume_memchunk(
             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]);
+                linear[channel] = (int32_t) (pa_sw_volume_to_linear(volume->values[channel]) * 0x10000);
 
             for (channel = 0, d = (int16_t*) ((uint8_t*) ptr + c->index), n = c->length/sizeof(int16_t); n > 0; d++, n--) {
-                int32_t t = (int32_t)(INT16_SWAP(*d));
-
-                t = (int32_t) (t * linear[channel]);
-
-                if (t < -0x8000) t = -0x8000;
-                if (t > 0x7FFF) t = 0x7FFF;
+                int32_t t;
 
+                t = (int32_t)(INT16_SWAP(*d));
+                t = (t * linear[channel]) / 0x10000;
+                t = CLAMP(t, -0x8000, 0x7FFF);
                 *d = INT16_SWAP((int16_t) t);
 
                 if (++channel >= spec->channels)
@@ -422,16 +413,18 @@ void pa_volume_memchunk(
         case PA_SAMPLE_U8: {
             uint8_t *d;
             size_t n;
-            unsigned channel = 0;
-
-            for (d = (uint8_t*) ptr + 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)
@@ -457,7 +450,6 @@ void pa_volume_memchunk(
                     continue;
 
                 v = (float) pa_sw_volume_to_linear(volume->values[channel]);
-
                 t = d + channel;
                 oil_scalarmult_f32(t, skip, t, skip, &v, n);
             }
@@ -465,9 +457,8 @@ void pa_volume_memchunk(
         }
 
         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);
@@ -477,7 +468,7 @@ 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;
@@ -485,11 +476,10 @@ size_t pa_frame_align(size_t l, const pa_sample_spec *ss) {
 
 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;
 }
-

commit 668340099c1ebc6d3d28bf04dce5249ee28b223a
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sat Sep 22 00:26:18 2007 +0000

    rework a couple of sample type converters, to actually work
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1883 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/sconv-s16le.c b/src/pulsecore/sconv-s16le.c
index c82708c..86b3729 100644
--- a/src/pulsecore/sconv-s16le.c
+++ b/src/pulsecore/sconv-s16le.c
@@ -82,12 +82,7 @@ void pa_sconv_s16le_from_float32ne(unsigned n, const float *a, int16_t *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);
         *(b++) = INT16_TO(s);
     }
@@ -104,8 +99,6 @@ void pa_sconv_s16le_to_float32re(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 = *(a++);
         float k = ((float) INT16_FROM(s))/0x7FFF;
@@ -113,31 +106,19 @@ void pa_sconv_s16le_to_float32re(unsigned n, const int16_t *a, float *b) {
         *j = UINT32_SWAP(*j);
         *(b++) = k;
     }
-
-#endif
 }
 
 void pa_sconv_s16le_from_float32re(unsigned n, const float *a, int16_t *b) {
     pa_assert(a);
     pa_assert(b);
 
-#if SWAP_WORDS == 1
-
     for (; n > 0; n--) {
         int16_t s;
         float v = *(a++);
         uint32_t *j = (uint32_t*) &v;
         *j = UINT32_SWAP(*j);
-
-        if (v > 1)
-            v = 1;
-
-        if (v < -1)
-            v = -1;
-
+        v = CLAMP(v, -1, 1);
         s = (int16_t) (v * 0x7FFF);
         *(b++) = INT16_TO(s);
     }
-
-#endif
 }
diff --git a/src/pulsecore/sconv.c b/src/pulsecore/sconv.c
index 4986ba7..933192b 100644
--- a/src/pulsecore/sconv.c
+++ b/src/pulsecore/sconv.c
@@ -43,7 +43,7 @@
 
 /* u8 */
 static void u8_to_float32ne(unsigned n, const uint8_t *a, float *b) {
-    static const double add = -128.0/127.0, factor = 1.0/127.0;
+    static const double add = -1, factor = 1.0/128.0;
 
     pa_assert(a);
     pa_assert(b);
@@ -52,7 +52,7 @@ static void u8_to_float32ne(unsigned n, const uint8_t *a, float *b) {
 }
 
 static void u8_from_float32ne(unsigned n, const float *a, uint8_t *b) {
-    static const double add = 128.0, factor = 127.0;
+    static const double add = 128, factor = 127.0;
 
     pa_assert(a);
     pa_assert(b);
@@ -61,7 +61,7 @@ static void u8_from_float32ne(unsigned n, const float *a, uint8_t *b) {
 }
 
 static void u8_to_s16ne(unsigned n, const uint8_t *a, int16_t *b) {
-    static const int16_t add = -128, factor = 0x100;
+    static const int16_t add = -0x80, factor = 0x100;
 
     pa_assert(a);
     pa_assert(b);
@@ -75,8 +75,8 @@ 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 ++, a++)
+
+    for (; n > 0; n--, a++, b++)
         *b = (uint8_t) (*a / 0x100 + 0x80);
 }
 
@@ -121,7 +121,7 @@ static void ulaw_to_float32ne(unsigned n, const uint8_t *a, float *b) {
     pa_assert(b);
 
     for (; n > 0; n--)
-        *(b++) = st_ulaw2linear16(*(a++)) * 1.0F / 0x7FFF;
+        *(b++) = (float) st_ulaw2linear16(*(a++)) / 0x8000;
 }
 
 static void ulaw_from_float32ne(unsigned n, const float *a, uint8_t *b) {
@@ -130,14 +130,9 @@ static void ulaw_from_float32ne(unsigned n, const float *a, uint8_t *b) {
 
     for (; n > 0; n--) {
         float v = *(a++);
-
-        if (v > 1)
-            v = 1;
-
-        if (v < -1)
-            v = -1;
-
-        *(b++) = st_14linear2ulaw((int16_t) (v * 0x1FFF));
+        v = CLAMP(v, -1, 1);
+        v *= 0x1FFF;
+        *(b++) = st_14linear2ulaw((int16_t) v);
     }
 }
 
@@ -164,7 +159,7 @@ static void alaw_to_float32ne(unsigned n, const uint8_t *a, float *b) {
     pa_assert(b);
 
     for (; n > 0; n--, a++, b++)
-        *b = st_alaw2linear16(*a) * 1.0F / 0x7FFF;
+        *b = (float) st_alaw2linear16(*a) / 0x8000;
 }
 
 static void alaw_from_float32ne(unsigned n, const float *a, uint8_t *b) {
@@ -173,14 +168,9 @@ static void alaw_from_float32ne(unsigned n, const float *a, uint8_t *b) {
 
     for (; n > 0; n--, a++, b++) {
         float v = *a;
-
-        if (v > 1)
-            v = 1;
-
-        if (v < -1)
-            v = -1;
-
-        *b = st_13linear2alaw((int16_t) (v * 0xFFF));
+        v = CLAMP(v, -1, 1);
+        v *= 0xFFF;
+        *b = st_13linear2alaw((int16_t) v);
     }
 }
 
@@ -196,7 +186,7 @@ static void alaw_from_s16ne(unsigned n, const int16_t *a, uint8_t *b) {
     pa_assert(a);
     pa_assert(b);
 
-    for (; n > 0; n--)
+    for (; n > 0; n--, a++, b++)
         *b = st_13linear2alaw(*a >> 3);
 }
 

commit c6b43bf119d59b05cc270027080bd616b560db1b
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sat Sep 22 01:16:14 2007 +0000

    prefix by order macros with PA_
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1884 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/endianmacros.h b/src/pulsecore/endianmacros.h
index e2801c1..8f7cfad 100644
--- a/src/pulsecore/endianmacros.h
+++ b/src/pulsecore/endianmacros.h
@@ -36,56 +36,59 @@
 #endif
 
 #ifdef HAVE_BYTESWAP_H
-#define INT16_SWAP(x) ((int16_t) bswap_16((uint16_t) x))
-#define UINT16_SWAP(x) ((uint16_t) bswap_16((uint16_t) x))
-#define INT32_SWAP(x) ((int32_t) bswap_32((uint32_t) x))
-#define UINT32_SWAP(x) ((uint32_t) bswap_32((uint32_t) x))
+#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 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) ) )
+#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 MAYBE_INT32_SWAP(c,x) ((c) ? INT32_SWAP(x) : x)
-#define MAYBE_UINT32_SWAP(c,x) ((c) ? UINT32_SWAP(x) : x)
+#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 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
diff --git a/src/pulsecore/esound.h b/src/pulsecore/esound.h
index 3778a53..ea6a566 100644
--- a/src/pulsecore/esound.h
+++ b/src/pulsecore/esound.h
@@ -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/protocol-esound.c b/src/pulsecore/protocol-esound.c
index b694363..adefaf9 100644
--- a/src/pulsecore/protocol-esound.c
+++ b/src/pulsecore/protocol-esound.c
@@ -80,7 +80,7 @@
 
 typedef struct connection {
     pa_msgobject parent;
-    
+
     uint32_t index;
     int dead;
     pa_protocol_esound *protocol;
@@ -125,7 +125,7 @@ struct pa_protocol_esound {
     int public;
     pa_socket_server *server;
     pa_idxset *connections;
-    
+
     char *sink_name, *source_name;
     unsigned n_player;
     uint8_t esd_key[ESD_KEY_LEN];
@@ -227,7 +227,7 @@ static void connection_unlink(connection *c) {
         pa_client_free(c->client);
         c->client = NULL;
     }
-    
+
     if (c->state == ESD_STREAMING_DATA)
         c->protocol->n_player--;
 
@@ -254,7 +254,7 @@ static void connection_unlink(connection *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)
@@ -381,11 +381,11 @@ static int esd_proto_stream_play(connection *c, PA_GCC_UNUSED esd_proto_t reques
     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);
+    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;
@@ -445,7 +445,7 @@ static int esd_proto_stream_play(connection *c, PA_GCC_UNUSED esd_proto_t reques
     pa_atomic_store(&c->playback.missing, pa_memblockq_missing(c->input_memblockq));
 
     pa_sink_input_put(c->sink_input);
-    
+
     return 0;
 }
 
@@ -462,11 +462,11 @@ static int esd_proto_stream_record(connection *c, esd_proto_t request, const voi
     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);
+    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;
@@ -559,7 +559,7 @@ static int esd_proto_get_latency(connection *c, PA_GCC_UNUSED esd_proto_t reques
         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;
 }
@@ -582,9 +582,9 @@ static int esd_proto_server_info(connection *c, PA_GCC_UNUSED esd_proto_t reques
 
     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;
@@ -631,7 +631,7 @@ static int esd_proto_all_info(connection *c, esd_proto_t request, const void *da
         }
 
         /* 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 */
@@ -643,19 +643,19 @@ static int esd_proto_all_info(connection *c, esd_proto_t request, const void *da
         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;
@@ -677,7 +677,7 @@ static int esd_proto_all_info(connection *c, esd_proto_t request, const void *da
             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 */
@@ -689,23 +689,23 @@ static int esd_proto_all_info(connection *c, esd_proto_t request, const void *da
             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;
@@ -729,15 +729,15 @@ static int esd_proto_stream_pan(connection *c, PA_GCC_UNUSED esd_proto_t request
     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) {
@@ -766,11 +766,11 @@ static int esd_proto_sample_cache(connection *c, PA_GCC_UNUSED esd_proto_t reque
     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;
@@ -779,7 +779,7 @@ static int esd_proto_sample_cache(connection *c, PA_GCC_UNUSED esd_proto_t reque
     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);
@@ -842,7 +842,7 @@ static int esd_proto_sample_free_or_play(connection *c, esd_proto_t request, con
     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;
 
@@ -884,7 +884,7 @@ static int esd_proto_standby_or_resume(connection *c, PA_GCC_UNUSED esd_proto_t
 
 static void client_kill_cb(pa_client *c) {
     pa_assert(c);
-    
+
     connection_unlink(CONNECTION(c->userdata));
 }
 
@@ -907,7 +907,7 @@ static int do_read(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.");
@@ -950,7 +950,7 @@ static int do_read(connection *c) {
         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 (errno == EINTR || errno == EAGAIN)
                 return 0;
-            
+
             pa_log_debug("read(): %s", r < 0 ? pa_cstrerror(errno) : "EOF");
             return -1;
         }
@@ -976,11 +976,11 @@ static int do_read(connection *c) {
         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 (errno == EINTR || errno == EAGAIN)
                 return 0;
-            
+
             pa_log_debug("read(): %s", r < 0 ? pa_cstrerror(errno) : "EOF");
             return -1;
         }
@@ -1038,9 +1038,9 @@ static int do_read(connection *c) {
         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 (errno == EINTR || errno == EAGAIN)
                 return 0;
 
@@ -1074,7 +1074,7 @@ static int do_write(connection *c) {
 
             if (errno == EINTR || errno == EAGAIN)
                 return 0;
-            
+
             pa_log("write(): %s", pa_cstrerror(errno));
             return -1;
         }
@@ -1098,12 +1098,12 @@ static int do_write(connection *c) {
         pa_memblock_release(chunk.memblock);
 
         pa_memblock_unref(chunk.memblock);
-        
+
         if (r < 0) {
 
             if (errno == EINTR || errno == EAGAIN)
                 return 0;
-        
+
             pa_log("write(): %s", pa_cstrerror(errno));
             return -1;
         }
@@ -1178,7 +1178,7 @@ static int connection_process_msg(pa_msgobject *o, int code, void*userdata, int6
         case CONNECTION_MESSAGE_REQUEST_DATA:
             do_work(c);
             break;
-            
+
         case CONNECTION_MESSAGE_POST_DATA:
 /*             pa_log("got data %u", chunk->length); */
             pa_memblockq_push_align(c->output_memblockq, chunk);
@@ -1213,7 +1213,7 @@ static int sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int
             pa_memblockq_push_align(c->input_memblockq, chunk);
 
 /*             pa_log("got data, %u", pa_memblockq_get_length(c->input_memblockq)); */
-            
+
             return 0;
         }
 
@@ -1240,7 +1240,7 @@ static int sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int
 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);
@@ -1314,7 +1314,7 @@ static pa_usec_t source_output_get_latency_cb(pa_source_output *o) {
 
 static void auth_timeout(pa_mainloop_api*m, pa_time_event *e, const struct timeval *tv, void *userdata) {
     connection *c = CONNECTION(userdata);
-    
+
     pa_assert(m);
     pa_assert(tv);
     connection_assert_ref(c);
@@ -1328,7 +1328,7 @@ static void on_connection(pa_socket_server*s, pa_iochannel *io, void *userdata)
     connection *c;
     pa_protocol_esound *p = userdata;
     char cname[256], pname[128];
-    
+
     pa_assert(s);
     pa_assert(io);
     pa_assert(p);
diff --git a/src/pulsecore/sample-util.c b/src/pulsecore/sample-util.c
index 248a09b..bc83ac6 100644
--- a/src/pulsecore/sample-util.c
+++ b/src/pulsecore/sample-util.c
@@ -208,7 +208,7 @@ size_t pa_mix(
                         if (cvolume == PA_VOLUME_MUTED)
                             v = 0;
                         else {
-                            v = INT16_SWAP(*((int16_t*) ((uint8_t*) streams[i].internal + 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));
@@ -223,7 +223,7 @@ size_t pa_mix(
                     sum = CLAMP(sum, -0x8000, 0x7FFF);
                 }
 
-                *((int16_t*) data) = INT16_SWAP((int16_t) sum);
+                *((int16_t*) data) = PA_INT16_SWAP((int16_t) sum);
                 data = (uint8_t*) data + sizeof(int16_t);
 
                 if (++channel >= spec->channels)
@@ -398,10 +398,10 @@ void pa_volume_memchunk(
             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)(INT16_SWAP(*d));
+                t = (int32_t)(PA_INT16_SWAP(*d));
                 t = (t * linear[channel]) / 0x10000;
                 t = CLAMP(t, -0x8000, 0x7FFF);
-                *d = INT16_SWAP((int16_t) t);
+                *d = PA_INT16_SWAP((int16_t) t);
 
                 if (++channel >= spec->channels)
                     channel = 0;
diff --git a/src/pulsecore/sconv-s16be.c b/src/pulsecore/sconv-s16be.c
index 658b3f5..f74d028 100644
--- a/src/pulsecore/sconv-s16be.c
+++ b/src/pulsecore/sconv-s16be.c
@@ -27,8 +27,8 @@
 
 #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
diff --git a/src/pulsecore/sconv-s16le.c b/src/pulsecore/sconv-s16le.c
index 86b3729..6925052 100644
--- a/src/pulsecore/sconv-s16le.c
+++ b/src/pulsecore/sconv-s16le.c
@@ -38,11 +38,11 @@
 #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
@@ -103,7 +103,7 @@ void pa_sconv_s16le_to_float32re(unsigned n, const int16_t *a, float *b) {
         int16_t s = *(a++);
         float k = ((float) INT16_FROM(s))/0x7FFF;
         uint32_t *j = (uint32_t*) &k;
-        *j = UINT32_SWAP(*j);
+        *j = PA_UINT32_SWAP(*j);
         *(b++) = k;
     }
 }
@@ -116,7 +116,7 @@ void pa_sconv_s16le_from_float32re(unsigned n, const float *a, int16_t *b) {
         int16_t s;
         float v = *(a++);
         uint32_t *j = (uint32_t*) &v;
-        *j = UINT32_SWAP(*j);
+        *j = PA_UINT32_SWAP(*j);
         v = CLAMP(v, -1, 1);
         s = (int16_t) (v * 0x7FFF);
         *(b++) = INT16_TO(s);
diff --git a/src/pulsecore/sconv.c b/src/pulsecore/sconv.c
index 933192b..7f5da63 100644
--- a/src/pulsecore/sconv.c
+++ b/src/pulsecore/sconv.c
@@ -94,7 +94,7 @@ static void float32re_to_float32ne(unsigned n, const float *a, float *b) {
     pa_assert(b);
 
     for (; n > 0; n--, a++, b++)
-        *((uint32_t *) b) = UINT32_SWAP(*((uint32_t *) a));
+        *((uint32_t *) b) = PA_UINT32_SWAP(*((uint32_t *) a));
 }
 
 /* s16 */
@@ -111,7 +111,7 @@ static void s16re_to_s16ne(unsigned n, const int16_t *a, int16_t *b) {
     pa_assert(b);
 
     for (; n > 0; n--, a++, b++)
-        *b = UINT16_SWAP(*a);
+        *b = PA_UINT16_SWAP(*a);
 }
 
 /* ulaw */
diff --git a/src/tests/resampler-test.c b/src/tests/resampler-test.c
index e2cf1d8..3b4a738 100644
--- a/src/tests/resampler-test.c
+++ b/src/tests/resampler-test.c
@@ -38,7 +38,7 @@
 
 static float swap_float(float a) {
     uint32_t *b = (uint32_t*) &a;
-    *b = UINT32_SWAP(*b);
+    *b = PA_UINT32_SWAP(*b);
     return a;
 }
 

commit 6cfb09698a14b4634b447410496424eb0126bfce
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sat Sep 22 01:35:32 2007 +0000

    include the name of the master sink in the name for piggy-backed virtual sinks
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1885 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-ladspa-sink.c b/src/modules/module-ladspa-sink.c
index fb6da94..6919594 100644
--- a/src/modules/module-ladspa-sink.c
+++ b/src/modules/module-ladspa-sink.c
@@ -56,8 +56,6 @@ PA_MODULE_USAGE(
         "label=<ladspa plugin label> "
         "control=<comma seperated list of input control values>")
 
-#define DEFAULT_SINK_NAME "ladspa"
-
 struct userdata {
     pa_core *core;
     pa_module *module;
@@ -278,6 +276,7 @@ int pa__init(pa_module*m) {
     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);
 
@@ -558,8 +557,10 @@ int pa__init(pa_module*m) {
         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))) {
+    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;
     }
@@ -570,7 +571,7 @@ int pa__init(pa_module*m) {
     u->sink->flags = PA_SINK_LATENCY|PA_SINK_CAN_SUSPEND;
 
     pa_sink_set_module(u->sink, m);
-    pa_sink_set_description(u->sink, t = pa_sprintf_malloc("LADSPA on '%s'", master->description));
+    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);
@@ -601,6 +602,7 @@ int pa__init(pa_module*m) {
     pa_modargs_free(ma);
 
     pa_xfree(use_default);
+    pa_xfree(default_sink_name);
 
     return 0;
 
@@ -609,6 +611,7 @@ fail:
         pa_modargs_free(ma);
 
     pa_xfree(use_default);
+    pa_xfree(default_sink_name);
 
     pa__done(m);
 
diff --git a/src/modules/module-remap-sink.c b/src/modules/module-remap-sink.c
index 1d272b1..bff787b 100644
--- a/src/modules/module-remap-sink.c
+++ b/src/modules/module-remap-sink.c
@@ -52,12 +52,10 @@ PA_MODULE_USAGE(
         "rate=<sample rate> "
         "channel_map=<channel map>")
 
-#define DEFAULT_SINK_NAME "remapped"
-
 struct userdata {
     pa_core *core;
     pa_module *module;
-    
+
     pa_sink *sink, *master;
     pa_sink_input *sink_input;
 
@@ -67,7 +65,7 @@ struct userdata {
 static const char* const valid_modargs[] = {
     "sink_name",
     "master",
-    "master_channel_map", 
+    "master_channel_map",
     "rate",
     "format",
     "channels",
@@ -78,7 +76,7 @@ static const char* const valid_modargs[] = {
 /* 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: {
@@ -86,25 +84,25 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
 
             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_cork(u->sink_input, state == PA_SINK_SUSPENDED);
-    
+
     return 0;
 }
 
@@ -149,13 +147,13 @@ static void sink_input_drop_cb(pa_sink_input *i, size_t length) {
     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);
@@ -184,7 +182,7 @@ static void sink_input_attach_cb(pa_sink_input *i) {
 
     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);
 }
 
@@ -202,7 +200,7 @@ static void sink_input_kill_cb(pa_sink_input *i) {
     pa_sink_unlink(u->sink);
     pa_sink_unref(u->sink);
     u->sink = NULL;
-    
+
     pa_module_unload_request(u->module);
 }
 
@@ -214,6 +212,7 @@ int pa__init(pa_module*m) {
     char *t;
     pa_sink *master;
     pa_sink_input_new_data data;
+    char *default_sink_name = NULL;
 
     pa_assert(m);
 
@@ -244,7 +243,7 @@ int pa__init(pa_module*m) {
         pa_log("Number of channels doesn't match");
         goto fail;
     }
-    
+
     u = pa_xnew0(struct userdata, 1);
     u->core = m->core;
     u->module = m;
@@ -252,8 +251,10 @@ int pa__init(pa_module*m) {
     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))) {
+    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;
     }
@@ -262,9 +263,9 @@ int pa__init(pa_module*m) {
     u->sink->set_state = sink_set_state;
     u->sink->userdata = u;
     u->sink->flags = PA_SINK_LATENCY|PA_SINK_CAN_SUSPEND;
-    
+
     pa_sink_set_module(u->sink, m);
-    pa_sink_set_description(u->sink, t = pa_sprintf_malloc("Remapped sink of '%s'", master->description));
+    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);
@@ -273,7 +274,7 @@ int pa__init(pa_module*m) {
     pa_sink_input_new_data_init(&data);
     data.sink = u->master;
     data.driver = __FILE__;
-    data.name = "Remapped stream";
+    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;
@@ -293,6 +294,7 @@ int pa__init(pa_module*m) {
     pa_sink_input_put(u->sink_input);
 
     pa_modargs_free(ma);
+    pa_xfree(default_sink_name);
 
     return 0;
 
@@ -302,12 +304,14 @@ fail:
 
     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))

commit e04a8576bb113c19a51d026dd30de700b07055c7
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sat Sep 22 02:00:32 2007 +0000

    minor optimization
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1886 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c
index 57c6c60..9360bee 100644
--- a/src/pulsecore/sink-input.c
+++ b/src/pulsecore/sink-input.c
@@ -690,7 +690,7 @@ 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_resampler *new_resampler = NULL;
+    pa_resampler *new_resampler;
     pa_sink *origin;
     pa_usec_t silence_usec = 0;
     pa_sink_input_move_info info;
@@ -739,7 +739,8 @@ int pa_sink_input_move_to(pa_sink_input *i, pa_sink *dest, int immediately) {
             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);
 

commit 1c44be2a7b37584bc95dd25930f7f734cef0e5b8
Author: Tanu Kaskinen <tanuk at iki.fi>
Date:   Sat Sep 22 07:31:29 2007 +0000

    Correct the parameter positions with the pa_cvolume_set() call.
    
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1887 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-match.c b/src/modules/module-match.c
index 373ed48..5a92296 100644
--- a/src/modules/module-match.c
+++ b/src/modules/module-match.c
@@ -182,7 +182,7 @@ 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);
         }
     }

commit ecad93740968fc84b394b138b23351469ef00f9f
Author: Tanu Kaskinen <tanuk at iki.fi>
Date:   Sat Sep 22 08:39:07 2007 +0000

    Fix the assignment of control values by using the right variable for indexing.
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1888 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-ladspa-sink.c b/src/modules/module-ladspa-sink.c
index 6919594..38b7e01 100644
--- a/src/modules/module-ladspa-sink.c
+++ b/src/modules/module-ladspa-sink.c
@@ -471,7 +471,7 @@ int pa__init(pa_module*m) {
 
             pa_assert(h < n_control);
 
-            if (use_default[c]) {
+            if (use_default[h]) {
                 LADSPA_Data lower, upper;
 
                 if (!LADSPA_IS_HINT_HAS_DEFAULT(hint)) {

commit 7bcbf16e9483ea111d6c708015b5c0154edca1d4
Author: Tanu Kaskinen <tanuk at iki.fi>
Date:   Sun Sep 23 14:39:39 2007 +0000

    Comment typo fix.
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1889 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/resampler.h b/src/pulsecore/resampler.h
index 8de8ad7..23e1acb 100644
--- a/src/pulsecore/resampler.h
+++ b/src/pulsecore/resampler.h
@@ -63,7 +63,7 @@ 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);
 
-/* Requires the maximum size of input blocks we can process without needing bounce buffers larger than the mempool tile size. */
+/* 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 */

commit de079ac40474fdf845de799b6ced5892282a70fe
Author: Tanu Kaskinen <tanuk at iki.fi>
Date:   Sun Sep 23 14:51:07 2007 +0000

    Added an assertion for the case when the sink programmer hasn't installed the thread_mq properly.
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1890 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c
index 24f5997..c282c17 100644
--- a/src/pulsecore/protocol-native.c
+++ b/src/pulsecore/protocol-native.c
@@ -792,8 +792,10 @@ static void request_bytes(playback_stream *s) {
     minreq = pa_memblockq_get_minreq(s->memblockq);
 
     previous_missing = pa_atomic_add(&s->missing, delta);
-    if (previous_missing < minreq && previous_missing+delta >= minreq)
+    if (previous_missing < minreq && previous_missing+delta >= 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(connection *c) {

commit 286068526977a9de141a009897accd4393cce894
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sun Sep 23 19:23:44 2007 +0000

    use O_NOFOLLOW when creating PID file, to avoid symlink vulnerability
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1891 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/pid.c b/src/pulsecore/pid.c
index 44f5e84..38d2681 100644
--- a/src/pulsecore/pid.c
+++ b/src/pulsecore/pid.c
@@ -88,7 +88,12 @@ static int open_pid_file(const char *fn, int mode) {
     for (;;) {
         struct stat st;
 
-        if ((fd = open(fn, mode, S_IRUSR|S_IWUSR)) < 0) {
+        if ((fd = open(fn, mode|O_NOCTTY
+#ifdef O_NOFOLLOW
+                       |O_NOFOLLOW
+#endif
+                       , S_IRUSR|S_IWUSR
+             )) < 0) {
             if (mode != O_RDONLY || errno != ENOENT)
                 pa_log_warn("Failed to open PID file '%s': %s", fn, pa_cstrerror(errno));
             goto fail;
@@ -184,7 +189,7 @@ int pa_pid_file_create(void) {
 fail:
     if (fd >= 0) {
         pa_lock_fd(fd, 0);
-        
+
         if (pa_close(fd) < 0) {
             pa_log("Failed to close PID file '%s': %s", fn, pa_cstrerror(errno));
             ret = -1;
@@ -204,8 +209,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("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;
     }
 

commit fc00eaf1d4b854c4dd25edaf25bdb5a800f7827a
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sun Sep 23 19:30:56 2007 +0000

    use O_NOFOLLOW when creating lock files, too
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1892 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/core-util.c b/src/pulsecore/core-util.c
index 5532c40..6db0870 100644
--- a/src/pulsecore/core-util.c
+++ b/src/pulsecore/core-util.c
@@ -144,7 +144,7 @@ void pa_make_fd_nonblock(int fd) {
 
     if (!(v & O_NONBLOCK))
         pa_assert_se(fcntl(fd, F_SETFL, v|O_NONBLOCK) >= 0);
-    
+
 #elif defined(OS_IS_WIN32)
     u_long arg = 1;
     if (ioctlsocket(fd, FIONBIO, &arg) < 0) {
@@ -521,21 +521,21 @@ void pa_make_realtime(void) {
 
     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)
@@ -629,16 +629,16 @@ const char *pa_sig2str(int sig) {
 
     if (sig <= 0)
         goto fail;
- 
+
 #ifdef NSIG
     if (sig >= NSIG)
         goto fail;
 #endif
-        
+
 #ifdef HAVE_SIG2STR
     {
         char buf[SIG2STR_MAX];
-        
+
         if (str2sig(sig, buf) == 0) {
             pa_xfree(PA_STATIC_TLS_GET(signame));
             t = pa_sprintf_malloc("SIG%s", buf);
@@ -703,8 +703,8 @@ const char *pa_sig2str(int sig) {
         PA_STATIC_TLS_SET(signame, t);
         return t;
     }
-#endif        
-    
+#endif
+
 #endif
 
 fail:
@@ -943,7 +943,11 @@ int pa_lock_lockfile(const char *fn) {
     for (;;) {
         struct stat st;
 
-        if ((fd = open(fn, O_CREAT|O_RDWR, S_IRUSR|S_IWUSR)) < 0) {
+        if ((fd = open(fn, O_CREAT|O_RDWR|O_NOCTTY
+#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;
         }
@@ -1131,7 +1135,7 @@ 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;
-    
+
     pa_assert(p);
     pa_assert(d);
 
@@ -1226,7 +1230,7 @@ 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;
-    
+
     pa_assert(s);
     pa_assert(ret_i);
 
@@ -1238,7 +1242,7 @@ int pa_atoi(const char *s, int32_t *ret_i) {
 
     if ((int32_t) l != l)
         return -1;
-    
+
     *ret_i = (int32_t) l;
 
     return 0;
@@ -1248,7 +1252,7 @@ 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;
-    
+
     pa_assert(s);
     pa_assert(ret_u);
 
@@ -1278,21 +1282,21 @@ 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);
@@ -1311,7 +1315,7 @@ int pa_atof(const char *s, float *ret_f) {
         r =  -1;
     else
         *ret_f = f;
-    
+
     return r;
 }
 
@@ -1323,7 +1327,7 @@ int pa_snprintf(char *str, size_t size, const char *format, ...) {
     pa_assert(str);
     pa_assert(size > 0);
     pa_assert(format);
-    
+
     va_start(ap, format);
     ret = vsnprintf(str, size, format, ap);
     va_end(ap);
@@ -1346,13 +1350,13 @@ char *pa_truncate_utf8(char *c, size_t l) {
 
     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))
@@ -1369,7 +1373,7 @@ char *pa_getcwd(void) {
 char *pa_make_path_absolute(const char *p) {
     char *r;
     char *cwd;
-    
+
     pa_assert(p);
 
     if (p[0] == '/')
@@ -1391,47 +1395,47 @@ void *pa_will_need(const void *p, size_t l) {
     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    
+#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));
 
     while (size > 0 && bs > 0) {
 
         if (bs > size)
             bs = size;
-        
+
         if (mlock(a, bs) < 0) {
             bs = PA_PAGE_ALIGN(bs / 2);
             continue;
@@ -1453,13 +1457,12 @@ void *pa_will_need(const void *p, size_t l) {
 
 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;
 }
-

commit 77ed60ce4cd02cb4b383ab4d6e9b51701fb03a07
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sun Sep 23 21:03:24 2007 +0000

    instead of using the mixer ioctl()s on the dsp fd, open a seperate fd for the mixer. This allows us the keep the mixer fd open while closing the dsp device while suspending.
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1893 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-oss.c b/src/modules/module-oss.c
index 037c401..358154a 100644
--- a/src/modules/module-oss.c
+++ b/src/modules/module-oss.c
@@ -36,8 +36,6 @@
  *
  */
 
-/* TODO: handle restoring of volume after suspend */
-
 #ifdef HAVE_CONFIG_H
 #include <config.h>
 #endif
@@ -101,13 +99,13 @@ struct userdata {
     pa_module *module;
     pa_sink *sink;
     pa_source *source;
-    
+
     pa_thread *thread;
     pa_thread_mq thread_mq;
     pa_rtpoll *rtpoll;
 
     char *device_name;
-    
+
     pa_memchunk memchunk;
 
     size_t frame_size;
@@ -115,14 +113,14 @@ struct userdata {
     int use_getospace, use_getispace;
     int use_getodelay;
 
-    int use_pcm_volume;
-    int use_input_volume;
-
     int sink_suspended, source_suspended;
 
     int fd;
     int mode;
 
+    int mixer_fd;
+    int mixer_devmask;
+
     int nfrags, frag_size;
 
     int use_mmap;
@@ -155,7 +153,7 @@ static void trigger(struct userdata *u, int quick) {
     int enable_bits = 0, zero = 0;
 
     pa_assert(u);
-    
+
     if (u->fd < 0)
         return;
 
@@ -163,10 +161,10 @@ static void trigger(struct userdata *u, int quick) {
 
     if (u->source && PA_SOURCE_OPENED(u->source->thread_info.state))
         enable_bits |= PCM_ENABLE_INPUT;
-    
+
     if (u->sink && PA_SINK_OPENED(u->sink->thread_info.state))
         enable_bits |= PCM_ENABLE_OUTPUT;
-    
+
     if (u->use_mmap) {
 
         if (!quick)
@@ -177,28 +175,28 @@ static void trigger(struct userdata *u, int quick) {
             if (ioctl(u->fd, SNDCTL_DSP_HALT, NULL) < 0)
                 pa_log_warn("SNDCTL_DSP_HALT: %s", pa_cstrerror(errno));
 #endif
-        
+
         if (ioctl(u->fd, SNDCTL_DSP_SETTRIGGER, &enable_bits) < 0)
             pa_log_warn("SNDCTL_DSP_SETTRIGGER: %s", pa_cstrerror(errno));
-        
+
         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);
@@ -213,7 +211,7 @@ static void mmap_fill_memblocks(struct userdata *u, unsigned n) {
     pa_assert(u->out_mmap_memblocks);
 
 /*     pa_log("Mmmap writing %u blocks", n); */
-    
+
     while (n > 0) {
         pa_memchunk chunk;
 
@@ -242,12 +240,12 @@ static void mmap_fill_memblocks(struct userdata *u, unsigned 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;
@@ -258,7 +256,7 @@ static int mmap_write(struct userdata *u) {
 
     if (info.blocks > 0)
         mmap_fill_memblocks(u, info.blocks);
-    
+
     return info.blocks;
 }
 
@@ -272,14 +270,14 @@ static void mmap_post_memblocks(struct userdata *u, unsigned n) {
         pa_memchunk chunk;
 
         if (!u->in_mmap_memblocks[u->in_mmap_current]) {
-            
+
             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);
-            
+
             chunk.length = pa_memblock_get_length(chunk.memblock);
             chunk.index = 0;
 
@@ -296,7 +294,7 @@ static void mmap_post_memblocks(struct userdata *u, unsigned n) {
 
 static void mmap_clear_memblocks(struct userdata*u, unsigned n) {
     unsigned i = u->in_mmap_current;
-    
+
     pa_assert(u);
     pa_assert(u->in_mmap_memblocks);
 
@@ -323,7 +321,7 @@ static int mmap_read(struct userdata *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;
@@ -336,14 +334,14 @@ static int mmap_read(struct userdata *u) {
         mmap_post_memblocks(u, info.blocks);
         mmap_clear_memblocks(u, u->in_nfrags/2);
     }
-    
+
     return info.blocks;
 }
 
 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) {
@@ -391,23 +389,23 @@ static pa_usec_t mmap_source_get_latency(struct userdata *u) {
 
 static pa_usec_t io_sink_get_latency(struct userdata *u) {
     pa_usec_t r = 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);
-        
+
     }
-    
+
     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;
@@ -424,9 +422,9 @@ static pa_usec_t io_sink_get_latency(struct userdata *u) {
 
 static pa_usec_t io_source_get_latency(struct userdata *u) {
     pa_usec_t r = 0;
-    
+
     pa_assert(u);
-    
+
     if (u->use_getispace) {
         struct audio_buf_info info;
 
@@ -445,7 +443,7 @@ static int suspend(struct userdata *u) {
     pa_assert(u->fd >= 0);
 
     pa_log_info("Suspending...");
-    
+
     if (u->out_mmap_memblocks) {
         unsigned i;
         for (i = 0; i < u->out_nfrags; i++)
@@ -463,12 +461,12 @@ static int suspend(struct userdata *u) {
                 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;
@@ -483,9 +481,9 @@ static int suspend(struct userdata *u) {
         pa_rtpoll_item_free(u->rtpoll_item);
         u->rtpoll_item = NULL;
     }
-    
+
     pa_log_info("Device suspended...");
-    
+
     return 0;
 }
 
@@ -567,7 +565,7 @@ static int unsuspend(struct userdata *u) {
 
                 goto fail;
             }
-            
+
             pa_silence_memory(u->out_mmap, u->out_hwbuf_size, &ss);
         }
     }
@@ -576,13 +574,18 @@ static int unsuspend(struct userdata *u) {
     u->out_mmap_saved_nfrags = u->in_mmap_saved_nfrags = 0;
 
     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 = 0;
     pollfd->revents = 0;
 
+    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;
@@ -624,29 +627,29 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
                     if (!u->source || u->source_suspended) {
                         if (suspend(u) < 0)
                             return -1;
-                    } 
+                    }
 
                     do_trigger = 1;
 
                     u->sink_suspended = 1;
                     break;
-                    
+
                 case PA_SINK_IDLE:
                 case PA_SINK_RUNNING:
-                    
+
                     if (u->sink->thread_info.state == PA_SINK_SUSPENDED) {
-                        
+
                         if (!u->source || u->source_suspended) {
-                            if (unsuspend(u) < 0) 
+                            if (unsuspend(u) < 0)
                                 return -1;
                             quick = 0;
                         }
 
                         do_trigger = 1;
-                        
+
                         u->out_mmap_current = 0;
                         u->out_mmap_saved_nfrags = 0;
-                        
+
                         u->sink_suspended = 0;
                     }
 
@@ -656,41 +659,16 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
                 case PA_SINK_INIT:
                     ;
             }
-            
-            break;
-
-        case PA_SINK_MESSAGE_SET_VOLUME:
-
-            if (u->use_pcm_volume && u->fd >= 0) {
-
-                if (pa_oss_set_pcm_volume(u->fd, &u->sink->sample_spec, ((pa_cvolume*) data)) < 0) {
-                    pa_log_info("Device doesn't support setting mixer settings: %s", pa_cstrerror(errno));
-                    u->use_pcm_volume = 0;
-                } else
-                    return 0;
-            }
 
             break;
 
-        case PA_SINK_MESSAGE_GET_VOLUME:
-
-            if (u->use_pcm_volume && u->fd >= 0) {
-
-                if (pa_oss_get_pcm_volume(u->fd, &u->sink->sample_spec, ((pa_cvolume*) data)) < 0) {
-                    pa_log_info("Device doesn't support reading mixer settings: %s", pa_cstrerror(errno));
-                    u->use_pcm_volume = 0;
-                } else
-                    return 0;
-            }
-
-            break;
     }
 
     ret = pa_sink_process_msg(o, code, data, offset, chunk);
 
     if (do_trigger)
         trigger(u, quick);
-    
+
     return ret;
 }
 
@@ -709,7 +687,7 @@ static int source_process_msg(pa_msgobject *o, int code, void *data, int64_t off
                 else
                     r = io_source_get_latency(u);
             }
-            
+
             *((pa_usec_t*) data) = r;
             return 0;
         }
@@ -721,31 +699,31 @@ static int source_process_msg(pa_msgobject *o, int code, void *data, int64_t off
                     pa_assert(PA_SOURCE_OPENED(u->source->thread_info.state));
 
                     if (!u->sink || u->sink_suspended) {
-                        if (suspend(u) < 0) 
+                        if (suspend(u) < 0)
                             return -1;
-                    } 
+                    }
 
                     do_trigger = 1;
-                    
+
                     u->source_suspended = 1;
                     break;
 
                 case PA_SOURCE_IDLE:
                 case PA_SOURCE_RUNNING:
-                    
+
                     if (u->source->thread_info.state == PA_SOURCE_SUSPENDED) {
 
                         if (!u->sink || u->sink_suspended) {
-                            if (unsuspend(u) < 0) 
+                            if (unsuspend(u) < 0)
                                 return -1;
                             quick = 0;
-                        } 
+                        }
 
                         do_trigger = 1;
-                        
+
                         u->in_mmap_current = 0;
                         u->in_mmap_saved_nfrags = 0;
-                        
+
                         u->source_suspended = 0;
                     }
                     break;
@@ -757,39 +735,94 @@ static int source_process_msg(pa_msgobject *o, int code, void *data, int64_t off
             }
             break;
 
-        case PA_SOURCE_MESSAGE_SET_VOLUME:
+    }
 
-            if (u->use_input_volume && u->fd >= 0) {
+    ret = pa_source_process_msg(o, code, data, offset, chunk);
 
-                if (pa_oss_set_input_volume(u->fd, &u->source->sample_spec, ((pa_cvolume*) data)) < 0) {
-                    pa_log_info("Device doesn't support setting mixer settings: %s", pa_cstrerror(errno));
-                    u->use_input_volume = 0;
-                } else
-                    return 0;
-            }
+    if (do_trigger)
+        trigger(u, quick);
 
-            break;
+    return ret;
+}
 
-        case PA_SOURCE_MESSAGE_GET_VOLUME:
+static int sink_get_volume(pa_sink *s) {
+    struct userdata *u;
+    int r;
 
-            if (u->use_input_volume && u->fd >= 0) {
+    pa_assert_se(u = s->userdata);
 
-                if (pa_oss_get_input_volume(u->fd, &u->source->sample_spec, ((pa_cvolume*) data)) < 0) {
-                    pa_log_info("Device doesn't support reading mixer settings: %s", pa_cstrerror(errno));
-                    u->use_input_volume = 0;
-                } else
-                    return 0;
-            }
+    pa_assert(u->mixer_devmask & (SOUND_MASK_VOLUME|SOUND_MASK_PCM));
 
-            break;
-    }
+    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;
 
-    ret = pa_source_process_msg(o, code, data, offset, chunk);
+    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;
 
-    if (do_trigger)
-        trigger(u, quick);
+    pa_log_info("Device doesn't support reading mixer settings: %s", pa_cstrerror(errno));
+    return -1;
+}
 
-    return ret;
+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;
+}
+
+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) {
@@ -808,12 +841,12 @@ static void thread_func(void *userdata) {
     pa_rtpoll_install(u->rtpoll);
 
     trigger(u, 0);
-    
+
     for (;;) {
         int ret;
 
 /*        pa_log("loop");    */
-        
+
         /* Render some data and write it to the dsp */
 
         if (u->sink && u->sink->thread_info.state != PA_SINK_UNLINKED && u->fd >= 0 && (revents & POLLOUT)) {
@@ -824,19 +857,19 @@ static void thread_func(void *userdata) {
                     goto fail;
 
                 revents &= ~POLLOUT;
-                
+
                 if (ret > 0)
                     continue;
 
             } else {
                 ssize_t l;
                 int loop = 0;
-                
+
                 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 = 0;
@@ -847,59 +880,59 @@ static void thread_func(void *userdata) {
                         }
                     }
                 }
-                
+
                 do {
                     void *p;
                     ssize_t t;
-                    
+
                     pa_assert(l > 0);
-                    
+
                     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"); 
-                            
+                            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;
                     }
-                    
+
                 } while (loop && l > 0);
-                
+
                 continue;
             }
         }
@@ -914,7 +947,7 @@ static void thread_func(void *userdata) {
                     goto fail;
 
                 revents &= ~POLLIN;
-                
+
                 if (ret > 0)
                     continue;
 
@@ -954,7 +987,7 @@ static void thread_func(void *userdata) {
                         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);
@@ -962,7 +995,7 @@ static void thread_func(void *userdata) {
                     pa_assert(t != 0); /* EOF cannot happen */
 
 /*                     pa_log("read %i bytes of %u", t, l); */
-                    
+
                     if (t < 0) {
                         pa_memblock_unref(memchunk.memblock);
 
@@ -970,7 +1003,7 @@ static void thread_func(void *userdata) {
                             continue;
 
                         else if (errno == EAGAIN) {
-                            pa_log_debug("EAGAIN"); 
+                            pa_log_debug("EAGAIN");
 
                             revents &= ~POLLIN;
                             break;
@@ -1007,19 +1040,19 @@ static void thread_func(void *userdata) {
                 ((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, 1)) < 0)
             goto fail;
 
         if (ret == 0)
             goto finish;
-        
+
         if (u->fd >= 0) {
             struct pollfd *pollfd;
-            
+
             pollfd = pa_rtpoll_item_get_pollfd(u->rtpoll_item, NULL);
-            
+
             if (pollfd->revents & ~(POLLOUT|POLLIN)) {
                 pa_log("DSP shutdown.");
                 goto fail;
@@ -1041,7 +1074,7 @@ finish:
 }
 
 int pa__init(pa_module*m) {
-    
+
     struct audio_buf_info info;
     struct userdata *u = NULL;
     const char *dev;
@@ -1096,7 +1129,7 @@ int pa__init(pa_module*m) {
         pa_log("Failed to parse mmap argument.");
         goto fail;
     }
-    
+
     if ((fd = pa_oss_open(dev = pa_modargs_get_value(ma, "device", DEFAULT_DEVICE), &mode, &caps)) < 0)
         goto fail;
 
@@ -1104,7 +1137,7 @@ int pa__init(pa_module*m) {
         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;
@@ -1135,9 +1168,9 @@ int pa__init(pa_module*m) {
     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->use_input_volume = u->use_pcm_volume = 1;
     u->mode = mode;
     u->frame_size = pa_frame_size(&ss);
     u->device_name = pa_xstrdup(dev);
@@ -1152,7 +1185,7 @@ int pa__init(pa_module*m) {
     pollfd->fd = fd;
     pollfd->events = 0;
     pollfd->revents = 0;
-    
+
     if (ioctl(fd, SNDCTL_DSP_GETISPACE, &info) >= 0) {
         pa_log_info("Input -- %u fragments of size %u.", info.fragstotal, info.fragsize);
         u->in_fragment_size = info.fragsize;
@@ -1169,7 +1202,7 @@ int pa__init(pa_module*m) {
 
     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;
 
@@ -1210,7 +1243,7 @@ int pa__init(pa_module*m) {
                                           hwdesc[0] ? ")" : "",
                                           use_mmap ? " via DMA" : ""));
         pa_xfree(t);
-        u->source->flags = PA_SOURCE_HARDWARE|PA_SOURCE_CAN_SUSPEND|PA_SOURCE_LATENCY|PA_SOURCE_HW_VOLUME_CTRL;
+        u->source->flags = PA_SOURCE_HARDWARE|PA_SOURCE_CAN_SUSPEND|PA_SOURCE_LATENCY;
         u->source->refresh_volume = 1;
 
         if (use_mmap)
@@ -1236,7 +1269,7 @@ int pa__init(pa_module*m) {
                 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 {
@@ -1253,7 +1286,7 @@ int pa__init(pa_module*m) {
 
         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);
@@ -1265,15 +1298,46 @@ int pa__init(pa_module*m) {
                                         hwdesc[0] ? ")" : "",
                                         use_mmap ? " via DMA" : ""));
         pa_xfree(t);
-        u->sink->flags = PA_SINK_HARDWARE|PA_SINK_CAN_SUSPEND|PA_SINK_LATENCY|PA_SINK_HW_VOLUME_CTRL;
+        u->sink->flags = PA_SINK_HARDWARE|PA_SINK_CAN_SUSPEND|PA_SINK_LATENCY;
         u->sink->refresh_volume = 1;
 
         if (use_mmap)
             u->out_mmap_memblocks = pa_xnew0(pa_memblock*, u->out_nfrags);
     }
 
+    if ((u->mixer_fd = pa_oss_open_mixer_for_device(u->device_name)) >= 0) {
+        int do_close = 1;
+        u->mixer_devmask = 0;
+
+        if (ioctl(fd, SOUND_MIXER_READ_DEVMASK, &u->mixer_devmask) < 0)
+            pa_log_warn("SOUND_MIXER_READ_DEVMASK failed: %s", pa_cstrerror(errno));
+
+        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;
+            }
+
+            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;
+            }
+        }
+
+        if (do_close) {
+            pa_close(u->mixer_fd);
+            u->mixer_fd = -1;
+        }
+    }
+
 go_on:
-    
+
     pa_assert(u->source || u->sink);
 
     pa_memchunk_reset(&u->memchunk);
@@ -1284,16 +1348,16 @@ go_on:
     }
 
     /* Read mixer settings */
-    if (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)
-        pa_asyncmsgq_send(u->thread_mq.inq, PA_MSGOBJECT(u->sink), PA_SINK_MESSAGE_GET_VOLUME, &u->sink->volume, 0, NULL);
+    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)
         pa_sink_put(u->sink);
     if (u->source)
         pa_source_put(u->source);
-    
+
     pa_modargs_free(ma);
 
     return 0;
@@ -1337,16 +1401,16 @@ void pa__done(pa_module*m) {
 
     if (u->source)
         pa_source_unref(u->source);
-    
+
     if (u->memchunk.memblock)
         pa_memblock_unref(u->memchunk.memblock);
 
     if (u->rtpoll_item)
         pa_rtpoll_item_free(u->rtpoll_item);
-    
+
     if (u->rtpoll)
         pa_rtpoll_free(u->rtpoll);
-    
+
     if (u->out_mmap_memblocks) {
         unsigned i;
         for (i = 0; i < u->out_nfrags; i++)
@@ -1368,11 +1432,14 @@ void pa__done(pa_module*m) {
 
     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);
 }
diff --git a/src/modules/oss-util.c b/src/modules/oss-util.c
index 3bef8a3..25e45a3 100644
--- a/src/modules/oss-util.c
+++ b/src/modules/oss-util.c
@@ -36,6 +36,7 @@
 #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>
@@ -248,7 +249,7 @@ 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;
 
@@ -259,16 +260,18 @@ static int pa_oss_get_volume(int fd, int mixer, const pa_sample_spec *ss, pa_cvo
     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, long 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, long 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;
+
+    if (p == 0)
+        return 0;
+
+    p = strchr(p, 0) -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' && *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")) &&
@@ -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;
+}
diff --git a/src/modules/oss-util.h b/src/modules/oss-util.h
index 087e0d2..259a622 100644
--- a/src/modules/oss-util.h
+++ b/src/modules/oss-util.h
@@ -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

commit ba322a49e1754eba11495da9a10e3e0dbbe89244
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Sep 24 16:10:43 2007 +0000

    drop the PA_SOURCE_CAN_SUSPEND and PA_SINK_CAN_SUSPEND flags, since they were a bad idea in the first place. All sinks/sources are now *required* to handle suspending in one way or another. Luckily all current sink/source implementations handle it fine anyway.
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1894 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-alsa-sink.c b/src/modules/module-alsa-sink.c
index 4f2e570..0489fa8 100644
--- a/src/modules/module-alsa-sink.c
+++ b/src/modules/module-alsa-sink.c
@@ -70,11 +70,11 @@ 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;
@@ -110,7 +110,7 @@ static const char* const valid_modargs[] = {
 
 static int mmap_write(struct userdata *u) {
     int work_done = 0;
-    
+
     pa_assert(u);
     pa_sink_assert_ref(u->sink);
 
@@ -121,33 +121,33 @@ static int mmap_write(struct userdata *u) {
         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 ((err = snd_pcm_recover(u->pcm_handle, n, 1)) == 0)
                 continue;
 
             if (err == -EAGAIN)
                 return work_done;
-            
+
             pa_log("snd_pcm_avail_update: %s", snd_strerror(err));
             return -1;
         }
 
 /*         pa_log("Got request for %i samples", (int) n); */
-        
+
         if (n <= 0)
             return work_done;
 
         frames = n;
-        
+
         if ((err = snd_pcm_mmap_begin(u->pcm_handle, &areas, &offset, &frames)) < 0) {
-            
+
             if (err == -EPIPE) {
                 pa_log_debug("snd_pcm_mmap_begin: Buffer underrun!");
                 u->first = 1;
@@ -172,7 +172,7 @@ static int mmap_write(struct userdata *u) {
         pa_assert((areas[0].step >> 3) == u->frame_size);
 
         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;
@@ -189,13 +189,13 @@ static int mmap_write(struct userdata *u) {
                 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 (err == -EAGAIN)
                 return work_done;
-            
+
             pa_log("Failed to write data to DSP: %s", snd_strerror(err));
             return -1;
         }
@@ -204,7 +204,7 @@ static int mmap_write(struct userdata *u) {
 
         if (frames >= (snd_pcm_uframes_t) n)
             return work_done;
-        
+
 /*         pa_log("wrote %i samples", (int) frames); */
     }
 }
@@ -214,7 +214,7 @@ static int unix_write(struct userdata *u) {
     int work_done = 0;
 
     snd_pcm_status_alloca(&status);
-    
+
     pa_assert(u);
     pa_sink_assert_ref(u->sink);
 
@@ -223,7 +223,7 @@ static int unix_write(struct userdata *u) {
         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;
@@ -231,32 +231,32 @@ static int unix_write(struct userdata *u) {
 
         if (snd_pcm_status_get_avail_max(status)*u->frame_size >= u->hwbuf_size)
             pa_log_debug("Buffer underrun!");
-                    
+
         l = snd_pcm_status_get_avail(status) * u->frame_size;
 
 /*         pa_log("%u bytes to write", l); */
-                    
+
         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);
-                    
+
         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;
@@ -265,10 +265,10 @@ static int unix_write(struct userdata *u) {
                 return -1;
             }
         }
-                        
+
         u->memchunk.index += t * u->frame_size;
         u->memchunk.length -= t * u->frame_size;
-                    
+
         if (u->memchunk.length <= 0) {
             pa_memblock_unref(u->memchunk.memblock);
             pa_memchunk_reset(&u->memchunk);
@@ -278,7 +278,7 @@ static int unix_write(struct userdata *u) {
 
         if (t * u->frame_size >= (unsigned) l)
             return work_done;
-    } 
+    }
 }
 
 static pa_usec_t sink_get_latency(struct userdata *u) {
@@ -288,18 +288,18 @@ static pa_usec_t sink_get_latency(struct userdata *u) {
     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) 
+    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);
 
@@ -310,7 +310,7 @@ static int build_pollfd(struct userdata *u) {
     int err;
     struct pollfd *pollfd;
     int n;
-    
+
     pa_assert(u);
     pa_assert(u->pcm_handle);
 
@@ -329,7 +329,7 @@ static int build_pollfd(struct userdata *u) {
         pa_log("snd_pcm_poll_descriptors() failed: %s", snd_strerror(err));
         return -1;
     }
-    
+
     return 0;
 }
 
@@ -338,7 +338,7 @@ static int suspend(struct userdata *u) {
     pa_assert(u->pcm_handle);
 
     /* Let's suspend */
-    snd_pcm_drain(u->pcm_handle);    
+    snd_pcm_drain(u->pcm_handle);
     snd_pcm_close(u->pcm_handle);
     u->pcm_handle = NULL;
 
@@ -346,9 +346,9 @@ static int suspend(struct userdata *u) {
         pa_rtpoll_item_free(u->alsa_rtpoll_item);
         u->alsa_rtpoll_item = NULL;
     }
-    
+
     pa_log_info("Device suspended...");
-    
+
     return 0;
 }
 
@@ -373,7 +373,7 @@ static int unsuspend(struct userdata *u) {
     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;
@@ -401,11 +401,11 @@ static int unsuspend(struct userdata *u) {
 
     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;
@@ -438,13 +438,13 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
         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:
@@ -454,14 +454,14 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
                         if (unsuspend(u) < 0)
                             return -1;
                     }
-                    
+
                     break;
 
                 case PA_SINK_UNLINKED:
                 case PA_SINK_INIT:
                     ;
             }
-            
+
             break;
     }
 
@@ -512,7 +512,7 @@ static int sink_get_volume_cb(pa_sink *s) {
 
 fail:
     pa_log_error("Unable to read volume: %s", snd_strerror(err));
-    
+
     s->get_volume = NULL;
     s->set_volume = NULL;
     return -1;
@@ -547,7 +547,7 @@ static int sink_set_volume_cb(pa_sink *s) {
 
 fail:
     pa_log_error("Unable to set volume: %s", snd_strerror(err));
-    
+
     s->get_volume = NULL;
     s->set_volume = NULL;
     return -1;
@@ -582,7 +582,7 @@ static int sink_set_mute_cb(pa_sink *s) {
 
     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_mute = NULL;
         s->set_mute = NULL;
         return -1;
@@ -593,7 +593,7 @@ static int sink_set_mute_cb(pa_sink *s) {
 
 static void thread_func(void *userdata) {
     struct userdata *u = userdata;
-    
+
     pa_assert(u);
 
     pa_log_debug("Thread starting up");
@@ -603,17 +603,17 @@ static void thread_func(void *userdata) {
 
     pa_thread_mq_install(&u->thread_mq);
     pa_rtpoll_install(u->rtpoll);
-    
+
     if (build_pollfd(u) < 0)
         goto fail;
 
     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;
@@ -636,7 +636,7 @@ static void thread_func(void *userdata) {
 
         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;
@@ -655,7 +655,7 @@ static void thread_func(void *userdata) {
                 if (revents & POLLERR)
                     pa_log_warn("Got POLLERR from ALSA");
                 if (revents & POLLNVAL)
-                    pa_log_warn("Got POLLNVAL from ALSA"); 
+                    pa_log_warn("Got POLLNVAL from ALSA");
                 if (revents & POLLHUP)
                     pa_log_warn("Got POLLHUP from ALSA");
 
@@ -675,7 +675,7 @@ finish:
 }
 
 int pa__init(pa_module*m) {
-    
+
     pa_modargs *ma = NULL;
     struct userdata *u = NULL;
     char *dev;
@@ -693,7 +693,7 @@ int pa__init(pa_module*m) {
     int use_mmap = 1, b;
 
     snd_pcm_info_alloca(&pcm_info);
-    
+
     pa_assert(m);
 
     if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
@@ -724,7 +724,7 @@ int pa__init(pa_module*m) {
         pa_log("Failed to parse mmap argument.");
         goto fail;
     }
-        
+
     u = pa_xnew0(struct userdata, 1);
     u->core = m->core;
     u->module = m;
@@ -741,19 +741,19 @@ int pa__init(pa_module*m) {
     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);
@@ -765,7 +765,7 @@ int pa__init(pa_module*m) {
                     continue;
                 }
             }
-            
+
             pa_log("Failed to set hardware parameters: %s", snd_strerror(err));
             pa_xfree(dev);
             goto fail;
@@ -773,9 +773,9 @@ int pa__init(pa_module*m) {
 
         break;
     }
-    
+
     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;
@@ -807,7 +807,7 @@ int pa__init(pa_module*m) {
 
         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;
         }
@@ -822,7 +822,7 @@ int pa__init(pa_module*m) {
 
     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;
@@ -840,8 +840,8 @@ int pa__init(pa_module*m) {
                                     snd_pcm_info_get_name(pcm_info),
                                     use_mmap ? " via DMA" : ""));
     pa_xfree(t);
-    
-    u->sink->flags = PA_SINK_HARDWARE|PA_SINK_CAN_SUSPEND|PA_SINK_HW_VOLUME_CTRL|PA_SINK_LATENCY;
+
+    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;
@@ -854,9 +854,9 @@ int pa__init(pa_module*m) {
 
     if (u->mixer_handle) {
         /* Initialize mixer code */
-        
+
         pa_assert(u->mixer_elem);
-        
+
         if (snd_mixer_selem_has_playback_volume(u->mixer_elem)) {
             int i;
 
@@ -872,7 +872,7 @@ int pa__init(pa_module*m) {
             } 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_mute = sink_get_mute_cb;
             u->sink->set_mute = sink_set_mute_cb;
@@ -894,7 +894,7 @@ int pa__init(pa_module*m) {
         pa_log("Failed to create thread.");
         goto fail;
     }
-    
+
     /* Get initial mixer settings */
     if (u->sink->get_volume)
         u->sink->get_volume(u->sink);
@@ -902,11 +902,11 @@ int pa__init(pa_module*m) {
         u->sink->get_mute(u->sink);
 
     pa_sink_put(u->sink);
-    
+
     pa_modargs_free(ma);
-    
+
     return 0;
-    
+
 fail:
 
     if (ma)
@@ -919,7 +919,7 @@ fail:
 
 void pa__done(pa_module*m) {
     struct userdata *u;
-    
+
     pa_assert(m);
 
     if (!(u = m->userdata))
@@ -937,19 +937,19 @@ void pa__done(pa_module*m) {
 
     if (u->sink)
         pa_sink_unref(u->sink);
-    
+
     if (u->memchunk.memblock)
         pa_memblock_unref(u->memchunk.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);
 
@@ -960,7 +960,6 @@ void pa__done(pa_module*m) {
 
     pa_xfree(u->device_name);
     pa_xfree(u);
-    
+
     snd_config_update_free_global();
 }
-
diff --git a/src/modules/module-alsa-source.c b/src/modules/module-alsa-source.c
index 82f66bb..de019ff 100644
--- a/src/modules/module-alsa-source.c
+++ b/src/modules/module-alsa-source.c
@@ -71,7 +71,7 @@ struct userdata {
     pa_core *core;
     pa_module *module;
     pa_source *source;
-    
+
     pa_thread *thread;
     pa_thread_mq thread_mq;
     pa_rtpoll *rtpoll;
@@ -108,7 +108,7 @@ static const char* const valid_modargs[] = {
 
 static int mmap_read(struct userdata *u) {
     int work_done = 0;
-    
+
     pa_assert(u);
     pa_source_assert_ref(u->source);
 
@@ -119,31 +119,31 @@ static int mmap_read(struct userdata *u) {
         snd_pcm_uframes_t offset, frames;
         pa_memchunk chunk;
         void *p;
-        
+
         if ((n = snd_pcm_avail_update(u->pcm_handle)) < 0) {
 
             if (n == -EPIPE)
                 pa_log_debug("snd_pcm_avail_update: Buffer underrun!");
-            
+
             if ((err = snd_pcm_recover(u->pcm_handle, n, 1)) == 0)
                 continue;
 
             if (err == -EAGAIN)
                 return work_done;
-            
+
             pa_log("snd_pcm_avail_update: %s", snd_strerror(err));
             return -1;
         }
 
 /*         pa_log("Got request for %i samples", (int) n); */
-        
+
         if (n <= 0)
             return work_done;
 
         frames = n;
-        
+
         if ((err = snd_pcm_mmap_begin(u->pcm_handle, &areas, &offset, &frames)) < 0) {
-            
+
             if (err == -EPIPE)
                 pa_log_debug("snd_pcm_mmap_begin: Buffer underrun!");
 
@@ -166,7 +166,7 @@ static int mmap_read(struct userdata *u) {
         pa_assert((areas[0].step >> 3) == u->frame_size);
 
         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;
@@ -181,13 +181,13 @@ static int mmap_read(struct userdata *u) {
 
             if (err == -EPIPE)
                 pa_log_debug("snd_pcm_mmap_commit: Buffer underrun!");
-            
+
             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;
         }
@@ -213,7 +213,7 @@ static int unix_read(struct userdata *u) {
         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;
@@ -221,12 +221,12 @@ static int unix_read(struct userdata *u) {
 
         if (snd_pcm_status_get_avail_max(status)*u->frame_size >= u->hwbuf_size)
             pa_log_debug("Buffer overrun!");
-                    
+
         l = snd_pcm_status_get_avail(status) * u->frame_size;
 
         if (l <= 0)
             return work_done;
-                    
+
         chunk.memblock = pa_memblock_new(u->core->mempool, (size_t) -1);
 
         k = pa_memblock_get_length(chunk.memblock);
@@ -239,17 +239,17 @@ static int unix_read(struct userdata *u) {
         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;
@@ -257,14 +257,14 @@ static int unix_read(struct userdata *u) {
                 pa_log("Failed to read data from DSP: %s", snd_strerror(t));
                 return -1;
             }
-        } 
-                        
+        }
+
         chunk.index = 0;
         chunk.length = t * u->frame_size;
 
         pa_source_post(u->source, &chunk);
         pa_memblock_unref(chunk.memblock);
-                    
+
         work_done = 1;
 
         if (t * u->frame_size >= (unsigned) l)
@@ -279,11 +279,11 @@ static pa_usec_t source_get_latency(struct userdata *u) {
     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) 
+    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);
@@ -298,7 +298,7 @@ static int build_pollfd(struct userdata *u) {
     int err;
     struct pollfd *pollfd;
     int n;
-    
+
     pa_assert(u);
     pa_assert(u->pcm_handle);
 
@@ -312,12 +312,12 @@ static int build_pollfd(struct userdata *u) {
 
     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;
 }
 
@@ -333,9 +333,9 @@ static int suspend(struct userdata *u) {
         pa_rtpoll_item_free(u->alsa_rtpoll_item);
         u->alsa_rtpoll_item = NULL;
     }
-    
+
     pa_log_info("Device suspended...");
-    
+
     return 0;
 }
 
@@ -360,7 +360,7 @@ static int unsuspend(struct userdata *u) {
     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;
@@ -370,7 +370,7 @@ static int unsuspend(struct userdata *u) {
         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;
@@ -388,11 +388,11 @@ static int unsuspend(struct userdata *u) {
 
     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;
@@ -425,13 +425,13 @@ static int source_process_msg(pa_msgobject *o, int code, void *data, int64_t off
         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:
@@ -441,14 +441,14 @@ static int source_process_msg(pa_msgobject *o, int code, void *data, int64_t off
                         if (unsuspend(u) < 0)
                             return -1;
                     }
-                    
+
                     break;
 
                 case PA_SOURCE_UNLINKED:
                 case PA_SOURCE_INIT:
                     ;
             }
-            
+
             break;
     }
 
@@ -499,7 +499,7 @@ static int source_get_volume_cb(pa_source *s) {
 
 fail:
     pa_log_error("Unable to read volume: %s", snd_strerror(err));
-    
+
     s->get_volume = NULL;
     s->set_volume = NULL;
     return -1;
@@ -534,7 +534,7 @@ static int source_set_volume_cb(pa_source *s) {
 
 fail:
     pa_log_error("Unable to set volume: %s", snd_strerror(err));
-    
+
     s->get_volume = NULL;
     s->set_volume = NULL;
     return -1;
@@ -569,7 +569,7 @@ static int source_set_mute_cb(pa_source *s) {
 
     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_mute = NULL;
         s->set_mute = NULL;
         return -1;
@@ -590,18 +590,18 @@ static void thread_func(void *userdata) {
 
     pa_thread_mq_install(&u->thread_mq);
     pa_rtpoll_install(u->rtpoll);
-    
+
     if (build_pollfd(u) < 0)
         goto fail;
 
     snd_pcm_start(u->pcm_handle);
-    
+
     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;
@@ -618,7 +618,7 @@ static void thread_func(void *userdata) {
 
         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;
@@ -627,7 +627,7 @@ static void thread_func(void *userdata) {
             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;
@@ -637,7 +637,7 @@ static void thread_func(void *userdata) {
                 if (revents & POLLERR)
                     pa_log_warn("Got POLLERR from ALSA");
                 if (revents & POLLNVAL)
-                    pa_log_warn("Got POLLNVAL from ALSA"); 
+                    pa_log_warn("Got POLLNVAL from ALSA");
                 if (revents & POLLHUP)
                     pa_log_warn("Got POLLHUP from ALSA");
 
@@ -657,7 +657,7 @@ finish:
 }
 
 int pa__init(pa_module*m) {
-    
+
     pa_modargs *ma = NULL;
     struct userdata *u = NULL;
     char *dev;
@@ -677,7 +677,7 @@ int pa__init(pa_module*m) {
     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");
         goto fail;
@@ -706,7 +706,7 @@ int pa__init(pa_module*m) {
         pa_log("Failed to parse mmap argument.");
         goto fail;
     }
-    
+
     u = pa_xnew0(struct userdata, 1);
     u->core = m->core;
     u->module = m;
@@ -720,9 +720,9 @@ int pa__init(pa_module*m) {
     snd_config_update_free_global();
 
     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);
@@ -734,7 +734,7 @@ int pa__init(pa_module*m) {
 
             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);
@@ -746,7 +746,7 @@ int pa__init(pa_module*m) {
                     continue;
                 }
             }
-            
+
             pa_log("Failed to set hardware parameters: %s", snd_strerror(err));
             pa_xfree(dev);
             goto fail;
@@ -756,7 +756,7 @@ int pa__init(pa_module*m) {
     }
 
     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;
@@ -774,7 +774,7 @@ int pa__init(pa_module*m) {
         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);
 
@@ -785,7 +785,7 @@ int pa__init(pa_module*m) {
     if ((err = snd_mixer_open(&u->mixer_handle, 0)) < 0)
         pa_log("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, "Capture", NULL))) {
             snd_mixer_close(u->mixer_handle);
@@ -802,7 +802,7 @@ int pa__init(pa_module*m) {
 
     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;
@@ -821,7 +821,7 @@ int pa__init(pa_module*m) {
                                       use_mmap ? " via DMA" : ""));
     pa_xfree(t);
 
-    u->source->flags = PA_SOURCE_HARDWARE|PA_SOURCE_CAN_SUSPEND|PA_SOURCE_LATENCY|PA_SOURCE_HW_VOLUME_CTRL;
+    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;
@@ -832,7 +832,7 @@ int pa__init(pa_module*m) {
 
     if (u->mixer_handle) {
         pa_assert(u->mixer_elem);
-        
+
         if (snd_mixer_selem_has_capture_volume(u->mixer_elem)) {
             int i;
 
@@ -847,19 +847,19 @@ int pa__init(pa_module*m) {
                 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_mute = source_get_mute_cb;
             u->source->set_mute = source_set_mute_cb;
         }
 
         u->mixer_fdl = pa_alsa_fdlist_new();
-        
+
         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
@@ -875,25 +875,25 @@ int pa__init(pa_module*m) {
     if (u->source->get_mute)
         u->source->get_mute(u->source);
 
-    pa_source_put(u->source);    
-    
+    pa_source_put(u->source);
+
     pa_modargs_free(ma);
-    
+
     return 0;
-    
+
 fail:
 
     if (ma)
         pa_modargs_free(ma);
 
     pa__done(m);
-    
+
     return -1;
 }
 
 void pa__done(pa_module*m) {
     struct userdata *u;
-    
+
     pa_assert(m);
 
     if (!(u = m->userdata))
@@ -914,10 +914,10 @@ void pa__done(pa_module*m) {
 
     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);
 
@@ -934,4 +934,3 @@ void pa__done(pa_module*m) {
 
     snd_config_update_free_global();
 }
-
diff --git a/src/modules/module-combine.c b/src/modules/module-combine.c
index af5ddb1..656cef9 100644
--- a/src/modules/module-combine.c
+++ b/src/modules/module-combine.c
@@ -1134,7 +1134,7 @@ int pa__init(pa_module*m) {
     u->sink->set_state = sink_set_state;
     u->sink->userdata = u;
 
-    u->sink->flags = PA_SINK_CAN_SUSPEND|PA_SINK_LATENCY;
+    u->sink->flags = PA_SINK_LATENCY;
     pa_sink_set_module(u->sink, m);
     pa_sink_set_description(u->sink, "Simultaneous output");
 
diff --git a/src/modules/module-ladspa-sink.c b/src/modules/module-ladspa-sink.c
index 38b7e01..9f771c6 100644
--- a/src/modules/module-ladspa-sink.c
+++ b/src/modules/module-ladspa-sink.c
@@ -568,7 +568,7 @@ int pa__init(pa_module*m) {
     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_CAN_SUSPEND;
+    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));
diff --git a/src/modules/module-oss.c b/src/modules/module-oss.c
index 358154a..8d08899 100644
--- a/src/modules/module-oss.c
+++ b/src/modules/module-oss.c
@@ -1243,7 +1243,7 @@ int pa__init(pa_module*m) {
                                           hwdesc[0] ? ")" : "",
                                           use_mmap ? " via DMA" : ""));
         pa_xfree(t);
-        u->source->flags = PA_SOURCE_HARDWARE|PA_SOURCE_CAN_SUSPEND|PA_SOURCE_LATENCY;
+        u->source->flags = PA_SOURCE_HARDWARE|PA_SOURCE_LATENCY;
         u->source->refresh_volume = 1;
 
         if (use_mmap)
@@ -1298,7 +1298,7 @@ int pa__init(pa_module*m) {
                                         hwdesc[0] ? ")" : "",
                                         use_mmap ? " via DMA" : ""));
         pa_xfree(t);
-        u->sink->flags = PA_SINK_HARDWARE|PA_SINK_CAN_SUSPEND|PA_SINK_LATENCY;
+        u->sink->flags = PA_SINK_HARDWARE|PA_SINK_LATENCY;
         u->sink->refresh_volume = 1;
 
         if (use_mmap)
diff --git a/src/modules/module-remap-sink.c b/src/modules/module-remap-sink.c
index bff787b..d712a04 100644
--- a/src/modules/module-remap-sink.c
+++ b/src/modules/module-remap-sink.c
@@ -262,7 +262,7 @@ int pa__init(pa_module*m) {
     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_CAN_SUSPEND;
+    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));
diff --git a/src/modules/module-suspend-on-idle.c b/src/modules/module-suspend-on-idle.c
index 79850e7..4fcb404 100644
--- a/src/modules/module-suspend-on-idle.c
+++ b/src/modules/module-suspend-on-idle.c
@@ -57,7 +57,7 @@ struct userdata {
         *source_unlink_slot,
         *sink_state_changed_slot,
         *source_state_changed_slot;
-    
+
     pa_hook_slot
         *sink_input_new_slot,
         *source_output_new_slot,
@@ -83,7 +83,7 @@ static void timeout_cb(pa_mainloop_api*a, pa_time_event* e, const struct timeval
     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, 1);
@@ -119,7 +119,7 @@ static void resume(struct device_info *d) {
     if (d->sink) {
         pa_sink_suspend(d->sink, 0);
         pa_source_suspend(d->sink->monitor_source, 0);
-        
+
         pa_log_debug("Sink %s becomes busy.", d->sink->name);
     }
 
@@ -134,14 +134,14 @@ static void resume(struct device_info *d) {
 
 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;
 }
 
@@ -151,10 +151,10 @@ static pa_hook_result_t source_output_new_hook_cb(pa_core *c, pa_source_output *
     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;
 }
 
@@ -168,7 +168,7 @@ static pa_hook_result_t sink_input_unlink_hook_cb(pa_core *c, pa_sink_input *s,
         if ((d = pa_hashmap_get(u->device_infos, s->sink)))
             restart(d);
     }
-    
+
     return PA_HOOK_OK;
 }
 
@@ -182,7 +182,7 @@ static pa_hook_result_t source_output_unlink_hook_cb(pa_core *c, pa_source_outpu
         if ((d = pa_hashmap_get(u->device_infos, s->source)))
             restart(d);
     }
-    
+
     return PA_HOOK_OK;
 }
 
@@ -196,7 +196,7 @@ static pa_hook_result_t sink_input_move_hook_cb(pa_core *c, pa_sink_input *s, st
         if ((d = pa_hashmap_get(u->device_infos, s->sink)))
             restart(d);
     }
-    
+
     return PA_HOOK_OK;
 }
 
@@ -208,7 +208,7 @@ static pa_hook_result_t sink_input_move_post_hook_cb(pa_core *c, pa_sink_input *
 
     if ((d = pa_hashmap_get(u->device_infos, s->sink)))
         resume(d);
-    
+
     return PA_HOOK_OK;
 }
 
@@ -223,7 +223,7 @@ static pa_hook_result_t source_output_move_hook_cb(pa_core *c, pa_source_output
         if ((d = pa_hashmap_get(u->device_infos, s->source)))
             restart(d);
     }
-    
+
     return PA_HOOK_OK;
 }
 
@@ -235,7 +235,7 @@ static pa_hook_result_t source_output_move_post_hook_cb(pa_core *c, pa_source_ou
 
     if ((d = pa_hashmap_get(u->device_infos, s->source)))
         resume(d);
-    
+
     return PA_HOOK_OK;
 }
 
@@ -243,7 +243,7 @@ static pa_hook_result_t device_new_hook_cb(pa_core *c, pa_object *o, struct user
     struct device_info *d;
     pa_source *source;
     pa_sink *sink;
-    
+
     pa_assert(c);
     pa_object_assert_ref(o);
     pa_assert(u);
@@ -252,12 +252,6 @@ static pa_hook_result_t device_new_hook_cb(pa_core *c, pa_object *o, struct user
     sink = pa_sink_isinstance(o) ? PA_SINK(o) : NULL;
 
     pa_assert(source || sink);
-    
-    if (source && !(source->flags & PA_SOURCE_CAN_SUSPEND))
-        return PA_HOOK_OK;
-
-    if (sink && !(sink->flags & PA_SINK_CAN_SUSPEND))
-        return PA_HOOK_OK;
 
     d = pa_xnew(struct device_info, 1);
     d->userdata = u;
@@ -275,20 +269,20 @@ static pa_hook_result_t device_new_hook_cb(pa_core *c, pa_object *o, struct user
 
 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);
@@ -311,14 +305,14 @@ static pa_hook_result_t device_state_changed_hook_cb(pa_core *c, pa_object *o, s
 
     if (pa_sink_isinstance(o)) {
         pa_sink *s = PA_SINK(o);
-        
+
         if (pa_sink_used_by(s) <= 0) {
             pa_sink_state_t state = pa_sink_get_state(s);
 
             if (state == PA_SINK_RUNNING || state == PA_SINK_IDLE)
                 restart(d);
         }
-        
+
     } else if (pa_source_isinstance(o)) {
         pa_source *s = PA_SOURCE(o);
 
@@ -329,7 +323,7 @@ static pa_hook_result_t device_state_changed_hook_cb(pa_core *c, pa_object *o, s
                 restart(d);
         }
     }
-            
+
     return PA_HOOK_OK;
 }
 
@@ -352,7 +346,7 @@ int pa__init(pa_module*m) {
         pa_log("Failed to parse timeout value.");
         goto fail;
     }
-    
+
     m->userdata = u = pa_xnew(struct userdata, 1);
     u->core = m->core;
     u->timeout = timeout;
@@ -380,29 +374,29 @@ int pa__init(pa_module*m) {
     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);
 
-    
+
     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)
@@ -439,6 +433,6 @@ void pa__done(pa_module*m) {
         device_info_free(d);
 
     pa_hashmap_free(u->device_infos, NULL, NULL);
-    
+
     pa_xfree(u);
 }
diff --git a/src/pulse/def.h b/src/pulse/def.h
index 4102ba6..c281623 100644
--- a/src/pulse/def.h
+++ b/src/pulse/def.h
@@ -300,16 +300,14 @@ typedef enum pa_seek_mode {
 typedef enum pa_sink_flags {
     PA_SINK_HW_VOLUME_CTRL = 1,   /**< Supports hardware volume control */
     PA_SINK_LATENCY = 2,          /**< Supports latency querying */
-    PA_SINK_HARDWARE = 4,         /**< Is a hardware sink of some kind, in contrast to "virtual"/software sinks \since 0.9.3 */
-    PA_SINK_CAN_SUSPEND = 8       /**< Can suspend \since 0.9.7 */
+    PA_SINK_HARDWARE = 4          /**< Is a hardware sink of some kind, in contrast to "virtual"/software sinks \since 0.9.3 */
 } pa_sink_flags_t;
 
 /** Special source flags. \since 0.8  */
 typedef enum pa_source_flags {
     PA_SOURCE_HW_VOLUME_CTRL = 1,  /**< Supports hardware volume control */
     PA_SOURCE_LATENCY = 2,         /**< Supports latency querying */
-    PA_SOURCE_HARDWARE = 4,        /**< Is a hardware source of some kind, in contrast to "virtual"/software source \since 0.9.3 */
-    PA_SOURCE_CAN_SUSPEND = 8      /**< Can suspend \since 0.9.7 */
+    PA_SOURCE_HARDWARE = 4         /**< Is a hardware source of some kind, in contrast to "virtual"/software source \since 0.9.3 */
 } pa_source_flags_t;
 
 /** A generic free() like callback prototype */
diff --git a/src/pulse/stream.c b/src/pulse/stream.c
index 6d14a70..47906a5 100644
--- a/src/pulse/stream.c
+++ b/src/pulse/stream.c
@@ -423,7 +423,7 @@ static void create_stream_complete(pa_stream *s) {
         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) {
@@ -497,7 +497,7 @@ void pa_create_stream_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED
         s->state = PA_STREAM_READY;
         request_auto_timing_update(s, 1);
         s->state = PA_STREAM_CREATING;
-        
+
     } else
         create_stream_complete(s);
 
@@ -540,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)
@@ -921,7 +921,7 @@ 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) 
+    if (o->stream->state == PA_STREAM_CREATING)
         create_stream_complete(o->stream);
 
     if (o->stream->latency_update_callback)
diff --git a/src/pulsecore/cli-text.c b/src/pulsecore/cli-text.c
index bac61dc..ec22019 100644
--- a/src/pulsecore/cli-text.c
+++ b/src/pulsecore/cli-text.c
@@ -111,7 +111,7 @@ char *pa_sink_list_to_string(pa_core *c) {
             "  %c index: %u\n"
             "\tname: <%s>\n"
             "\tdriver: <%s>\n"
-            "\tflags: %s%s%s%s\n"
+            "\tflags: %s%s%s\n"
             "\tstate: %s\n"
             "\tvolume: <%s>\n"
             "\tmute: <%i>\n"
@@ -119,7 +119,7 @@ char *pa_sink_list_to_string(pa_core *c) {
             "\tmonitor source: <%u>\n"
             "\tsample spec: <%s>\n"
             "\tchannel map: <%s>\n"
-            "\tused by: <%u>\n", 
+            "\tused by: <%u>\n",
             c->default_sink_name && !strcmp(sink->name, c->default_sink_name) ? '*' : ' ',
             sink->index,
             sink->name,
@@ -127,7 +127,6 @@ char *pa_sink_list_to_string(pa_core *c) {
             sink->flags & PA_SINK_HW_VOLUME_CTRL ? "HW_VOLUME_CTRL " : "",
             sink->flags & PA_SINK_LATENCY ? "LATENCY " : "",
             sink->flags & PA_SINK_HARDWARE ? "HARDWARE " : "",
-            sink->flags & PA_SINK_CAN_SUSPEND ? "CAN_SUSPEND " : "",
             state_table[pa_sink_get_state(sink)],
             pa_cvolume_snprint(cv, sizeof(cv), pa_sink_get_volume(sink)),
             !!pa_sink_get_mute(sink),
@@ -171,7 +170,7 @@ char *pa_source_list_to_string(pa_core *c) {
             "  %c index: %u\n"
             "\tname: <%s>\n"
             "\tdriver: <%s>\n"
-            "\tflags: %s%s%s%s\n"
+            "\tflags: %s%s%s\n"
             "\tstate: %s\n"
             "\tvolume: <%s>\n"
             "\tmute: <%u>\n"
@@ -186,7 +185,6 @@ char *pa_source_list_to_string(pa_core *c) {
             source->flags & PA_SOURCE_HW_VOLUME_CTRL ? "HW_VOLUME_CTRL " : "",
             source->flags & PA_SOURCE_LATENCY ? "LATENCY " : "",
             source->flags & PA_SOURCE_HARDWARE ? "HARDWARE " : "",
-            source->flags & PA_SOURCE_CAN_SUSPEND ? "CAN_SUSPEND " : "",
             state_table[pa_source_get_state(source)],
             pa_cvolume_snprint(cv, sizeof(cv), pa_source_get_volume(source)),
             !!pa_source_get_mute(source),
diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c
index b814f83..830960a 100644
--- a/src/pulsecore/sink.c
+++ b/src/pulsecore/sink.c
@@ -170,9 +170,6 @@ static int sink_set_state(pa_sink *s, pa_sink_state_t state) {
     if (s->state == state)
         return 0;
 
-    if (state == PA_SINK_SUSPENDED && !(s->flags & PA_SINK_CAN_SUSPEND))
-        return -1;
-
     if ((s->state == PA_SINK_SUSPENDED && PA_SINK_OPENED(state)) ||
         (PA_SINK_OPENED(s->state) && state == PA_SINK_SUSPENDED)) {
         pa_sink_input *i;
diff --git a/src/pulsecore/source.c b/src/pulsecore/source.c
index 9745a13..20088c7 100644
--- a/src/pulsecore/source.c
+++ b/src/pulsecore/source.c
@@ -145,9 +145,6 @@ static int source_set_state(pa_source *s, pa_source_state_t state) {
     if (s->state == state)
         return 0;
 
-    if (state == PA_SOURCE_SUSPENDED && !(s->flags & PA_SOURCE_CAN_SUSPEND))
-        return -1;
-
     if ((s->state == PA_SOURCE_SUSPENDED && PA_SOURCE_OPENED(state)) ||
         (PA_SOURCE_OPENED(s->state) && state == PA_SOURCE_SUSPENDED)) {
         pa_source_output *o;

commit 55651ec215b8359aaf3668cc37eb270847563cc3
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Sep 24 16:24:23 2007 +0000

    don't count streams using the monitor source in pa_sink_used_by(), because this would disallow suspending a sink ehn an rtp stream is connected
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1895 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/cli-text.c b/src/pulsecore/cli-text.c
index ec22019..6683e69 100644
--- a/src/pulsecore/cli-text.c
+++ b/src/pulsecore/cli-text.c
@@ -119,7 +119,8 @@ char *pa_sink_list_to_string(pa_core *c) {
             "\tmonitor source: <%u>\n"
             "\tsample spec: <%s>\n"
             "\tchannel map: <%s>\n"
-            "\tused by: <%u>\n",
+            "\tused by: <%u>\n"
+            "\tlinked by: <%u>\n",
             c->default_sink_name && !strcmp(sink->name, c->default_sink_name) ? '*' : ' ',
             sink->index,
             sink->name,
@@ -134,7 +135,8 @@ char *pa_sink_list_to_string(pa_core *c) {
             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_sink_used_by(sink));
+            pa_sink_used_by(sink),
+            pa_sink_linked_by(sink));
 
         if (sink->module)
             pa_strbuf_printf(s, "\tmodule: <%u>\n", sink->module->index);
@@ -177,7 +179,8 @@ char *pa_source_list_to_string(pa_core *c) {
             "\tlatency: <%0.0f usec>\n"
             "\tsample spec: <%s>\n"
             "\tchannel map: <%s>\n"
-            "\tused by: <%u>\n",
+            "\tused by: <%u>\n"
+            "\tlinked by: <%u>\n",
             c->default_source_name && !strcmp(source->name, c->default_source_name) ? '*' : ' ',
             source->index,
             source->name,
@@ -191,7 +194,8 @@ char *pa_source_list_to_string(pa_core *c) {
             (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_source_used_by(source));
+            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);
diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c
index 830960a..733a9d9 100644
--- a/src/pulsecore/sink.c
+++ b/src/pulsecore/sink.c
@@ -775,8 +775,11 @@ unsigned pa_sink_linked_by(pa_sink *s) {
 
     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;
 }
@@ -788,13 +791,11 @@ unsigned pa_sink_used_by(pa_sink *s) {
     pa_assert(PA_SINK_LINKED(s->state));
 
     ret = pa_idxset_size(s->inputs);
-
     pa_assert(ret >= s->n_corked);
-
     ret -= s->n_corked;
 
-    if (s->monitor_source)
-        ret += pa_source_used_by(s->monitor_source);
+    /* Streams connected to our monitor source do not matter for
+     * pa_sink_used_by()!.*/
 
     return ret;
 }

commit ef020c6e8918c0481451e5640e95faf56ed453a5
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Sep 24 17:14:00 2007 +0000

    fix stream corking: ignore pa_sink_input() when we are in corked state
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1896 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c
index 9360bee..4a9ba6a 100644
--- a/src/pulsecore/sink-input.c
+++ b/src/pulsecore/sink-input.c
@@ -397,7 +397,7 @@ int pa_sink_input_peek(pa_sink_input *i, size_t length, pa_memchunk *chunk, pa_c
     pa_assert(chunk);
     pa_assert(volume);
 
-    if (!i->peek || !i->drop || i->thread_info.state == PA_SINK_INPUT_UNLINKED || i->thread_info.state == PA_SINK_INPUT_CORKED)
+    if (!i->peek || !i->drop || i->thread_info.state == PA_SINK_INPUT_CORKED)
         goto finish;
 
     pa_assert(i->thread_info.state == PA_SINK_INPUT_RUNNING || i->thread_info.state == PA_SINK_INPUT_DRAINED);
@@ -518,6 +518,9 @@ void pa_sink_input_drop(pa_sink_input *i, size_t length) {
     pa_assert(pa_frame_aligned(length, &i->sink->sample_spec));
     pa_assert(length > 0);
 
+    if (!i->peek || !i->drop || i->thread_info.state == PA_SINK_INPUT_CORKED)
+        return;
+
     if (i->thread_info.move_silence > 0) {
 
         if (i->thread_info.move_silence >= length) {

commit e37fa011ac18742303c351aee1cb2f6739e04b82
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Sep 24 21:47:22 2007 +0000

    add hooks for name/description changes of sinks/source and streams
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1897 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/core.h b/src/pulsecore/core.h
index c8d7580..b841c20 100644
--- a/src/pulsecore/core.h
+++ b/src/pulsecore/core.h
@@ -47,22 +47,26 @@ typedef enum pa_core_hook {
     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_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_MAX
 } pa_core_hook_t;
 
@@ -90,7 +94,7 @@ struct pa_core {
 
     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;
 
@@ -110,7 +114,7 @@ struct pa_core {
     int disallow_module_loading, running_as_daemon;
     pa_resample_method_t resample_method;
     int is_system_instance;
-    int high_priority; 
+    int high_priority;
 
     /* hooks */
     pa_hook hooks[PA_CORE_HOOK_MAX];
diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c
index 4a9ba6a..632cf02 100644
--- a/src/pulsecore/sink-input.c
+++ b/src/pulsecore/sink-input.c
@@ -683,7 +683,10 @@ 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) {
diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c
index 733a9d9..46f890d 100644
--- a/src/pulsecore/sink.c
+++ b/src/pulsecore/sink.c
@@ -764,7 +764,10 @@ 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_linked_by(pa_sink *s) {
diff --git a/src/pulsecore/source-output.c b/src/pulsecore/source-output.c
index 1991613..f83ca3b 100644
--- a/src/pulsecore/source-output.c
+++ b/src/pulsecore/source-output.c
@@ -356,7 +356,10 @@ void pa_source_output_set_name(pa_source_output *o, const char *name) {
     pa_xfree(o->name);
     o->name = pa_xstrdup(name);
 
-    pa_subscription_post(o->source->core, PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_CHANGE, o->index);
+    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) {
diff --git a/src/pulsecore/source.c b/src/pulsecore/source.c
index 20088c7..2106edc 100644
--- a/src/pulsecore/source.c
+++ b/src/pulsecore/source.c
@@ -418,7 +418,10 @@ 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);
+    }
 }
 
 void pa_source_set_asyncmsgq(pa_source *s, pa_asyncmsgq *q) {

commit 3c75d35dd004a55753934ed328d7e037cbf8c596
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Sep 24 21:49:02 2007 +0000

    rework zeroconf service publishing, to use synchronous hooks instead of asynchronous subscription events. Don't push autoload entries anymore.
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1898 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-zeroconf-publish.c b/src/modules/module-zeroconf-publish.c
index 8b62ffb..ac9d047 100644
--- a/src/modules/module-zeroconf-publish.c
+++ b/src/modules/module-zeroconf-publish.c
@@ -39,7 +39,6 @@
 #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,53 +70,43 @@ 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) {
-    pa_assert(u);
+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(s->loaded.valid);
     pa_assert(ret_ss);
     pa_assert(ret_description);
 
-    if (s->loaded.type == PA_NAMEREG_SINK) {
-        pa_sink *sink = PA_SINK(pa_idxset_get_by_index(u->core->sinks, s->loaded.index));
-        pa_sink_assert_ref(sink);
+    if (pa_sink_isinstance(s->device)) {
+        pa_sink *sink = PA_SINK(s->device);
+
         *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_SOURCE(pa_idxset_get_by_index(u->core->sources, s->loaded.index));
-        pa_source_assert_ref(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
         pa_assert_not_reached();
@@ -125,7 +114,7 @@ static void get_service_data(struct userdata *u, struct service *s, pa_sample_sp
 
 static AvahiStringList* txt_record_server_data(pa_core *c, AvahiStringList *l) {
     char s[128];
-    
+
     pa_core_assert_ref(c);
 
     l = avahi_string_list_add_pair(l, "server-version", PACKAGE_NAME" "PACKAGE_VERSION);
@@ -136,340 +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;
 
     pa_assert(s);
 
-    if (state == AVAHI_ENTRY_GROUP_COLLISION) {
-        char *t;
+    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;
 
-        t = avahi_alternative_service_name(s->service_name);
-        pa_xfree(s->service_name);
-        s->service_name = t;
+            publish_service(s);
+            break;
+        }
+
+        case AVAHI_ENTRY_GROUP_FAILURE: {
+            pa_log("Failed to register service: %s", avahi_strerror(avahi_client_errno(avahi_entry_group_get_client(g))));
+
+            avahi_entry_group_free(g);
+            s->entry_group = NULL;
+
+            break;
+        }
 
-        publish_service(s->userdata, s);
+        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];
 
-    pa_assert(u);
     pa_assert(s);
 
-    if (!u->client || avahi_client_get_state(u->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))
+    if (!s->userdata->client || avahi_client_get_state(s->userdata->client) != AVAHI_CLIENT_S_RUNNING)
         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], 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_truncate_utf8(pa_sprintf_malloc("%s@%s: %s", pa_get_user_name(un, sizeof(un)), pa_get_host_name(hn, sizeof(hn)), description ? description : s->name), AVAHI_LABEL_MAX-1);
-
-    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;
-
-    pa_assert(u);
-    pa_sink_assert_ref(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;
-
-    pa_assert(u);
-    pa_source_assert_ref(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;
-
-    pa_assert(u);
+static void service_free(struct service *s) {
     pa_assert(s);
 
-    svc = get_service(u, s->name, NULL);
-    if (svc->autoload.valid)
-        return publish_service(u, svc);
-
-    svc->autoload.valid = 1;
-    svc->autoload.type = s->type;
-    svc->autoload.index = s->index;
+    pa_hashmap_remove(s->userdata->services, s->device);
 
-    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;
-    
-    pa_assert(u);
-    pa_assert(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;
-    
-    pa_assert(u);
-    pa_assert(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;
-    
-    pa_assert(u);
-    pa_assert(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;
-    
     pa_assert(u);
-    pa_core_assert_ref(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_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;
-            }
+    switch (state) {
 
+        case AVAHI_ENTRY_GROUP_ESTABLISHED:
+            pa_log_info("Successfully established main service.");
             break;
 
-        case PA_SUBSCRIPTION_EVENT_SOURCE:
+        case AVAHI_ENTRY_GROUP_COLLISION: {
+            char *t;
 
-            if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_NEW) {
-                pa_source *source;
-
-                if ((source = PA_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;
-    pa_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;
     }
 }
 
@@ -478,7 +344,7 @@ static int publish_main_service(struct userdata *u) {
     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)));
@@ -487,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,
@@ -520,7 +386,6 @@ 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;
 
@@ -529,17 +394,10 @@ static int publish_all_services(struct userdata *u) {
     pa_log_debug("Publishing services in Zeroconf");
 
     for (sink = PA_SINK(pa_idxset_first(u->core->sinks, &idx)); sink; sink = PA_SINK(pa_idxset_next(u->core->sinks, &idx)))
-        if (publish_sink(u, sink) < 0)
-            goto fail;
+        publish_service(get_service(u, PA_OBJECT(sink)));
 
     for (source = PA_SOURCE(pa_idxset_first(u->core->sources, &idx)); source; source = PA_SOURCE(pa_idxset_next(u->core->sources, &idx)))
-        if (publish_source(u, source) < 0)
-            goto fail;
-
-    if (u->core->autoload_idxset)
-        for (autoload = pa_idxset_first(u->core->autoload_idxset, &idx); autoload; autoload = pa_idxset_next(u->core->autoload_idxset, &idx))
-            if (publish_autoload(u, autoload) < 0)
-                goto fail;
+        publish_service(get_service(u, PA_OBJECT(source)));
 
     if (publish_main_service(u) < 0)
         goto fail;
@@ -550,7 +408,7 @@ 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;
 
@@ -561,27 +419,31 @@ static void unpublish_all_services(struct userdata *u, int rem) {
     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;
-    
+
     pa_assert(c);
     pa_assert(u);
 
@@ -593,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)))
@@ -613,7 +479,7 @@ static void client_callback(AvahiClient *c, AvahiClientState state, void *userda
 }
 
 int pa__init(pa_module*m) {
-    
+
     struct userdata *u;
     uint32_t port = PA_NATIVE_DEFAULT_PORT;
     pa_modargs *ma = NULL;
@@ -636,15 +502,14 @@ int pa__init(pa_module*m) {
 
     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(m->core,
-                                          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;
 
@@ -668,21 +533,6 @@ fail:
     return -1;
 }
 
-static void service_free(void *p, void *userdata) {
-    struct service *s = p;
-    struct userdata *u = userdata;
-
-    pa_assert(s);
-    pa_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_module*m) {
     struct userdata*u;
     pa_assert(m);
@@ -690,18 +540,27 @@ void pa__done(pa_module*m) {
     if (!(u = m->userdata))
         return;
 
-    if (u->services)
-        pa_hashmap_free(u->services, service_free, u);
+    if (u->services) {
+        struct service *s;
+
+        while ((s = pa_hashmap_get_first(u->services)))
+            service_free(s);
 
-    if (u->subscription)
-        pa_subscription_free(u->subscription);
+        pa_hashmap_free(u->services, NULL, NULL);
+    }
 
-    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);
+    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);
@@ -715,4 +574,3 @@ void pa__done(pa_module*m) {
     pa_xfree(u->service_name);
     pa_xfree(u);
 }
-

commit ac86fa1b9725d602b68410a56ebee355877f769d
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Sep 24 22:41:00 2007 +0000

    fix IDLE vs. RUNNING state handling of sinks/sources when changing cork status for streams
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1899 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c
index 632cf02..e99e0a0 100644
--- a/src/pulsecore/sink-input.c
+++ b/src/pulsecore/sink-input.c
@@ -233,6 +233,8 @@ static void update_n_corked(pa_sink_input *i, pa_sink_input_state_t state) {
         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) {
@@ -350,6 +352,9 @@ void pa_sink_input_put(pa_sink_input *i) {
     i->thread_info.volume = i->volume;
     i->thread_info.muted = i->muted;
 
+    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);
 
diff --git a/src/pulsecore/source-output.c b/src/pulsecore/source-output.c
index f83ca3b..207e2a3 100644
--- a/src/pulsecore/source-output.c
+++ b/src/pulsecore/source-output.c
@@ -188,6 +188,8 @@ static int source_output_set_state(pa_source_output *o, pa_source_output_state_t
     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;
 
     return 0;
@@ -262,6 +264,9 @@ void pa_source_output_put(pa_source_output *o) {
 
     o->thread_info.state = o->state = o->flags & PA_SOURCE_OUTPUT_START_CORKED ? PA_SOURCE_OUTPUT_CORKED : PA_SOURCE_OUTPUT_RUNNING;
 
+    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);
 

commit f0f9df999045c202def3a46589a98bdae86127ea
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Sep 24 23:31:22 2007 +0000

    * add new state changed hook for streams
    * update sink->n_corked properly when moving streams
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1900 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/core.h b/src/pulsecore/core.h
index b841c20..dfa80f8 100644
--- a/src/pulsecore/core.h
+++ b/src/pulsecore/core.h
@@ -60,6 +60,7 @@ typedef enum pa_core_hook {
     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,
@@ -67,6 +68,7 @@ typedef enum pa_core_hook {
     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;
 
diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c
index e99e0a0..ce48765 100644
--- a/src/pulsecore/sink-input.c
+++ b/src/pulsecore/sink-input.c
@@ -262,6 +262,9 @@ static int sink_input_set_state(pa_sink_input *i, pa_sink_input_state_t 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;
 }
 
@@ -825,6 +828,11 @@ int pa_sink_input_move_to(pa_sink_input *i, pa_sink *dest, int immediately) {
     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->thread_info.resampler) {
         if (i->thread_info.resampler)
diff --git a/src/pulsecore/source-output.c b/src/pulsecore/source-output.c
index 207e2a3..2a902dc 100644
--- a/src/pulsecore/source-output.c
+++ b/src/pulsecore/source-output.c
@@ -192,6 +192,9 @@ static int source_output_set_state(pa_source_output *o, pa_source_output_state_t
 
     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;
 }
 
@@ -427,6 +430,11 @@ int pa_source_output_move_to(pa_source_output *o, pa_source *dest) {
     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->thread_info.resampler) {
         if (o->thread_info.resampler)

commit 0e3e9e227477784a1559dd71f667c269f06e635c
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Sep 24 23:32:01 2007 +0000

    only post data into the monitor source when it is not suspended
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1901 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c
index 46f890d..38e7d63 100644
--- a/src/pulsecore/sink.c
+++ b/src/pulsecore/sink.c
@@ -482,7 +482,7 @@ void pa_sink_render(pa_sink*s, size_t length, pa_memchunk *result) {
     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);
 
     pa_sink_unref(s);
@@ -549,7 +549,7 @@ void pa_sink_render_into(pa_sink*s, pa_memchunk *target) {
     if (s->thread_info.state == PA_SINK_RUNNING)
         inputs_drop(s, info, n, target->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, target);
 
     pa_sink_unref(s);

commit 609ad12f293eb0febebc7630c23a9978ce662211
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Sep 24 23:32:52 2007 +0000

    * decouple suspending of monitor sources and their sinks
    * implement resume-on-uncork
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1902 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-suspend-on-idle.c b/src/modules/module-suspend-on-idle.c
index 4fcb404..5a71139 100644
--- a/src/modules/module-suspend-on-idle.c
+++ b/src/modules/module-suspend-on-idle.c
@@ -66,7 +66,9 @@ struct userdata {
         *sink_input_move_slot,
         *source_output_move_slot,
         *sink_input_move_post_slot,
-        *source_output_move_post_slot;
+        *source_output_move_post_slot,
+        *sink_input_state_changed_slot,
+        *source_output_state_changed_slot;
 };
 
 struct device_info {
@@ -86,13 +88,12 @@ static void timeout_cb(pa_mainloop_api*a, pa_time_event* e, const struct timeval
 
     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, 1);
-        pa_source_suspend(d->sink->monitor_source, 1);
+        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, 1);
+        pa_source_suspend(d->source, TRUE);
     }
 }
 
@@ -117,16 +118,13 @@ static void resume(struct device_info *d) {
     d->userdata->core->mainloop->time_restart(d->time_event, NULL);
 
     if (d->sink) {
-        pa_sink_suspend(d->sink, 0);
-        pa_source_suspend(d->sink->monitor_source, 0);
+        pa_sink_suspend(d->sink, FALSE);
 
         pa_log_debug("Sink %s becomes busy.", d->sink->name);
     }
 
     if (d->source) {
-        pa_source_suspend(d->source, 0);
-        if (d->source->monitor_of)
-            pa_sink_suspend(d->source->monitor_of, 0);
+        pa_source_suspend(d->source, FALSE);
 
         pa_log_debug("Source %s becomes busy.", d->source->name);
     }
@@ -239,6 +237,36 @@ static pa_hook_result_t source_output_move_post_hook_cb(pa_core *c, pa_source_ou
     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;
@@ -305,21 +333,22 @@ static pa_hook_result_t device_state_changed_hook_cb(pa_core *c, pa_object *o, s
 
     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) {
-            pa_sink_state_t state = pa_sink_get_state(s);
 
-            if (state == PA_SINK_RUNNING || state == PA_SINK_IDLE)
+            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) {
-            pa_sink_state_t state = pa_source_get_state(s);
 
-            if (state == PA_SINK_RUNNING || state == PA_SINK_IDLE)
+            if (PA_SOURCE_OPENED(state))
                 restart(d);
         }
     }
@@ -373,6 +402,8 @@ int pa__init(pa_module*m) {
     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);
@@ -419,6 +450,8 @@ void pa__done(pa_module*m) {
         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);
@@ -428,6 +461,8 @@ void pa__done(pa_module*m) {
         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);

commit 86ec4215928ae1ee0752406cf4f9fe2df77795d8
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Sep 24 23:53:58 2007 +0000

    fix suspending in module-combine.c
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1903 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-combine.c b/src/modules/module-combine.c
index 656cef9..d9c2af6 100644
--- a/src/modules/module-combine.c
+++ b/src/modules/module-combine.c
@@ -450,7 +450,7 @@ static void sink_input_detach_cb(pa_sink_input *i) {
     pa_sink_input_assert_ref(i);
     pa_assert_se(o = i->userdata);
 
-    pa_log("detaching %s", i->sink->name);
+/*     pa_log("detaching %s", i->sink->name); */
 
     pa_assert(o->inq_rtpoll_item);
     pa_rtpoll_item_free(o->inq_rtpoll_item);
@@ -516,6 +516,9 @@ static int suspend(struct userdata *u) {
 
     /* Let's suspend by unlinking all streams */
 
+    if (update_master(u, NULL) < 0)
+        pa_module_unload_request(u->module);
+
     for (o = pa_idxset_first(u->outputs, &idx); o; o = pa_idxset_next(u->outputs, &idx)) {
 
         if (o->sink_input) {
@@ -525,9 +528,6 @@ static int suspend(struct userdata *u) {
         }
     }
 
-    if (pick_master(u, NULL) < 0)
-        pa_module_unload_request(u->module);
-
     pa_log_info("Device suspended...");
 
     return 0;

commit 16872268115a52735d9dffd846f392b6c25a0b49
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Sep 25 00:45:57 2007 +0000

    fix make dist
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1904 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/Makefile.am b/src/Makefile.am
index 9b4cb51..a92a557 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -78,8 +78,8 @@ endif
 if OS_IS_WIN32
 PA_THREAD_OBJS = \
 		pulsecore/mutex-win32.c pulsecore/mutex.h \
-		pulsecore/thread-win32.c pulsecore/thread.h \
-		pulsecore/semaphore-win32.c pulsecore/semaphore.h
+		pulsecore/thread-win32.c pulsecore/thread.h
+#		pulsecore/semaphore-win32.c pulsecore/semaphore.h
 else
 PA_THREAD_OBJS = \
 		pulsecore/mutex-posix.c pulsecore/mutex.h \

commit 5fe1589c8e258f9869e903a2d0856a8174ce9dde
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Sep 25 00:53:49 2007 +0000

    work around newest open() magic in fedora glibc
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1905 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/utils/padsp.c b/src/utils/padsp.c
index 556ac2b..299033e 100644
--- a/src/utils/padsp.c
+++ b/src/utils/padsp.c
@@ -61,6 +61,10 @@
 # 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,
@@ -1436,35 +1440,23 @@ fail:
     return -1;
 }
 
-#undef open
-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);
@@ -1478,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;
 
@@ -2491,17 +2499,20 @@ int stat64(const char *pathname, struct stat64 *buf) {
     return 0;
 }
 
-#undef open64
 int open64(const char *filename, int flags, ...) {
     va_list args;
     mode_t mode = 0;
 
     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 &&
@@ -2511,7 +2522,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
@@ -2603,7 +2614,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))) {

commit a9e667bb8384c508d1edbffe2af137db91f73abd
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Sep 25 01:58:16 2007 +0000

    make sure when can shutdown PA cleanly without segfault
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1906 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-zeroconf-publish.c b/src/modules/module-zeroconf-publish.c
index ac9d047..113686c 100644
--- a/src/modules/module-zeroconf-publish.c
+++ b/src/modules/module-zeroconf-publish.c
@@ -115,7 +115,7 @@ static void get_service_data(struct service *s, pa_sample_spec *ret_ss, pa_chann
 static AvahiStringList* txt_record_server_data(pa_core *c, AvahiStringList *l) {
     char s[128];
 
-    pa_core_assert_ref(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)));

commit e99bc33bcb6c3055ad3ebe6026783a5b38f9305c
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Sep 26 13:33:25 2007 +0000

    fix build with compilers that lack __thread
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1907 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/thread.h b/src/pulsecore/thread.h
index 6aaf8c8..54ef320 100644
--- a/src/pulsecore/thread.h
+++ b/src/pulsecore/thread.h
@@ -76,7 +76,7 @@ void *pa_tls_set(pa_tls *t, void *userdata);
         if (_free_cb) {                                                 \
             void *p;                                                    \
             if ((p = pa_tls_get(name##_tls.tls)))                       \
-                free_cb(p);                                             \
+                _free_cb(p);                                            \
         }                                                               \
         pa_tls_free(name##_tls.tls);                                    \
     }                                                                   \

commit 008c7099007c9cda76a2d3bc966d2392c7b7a76d
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Sep 26 22:50:08 2007 +0000

    Use Linux eventfd() if kernel supports it
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1908 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/fdsem.c b/src/pulsecore/fdsem.c
index c81797e..b919ba4 100644
--- a/src/pulsecore/fdsem.c
+++ b/src/pulsecore/fdsem.c
@@ -25,6 +25,7 @@
 #include <config.h>
 #endif
 
+#include <sys/syscall.h>
 #include <unistd.h>
 #include <errno.h>
 
@@ -35,10 +36,37 @@
 #include <pulsecore/core-util.h>
 #include <pulse/xmalloc.h>
 
+#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;
@@ -48,25 +76,38 @@ pa_fdsem *pa_fdsem_new(void) {
     pa_fdsem *f;
 
     f = pa_xnew(pa_fdsem, 1);
-    
-    if (pipe(f->fds) < 0) {
-        pa_xfree(f);
-        return NULL;
-    }
 
-    pa_make_fd_cloexec(f->fds[0]);
-    pa_make_fd_cloexec(f->fds[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);
@@ -81,12 +122,24 @@ static void flush(pa_fdsem *f) {
 
     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);
 }
 
@@ -98,11 +151,22 @@ void pa_fdsem_post(pa_fdsem *f) {
         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;
@@ -123,16 +187,29 @@ void pa_fdsem_wait(pa_fdsem *f) {
         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);
     }
 
@@ -143,17 +220,21 @@ 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];
 }
 
@@ -170,7 +251,7 @@ int pa_fdsem_before_poll(pa_fdsem *f) {
     if (pa_atomic_cmpxchg(&f->signalled, 1, 0)) {
         pa_assert_se(pa_atomic_dec(&f->waiting) >= 1);
         return -1;
-    }        
+    }
     return 0;
 }
 

commit 107f12ae3ccc95f124d2659e062f5d1f4093dc02
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Sep 28 00:29:51 2007 +0000

    speed up semaphore allocation with an flist
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1909 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/asyncmsgq.c b/src/pulsecore/asyncmsgq.c
index c0917ca..9910f65 100644
--- a/src/pulsecore/asyncmsgq.c
+++ b/src/pulsecore/asyncmsgq.c
@@ -40,6 +40,7 @@
 #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;
@@ -154,7 +155,11 @@ int pa_asyncmsgq_send(pa_asyncmsgq *a, pa_msgobject *object, int code, const voi
         i.memchunk = *chunk;
     } else
         pa_memchunk_reset(&i.memchunk);
-    pa_assert_se(i.semaphore = pa_semaphore_new(0));
+
+    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);
@@ -162,7 +167,9 @@ int pa_asyncmsgq_send(pa_asyncmsgq *a, pa_msgobject *object, int code, const voi
     pa_mutex_unlock(a->mutex);
 
     pa_semaphore_wait(i.semaphore);
-    pa_semaphore_free(i.semaphore);
+
+    if (pa_flist_push(PA_STATIC_FLIST_GET(semaphores), i.semaphore) < 0)
+        pa_semaphore_free(i.semaphore);
 
     return i.ret;
 }
@@ -192,7 +199,7 @@ int pa_asyncmsgq_get(pa_asyncmsgq *a, pa_msgobject **object, int *code, void **u
         *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;
 }
 
@@ -244,7 +251,7 @@ int pa_asyncmsgq_wait_for(pa_asyncmsgq *a, int code) {
     } while (c != code);
 
     pa_asyncmsgq_unref(a);
-    
+
     return 0;
 }
 
@@ -257,15 +264,15 @@ int pa_asyncmsgq_process_one(pa_asyncmsgq *a) {
     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;
 }
 

commit 584ca6193c41c2fbe8e0d7acf7075a0eb33b1090
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Sep 28 00:30:48 2007 +0000

    don't free silence memblocks that don't exist
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1910 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c
index ce48765..6f654b6 100644
--- a/src/pulsecore/sink-input.c
+++ b/src/pulsecore/sink-input.c
@@ -540,9 +540,10 @@ void pa_sink_input_drop(pa_sink_input *i, size_t length) {
         }
 
         if (i->thread_info.move_silence <= 0) {
-            pa_assert(i->thread_info.silence_memblock);
-            pa_memblock_unref(i->thread_info.silence_memblock);
-            i->thread_info.silence_memblock = NULL;
+            if (i->thread_info.silence_memblock) {
+                pa_memblock_unref(i->thread_info.silence_memblock);
+                i->thread_info.silence_memblock = NULL;
+            }
         }
 
         if (length <= 0)

commit 6d8aea724eb0011a068c9c883450418c80fda777
Author: Pierre Ossman <ossman at cendio.se>
Date:   Fri Sep 28 09:23:05 2007 +0000

    Incorrectly used str2sig() instead of sig2str().
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1911 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/core-util.c b/src/pulsecore/core-util.c
index 6db0870..3defe2b 100644
--- a/src/pulsecore/core-util.c
+++ b/src/pulsecore/core-util.c
@@ -639,7 +639,7 @@ const char *pa_sig2str(int sig) {
     {
         char buf[SIG2STR_MAX];
 
-        if (str2sig(sig, buf) == 0) {
+        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);

commit df33b4c7b339a1c26ccbfd80e5b91637c177b378
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Sep 28 12:22:56 2007 +0000

    only do IO if we are RUNNING or IDLE, but not when we are in INIT
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1912 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-oss.c b/src/modules/module-oss.c
index 8d08899..82b5b6c 100644
--- a/src/modules/module-oss.c
+++ b/src/modules/module-oss.c
@@ -849,7 +849,7 @@ static void thread_func(void *userdata) {
 
         /* Render some data and write it to the dsp */
 
-        if (u->sink && u->sink->thread_info.state != PA_SINK_UNLINKED && u->fd >= 0 && (revents & POLLOUT)) {
+        if (u->sink && PA_SINK_OPENED(u->sink->thread_info.state) && (revents & POLLOUT)) {
 
             if (u->use_mmap) {
 
@@ -939,7 +939,7 @@ static void thread_func(void *userdata) {
 
         /* Try to read some data and pass it on to the source driver */
 
-        if (u->source && u->source->thread_info.state != PA_SOURCE_UNLINKED && u->fd >= 0 && ((revents & POLLIN))) {
+        if (u->source && PA_SOURCE_OPENED(u->source->thread_info.state) && ((revents & POLLIN))) {
 
             if (u->use_mmap) {
 

commit 3cdff5f3cc79aeabedada6633ce2d779d0a21b60
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Sep 28 12:52:47 2007 +0000

    Allocate rtsigs from back to front, to avoid clashes with other libraries makeing use of rtsigs
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1913 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/rtsig.c b/src/pulsecore/rtsig.c
index 3513bed..1af45e7 100644
--- a/src/pulsecore/rtsig.c
+++ b/src/pulsecore/rtsig.c
@@ -50,17 +50,17 @@ 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_inc(&rtsig_current);
+    sig = pa_atomic_dec(&rtsig_current);
 
-    pa_assert(sig >= SIGRTMIN);
-    pa_assert(sig >= rtsig_start);
-    
-    if (sig > rtsig_end) {
-        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;
     }
 
@@ -73,7 +73,7 @@ int pa_rtsig_get_for_thread(void) {
 
     if ((p = PA_STATIC_TLS_GET(rtsig_tls)))
         return PA_PTR_TO_INT(p);
-    
+
     if ((sig = pa_rtsig_get()) < 0)
         return -1;
 
@@ -102,11 +102,12 @@ void pa_rtsig_configure(int start, int end) {
     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);
-    
-    pa_atomic_store(&rtsig_current, rtsig_start);
+
+    /* We allocate starting from the end */
+    pa_atomic_store(&rtsig_current, rtsig_end);
 }

commit f8c17861b8e528909b2d14641a2cd362fd7c4f8f
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Sep 28 12:53:17 2007 +0000

    use the full range of RTSIGS for our stuff
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1914 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/daemon/main.c b/src/daemon/main.c
index a660ab1..0e759d2 100644
--- a/src/daemon/main.c
+++ b/src/daemon/main.c
@@ -327,7 +327,7 @@ int main(int argc, char *argv[]) {
     struct timeval tv;
 #endif
 
-    
+
 #if defined(__linux__) && defined(__OPTIMIZE__)
     /*
        Disable lazy relocations to make usage of external libraries
@@ -343,7 +343,7 @@ int main(int argc, char *argv[]) {
         pa_assert_se(execv("/proc/self/exe", argv) == 0);
     }
 #endif
-    
+
 #ifdef HAVE_GETUID
     real_root = getuid() == 0;
     suid_root = !real_root && geteuid() == 0;
@@ -440,10 +440,10 @@ int main(int argc, char *argv[]) {
             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;
@@ -482,7 +482,7 @@ int main(int argc, char *argv[]) {
                 retval = 0;
 
             goto finish;
-            
+
         default:
             pa_assert(conf->cmd == PA_CMD_DAEMON);
     }
@@ -608,13 +608,13 @@ int main(int argc, char *argv[]) {
 #endif
 
     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!");
-    
-    pa_rtsig_configure(SIGRTMIN+10, SIGRTMAX);
+
+    pa_rtsig_configure(SIGRTMIN, SIGRTMAX);
 
     pa_assert_se(mainloop = pa_mainloop_new());
 
@@ -659,7 +659,7 @@ int main(int argc, char *argv[]) {
 
     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)
         r = pa_cli_command_execute_file(c, conf->default_script_file, buf, &conf->fail);
@@ -736,6 +736,6 @@ finish:
 #ifdef HAVE_DBUS
     dbus_shutdown();
 #endif
-    
+
     return retval;
 }

commit 229afb5e2dca2ea4cf8e5f48268cd9c419ea6f4b
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Sep 28 13:00:35 2007 +0000

    Move the poll() call outside the #ifdef checking for ppoll, since we want the poll in all cases. Prior to this change the check for negative return values of poll/ppoll was never actually executed when ppoll() was available
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1915 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/rtpoll.c b/src/pulsecore/rtpoll.c
index 1b52385..921619d 100644
--- a/src/pulsecore/rtpoll.c
+++ b/src/pulsecore/rtpoll.c
@@ -62,9 +62,9 @@ struct pa_rtpoll {
     timer_t timer;
 #ifdef __linux__
     pa_bool_t dont_use_ppoll;
-#endif    
 #endif
-    
+#endif
+
     PA_LLIST_HEAD(pa_rtpoll_item, items);
 };
 
@@ -81,7 +81,7 @@ struct pa_rtpoll_item {
     int (*before_cb)(pa_rtpoll_item *i);
     void (*after_cb)(pa_rtpoll_item *i);
     void *userdata;
-    
+
     PA_LLIST_FIELDS(pa_rtpoll_item);
 };
 
@@ -99,11 +99,11 @@ pa_rtpoll *pa_rtpoll_new(void) {
 #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 ||
@@ -119,7 +119,7 @@ pa_rtpoll *pa_rtpoll_new(void) {
     p->rtsig = -1;
     sigemptyset(&p->sigset_unblocked);
     p->timer = (timer_t) -1;
-        
+
 #endif
 
     p->n_pollfd_alloc = 32;
@@ -136,7 +136,7 @@ pa_rtpoll *pa_rtpoll_new(void) {
     p->scan_for_dead = FALSE;
     p->rebuild_needed = FALSE;
     p->quit = FALSE;
-    
+
     PA_LLIST_HEAD_INIT(pa_rtpoll_item, p->items);
 
     return p;
@@ -145,7 +145,7 @@ pa_rtpoll *pa_rtpoll_new(void) {
 void pa_rtpoll_install(pa_rtpoll *p) {
     pa_assert(p);
     pa_assert(!p->installed);
-    
+
     p->installed = 1;
 
 #ifdef HAVE_PPOLL
@@ -162,7 +162,7 @@ void pa_rtpoll_install(pa_rtpoll *p) {
     {
         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);
@@ -171,12 +171,12 @@ void pa_rtpoll_install(pa_rtpoll *p) {
         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
 }
 
@@ -185,7 +185,7 @@ 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;
@@ -203,7 +203,7 @@ static void rtpoll_rebuild(pa_rtpoll *p) {
 
         if (i->n_pollfd > 0)  {
             size_t l = i->n_pollfd * sizeof(struct pollfd);
-            
+
             if (i->pollfd)
                 memcpy(e, i->pollfd, l);
             else
@@ -212,7 +212,7 @@ static void rtpoll_rebuild(pa_rtpoll *p) {
             i->pollfd = e;
         } else
             i->pollfd = NULL;
-        
+
         e += i->n_pollfd;
     }
 
@@ -220,7 +220,7 @@ static void rtpoll_rebuild(pa_rtpoll *p) {
     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));
 
@@ -236,7 +236,7 @@ static void rtpoll_item_destroy(pa_rtpoll_item *i) {
     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);
 
@@ -253,22 +253,22 @@ void pa_rtpoll_free(pa_rtpoll *p) {
     pa_xfree(p->pollfd2);
 
 #ifdef HAVE_PPOLL
-    if (p->timer != (timer_t) -1) 
+    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;
 }
@@ -277,12 +277,12 @@ 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);
     }
 }
@@ -291,30 +291,30 @@ int pa_rtpoll_run(pa_rtpoll *p, pa_bool_t wait) {
     pa_rtpoll_item *i;
     int r = 0;
     struct timespec 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;
         }
     }
@@ -322,10 +322,10 @@ int pa_rtpoll_run(pa_rtpoll *p, pa_bool_t wait) {
     /* 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;
 
@@ -334,10 +334,10 @@ int pa_rtpoll_run(pa_rtpoll *p, pa_bool_t wait) {
             /* 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;
 
@@ -346,7 +346,7 @@ int pa_rtpoll_run(pa_rtpoll *p, pa_bool_t wait) {
 
             if (k < 0)
                 r = k;
-            
+
             goto finish;
         }
     }
@@ -367,7 +367,7 @@ int pa_rtpoll_run(pa_rtpoll *p, pa_bool_t wait) {
         else
             pa_timespec_store(&timeout, pa_timespec_diff(&p->next_elapse, &now));
     }
-    
+
     /* OK, now let's sleep */
 #ifdef HAVE_PPOLL
 
@@ -379,17 +379,16 @@ int pa_rtpoll_run(pa_rtpoll *p, pa_bool_t wait) {
     else
 #endif
 
-#else
-        r = poll(p->pollfd, p->n_pollfd_used, p->timer_enabled > 0 ? (timeout.tv_sec*1000) + (timeout.tv_nsec / 1000000) : -1);
 #endif
+        r = poll(p->pollfd, p->n_pollfd_used, p->timer_enabled > 0 ? (timeout.tv_sec*1000) + (timeout.tv_nsec / 1000000) : -1);
 
     if (r < 0) {
-        reset_all_revents(p);
-    
         if (errno == EAGAIN || errno == EINTR)
             r = 0;
         else
             pa_log_error("poll(): %s", pa_cstrerror(errno));
+
+        reset_all_revents(p);
     }
 
     if (p->timer_enabled) {
@@ -422,12 +421,12 @@ int pa_rtpoll_run(pa_rtpoll *p, pa_bool_t wait) {
 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;
 
@@ -447,7 +446,7 @@ static void update_timer(pa_rtpoll *p) {
 #ifdef __linux__
     if (!p->dont_use_ppoll) {
 #endif
-        
+
         if (p->timer == (timer_t) -1) {
             struct sigevent se;
 
@@ -473,7 +472,7 @@ static void update_timer(pa_rtpoll *p) {
                  * "disarming" */
                 if (its.it_value.tv_sec == 0)
                     its.it_value.tv_nsec = 1;
-                
+
                 if (p->period > 0)
                     pa_timespec_store(&its.it_interval, p->period);
             }
@@ -484,18 +483,18 @@ static void update_timer(pa_rtpoll *p) {
 #ifdef __linux__
     }
 #endif
-    
+
 #endif
 }
 
 void pa_rtpoll_set_timer_absolute(pa_rtpoll *p, const struct timespec *ts) {
     pa_assert(p);
     pa_assert(ts);
-    
+
     p->next_elapse = *ts;
     p->period = 0;
     p->timer_enabled = TRUE;
-    
+
     update_timer(p);
 }
 
@@ -533,7 +532,7 @@ void pa_rtpoll_set_timer_disabled(pa_rtpoll *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))))
@@ -582,20 +581,20 @@ void pa_rtpoll_item_free(pa_rtpoll_item *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->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;
 }
 
@@ -635,7 +634,7 @@ static int fdsem_before(pa_rtpoll_item *i) {
 
 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);
 }
@@ -643,7 +642,7 @@ static void fdsem_after(pa_rtpoll_item *i) {
 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);
 
@@ -653,7 +652,7 @@ pa_rtpoll_item *pa_rtpoll_item_new_fdsem(pa_rtpoll *p, pa_rtpoll_priority_t prio
 
     pollfd->fd = pa_fdsem_get(f);
     pollfd->events = POLLIN;
-    
+
     i->before_cb = fdsem_before;
     i->after_cb = fdsem_after;
     i->userdata = f;
@@ -663,7 +662,7 @@ pa_rtpoll_item *pa_rtpoll_item_new_fdsem(pa_rtpoll *p, pa_rtpoll_priority_t prio
 
 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 */
 
@@ -672,7 +671,7 @@ static int asyncmsgq_before(pa_rtpoll_item *i) {
 
 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);
 }
@@ -688,7 +687,7 @@ static int asyncmsgq_work(pa_rtpoll_item *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);
@@ -698,7 +697,7 @@ static int asyncmsgq_work(pa_rtpoll_item *i) {
         ret = pa_asyncmsgq_dispatch(object, code, data, offset, &chunk);
         pa_asyncmsgq_done(i->userdata, ret);
         return 1;
-    } 
+    }
 
     return 0;
 }
@@ -706,7 +705,7 @@ static int asyncmsgq_work(pa_rtpoll_item *i) {
 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);
 
@@ -715,7 +714,7 @@ pa_rtpoll_item *pa_rtpoll_item_new_asyncmsgq(pa_rtpoll *p, pa_rtpoll_priority_t
     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;

commit 33f2f497de3c1a99a05cc20172a7b03b38a084e1
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Sep 28 13:02:28 2007 +0000

    rework module-combine once again. We now run the data generation always in a seperate thread. This should help use to avoid all the awful race conditions we had in previously
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1916 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-combine.c b/src/modules/module-combine.c
index d9c2af6..447f41c 100644
--- a/src/modules/module-combine.c
+++ b/src/modules/module-combine.c
@@ -84,11 +84,12 @@ static const char* const valid_modargs[] = {
 
 struct output {
     struct userdata *userdata;
+
     pa_sink *sink;
     pa_sink_input *sink_input;
 
-    pa_asyncmsgq *inq,    /* Message queue from the master to this sink input */
-                 *outq;   /* Message queue from this sink input to the master */
+    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;
@@ -107,35 +108,33 @@ struct userdata {
     pa_thread_mq thread_mq;
     pa_rtpoll *rtpoll;
 
-    struct output *master;
-
     pa_time_event *time_event;
     uint32_t adjust_time;
 
-    int automatic;
+    pa_bool_t automatic;
     size_t block_size;
 
-    struct timespec timestamp;
-
     pa_hook_slot *sink_new_slot, *sink_unlink_slot, *sink_state_changed_slot;
 
     pa_resample_method_t resample_method;
 
     struct timespec adjust_timestamp;
 
+    struct output *master;
     pa_idxset* outputs; /* managed in main context */
 
     struct {
-        PA_LLIST_HEAD(struct output, outputs); /* managed in IO thread context */
-        struct output *master;
+        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 timespec timestamp;
+        pa_bool_t in_null_mode;
     } thread_info;
 };
 
 enum {
     SINK_MESSAGE_ADD_OUTPUT = PA_SINK_MESSAGE_MAX,
     SINK_MESSAGE_REMOVE_OUTPUT,
-    SINK_MESSAGE_NEED,
-    SINK_MESSAGE_SET_MASTER
+    SINK_MESSAGE_NEED
 };
 
 enum {
@@ -143,9 +142,9 @@ enum {
 };
 
 static void output_free(struct output *o);
-static int output_create_sink_input(struct userdata *u, struct output *o);
-static int update_master(struct userdata *u, struct output *o);
-static int pick_master(struct userdata *u, struct output *except);
+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;
@@ -159,22 +158,25 @@ static void adjust_rates(struct userdata *u) {
     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)) {
-        uint32_t sink_latency;
+        pa_usec_t sink_latency;
 
         if (!o->sink_input || !PA_SINK_OPENED(pa_sink_get_state(o->sink)))
             continue;
 
-        sink_latency = o->sink_input->sink ? pa_sink_get_latency(o->sink_input->sink) : 0;
+        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;
     }
 
@@ -184,7 +186,7 @@ static void adjust_rates(struct userdata *u) {
     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 is %s", u->sink->name, u->master->sink->description);
+    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;
 
@@ -195,9 +197,9 @@ static void adjust_rates(struct userdata *u) {
             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)) {
             pa_log_warn("[%s] sample rates too different, not adjusting (%u vs. %u).", o->sink_input->name, base_rate, r);
@@ -231,36 +233,46 @@ static void thread_func(void *userdata) {
 
     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->timestamp);
-
-    /* This is only run when we are in NULL mode, to make sure that
-     * playback doesn't stop. In all other cases we hook our stuff
-     * into the master sink. */
+    pa_rtclock_get(&u->thread_info.timestamp);
+    u->thread_info.in_null_mode = FALSE;
 
     for (;;) {
         int ret;
 
-        /* Render some data and drop it immediately */
-        if (u->sink->thread_info.state == PA_SINK_RUNNING) {
+        /* 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 timespec now;
 
             pa_rtclock_get(&now);
 
-            if (pa_timespec_cmp(&u->timestamp, &now) <= 0) {
+            if (!u->thread_info.in_null_mode || pa_timespec_cmp(&u->thread_info.timestamp, &now) <= 0) {
                 pa_sink_skip(u->sink, u->block_size);
-                pa_timespec_add(&u->timestamp, pa_bytes_to_usec(u->block_size, &u->sink->sample_spec));
+
+                if (!u->thread_info.in_null_mode)
+                    u->thread_info.timestamp = now;
+
+                pa_timespec_add(&u->thread_info.timestamp, pa_bytes_to_usec(u->block_size, &u->sink->sample_spec));
             }
 
-            pa_rtpoll_set_timer_absolute(u->rtpoll, &u->timestamp);
-        } else
+            pa_rtpoll_set_timer_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, 1)) < 0)
+        if ((ret = pa_rtpoll_run(u->rtpoll, TRUE)) < 0) {
+            pa_log_info("pa_rtpoll_run() = %i", ret);
             goto fail;
+        }
 
         if (ret == 0)
             goto finish;
@@ -281,12 +293,13 @@ static void render_memblock(struct userdata *u, struct output *o, size_t length)
     pa_assert(u);
     pa_assert(o);
 
-    if (!PA_SINK_OPENED(u->sink->thread_info.state))
-        return;
+    /* 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. */
 
-    /* We are run by the master output (u->master), possibly on behalf
-     * of another output (o). The other output is waiting for us,
-     * hence it is safe to access its mainblockq directly. */
+    /* If we are not running, we cannot produce any data */
+    if (!pa_atomic_load(&u->thread_info.running))
+        return;
 
     /* Maybe there's some data in the requesting output's queue
      * now? */
@@ -302,19 +315,16 @@ static void render_memblock(struct userdata *u, struct output *o, size_t length)
         pa_sink_render(u->sink, length, &chunk);
 
         /* OK, let's send this data to the other threads */
-        for (j = o->userdata->thread_info.outputs; j; j = j->next)
+        for (j = u->thread_info.active_outputs; j; j = j->next)
 
             /* Send to other outputs, which are not the requesting
-             * one, and not the master */
+             * one */
 
-            if (j != o && j != u->thread_info.master && j->sink_input)
+            if (j != o)
                 pa_asyncmsgq_post(j->inq, PA_MSGOBJECT(j->sink_input), SINK_INPUT_MESSAGE_POST, NULL, 0, &chunk, NULL);
 
-        /* Now push it into the master queue */
-        pa_memblockq_push_align(u->thread_info.master->memblockq, &chunk);
-
-        /* And into the requesting output's queue */
-        if (o != u->thread_info.master)
+        /* And place it directly into the requesting output's queue */
+        if (o)
             pa_memblockq_push_align(o->memblockq, &chunk);
 
         pa_memblock_unref(chunk.memblock);
@@ -337,16 +347,8 @@ static void request_memblock(struct output *o, size_t length) {
     if (pa_memblockq_is_readable(o->memblockq))
         return;
 
-    /* OK, we need to prepare new data */
-
-    if (o == o->userdata->thread_info.master)
-        /* OK, we're the master, so let's render some data */
-        render_memblock(o->userdata, o, length);
-
-    else
-        /* We're not the master, we need to ask the master to do the
-         * rendering for us */
-
+    /* 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);
 }
 
@@ -360,7 +362,7 @@ static int sink_input_peek_cb(pa_sink_input *i, size_t length, pa_memchunk *chun
     /* If necessary, get some new data */
     request_memblock(o, length);
 
-    return  pa_memblockq_peek(o->memblockq, chunk);
+    return pa_memblockq_peek(o->memblockq, chunk);
 }
 
 /* Called from I/O thread context */
@@ -374,49 +376,6 @@ static void sink_input_drop_cb(pa_sink_input *i, size_t length) {
     pa_memblockq_drop(o->memblockq, length);
 }
 
-/* Called from I/O thread context for the master */
-static void create_master_rtpolls(struct userdata *u) {
-    struct output *k;
-
-    pa_assert(u);
-
-    pa_assert(!u->master->outq_rtpoll_item);
-
-    /* Set up the queues from the outputs to the master */
-    for (k = u->thread_info.outputs; k; k = k->next) {
-
-        pa_assert(!k->outq_rtpoll_item);
-
-        if (k == u->master)
-            continue;
-
-        k->outq_rtpoll_item = pa_rtpoll_item_new_asyncmsgq(
-                u->master->sink->rtpoll,
-                PA_RTPOLL_EARLY+1,  /* This one has a slightly lower priority than the normal message handling */
-                k->outq);
-    }
-}
-
-/* Called from I/O thread context for the master */
-static void free_master_rtpolls(struct userdata *u) {
-    struct output *k;
-
-    pa_assert(!u->master->outq_rtpoll_item);
-
-    for (k = u->thread_info.outputs; k; k = k->next) {
-
-        if (k == u->master)
-            continue;
-
-        if (k->outq_rtpoll_item) {
-            pa_rtpoll_item_free(k->outq_rtpoll_item);
-            k->outq_rtpoll_item = NULL;
-        }
-
-        pa_assert(!k->outq_rtpoll_item);
-    }
-}
-
 /* Called from I/O thread context */
 static void sink_input_attach_cb(pa_sink_input *i) {
     struct output *o;
@@ -424,22 +383,11 @@ static void sink_input_attach_cb(pa_sink_input *i) {
     pa_sink_input_assert_ref(i);
     pa_assert_se(o = i->userdata);
 
-    if (o->userdata->thread_info.master == o) {
-        create_master_rtpolls(o->userdata);
-
-        /* Calling these two functions here is safe, because both
-         * threads that might access this sink are known to be
-         * waiting for us. */
-        pa_sink_set_asyncmsgq(o->userdata->sink, i->sink->asyncmsgq);
-        pa_sink_set_rtpoll(o->userdata->sink, i->sink->rtpoll);
-        pa_sink_attach_within_thread(o->userdata->sink);
-    }
-
-    /* Set up the queues from the inputs to the master */
+    /* 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_NORMAL,  /* This one has a lower priority than the normal message handling */
+            PA_RTPOLL_LATE,  /* This one is not that important, since we check for data in _peek() anyway. */
             o->inq);
 }
 
@@ -450,16 +398,10 @@ static void sink_input_detach_cb(pa_sink_input *i) {
     pa_sink_input_assert_ref(i);
     pa_assert_se(o = i->userdata);
 
-/*     pa_log("detaching %s", i->sink->name); */
-
+    /* 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;
-
-    if (o->userdata->thread_info.master == o) {
-        pa_sink_detach_within_thread(o->userdata->sink);
-        free_master_rtpolls(o->userdata);
-    }
 }
 
 /* Called from main context */
@@ -467,14 +409,10 @@ static void sink_input_kill_cb(pa_sink_input *i) {
     struct output *o;
 
     pa_sink_input_assert_ref(i);
-    o = i->userdata;
-    pa_assert(o);
-
-    pa_sink_input_unlink(o->sink_input);
-    pa_sink_input_unref(o->sink_input);
-    o->sink_input = NULL;
+    pa_assert(o = i->userdata);
 
     pa_module_unload_request(o->userdata->module);
+    output_free(o);
 }
 
 /* Called from thread context */
@@ -493,7 +431,7 @@ static int sink_input_process_msg(pa_msgobject *obj, int code, void *data, int64
             break;
         }
 
-        case SINK_INPUT_MESSAGE_POST: {
+        case SINK_INPUT_MESSAGE_POST:
 
             if (PA_SINK_OPENED(o->sink_input->sink->thread_info.state))
                 pa_memblockq_push_align(o->memblockq, chunk);
@@ -501,66 +439,78 @@ static int sink_input_process_msg(pa_msgobject *obj, int code, void *data, int64
                 pa_memblockq_flush(o->memblockq);
 
             break;
-        }
     }
 
     return pa_sink_input_process_msg(obj, code, data, offset, chunk);
 }
 
 /* Called from main context */
-static int suspend(struct userdata *u) {
+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;
+
+}
+
+/* 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);
 
-    if (update_master(u, NULL) < 0)
-        pa_module_unload_request(u->module);
-
-    for (o = pa_idxset_first(u->outputs, &idx); o; o = pa_idxset_next(u->outputs, &idx)) {
-
-        if (o->sink_input) {
-            pa_sink_input_unlink(o->sink_input);
-            pa_sink_input_unref(o->sink_input);
-            o->sink_input = NULL;
-        }
-    }
+    pick_master(u, NULL);
 
     pa_log_info("Device suspended...");
-
-    return 0;
 }
 
 /* Called from main context */
-static int unsuspend(struct userdata *u) {
+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, 0);
+        pa_sink_suspend(o->sink, FALSE);
 
-        if (PA_SINK_OPENED(pa_sink_get_state(o->sink))) {
-            if (output_create_sink_input(u, o) < 0)
-                output_free(o);
-        }
+        if (PA_SINK_OPENED(pa_sink_get_state(o->sink)))
+            enable_output(o);
     }
 
-    if (pick_master(u, NULL) < 0)
-        pa_module_unload_request(u->module);
-
-    for (o = pa_idxset_first(u->outputs, &idx); o; o = pa_idxset_next(u->outputs, &idx))
-        if (o->sink_input && pa_sink_get_state(o->sink_input) == PA_SINK_INPUT_INIT)
-             pa_sink_input_put(o->sink_input);
+    pick_master(u, NULL);
 
     pa_log_info("Resumed successfully...");
-    return 0;
 }
 
 /* Called from main context */
@@ -577,18 +527,14 @@ static int sink_set_state(pa_sink *sink, pa_sink_state_t state) {
         case PA_SINK_SUSPENDED:
             pa_assert(PA_SINK_OPENED(pa_sink_get_state(u->sink)));
 
-            if (suspend(u) < 0)
-                return -1;
-
+            suspend(u);
             break;
 
         case PA_SINK_IDLE:
         case PA_SINK_RUNNING:
 
-            if (pa_sink_get_state(u->sink) == PA_SINK_SUSPENDED) {
-                if (unsuspend(u) < 0)
-                    return -1;
-            }
+            if (pa_sink_get_state(u->sink) == PA_SINK_SUSPENDED)
+                unsuspend(u);
 
             break;
 
@@ -607,67 +553,41 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
     switch (code) {
 
         case PA_SINK_MESSAGE_SET_STATE:
-
-            if ((pa_sink_state_t) PA_PTR_TO_UINT(data) == PA_SINK_RUNNING) {
-                /* Only useful when running in NULL mode, i.e. when no
-                 * master sink is attached */
-                pa_rtclock_get(&u->timestamp);
-            }
-
+            pa_atomic_store(&u->thread_info.running, PA_PTR_TO_UINT(data) == PA_SINK_RUNNING);
             break;
 
-        case PA_SINK_MESSAGE_GET_LATENCY: {
-            struct timespec now;
+        case PA_SINK_MESSAGE_GET_LATENCY:
 
             /* This code will only be called when running in NULL
-             * mode, i.e. when no master sink is attached. See
+             * mode, i.e. when no output is attached. See
              * sink_get_latency_cb() below */
-            pa_rtclock_get(&now);
 
-            if (pa_timespec_cmp(&u->timestamp, &now) > 0)
-                *((pa_usec_t*) data) = 0;
-            else
-                *((pa_usec_t*) data) = pa_timespec_diff(&u->timestamp, &now);
-            break;
-        }
-
-        case SINK_MESSAGE_SET_MASTER:
-
-            if (u->thread_info.master && data != u->thread_info.master) {
-
-                if (u->thread_info.master->sink_input->thread_info.attached)
-                    free_master_rtpolls(u);
+            if (u->thread_info.in_null_mode) {
+                struct timespec now;
 
+                if (pa_timespec_cmp(&u->thread_info.timestamp, pa_rtclock_get(&now)) > 0) {
+                    *((pa_usec_t*) data) = pa_timespec_diff(&u->thread_info.timestamp, &now);
+                    break;
+                }
             }
 
-            if ((u->thread_info.master = data)) {
-
-                /* There's now a master, and we're being executed in
-                 * its thread, let's register the asyncmsgqs from other
-                 * outputs to us */
-
-                if (u->thread_info.master->sink_input->thread_info.attached)
-                    create_master_rtpolls(u);
+            *((pa_usec_t*) data) = 0;
 
-            }
-
-            return 0;
+            break;
 
         case SINK_MESSAGE_ADD_OUTPUT: {
             struct output *op = data;
 
-            PA_LLIST_PREPEND(struct output, u->thread_info.outputs, op);
+            PA_LLIST_PREPEND(struct output, u->thread_info.active_outputs, op);
 
             pa_assert(!op->outq_rtpoll_item);
 
-            if (op != u->thread_info.master) {
-                /* Create pa_asyncmsgq to master */
+            /* Create pa_asyncmsgq to the sink thread */
 
-                op->outq_rtpoll_item = pa_rtpoll_item_new_asyncmsgq(
-                        u->thread_info.master->sink->rtpoll,
-                        PA_RTPOLL_EARLY+1,  /* This one has a slightly lower priority than the normal message handling */
-                        op->outq);
-            }
+            op->outq_rtpoll_item = pa_rtpoll_item_new_asyncmsgq(
+                    u->rtpoll,
+                    PA_RTPOLL_EARLY-1,  /* This item is very important */
+                    op->outq);
 
             return 0;
         }
@@ -675,14 +595,13 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
         case SINK_MESSAGE_REMOVE_OUTPUT: {
             struct output *op = data;
 
-            PA_LLIST_REMOVE(struct output, u->thread_info.outputs, op);
+            PA_LLIST_REMOVE(struct output, u->thread_info.active_outputs, op);
 
-            /* Remove the q that leads from this output to the master output */
+            /* Remove the q that leads from this output to the sink thread */
 
-            if (op->outq_rtpoll_item) {
-                pa_rtpoll_item_free(op->outq_rtpoll_item);
-                op->outq_rtpoll_item = NULL;
-            }
+            pa_assert(op->outq_rtpoll_item);
+            pa_rtpoll_item_free(op->outq_rtpoll_item);
+            op->outq_rtpoll_item = NULL;
 
             return 0;
         }
@@ -700,8 +619,7 @@ static pa_usec_t sink_get_latency_cb(pa_sink *s) {
     struct userdata *u;
 
     pa_sink_assert_ref(s);
-    u = s->userdata;
-    pa_assert(u);
+    pa_assert_se(u = s->userdata);
 
     if (u->master) {
         /* If we have a master sink, we just return the latency of it
@@ -712,10 +630,10 @@ static pa_usec_t sink_get_latency_cb(pa_sink *s) {
 
         return
             pa_sink_input_get_latency(u->master->sink_input) +
-            pa_sink_get_latency(u->master->sink_input->sink);
+            pa_sink_get_latency(u->master->sink);
 
     } else {
-        pa_usec_t usec;
+        pa_usec_t usec = 0;
 
         /* We have no master, hence let's ask our own thread which
          * implements the NULL sink */
@@ -759,94 +677,50 @@ static void update_description(struct userdata *u) {
     pa_xfree(t);
 }
 
-static int update_master(struct userdata *u, struct output *o) {
+static void update_master(struct userdata *u, struct output *o) {
     pa_assert(u);
 
-    /* Make sure everything is detached from the old thread before we move our stuff to a new thread */
-    if (u->sink && PA_SINK_LINKED(pa_sink_get_state(u->sink))) {
-        pa_sink_detach(u->sink);
-        pa_asyncmsgq_send(u->sink->asyncmsgq, PA_MSGOBJECT(u->sink), SINK_MESSAGE_SET_MASTER, NULL, 0, NULL);
-    } else
-        u->thread_info.master = NULL;
-
-    if (o) {
-        /* If we have a master sink we run our own sink in its thread */
-
-        pa_assert(o->sink_input);
-        pa_assert(PA_SINK_OPENED(pa_sink_get_state(o->sink)));
-
-        if (u->thread) {
-            /* If we previously were in NULL mode, let's kill the thread */
-            pa_asyncmsgq_send(u->thread_mq.inq, NULL, PA_MESSAGE_SHUTDOWN, NULL, 0, NULL);
-            pa_thread_free(u->thread);
-            u->thread = NULL;
-
-            pa_assert(u->rtpoll);
-            pa_rtpoll_free(u->rtpoll);
-            u->rtpoll = NULL;
-        }
-
-        pa_sink_set_asyncmsgq(u->sink, o->sink->asyncmsgq);
-        pa_sink_set_rtpoll(u->sink, o->sink->rtpoll);
-        u->master = o;
+    if (u->master == o)
+        return;
 
+    if ((u->master = o))
         pa_log_info("Master sink is now '%s'", o->sink_input->sink->name);
-
-    } else {
-
-        /* We have no master sink, let's create our own thread */
-
-        pa_sink_set_asyncmsgq(u->sink, u->thread_mq.inq);
-        u->master = NULL;
-
-        if (!u->thread) {
-            pa_assert(!u->rtpoll);
-
-            u->rtpoll = pa_rtpoll_new();
-            pa_rtpoll_item_new_asyncmsgq(u->rtpoll, PA_RTPOLL_EARLY, u->thread_mq.inq);
-
-            pa_sink_set_rtpoll(u->sink, u->rtpoll);
-
-            if (!(u->thread = pa_thread_new(thread_func, u))) {
-                pa_log("Failed to create thread.");
-                return -1;
-            }
-        }
-
-        pa_log_info("No suitable master sink found, going to NULL mode\n");
-    }
-
-    /* Now attach everything again */
-    if (u->sink && PA_SINK_LINKED(pa_sink_get_state(u->sink))) {
-        pa_asyncmsgq_send(u->sink->asyncmsgq, PA_MSGOBJECT(u->sink), SINK_MESSAGE_SET_MASTER, u->master, 0, NULL);
-        pa_sink_attach(u->sink);
-    } else
-        u->thread_info.master = u->master;
-
-    return 0;
+    else
+        pa_log_info("No master selected, lacking suitable outputs.");
 }
 
-static int pick_master(struct userdata *u, struct output *except) {
+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)))
-        return update_master(u, u->master);
+    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;
+    }
 
     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)))
-            return update_master(u, o);
+        if (o != except &&
+            o->sink_input &&
+            PA_SINK_OPENED(pa_sink_get_state(o->sink))) {
+            update_master(u, o);
+            return;
+        }
 
-    return update_master(u, NULL);
+    update_master(u, NULL);
 }
 
-static int output_create_sink_input(struct userdata *u, struct output *o) {
+static int output_create_sink_input(struct output *o) {
     pa_sink_input_new_data data;
     char *t;
 
-    pa_assert(u);
-    pa_assert(!o->sink_input);
+    pa_assert(o);
+
+    if (o->sink_input)
+        return 0;
 
     t = pa_sprintf_malloc("Simultaneous output on %s", o->sink->description);
 
@@ -854,12 +728,12 @@ static int output_create_sink_input(struct userdata *u, struct output *o) {
     data.sink = o->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;
-    data.resample_method = u->resample_method;
+    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(u->core, &data, PA_SINK_INPUT_VARIABLE_RATE|PA_SINK_INPUT_DONT_MOVE);
+    o->sink_input = pa_sink_input_new(o->userdata->core, &data, PA_SINK_INPUT_VARIABLE_RATE|PA_SINK_INPUT_DONT_MOVE);
 
     pa_xfree(t);
 
@@ -874,6 +748,7 @@ static int output_create_sink_input(struct userdata *u, struct output *o) {
     o->sink_input->kill = sink_input_kill_cb;
     o->sink_input->userdata = o;
 
+
     return 0;
 }
 
@@ -901,29 +776,38 @@ static struct output *output_new(struct userdata *u, pa_sink *sink) {
             0,
             NULL);
 
-
     pa_assert_se(pa_idxset_put(u->outputs, o, NULL) == 0);
 
-    update_description(u);
-
     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
-        PA_LLIST_PREPEND(struct output, u->thread_info.outputs, o);
+    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);
+
+        o->outq_rtpoll_item = pa_rtpoll_item_new_asyncmsgq(
+                u->rtpoll,
+                PA_RTPOLL_EARLY-1,  /* This item is very important */
+                o->outq);
+    }
 
     if (PA_SINK_OPENED(pa_sink_get_state(u->sink)) || pa_sink_get_state(u->sink) == PA_SINK_INIT) {
-        pa_sink_suspend(sink, 0);
+        pa_sink_suspend(sink, FALSE);
 
         if (PA_SINK_OPENED(pa_sink_get_state(sink)))
-            if (output_create_sink_input(u, o) < 0)
+            if (output_create_sink_input(o) < 0)
                 goto fail;
     }
 
+
+    update_description(u);
+
     return o;
 
 fail:
 
     if (o) {
+        pa_idxset_remove_by_data(u->outputs, o, NULL);
+
         if (o->sink_input) {
             pa_sink_input_unlink(o->sink_input);
             pa_sink_input_unref(o->sink_input);
@@ -962,12 +846,11 @@ static pa_hook_result_t sink_new_hook_cb(pa_core *c, pa_sink *s, struct userdata
         return PA_HOOK_OK;
     }
 
-    if (pick_master(u, NULL) < 0)
-        pa_module_unload_request(u->module);
-
     if (o->sink_input)
         pa_sink_input_put(o->sink_input);
 
+    pick_master(u, NULL);
+
     return PA_HOOK_OK;
 }
 
@@ -1014,24 +897,13 @@ static pa_hook_result_t sink_state_changed_hook_cb(pa_core *c, pa_sink *s, struc
     state = pa_sink_get_state(s);
 
     if (PA_SINK_OPENED(state) && PA_SINK_OPENED(pa_sink_get_state(u->sink)) && !o->sink_input) {
-        output_create_sink_input(u, o);
-
-        if (pick_master(u, NULL) < 0)
-            pa_module_unload_request(u->module);
-
-        if (o->sink_input)
-            pa_sink_input_put(o->sink_input);
+        enable_output(o);
+        pick_master(u, NULL);
     }
 
     if (state == PA_SINK_SUSPENDED && o->sink_input) {
-        pa_sink_input_unlink(o->sink_input);
-        pa_sink_input_unref(o->sink_input);
-        o->sink_input = NULL;
-
-        pa_memblockq_flush(o->memblockq);
-
-        if (pick_master(u, o) < 0)
-            pa_module_unload_request(u->module);
+        disable_output(o);
+        pick_master(u, o);
     }
 
     return PA_HOOK_OK;
@@ -1067,16 +939,20 @@ int pa__init(pa_module*m) {
     u->module = m;
     m->userdata = u;
     u->sink = NULL;
-    u->thread_info.master = u->master = NULL;
+    u->master = NULL;
     u->time_event = NULL;
     u->adjust_time = DEFAULT_ADJUST_TIME;
     pa_thread_mq_init(&u->thread_mq, m->core->mainloop);
-    u->rtpoll = NULL;
+    u->rtpoll = pa_rtpoll_new();
     u->thread = NULL;
-    PA_LLIST_HEAD_INIT(struct output, u->thread_info.outputs);
     u->resample_method = resample_method;
     u->outputs = pa_idxset_new(NULL, NULL);
     pa_timespec_reset(&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");
@@ -1097,11 +973,11 @@ int pa__init(pa_module*m) {
         }
 
         ss = master_sink->sample_spec;
-        u->automatic = 0;
+        u->automatic = FALSE;
     } else {
         master_sink = NULL;
         ss = m->core->default_sample_spec;
-        u->automatic = 1;
+        u->automatic = TRUE;
     }
 
     if ((pa_modargs_get_sample_spec(ma, &ss) < 0)) {
@@ -1137,6 +1013,8 @@ int pa__init(pa_module*m) {
     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)
@@ -1200,8 +1078,12 @@ int pa__init(pa_module*m) {
     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);
 
-    if (pick_master(u, NULL) < 0)
+    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);
@@ -1234,22 +1116,12 @@ fail:
 static void output_free(struct output *o) {
     pa_assert(o);
 
-    /* Make sure the master points to a different output */
-    if (pick_master(o->userdata, o) < 0)
-        pa_module_unload_request(o->userdata->module);
+    pick_master(o->userdata, o);
 
-    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_REMOVE_OUTPUT, o, 0, NULL);
-    else
-        PA_LLIST_REMOVE(struct output, o->userdata->thread_info.outputs, o);
+    disable_output(o);
 
     pa_assert_se(pa_idxset_remove_by_data(o->userdata->outputs, o, NULL));
 
-    if (o->sink_input) {
-        pa_sink_input_unlink(o->sink_input);
-        pa_sink_input_unref(o->sink_input);
-    }
-
     update_description(o->userdata);
 
     if (o->inq_rtpoll_item)
@@ -1288,9 +1160,6 @@ void pa__done(pa_module*m) {
     if (u->sink_state_changed_slot)
         pa_hook_slot_free(u->sink_state_changed_slot);
 
-    if (u->sink)
-        pa_sink_unlink(u->sink);
-
     if (u->outputs) {
         while ((o = pa_idxset_first(u->outputs, NULL)))
             output_free(o);
@@ -1298,6 +1167,9 @@ void pa__done(pa_module*m) {
         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);

commit 67b899acc915a3d01623a7d517f81eab7231d11d
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Sep 28 13:15:11 2007 +0000

    treat timer_enabled like a real, grown-up boolean variable
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1917 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/rtpoll.c b/src/pulsecore/rtpoll.c
index 921619d..de0ffa4 100644
--- a/src/pulsecore/rtpoll.c
+++ b/src/pulsecore/rtpoll.c
@@ -374,13 +374,13 @@ int pa_rtpoll_run(pa_rtpoll *p, pa_bool_t wait) {
 #ifdef __linux__
     if (!p->dont_use_ppoll)
 #endif
-        r = ppoll(p->pollfd, p->n_pollfd_used, p->timer_enabled > 0  ? &timeout : NULL, p->rtsig < 0 ? NULL : &p->sigset_unblocked);
+        r = ppoll(p->pollfd, p->n_pollfd_used, p->timer_enabled ? &timeout : NULL, p->rtsig < 0 ? NULL : &p->sigset_unblocked);
 #ifdef __linux__
     else
 #endif
 
 #endif
-        r = poll(p->pollfd, p->n_pollfd_used, p->timer_enabled > 0 ? (timeout.tv_sec*1000) + (timeout.tv_nsec / 1000000) : -1);
+        r = poll(p->pollfd, p->n_pollfd_used, p->timer_enabled ? (timeout.tv_sec*1000) + (timeout.tv_nsec / 1000000) : -1);
 
     if (r < 0) {
         if (errno == EAGAIN || errno == EINTR)
@@ -403,7 +403,7 @@ int pa_rtpoll_run(pa_rtpoll *p, pa_bool_t wait) {
                 pa_timespec_add(&p->next_elapse, (pa_timespec_diff(&now, &p->next_elapse) / p->period + 1) * p->period);
 
         } else
-            p->timer_enabled = 0;
+            p->timer_enabled = FALSE;
     }
 
     /* Let's tell everyone that we left the sleep */

commit bdf97468f34407674d191f216febb1987adb16f6
Author: Pierre Ossman <ossman at cendio.se>
Date:   Fri Sep 28 14:01:25 2007 +0000

    Update module-solaris to new structure.
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1918 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/Makefile.am b/src/Makefile.am
index a92a557..e1d210b 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1005,10 +1005,10 @@ modlibexec_LTLIBRARIES += \
 		module-alsa-source.la
 endif
 
-#if HAVE_SOLARIS
-#modlibexec_LTLIBRARIES += \
-#		module-solaris.la
-#endif
+if HAVE_SOLARIS
+modlibexec_LTLIBRARIES += \
+		module-solaris.la
+endif
 
 if HAVE_AVAHI
 modlibexec_LTLIBRARIES += \
@@ -1285,9 +1285,9 @@ module_alsa_source_la_CFLAGS = $(AM_CFLAGS) $(ASOUNDLIB_CFLAGS)
 
 # Solaris
 
-#module_solaris_la_SOURCES = modules/module-solaris.c
-#module_solaris_la_LDFLAGS = -module -avoid-version
-#module_solaris_la_LIBADD = $(AM_LIBADD) libiochannel.la
+module_solaris_la_SOURCES = modules/module-solaris.c
+module_solaris_la_LDFLAGS = -module -avoid-version
+module_solaris_la_LIBADD = $(AM_LIBADD) libiochannel.la
 
 # Avahi
 
diff --git a/src/modules/module-solaris.c b/src/modules/module-solaris.c
index c8ff770..a8a9471 100644
--- a/src/modules/module-solaris.c
+++ b/src/modules/module-solaris.c
@@ -4,7 +4,7 @@
   This file is part of PulseAudio.
 
   Copyright 2006 Lennart Poettering
-  Copyright 2006 Pierre Ossman <ossman at cendio.se> for Cendio AB
+  Copyright 2006-2007 Pierre Ossman <ossman at 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,52 +609,15 @@ 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 = PA_PAGE_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);
 }

commit dbcd086332a654db9913638719073a899b07db81
Author: Tanu Kaskinen <tanuk at iki.fi>
Date:   Sun Sep 30 13:19:26 2007 +0000

    Fixed PA_GCC_CONST definition.
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1919 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/gccmacro.h b/src/pulsecore/gccmacro.h
index d211c2e..e9f0d09 100644
--- a/src/pulsecore/gccmacro.h
+++ b/src/pulsecore/gccmacro.h
@@ -70,9 +70,9 @@
 
 #ifndef PA_GCC_CONST
 #ifdef __GNUCC__
-#define PA_GCC_CONST __attribute__ ((pure))
+#define PA_GCC_CONST __attribute__ ((const))
 #else
-/** This function's return value depends only the arguments list (stricter version of PA_GCC_CONST) **/
+/** This function's return value depends only the arguments list (stricter version of PA_GCC_PURE) **/
 #define PA_GCC_CONST
 #endif
 #endif

commit abd692e1ba07df525e9ef23ea1aff3ccff404ca3
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Oct 1 00:16:24 2007 +0000

    fix silence initializer for alaw and ulaw
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1920 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/sample-util.c b/src/pulsecore/sample-util.c
index bc83ac6..fee22c7 100644
--- a/src/pulsecore/sample-util.c
+++ b/src/pulsecore/sample-util.c
@@ -104,9 +104,11 @@ void pa_silence_memory(void *p, size_t length, const pa_sample_spec *spec) {
             c = 0;
             break;
         case PA_SAMPLE_ALAW:
-        case PA_SAMPLE_ULAW:
-            c = 80;
+            c = 0xd5;
             break;
+        case PA_SAMPLE_ULAW:
+            c = 0xff;
+            breaK;
         default:
             pa_assert_not_reached();
     }

commit 9d34a1e18b33330717caca6c25345ccb061cd7ea
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Oct 1 00:44:29 2007 +0000

    fix trivial typo
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1921 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/sample-util.c b/src/pulsecore/sample-util.c
index fee22c7..56d89c8 100644
--- a/src/pulsecore/sample-util.c
+++ b/src/pulsecore/sample-util.c
@@ -108,7 +108,7 @@ void pa_silence_memory(void *p, size_t length, const pa_sample_spec *spec) {
             break;
         case PA_SAMPLE_ULAW:
             c = 0xff;
-            breaK;
+            break;
         default:
             pa_assert_not_reached();
     }

commit d6a22032078bcb260eb2e0dd2ca36235c5251115
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Oct 1 16:39:04 2007 +0000

    Fix race condition between IO thread creation and pa_sink_put(). Move activation of rtpoll fds when we change the state INIT->IDLE.
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1922 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-alsa-sink.c b/src/modules/module-alsa-sink.c
index 0489fa8..bb78bca 100644
--- a/src/modules/module-alsa-sink.c
+++ b/src/modules/module-alsa-sink.c
@@ -450,6 +450,11 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
                 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;
@@ -604,9 +609,6 @@ static void thread_func(void *userdata) {
     pa_thread_mq_install(&u->thread_mq);
     pa_rtpoll_install(u->rtpoll);
 
-    if (build_pollfd(u) < 0)
-        goto fail;
-
     for (;;) {
         int ret;
 
diff --git a/src/modules/module-alsa-source.c b/src/modules/module-alsa-source.c
index de019ff..0f19a4a 100644
--- a/src/modules/module-alsa-source.c
+++ b/src/modules/module-alsa-source.c
@@ -437,6 +437,13 @@ static int source_process_msg(pa_msgobject *o, int code, void *data, int64_t off
                 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;
@@ -591,11 +598,6 @@ static void thread_func(void *userdata) {
     pa_thread_mq_install(&u->thread_mq);
     pa_rtpoll_install(u->rtpoll);
 
-    if (build_pollfd(u) < 0)
-        goto fail;
-
-    snd_pcm_start(u->pcm_handle);
-
     for (;;) {
         int ret;
 
diff --git a/src/modules/module-ladspa-sink.c b/src/modules/module-ladspa-sink.c
index 9f771c6..29ca89f 100644
--- a/src/modules/module-ladspa-sink.c
+++ b/src/modules/module-ladspa-sink.c
@@ -114,7 +114,7 @@ static int sink_set_state(pa_sink *s, pa_sink_state_t state) {
     pa_sink_assert_ref(s);
     pa_assert_se(u = s->userdata);
 
-    if (PA_SINK_LINKED(state) && u->sink_input)
+    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;
diff --git a/src/modules/module-oss.c b/src/modules/module-oss.c
index 82b5b6c..cb975fd 100644
--- a/src/modules/module-oss.c
+++ b/src/modules/module-oss.c
@@ -110,10 +110,10 @@ struct userdata {
 
     size_t frame_size;
     uint32_t in_fragment_size, out_fragment_size, in_nfrags, out_nfrags, in_hwbuf_size, out_hwbuf_size;
-    int use_getospace, use_getispace;
-    int use_getodelay;
+    pa_bool_t use_getospace, use_getispace;
+    pa_bool_t use_getodelay;
 
-    int sink_suspended, source_suspended;
+    pa_bool_t sink_suspended, source_suspended;
 
     int fd;
     int mode;
@@ -123,7 +123,7 @@ struct userdata {
 
     int nfrags, frag_size;
 
-    int use_mmap;
+    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;
@@ -149,7 +149,7 @@ static const char* const valid_modargs[] = {
     NULL
 };
 
-static void trigger(struct userdata *u, int quick) {
+static void trigger(struct userdata *u, pa_bool_t quick) {
     int enable_bits = 0, zero = 0;
 
     pa_assert(u);
@@ -157,7 +157,7 @@ static void trigger(struct userdata *u, int quick) {
     if (u->fd < 0)
         return;
 
-/*     pa_log_debug("trigger");  */
+     pa_log_debug("trigger");
 
     if (u->source && PA_SOURCE_OPENED(u->source->thread_info.state))
         enable_bits |= PCM_ENABLE_INPUT;
@@ -165,6 +165,9 @@ static void trigger(struct userdata *u, int quick) {
     if (u->sink && PA_SINK_OPENED(u->sink->thread_info.state))
         enable_bits |= PCM_ENABLE_OUTPUT;
 
+    pa_log_debug("trigger: %i", enable_bits);
+
+
     if (u->use_mmap) {
 
         if (!quick)
@@ -327,6 +330,8 @@ static int mmap_read(struct userdata *u) {
         return -1;
     }
 
+/*     pa_log("... %i", info.blocks); */
+
     info.blocks += u->in_mmap_saved_nfrags;
     u->in_mmap_saved_nfrags = 0;
 
@@ -438,6 +443,22 @@ static pa_usec_t io_source_get_latency(struct userdata *u) {
     return r;
 }
 
+static void build_pollfd(struct userdata *u) {
+    struct pollfd *pollfd;
+
+    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 suspend(struct userdata *u) {
     pa_assert(u);
     pa_assert(u->fd >= 0);
@@ -493,7 +514,6 @@ static int unsuspend(struct userdata *u) {
     int frag_size, in_frag_size, out_frag_size;
     int in_nfrags, out_nfrags;
     struct audio_buf_info info;
-    struct pollfd *pollfd;
 
     pa_assert(u);
     pa_assert(u->fd < 0);
@@ -575,11 +595,7 @@ static int unsuspend(struct userdata *u) {
 
     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 = 0;
-    pollfd->revents = 0;
+    build_pollfd(u);
 
     if (u->sink)
         pa_sink_get_volume(u->sink);
@@ -598,7 +614,8 @@ fail:
 
 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 do_trigger = 0, ret, quick = 1;
+    int ret;
+    pa_bool_t do_trigger = FALSE, quick = TRUE;
 
     switch (code) {
 
@@ -629,28 +646,33 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
                             return -1;
                     }
 
-                    do_trigger = 1;
+                    do_trigger = TRUE;
 
-                    u->sink_suspended = 1;
+                    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 = 0;
+                            quick = FALSE;
                         }
 
-                        do_trigger = 1;
+                        do_trigger = TRUE;
 
                         u->out_mmap_current = 0;
                         u->out_mmap_saved_nfrags = 0;
 
-                        u->sink_suspended = 0;
+                        u->sink_suspended = FALSE;
                     }
 
                     break;
@@ -674,7 +696,8 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
 
 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 do_trigger = 0, ret, quick = 1;
+    int ret;
+    int do_trigger = FALSE, quick = TRUE;
 
     switch (code) {
 
@@ -703,28 +726,33 @@ static int source_process_msg(pa_msgobject *o, int code, void *data, int64_t off
                             return -1;
                     }
 
-                    do_trigger = 1;
+                    do_trigger = TRUE;
 
-                    u->source_suspended = 1;
+                    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 = 0;
+                            quick = FALSE;
                         }
 
-                        do_trigger = 1;
+                        do_trigger = TRUE;
 
                         u->in_mmap_current = 0;
                         u->in_mmap_saved_nfrags = 0;
 
-                        u->source_suspended = 0;
+                        u->source_suspended = FALSE;
                     }
                     break;
 
@@ -840,8 +868,6 @@ static void thread_func(void *userdata) {
     pa_thread_mq_install(&u->thread_mq);
     pa_rtpoll_install(u->rtpoll);
 
-    trigger(u, 0);
-
     for (;;) {
         int ret;
 
@@ -849,7 +875,7 @@ static void thread_func(void *userdata) {
 
         /* Render some data and write it to the dsp */
 
-        if (u->sink && PA_SINK_OPENED(u->sink->thread_info.state) && (revents & POLLOUT)) {
+        if (u->sink && PA_SINK_OPENED(u->sink->thread_info.state) && ((revents & POLLOUT) || u->use_mmap || u->use_getospace)) {
 
             if (u->use_mmap) {
 
@@ -863,7 +889,7 @@ static void thread_func(void *userdata) {
 
             } else {
                 ssize_t l;
-                int loop = 0;
+                pa_bool_t loop = FALSE, work_done = FALSE;
 
                 l = u->out_fragment_size;
 
@@ -872,21 +898,35 @@ static void thread_func(void *userdata) {
 
                     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;
+                        u->use_getospace = FALSE;
                     } else {
-                        if (info.bytes >= l) {
-                            l = (info.bytes/l)*l;
-                            loop = 1;
-                        }
+                        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;
                     }
                 }
 
-                do {
+                /* 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;
 
-                    pa_assert(l > 0);
-
                     if (u->memchunk.length <= 0)
                         pa_sink_render(u->sink, l, &u->memchunk);
 
@@ -929,17 +969,21 @@ static void thread_func(void *userdata) {
                         l -= t;
 
                         revents &= ~POLLOUT;
+                        work_done = TRUE;
                     }
 
-                } while (loop && l > 0);
+                    if (!loop)
+                        break;
+                }
 
-                continue;
+                if (work_done)
+                    continue;
             }
         }
 
-        /* Try to read some data and pass it on to the source driver */
+        /* 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))) {
+        if (u->source && PA_SOURCE_OPENED(u->source->thread_info.state) && ((revents & POLLIN) || u->use_mmap || u->use_getispace)) {
 
             if (u->use_mmap) {
 
@@ -956,7 +1000,7 @@ static void thread_func(void *userdata) {
                 void *p;
                 ssize_t l;
                 pa_memchunk memchunk;
-                int loop = 0;
+                pa_bool_t loop = FALSE, work_done = FALSE;
 
                 l = u->in_fragment_size;
 
@@ -965,16 +1009,21 @@ static void thread_func(void *userdata) {
 
                     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;
+                        u->use_getispace = FALSE;
                     } else {
-                        if (info.bytes >= l) {
-                            l = (info.bytes/l)*l;
-                            loop = 1;
-                        }
+                        l = info.bytes;
+                        loop = TRUE;
                     }
                 }
 
-                do {
+                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);
@@ -1023,18 +1072,25 @@ static void thread_func(void *userdata) {
                         l -= t;
 
                         revents &= ~POLLIN;
+                        work_done = TRUE;
                     }
-                } while (loop && l > 0);
 
-                continue;
+                    if (!loop)
+                        break;
+                }
+
+                if (work_done)
+                    continue;
             }
         }
 
-/*         pa_log("loop2"); */
+/*         pa_log("loop2 revents=%i", revents); */
 
-        if (u->fd >= 0) {
+        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) |
@@ -1042,13 +1098,13 @@ static void thread_func(void *userdata) {
         }
 
         /* Hmm, nothing to do. Let's sleep */
-        if ((ret = pa_rtpoll_run(u->rtpoll, 1)) < 0)
+        if ((ret = pa_rtpoll_run(u->rtpoll, TRUE)) < 0)
             goto fail;
 
         if (ret == 0)
             goto finish;
 
-        if (u->fd >= 0) {
+        if (u->rtpoll_item) {
             struct pollfd *pollfd;
 
             pollfd = pa_rtpoll_item_get_pollfd(u->rtpoll_item, NULL);
@@ -1088,7 +1144,6 @@ int pa__init(pa_module*m) {
     char hwdesc[64], *t;
     const char *name;
     int namereg_fail;
-    struct pollfd *pollfd;
 
     pa_assert(m);
 
@@ -1180,11 +1235,8 @@ int pa__init(pa_module*m) {
     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 = 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->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);
@@ -1244,7 +1296,7 @@ int pa__init(pa_module*m) {
                                           use_mmap ? " via DMA" : ""));
         pa_xfree(t);
         u->source->flags = PA_SOURCE_HARDWARE|PA_SOURCE_LATENCY;
-        u->source->refresh_volume = 1;
+        u->source->refresh_volume = TRUE;
 
         if (use_mmap)
             u->in_mmap_memblocks = pa_xnew0(pa_memblock*, u->in_nfrags);
@@ -1261,7 +1313,7 @@ int pa__init(pa_module*m) {
                     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 = 0;
+                    u->use_mmap = (use_mmap = FALSE);
                     u->out_mmap = NULL;
                 }
             } else {
@@ -1299,7 +1351,7 @@ int pa__init(pa_module*m) {
                                         use_mmap ? " via DMA" : ""));
         pa_xfree(t);
         u->sink->flags = PA_SINK_HARDWARE|PA_SINK_LATENCY;
-        u->sink->refresh_volume = 1;
+        u->sink->refresh_volume = TRUE;
 
         if (use_mmap)
             u->out_mmap_memblocks = pa_xnew0(pa_memblock*, u->out_nfrags);
diff --git a/src/modules/module-remap-sink.c b/src/modules/module-remap-sink.c
index d712a04..e863c0c 100644
--- a/src/modules/module-remap-sink.c
+++ b/src/modules/module-remap-sink.c
@@ -100,7 +100,7 @@ static int sink_set_state(pa_sink *s, pa_sink_state_t state) {
     pa_sink_assert_ref(s);
     pa_assert_se(u = s->userdata);
 
-    if (PA_SINK_LINKED(state) && u->sink_input)
+    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;
diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c
index 38e7d63..dccb34c 100644
--- a/src/pulsecore/sink.c
+++ b/src/pulsecore/sink.c
@@ -147,21 +147,6 @@ pa_sink* pa_sink_new(
     return s;
 }
 
-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);
-
-    s->thread_info.state = s->state = PA_SINK_IDLE;
-
-    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);
-}
-
 static int sink_set_state(pa_sink *s, pa_sink_state_t state) {
     int ret;
 
@@ -196,6 +181,21 @@ static int sink_set_state(pa_sink *s, pa_sink_state_t state) {
     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;
@@ -806,7 +806,7 @@ unsigned pa_sink_used_by(pa_sink *s) {
 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(PA_SINK_LINKED(s->thread_info.state));
+    pa_assert(s->thread_info.state != PA_SINK_UNLINKED);
 
     switch ((pa_sink_message_t) code) {
 
diff --git a/src/pulsecore/source.c b/src/pulsecore/source.c
index 2106edc..9a6902a 100644
--- a/src/pulsecore/source.c
+++ b/src/pulsecore/source.c
@@ -124,19 +124,6 @@ pa_source* pa_source_new(
     return s;
 }
 
-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);
-
-    s->thread_info.state = s->state = PA_SOURCE_IDLE;
-
-    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);
-}
-
 static int source_set_state(pa_source *s, pa_source_state_t state) {
     int ret;
 
@@ -171,6 +158,19 @@ static int source_set_state(pa_source *s, pa_source_state_t state) {
     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;
@@ -460,7 +460,7 @@ unsigned pa_source_used_by(pa_source *s) {
 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(PA_SOURCE_LINKED(s->thread_info.state));
+    pa_assert(s->thread_info.state != PA_SOURCE_UNLINKED);
 
     switch ((pa_source_message_t) code) {
         case PA_SOURCE_MESSAGE_ADD_OUTPUT: {

commit 2e780e88c219fdd63f8b0f4c835c7d0500b88910
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Oct 1 16:41:50 2007 +0000

    Move request size handling into pa_memblockq, function pa_memblockq_pop_missing()
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1923 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/memblockq.c b/src/pulsecore/memblockq.c
index ecdf45b..a46155a 100644
--- a/src/pulsecore/memblockq.c
+++ b/src/pulsecore/memblockq.c
@@ -47,15 +47,17 @@ struct list_item {
 };
 
 PA_STATIC_FLIST_DECLARE(list_items, 0, pa_xfree);
-        
+
 struct pa_memblockq {
     struct list_item *blocks, *blocks_tail;
     unsigned n_blocks;
     size_t maxlength, tlength, base, prebuf, minreq;
     int64_t read_index, write_index;
-    int in_prebuf;
+    pa_bool_t in_prebuf;
     pa_memblock *silence;
     pa_mcalign *mcalign;
+    int64_t missing;
+    size_t requested;
 };
 
 pa_memblockq* pa_memblockq_new(
@@ -109,6 +111,9 @@ pa_memblockq* pa_memblockq_new(
     bq->silence = silence ? pa_memblock_ref(silence) : NULL;
     bq->mcalign = NULL;
 
+    bq->missing = bq->tlength;
+    bq->requested = 0;
+
     return bq;
 }
 
@@ -116,7 +121,7 @@ void pa_memblockq_free(pa_memblockq* bq) {
     pa_assert(bq);
 
     pa_memblockq_flush(bq);
-    
+
     if (bq->silence)
         pa_memblock_unref(bq->silence);
 
@@ -150,7 +155,7 @@ static void drop_block(pa_memblockq *bq, struct list_item *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;
 
     pa_assert(bq);
@@ -161,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;
@@ -169,15 +174,15 @@ 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 list_item *q, *n;
     pa_memchunk chunk;
+    int64_t old, delta;
 
     pa_assert(bq);
     pa_assert(uchunk);
@@ -191,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) {
@@ -207,7 +213,7 @@ int pa_memblockq_push(pa_memblockq* bq, const pa_memchunk *uchunk) {
         } else {
             /* We drop the incoming data completely */
             bq->write_index += chunk.length;
-            return 0;
+            goto finish;
         }
     }
 
@@ -245,7 +251,7 @@ int pa_memblockq_push(pa_memblockq* bq, const pa_memchunk *uchunk) {
                 /* Create a new list entry for the end of thie memchunk */
                 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);
 
@@ -308,15 +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
         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->chunk = chunk;
     pa_memblock_ref(n->chunk.memblock);
     n->index = bq->write_index;
@@ -336,27 +341,42 @@ 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;
 }
 
-static int memblockq_check_prebuf(pa_memblockq *bq) {
+static pa_bool_t memblockq_check_prebuf(pa_memblockq *bq) {
     pa_assert(bq);
-    
+
     if (bq->in_prebuf) {
-        
+
         if (pa_memblockq_get_length(bq) < bq->prebuf)
-            return 1;
+            return TRUE;
 
-        bq->in_prebuf = 0;
-        return 0;
+        bq->in_prebuf = FALSE;
+        return FALSE;
     } else {
 
         if (bq->prebuf > 0 && bq->read_index >= bq->write_index) {
-            bq->in_prebuf = 1;
-            return 1;
+            bq->in_prebuf = TRUE;
+            return TRUE;
         }
 
-        return 0;
+        return FALSE;
     }
 }
 
@@ -409,15 +429,18 @@ int pa_memblockq_peek(pa_memblockq* bq, pa_memchunk *chunk) {
 }
 
 void pa_memblockq_drop(pa_memblockq *bq, size_t length) {
+    int64_t old, delta;
     pa_assert(bq);
     pa_assert(length % bq->base == 0);
-    
+
+    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;
 
@@ -462,6 +485,9 @@ void pa_memblockq_drop(pa_memblockq *bq, size_t length) {
             break;
         }
     }
+
+    delta = bq->read_index - old;
+    bq->missing += delta;
 }
 
 int pa_memblockq_is_readable(pa_memblockq *bq) {
@@ -493,6 +519,7 @@ size_t pa_memblockq_missing(pa_memblockq *bq) {
         return 0;
 
     l = bq->tlength - l;
+
     return l >= bq->minreq ? l : 0;
 }
 
@@ -503,27 +530,43 @@ size_t pa_memblockq_get_minreq(pa_memblockq *bq) {
 }
 
 void pa_memblockq_seek(pa_memblockq *bq, int64_t offset, pa_seek_mode_t seek) {
+    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;
+            break;
+        default:
+            pa_assert_not_reached();
     }
 
-    pa_assert_not_reached();
+    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) {
+    int64_t old, delta;
     pa_assert(bq);
 
     while (bq->blocks)
@@ -531,9 +574,22 @@ void pa_memblockq_flush(pa_memblockq *bq) {
 
     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) {
@@ -594,14 +650,14 @@ void pa_memblockq_shorten(pa_memblockq *bq, size_t length) {
 void pa_memblockq_prebuf_disable(pa_memblockq *bq) {
     pa_assert(bq);
 
-    bq->in_prebuf = 0;
+    bq->in_prebuf = FALSE;
 }
 
 void pa_memblockq_prebuf_force(pa_memblockq *bq) {
     pa_assert(bq);
 
     if (!bq->in_prebuf && bq->prebuf > 0)
-        bq->in_prebuf = 1;
+        bq->in_prebuf = TRUE;
 }
 
 size_t pa_memblockq_get_maxlength(pa_memblockq *bq) {
@@ -615,3 +671,20 @@ size_t pa_memblockq_get_prebuf(pa_memblockq *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;
+}
diff --git a/src/pulsecore/memblockq.h b/src/pulsecore/memblockq.h
index 5eb23aa..8c3e70f 100644
--- a/src/pulsecore/memblockq.h
+++ b/src/pulsecore/memblockq.h
@@ -103,6 +103,10 @@ 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);
 

commit 7c1768d4d1a61b998811c5044e16525b05cd88b0
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Oct 1 16:42:59 2007 +0000

    update native protocol to make use of pa_memblockq_pop_missing
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1924 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c
index c282c17..9ae0f08 100644
--- a/src/pulsecore/protocol-native.c
+++ b/src/pulsecore/protocol-native.c
@@ -80,7 +80,7 @@ typedef struct record_stream {
 
     connection *connection;
     uint32_t index;
-    
+
     pa_source_output *source_output;
     pa_memblockq *memblockq;
     size_t fragment_size;
@@ -92,10 +92,10 @@ typedef struct output_stream {
 
 typedef struct playback_stream {
     output_stream parent;
-    
+
     connection *connection;
     uint32_t index;
-    
+
     pa_sink_input *sink_input;
     pa_memblockq *memblockq;
     int drain_request;
@@ -104,7 +104,7 @@ typedef struct playback_stream {
     int underrun;
 
     pa_atomic_t missing;
-    size_t last_missing;
+    size_t minreq;
 
     /* Only updated after SINK_INPUT_MESSAGE_UPDATE_LATENCY */
     int64_t read_index, write_index;
@@ -113,10 +113,10 @@ typedef struct playback_stream {
 
 typedef struct upload_stream {
     output_stream parent;
-    
+
     connection *connection;
     uint32_t index;
-    
+
     pa_memchunk memchunk;
     size_t length;
     char *name;
@@ -126,7 +126,7 @@ typedef struct upload_stream {
 
 struct connection {
     pa_msgobject parent;
-    
+
     int authorized;
     uint32_t version;
     pa_protocol_native *protocol;
@@ -299,7 +299,7 @@ static const pa_pdispatch_cb_t command_table[PA_COMMAND_MAX] = {
 
     [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_trigger_or_flush_or_prebuf_playback_stream,
     [PA_COMMAND_TRIGGER_PLAYBACK_STREAM] = command_trigger_or_flush_or_prebuf_playback_stream,
@@ -360,7 +360,7 @@ static upload_stream* upload_stream_new(
         const char *name, size_t length) {
 
     upload_stream *s;
-    
+
     pa_assert(c);
     pa_assert(ss);
     pa_assert(name);
@@ -376,7 +376,7 @@ static upload_stream* upload_stream_new(
     s->length = length;
 
     pa_idxset_put(c->output_streams, s, &s->index);
-    
+
     return s;
 }
 
@@ -394,7 +394,7 @@ static void record_stream_unlink(record_stream *s) {
 
     pa_assert_se(pa_idxset_remove_by_data(s->connection->record_streams, s, NULL) == s);
     s->connection = NULL;
-    record_stream_unref(s);    
+    record_stream_unref(s);
 }
 
 static void record_stream_free(pa_object *o) {
@@ -402,7 +402,7 @@ static void record_stream_free(pa_object *o) {
     pa_assert(s);
 
     record_stream_unlink(s);
-    
+
     pa_memblockq_free(s->memblockq);
     pa_xfree(s);
 }
@@ -413,11 +413,11 @@ static int record_stream_process_msg(pa_msgobject *o, int code, void*userdata, i
 
     if (!s->connection)
         return -1;
-    
+
     switch (code) {
-        
+
         case RECORD_STREAM_MESSAGE_POST_DATA:
-            
+
             if (pa_memblockq_push_align(s->memblockq, chunk) < 0) {
 /*                 pa_log_warn("Failed to push data into output queue."); */
                 return -1;
@@ -512,7 +512,7 @@ static void playback_stream_unlink(playback_stream *s) {
 
     pa_assert_se(pa_idxset_remove_by_data(s->connection->output_streams, s, NULL) == s);
     s->connection = NULL;
-    playback_stream_unref(s);    
+    playback_stream_unref(s);
 }
 
 static void playback_stream_free(pa_object* o) {
@@ -520,7 +520,7 @@ static void playback_stream_free(pa_object* o) {
     pa_assert(s);
 
     playback_stream_unlink(s);
-    
+
     pa_memblockq_free(s->memblockq);
     pa_xfree(s);
 }
@@ -535,23 +535,26 @@ static int playback_stream_process_msg(pa_msgobject *o, int code, void*userdata,
     switch (code) {
         case PLAYBACK_STREAM_MESSAGE_REQUEST_DATA: {
             pa_tagstruct *t;
-            int32_t l = 0;
+            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 <= 0)
+            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 */
@@ -689,16 +692,16 @@ static playback_stream* playback_stream_new(
     *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_missing(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->last_missing = *missing;
     s->drain_request = 0;
 
     pa_idxset_put(c->output_streams, s, &s->index);
 
     pa_sink_input_put(s->sink_input);
-    
+
     return s;
 }
 
@@ -708,9 +711,9 @@ static int connection_process_msg(pa_msgobject *o, int code, void*userdata, int6
 
     if (!c->protocol)
         return -1;
-    
+
     switch (code) {
-        
+
         case CONNECTION_MESSAGE_REVOKE:
             pa_pstream_send_revoke(c->pstream, PA_PTR_TO_UINT(userdata));
             break;
@@ -751,7 +754,7 @@ static void connection_unlink(connection *c) {
         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);
@@ -759,11 +762,11 @@ static void connection_unlink(connection *c) {
 
 static void connection_free(pa_object *o) {
     connection *c = CONNECTION(o);
-    
+
     pa_assert(c);
 
     connection_unlink(c);
-    
+
     pa_idxset_free(c->record_streams, NULL, NULL);
     pa_idxset_free(c->output_streams, NULL, NULL);
 
@@ -776,23 +779,19 @@ static void connection_free(pa_object *o) {
 
 /* Called from thread context */
 static void request_bytes(playback_stream *s) {
-    size_t new_missing, delta, previous_missing;
-    size_t minreq;
+    size_t m, previous_missing;
 
     playback_stream_assert_ref(s);
 
-    new_missing = pa_memblockq_missing(s->memblockq);
-    delta = new_missing > s->last_missing ? new_missing - s->last_missing : 0;
-    s->last_missing = new_missing;
+    m = pa_memblockq_pop_missing(s->memblockq);
 
-    if (delta <= 0)
+    if (m <= 0)
         return;
 
-/*     pa_log("request_bytes(%u)", delta); */
-    minreq = pa_memblockq_get_minreq(s->memblockq);
+/*     pa_log("request_bytes(%u)", m); */
 
-    previous_missing = pa_atomic_add(&s->missing, delta);
-    if (previous_missing < minreq && previous_missing+delta >= minreq) {
+    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);
     }
@@ -821,7 +820,7 @@ static void send_memblock(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, schunk.length);
             pa_memblock_unref(schunk.memblock);
 
@@ -865,7 +864,7 @@ static int sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int
 
     switch (code) {
 
-        case SINK_INPUT_MESSAGE_SEEK: 
+        case SINK_INPUT_MESSAGE_SEEK:
             pa_memblockq_seek(s->memblockq, offset, PA_PTR_TO_UINT(userdata));
             request_bytes(s);
             return 0;
@@ -873,6 +872,8 @@ static int sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int
         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");
@@ -904,7 +905,7 @@ static int sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int
         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);
 
@@ -912,11 +913,11 @@ static int sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int
                 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;
@@ -924,7 +925,7 @@ static int sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int
                 default:
                     pa_assert_not_reached();
             }
-            
+
             func(s->memblockq);
             s->underrun = 0;
             request_bytes(s);
@@ -943,17 +944,17 @@ static int sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int
                 ssync->underrun = 0;
                 request_bytes(ssync);
             }
-            
+
             return 0;
         }
 
-        case SINK_INPUT_MESSAGE_UPDATE_LATENCY: 
+        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);
@@ -993,7 +994,7 @@ static int sink_input_peek_cb(pa_sink_input *i, size_t length, pa_memchunk *chun
         return -1;
     }
 
-/*     pa_log("peek: %u", chunk->length);     */
+/*     pa_log("peek: %u", chunk->length); */
 
     request_bytes(s);
 
@@ -1018,7 +1019,7 @@ static void sink_input_drop_cb(pa_sink_input *i, size_t length) {
 
     request_bytes(s);
 
-/*     pa_log("after_drop: %u %u", pa_memblockq_get_length(s->memblockq), pa_memblockq_is_readable(s->memblockq));   */
+/*     pa_log("after_drop: %u %u", pa_memblockq_get_length(s->memblockq), pa_memblockq_is_readable(s->memblockq)); */
 }
 
 static void sink_input_kill_cb(pa_sink_input *i) {
@@ -1103,7 +1104,7 @@ static void command_create_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GC
     pa_sink *sink = NULL;
     pa_cvolume volume;
     int corked;
-    
+
     connection_assert_ref(c);
     pa_assert(t);
 
@@ -1156,7 +1157,7 @@ static void command_create_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GC
     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 */
 
@@ -1185,25 +1186,25 @@ static void command_delete_stream(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t comma
     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
 
     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;
         }
-            
+
         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;
         }
@@ -1215,7 +1216,7 @@ static void command_delete_stream(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t comma
                 pa_pstream_send_error(c->pstream, tag, PA_ERR_EXIST);
                 return;
             }
-            
+
             upload_stream_unlink(s);
             break;
         }
@@ -1294,7 +1295,7 @@ static void command_exit(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t
 
     connection_assert_ref(c);
     pa_assert(t);
-    
+
     if (!pa_tagstruct_eof(t)) {
         protocol_error(c);
         return;
@@ -1427,7 +1428,7 @@ static void command_lookup(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, uin
     connection *c = CONNECTION(userdata);
     const char *name;
     uint32_t idx = PA_IDXSET_INVALID;
-    
+
     connection_assert_ref(c);
     pa_assert(t);
 
@@ -1532,12 +1533,12 @@ static void command_get_playback_latency(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_
     CHECK_VALIDITY(c->pstream, s, 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);
-    latency += pa_bytes_to_usec(s->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);
@@ -1792,7 +1793,7 @@ static void sink_input_fill_tagstruct(connection *c, pa_tagstruct *t, pa_sink_in
     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));    
+        pa_tagstruct_put_boolean(t, pa_sink_input_get_mute(s));
 }
 
 static void source_output_fill_tagstruct(pa_tagstruct *t, pa_source_output *s) {
@@ -1815,7 +1816,7 @@ 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) {
     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);
@@ -2073,7 +2074,7 @@ static void command_set_volume(
     CHECK_VALIDITY(c->pstream, pa_cvolume_valid(&volume), tag, PA_ERR_INVALID);
 
     switch (command) {
-        
+
         case PA_COMMAND_SET_SINK_VOLUME:
             if (idx != PA_INVALID_INDEX)
                 sink = pa_idxset_get_by_index(c->protocol->core->sinks, idx);
@@ -2087,7 +2088,7 @@ static void command_set_volume(
             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;
@@ -2139,7 +2140,7 @@ static void command_set_mute(
     CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX || !name || (*name && pa_utf8_valid(name)), tag, PA_ERR_INVALID);
 
     switch (command) {
-        
+
         case PA_COMMAND_SET_SINK_MUTE:
 
             if (idx != PA_INVALID_INDEX)
@@ -2227,7 +2228,7 @@ static void command_trigger_or_flush_or_prebuf_playback_stream(PA_GCC_UNUSED pa_
         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_asyncmsgq_send(s->sink_input->sink->asyncmsgq, PA_MSGOBJECT(s->sink_input), SINK_INPUT_MESSAGE_PREBUF_FORCE, NULL, 0, NULL);
             break;
@@ -2275,7 +2276,7 @@ static void command_flush_record_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_U
 
     connection_assert_ref(c);
     pa_assert(t);
-    
+
     if (pa_tagstruct_getu32(t, &idx) < 0 ||
         !pa_tagstruct_eof(t)) {
         protocol_error(c);
@@ -2405,7 +2406,7 @@ static void command_load_module(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED ui
 
     connection_assert_ref(c);
     pa_assert(t);
-    
+
     if (pa_tagstruct_gets(t, &name) < 0 ||
         pa_tagstruct_gets(t, &argument) < 0 ||
         !pa_tagstruct_eof(t)) {
@@ -2562,7 +2563,7 @@ 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) {
     connection *c = CONNECTION(userdata);
     pa_tagstruct *reply;
-    
+
     connection_assert_ref(c);
     pa_assert(t);
 
@@ -2680,7 +2681,7 @@ static void command_suspend(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa
 
             if (idx != PA_INVALID_INDEX)
                 sink = pa_idxset_get_by_index(c->protocol->core->sinks, idx);
-            else 
+            else
                 sink = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SINK, 1);
 
             CHECK_VALIDITY(c->pstream, sink, tag, PA_ERR_NOENTITY);
@@ -2693,9 +2694,9 @@ static void command_suspend(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa
     } 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;
@@ -2708,7 +2709,7 @@ static void command_suspend(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa
                 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) {
@@ -2739,7 +2740,7 @@ static void pstream_packet_callback(pa_pstream *p, pa_packet *packet, const pa_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) {
     connection *c = CONNECTION(userdata);
     output_stream *stream;
-    
+
     pa_assert(p);
     pa_assert(chunk);
     connection_assert_ref(c);
@@ -2752,12 +2753,12 @@ static void pstream_memblock_callback(pa_pstream *p, uint32_t channel, int64_t o
 
     if (playback_stream_isinstance(stream)) {
         playback_stream *ps = PLAYBACK_STREAM(stream);
-        
+
         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);
-        
+
         pa_asyncmsgq_post(ps->sink_input->sink->asyncmsgq, PA_MSGOBJECT(ps->sink_input), SINK_INPUT_MESSAGE_POST_DATA, NULL, 0, chunk, NULL);
-        
+
     } else {
         upload_stream *u = UPLOAD_STREAM(stream);
         size_t l;
@@ -2799,7 +2800,7 @@ static void pstream_memblock_callback(pa_pstream *p, uint32_t channel, int64_t o
 
 static void pstream_die_callback(pa_pstream *p, void *userdata) {
     connection *c = CONNECTION(userdata);
-    
+
     pa_assert(p);
     connection_assert_ref(c);
 
@@ -2818,7 +2819,7 @@ static void pstream_drain_callback(pa_pstream *p, void *userdata) {
 
 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
@@ -2827,7 +2828,7 @@ static void pstream_revoke_callback(pa_pstream *p, uint32_t block_id, void *user
 
 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
@@ -2838,7 +2839,7 @@ static void pstream_release_callback(pa_pstream *p, uint32_t block_id, void *use
 
 static void client_kill_cb(pa_client *c) {
     pa_assert(c);
-    
+
     connection_unlink(CONNECTION(c->userdata));
 }
 
@@ -2846,7 +2847,7 @@ static void client_kill_cb(pa_client *c) {
 
 static void auth_timeout(pa_mainloop_api*m, pa_time_event *e, const struct timeval *tv, void *userdata) {
     connection *c = CONNECTION(userdata);
-    
+
     pa_assert(m);
     pa_assert(tv);
     connection_assert_ref(c);
@@ -3075,7 +3076,7 @@ pa_protocol_native* pa_protocol_native_new_iochannel(
         pa_iochannel *io,
         pa_module *m,
         pa_modargs *ma) {
-    
+
     pa_protocol_native *p;
 
     if (!(p = protocol_new_internal(core, m, ma)))

commit ef8812e89bb867f127813e1b193589a52f0f2073
Author: Pierre Ossman <ossman at cendio.se>
Date:   Wed Oct 3 14:41:21 2007 +0000

    Replace all references to sys/poll.h with poll.h as that's what POSIX defines.
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1925 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/configure.ac b/configure.ac
index 0da5253..b22a990 100644
--- a/configure.ac
+++ b/configure.ac
@@ -185,7 +185,7 @@ 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 sys/dl.h dlfcn.h])
 AC_CHECK_HEADERS([netinet/ip.h], [], [],
@@ -203,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])
 
diff --git a/src/pulse/mainloop.c b/src/pulse/mainloop.c
index bab8eb5..ad4e4e9 100644
--- a/src/pulse/mainloop.c
+++ b/src/pulse/mainloop.c
@@ -34,8 +34,8 @@
 #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>
 #endif
diff --git a/src/pulse/thread-mainloop.c b/src/pulse/thread-mainloop.c
index 3068570..9dd47ae 100644
--- a/src/pulse/thread-mainloop.c
+++ b/src/pulse/thread-mainloop.c
@@ -29,8 +29,8 @@
 #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>
 #endif

commit 8dcc1fa6161c2a507d008a50a6d7f5170ce54a14
Author: Pierre Ossman <ossman at cendio.se>
Date:   Wed Oct 3 14:43:56 2007 +0000

    Adapt rtpoll and friends to Windows by replacing timespec with timeval and
    add a fallback when clock_gettime() isn't available.
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1926 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/configure.ac b/configure.ac
index b22a990..152cd51 100644
--- a/configure.ac
+++ b/configure.ac
@@ -271,9 +271,10 @@ AC_CHECK_FUNCS([lrintf strtof])
 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_fadvise posix_madvise \
-    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")
diff --git a/src/modules/module-combine.c b/src/modules/module-combine.c
index 447f41c..665bf9d 100644
--- a/src/modules/module-combine.c
+++ b/src/modules/module-combine.c
@@ -118,7 +118,7 @@ struct userdata {
 
     pa_resample_method_t resample_method;
 
-    struct timespec adjust_timestamp;
+    struct timeval adjust_timestamp;
 
     struct output *master;
     pa_idxset* outputs; /* managed in main context */
@@ -126,7 +126,7 @@ struct userdata {
     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 timespec timestamp;
+        struct timeval timestamp;
         pa_bool_t in_null_mode;
     } thread_info;
 };
@@ -247,17 +247,17 @@ static void thread_func(void *userdata) {
 
         /* 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 timespec now;
+            struct timeval now;
 
             pa_rtclock_get(&now);
 
-            if (!u->thread_info.in_null_mode || pa_timespec_cmp(&u->thread_info.timestamp, &now) <= 0) {
+            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_timespec_add(&u->thread_info.timestamp, pa_bytes_to_usec(u->block_size, &u->sink->sample_spec));
+                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);
@@ -563,10 +563,10 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
              * sink_get_latency_cb() below */
 
             if (u->thread_info.in_null_mode) {
-                struct timespec now;
+                struct timeval now;
 
-                if (pa_timespec_cmp(&u->thread_info.timestamp, pa_rtclock_get(&now)) > 0) {
-                    *((pa_usec_t*) data) = pa_timespec_diff(&u->thread_info.timestamp, &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;
                 }
             }
@@ -947,7 +947,7 @@ int pa__init(pa_module*m) {
     u->thread = NULL;
     u->resample_method = resample_method;
     u->outputs = pa_idxset_new(NULL, NULL);
-    pa_timespec_reset(&u->adjust_timestamp);
+    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);
diff --git a/src/modules/module-null-sink.c b/src/modules/module-null-sink.c
index 04df239..d993988 100644
--- a/src/modules/module-null-sink.c
+++ b/src/modules/module-null-sink.c
@@ -75,7 +75,7 @@ struct userdata {
 
     size_t block_size;
     
-    struct timespec timestamp;
+    struct timeval timestamp;
 };
 
 static const char* const valid_modargs[] = {
@@ -100,14 +100,14 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
             break;
             
         case PA_SINK_MESSAGE_GET_LATENCY: {
-            struct timespec now;
+            struct timeval now;
     
             pa_rtclock_get(&now);
             
-            if (pa_timespec_cmp(&u->timestamp, &now) > 0)
+            if (pa_timeval_cmp(&u->timestamp, &now) > 0)
                 *((pa_usec_t*) data) = 0;
             else
-                *((pa_usec_t*) data) = pa_timespec_diff(&u->timestamp, &now);
+                *((pa_usec_t*) data) = pa_timeval_diff(&u->timestamp, &now);
             break;
         }
     }
@@ -132,13 +132,13 @@ static void thread_func(void *userdata) {
 
         /* Render some data and drop it immediately */
         if (u->sink->thread_info.state == PA_SINK_RUNNING) {
-            struct timespec now;
+            struct timeval now;
             
             pa_rtclock_get(&now);
 
-            if (pa_timespec_cmp(&u->timestamp, &now) <= 0) {
+            if (pa_timeval_cmp(&u->timestamp, &now) <= 0) {
                 pa_sink_skip(u->sink, u->block_size);
-                pa_timespec_add(&u->timestamp, pa_bytes_to_usec(u->block_size, &u->sink->sample_spec));
+                pa_timeval_add(&u->timestamp, pa_bytes_to_usec(u->block_size, &u->sink->sample_spec));
             }
 
             pa_rtpoll_set_timer_absolute(u->rtpoll, &u->timestamp);
diff --git a/src/pulsecore/rtclock.c b/src/pulsecore/rtclock.c
index 7dd83b3..0d983f8 100644
--- a/src/pulsecore/rtclock.c
+++ b/src/pulsecore/rtclock.c
@@ -35,123 +35,48 @@
 
 #include "rtclock.h"
 
-struct timespec *pa_timespec_store(struct timespec *a, pa_usec_t u) {
-    pa_assert(a);
+pa_usec_t pa_rtclock_age(const struct timeval *tv) {
+    struct timeval now;
+    pa_assert(tv);
 
-    a->tv_sec = u / PA_USEC_PER_SEC;
-
-    u -= (pa_usec_t) a->tv_sec * PA_USEC_PER_SEC;
-    
-    a->tv_nsec = u * 1000;
-
-    return a;
-}
-
-struct timespec *pa_timespec_reset(struct timespec *a) {
-    pa_assert(a);
-
-    a->tv_sec = a->tv_nsec = 0;
-    return a;
-}
-
-pa_usec_t pa_timespec_load(struct timespec *ts) {
-    pa_assert(ts);
-    
-    return (pa_usec_t) ts->tv_sec * PA_USEC_PER_SEC + (pa_usec_t) (ts->tv_nsec / 1000);
-}
-
-pa_usec_t pa_timespec_diff(const struct timespec *a, const struct timespec *b) {
-    pa_usec_t r;
-    
-    pa_assert(a);
-    pa_assert(b);
-
-    /* Check which whan is the earlier time and swap the two arguments if required. */
-    if (pa_timespec_cmp(a, b) < 0) {
-        const struct timespec *c;
-        c = a;
-        a = b;
-        b = c;
-    }
-
-    /* Calculate the second difference*/
-    r = ((pa_usec_t) a->tv_sec - b->tv_sec) * PA_USEC_PER_SEC;
-
-    /* Calculate the microsecond difference */
-    if (a->tv_nsec > b->tv_nsec)
-        r += (pa_usec_t) ((a->tv_nsec - b->tv_nsec) / 1000);
-    else if (a->tv_nsec < b->tv_nsec)
-        r -= (pa_usec_t) ((b->tv_nsec - a->tv_nsec) / 1000);
-
-    return r;
-}
-
-int pa_timespec_cmp(const struct timespec *a, const struct timespec *b) {
-    pa_assert(a);
-    pa_assert(b);
-
-    if (a->tv_sec < b->tv_sec)
-        return -1;
-
-    if (a->tv_sec > b->tv_sec)
-        return 1;
-
-    if (a->tv_nsec < b->tv_nsec)
-        return -1;
-
-    if (a->tv_nsec > b->tv_nsec)
-        return 1;
-
-    return 0;
+    return pa_timeval_diff(pa_rtclock_get(&now), tv);
 }
 
-struct timespec* pa_timespec_add(struct timespec *ts, pa_usec_t v) {
-    unsigned long secs;
-    pa_assert(ts);
-
-    secs = (unsigned long) (v/PA_USEC_PER_SEC);
-    ts->tv_sec += secs;
-    v -= ((pa_usec_t) secs) * PA_USEC_PER_SEC;
-
-    ts->tv_nsec += (long) (v*1000);
-
-    /* Normalize */
-    while (ts->tv_nsec >= PA_NSEC_PER_SEC) {
-        ts->tv_sec++;
-        ts->tv_nsec -= PA_NSEC_PER_SEC;
-    }
-
-    return ts;
-}
-
-pa_usec_t pa_rtclock_age(const struct timespec *ts) {
-    struct timespec now;
-    pa_assert(ts);
-
-    return pa_timespec_diff(pa_rtclock_get(&now), ts);
-}
-
-struct timespec *pa_rtclock_get(struct timespec *ts) {
+struct timeval *pa_rtclock_get(struct timeval *tv) {
+#ifdef HAVE_CLOCK_GETTIME
     static int no_monotonic = 0;
+    struct timespec ts;
 
     /* No locking or atomic ops for no_monotonic here */
-    
-    pa_assert(ts);
 
     if (!no_monotonic) {
 #ifdef CLOCK_MONOTONIC
-        if (clock_gettime(CLOCK_MONOTONIC, ts) >= 0)
-            return ts;
+        if (clock_gettime(CLOCK_MONOTONIC, &ts) >= 0)
+            goto out;
 #endif        
 
         no_monotonic = 1;
     }
 
     pa_assert_se(clock_gettime(CLOCK_REALTIME, ts) == 0);
-    return ts;
+
+out:
+    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
 }
 
 int pa_rtclock_hrtimer(void) {
+#ifdef HAVE_CLOCK_GETTIME
     struct timespec ts;
     
 #ifdef CLOCK_MONOTONIC
@@ -161,5 +86,11 @@ int pa_rtclock_hrtimer(void) {
 
     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 0;
+
+#endif
 }
 
diff --git a/src/pulsecore/rtclock.h b/src/pulsecore/rtclock.h
index cfc968f..0d232a0 100644
--- a/src/pulsecore/rtclock.h
+++ b/src/pulsecore/rtclock.h
@@ -24,25 +24,14 @@
   USA.
 ***/
 
-#include <sys/types.h>
-#include <time.h>
+struct timeval;
 
-#include <pulse/sample.h>
+/* Something like pulse/timeval.h but based on CLOCK_MONOTONIC */
 
-/* Something like pulse/timeval.h but based on CLOCK_MONOTONIC and
- * timespec instead of timeval */
-
-struct timespec *pa_rtclock_get(struct timespec *ts);
-pa_usec_t pa_rtclock_age(const struct timespec *tv);
+struct timeval *pa_rtclock_get(struct timeval *ts);
+pa_usec_t pa_rtclock_age(const struct timeval *tv);
 int pa_rtclock_hrtimer(void);
 
-struct timespec *pa_timespec_store(struct timespec *a, pa_usec_t u);
-struct timespec *pa_timespec_reset(struct timespec *a);
-pa_usec_t pa_timespec_load(struct timespec *tv);
-struct timespec *pa_timespec_add(struct timespec *tv, pa_usec_t t);
-pa_usec_t pa_timespec_diff(const struct timespec *a, const struct timespec *b);
-int pa_timespec_cmp(const struct timespec *a, const struct timespec *b);
-
 /* timer with a resolution better than this are considered high-resolution */
 #define PA_HRTIMER_THRESHOLD_USEC 10
 
diff --git a/src/pulsecore/rtpoll.c b/src/pulsecore/rtpoll.c
index de0ffa4..c81fcd1 100644
--- a/src/pulsecore/rtpoll.c
+++ b/src/pulsecore/rtpoll.c
@@ -26,14 +26,24 @@
 #include <config.h>
 #endif
 
-#include <sys/utsname.h>
 #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>
@@ -43,6 +53,8 @@
 #include <pulsecore/flist.h>
 #include <pulsecore/core-util.h>
 
+#include <pulsecore/winsock.h>
+
 #include "rtpoll.h"
 
 struct pa_rtpoll {
@@ -50,7 +62,7 @@ struct pa_rtpoll {
     unsigned n_pollfd_alloc, n_pollfd_used;
 
     pa_bool_t timer_enabled;
-    struct timespec next_elapse;
+    struct timeval next_elapse;
     pa_usec_t period;
 
     pa_bool_t scan_for_dead;
@@ -290,7 +302,7 @@ static void reset_all_revents(pa_rtpoll *p) {
 int pa_rtpoll_run(pa_rtpoll *p, pa_bool_t wait) {
     pa_rtpoll_item *i;
     int r = 0;
-    struct timespec timeout;
+    struct timeval timeout;
 
     pa_assert(p);
     pa_assert(!p->running);
@@ -357,15 +369,14 @@ int pa_rtpoll_run(pa_rtpoll *p, pa_bool_t wait) {
     /* Calculate timeout */
     if (!wait || p->quit) {
         timeout.tv_sec = 0;
-        timeout.tv_nsec = 0;
+        timeout.tv_usec = 0;
     } else if (p->timer_enabled) {
-        struct timespec now;
+        struct timeval now;
         pa_rtclock_get(&now);
 
-        if (pa_timespec_cmp(&p->next_elapse, &now) <= 0)
-            memset(&timeout, 0, sizeof(timeout));
-        else
-            pa_timespec_store(&timeout, pa_timespec_diff(&p->next_elapse, &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 */
@@ -380,7 +391,7 @@ int pa_rtpoll_run(pa_rtpoll *p, pa_bool_t wait) {
 #endif
 
 #endif
-        r = poll(p->pollfd, p->n_pollfd_used, p->timer_enabled ? (timeout.tv_sec*1000) + (timeout.tv_nsec / 1000000) : -1);
+        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)
@@ -393,14 +404,14 @@ int pa_rtpoll_run(pa_rtpoll *p, pa_bool_t wait) {
 
     if (p->timer_enabled) {
         if (p->period > 0) {
-            struct timespec now;
+            struct timeval now;
             pa_rtclock_get(&now);
 
-            pa_timespec_add(&p->next_elapse, p->period);
+            pa_timeval_add(&p->next_elapse, p->period);
 
             /* Guarantee that the next timeout will happen in the future */
-            if (pa_timespec_cmp(&p->next_elapse, &now) < 0)
-                pa_timespec_add(&p->next_elapse, (pa_timespec_diff(&now, &p->next_elapse) / p->period + 1) * p->period);
+            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;
@@ -487,7 +498,7 @@ static void update_timer(pa_rtpoll *p) {
 #endif
 }
 
-void pa_rtpoll_set_timer_absolute(pa_rtpoll *p, const struct timespec *ts) {
+void pa_rtpoll_set_timer_absolute(pa_rtpoll *p, const struct timeval *ts) {
     pa_assert(p);
     pa_assert(ts);
 
@@ -503,7 +514,7 @@ void pa_rtpoll_set_timer_periodic(pa_rtpoll *p, pa_usec_t usec) {
 
     p->period = usec;
     pa_rtclock_get(&p->next_elapse);
-    pa_timespec_add(&p->next_elapse, usec);
+    pa_timeval_add(&p->next_elapse, usec);
     p->timer_enabled = TRUE;
 
     update_timer(p);
@@ -514,7 +525,7 @@ void pa_rtpoll_set_timer_relative(pa_rtpoll *p, pa_usec_t usec) {
 
     p->period = 0;
     pa_rtclock_get(&p->next_elapse);
-    pa_timespec_add(&p->next_elapse, usec);
+    pa_timeval_add(&p->next_elapse, usec);
     p->timer_enabled = TRUE;
 
     update_timer(p);
diff --git a/src/pulsecore/rtpoll.h b/src/pulsecore/rtpoll.h
index a1242b3..d38d086 100644
--- a/src/pulsecore/rtpoll.h
+++ b/src/pulsecore/rtpoll.h
@@ -24,7 +24,6 @@
   USA.
 ***/
 
-#include <poll.h>
 #include <sys/types.h>
 #include <limits.h>
 
@@ -75,7 +74,7 @@ void pa_rtpoll_install(pa_rtpoll *p);
  * cleanly. */
 int pa_rtpoll_run(pa_rtpoll *f, pa_bool_t wait);
 
-void pa_rtpoll_set_timer_absolute(pa_rtpoll *p, const struct timespec *ts);
+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);

commit ce74146a817481c95942f4afee73d918ba82427d
Author: Pierre Ossman <ossman at cendio.se>
Date:   Wed Oct 3 14:46:36 2007 +0000

    Add stubs when RT signals aren't available.
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1927 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/rtsig.c b/src/pulsecore/rtsig.c
index 1af45e7..bfc49c8 100644
--- a/src/pulsecore/rtsig.c
+++ b/src/pulsecore/rtsig.c
@@ -36,6 +36,8 @@
 
 #include "rtsig.h"
 
+#ifdef SIGRTMIN
+
 static void _free_rtsig(void *p) {
     pa_rtsig_put(PA_PTR_TO_INT(p));
 }
@@ -111,3 +113,21 @@ void pa_rtsig_configure(int start, int end) {
     /* 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 */

commit cef65632734caf00fbf1b0e44672d0e3c533c52f
Author: Pierre Ossman <ossman at cendio.se>
Date:   Wed Oct 3 14:47:26 2007 +0000

    Assorted minor Windows compatibility fixes for recent code updates.
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1928 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/configure.ac b/configure.ac
index 152cd51..cf9069a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -219,6 +219,7 @@ 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. ####
 
diff --git a/libltdl/config.h b/libltdl/config.h
index a04820a..a4186d9 100644
--- a/libltdl/config.h
+++ b/libltdl/config.h
@@ -2,22 +2,22 @@
 /* config-h.in.  Generated from configure.ac by autoheader.  */
 
 /* Define to 1 if you have the `argz_append' function. */
-#define HAVE_ARGZ_APPEND 1
+/* #undef HAVE_ARGZ_APPEND */
 
 /* Define to 1 if you have the `argz_create_sep' function. */
-#define HAVE_ARGZ_CREATE_SEP 1
+/* #undef HAVE_ARGZ_CREATE_SEP */
 
 /* Define to 1 if you have the <argz.h> header file. */
-#define HAVE_ARGZ_H 1
+/* #undef HAVE_ARGZ_H */
 
 /* Define to 1 if you have the `argz_insert' function. */
-#define HAVE_ARGZ_INSERT 1
+/* #undef HAVE_ARGZ_INSERT */
 
 /* Define to 1 if you have the `argz_next' function. */
-#define HAVE_ARGZ_NEXT 1
+/* #undef HAVE_ARGZ_NEXT */
 
 /* Define to 1 if you have the `argz_stringify' function. */
-#define HAVE_ARGZ_STRINGIFY 1
+/* #undef HAVE_ARGZ_STRINGIFY */
 
 /* Define to 1 if you have the <assert.h> header file. */
 #define HAVE_ASSERT_H 1
@@ -42,10 +42,10 @@
 /* #undef HAVE_DLD_H */
 
 /* Define to 1 if you have the `dlerror' function. */
-#define HAVE_DLERROR 1
+/* #undef HAVE_DLERROR */
 
 /* Define to 1 if you have the <dlfcn.h> header file. */
-#define HAVE_DLFCN_H 1
+/* #undef HAVE_DLFCN_H */
 
 /* Define to 1 if you have the <dl.h> header file. */
 /* #undef HAVE_DL_H */
@@ -57,7 +57,7 @@
 #define HAVE_ERRNO_H 1
 
 /* Define to 1 if the system has the type `error_t'. */
-#define HAVE_ERROR_T 1
+/* #undef HAVE_ERROR_T */
 
 /* Define to 1 if you have the `index' function. */
 /* #undef HAVE_INDEX */
@@ -66,7 +66,7 @@
 #define HAVE_INTTYPES_H 1
 
 /* Define if you have the libdl library or equivalent. */
-#define HAVE_LIBDL 1
+/* #undef HAVE_LIBDL */
 
 /* Define to 1 if you have the <mach-o/dyld.h> header file. */
 /* #undef HAVE_MACH_O_DYLD_H */
@@ -146,7 +146,7 @@
 #define HAVE_UNISTD_H 1
 
 /* Define if the OS needs help to load dependent libraries for dlopen(). */
-/* #undef LTDL_DLOPEN_DEPLIBS */
+#define LTDL_DLOPEN_DEPLIBS 1
 
 /* Define to the sub-directory in which libtool stores uninstalled libraries.
    */
@@ -154,13 +154,13 @@
 
 /* Define to the name of the environment variable that determines the dynamic
    library search path. */
-#define LTDL_SHLIBPATH_VAR "LD_LIBRARY_PATH"
+#define LTDL_SHLIBPATH_VAR "PATH"
 
 /* Define to the extension used for shared libraries, say, ".so". */
-#define LTDL_SHLIB_EXT ".so"
+#define LTDL_SHLIB_EXT ".dll"
 
 /* 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 LTDL_SYSSEARCHPATH "/lib:/usr/lib"
 
 /* Define if dlsym() requires a leading underscore in symbol names. */
 /* #undef NEED_USCORE */
@@ -187,7 +187,7 @@
 /* #undef const */
 
 /* Define to a type to use for `error_t' if it is not otherwise available. */
-/* #undef error_t */
+#define error_t int
 
 /* 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.  */
diff --git a/src/Makefile.am b/src/Makefile.am
index e1d210b..98e7874 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -78,8 +78,8 @@ endif
 if OS_IS_WIN32
 PA_THREAD_OBJS = \
 		pulsecore/mutex-win32.c pulsecore/mutex.h \
-		pulsecore/thread-win32.c pulsecore/thread.h
-#		pulsecore/semaphore-win32.c pulsecore/semaphore.h
+		pulsecore/thread-win32.c pulsecore/thread.h \
+		pulsecore/semaphore-win32.c pulsecore/semaphore.h
 else
 PA_THREAD_OBJS = \
 		pulsecore/mutex-posix.c pulsecore/mutex.h \
diff --git a/src/pulsecore/authkey.c b/src/pulsecore/authkey.c
index 4d9bfd3..d422d6a 100644
--- a/src/pulsecore/authkey.c
+++ b/src/pulsecore/authkey.c
@@ -71,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) {
diff --git a/src/pulsecore/core-util.c b/src/pulsecore/core-util.c
index 3defe2b..a644b66 100644
--- a/src/pulsecore/core-util.c
+++ b/src/pulsecore/core-util.c
@@ -653,13 +653,21 @@ const char *pa_sig2str(int sig) {
         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";
 #endif
@@ -670,30 +678,58 @@ const char *pa_sig2str(int sig) {
 #ifdef 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";
 #endif
+#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
+#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
@@ -943,7 +979,10 @@ int pa_lock_lockfile(const char *fn) {
     for (;;) {
         struct stat st;
 
-        if ((fd = open(fn, O_CREAT|O_RDWR|O_NOCTTY
+        if ((fd = open(fn, O_CREAT|O_RDWR
+#ifdef O_NOCTTY
+                       |O_NOCTTY
+#endif
 #ifdef O_NOFOLLOW
                        |O_NOFOLLOW
 #endif
@@ -1431,6 +1470,7 @@ void *pa_will_need(const void *p, size_t l) {
 
     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)
@@ -1446,9 +1486,10 @@ void *pa_will_need(const void *p, size_t l) {
         a = (const uint8_t*) a + bs;
         size -= bs;
     }
+#endif
 
     if (bs <= 0)
-        pa_log_debug("mlock() failed too, giving up: %s", pa_cstrerror(errno));
+        pa_log_debug("mlock() failed too (or doesn't exist), giving up: %s", pa_cstrerror(errno));
     else
         pa_log_debug("mlock() worked fine!");
 
diff --git a/src/pulsecore/fdsem.c b/src/pulsecore/fdsem.c
index b919ba4..927bf00 100644
--- a/src/pulsecore/fdsem.c
+++ b/src/pulsecore/fdsem.c
@@ -25,7 +25,10 @@
 #include <config.h>
 #endif
 
+#ifdef HAVE_SYS_SYSCALL_H
 #include <sys/syscall.h>
+#endif
+
 #include <unistd.h>
 #include <errno.h>
 
@@ -36,6 +39,10 @@
 #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__)
diff --git a/src/pulsecore/ioline.c b/src/pulsecore/ioline.c
index a362700..efb5072 100644
--- a/src/pulsecore/ioline.c
+++ b/src/pulsecore/ioline.c
@@ -32,6 +32,7 @@
 
 #include <pulse/xmalloc.h>
 
+#include <pulsecore/winsock.h>
 #include <pulsecore/core-error.h>
 #include <pulsecore/log.h>
 #include <pulsecore/macro.h>
diff --git a/src/pulsecore/mutex-win32.c b/src/pulsecore/mutex-win32.c
index 1f16e24..77d63d1 100644
--- a/src/pulsecore/mutex-win32.c
+++ b/src/pulsecore/mutex-win32.c
@@ -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);
diff --git a/src/pulsecore/once.c b/src/pulsecore/once.c
index 4f6e5b6..198bd41 100644
--- a/src/pulsecore/once.c
+++ b/src/pulsecore/once.c
@@ -25,8 +25,6 @@
 #include <config.h>
 #endif
 
-#include <pthread.h>
-
 #include <pulsecore/macro.h>
 #include <pulsecore/mutex.h>
 
diff --git a/src/pulsecore/pid.c b/src/pulsecore/pid.c
index 38d2681..55ff208 100644
--- a/src/pulsecore/pid.c
+++ b/src/pulsecore/pid.c
@@ -88,7 +88,10 @@ static int open_pid_file(const char *fn, int mode) {
     for (;;) {
         struct stat st;
 
-        if ((fd = open(fn, mode|O_NOCTTY
+        if ((fd = open(fn, mode
+#ifdef O_NOCTTY
+                       |O_NOCTTY
+#endif
 #ifdef O_NOFOLLOW
                        |O_NOFOLLOW
 #endif
diff --git a/src/pulsecore/rtsig.h b/src/pulsecore/rtsig.h
index 48f5f05..7830d27 100644
--- a/src/pulsecore/rtsig.h
+++ b/src/pulsecore/rtsig.h
@@ -24,9 +24,6 @@
   USA.
 ***/
 
-#include <poll.h>
-#include <sys/types.h>
-
 /* Return the next unused POSIX Realtime signals */
 int pa_rtsig_get(void);
 
diff --git a/src/pulsecore/sound-file-stream.c b/src/pulsecore/sound-file-stream.c
index 6c70c4f..d9f11a2 100644
--- a/src/pulsecore/sound-file-stream.c
+++ b/src/pulsecore/sound-file-stream.c
@@ -244,7 +244,11 @@ int pa_play_file(
 
     memset(&sfinfo, 0, sizeof(sfinfo));
 
-    if ((fd = open(fname, O_RDONLY|O_NOCTTY)) < 0) {
+    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;
     }
diff --git a/src/pulsecore/sound-file.c b/src/pulsecore/sound-file.c
index b1c509f..5035293 100644
--- a/src/pulsecore/sound-file.c
+++ b/src/pulsecore/sound-file.c
@@ -63,7 +63,11 @@ int pa_sound_file_load(
     pa_memchunk_reset(chunk);
     memset(&sfinfo, 0, sizeof(sfinfo));
 
-    if ((fd = open(fname, O_RDONLY|O_NOCTTY)) < 0) {
+    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;
     }
diff --git a/src/pulsecore/thread-win32.c b/src/pulsecore/thread-win32.c
index 46d273b..cad1420 100644
--- a/src/pulsecore/thread-win32.c
+++ b/src/pulsecore/thread-win32.c
@@ -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) {
diff --git a/src/pulsecore/winsock.h b/src/pulsecore/winsock.h
index ae868b3..0352bf4 100644
--- a/src/pulsecore/winsock.h
+++ b/src/pulsecore/winsock.h
@@ -15,6 +15,8 @@
 #define EHOSTUNREACH    WSAEHOSTUNREACH
 #define EWOULDBLOCK     WSAEWOULDBLOCK
 
+typedef long suseconds_t;
+
 #endif
 
 #ifdef HAVE_WS2TCPIP_H

commit 586ef22ee4a1d5f59fc1756412de9e0b8fb4f362
Author: Pierre Ossman <ossman at cendio.se>
Date:   Wed Oct 3 14:48:40 2007 +0000

    Platform dependent semaphore implementation for Windows.
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1929 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/semaphore-win32.c b/src/pulsecore/semaphore-win32.c
new file mode 100644
index 0000000..f657634
--- /dev/null
+++ b/src/pulsecore/semaphore-win32.c
@@ -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 at 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);
+}

commit 60a935b29f69fd25cfb70ced04c366e429499ac4
Author: Pierre Ossman <ossman at cendio.se>
Date:   Wed Oct 3 15:00:13 2007 +0000

    module_ladspa used libltdl so make sure it links against it.
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1930 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/Makefile.am b/src/Makefile.am
index 98e7874..ad7b652 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1224,7 +1224,7 @@ 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) libpulsecore.la
+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

commit cb400878fe52b1418ac9e12389e5a4fa3231732e
Author: Pierre Ossman <ossman at cendio.se>
Date:   Wed Oct 3 15:00:36 2007 +0000

    Don't call pa_rtsig_configure() when we lack the necessary defines.
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1931 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/daemon/main.c b/src/daemon/main.c
index 0e759d2..c135a6b 100644
--- a/src/daemon/main.c
+++ b/src/daemon/main.c
@@ -614,7 +614,9 @@ int main(int argc, char *argv[]) {
     else
         pa_log_info("Dude, your kernel stinks! The chef's recommendation today is Linux with high-resolution timers enabled!");
 
+#ifdef SIGRTMIN
     pa_rtsig_configure(SIGRTMIN, SIGRTMAX);
+#endif
 
     pa_assert_se(mainloop = pa_mainloop_new());
 

commit 87cc073653f42c4e5237489fdc43fd4cda7e7144
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Oct 4 22:41:33 2007 +0000

    fix poll.h check, bad boy ossman broke
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1932 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/poll.c b/src/pulsecore/poll.c
index 2f8eae8..288f7df 100644
--- a/src/pulsecore/poll.c
+++ b/src/pulsecore/poll.c
@@ -45,7 +45,7 @@
 
 #include "winsock.h"
 
-#ifndef HAVE_SYS_POLL_H
+#ifndef HAVE_POLL_H
 
 #include <pulsecore/core-util.h>
 

commit d74fa66f35eda1add73313d60c321f63269b3c56
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sun Oct 7 13:54:15 2007 +0000

    Fix build; change return value of pa_rtclock_hrtimer() to pa_bool
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1933 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/rtclock.c b/src/pulsecore/rtclock.c
index 0d983f8..b34e6a4 100644
--- a/src/pulsecore/rtclock.c
+++ b/src/pulsecore/rtclock.c
@@ -53,12 +53,12 @@ struct timeval *pa_rtclock_get(struct timeval *tv) {
 #ifdef CLOCK_MONOTONIC
         if (clock_gettime(CLOCK_MONOTONIC, &ts) >= 0)
             goto out;
-#endif        
+#endif
 
         no_monotonic = 1;
     }
 
-    pa_assert_se(clock_gettime(CLOCK_REALTIME, ts) == 0);
+    pa_assert_se(clock_gettime(CLOCK_REALTIME, &ts) == 0);
 
 out:
     pa_assert(tv);
@@ -75,22 +75,21 @@ out:
 #endif
 }
 
-int pa_rtclock_hrtimer(void) {
+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        
+#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 0;
+    return FALSE;
 
 #endif
 }
-
diff --git a/src/pulsecore/rtclock.h b/src/pulsecore/rtclock.h
index 0d232a0..72bbd5e 100644
--- a/src/pulsecore/rtclock.h
+++ b/src/pulsecore/rtclock.h
@@ -24,13 +24,15 @@
   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_age(const struct timeval *tv);
-int pa_rtclock_hrtimer(void);
+pa_bool_t pa_rtclock_hrtimer(void);
 
 /* timer with a resolution better than this are considered high-resolution */
 #define PA_HRTIMER_THRESHOLD_USEC 10

commit efc81a8f20652147aa720d8fd3803105081ad2a6
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sun Oct 7 13:54:49 2007 +0000

    add new API function pa_timeval_store()
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1934 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulse/timeval.c b/src/pulse/timeval.c
index 44d74c9..dcc0bd7 100644
--- a/src/pulse/timeval.c
+++ b/src/pulse/timeval.c
@@ -55,7 +55,7 @@ struct timeval *pa_gettimeofday(struct timeval *tv) {
 #else
 #define EPOCHFILETIME (116444736000000000LL)
 #endif
-    
+
     FILETIME        ft;
     LARGE_INTEGER   li;
     __int64         t;
@@ -79,7 +79,7 @@ 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;
-    
+
     pa_assert(a);
     pa_assert(b);
 
@@ -147,3 +147,12 @@ struct timeval* pa_timeval_add(struct timeval *tv, pa_usec_t v) {
 
     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;
+}
diff --git a/src/pulse/timeval.h b/src/pulse/timeval.h
index e90df9f..60b9d08 100644
--- a/src/pulse/timeval.h
+++ b/src/pulse/timeval.h
@@ -55,6 +55,9 @@ 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) PA_GCC_PURE;
 
+/** Store the specified uec value in the timeval struct */
+struct timeval* pa_timeval_store(struct timeval *tv, pa_usec_t v);
+
 PA_C_DECL_END
 
 #endif

commit 2198c2ec6e130ba9fbd762026151b57eb6570702
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sun Oct 7 13:55:37 2007 +0000

    fix build
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1935 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/rtpoll.c b/src/pulsecore/rtpoll.c
index c81fcd1..354c4c0 100644
--- a/src/pulsecore/rtpoll.c
+++ b/src/pulsecore/rtpoll.c
@@ -385,7 +385,12 @@ int pa_rtpoll_run(pa_rtpoll *p, pa_bool_t wait) {
 #ifdef __linux__
     if (!p->dont_use_ppoll)
 #endif
-        r = ppoll(p->pollfd, p->n_pollfd_used, p->timer_enabled ? &timeout : NULL, p->rtsig < 0 ? NULL : &p->sigset_unblocked);
+    {
+        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
@@ -477,15 +482,20 @@ static void update_timer(pa_rtpoll *p) {
             memset(&its, 0, sizeof(its));
 
             if (p->timer_enabled) {
-                its.it_value = p->next_elapse;
+                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)
-                    pa_timespec_store(&its.it_interval, p->period);
+                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);

commit 3736246a364ab7e480924706c2e30f6fcf366f61
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sun Oct 7 13:56:07 2007 +0000

    s/timespec/timeval
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1936 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/rtp/module-rtp-recv.c b/src/modules/rtp/module-rtp-recv.c
index 62be53f..6c01893 100644
--- a/src/modules/rtp/module-rtp-recv.c
+++ b/src/modules/rtp/module-rtp-recv.c
@@ -31,6 +31,7 @@
 #include <errno.h>
 #include <string.h>
 #include <unistd.h>
+#include <poll.h>
 
 #include <pulse/timeval.h>
 #include <pulse/xmalloc.h>
@@ -161,10 +162,10 @@ static void sink_input_kill(pa_sink_input* i) {
 static int rtpoll_work_cb(pa_rtpoll_item *i) {
     pa_memchunk chunk;
     int64_t k, j, delta;
-    struct timespec now;
+    struct timeval now;
     struct session *s;
     struct pollfd *p;
-    
+
     pa_assert_se(s = pa_rtpoll_item_get_userdata(i));
 
     p = pa_rtpoll_item_get_pollfd(i, NULL);
@@ -173,12 +174,12 @@ static int rtpoll_work_cb(pa_rtpoll_item *i) {
         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;
 
@@ -234,7 +235,7 @@ static int rtpoll_work_cb(pa_rtpoll_item *i) {
 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);
 
@@ -317,7 +318,7 @@ static struct session *session_new(struct userdata *u, const pa_sdp_info *sdp_in
     int fd = -1;
     pa_memblock *silence;
     pa_sink_input_new_data data;
-    struct timespec now;
+    struct timeval now;
 
     pa_assert(u);
     pa_assert(sdp_info);
@@ -406,7 +407,7 @@ fail:
 
     if (fd >= 0)
         pa_close(fd);
-    
+
     return NULL;
 }
 
@@ -422,7 +423,7 @@ static void session_free(struct session *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);
@@ -461,10 +462,10 @@ 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 timespec now;
+            struct timeval now;
             pa_rtclock_get(&now);
             pa_atomic_store(&s->timestamp, now.tv_sec);
-            
+
             pa_sdp_info_destroy(&info);
         }
     }
@@ -473,7 +474,7 @@ static void sap_event_cb(pa_mainloop_api *m, pa_io_event *e, int fd, pa_io_event
 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 timespec now;
+    struct timeval now;
     struct timeval tv;
 
     pa_assert(m);
@@ -484,7 +485,7 @@ static void check_death_event_cb(pa_mainloop_api *m, pa_time_event *t, const str
     pa_rtclock_get(&now);
 
     pa_log_debug("Checking for dead streams ...");
-    
+
     for (s = u->sessions; s; s = n) {
         int k;
         n = s->next;
@@ -511,7 +512,7 @@ int pa__init(pa_module*m) {
     const char *sap_address;
     int fd = -1;
     struct timeval tv;
-    
+
     pa_assert(m);
 
     if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
@@ -554,7 +555,7 @@ int pa__init(pa_module*m) {
     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);
 
     return 0;
@@ -572,7 +573,7 @@ fail:
 void pa__done(pa_module*m) {
     struct userdata *u;
     struct session *s;
-    
+
     pa_assert(m);
 
     if (!(u = m->userdata))
@@ -589,7 +590,7 @@ void pa__done(pa_module*m) {
     if (u->by_origin) {
         while ((s = pa_hashmap_get_first(u->by_origin)))
             session_free(s);
-        
+
         pa_hashmap_free(u->by_origin, NULL, NULL);
     }
 

commit a687c319b7bc394e536b9386d3a3258342f23763
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sun Oct 7 13:56:50 2007 +0000

    add missing poll.h inclusion
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1937 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-oss.c b/src/modules/module-oss.c
index cb975fd..19dceef 100644
--- a/src/modules/module-oss.c
+++ b/src/modules/module-oss.c
@@ -55,6 +55,7 @@
 #include <unistd.h>
 #include <limits.h>
 #include <signal.h>
+#include <poll.h>
 
 #include <pulse/xmalloc.h>
 #include <pulse/util.h>

commit 215cac8be498ab57202c6414a824478da2b8d6e9
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sun Oct 7 13:57:20 2007 +0000

    add missing poll.h inclusion
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1938 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-pipe-sink.c b/src/modules/module-pipe-sink.c
index edacf04..41509f4 100644
--- a/src/modules/module-pipe-sink.c
+++ b/src/modules/module-pipe-sink.c
@@ -34,6 +34,7 @@
 #include <unistd.h>
 #include <limits.h>
 #include <sys/ioctl.h>
+#include <poll.h>
 
 #include <pulse/xmalloc.h>
 
@@ -67,11 +68,11 @@ struct userdata {
     pa_core *core;
     pa_module *module;
     pa_sink *sink;
-    
+
     pa_thread *thread;
     pa_thread_mq thread_mq;
     pa_rtpoll *rtpoll;
-    
+
     char *filename;
     int fd;
 
@@ -94,23 +95,23 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
     struct userdata *u = PA_SINK(o)->userdata;
 
     switch (code) {
-            
+
         case PA_SINK_MESSAGE_GET_LATENCY: {
             size_t n = 0;
             int l;
 
-#ifdef TIOCINQ            
+#ifdef TIOCINQ
             if (ioctl(u->fd, TIOCINQ, &l) >= 0 && l > 0)
                 n = (size_t) l;
 #endif
-            
+
             n += u->memchunk.length;
-            
+
             *((pa_usec_t*) data) = pa_bytes_to_usec(n, &u->sink->sample_spec);
             break;
         }
     }
-    
+
     return pa_sink_process_msg(o, code, data, offset, chunk);
 }
 
@@ -180,12 +181,12 @@ static void thread_func(void *userdata) {
             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
@@ -227,7 +228,7 @@ int pa__init(pa_module*m) {
     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));
 
     mkfifo(u->filename, 0666);
@@ -257,7 +258,7 @@ int pa__init(pa_module*m) {
     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);
@@ -291,7 +292,7 @@ fail:
 
 void pa__done(pa_module*m) {
     struct userdata *u;
-    
+
     pa_assert(m);
 
     if (!(u = m->userdata))
@@ -306,7 +307,7 @@ void pa__done(pa_module*m) {
     }
 
     pa_thread_mq_done(&u->thread_mq);
-    
+
     if (u->sink)
         pa_sink_unref(u->sink);
 
@@ -315,7 +316,7 @@ void pa__done(pa_module*m) {
 
     if (u->rtpoll_item)
         pa_rtpoll_item_free(u->rtpoll_item);
-    
+
     if (u->rtpoll)
         pa_rtpoll_free(u->rtpoll);
 

commit b0bce200f2484cd0082a081724479627377db5d0
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sun Oct 7 13:57:35 2007 +0000

    add missing poll.h inclusion
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1939 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/tests/rtpoll-test.c b/src/tests/rtpoll-test.c
index bad8e7d..3ab992a 100644
--- a/src/tests/rtpoll-test.c
+++ b/src/tests/rtpoll-test.c
@@ -24,6 +24,7 @@
 #endif
 
 #include <signal.h>
+#include <poll.h>
 
 #include <pulsecore/log.h>
 #include <pulsecore/rtpoll.h>
@@ -49,7 +50,7 @@ int main(int argc, char *argv[]) {
     struct pollfd *pollfd;
 
     pa_rtsig_configure(SIGRTMIN+10, SIGRTMAX);
-    
+
     p = pa_rtpoll_new();
 
     i = pa_rtpoll_item_new(p, PA_RTPOLL_EARLY, 1);
@@ -62,14 +63,14 @@ int main(int argc, char *argv[]) {
 
     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);
@@ -77,13 +78,13 @@ int main(int argc, char *argv[]) {
     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;

commit 2385efef61043ceef4a9a4d83a71c2d95af2d3e4
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Oct 15 14:38:16 2007 +0000

    fix url
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1940 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/configure.ac b/configure.ac
index cf9069a..f9fd12c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -34,7 +34,7 @@ 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, 11)

commit 190081782c4f3a45b641d2dcda2337a396677684
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Oct 17 16:54:46 2007 +0000

    Properly handle if ALSA sends us an POLLERR event, this should allow us to survive a system suspend cycle better
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1941 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/alsa-util.c b/src/modules/alsa-util.c
index ee2dfdb..9ea5ad1 100644
--- a/src/modules/alsa-util.c
+++ b/src/modules/alsa-util.c
@@ -56,7 +56,7 @@ 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 = userdata;
     int err, i;
     unsigned short revents;
@@ -139,7 +139,7 @@ static void defer_cb(pa_mainloop_api*a, PA_GCC_UNUSED pa_defer_event* e, void *u
     if (fdl->ios) {
         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 = NULL;
@@ -290,7 +290,7 @@ int pa_alsa_set_hw_params(snd_pcm_t *pcm_handle, pa_sample_spec *ss, uint32_t *p
     pa_assert(period_size);
 
     snd_pcm_hw_params_alloca(&hwparams);
-    
+
     buffer_size = *periods * *period_size;
 
     if ((ret = snd_pcm_hw_params_any(pcm_handle, hwparams)) < 0 ||
@@ -302,11 +302,11 @@ int pa_alsa_set_hw_params(snd_pcm_t *pcm_handle, pa_sample_spec *ss, uint32_t *p
             if ((ret = snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0)
                 goto finish;
 
-    } else if ((ret = snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) 
+    } else if ((ret = snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0)
         goto finish;
     else if (*use_mmap)
         *use_mmap = 0;
-    
+
     if ((ret = set_format(pcm_handle, hwparams, &f)) < 0)
         goto finish;
 
@@ -363,7 +363,7 @@ finish:
 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);
@@ -382,7 +382,7 @@ int pa_alsa_set_sw_params(snd_pcm_t *pcm) {
         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;
@@ -418,7 +418,7 @@ 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);
 
     pa_assert(mixer);
diff --git a/src/modules/module-alsa-sink.c b/src/modules/module-alsa-sink.c
index bb78bca..a09247f 100644
--- a/src/modules/module-alsa-sink.c
+++ b/src/modules/module-alsa-sink.c
@@ -654,6 +654,7 @@ static void thread_func(void *userdata) {
             }
 
             if (revents & (POLLERR|POLLNVAL|POLLHUP)) {
+
                 if (revents & POLLERR)
                     pa_log_warn("Got POLLERR from ALSA");
                 if (revents & POLLNVAL)
@@ -661,7 +662,34 @@ static void thread_func(void *userdata) {
                 if (revents & POLLHUP)
                     pa_log_warn("Got POLLHUP from ALSA");
 
-                goto fail;
+                /* 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;
+                }
             }
         }
     }
diff --git a/src/modules/module-alsa-source.c b/src/modules/module-alsa-source.c
index 0f19a4a..d840cac 100644
--- a/src/modules/module-alsa-source.c
+++ b/src/modules/module-alsa-source.c
@@ -636,6 +636,7 @@ static void thread_func(void *userdata) {
             }
 
             if (revents & (POLLERR|POLLNVAL|POLLHUP)) {
+
                 if (revents & POLLERR)
                     pa_log_warn("Got POLLERR from ALSA");
                 if (revents & POLLNVAL)
@@ -643,7 +644,34 @@ static void thread_func(void *userdata) {
                 if (revents & POLLHUP)
                     pa_log_warn("Got POLLHUP from ALSA");
 
-                goto fail;
+                /* 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;
+                }
             }
         }
     }

commit 925eadd9e209da3bfcfef5d06ae324fa4966ecb5
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Oct 22 21:48:16 2007 +0000

    add interleaving/deinterleaving APIs
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1942 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/sample-util.c b/src/pulsecore/sample-util.c
index 56d89c8..2177130 100644
--- a/src/pulsecore/sample-util.c
+++ b/src/pulsecore/sample-util.c
@@ -31,6 +31,7 @@
 #include <stdlib.h>
 
 #include <liboil/liboilfuncs.h>
+#include <liboil/liboil.h>
 
 #include <pulsecore/log.h>
 #include <pulsecore/macro.h>
@@ -485,3 +486,59 @@ int pa_frame_aligned(size_t l, const pa_sample_spec *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;
+        }
+    }
+}
diff --git a/src/pulsecore/sample-util.h b/src/pulsecore/sample-util.h
index 92c6e9f..0a39d5c 100644
--- a/src/pulsecore/sample-util.h
+++ b/src/pulsecore/sample-util.h
@@ -60,4 +60,7 @@ 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

commit 402950429bcafdc098309c8cb6e7dd6f5f37f650
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Oct 22 21:48:34 2007 +0000

    minor fixup
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1943 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-pipe-sink.c b/src/modules/module-pipe-sink.c
index 41509f4..7574847 100644
--- a/src/modules/module-pipe-sink.c
+++ b/src/modules/module-pipe-sink.c
@@ -174,7 +174,7 @@ static void thread_func(void *userdata) {
         /* 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, 1)) < 0)
+        if ((ret = pa_rtpoll_run(u->rtpoll, TRUE)) < 0)
             goto fail;
 
         if (ret == 0)

commit 468c13e672604fcbc33c24e9e1d0c9d9169ba1a4
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Oct 22 21:48:55 2007 +0000

    Port JACK sink module over from old core
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1944 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-jack-sink.c b/src/modules/module-jack-sink.c
index 1092aed..b0cc4b1 100644
--- a/src/modules/module-jack-sink.c
+++ b/src/modules/module-jack-sink.c
@@ -34,25 +34,39 @@
 #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/sink.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-sink-symdef.h"
 
+/* 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_DESCRIPTION("JACK Sink")
 PA_MODULE_VERSION(PACKAGE_VERSION)
 PA_MODULE_USAGE(
         "sink_name=<name of sink> "
@@ -67,7 +81,6 @@ PA_MODULE_USAGE(
 struct userdata {
     pa_core *core;
     pa_module *module;
-
     pa_sink *sink;
 
     unsigned channels;
@@ -75,19 +88,18 @@ struct userdata {
     jack_port_t* port[PA_CHANNELS_MAX];
     jack_client_t *client;
 
-    pthread_mutex_t mutex;
-    pthread_cond_t cond;
+    void *buffer[PA_CHANNELS_MAX];
 
-    void * buffer[PA_CHANNELS_MAX];
-    jack_nframes_t frames_requested;
-    int quit_requested;
+    pa_thread_mq thread_mq;
+    pa_asyncmsgq *jack_msgq;
+    pa_rtpoll *rtpoll;
+    pa_rtpoll_item *rtpoll_item;
 
-    int pipe_fd_type;
-    int pipe_fds[2];
-    pa_io_event *io_event;
+    pa_thread *thread;
 
     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,146 +112,160 @@ static const char* const valid_modargs[] = {
     NULL
 };
 
-static void stop_sink(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_sink_disconnect(u->sink);
-    pa_sink_unref(u->sink);
-    u->sink = NULL;
-    pa_module_unload_request(u->module);
-}
+enum {
+    SINK_MESSAGE_RENDER = PA_SINK_MESSAGE_MAX,
+    SINK_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 sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offset, pa_memchunk *memchunk) {
+    struct userdata *u = PA_SINK(o)->userdata;
 
-    assert(m);
-    assert(e);
-    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 SINK_MESSAGE_RENDER:
 
-    if (u->quit_requested) {
-        stop_sink(u);
-        u->quit_requested = 0;
-        return;
-    }
+            /* Handle the request from the JACK thread */
 
-    pthread_mutex_lock(&u->mutex);
+            if (u->sink->thread_info.state == PA_SINK_RUNNING) {
+                pa_memchunk chunk;
+                size_t nbytes;
+                void *p;
 
-    if (u->frames_requested > 0) {
-        unsigned fs;
-        jack_nframes_t frame_idx;
-        pa_memchunk chunk;
-        void *p;
+                pa_assert(offset > 0);
+                nbytes = offset * pa_frame_size(&u->sink->sample_spec);
 
-        fs = pa_frame_size(&u->sink->sample_spec);
+                pa_sink_render_full(u->sink, nbytes, &chunk);
 
-        pa_sink_render_full(u->sink, u->frames_requested * fs, &chunk);
-        p = pa_memblock_acquire(chunk.memblock);
+                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);
 
-        for (frame_idx = 0; frame_idx < u->frames_requested; frame_idx ++) {
-            unsigned c;
+                pa_memblock_unref(chunk.memblock);
+            } else {
+                unsigned c;
+                pa_sample_spec ss;
 
-            for (c = 0; c < u->channels; c++) {
-                float *s = ((float*) ((uint8_t*) p + chunk.index)) + (frame_idx * u->channels) + c;
-                float *d = ((float*) u->buffer[c]) + frame_idx;
+                /* Humm, we're not RUNNING, hence let's write some silence */
 
-                *d = *s;
+                ss = u->sink->sample_spec;
+                ss.channels = 1;
+
+                for (c = 0; c < u->channels; c++)
+                    pa_silence_memory(u->buffer[c], offset * pa_sample_size(&ss), &ss);
             }
-        }
 
-        pa_memblock_release(chunk.memblock);
-        pa_memblock_unref(chunk.memblock);
+            u->frames_in_buffer = offset;
+            u->saved_frame_time = * (jack_nframes_t*) data;
+            u->saved_frame_time_valid = TRUE;
 
-        u->frames_requested = 0;
+            return 0;
 
-        pthread_cond_signal(&u->cond);
-    }
+        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;
 
-    pthread_mutex_unlock(&u->mutex);
-}
+        case PA_SINK_MESSAGE_GET_LATENCY: {
+            jack_nframes_t l, ft, d;
+            size_t n;
 
-static void request_render(struct userdata *u) {
-    char c = 'x';
-    assert(u);
+            /* This is the "worst-case" latency */
+            l = jack_port_get_total_latency(u->client, u->port[0]) + u->frames_in_buffer;
 
-    assert(u->pipe_fds[1] >= 0);
-    pa_write(u->pipe_fds[1], &c, 1, &u->pipe_fd_type);
-}
+            if (u->saved_frame_time_valid) {
+                /* Adjust the worst case latency by the time that
+                 * passed since we last handed data to JACK */
 
-static void jack_shutdown(void *arg) {
-    struct userdata *u = arg;
-    assert(u);
+                ft = jack_frame_time(u->client);
+                d = ft > u->saved_frame_time ? ft - u->saved_frame_time : 0;
+                l = l > d ? l - d : 0;
+            }
 
-    u->quit_requested = 1;
-    request_render(u);
+            /* 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;
+        }
+    }
+
+    return pa_sink_process_msg(o, code, data, offset, memchunk);
 }
 
 static int jack_process(jack_nframes_t nframes, void *arg) {
     struct userdata *u = arg;
-    assert(u);
+    unsigned c;
+    jack_nframes_t frame_time;
+    pa_assert(u);
 
-    if (jack_transport_query(u->client, NULL) == JackTransportRolling) {
-        unsigned c;
+    /* We just forward the request to our other RT thread */
 
-        pthread_mutex_lock(&u->mutex);
+    for (c = 0; c < u->channels; c++)
+        pa_assert_se(u->buffer[c] = jack_port_get_buffer(u->port[c], nframes));
 
-        u->frames_requested = nframes;
+    frame_time = jack_frame_time(u->client);
 
-        for (c = 0; c < u->channels; c++) {
-            u->buffer[c] = jack_port_get_buffer(u->port[c], nframes);
-            assert(u->buffer[c]);
-        }
+    pa_assert_se(pa_asyncmsgq_send(u->jack_msgq, PA_MSGOBJECT(u->sink), SINK_MESSAGE_RENDER, &frame_time, nframes, NULL) == 0);
+    return 0;
+}
 
-        request_render(u);
+static void thread_func(void *userdata) {
+    struct userdata *u = userdata;
 
-        pthread_cond_wait(&u->cond, &u->mutex);
+    pa_assert(u);
 
-        u->frames_in_buffer = nframes;
-        u->timestamp = jack_get_current_transport_frame(u->client);
+    pa_log_debug("Thread starting up");
 
-        pthread_mutex_unlock(&u->mutex);
-    }
+    if (u->core->high_priority)
+        pa_make_realtime();
 
-    return 0;
-}
+    pa_thread_mq_install(&u->thread_mq);
+    pa_rtpoll_install(u->rtpoll);
 
-static pa_usec_t sink_get_latency_cb(pa_sink *s) {
-    struct userdata *u;
-    jack_nframes_t n, l, d;
+    for (;;) {
+        int ret;
 
-    assert(s);
-    u = s->userdata;
+        if ((ret = pa_rtpoll_run(u->rtpoll, TRUE)) < 0)
+            goto fail;
 
-    if (jack_transport_query(u->client, NULL) != JackTransportRolling)
-        return 0;
+        if (ret == 0)
+            goto finish;
+    }
 
-    n = jack_get_current_transport_frame(u->client);
+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");
+}
 
-    if (n < u->timestamp)
-        return 0;
+static void jack_error_func(const char*t) {
+    char *s;
 
-    d = n - u->timestamp;
-    l = jack_port_get_total_latency(u->client, u->port[0]) + u->frames_in_buffer;
+    s = pa_xstrndup(s, strcspn(s, "\n\r"));
+    pa_log_warn("JACK error >%s<", s);
+    pa_xfree(s);
+}
+
+static void jack_init(void *arg) {
+    struct userdata *u = arg;
 
-    if (d >= l)
-        return 0;
+    pa_log_info("JACK thread starting up.");
 
-    return pa_bytes_to_usec((l - d) * pa_frame_size(&s->sample_spec), &s->sample_spec);
+    if (u->core->high_priority)
+        pa_make_realtime();
 }
 
-static void jack_error_func(const char*t) {
-    pa_log_warn("JACK error >%s<", t);
+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->sink), SINK_MESSAGE_ON_SHUTDOWN, NULL, 0, NULL, NULL);
 }
 
-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;
@@ -252,18 +278,17 @@ 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;
     }
 
@@ -271,21 +296,23 @@ int pa__init(pa_core *c, pa_module*m) {
     client_name = pa_modargs_get_value(ma, "client_name", "PulseAudio");
 
     u = pa_xnew0(struct userdata, 1);
-    m->userdata = u;
-    u->core = c;
+    u->core = m->core;
     u->module = m;
-    u->pipe_fds[0] = u->pipe_fds[1] = -1;
-    u->pipe_fd_type = 0;
+    m->userdata = u;
+    u->saved_frame_time_valid = FALSE;
+    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);
 
-    pthread_mutex_init(&u->mutex, NULL);
-    pthread_cond_init(&u->cond, NULL);
+    /* The queue linking the JACK thread and our RT thread */
+    u->jack_msgq = pa_asyncmsgq_new(0);
 
-    if (pipe(u->pipe_fds) < 0) {
-        pa_log("pipe() failed: %s", pa_cstrerror(errno));
-        goto fail;
-    }
-
-    pa_make_nonblock_fd(u->pipe_fds[1]);
+    /* 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.");
@@ -299,16 +326,16 @@ 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.");
+        pa_log("Failed to parse channels= argument.");
         goto fail;
     }
 
     pa_channel_map_init_auto(&map, channels, PA_CHANNEL_MAP_ALSA);
-    if (pa_modargs_get_channel_map(ma, &map) < 0 || map.channels != channels) {
-        pa_log("failed to parse channel_map= argument.");
+    if (pa_modargs_get_channel_map(ma, NULL, &map) < 0 || map.channels != channels) {
+        pa_log("Failed to parse channel_map= argument.");
         goto fail;
     }
 
@@ -318,7 +345,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, JackPortIsOutput|JackPortIsTerminal, 0))) {
@@ -327,19 +354,29 @@ int pa__init(pa_core *c, pa_module*m) {
         }
     }
 
-    if (!(u->sink = pa_sink_new(c, __FILE__, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss, &map))) {
+    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->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, t = pa_sprintf_malloc("Jack sink (%s)", jack_get_client_name(u->client)));
     pa_xfree(t);
-    u->sink->get_latency = sink_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");
@@ -350,21 +387,20 @@ int pa__init(pa_core *c, pa_module*m) {
         for (i = 0, p = ports; i < ss.channels; i++, p++) {
 
             if (!*p) {
-                pa_log("not enough physical output ports, leaving unconnected.");
+                pa_log("Not enough physical output ports, leaving unconnected.");
                 break;
             }
 
-            pa_log_info("connecting %s to %s", jack_port_name(u->port[i]), *p);
+            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);
+                pa_log("Failed to connect %s to %s, leaving unconnected.", jack_port_name(u->port[i]), *p);
                 break;
             }
         }
-
     }
 
-    u->io_event = c->mainloop->io_new(c->mainloop, u->pipe_fds[0], PA_IO_EVENT_INPUT, io_event_cb, u);
+    pa_sink_put(u->sink);
 
     free(ports);
     pa_modargs_free(ma);
@@ -377,14 +413,15 @@ 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;
@@ -392,20 +429,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->sink)
+        pa_sink_unlink(u->sink);
 
-    if (u->sink) {
-        pa_sink_disconnect(u->sink);
-        pa_sink_unref(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->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->sink)
+        pa_sink_unref(u->sink);
+
+    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);
 }

commit 02adb5f32ef2fc29c1e123a82dbbe0816926b095
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Oct 22 21:49:14 2007 +0000

    enable jack sink in Makefile
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1945 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/Makefile.am b/src/Makefile.am
index ad7b652..c7bc66e 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1025,11 +1025,11 @@ modlibexec_LTLIBRARIES += \
 		module-mmkbd-evdev.la
 endif
 
-#if HAVE_JACK
-#modlibexec_LTLIBRARIES += \
-#		module-jack-sink.la \
+if HAVE_JACK
+modlibexec_LTLIBRARIES += \
+		module-jack-sink.la
 #		module-jack-source.la
-#endif
+endif
 
 if HAVE_GCONF
 modlibexec_LTLIBRARIES += \
@@ -1360,15 +1360,15 @@ module_rtp_recv_la_CFLAGS = $(AM_CFLAGS)
 
 # JACK
 
-#module_jack_sink_la_SOURCES = modules/module-jack-sink.c
-#module_jack_sink_la_LDFLAGS = -module -avoid-version
-#module_jack_sink_la_LIBADD = $(AM_LIBADD) libpulsecore.la $(JACK_LIBS)
-#module_jack_sink_la_CFLAGS = $(AM_CFLAGS) $(JACK_CFLAGS)
+module_jack_sink_la_SOURCES = modules/module-jack-sink.c
+module_jack_sink_la_LDFLAGS = -module -avoid-version
+module_jack_sink_la_LIBADD = $(AM_LIBADD) libpulsecore.la $(JACK_LIBS)
+module_jack_sink_la_CFLAGS = $(AM_CFLAGS) $(JACK_CFLAGS)
 
-#module_jack_source_la_SOURCES = modules/module-jack-source.c
-#module_jack_source_la_LDFLAGS = -module -avoid-version
-#module_jack_source_la_LIBADD = $(AM_LIBADD) libpulsecore.la $(JACK_LIBS)
-#module_jack_source_la_CFLAGS = $(AM_CFLAGS) $(JACK_CFLAGS)
+module_jack_source_la_SOURCES = modules/module-jack-source.c
+module_jack_source_la_LDFLAGS = -module -avoid-version
+module_jack_source_la_LIBADD = $(AM_LIBADD) libpulsecore.la $(JACK_LIBS)
+module_jack_source_la_CFLAGS = $(AM_CFLAGS) $(JACK_CFLAGS)
 
 # HAL
 libdbus_util_la_SOURCES = modules/dbus-util.c modules/dbus-util.h

commit 498a156a8d73b23aaab21d9639c2238dedfbd3eb
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Oct 22 22:39:51 2007 +0000

    also port over JACK source to new core
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1946 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/Makefile.am b/src/Makefile.am
index c7bc66e..fcfee4f 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1027,8 +1027,8 @@ endif
 
 if HAVE_JACK
 modlibexec_LTLIBRARIES += \
-		module-jack-sink.la
-#		module-jack-source.la
+		module-jack-sink.la \
+		module-jack-source.la
 endif
 
 if HAVE_GCONF
diff --git a/src/modules/module-jack-sink.c b/src/modules/module-jack-sink.c
index b0cc4b1..49943fa 100644
--- a/src/modules/module-jack-sink.c
+++ b/src/modules/module-jack-sink.c
@@ -293,7 +293,7 @@ int pa__init(pa_module*m) {
     }
 
     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 Sink");
 
     u = pa_xnew0(struct userdata, 1);
     u->core = m->core;
diff --git a/src/modules/module-jack-source.c b/src/modules/module-jack-source.c
index e19b218..d0124cf 100644
--- a/src/modules/module-jack-source.c
+++ b/src/modules/module-jack-source.c
@@ -34,25 +34,29 @@
 #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 +71,6 @@ PA_MODULE_USAGE(
 struct userdata {
     pa_core *core;
     pa_module *module;
-
     pa_source *source;
 
     unsigned channels;
@@ -75,19 +78,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,146 +99,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;
-        void *p;
+            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;
 
-        p = pa_memblock_acquire(chunk.memblock);
+        case PA_SOURCE_MESSAGE_GET_LATENCY: {
+            jack_nframes_t l, ft, d;
+            size_t n;
 
-        for (frame_idx = 0; frame_idx < u->frames_posted; frame_idx ++) {
-            unsigned c;
+            /* This is the "worst-case" latency */
+            l = jack_port_get_total_latency(u->client, u->port[0]);
 
-            for (c = 0; c < u->channels; c++) {
-                float *s = ((float*) u->buffer[c]) + frame_idx;
-                float *d = ((float*) ((uint8_t*) p + chunk.index)) + (frame_idx * u->channels) + c;
+            if (u->saved_frame_time_valid) {
+                /* Adjust the worst case latency by the time that
+                 * passed since we last handed data to JACK */
 
-                *d = *s;
+                ft = jack_frame_time(u->client);
+                d = ft > u->saved_frame_time ? ft - u->saved_frame_time : 0;
+                l += d;
             }
+
+            /* Convert it to usec */
+            n = l * pa_frame_size(&u->source->sample_spec);
+            *((pa_usec_t*) data) = pa_bytes_to_usec(n, &u->source->sample_spec);
+
+            return 0;
         }
+    }
+
+    return pa_source_process_msg(o, code, data, offset, chunk);
+}
 
-        pa_memblock_release(chunk.memblock);
+static int jack_process(jack_nframes_t nframes, void *arg) {
+    unsigned c;
+    struct userdata *u = arg;
+    const void *buffer[PA_CHANNELS_MAX];
+    void *p;
+    jack_nframes_t frame_time;
+    pa_memchunk chunk;
 
-        pa_source_post(u->source, &chunk);
-        pa_memblock_unref(chunk.memblock);
+    pa_assert(u);
 
-        u->frames_posted = 0;
+    for (c = 0; c < u->channels; c++)
+        pa_assert(buffer[c] = jack_port_get_buffer(u->port[c], nframes));
 
-        pthread_cond_signal(&u->cond);
-    }
+    /* We interleave the data and pass it on to the other RT thread */
 
-    pthread_mutex_unlock(&u->mutex);
-}
+    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);
 
-static void request_post(struct userdata *u) {
-    char c = 'x';
-    assert(u);
+    frame_time = jack_frame_time(u->client);
 
-    assert(u->pipe_fds[1] >= 0);
-    pa_write(u->pipe_fds[1], &c, 1, &u->pipe_fd_type);
-}
+    pa_asyncmsgq_post(u->jack_msgq, PA_MSGOBJECT(u->source), SOURCE_MESSAGE_POST, NULL, frame_time, &chunk, NULL);
 
-static void jack_shutdown(void *arg) {
-    struct userdata *u = arg;
-    assert(u);
+    pa_memblock_unref(chunk.memblock);
 
-    u->quit_requested = 1;
-    request_post(u);
+    return 0;
 }
 
-static int jack_process(jack_nframes_t nframes, void *arg) {
-    struct userdata *u = arg;
-    assert(u);
+static void thread_func(void *userdata) {
+    struct userdata *u = userdata;
 
-    if (jack_transport_query(u->client, NULL) == JackTransportRolling) {
-        unsigned c;
+    pa_assert(u);
 
-        pthread_mutex_lock(&u->mutex);
+    pa_log_debug("Thread starting up");
 
-        u->frames_posted = nframes;
+    if (u->core->high_priority)
+        pa_make_realtime();
 
-        for (c = 0; c < u->channels; c++) {
-            u->buffer[c] = jack_port_get_buffer(u->port[c], nframes);
-            assert(u->buffer[c]);
-        }
+    pa_thread_mq_install(&u->thread_mq);
+    pa_rtpoll_install(u->rtpoll);
 
-        request_post(u);
+    for (;;) {
+        int ret;
 
-        pthread_cond_wait(&u->cond, &u->mutex);
-
-        u->frames_in_buffer = nframes;
-        u->timestamp = jack_get_current_transport_frame(u->client);
+        if ((ret = pa_rtpoll_run(u->rtpoll, TRUE)) < 0)
+            goto fail;
 
-        pthread_mutex_unlock(&u->mutex);
+        if (ret == 0)
+            goto finish;
     }
 
-    return 0;
-}
-
-static pa_usec_t source_get_latency_cb(pa_source *s) {
-    struct userdata *u;
-    jack_nframes_t n, l, d;
+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);
 
-    assert(s);
-    u = s->userdata;
+finish:
+    pa_log_debug("Thread shutting down");
+}
 
-    if (jack_transport_query(u->client, NULL) != JackTransportRolling)
-        return 0;
+static void jack_error_func(const char*t) {
+    char *s;
 
-    n = jack_get_current_transport_frame(u->client);
+    s = pa_xstrndup(s, strcspn(s, "\n\r"));
+    pa_log_warn("JACK error >%s<", s);
+    pa_xfree(s);
+}
 
-    if (n < u->timestamp)
-        return 0;
+static void jack_init(void *arg) {
+    struct userdata *u = arg;
 
-    d = n - u->timestamp;
-    l = jack_port_get_total_latency(u->client, u->port[0]);
+    pa_log_info("JACK thread starting up.");
 
-    return pa_bytes_to_usec((l + d) * pa_frame_size(&s->sample_spec), &s->sample_spec);
+    if (u->core->high_priority)
+        pa_make_realtime();
 }
 
-static void jack_error_func(const char*t) {
-    pa_log_warn("JACK error >%s<", t);
+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_core *c, pa_module*m) {
+int pa__init(pa_module*m) {
     struct userdata *u = NULL;
     pa_sample_spec ss;
     pa_channel_map map;
@@ -252,40 +255,34 @@ int pa__init(pa_core *c, pa_module*m) {
     const char **ports = NULL, **p;
     char *t;
 
-    assert(c);
     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);
-
-    if (pipe(u->pipe_fds) < 0) {
-        pa_log("pipe() failed: %s", pa_cstrerror(errno));
-        goto fail;
-    }
+    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);
 
-    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.");
@@ -299,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.");
@@ -307,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;
     }
@@ -327,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");
@@ -364,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);
@@ -377,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);
+    assert(m);
 
     if (!(u = m->userdata))
         return;
@@ -392,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);
 }

commit 65b570cdaef65b978796e93062c307684a7a0af8
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Oct 23 00:07:52 2007 +0000

    properly copy error string
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1947 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-jack-sink.c b/src/modules/module-jack-sink.c
index 49943fa..5019d65 100644
--- a/src/modules/module-jack-sink.c
+++ b/src/modules/module-jack-sink.c
@@ -244,7 +244,7 @@ finish:
 static void jack_error_func(const char*t) {
     char *s;
 
-    s = pa_xstrndup(s, strcspn(s, "\n\r"));
+    s = pa_xstrndup(t, strcspn(t, "\n\r"));
     pa_log_warn("JACK error >%s<", s);
     pa_xfree(s);
 }
diff --git a/src/modules/module-jack-source.c b/src/modules/module-jack-source.c
index d0124cf..b62ebe7 100644
--- a/src/modules/module-jack-source.c
+++ b/src/modules/module-jack-source.c
@@ -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>
@@ -221,7 +220,7 @@ finish:
 static void jack_error_func(const char*t) {
     char *s;
 
-    s = pa_xstrndup(s, strcspn(s, "\n\r"));
+    s = pa_xstrndup(t, strcspn(t, "\n\r"));
     pa_log_warn("JACK error >%s<", s);
     pa_xfree(s);
 }
@@ -255,7 +254,7 @@ int pa__init(pa_module*m) {
     const char **ports = NULL, **p;
     char *t;
 
-    assert(m);
+    pa_assert(m);
 
     jack_set_error_function(jack_error_func);
 
@@ -277,6 +276,7 @@ int pa__init(pa_module*m) {
     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);
@@ -315,7 +315,7 @@ int pa__init(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))) {
@@ -391,7 +391,7 @@ fail:
 
 void pa__done(pa_module*m) {
     struct userdata *u;
-    assert(m);
+    pa_assert(m);
 
     if (!(u = m->userdata))
         return;

commit 9464b9b45f4675bb668960734c335e4404d4d49e
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Oct 23 22:50:39 2007 +0000

    add definition of PA_USEC_PER_MSEC
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1948 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulse/timeval.h b/src/pulse/timeval.h
index 60b9d08..a7d3ba3 100644
--- a/src/pulse/timeval.h
+++ b/src/pulse/timeval.h
@@ -36,6 +36,7 @@ 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;
 

commit dc987e9df842732336c529201694f10054d401cb
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Oct 23 22:55:56 2007 +0000

    add better time interpolator: use linear regression to determine gradient from
    measurements, predict a short distance ahead, and smoothen estimation function
    with 3rd degree spline interpolation.
    
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1949 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/Makefile.am b/src/Makefile.am
index fcfee4f..be55994 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -237,7 +237,8 @@ noinst_PROGRAMS = \
 		queue-test \
 		rtpoll-test \
 		sig2str-test \
-		resampler-test
+		resampler-test \
+		smoother-test
 
 if HAVE_SIGXCPU
 noinst_PROGRAMS += \
@@ -387,6 +388,11 @@ 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          #
 ###################################
@@ -716,6 +722,7 @@ libpulsecore_la_SOURCES += \
 		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
@@ -948,9 +955,9 @@ modlibexec_LTLIBRARIES += \
 		module-combine.la \
 		module-remap-sink.la \
 		module-ladspa-sink.la
-#		module-tunnel-sink.la \
-#		module-tunnel-source.la \
 #		module-esound-sink.la
+#		module-tunnel-sink.la
+#		module-tunnel-source.la
 
 # See comment at librtp.la above
 if !OS_IS_WIN32
@@ -1187,9 +1194,9 @@ module_esound_compat_spawnpid_la_SOURCES = modules/module-esound-compat-spawnpid
 module_esound_compat_spawnpid_la_LDFLAGS = -module -avoid-version
 module_esound_compat_spawnpid_la_LIBADD = $(AM_LIBADD) libpulsecore.la
 
-#module_esound_sink_la_SOURCES = modules/module-esound-sink.c
-#module_esound_sink_la_LDFLAGS = -module -avoid-version
-#module_esound_sink_la_LIBADD = $(AM_LIBADD) libpulsecore.la libiochannel.la libsocket-client.la libauthkey.la
+# module_esound_sink_la_SOURCES = modules/module-esound-sink.c
+# module_esound_sink_la_LDFLAGS = -module -avoid-version
+# module_esound_sink_la_LIBADD = $(AM_LIBADD) libpulsecore.la libiochannel.la libsocket-client.la libauthkey.la
 
 # Pipes
 
diff --git a/src/pulsecore/time-smoother.c b/src/pulsecore/time-smoother.c
new file mode 100644
index 0000000..0b3594a
--- /dev/null
+++ b/src/pulsecore/time-smoother.c
@@ -0,0 +1,317 @@
+/* $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 100
+
+/*
+ * 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 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_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->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;
+
+    return 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_assert(s);
+
+    /* First, we calculate the position we'd estimate for x, so that
+     * we can adjust our position smoothly from this one */
+    estimate(s, x, &s->ey, &s->de);
+    s->ex = x;
+
+    /* 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);
+
+    estimate(s, x, &y, NULL);
+    return y;
+}
diff --git a/src/pulsecore/time-smoother.h b/src/pulsecore/time-smoother.h
new file mode 100644
index 0000000..038b7ae
--- /dev/null
+++ b/src/pulsecore/time-smoother.h
@@ -0,0 +1,37 @@
+#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_x, pa_usec_t history_x, pa_bool_t monotonic);
+
+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);
+
+#endif
diff --git a/src/tests/smoother-test.c b/src/tests/smoother-test.c
new file mode 100644
index 0000000..ed4327e
--- /dev/null
+++ b/src/tests/smoother-test.c
@@ -0,0 +1,72 @@
+/* $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];
+
+    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;
+    }
+
+    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 && 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);
+    }
+
+}

commit 0d84e4ccb97b6dfa1c8022a93c9f3af129359140
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Oct 24 13:30:47 2007 +0000

    fix alsa mmap initialization bogosity, discovered by Jyri Sarha
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1950 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/alsa-util.c b/src/modules/alsa-util.c
index 9ea5ad1..906de58 100644
--- a/src/modules/alsa-util.c
+++ b/src/modules/alsa-util.c
@@ -298,14 +298,19 @@ int pa_alsa_set_hw_params(snd_pcm_t *pcm_handle, pa_sample_spec *ss, uint32_t *p
         goto finish;
 
     if (use_mmap && *use_mmap) {
-        if ((ret = snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_MMAP_INTERLEAVED)) < 0)
+        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;
-    else if (*use_mmap)
-        *use_mmap = 0;
 
     if ((ret = set_format(pcm_handle, hwparams, &f)) < 0)
         goto finish;

commit 81ed6e6c6f10796f7111318a7029d80bce3028dd
Author: Tanu Kaskinen <tanuk at iki.fi>
Date:   Thu Oct 25 05:36:02 2007 +0000

    A couple of comment typo fixes.
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1951 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/asyncmsgq.c b/src/pulsecore/asyncmsgq.c
index 9910f65..96b43a7 100644
--- a/src/pulsecore/asyncmsgq.c
+++ b/src/pulsecore/asyncmsgq.c
@@ -134,7 +134,7 @@ void pa_asyncmsgq_post(pa_asyncmsgq *a, pa_msgobject *object, int code, const vo
         pa_memchunk_reset(&i->memchunk);
     i->semaphore = NULL;
 
-    /* Thus mutex makes the queue multiple-writer safe. This lock is only used on the writing side */
+    /* 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);
diff --git a/src/pulsecore/asyncmsgq.h b/src/pulsecore/asyncmsgq.h
index 393bb0b..5d3867b 100644
--- a/src/pulsecore/asyncmsgq.h
+++ b/src/pulsecore/asyncmsgq.h
@@ -45,7 +45,7 @@
  *    A memchunk (may be NULL)
  *
  * There are two functions for submitting messages: _post and
- * _send. The fromer just enqueues the message asynchronously, the
+ * _send. The former just enqueues the message asynchronously, the
  * latter waits for completion, synchronously. */
 
 enum {

commit 7ccf40ee3bb2d91e6fad6e40acaa7ac9e2e1b4fb
Author: Tanu Kaskinen <tanuk at iki.fi>
Date:   Thu Oct 25 05:49:11 2007 +0000

    Add "support" for plugins that have control output ports, i.e. don't crash on them anymore (the plugins correctly assume that every port is connected to a buffer, so we connect them to a dummy buffer that isn't used anywhere).
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1952 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-ladspa-sink.c b/src/modules/module-ladspa-sink.c
index 29ca89f..0265d97 100644
--- a/src/modules/module-ladspa-sink.c
+++ b/src/modules/module-ladspa-sink.c
@@ -21,6 +21,9 @@
   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
@@ -71,6 +74,10 @@ struct userdata {
     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;
 };
 
@@ -386,8 +393,10 @@ int pa__init(pa_module*m) {
 
         } else if (LADSPA_IS_PORT_INPUT(d->PortDescriptors[p]) && LADSPA_IS_PORT_CONTROL(d->PortDescriptors[p]))
             n_control++;
-        else
-            pa_log("Cannot handle type of port %s", d->PortNames[p]);
+        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)) {
@@ -466,9 +475,15 @@ int pa__init(pa_module*m) {
         for (p = 0; p < d->PortCount; p++) {
             LADSPA_PortRangeHintDescriptor hint = d->PortRangeHints[p].HintDescriptor;
 
-            if (!LADSPA_IS_PORT_INPUT(d->PortDescriptors[p]) || !LADSPA_IS_PORT_CONTROL(d->PortDescriptors[p]))
+            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]) {

commit ca744a4ac55e5ef5d1894a0ddfd404ec237a43b6
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sat Oct 27 12:57:57 2007 +0000

    add pa_timeval_load() API
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1954 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulse/timeval.c b/src/pulse/timeval.c
index dcc0bd7..70ceb71 100644
--- a/src/pulse/timeval.c
+++ b/src/pulse/timeval.c
@@ -156,3 +156,11 @@ struct timeval* pa_timeval_store(struct timeval *tv, pa_usec_t v) {
 
     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;
+}
diff --git a/src/pulse/timeval.h b/src/pulse/timeval.h
index a7d3ba3..65a0e51 100644
--- a/src/pulse/timeval.h
+++ b/src/pulse/timeval.h
@@ -56,9 +56,12 @@ 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) PA_GCC_PURE;
 
-/** Store the specified uec value in the timeval struct */
+/** 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
 
 #endif

commit b4bb747ba70caf2675c61c7d93e700adae28e209
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sat Oct 27 12:58:24 2007 +0000

    add pa_rtclock_usec() API
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1955 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/rtclock.c b/src/pulsecore/rtclock.c
index b34e6a4..cec7124 100644
--- a/src/pulsecore/rtclock.c
+++ b/src/pulsecore/rtclock.c
@@ -93,3 +93,9 @@ pa_bool_t pa_rtclock_hrtimer(void) {
 
 #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
index 72bbd5e..f0360af 100644
--- a/src/pulsecore/rtclock.h
+++ b/src/pulsecore/rtclock.h
@@ -31,6 +31,9 @@ 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);
 

commit c4d9a2bf858e1603649352fce0551cbdcbfaad0c
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sat Oct 27 12:58:54 2007 +0000

    add missing pa_smoother destructor
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1956 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/time-smoother.c b/src/pulsecore/time-smoother.c
index 0b3594a..f8d2f91 100644
--- a/src/pulsecore/time-smoother.c
+++ b/src/pulsecore/time-smoother.c
@@ -108,6 +108,12 @@ pa_smoother* pa_smoother_new(pa_usec_t adjust_time, pa_usec_t history_time, pa_b
     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;
 
diff --git a/src/pulsecore/time-smoother.h b/src/pulsecore/time-smoother.h
index 038b7ae..8164718 100644
--- a/src/pulsecore/time-smoother.h
+++ b/src/pulsecore/time-smoother.h
@@ -30,6 +30,7 @@
 typedef struct pa_smoother pa_smoother;
 
 pa_smoother* pa_smoother_new(pa_usec_t adjust_x, pa_usec_t history_x, 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);
diff --git a/src/tests/smoother-test.c b/src/tests/smoother-test.c
index ed4327e..96acdd4 100644
--- a/src/tests/smoother-test.c
+++ b/src/tests/smoother-test.c
@@ -69,4 +69,7 @@ int main(int argc, char*argv[]) {
         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;
 }

commit 55e4a3e221ef2adbc53a7c00a2e2fade2390036e
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sat Oct 27 12:59:59 2007 +0000

    modernize pa_iochannel a bit, add pa_iochannel_get_send_fd()
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1957 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/iochannel.c b/src/pulsecore/iochannel.c
index 90136fe..01f17ab 100644
--- a/src/pulsecore/iochannel.c
+++ b/src/pulsecore/iochannel.c
@@ -58,11 +58,11 @@ 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;
 };
@@ -90,7 +90,7 @@ 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;
 
     pa_assert(m);
     pa_assert(e);
@@ -98,19 +98,19 @@ static void callback(pa_mainloop_api* m, pa_io_event *e, int fd, pa_io_event_fla
     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;
+        io->readable = TRUE;
+        changed = TRUE;
         pa_assert(e == io->input_event);
     }
 
     if ((f & PA_IO_EVENT_OUTPUT) && !io->writable) {
-        io->writable = 1;
-        changed = 1;
+        io->writable = TRUE;
+        changed = TRUE;
         pa_assert(e == io->output_event);
     }
 
@@ -136,10 +136,10 @@ 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;
 
@@ -182,19 +182,19 @@ void pa_iochannel_free(pa_iochannel*io) {
     pa_xfree(io);
 }
 
-int pa_iochannel_is_readable(pa_iochannel*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) {
+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) {
+pa_bool_t pa_iochannel_is_hungup(pa_iochannel*io) {
     pa_assert(io);
 
     return io->hungup;
@@ -208,9 +208,8 @@ ssize_t pa_iochannel_write(pa_iochannel*io, const void*data, size_t l) {
     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);
     }
 
@@ -224,9 +223,8 @@ ssize_t pa_iochannel_read(pa_iochannel*io, void*data, size_t l) {
     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,7 +233,7 @@ 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;
 
@@ -309,14 +307,14 @@ 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;
@@ -358,12 +356,12 @@ ssize_t pa_iochannel_read_with_creds(pa_iochannel*io, void*data, size_t l, pa_cr
 
                 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);
     }
 
@@ -379,10 +377,10 @@ void pa_iochannel_set_callback(pa_iochannel*io, pa_iochannel_cb_t _callback, voi
     io->userdata = userdata;
 }
 
-void pa_iochannel_set_noclose(pa_iochannel*io, int b) {
+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) {
@@ -416,3 +414,9 @@ int pa_iochannel_get_recv_fd(pa_iochannel *io) {
 
     return io->ifd;
 }
+
+int pa_iochannel_get_send_fd(pa_iochannel *io) {
+    pa_assert(io);
+
+    return io->ofd;
+}
diff --git a/src/pulsecore/iochannel.h b/src/pulsecore/iochannel.h
index 90eb963..c9794d9 100644
--- a/src/pulsecore/iochannel.h
+++ b/src/pulsecore/iochannel.h
@@ -33,6 +33,7 @@
 
 #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
@@ -58,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);
@@ -87,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
diff --git a/src/pulsecore/pstream.c b/src/pulsecore/pstream.c
index 333012c..9d32a36 100644
--- a/src/pulsecore/pstream.c
+++ b/src/pulsecore/pstream.c
@@ -217,12 +217,12 @@ 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;
-    
+
     pa_assert(p);
     pa_assert(PA_REFCNT_VALUE(p) > 0);
     pa_assert(p->defer_event == e);
     pa_assert(p->mainloop == m);
-    
+
     do_something(p);
 }
 
@@ -244,7 +244,7 @@ pa_pstream *pa_pstream_new(pa_mainloop_api *m, pa_iochannel *io, pa_mempool *poo
     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();
 
     p->write.current = NULL;
@@ -266,7 +266,7 @@ pa_pstream *pa_pstream_new(pa_mainloop_api *m, pa_iochannel *io, pa_mempool *poo
     p->revoke_callback_userdata = NULL;
     p->release_callback = NULL;
     p->release_callback_userdata = NULL;
-    
+
     p->mempool = pool;
 
     p->use_shm = 0;
@@ -335,7 +335,7 @@ void pa_pstream_send_packet(pa_pstream*p, pa_packet *packet, const pa_creds *cre
 
     if (!(i = pa_flist_pop(PA_STATIC_FLIST_GET(items))))
         i = pa_xnew(struct item_info, 1);
-    
+
     i->type = PA_PSTREAM_ITEM_PACKET;
     i->packet = pa_packet_ref(packet);
 
@@ -365,7 +365,7 @@ void pa_pstream_send_memblock(pa_pstream*p, uint32_t channel, int64_t offset, pa
     length = chunk->length;
 
     bsm = pa_mempool_block_size_max(p->mempool);
-    
+
     while (length > 0) {
         struct item_info *i;
         size_t n;
@@ -662,7 +662,7 @@ static int do_read(pa_pstream *p) {
 
 #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)
             goto fail;
@@ -970,7 +970,7 @@ void pa_pstream_unlink(pa_pstream *p) {
 
     if (p->dead)
         return;
-    
+
     p->dead = 1;
 
     if (p->import) {
@@ -991,7 +991,7 @@ void pa_pstream_unlink(pa_pstream *p) {
     if (p->defer_event) {
         p->mainloop->defer_free(p->defer_event);
         p->defer_event = NULL;
-    }    
+    }
 
     p->die_callback = NULL;
     p->drain_callback = NULL;

commit 581e7f18023682c05cb172ad06ced0c25d5e0c0f
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sat Oct 27 15:48:01 2007 +0000

    add ability to "pause" the input time temporarily. don't accidently overwrite variables we still need.
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1958 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/time-smoother.c b/src/pulsecore/time-smoother.c
index f8d2f91..6bda3df 100644
--- a/src/pulsecore/time-smoother.c
+++ b/src/pulsecore/time-smoother.c
@@ -34,7 +34,7 @@
 
 #include "time-smoother.h"
 
-#define HISTORY_MAX 100
+#define HISTORY_MAX 50
 
 /*
  * Implementation of a time smoothing algorithm to synchronize remote
@@ -63,6 +63,8 @@ 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 */
 
@@ -79,6 +81,9 @@ struct pa_smoother {
     /* 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) {
@@ -90,6 +95,7 @@ pa_smoother* pa_smoother_new(pa_usec_t adjust_time, pa_usec_t history_time, pa_b
     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;
@@ -105,6 +111,8 @@ pa_smoother* pa_smoother_new(pa_usec_t adjust_time, pa_usec_t history_time, pa_b
 
     s->abc_valid = FALSE;
 
+    s->paused = FALSE;
+
     return s;
 }
 
@@ -293,12 +301,24 @@ static void estimate(pa_smoother *s, pa_usec_t x, pa_usec_t *y, double *deriv) {
 }
 
 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, &s->ey, &s->de);
-    s->ex = x;
+    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);
@@ -317,7 +337,42 @@ 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
index 8164718..8b8512e 100644
--- a/src/pulsecore/time-smoother.h
+++ b/src/pulsecore/time-smoother.h
@@ -29,10 +29,15 @@
 
 typedef struct pa_smoother pa_smoother;
 
-pa_smoother* pa_smoother_new(pa_usec_t adjust_x, pa_usec_t history_x, pa_bool_t monotonic);
+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

commit 56804de3d384d6d2b345a53e69a488b2d4587aef
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sat Oct 27 15:48:23 2007 +0000

    minor fixups, to make the test more deterministic
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1959 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/tests/smoother-test.c b/src/tests/smoother-test.c
index 96acdd4..c0501ec 100644
--- a/src/tests/smoother-test.c
+++ b/src/tests/smoother-test.c
@@ -45,12 +45,17 @@ int main(int argc, char*argv[]) {
 
     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;

commit 87faa546c2e32e49f810e77b5e1ea1d3b990d39b
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sat Oct 27 16:16:01 2007 +0000

    minor fix to make gcc shut up
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1960 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/tests/smoother-test.c b/src/tests/smoother-test.c
index c0501ec..caa7df7 100644
--- a/src/tests/smoother-test.c
+++ b/src/tests/smoother-test.c
@@ -65,7 +65,7 @@ int main(int argc, char*argv[]) {
 
     for (x = 0, u = 0; x < PA_USEC_PER_SEC * 10; x += PA_USEC_PER_MSEC) {
 
-        while (msec[u] > 0 && msec[u]*PA_USEC_PER_MSEC < x) {
+        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;

commit 98d363c8ef6de57f6dae0c77a86291144a1f426a
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sat Oct 27 22:05:20 2007 +0000

    minor cleanup
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1961 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/rtclock.c b/src/pulsecore/rtclock.c
index cec7124..07d776e 100644
--- a/src/pulsecore/rtclock.c
+++ b/src/pulsecore/rtclock.c
@@ -44,23 +44,20 @@ pa_usec_t pa_rtclock_age(const struct timeval *tv) {
 
 struct timeval *pa_rtclock_get(struct timeval *tv) {
 #ifdef HAVE_CLOCK_GETTIME
-    static int no_monotonic = 0;
     struct timespec ts;
 
-    /* No locking or atomic ops for no_monotonic here */
-
-    if (!no_monotonic) {
 #ifdef CLOCK_MONOTONIC
-        if (clock_gettime(CLOCK_MONOTONIC, &ts) >= 0)
-            goto out;
-#endif
+    /* No locking or atomic ops for no_monotonic here */
+    static pa_bool_t no_monotonic = FALSE;
 
-        no_monotonic = 1;
-    }
+    if (!no_monotonic)
+        if (clock_gettime(CLOCK_MONOTONIC, &ts) < 0)
+            no_monotonic = TRUE;
 
-    pa_assert_se(clock_gettime(CLOCK_REALTIME, &ts) == 0);
+    if (no_monotonic)
+#endif
+        pa_assert_se(clock_gettime(CLOCK_REALTIME, &ts) == 0);
 
-out:
     pa_assert(tv);
 
     tv->tv_sec = ts.tv_sec;

commit 66dc0b44c5571d09699c62b36fe8fecacb6acca6
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sat Oct 27 22:06:20 2007 +0000

    don't use SIGRTMAX, for compatibility with valgrind which apparently uses this signal
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1962 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/daemon/main.c b/src/daemon/main.c
index c135a6b..6c9f662 100644
--- a/src/daemon/main.c
+++ b/src/daemon/main.c
@@ -615,7 +615,8 @@ int main(int argc, char *argv[]) {
         pa_log_info("Dude, your kernel stinks! The chef's recommendation today is Linux with high-resolution timers enabled!");
 
 #ifdef SIGRTMIN
-    pa_rtsig_configure(SIGRTMIN, SIGRTMAX);
+    /* 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());

commit 94cf167f40e9a4aae8e158cdd655b5b546d546fe
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sat Oct 27 22:07:21 2007 +0000

    port module-esound-sink to new core
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1963 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/configure.ac b/configure.ac
index f9fd12c..27806ce 100644
--- a/configure.ac
+++ b/configure.ac
@@ -187,7 +187,7 @@ AC_HEADER_STDC
 AC_CHECK_HEADERS([arpa/inet.h glob.h grp.h netdb.h netinet/in.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 sys/dl.h dlfcn.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
diff --git a/src/Makefile.am b/src/Makefile.am
index be55994..eee4719 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -954,8 +954,8 @@ modlibexec_LTLIBRARIES += \
 		module-esound-protocol-tcp.la \
 		module-combine.la \
 		module-remap-sink.la \
-		module-ladspa-sink.la
-#		module-esound-sink.la
+		module-ladspa-sink.la \
+		module-esound-sink.la
 #		module-tunnel-sink.la
 #		module-tunnel-source.la
 
@@ -1194,9 +1194,9 @@ module_esound_compat_spawnpid_la_SOURCES = modules/module-esound-compat-spawnpid
 module_esound_compat_spawnpid_la_LDFLAGS = -module -avoid-version
 module_esound_compat_spawnpid_la_LIBADD = $(AM_LIBADD) libpulsecore.la
 
-# module_esound_sink_la_SOURCES = modules/module-esound-sink.c
-# module_esound_sink_la_LDFLAGS = -module -avoid-version
-# module_esound_sink_la_LIBADD = $(AM_LIBADD) libpulsecore.la libiochannel.la libsocket-client.la libauthkey.la
+module_esound_sink_la_SOURCES = modules/module-esound-sink.c
+module_esound_sink_la_LDFLAGS = -module -avoid-version
+module_esound_sink_la_LIBADD = $(AM_LIBADD) libpulsecore.la libiochannel.la libsocket-client.la libauthkey.la
 
 # Pipes
 
diff --git a/src/modules/module-esound-sink.c b/src/modules/module-esound-sink.c
index faa77a5..8b46637 100644
--- a/src/modules/module-esound-sink.c
+++ b/src/modules/module-esound-sink.c
@@ -28,14 +28,23 @@
 #include <stdlib.h>
 #include <sys/stat.h>
 #include <stdio.h>
-#include <assert.h>
 #include <errno.h>
 #include <string.h>
 #include <fcntl.h>
 #include <unistd.h>
 #include <limits.h>
+#include <poll.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <sys/ioctl.h>
+
+#ifdef HAVE_LINUX_SOCKIOS_H
+#include <linux/sockios.h>
+#endif
 
 #include <pulse/xmalloc.h>
+#include <pulse/timeval.h>
 
 #include <pulsecore/core-error.h>
 #include <pulsecore/iochannel.h>
@@ -47,27 +56,37 @@
 #include <pulsecore/socket-client.h>
 #include <pulsecore/esound.h>
 #include <pulsecore/authkey.h>
+#include <pulsecore/thread-mq.h>
+#include <pulsecore/thread.h>
+#include <pulsecore/time-smoother.h>
+#include <pulsecore/rtclock.h>
+#include <pulsecore/socket-util.h>
 
 #include "module-esound-sink-symdef.h"
 
 PA_MODULE_AUTHOR("Lennart Poettering")
 PA_MODULE_DESCRIPTION("ESOUND Sink")
 PA_MODULE_VERSION(PACKAGE_VERSION)
-PA_MODULE_USAGE("sink_name=<name for the sink> server=<address> cookie=<filename>  format=<sample format> channels=<number of channels> rate=<sample rate>")
+PA_MODULE_USAGE(
+        "sink_name=<name for the sink> "
+        "server=<address> cookie=<filename>  "
+        "format=<sample format> "
+        "channels=<number of channels> "
+        "rate=<sample rate>")
 
-#define DEFAULT_SINK_NAME "esound_output"
+#define DEFAULT_SINK_NAME "esound_out"
 
 struct userdata {
     pa_core *core;
-
+    pa_module *module;
     pa_sink *sink;
-    pa_iochannel *io;
-    pa_socket_client *client;
 
-    pa_defer_event *defer_event;
+    pa_thread_mq thread_mq;
+    pa_rtpoll *rtpoll;
+    pa_rtpoll_item *rtpoll_item;
+    pa_thread *thread;
 
     pa_memchunk memchunk;
-    pa_module *module;
 
     void *write_data;
     size_t write_length, write_index;
@@ -75,12 +94,28 @@ struct userdata {
     void *read_data;
     size_t read_length, read_index;
 
-    enum { STATE_AUTH, STATE_LATENCY, STATE_RUNNING, STATE_DEAD } state;
+    enum {
+        STATE_AUTH,
+        STATE_LATENCY,
+        STATE_PREPARE,
+        STATE_RUNNING,
+        STATE_DEAD
+    } state;
 
     pa_usec_t latency;
 
     esd_format_t format;
     int32_t rate;
+
+    pa_smoother *smoother;
+    int fd;
+
+    int64_t offset;
+
+    pa_iochannel *io;
+    pa_socket_client *client;
+
+    size_t block_size;
 };
 
 static const char* const valid_modargs[] = {
@@ -93,42 +128,211 @@ static const char* const valid_modargs[] = {
     NULL
 };
 
-static void cancel(struct userdata *u) {
-    assert(u);
+enum {
+    SINK_MESSAGE_PASS_SOCKET = PA_SINK_MESSAGE_MAX
+};
 
-    u->state = STATE_DEAD;
+static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offset, pa_memchunk *chunk) {
+    struct userdata *u = PA_SINK(o)->userdata;
 
-    if (u->io) {
-        pa_iochannel_free(u->io);
-        u->io = NULL;
-    }
+    switch (code) {
 
-    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,52 +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) {
-        void *p;
-
-        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);
-        assert(u->memchunk.length);
+        pa_assert(u->fd < 0);
+        u->fd = pa_iochannel_get_send_fd(u->io);
 
-        p = pa_memblock_acquire(u->memchunk.memblock);
+        pa_iochannel_set_noclose(u->io, TRUE);
+        pa_iochannel_free(u->io);
+        u->io = NULL;
 
-        if ((r = pa_iochannel_write(u->io, (uint8_t*) p + u->memchunk.index, u->memchunk.length)) < 0) {
-            pa_memblock_release(u->memchunk.memblock);
-            pa_log("write() failed: %s", pa_cstrerror(errno));
-            return -1;
-        }
-        pa_memblock_release(u->memchunk.memblock);
+        pa_make_tcp_socket_low_delay(u->fd);
 
-        u->memchunk.index += r;
-        u->memchunk.length -= r;
+        pa_log_info("Connection authenticated, handing fd to IO thread...");
 
-        if (u->memchunk.length <= 0) {
-            pa_memblock_unref(u->memchunk.memblock);
-            u->memchunk.memblock = NULL;
-        }
+        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) {
@@ -190,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);
 
@@ -205,7 +401,7 @@ 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);
@@ -215,7 +411,7 @@ static int handle_response(struct userdata *u) {
             }
 
             /* 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;
@@ -223,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);
@@ -234,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;
@@ -252,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);
@@ -270,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) {
@@ -315,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;
@@ -350,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;
@@ -388,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);
 
@@ -410,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);
@@ -434,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);
+}

commit daa2863daf54bd34ee895d8d514bf58ab64a6af9
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sun Oct 28 16:13:25 2007 +0000

    don't use errno on EOF
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1964 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/protocol-esound.c b/src/pulsecore/protocol-esound.c
index adefaf9..76ba9dd 100644
--- a/src/pulsecore/protocol-esound.c
+++ b/src/pulsecore/protocol-esound.c
@@ -82,11 +82,11 @@ 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;
@@ -302,7 +302,7 @@ static void connection_write(connection *c, const void *data, size_t length) {
     memcpy((uint8_t*) c->write_data + i, data, length);
 }
 
-static void format_esd2native(int format, int swap_bytes, pa_sample_spec *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;
@@ -344,7 +344,7 @@ static int esd_proto_connect(connection *c, PA_GCC_UNUSED esd_proto_t request, c
             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;
@@ -355,9 +355,9 @@ static int esd_proto_connect(connection *c, PA_GCC_UNUSED esd_proto_t request, c
 
     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_warn("Client sent invalid endian key");
         return -1;
@@ -893,7 +893,7 @@ static void client_kill_cb(pa_client *c) {
 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;
@@ -948,7 +948,7 @@ static int do_read(connection *c) {
         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 (errno == EINTR || errno == EAGAIN)
+            if (r < 0 && (errno == EINTR || errno == EAGAIN))
                 return 0;
 
             pa_log_debug("read(): %s", r < 0 ? pa_cstrerror(errno) : "EOF");
@@ -978,7 +978,7 @@ static int do_read(connection *c) {
         pa_memblock_release(c->scache.memchunk.memblock);
 
         if (r <= 0) {
-            if (errno == EINTR || errno == EAGAIN)
+            if (r < 0 && (errno == EINTR || errno == EAGAIN))
                 return 0;
 
             pa_log_debug("read(): %s", r < 0 ? pa_cstrerror(errno) : "EOF");
@@ -1041,7 +1041,7 @@ static int do_read(connection *c) {
 
         if (r <= 0) {
 
-            if (errno == EINTR || errno == EAGAIN)
+            if (r < 0 && (errno == EINTR || errno == EAGAIN))
                 return 0;
 
             pa_log_debug("read(): %s", r < 0 ? pa_cstrerror(errno) : "EOF");
@@ -1072,7 +1072,7 @@ static int do_write(connection *c) {
         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 (errno == EINTR || errno == EAGAIN)
+            if (r < 0 && (errno == EINTR || errno == EAGAIN))
                 return 0;
 
             pa_log("write(): %s", pa_cstrerror(errno));
@@ -1101,7 +1101,7 @@ static int do_write(connection *c) {
 
         if (r < 0) {
 
-            if (errno == EINTR || errno == EAGAIN)
+            if (r < 0 && (errno == EINTR || errno == EAGAIN))
                 return 0;
 
             pa_log("write(): %s", pa_cstrerror(errno));
@@ -1142,7 +1142,7 @@ static void do_work(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;
@@ -1354,8 +1354,8 @@ static void on_connection(pa_socket_server*s, pa_iochannel *io, void *userdata)
     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);
@@ -1385,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) {

commit b718d18a2391726758e60862bfb6b6ee1b848daf
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sun Oct 28 16:35:09 2007 +0000

    fix error handling
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1965 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/protocol-simple.c b/src/pulsecore/protocol-simple.c
index da5f24e..64e2a81 100644
--- a/src/pulsecore/protocol-simple.c
+++ b/src/pulsecore/protocol-simple.c
@@ -69,7 +69,7 @@ typedef struct 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;
@@ -108,7 +108,7 @@ static void connection_unlink(connection *c) {
 
     if (!c->protocol)
         return;
-    
+
     if (c->sink_input) {
         pa_sink_input_unlink(c->sink_input);
         pa_sink_input_unref(c->sink_input);
@@ -130,7 +130,7 @@ static void connection_unlink(connection *c) {
         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);
@@ -141,7 +141,7 @@ static void connection_free(pa_object *o) {
     pa_assert(c);
 
     connection_unref(c);
-    
+
     if (c->playback.current_memblock)
         pa_memblock_unref(c->playback.current_memblock);
 
@@ -185,7 +185,7 @@ static int do_read(connection *c) {
 
     if (r <= 0) {
 
-        if (errno == EINTR || errno == EAGAIN)
+        if (r < 0 && (errno == EINTR || errno == EAGAIN))
             return 0;
 
         pa_log_debug("read(): %s", r == 0 ? "EOF" : pa_cstrerror(errno));
@@ -284,7 +284,7 @@ static int connection_process_msg(pa_msgobject *o, int code, void*userdata, int6
         case CONNECTION_MESSAGE_REQUEST_DATA:
             do_work(c);
             break;
-            
+
         case CONNECTION_MESSAGE_POST_DATA:
 /*             pa_log("got data %u", chunk->length); */
             pa_memblockq_push_align(c->output_memblockq, chunk);
@@ -319,7 +319,7 @@ static int sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int
             pa_memblockq_push_align(c->input_memblockq, chunk);
 
 /*             pa_log("got data, %u", pa_memblockq_get_length(c->input_memblockq)); */
-            
+
             return 0;
         }
 
@@ -634,4 +634,3 @@ void pa_protocol_simple_free(pa_protocol_simple *p) {
 
     pa_xfree(p);
 }
-
diff --git a/src/pulsecore/socket-client.c b/src/pulsecore/socket-client.c
index 6748c28..5b5bc5c 100644
--- a/src/pulsecore/socket-client.c
+++ b/src/pulsecore/socket-client.c
@@ -134,7 +134,7 @@ static void do_call(pa_socket_client *c) {
     pa_iochannel *io = NULL;
     int error;
     socklen_t lerror;
-    
+
     pa_assert(c);
     pa_assert(PA_REFCNT_VALUE(c) >= 1);
     pa_assert(c->callback);
@@ -156,7 +156,7 @@ 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;
     }
@@ -179,7 +179,7 @@ finish:
 
 static void connect_fixed_cb(pa_mainloop_api *m, pa_defer_event *e, void *userdata) {
     pa_socket_client *c = userdata;
-    
+
     pa_assert(m);
     pa_assert(c);
     pa_assert(PA_REFCNT_VALUE(c) >= 1);
@@ -196,13 +196,13 @@ static void connect_io_cb(pa_mainloop_api*m, pa_io_event *e, int fd, PA_GCC_UNUS
     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;
-    
+
     pa_assert(c);
     pa_assert(PA_REFCNT_VALUE(c) >= 1);
     pa_assert(sa);
@@ -230,15 +230,15 @@ static int do_connect(pa_socket_client *c, const struct sockaddr *sa, socklen_t
 
 pa_socket_client* pa_socket_client_new_ipv4(pa_mainloop_api *m, uint32_t address, uint16_t port) {
     struct sockaddr_in sa;
-    
+
     pa_assert(m);
     pa_assert(port > 0);
-    
+
     memset(&sa, 0, sizeof(sa));
     sa.sin_family = AF_INET;
     sa.sin_port = htons(port);
     sa.sin_addr.s_addr = htonl(address);
-    
+
     return pa_socket_client_new_sockaddr(m, (struct sockaddr*) &sa, sizeof(sa));
 }
 
@@ -246,7 +246,7 @@ 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;
-    
+
     pa_assert(m);
     pa_assert(filename);
 
@@ -307,11 +307,11 @@ 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;
-    
+
     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)
@@ -375,7 +375,7 @@ pa_socket_client* pa_socket_client_new_ipv6(pa_mainloop_api *m, uint8_t address[
     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);
@@ -390,7 +390,7 @@ 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;
-        
+
     pa_assert(m);
     pa_assert(c);
     pa_assert(PA_REFCNT_VALUE(c) >= 1);
@@ -432,7 +432,7 @@ fail:
 
 static void timeout_cb(pa_mainloop_api *m, pa_time_event *e, const struct timeval *tv, void *userdata) {
     pa_socket_client *c = userdata;
-        
+
     pa_assert(m);
     pa_assert(e);
     pa_assert(tv);
@@ -460,7 +460,7 @@ 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;
-    
+
     pa_assert(m);
     pa_assert(name);
 

commit d8976a21aadf7e998e995c5e5416a8ed3703557e
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sun Oct 28 16:45:59 2007 +0000

    Merge r1473 from trunk (mixer ioctls on /dev/dsp)
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1966 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/utils/padsp.c b/src/utils/padsp.c
index 299033e..b48af93 100644
--- a/src/utils/padsp.c
+++ b/src/utils/padsp.c
@@ -2292,7 +2292,8 @@ static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno)
             break;
 
         default:
-            debug(DEBUG_LEVEL_NORMAL, __FILE__": unknown ioctl 0x%08lx\n", request);
+            /* Mixer ioctls are valid on /dev/dsp aswell */
+            return mixer_ioctl(i, request, argp, _errno);
 
 inval:
             *_errno = EINVAL;

commit 9eb840cdee99ce4ecf835c00e32c62889ad4a561
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sun Oct 28 16:49:25 2007 +0000

    Merge r1503 from trunk: Make -no-undefined actually work (and fix up error found by it).
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1967 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/Makefile.am b/src/Makefile.am
index eee4719..28ed869 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -64,7 +64,7 @@ AM_LIBADD = $(PTHREAD_LIBS)
 AM_LDADD = $(PTHREAD_LIBS)
 
 # Only required on some platforms but defined for all to avoid errors
-AM_LDFLAGS = -no-undefined
+AM_LDFLAGS = -Wl,-no-undefined
 
 if STATIC_BINS
 BINLDFLAGS = -static
@@ -1271,7 +1271,7 @@ liboss_util_la_LIBADD = libpulsecore.la
 
 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
+module_oss_la_LIBADD = $(AM_LIBADD) libiochannel.la liboss-util.la libpulsecore.la
 
 # ALSA
 

commit c6071b05a54ed8a5d3b06af3f586fa262279bc13
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sun Oct 28 16:50:25 2007 +0000

    Merge r1505 from trunk: Make sure we link to the core to get all symbols.
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1968 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/Makefile.am b/src/Makefile.am
index 28ed869..e17e5ec 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1294,7 +1294,7 @@ module_alsa_source_la_CFLAGS = $(AM_CFLAGS) $(ASOUNDLIB_CFLAGS)
 
 module_solaris_la_SOURCES = modules/module-solaris.c
 module_solaris_la_LDFLAGS = -module -avoid-version
-module_solaris_la_LIBADD = $(AM_LIBADD) libiochannel.la
+module_solaris_la_LIBADD = $(AM_LIBADD) libiochannel.la libpulsecore.la
 
 # Avahi
 

commit f096ca40aa2a607f18683ff1bdef5468c9be23f0
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sun Oct 28 16:53:47 2007 +0000

    Merge r1504 from trunk: Solaris hides inet_ntop in nsl
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1969 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/configure.ac b/configure.ac
index 27806ce..1a817c5 100644
--- a/configure.ac
+++ b/configure.ac
@@ -253,6 +253,7 @@ AC_SEARCH_LIBS([pow], [m])
 AC_SEARCH_LIBS([sched_setscheduler], [rt])
 AC_SEARCH_LIBS([dlopen], [dl])
 AC_SEARCH_LIBS([shm_open], [rt])
+AC_SEARCH_LIBS([inet_ntop], [nsl])
 
 # BSD
 AC_SEARCH_LIBS([connect], [socket])

commit 575541d20c4c21383d0c7ba40dd3c45c2949e18a
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sun Oct 28 16:55:15 2007 +0000

    Merge r1502 from trunk: Move pthreads detection as it gets confused by things in LIBS.
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1970 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/configure.ac b/configure.ac
index 1a817c5..3a075e6 100644
--- a/configure.ac
+++ b/configure.ac
@@ -244,6 +244,10 @@ AC_CHECK_DEFINE([INADDR_NONE], [netinet/in.h], [],
     [AC_CHECK_DEFINE([INADDR_NONE], [winsock2.h], [],
         [AC_DEFINE([INADDR_NONE],  [0xffffffff], [Define INADDR_NONE if not found in <netinet/in.h>])])])
 
+#### POSIX threads ####
+
+ACX_PTHREAD
+
 #### Check for libs ####
 
 # ISO
@@ -297,10 +301,6 @@ AC_CHECK_FUNCS([lstat])
 
 AC_CHECK_FUNCS([setresuid setresgid setreuid setregid seteuid setegid ppoll strsignal sig2str strtof_l])
 
-#### POSIX threads ####
-
-ACX_PTHREAD
-
 AC_MSG_CHECKING([for PTHREAD_PRIO_INHERIT])
 AC_LANG_CONFTEST([AC_LANG_SOURCE([[
 #include <pthread.h>

commit 4d4dafbf3f03931565d6b8f47bcc0d113dda8f94
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Jan 24 01:05:24 2008 +0000

    fix CVE-2008-0008.patch
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/tags/release-0.9.9@2100 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/daemon/caps.c b/src/daemon/caps.c
index 5b4008a..44ee355 100644
--- a/src/daemon/caps.c
+++ b/src/daemon/caps.c
@@ -63,13 +63,16 @@ void pa_drop_root(void) {
     pa_log_info("Dropping root priviliges.");
 
 #if defined(HAVE_SETRESUID)
-    setresuid(uid, uid, uid);
+    pa_assert_se(setresuid(uid, uid, uid) >= 0);
 #elif defined(HAVE_SETREUID)
-    setreuid(uid, uid);
+    pa_assert_se(setreuid(uid, uid) >= 0);
 #else
-    setuid(uid);
-    seteuid(uid);
+    pa_assert_se(setuid(uid) >= 0);
+    pa_assert_se(seteuid(uid) >= 0);
 #endif
+
+    pa_assert_se(getuid() == uid);
+    pa_assert_se(geteuid() == uid);
 }
 
 #else
@@ -147,4 +150,3 @@ int pa_drop_caps(void) {
 }
 
 #endif
-

commit 90a7f3bbedb0541f1bf3067f664b9c25c20f3c0e
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Jan 24 01:06:44 2008 +0000

    bump revision
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/tags/release-0.9.9@2101 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/configure.ac b/configure.ac
index b9be19b..2c2a7a9 100644
--- a/configure.ac
+++ b/configure.ac
@@ -5,7 +5,7 @@
 
 # This file is part of PulseAudio.
 #
-# Copyright 2004-2006 Lennart Poettering
+# Copyright 2004-2008 Lennart Poettering
 # Copyright 2006-2007 Pierre Ossman <ossman at cendio.se> for Cendio AB
 #
 # PulseAudio is free software; you can redistribute it and/or modify it
@@ -26,7 +26,7 @@ AC_PREREQ(2.57)
 
 m4_define(PA_MAJOR, [0])
 m4_define(PA_MINOR, [9])
-m4_define(PA_MICRO, [8])
+m4_define(PA_MICRO, [9])
 
 AC_INIT([pulseaudio], PA_MAJOR.PA_MINOR.PA_MICRO,[mzchyfrnhqvb (at) 0pointer (dot) net])
 AC_CONFIG_SRCDIR([src/daemon/main.c])

commit 8d9bdaca5a4092cd078d79c58c4bfa0da277bff4
Merge: dd81a90... 6ad7621...
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sat Mar 15 15:15:36 2008 +0000

    really create glitch-free branch
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2120 fefdeb5f-60dc-0310-8127-8f9354f1896f


commit 347cfc356aa1c5073a5fc1d4355392759df13ab8
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sat Mar 15 15:18:55 2008 +0000

    commit glitch-free work
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2121 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulse/context.c b/src/pulse/context.c
index 7243a29..b9d9308 100644
--- a/src/pulse/context.c
+++ b/src/pulse/context.c
@@ -35,6 +35,7 @@
 #include <errno.h>
 #include <signal.h>
 #include <limits.h>
+#include <locale.h>
 
 #ifdef HAVE_SYS_WAIT_H
 #include <sys/wait.h>
@@ -52,6 +53,8 @@
 
 #include <pulse/version.h>
 #include <pulse/xmalloc.h>
+#include <pulse/utf8.h>
+#include <pulse/util.h>
 
 #include <pulsecore/winsock.h>
 #include <pulsecore/core-error.h>
@@ -108,20 +111,32 @@ static void unlock_autospawn_lock_file(pa_context *c) {
 static void context_free(pa_context *c);
 
 pa_context *pa_context_new(pa_mainloop_api *mainloop, const char *name) {
+    return pa_context_new_with_proplist(mainloop, name, NULL);
+}
+
+pa_context *pa_context_new_with_proplist(pa_mainloop_api *mainloop, const char *name, pa_proplist *p) {
     pa_context *c;
 
     pa_assert(mainloop);
-    pa_assert(name);
+
+    if (!name && !pa_proplist_contains(p, PA_PROP_APPLICATION_NAME))
+        return NULL;
 
     c = pa_xnew(pa_context, 1);
     PA_REFCNT_INIT(c);
-    c->name = pa_xstrdup(name);
+
+    c->proplist = p ? pa_proplist_copy(p) : pa_proplist_new();
+
+    if (name)
+        pa_proplist_sets(c->proplist, PA_PROP_APPLICATION_NAME, name);
+
     c->mainloop = mainloop;
     c->client = NULL;
     c->pstream = NULL;
     c->pdispatch = NULL;
     c->playback_streams = pa_dynarray_new();
     c->record_streams = pa_dynarray_new();
+    c->client_index = PA_INVALID_INDEX;
 
     PA_LLIST_HEAD_INIT(pa_stream, c->streams);
     PA_LLIST_HEAD_INIT(pa_operation, c->operations);
@@ -204,7 +219,9 @@ static void context_free(pa_context *c) {
 
     pa_strlist_free(c->server_list);
 
-    pa_xfree(c->name);
+    if (c->proplist)
+        pa_proplist_free(c->proplist);
+
     pa_xfree(c->server);
     pa_xfree(c);
 }
@@ -415,7 +432,13 @@ static void setup_complete_callback(pa_pdispatch *pd, uint32_t command, uint32_t
             }
 
             reply = pa_tagstruct_command(c, PA_COMMAND_SET_CLIENT_NAME, &tag);
-            pa_tagstruct_puts(reply, c->name);
+
+            if (c->version >= 13) {
+                pa_init_proplist(c->proplist);
+                pa_tagstruct_put_proplist(reply, c->proplist);
+            } else
+                pa_tagstruct_puts(reply, pa_proplist_gets(c->proplist, PA_PROP_APPLICATION_NAME));
+
             pa_pstream_send_tagstruct(c->pstream, reply);
             pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, setup_complete_callback, c, NULL);
 
@@ -424,11 +447,19 @@ static void setup_complete_callback(pa_pdispatch *pd, uint32_t command, uint32_t
         }
 
         case PA_CONTEXT_SETTING_NAME :
+
+            if ((c->version >= 13 && (pa_tagstruct_getu32(t, &c->client_index) < 0 ||
+                                      c->client_index == PA_INVALID_INDEX)) ||
+                !pa_tagstruct_eof(t)) {
+                pa_context_fail(c, PA_ERR_PROTOCOL);
+                goto finish;
+            }
+
             pa_context_set_state(c, PA_CONTEXT_READY);
             break;
 
         default:
-            pa_assert(0);
+            pa_assert_not_reached();
     }
 
 finish:
@@ -987,12 +1018,19 @@ pa_operation* pa_context_set_name(pa_context *c, const char *name, pa_context_su
 
     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
 
-    o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
+    if (c->version >= 13) {
+        pa_proplist *p = pa_proplist_new();
+        pa_proplist_sets(p, PA_PROP_APPLICATION_NAME, name);
+        o = pa_context_proplist_update(c, PA_UPDATE_REPLACE, p, cb, userdata);
+        pa_proplist_free(p);
 
-    t = pa_tagstruct_command(c, PA_COMMAND_SET_CLIENT_NAME, &tag);
-    pa_tagstruct_puts(t, name);
-    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);
+    } else {
+        o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
+        t = pa_tagstruct_command(c, PA_COMMAND_SET_CLIENT_NAME, &tag);
+        pa_tagstruct_puts(t, name);
+        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;
 }
@@ -1024,6 +1062,8 @@ uint32_t pa_context_get_server_protocol_version(pa_context *c) {
     pa_assert(c);
     pa_assert(PA_REFCNT_VALUE(c) >= 1);
 
+    PA_CHECK_VALIDITY_RETURN_ANY(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE, PA_INVALID_INDEX);
+
     return c->version;
 }
 
@@ -1039,3 +1079,151 @@ pa_tagstruct *pa_tagstruct_command(pa_context *c, uint32_t command, uint32_t *ta
 
     return t;
 }
+
+uint32_t pa_context_get_index(pa_context *c) {
+    pa_assert(c);
+    pa_assert(PA_REFCNT_VALUE(c) >= 1);
+
+    PA_CHECK_VALIDITY_RETURN_ANY(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE, PA_INVALID_INDEX);
+    PA_CHECK_VALIDITY_RETURN_ANY(c, c->version >= 13, PA_ERR_NOTSUPPORTED, PA_INVALID_INDEX);
+
+    return c->client_index;
+}
+
+pa_operation *pa_context_proplist_update(pa_context *c, pa_update_mode_t mode, pa_proplist *p, 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, mode == PA_UPDATE_SET || mode == PA_UPDATE_MERGE || mode == PA_UPDATE_REPLACE, PA_ERR_INVALID);
+    PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
+    PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 13, PA_ERR_NOTSUPPORTED);
+
+    o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
+
+    t = pa_tagstruct_command(c, PA_COMMAND_UPDATE_CLIENT_PROPLIST, &tag);
+    pa_tagstruct_putu32(t, (uint32_t) mode);
+    pa_tagstruct_put_proplist(t, p);
+
+    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);
+
+    /* Please note that we don't update c->proplist here, because we
+     * don't export that field */
+
+    return o;
+}
+
+pa_operation *pa_context_proplist_remove(pa_context *c, const char *const keys[], pa_context_success_cb_t cb, void *userdata) {
+    pa_operation *o;
+    pa_tagstruct *t;
+    uint32_t tag;
+    const char * const *k;
+
+    pa_assert(c);
+    pa_assert(PA_REFCNT_VALUE(c) >= 1);
+
+    PA_CHECK_VALIDITY_RETURN_NULL(c, keys && keys[0], PA_ERR_INVALID);
+    PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
+    PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 13, PA_ERR_NOTSUPPORTED);
+
+    o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
+
+    t = pa_tagstruct_command(c, PA_COMMAND_REMOVE_CLIENT_PROPLIST, &tag);
+
+    for (k = keys; *k; k++)
+        pa_tagstruct_puts(t, *k);
+
+    pa_tagstruct_puts(t, NULL);
+
+    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);
+
+    /* Please note that we don't update c->proplist here, because we
+     * don't export that field */
+
+    return o;
+}
+
+void pa_init_proplist(pa_proplist *p) {
+    int a, b;
+#ifndef HAVE_DECL_ENVIRON
+    extern char **environ;
+#endif
+    char **e;
+
+    pa_assert(p);
+
+    for (e = environ; *e; e++) {
+
+        if (pa_startswith(*e, "PULSE_PROP_")) {
+            size_t kl = strcspn(*e+11, "=");
+            char *k;
+
+            if ((*e)[11+kl] != '=')
+                continue;
+
+            if (!pa_utf8_valid(*e+11+kl+1))
+                continue;
+
+            k = pa_xstrndup(*e+11, kl);
+
+            if (pa_proplist_contains(p, k)) {
+                pa_xfree(k);
+                continue;
+            }
+
+            pa_proplist_sets(p, k, *e+11+kl+1);
+            pa_xfree(k);
+        }
+    }
+
+    if (!pa_proplist_contains(p, PA_PROP_APPLICATION_PROCESS_ID)) {
+        char t[32];
+        pa_snprintf(t, sizeof(t), "%lu", (unsigned long) getpid());
+        pa_proplist_sets(p, PA_PROP_APPLICATION_PROCESS_ID, t);
+    }
+
+    if (!pa_proplist_contains(p, PA_PROP_APPLICATION_PROCESS_USER)) {
+        char t[64];
+        if (pa_get_user_name(t, sizeof(t))) {
+            char *c = pa_utf8_filter(t);
+            pa_proplist_sets(p, PA_PROP_APPLICATION_PROCESS_USER, c);
+            pa_xfree(c);
+        }
+    }
+
+    if (!pa_proplist_contains(p, PA_PROP_APPLICATION_PROCESS_HOST)) {
+        char t[64];
+        if (pa_get_host_name(t, sizeof(t))) {
+            char *c = pa_utf8_filter(t);
+            pa_proplist_sets(p, PA_PROP_APPLICATION_PROCESS_HOST, c);
+            pa_xfree(c);
+        }
+    }
+
+    if (!(a = pa_proplist_contains(p, PA_PROP_APPLICATION_PROCESS_BINARY)) ||
+        !(b = pa_proplist_contains(p, PA_PROP_APPLICATION_NAME))) {
+        char t[PATH_MAX];
+        if (pa_get_binary_name(t, sizeof(t))) {
+            char *c = pa_utf8_filter(t);
+
+            if (!a)
+                pa_proplist_sets(p, PA_PROP_APPLICATION_PROCESS_BINARY, c);
+            if (!b)
+                pa_proplist_sets(p, PA_PROP_APPLICATION_NAME, c);
+
+            pa_xfree(c);
+        }
+    }
+
+    if (!pa_proplist_contains(p, PA_PROP_APPLICATION_LANGUAGE)) {
+        const char *l;
+
+        if ((l = setlocale(LC_MESSAGES, NULL)))
+            pa_proplist_sets(p, PA_PROP_APPLICATION_LANGUAGE, l);
+    }
+}
diff --git a/src/pulse/context.h b/src/pulse/context.h
index 1de3aba..cb2a531 100644
--- a/src/pulse/context.h
+++ b/src/pulse/context.h
@@ -30,6 +30,7 @@
 #include <pulse/mainloop-api.h>
 #include <pulse/cdecl.h>
 #include <pulse/operation.h>
+#include <pulse/proplist.h>
 
 /** \page async Asynchronous API
  *
@@ -166,9 +167,15 @@ typedef void (*pa_context_notify_cb_t)(pa_context *c, void *userdata);
 typedef void (*pa_context_success_cb_t) (pa_context *c, int success, void *userdata);
 
 /** Instantiate a new connection context with an abstract mainloop API
- * and an application name */
+ * and an application name. It is recommended to use pa_context_new_with_proplist()
+ * instead and specify some initial properties.*/
 pa_context *pa_context_new(pa_mainloop_api *mainloop, const char *name);
 
+/** Instantiate a new connection context with an abstract mainloop API
+ * and an application name, and specify the the initial client property
+ * list. \since 0.9.10 */
+pa_context *pa_context_new_with_proplist(pa_mainloop_api *mainloop, const char *name, pa_proplist *proplist);
+
 /** Decrease the reference counter of the context by one */
 void pa_context_unref(pa_context *c);
 
@@ -228,6 +235,21 @@ uint32_t pa_context_get_protocol_version(pa_context *c);
 /** Return the protocol version of the connected server. \since 0.8 */
 uint32_t pa_context_get_server_protocol_version(pa_context *c);
 
+/* Update the property list of the client, adding new entries. Please
+ * note that it is highly recommended to set as much properties
+ * initially via pa_context_new_with_proplist() as possible instead a
+ * posteriori with this function, since that information may then be
+ * used to route streams of the client to the right device. \since 0.9.10 */
+pa_operation *pa_context_proplist_update(pa_context *c, pa_update_mode_t mode, pa_proplist *p, pa_context_success_cb_t cb, void *userdata);
+
+/* Update the property list of the client, remove entries. \since 0.9.10 */
+pa_operation *pa_context_proplist_remove(pa_context *c, const char *const keys[], pa_context_success_cb_t cb, void *userdata);
+
+/** Return the client index this context is
+ * identified in the server with. This is useful for usage with the
+ * introspection functions, such as pa_context_get_client_info(). \since 0.9.10 */
+uint32_t pa_context_get_index(pa_context *s);
+
 PA_C_DECL_END
 
 #endif
diff --git a/src/pulse/def.h b/src/pulse/def.h
index dabbc5e..edda792 100644
--- a/src/pulse/def.h
+++ b/src/pulse/def.h
@@ -209,6 +209,8 @@ typedef enum pa_stream_flags {
                                      * least PA 0.9.8. It is ignored
                                      * on older servers. \since
                                      * 0.9.8 */
+    PA_STREAM_PEAK_DETECT = 2048, /**< Find peaks instead of
+                                   * resampling. \since 0.9.9 */
 } pa_stream_flags_t;
 
 /** Playback and record buffer metrics */
@@ -378,7 +380,9 @@ typedef enum pa_sink_flags {
     PA_SINK_HW_VOLUME_CTRL = 1,   /**< Supports hardware volume control */
     PA_SINK_LATENCY = 2,          /**< Supports latency querying */
     PA_SINK_HARDWARE = 4,         /**< Is a hardware sink of some kind, in contrast to "virtual"/software sinks \since 0.9.3 */
-    PA_SINK_NETWORK = 8           /**< Is a networked sink of some kind. \since 0.9.7 */
+    PA_SINK_NETWORK = 8,          /**< Is a networked sink of some kind. \since 0.9.7 */
+    PA_SINK_HW_MUTE_CTRL = 16,    /**< Supports hardware mute control \since 0.9.10 */
+    PA_SINK_DECIBEL_VOLUME = 32   /**< Volume can be translated to dB with pa_sw_volume_to_dB() \since 0.9.10 */
 } pa_sink_flags_t;
 
 /** Special source flags. \since 0.8  */
@@ -386,7 +390,9 @@ typedef enum pa_source_flags {
     PA_SOURCE_HW_VOLUME_CTRL = 1,  /**< Supports hardware volume control */
     PA_SOURCE_LATENCY = 2,         /**< Supports latency querying */
     PA_SOURCE_HARDWARE = 4,        /**< Is a hardware source of some kind, in contrast to "virtual"/software source \since 0.9.3 */
-    PA_SOURCE_NETWORK = 8          /**< Is a networked sink of some kind. \since 0.9.7 */
+    PA_SOURCE_NETWORK = 8,         /**< Is a networked sink of some kind. \since 0.9.7 */
+    PA_SOURCE_HW_MUTE_CTRL = 16,   /**< Supports hardware mute control \since 0.9.10 */
+    PA_SOURCE_DECIBEL_VOLUME = 32  /**< Volume can be translated to dB with pa_sw_volume_to_dB() \since 0.9.10 */
 } pa_source_flags_t;
 
 /** A generic free() like callback prototype */
diff --git a/src/pulse/internal.h b/src/pulse/internal.h
index 873f136..d988e1a 100644
--- a/src/pulse/internal.h
+++ b/src/pulse/internal.h
@@ -50,7 +50,7 @@
 struct pa_context {
     PA_REFCNT_DECLARE;
 
-    char *name;
+    pa_proplist *proplist;
     pa_mainloop_api* mainloop;
 
     pa_socket_client *client;
@@ -85,6 +85,8 @@ struct pa_context {
     char *server;
 
     pa_client_conf *conf;
+
+    uint32_t client_index;
 };
 
 #define PA_MAX_WRITE_INDEX_CORRECTIONS 10
@@ -102,7 +104,7 @@ struct pa_stream {
     pa_mainloop_api *mainloop;
     PA_LLIST_FIELDS(pa_stream);
 
-    char *name;
+    pa_proplist *proplist;
     pa_bool_t manual_buffer_attr;
     pa_buffer_attr buffer_attr;
     pa_sample_spec sample_spec;
@@ -226,5 +228,6 @@ pa_tagstruct *pa_tagstruct_command(pa_context *c, uint32_t command, uint32_t *ta
 
 #define PA_CHECK_VALIDITY_RETURN_NULL(context, expression, error) PA_CHECK_VALIDITY_RETURN_ANY(context, expression, error, NULL)
 
+void pa_init_proplist(pa_proplist *p);
 
 #endif
diff --git a/src/pulse/introspect.c b/src/pulse/introspect.c
index 6610a72..4b282bd 100644
--- a/src/pulse/introspect.c
+++ b/src/pulse/introspect.c
@@ -149,7 +149,9 @@ 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));
+            i.proplist = pa_proplist_new();
 
             if (pa_tagstruct_getu32(t, &i.index) < 0 ||
                 pa_tagstruct_gets(t, &i.name) < 0 ||
@@ -163,9 +165,11 @@ static void context_get_sink_info_callback(pa_pdispatch *pd, uint32_t command, P
                 pa_tagstruct_gets(t, &i.monitor_source_name) < 0 ||
                 pa_tagstruct_get_usec(t, &i.latency) < 0 ||
                 pa_tagstruct_gets(t, &i.driver) < 0 ||
-                pa_tagstruct_getu32(t, &flags) < 0) {
+                pa_tagstruct_getu32(t, &flags) < 0 ||
+                (o->context->version >= 13 && pa_tagstruct_get_proplist(t, i.proplist) < 0)) {
 
                 pa_context_fail(o->context, PA_ERR_PROTOCOL);
+                pa_proplist_free(i.proplist);
                 goto finish;
             }
 
@@ -175,6 +179,8 @@ static void context_get_sink_info_callback(pa_pdispatch *pd, uint32_t command, P
                 pa_sink_info_cb_t cb = (pa_sink_info_cb_t) o->callback;
                 cb(o->context, &i, 0, o->userdata);
             }
+
+            pa_proplist_free(i.proplist);
         }
     }
 
@@ -260,7 +266,9 @@ 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));
+            i.proplist = pa_proplist_new();
 
             if (pa_tagstruct_getu32(t, &i.index) < 0 ||
                 pa_tagstruct_gets(t, &i.name) < 0 ||
@@ -274,9 +282,11 @@ static void context_get_source_info_callback(pa_pdispatch *pd, uint32_t command,
                 pa_tagstruct_gets(t, &i.monitor_of_sink_name) < 0 ||
                 pa_tagstruct_get_usec(t, &i.latency) < 0 ||
                 pa_tagstruct_gets(t, &i.driver) < 0 ||
-                pa_tagstruct_getu32(t, &flags) < 0) {
+                pa_tagstruct_getu32(t, &flags) < 0 ||
+                (o->context->version >= 13 && pa_tagstruct_get_proplist(t, i.proplist) < 0)) {
 
                 pa_context_fail(o->context, PA_ERR_PROTOCOL);
+                pa_proplist_free(i.proplist);
                 goto finish;
             }
 
@@ -286,6 +296,8 @@ static void context_get_source_info_callback(pa_pdispatch *pd, uint32_t command,
                 pa_source_info_cb_t cb = (pa_source_info_cb_t) o->callback;
                 cb(o->context, &i, 0, o->userdata);
             }
+
+            pa_proplist_free(i.proplist);
         }
     }
 
@@ -370,13 +382,18 @@ 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));
+            i.proplist = pa_proplist_new();
 
             if (pa_tagstruct_getu32(t, &i.index) < 0 ||
                 pa_tagstruct_gets(t, &i.name) < 0 ||
                 pa_tagstruct_getu32(t, &i.owner_module) < 0 ||
-                pa_tagstruct_gets(t, &i.driver) < 0 ) {
+                pa_tagstruct_gets(t, &i.driver) < 0 ||
+                (o->context->version >= 13 && pa_tagstruct_get_proplist(t, i.proplist) < 0)) {
+
                 pa_context_fail(o->context, PA_ERR_PROTOCOL);
+                pa_proplist_free(i.proplist);
                 goto finish;
             }
 
@@ -384,6 +401,8 @@ static void context_get_client_info_callback(pa_pdispatch *pd, uint32_t command,
                 pa_client_info_cb_t cb = (pa_client_info_cb_t) o->callback;
                 cb(o->context, &i, 0, o->userdata);
             }
+
+            pa_proplist_free(i.proplist);
         }
     }
 
@@ -521,7 +540,9 @@ 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));
+            i.proplist = pa_proplist_new();
 
             if (pa_tagstruct_getu32(t, &i.index) < 0 ||
                 pa_tagstruct_gets(t, &i.name) < 0 ||
@@ -535,9 +556,11 @@ static void context_get_sink_input_info_callback(pa_pdispatch *pd, uint32_t comm
                 pa_tagstruct_get_usec(t, &i.sink_usec) < 0 ||
                 pa_tagstruct_gets(t, &i.resample_method) < 0 ||
                 pa_tagstruct_gets(t, &i.driver) < 0 ||
-                (o->context->version >= 11 && pa_tagstruct_get_boolean(t, &i.mute) < 0)) {
+                (o->context->version >= 11 && pa_tagstruct_get_boolean(t, &i.mute) < 0) ||
+                (o->context->version >= 13 && pa_tagstruct_get_proplist(t, i.proplist) < 0)) {
 
                 pa_context_fail(o->context, PA_ERR_PROTOCOL);
+                pa_proplist_free(i.proplist);
                 goto finish;
             }
 
@@ -545,6 +568,8 @@ static void context_get_sink_input_info_callback(pa_pdispatch *pd, uint32_t comm
                 pa_sink_input_info_cb_t cb = (pa_sink_input_info_cb_t) o->callback;
                 cb(o->context, &i, 0, o->userdata);
             }
+
+            pa_proplist_free(i.proplist);
         }
     }
 
@@ -608,6 +633,7 @@ static void context_get_source_output_info_callback(pa_pdispatch *pd, uint32_t c
             pa_source_output_info i;
 
             memset(&i, 0, sizeof(i));
+            i.proplist = pa_proplist_new();
 
             if (pa_tagstruct_getu32(t, &i.index) < 0 ||
                 pa_tagstruct_gets(t, &i.name) < 0 ||
@@ -619,9 +645,11 @@ static void context_get_source_output_info_callback(pa_pdispatch *pd, uint32_t c
                 pa_tagstruct_get_usec(t, &i.buffer_usec) < 0 ||
                 pa_tagstruct_get_usec(t, &i.source_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 >= 13 && pa_tagstruct_get_proplist(t, i.proplist) < 0)) {
 
                 pa_context_fail(o->context, PA_ERR_PROTOCOL);
+                pa_proplist_free(i.proplist);
                 goto finish;
             }
 
@@ -629,6 +657,8 @@ static void context_get_source_output_info_callback(pa_pdispatch *pd, uint32_t c
                 pa_source_output_info_cb_t cb = (pa_source_output_info_cb_t) o->callback;
                 cb(o->context, &i, 0, o->userdata);
             }
+
+            pa_proplist_free(i.proplist);
         }
     }
 
@@ -933,6 +963,7 @@ static void context_get_sample_info_callback(pa_pdispatch *pd, uint32_t command,
             pa_sample_info i;
 
             memset(&i, 0, sizeof(i));
+            i.proplist = pa_proplist_new();
 
             if (pa_tagstruct_getu32(t, &i.index) < 0 ||
                 pa_tagstruct_gets(t, &i.name) < 0 ||
@@ -942,7 +973,8 @@ static void context_get_sample_info_callback(pa_pdispatch *pd, uint32_t command,
                 pa_tagstruct_get_channel_map(t, &i.channel_map) < 0 ||
                 pa_tagstruct_getu32(t, &i.bytes) < 0 ||
                 pa_tagstruct_get_boolean(t, &i.lazy) < 0 ||
-                pa_tagstruct_gets(t, &i.filename) < 0) {
+                pa_tagstruct_gets(t, &i.filename) < 0 ||
+                (o->context->version >= 13 && pa_tagstruct_get_proplist(t, i.proplist) < 0)) {
 
                 pa_context_fail(o->context, PA_ERR_PROTOCOL);
                 goto finish;
@@ -952,6 +984,8 @@ static void context_get_sample_info_callback(pa_pdispatch *pd, uint32_t command,
                 pa_sample_info_cb_t cb = (pa_sample_info_cb_t) o->callback;
                 cb(o->context, &i, 0, o->userdata);
             }
+
+            pa_proplist_free(i.proplist);
         }
     }
 
diff --git a/src/pulse/introspect.h b/src/pulse/introspect.h
index c148ee5..91f738d 100644
--- a/src/pulse/introspect.h
+++ b/src/pulse/introspect.h
@@ -32,6 +32,7 @@
 #include <pulse/cdecl.h>
 #include <pulse/channelmap.h>
 #include <pulse/volume.h>
+#include <pulse/proplist.h>
 
 /** \page introspect Server Query and Control
  *
@@ -206,6 +207,11 @@
 
 PA_C_DECL_BEGIN
 
+#define PA_PORT_SPDIF "spdif"
+#define PA_PORT_ANALOG_STEREO "analog-stereo"
+#define PA_PORT_ANALOG_5_1 "analog-5-1"
+#define PA_PORT_ANALOG_4_0 "analog-4-0"
+
 /** Stores information about sinks */
 typedef struct pa_sink_info {
     const char *name;                  /**< Name of the sink */
@@ -221,6 +227,7 @@ typedef struct pa_sink_info {
     pa_usec_t latency;                 /**< Length of filled playback buffer of this sink */
     const char *driver;                /**< Driver name. \since 0.8 */
     pa_sink_flags_t flags;             /**< Flags \since 0.8 */
+    pa_proplist *proplist;             /**< Property list \since 0.9.10 */
 } pa_sink_info;
 
 /** Callback prototype for pa_context_get_sink_info_by_name() and friends */
@@ -237,7 +244,7 @@ pa_operation* pa_context_get_sink_info_list(pa_context *c, pa_sink_info_cb_t cb,
 
 /** Stores information about sources */
 typedef struct pa_source_info {
-    const char *name ;                  /**< Name of the source */
+    const char *name;                   /**< Name of the source */
     uint32_t index;                     /**< Index of the source */
     const char *description;            /**< Description of this source */
     pa_sample_spec sample_spec;         /**< Sample spec of this source */
@@ -250,6 +257,7 @@ typedef struct pa_source_info {
     pa_usec_t latency;                  /**< Length of filled record buffer of this source. \since 0.5 */
     const char *driver;                 /**< Driver name \since 0.8 */
     pa_source_flags_t flags;            /**< Flags \since 0.8 */
+    pa_proplist *proplist;              /**< Property list \since 0.9.10 */
 } pa_source_info;
 
 /** Callback prototype for pa_context_get_source_info_by_name() and friends */
@@ -306,6 +314,7 @@ typedef struct pa_client_info {
     const char *name;                    /**< Name of this client */
     uint32_t owner_module;               /**< Index of the owning module, or PA_INVALID_INDEX */
     const char *driver;                  /**< Driver name \since 0.8 */
+    pa_proplist *proplist;               /**< Property list \since 0.9.10 */
 } pa_client_info;
 
 /** Callback prototype for pa_context_get_client_info() and firends*/
@@ -332,6 +341,7 @@ typedef struct pa_sink_input_info {
     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_proplist *proplist;               /**< Property list \since 0.9.10 */
 } pa_sink_input_info;
 
 /** Callback prototype for pa_context_get_sink_input_info() and firends*/
@@ -356,6 +366,7 @@ typedef struct pa_source_output_info {
     pa_usec_t source_usec;               /**< Latency of the source device, see pa_latency_info for details. \since 0.5 */
     const char *resample_method;         /**< Thre resampling method used by this source output. \since 0.7 */
     const char *driver;                  /**< Driver name \since 0.8 */
+    pa_proplist *proplist;               /**< Property list \since 0.9.10 */
 } pa_source_output_info;
 
 /** Callback prototype for pa_context_get_source_output_info() and firends*/
@@ -423,6 +434,7 @@ typedef struct pa_sample_info {
     uint32_t bytes;                       /**< Length of this sample in bytes. \since 0.4 */
     int lazy;                             /**< Non-zero when this is a lazy cache entry. \since 0.5 */
     const char *filename;                 /**< In case this is a lazy cache entry, the filename for the sound file to be loaded on demand. \since 0.5 */
+    pa_proplist *proplist;                /**< Property list for this sample. \since 0.9.10 */
 } pa_sample_info;
 
 /** Callback prototype for pa_context_get_sample_info_by_name() and firends */
diff --git a/src/pulse/proplist.c b/src/pulse/proplist.c
index c27c9d8..31fd10d 100644
--- a/src/pulse/proplist.c
+++ b/src/pulse/proplist.c
@@ -69,16 +69,14 @@ pa_proplist* pa_proplist_new(void) {
 }
 
 void pa_proplist_free(pa_proplist* p) {
-    struct property *prop;
-
-    while ((prop = pa_hashmap_steal_first(MAKE_HASHMAP(p))))
-        property_free(prop);
+    pa_assert(p);
 
+    pa_proplist_clear(p);
     pa_hashmap_free(MAKE_HASHMAP(p), NULL, NULL);
 }
 
 /** Will accept only valid UTF-8 */
-int pa_proplist_puts(pa_proplist *p, const char *key, const char *value) {
+int pa_proplist_sets(pa_proplist *p, const char *key, const char *value) {
     struct property *prop;
     pa_bool_t add = FALSE;
 
@@ -104,7 +102,7 @@ int pa_proplist_puts(pa_proplist *p, const char *key, const char *value) {
     return 0;
 }
 
-int pa_proplist_put(pa_proplist *p, const char *key, const void *data, size_t nbytes) {
+int pa_proplist_set(pa_proplist *p, const char *key, const void *data, size_t nbytes) {
     struct property *prop;
     pa_bool_t add = FALSE;
 
@@ -175,18 +173,27 @@ int pa_proplist_get(pa_proplist *p, const char *key, const void **data, size_t *
     return 0;
 }
 
-void pa_proplist_merge(pa_proplist *p, pa_proplist *other) {
+void pa_proplist_update(pa_proplist *p, pa_update_mode_t mode, pa_proplist *other) {
     struct property *prop;
     void *state = NULL;
 
     pa_assert(p);
+    pa_assert(mode == PA_UPDATE_SET || mode == PA_UPDATE_MERGE || mode == PA_UPDATE_REPLACE);
     pa_assert(other);
 
-    while ((prop = pa_hashmap_iterate(MAKE_HASHMAP(other), &state, NULL)))
-        pa_assert_se(pa_proplist_put(p, prop->key, prop->value, prop->nbytes) == 0);
+    if (mode == PA_UPDATE_SET)
+        pa_proplist_clear(p);
+
+    while ((prop = pa_hashmap_iterate(MAKE_HASHMAP(other), &state, NULL))) {
+
+        if (mode == PA_UPDATE_MERGE && pa_proplist_contains(p, prop->key))
+            continue;
+
+        pa_assert_se(pa_proplist_set(p, prop->key, prop->value, prop->nbytes) == 0);
+    }
 }
 
-int pa_proplist_remove(pa_proplist *p, const char *key) {
+int pa_proplist_unset(pa_proplist *p, const char *key) {
     struct property *prop;
 
     pa_assert(p);
@@ -196,12 +203,30 @@ int pa_proplist_remove(pa_proplist *p, const char *key) {
         return -1;
 
     if (!(prop = pa_hashmap_remove(MAKE_HASHMAP(p), key)))
-        return -1;
+        return -2;
 
     property_free(prop);
     return 0;
 }
 
+int pa_proplist_unset_many(pa_proplist *p, const char * const keys[]) {
+    const char * const * k;
+    int n = 0;
+
+    pa_assert(p);
+    pa_assert(keys);
+
+    for (k = keys; *k; k++)
+        if (!property_name_valid(*k))
+            return -1;
+
+    for (k = keys; *k; k++)
+        if (pa_proplist_unset(p, *k) >= 0)
+            n++;
+
+    return n;
+}
+
 const char *pa_proplist_iterate(pa_proplist *p, void **state) {
     struct property *prop;
 
@@ -255,3 +280,22 @@ int pa_proplist_contains(pa_proplist *p, const char *key) {
 
     return 1;
 }
+
+void pa_proplist_clear(pa_proplist *p) {
+    struct property *prop;
+    pa_assert(p);
+
+    while ((prop = pa_hashmap_steal_first(MAKE_HASHMAP(p))))
+        property_free(prop);
+}
+
+pa_proplist* pa_proplist_copy(pa_proplist *template) {
+    pa_proplist *p;
+
+    pa_assert_se(p = pa_proplist_new());
+
+    if (template)
+        pa_proplist_update(p, PA_UPDATE_REPLACE, template);
+
+    return p;
+}
diff --git a/src/pulse/proplist.h b/src/pulse/proplist.h
index c4cf9ac..4fea23d 100644
--- a/src/pulse/proplist.h
+++ b/src/pulse/proplist.h
@@ -28,63 +28,154 @@
 
 /* Defined properties:
  *
- *    x11.xid
- *    x11.display
- *    x11.x_pointer
- *    x11.y_pointer
- *    x11.button
- *    media.name
- *    media.title
- *    media.artist
- *    media.language
+ *    media.name                    "Guns'N'Roses: Civil War"
+ *    media.title                   "Civil War"
+ *    media.artist                  "Guns'N'Roses"
+ *    media.language                "de_DE"
  *    media.filename
  *    media.icon
  *    media.icon_name
- *    media.role                    video, music, game, event, phone, production
- *    application.name
+ *    media.role                    video, music, game, event, phone, production, routing, abstract
+ *    event.id                      button-click, session-login
+ *    event.x11.display
+ *    event.x11.xid
+ *    event.x11.x_pointer
+ *    event.x11.y_pointer
+ *    event.x11.button
+ *    application.name              "Rhythmbox Media Player"
+ *    application.id                "org.gnome.rhythmbox"
  *    application.version
  *    application.icon
  *    application.icon_name
+ *    application.process.id
+ *    application.process.binary
+ *    application.process.user
+ *    application.process.host
+ *    device.string
+ *    device.api                     oss, alsa, sunaudio
+ *    device.description
+ *    device.bus_path
+ *    device.serial
+ *    device.vendor_product_id
+ *    device.class                   sound, modem, monitor
+ *    device.form_factor             laptop-speakers, external-speakers, telephone, tv-capture, webcam-capture, microphone-capture, headset
+ *    device.connector               isa, pci, usb, firewire, bluetooth
+ *    device.access_mode             mmap, mmap_rewrite, serial
+ *    device.master_device
+ *    device.buffer_size
  */
 
-#define PA_PROP_X11_XID                  "x11.xid"
-#define PA_PROP_X11_DISPLAY              "x11.display"
-#define PA_PROP_X11_X_POINTER            "x11.x_pointer"
-#define PA_PROP_X11_Y_POINTER            "x11.y_pointer"
-#define PA_PROP_X11_BUTTON               "x11.button"
-#define PA_PROP_MEDIA_NAME               "media.name"
-#define PA_PROP_MEDIA_TITLE              "media.title"
-#define PA_PROP_MEDIA_ARTIST             "media.artist"
-#define PA_PROP_MEDIA_LANGUAGE           "media.language"
-#define PA_PROP_MEDIA_FILENAME           "media.filename"
-#define PA_PROP_MEDIA_ICON               "media.icon"
-#define PA_PROP_MEDIA_ICON_NAME          "media.icon_name"
-#define PA_PROP_MEDIA_ROLE               "media.role"
-#define PA_PROP_APPLICATION_NAME         "application.name"
-#define PA_PROP_APPLICATION_VERSION      "application.version"
-#define PA_PROP_APPLICATION_ICON         "application.icon"
-#define PA_PROP_APPLICATION_ICON_NAME    "application.icon_name"
-
+#define PA_PROP_MEDIA_NAME                  "media.name"
+#define PA_PROP_MEDIA_TITLE                 "media.title"
+#define PA_PROP_MEDIA_ARTIST                "media.artist"
+#define PA_PROP_MEDIA_LANGUAGE              "media.language"
+#define PA_PROP_MEDIA_FILENAME              "media.filename"
+#define PA_PROP_MEDIA_ICON                  "media.icon"
+#define PA_PROP_MEDIA_ICON_NAME             "media.icon_name"
+#define PA_PROP_MEDIA_ROLE                  "media.role"
+#define PA_PROP_EVENT_ID                    "event.id"
+#define PA_PROP_EVENT_X11_DISPLAY           "event.x11.display"
+#define PA_PROP_EVENT_X11_XID               "event.x11.xid"
+#define PA_PROP_EVENT_MOUSE_X               "event.mouse.x"
+#define PA_PROP_EVENT_MOUSE_Y               "event.mouse.y"
+#define PA_PROP_EVENT_MOUSE_BUTTON          "event.mouse.button"
+#define PA_PROP_APPLICATION_NAME            "application.name"
+#define PA_PROP_APPLICATION_ID              "application.id"
+#define PA_PROP_APPLICATION_VERSION         "application.version"
+#define PA_PROP_APPLICATION_ICON            "application.icon"
+#define PA_PROP_APPLICATION_ICON_NAME       "application.icon_name"
+#define PA_PROP_APPLICATION_LANGUAGE        "application.language"
+#define PA_PROP_APPLICATION_PROCESS_ID      "application.process.id"
+#define PA_PROP_APPLICATION_PROCESS_BINARY  "application.process.binary"
+#define PA_PROP_APPLICATION_PROCESS_USER    "application.process.user"
+#define PA_PROP_APPLICATION_PROCESS_HOST    "application.process.host"
+#define PA_PROP_DEVICE_STRING               "device.string"
+#define PA_PROP_DEVICE_API                  "device.api"
+#define PA_PROP_DEVICE_DESCRIPTION          "device.description"
+#define PA_PROP_DEVICE_BUS_PATH             "device.bus_path"
+#define PA_PROP_DEVICE_SERIAL               "device.serial"
+#define PA_PROP_DEVICE_VENDOR_PRODUCT_ID    "device.vendor_product_id"
+#define PA_PROP_DEVICE_CLASS                "device.class"
+#define PA_PROP_DEVICE_FORM_FACTOR          "device.form_factor"
+#define PA_PROP_DEVICE_CONNECTOR            "device.connector"
+#define PA_PROP_DEVICE_ACCESS_MODE          "device.access_mode"
+#define PA_PROP_DEVICE_MASTER_DEVICE        "device.master_device"
+
+/** A property list object. Basically a dictionary with UTF-8 strings
+ * as keys and arbitrary data as values. \since 0.9.10 */
 typedef struct pa_proplist pa_proplist;
 
+/** Allocate a property list. \since 0.9.10 */
 pa_proplist* pa_proplist_new(void);
-void pa_proplist_free(pa_proplist* p);
 
-/** Will accept only valid UTF-8 */
-int pa_proplist_puts(pa_proplist *p, const char *key, const char *value);
-int pa_proplist_put(pa_proplist *p, const char *key, const void *data, size_t nbytes);
+/** Free the property list. \since 0.9.10 */
+void pa_proplist_free(pa_proplist* p);
 
-/* Will return NULL if the data is not valid UTF-8 */
+/** Append a new string entry to the property list, possibly
+ * overwriting an already existing entry with the same key. An
+ * internal copy of the data passed is made. Will accept only valid
+ * UTF-8. \since 0.9.10 */
+int pa_proplist_sets(pa_proplist *p, const char *key, const char *value);
+
+/** Append a new arbitrary data entry to the property list, possibly
+ * overwriting an already existing entry with the same key. An
+ * internal copy of the data passed is made. \since 0.9.10 */
+int pa_proplist_set(pa_proplist *p, const char *key, const void *data, size_t nbytes);
+
+/* Return a string entry for the specified key. Will return NULL if
+ * the data is not valid UTF-8. Will return a NUL-terminated string in
+ * an internally allocated buffer. The caller should make a copy of
+ * the data before accessing the property list again. \since 0.9.10*/
 const char *pa_proplist_gets(pa_proplist *p, const char *key);
-int pa_proplist_get(pa_proplist *p, const char *key, const void **data, size_t *nbytes);
 
-void pa_proplist_merge(pa_proplist *p, pa_proplist *other);
-int pa_proplist_remove(pa_proplist *p, const char *key);
+/** Return the the value for the specified key. Will return a
+ * NUL-terminated string for string entries. The pointer returned will
+ * point to an internally allocated buffer. The caller should make a
+ * copy of the data before the property list is accessed again. \since 0.9.10 */
+int pa_proplist_get(pa_proplist *p, const char *key, const void **data, size_t *nbytes);
 
+/** Update mode enum for pa_proplist_update(). \since 0.9.10 */
+typedef enum pa_update_mode {
+    PA_UPDATE_SET,  /*< Replace the entirey property list with the new one. Don't keep any of the old data around */
+    PA_UPDATE_MERGE, /*< Merge new property list into the existing one, not replacing any old entries if they share a common key with the new property list. */
+    PA_UPDATE_REPLACE /*< Merge new property list into the existing one, replacing all old entries that share a common key with  the new property list. */
+} pa_update_mode_t;
+
+/** Merge property list "other" into "p", adhering the merge mode as
+ * specified in "mode". \since 0.9.10 */
+void pa_proplist_update(pa_proplist *p, pa_update_mode_t mode, pa_proplist *other);
+
+/** Removes a single entry from the property list, identified be the
+ * specified key name. \since 0.9.10 */
+int pa_proplist_unset(pa_proplist *p, const char *key);
+
+/** Similar to pa_proplist_remove() but takes an array of keys to
+ * remove. The array should be terminated by a NULL pointer. Return -1
+ * on failure, otherwise the number of entries actually removed (which
+ * might even be 0, if there where no matching entries to
+ * remove). \since 0.9.10 */
+int pa_proplist_unset_many(pa_proplist *p, const char * const keys[]);
+
+/** Iterate through the property list. The user should allocate a
+ * state variable of type void* and initialize it with NULL. A pointer
+ * to this variable should then be passed to pa_proplist_iterate()
+ * which should be called in a loop until it returns NULL which
+ * signifies EOL. The property list should not be modified during
+ * iteration through the list. On each invication this function will
+ * return the key string for the next entry. The keys in the property
+ * list do not have any particular order. \since 0.9.10 */
 const char *pa_proplist_iterate(pa_proplist *p, void **state);
 
+/** Format the property list nicely as a human readable string. \since 0.9.10 */
 char *pa_proplist_to_string(pa_proplist *p);
 
+/** Returns 1 if an entry for the specified key is existant in the property list. \since 0.9.10 */
 int pa_proplist_contains(pa_proplist *p, const char *key);
 
+/** Remove all entries from the property list object. \since 0.9.10 */
+void pa_proplist_clear(pa_proplist *p);
+
+/** Allocate a new property list and copy over every single entry from the specific list. \since 0.9.10 */
+pa_proplist* pa_proplist_copy(pa_proplist *template);
+
 #endif
diff --git a/src/pulse/sample.c b/src/pulse/sample.c
index 27c0df0..43340f2 100644
--- a/src/pulse/sample.c
+++ b/src/pulse/sample.c
@@ -32,6 +32,7 @@
 
 #include <pulsecore/core-util.h>
 #include <pulsecore/macro.h>
+#include <pulse/timeval.h>
 
 #include "sample.h"
 
@@ -70,13 +71,13 @@ size_t pa_bytes_per_second(const pa_sample_spec *spec) {
 pa_usec_t pa_bytes_to_usec(uint64_t length, const pa_sample_spec *spec) {
     pa_assert(spec);
 
-    return (pa_usec_t) (((double) length/pa_frame_size(spec)*1000000)/spec->rate);
+    return (((pa_usec_t) (length / pa_frame_size(spec)) * PA_USEC_PER_SEC) / spec->rate);
 }
 
 size_t pa_usec_to_bytes(pa_usec_t t, const pa_sample_spec *spec) {
     pa_assert(spec);
 
-    return (size_t) (((double) t * spec->rate / 1000000))*pa_frame_size(spec);
+    return (size_t) (((t * spec->rate) / PA_USEC_PER_SEC)) * pa_frame_size(spec);
 }
 
 int pa_sample_spec_valid(const pa_sample_spec *spec) {
@@ -97,7 +98,10 @@ int pa_sample_spec_equal(const pa_sample_spec*a, const pa_sample_spec*b) {
     pa_assert(a);
     pa_assert(b);
 
-    return (a->format == b->format) && (a->rate == b->rate) && (a->channels == b->channels);
+    return
+        (a->format == b->format) &&
+        (a->rate == b->rate) &&
+        (a->channels == b->channels);
 }
 
 const char *pa_sample_format_to_string(pa_sample_format_t f) {
diff --git a/src/pulse/scache.c b/src/pulse/scache.c
index 186b0a3..24f340e 100644
--- a/src/pulse/scache.c
+++ b/src/pulse/scache.c
@@ -49,12 +49,22 @@ int pa_stream_connect_upload(pa_stream *s, size_t length) {
     pa_stream_ref(s);
 
     s->direction = PA_STREAM_UPLOAD;
+    s->flags = 0;
 
     t = pa_tagstruct_command(s->context, PA_COMMAND_CREATE_UPLOAD_STREAM, &tag);
-    pa_tagstruct_puts(t, s->name);
+
+    if (s->context->version < 13)
+        pa_tagstruct_puts(t, pa_proplist_gets(s->proplist, PA_PROP_MEDIA_NAME));
+
     pa_tagstruct_put_sample_spec(t, &s->sample_spec);
     pa_tagstruct_put_channel_map(t, &s->channel_map);
     pa_tagstruct_putu32(t, length);
+
+    if (s->context->version >= 13) {
+        pa_init_proplist(s->proplist);
+        pa_tagstruct_put_proplist(t, s->proplist);
+    }
+
     pa_pstream_send_tagstruct(s->context->pstream, t);
     pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, pa_create_stream_callback, s, NULL);
 
@@ -85,6 +95,73 @@ int pa_stream_finish_upload(pa_stream *s) {
     return 0;
 }
 
+static void play_sample_ack_callback(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
+    pa_operation *o = userdata;
+    int success = 1;
+    uint32_t idx = PA_INVALID_INDEX;
+
+    pa_assert(pd);
+    pa_assert(o);
+    pa_assert(PA_REFCNT_VALUE(o) >= 1);
+
+    if (!o->context)
+        goto finish;
+
+    if (command != PA_COMMAND_REPLY) {
+        if (pa_context_handle_error(o->context, command, t) < 0)
+            goto finish;
+
+        success = 0;
+    } else if ((o->context->version >= 13 && pa_tagstruct_getu32(t, &idx) < 0) ||
+               !pa_tagstruct_eof(t)) {
+        pa_context_fail(o->context, PA_ERR_PROTOCOL);
+        goto finish;
+    } else if (o->context->version >= 13 && idx == PA_INVALID_INDEX)
+        success = 0;
+
+    if (o->callback) {
+        pa_context_success_cb_t cb = (pa_context_success_cb_t) o->callback;
+        cb(o->context, success, o->userdata);
+    }
+
+finish:
+    pa_operation_done(o);
+    pa_operation_unref(o);
+}
+
+static void play_sample_with_proplist_ack_callback(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
+    pa_operation *o = userdata;
+    uint32_t idx;
+
+    pa_assert(pd);
+    pa_assert(o);
+    pa_assert(PA_REFCNT_VALUE(o) >= 1);
+
+    if (!o->context)
+        goto finish;
+
+    if (command != PA_COMMAND_REPLY) {
+        if (pa_context_handle_error(o->context, command, t) < 0)
+            goto finish;
+
+        idx = PA_INVALID_INDEX;
+    } else if (pa_tagstruct_getu32(t, &idx) < 0 ||
+               !pa_tagstruct_eof(t)) {
+        pa_context_fail(o->context, PA_ERR_PROTOCOL);
+        goto finish;
+    }
+
+    if (o->callback) {
+        pa_context_play_sample_cb_t cb = (pa_context_play_sample_cb_t) o->callback;
+        cb(o->context, idx, o->userdata);
+    }
+
+finish:
+    pa_operation_done(o);
+    pa_operation_unref(o);
+}
+
+
 pa_operation *pa_context_play_sample(pa_context *c, const char *name, const char *dev, pa_volume_t volume, pa_context_success_cb_t cb, void *userdata) {
     pa_operation *o;
     pa_tagstruct *t;
@@ -107,8 +184,47 @@ pa_operation *pa_context_play_sample(pa_context *c, const char *name, const char
     pa_tagstruct_puts(t, dev);
     pa_tagstruct_putu32(t, volume);
     pa_tagstruct_puts(t, name);
+
+    if (c->version >= 13) {
+        pa_proplist *p = pa_proplist_new();
+        pa_tagstruct_put_proplist(t, p);
+        pa_proplist_free(p);
+    }
+
     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);
+    pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, play_sample_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
+
+    return o;
+}
+
+pa_operation *pa_context_play_sample_with_proplist(pa_context *c, const char *name, const char *dev, pa_volume_t volume, pa_proplist *p, pa_context_play_sample_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, name && *name, PA_ERR_INVALID);
+    PA_CHECK_VALIDITY_RETURN_NULL(c, !dev || *dev, PA_ERR_INVALID);
+    PA_CHECK_VALIDITY_RETURN_NULL(c, p, PA_ERR_INVALID);
+    PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 13, PA_ERR_NOTSUPPORTED);
+
+    o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
+
+    if (!dev)
+        dev = c->conf->default_sink;
+
+    t = pa_tagstruct_command(c, PA_COMMAND_PLAY_SAMPLE, &tag);
+    pa_tagstruct_putu32(t, PA_INVALID_INDEX);
+    pa_tagstruct_puts(t, dev);
+    pa_tagstruct_putu32(t, volume);
+    pa_tagstruct_puts(t, name);
+    pa_tagstruct_put_proplist(t, p);
+
+    pa_pstream_send_tagstruct(c->pstream, t);
+    pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, play_sample_with_proplist_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
 
     return o;
 }
@@ -128,9 +244,9 @@ pa_operation* pa_context_remove_sample(pa_context *c, const char *name, pa_conte
 
     t = pa_tagstruct_command(c, PA_COMMAND_REMOVE_SAMPLE, &tag);
     pa_tagstruct_puts(t, name);
+
     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;
 }
-
diff --git a/src/pulse/scache.h b/src/pulse/scache.h
index 31fd895..a9e0ce8 100644
--- a/src/pulse/scache.h
+++ b/src/pulse/scache.h
@@ -79,14 +79,25 @@
 
 PA_C_DECL_BEGIN
 
+/** Callback prototype for pa_context_play_sample_with_proplist(). The
+ * idx value is the index of the sink input object, or
+ * PA_INVALID_INDEX on failure. \since 0.9.10*/
+typedef void (*pa_context_play_sample_cb_t)(pa_context *c, uint32_t idx, void *userdata);
+
 /** Make this stream a sample upload stream */
 int pa_stream_connect_upload(pa_stream *s, size_t length);
 
-/** Finish the sample upload, the stream name will become the sample name. You cancel a samp
- * le upload by issuing pa_stream_disconnect() */
+/** Finish the sample upload, the stream name will become the sample
+ * name. You cancel a sample upload by issuing
+ * pa_stream_disconnect() */
 int pa_stream_finish_upload(pa_stream *s);
 
-/** Play a sample from the sample cache to the specified device. If the latter is NULL use the default sink. Returns an operation object */
+/** Remove a sample from the sample cache. Returns an operation object which may be used to cancel the operation while it is running */
+pa_operation* pa_context_remove_sample(pa_context *c, const char *name, pa_context_success_cb_t cb, void *userdata);
+
+/** Play a sample from the sample cache to the specified device. If
+ * the latter is NULL use the default sink. Returns an operation
+ * object */
 pa_operation* pa_context_play_sample(
         pa_context *c               /**< Context */,
         const char *name            /**< Name of the sample to play */,
@@ -95,8 +106,18 @@ pa_operation* pa_context_play_sample(
         pa_context_success_cb_t cb  /**< Call this function after successfully starting playback, or NULL */,
         void *userdata              /**< Userdata to pass to the callback */);
 
-/** Remove a sample from the sample cache. Returns an operation object which may be used to cancel the operation while it is running */
-pa_operation* pa_context_remove_sample(pa_context *c, const char *name, pa_context_success_cb_t, void *userdata);
+/** Play a sample from the sample cache to the specified device,
+ * allowing specification of a property list for the playback
+ * stream. If the latter is NULL use the default sink. Returns an
+ * operation object. \since 0.9.10 */
+pa_operation* pa_context_play_sample_with_proplist(
+        pa_context *c                   /**< Context */,
+        const char *name                /**< Name of the sample to play */,
+        const char *dev                 /**< Sink to play this sample on */,
+        pa_volume_t volume              /**< Volume to play this sample with */ ,
+        pa_proplist *proplist           /**< Property list for this sound. The property list of the cached entry will be merged into this property list */,
+        pa_context_play_sample_cb_t cb  /**< Call this function after successfully starting playback, or NULL */,
+        void *userdata                  /**< Userdata to pass to the callback */);
 
 PA_C_DECL_END
 
diff --git a/src/pulse/stream.c b/src/pulse/stream.c
index c44323f..321f222 100644
--- a/src/pulse/stream.c
+++ b/src/pulse/stream.c
@@ -44,6 +44,10 @@
 #define LATENCY_IPOL_INTERVAL_USEC (100000L)
 
 pa_stream *pa_stream_new(pa_context *c, const char *name, const pa_sample_spec *ss, const pa_channel_map *map) {
+    return pa_stream_new_with_proplist(c, name, ss, map, NULL);
+}
+
+pa_stream *pa_stream_new_with_proplist(pa_context *c, const char *name, const pa_sample_spec *ss, const pa_channel_map *map, pa_proplist *p) {
     pa_stream *s;
     int i;
     pa_channel_map tmap;
@@ -54,6 +58,7 @@ pa_stream *pa_stream_new(pa_context *c, const char *name, const pa_sample_spec *
     PA_CHECK_VALIDITY_RETURN_NULL(c, ss && pa_sample_spec_valid(ss), PA_ERR_INVALID);
     PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 12 || (ss->format != PA_SAMPLE_S32LE || ss->format != PA_SAMPLE_S32NE), PA_ERR_NOTSUPPORTED);
     PA_CHECK_VALIDITY_RETURN_NULL(c, !map || (pa_channel_map_valid(map) && map->channels == ss->channels), PA_ERR_INVALID);
+    PA_CHECK_VALIDITY_RETURN_NULL(c, name || pa_proplist_contains(p, PA_PROP_MEDIA_NAME), PA_ERR_INVALID);
 
     if (!map)
         PA_CHECK_VALIDITY_RETURN_NULL(c, map = pa_channel_map_init_auto(&tmap, ss->channels, PA_CHANNEL_MAP_DEFAULT), PA_ERR_INVALID);
@@ -83,11 +88,15 @@ pa_stream *pa_stream_new(pa_context *c, const char *name, const pa_sample_spec *
     s->suspended_userdata = NULL;
 
     s->direction = PA_STREAM_NODIRECTION;
-    s->name = pa_xstrdup(name);
     s->sample_spec = *ss;
     s->channel_map = *map;
     s->flags = 0;
 
+    s->proplist = p ? pa_proplist_copy(p) : pa_proplist_new();
+
+    if (name)
+        pa_proplist_sets(c->proplist, PA_PROP_MEDIA_NAME, name);
+
     s->channel = 0;
     s->channel_valid = 0;
     s->syncid = c->csyncid++;
@@ -151,7 +160,9 @@ static void stream_free(pa_stream *s) {
     if (s->record_memblockq)
         pa_memblockq_free(s->record_memblockq);
 
-    pa_xfree(s->name);
+    if (s->proplist)
+        pa_proplist_free(s->proplist);
+
     pa_xfree(s->device_name);
     pa_xfree(s);
 }
@@ -653,6 +664,7 @@ void pa_create_stream_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED
                 pa_frame_size(&s->sample_spec),
                 1,
                 0,
+                0,
                 NULL);
     }
 
@@ -692,19 +704,29 @@ static int create_stream(
 
     pa_assert(s);
     pa_assert(PA_REFCNT_VALUE(s) >= 1);
+    pa_assert(direction == PA_STREAM_PLAYBACK || direction == PA_STREAM_RECORD);
 
     PA_CHECK_VALIDITY(s->context, s->state == PA_STREAM_UNCONNECTED, PA_ERR_BADSTATE);
-    PA_CHECK_VALIDITY(s->context, !(flags & ~((direction != PA_STREAM_UPLOAD ?
-                                               PA_STREAM_START_CORKED|
-                                               PA_STREAM_INTERPOLATE_TIMING|
-                                               PA_STREAM_NOT_MONOTONOUS|
-                                               PA_STREAM_AUTO_TIMING_UPDATE|
-                                               PA_STREAM_NO_REMAP_CHANNELS|
-                                               PA_STREAM_NO_REMIX_CHANNELS|
-                                               PA_STREAM_FIX_FORMAT|
-                                               PA_STREAM_FIX_RATE|
-                                               PA_STREAM_FIX_CHANNELS|
-                                               PA_STREAM_DONT_MOVE : 0))), PA_ERR_INVALID);
+    PA_CHECK_VALIDITY(s->context, !(flags & ~(PA_STREAM_START_CORKED|
+                                              PA_STREAM_INTERPOLATE_TIMING|
+                                              PA_STREAM_NOT_MONOTONOUS|
+                                              PA_STREAM_AUTO_TIMING_UPDATE|
+                                              PA_STREAM_NO_REMAP_CHANNELS|
+                                              PA_STREAM_NO_REMIX_CHANNELS|
+                                              PA_STREAM_FIX_FORMAT|
+                                              PA_STREAM_FIX_RATE|
+                                              PA_STREAM_FIX_CHANNELS|
+                                              PA_STREAM_DONT_MOVE|
+                                              PA_STREAM_VARIABLE_RATE|
+                                              PA_STREAM_PEAK_DETECT)), PA_ERR_INVALID);
+
+    PA_CHECK_VALIDITY(s->context, s->context->version >= 12 || !(flags & PA_STREAM_VARIABLE_RATE), PA_ERR_NOTSUPPORTED);
+    PA_CHECK_VALIDITY(s->context, s->context->version >= 13 || !(flags & PA_STREAM_PEAK_DETECT), PA_ERR_NOTSUPPORTED);
+    /* Althought some of the other flags are not supported on older
+     * version, we don't check for them here, because it doesn't hurt
+     * when they are passed but actually not supported. This makes
+     * client development easier */
+
     PA_CHECK_VALIDITY(s->context, !volume || volume->channels == s->sample_spec.channels, PA_ERR_INVALID);
     PA_CHECK_VALIDITY(s->context, !sync_stream || (direction == PA_STREAM_PLAYBACK && sync_stream->direction == PA_STREAM_PLAYBACK), PA_ERR_INVALID);
 
@@ -737,9 +759,11 @@ static int create_stream(
             s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_CREATE_PLAYBACK_STREAM : PA_COMMAND_CREATE_RECORD_STREAM,
             &tag);
 
+    if (s->context->version < 13)
+        pa_tagstruct_puts(t, pa_proplist_gets(s->proplist, PA_PROP_MEDIA_NAME));
+
     pa_tagstruct_put(
             t,
-            PA_TAG_STRING, s->name,
             PA_TAG_SAMPLE_SPEC, &s->sample_spec,
             PA_TAG_CHANNEL_MAP, &s->channel_map,
             PA_TAG_U32, PA_INVALID_INDEX,
@@ -766,7 +790,7 @@ static int create_stream(
     } else
         pa_tagstruct_putu32(t, s->buffer_attr.fragsize);
 
-    if (s->context->version >= 12 && s->direction != PA_STREAM_UPLOAD) {
+    if (s->context->version >= 12) {
         pa_tagstruct_put(
                 t,
                 PA_TAG_BOOLEAN, flags & PA_STREAM_NO_REMAP_CHANNELS,
@@ -779,6 +803,17 @@ static int create_stream(
                 PA_TAG_INVALID);
     }
 
+    if (s->context->version >= 13) {
+
+        pa_init_proplist(s->proplist);
+
+        pa_tagstruct_put(
+                t,
+                PA_TAG_BOOLEAN, flags & PA_STREAM_PEAK_DETECT,
+                PA_TAG_PROPLIST, s->proplist,
+                PA_TAG_INVALID);
+    }
+
     pa_pstream_send_tagstruct(s->context->pstream, t);
     pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, pa_create_stream_callback, s, NULL);
 
@@ -1835,5 +1870,72 @@ pa_operation *pa_stream_update_sample_rate(pa_stream *s, uint32_t rate, pa_strea
     pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, stream_update_sample_rate_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
 
     return o;
+}
 
+pa_operation *pa_stream_proplist_update(pa_stream *s, pa_update_mode_t mode, pa_proplist *p, pa_stream_success_cb_t cb, void *userdata) {
+    pa_operation *o;
+    pa_tagstruct *t;
+    uint32_t tag;
+
+    pa_assert(s);
+    pa_assert(PA_REFCNT_VALUE(s) >= 1);
+
+    PA_CHECK_VALIDITY_RETURN_NULL(s->context, mode == PA_UPDATE_SET || mode == PA_UPDATE_MERGE || mode == PA_UPDATE_REPLACE, PA_ERR_INVALID);
+    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);
+    PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->context->version >= 13, PA_ERR_NOTSUPPORTED);
+
+    o = pa_operation_new(s->context, s, (pa_operation_cb_t) cb, userdata);
+
+    t = pa_tagstruct_command(
+            s->context,
+            s->direction == PA_STREAM_RECORD ? PA_COMMAND_UPDATE_RECORD_STREAM_PROPLIST : PA_COMMAND_UPDATE_PLAYBACK_STREAM_PROPLIST,
+            &tag);
+    pa_tagstruct_putu32(t, s->channel);
+    pa_tagstruct_putu32(t, (uint32_t) mode);
+    pa_tagstruct_put_proplist(t, p);
+
+    pa_pstream_send_tagstruct(s->context->pstream, t);
+    pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, pa_stream_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
+
+    /* Please note that we don't update s->proplist here, because we
+     * don't export that field */
+
+    return o;
+}
+
+pa_operation *pa_stream_proplist_remove(pa_stream *s, const char *const keys[], pa_stream_success_cb_t cb, void *userdata) {
+    pa_operation *o;
+    pa_tagstruct *t;
+    uint32_t tag;
+    const char * const*k;
+
+    pa_assert(s);
+    pa_assert(PA_REFCNT_VALUE(s) >= 1);
+
+    PA_CHECK_VALIDITY_RETURN_NULL(s->context, keys && keys[0], PA_ERR_INVALID);
+    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);
+    PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->context->version >= 13, PA_ERR_NOTSUPPORTED);
+
+    o = pa_operation_new(s->context, s, (pa_operation_cb_t) cb, userdata);
+
+    t = pa_tagstruct_command(
+            s->context,
+            s->direction == PA_STREAM_RECORD ? PA_COMMAND_REMOVE_RECORD_STREAM_PROPLIST : PA_COMMAND_REMOVE_PLAYBACK_STREAM_PROPLIST,
+            &tag);
+    pa_tagstruct_putu32(t, s->channel);
+
+    for (k = keys; *k; k++)
+        pa_tagstruct_puts(t, *k);
+
+    pa_tagstruct_puts(t, NULL);
+
+    pa_pstream_send_tagstruct(s->context->pstream, t);
+    pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, pa_stream_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
+
+    /* Please note that we don't update s->proplist here, because we
+     * don't export that field */
+
+    return o;
 }
diff --git a/src/pulse/stream.h b/src/pulse/stream.h
index 8547322..de7c967 100644
--- a/src/pulse/stream.h
+++ b/src/pulse/stream.h
@@ -276,13 +276,25 @@ typedef void (*pa_stream_request_cb_t)(pa_stream *p, size_t bytes, void *userdat
 /** A generic notification callback */
 typedef void (*pa_stream_notify_cb_t)(pa_stream *p, void *userdata);
 
-/** Create a new, unconnected stream with the specified name and sample type */
+/** Create a new, unconnected stream with the specified name and
+ * sample type. It is recommended to use pa_stream_new_with_proplist()
+ * instead and specify some initial properties. */
 pa_stream* pa_stream_new(
         pa_context *c                     /**< The context to create this stream in */,
         const char *name                  /**< A name for this stream */,
         const pa_sample_spec *ss          /**< The desired sample format */,
         const pa_channel_map *map         /**< The desired channel map, or NULL for default */);
 
+/** Create a new, unconnected stream with the specified name and
+ * sample type, and specify the the initial stream property
+ * list. \since 0.9.10 */
+pa_stream* pa_stream_new_with_proplist(
+        pa_context *c                     /**< The context to create this stream in */,
+        const char *name                  /**< A name for this stream */,
+        const pa_sample_spec *ss          /**< The desired sample format */,
+        const pa_channel_map *map         /**< The desired channel map, or NULL for default */,
+        pa_proplist *p                    /**< The initial property list */);
+
 /** Decrease the reference counter by one */
 void pa_stream_unref(pa_stream *s);
 
@@ -510,6 +522,17 @@ pa_operation *pa_stream_set_buffer_attr(pa_stream *s, const pa_buffer_attr *attr
  * is at least PulseAudio 0.9.8. \since 0.9.8 */
 pa_operation *pa_stream_update_sample_rate(pa_stream *s, uint32_t rate, pa_stream_success_cb_t cb, void *userdata);
 
+/* Update the property list of the sink input/source output of this
+ * stream, adding new entries. Please note that it is highly
+ * recommended to set as much properties initially via
+ * pa_stream_new_with_proplist() as possible instead a posteriori with
+ * this function, since that information may then be used to route
+ * this stream to the right device. \since 0.9.10 */
+pa_operation *pa_stream_proplist_update(pa_stream *s, pa_update_mode_t mode, pa_proplist *p, pa_stream_success_cb_t cb, void *userdata);
+
+/* Update the property list of the sink input/source output of this stream, remove entries. \since 0.9.10 */
+pa_operation *pa_stream_proplist_remove(pa_stream *s, const char *const keys[], pa_stream_success_cb_t cb, void *userdata);
+
 PA_C_DECL_END
 
 #endif
diff --git a/src/pulse/volume.h b/src/pulse/volume.h
index 22e5b8a..004e88c 100644
--- a/src/pulse/volume.h
+++ b/src/pulse/volume.h
@@ -101,10 +101,10 @@ PA_C_DECL_BEGIN
 typedef uint32_t pa_volume_t;
 
 /** Normal volume (100%) */
-#define PA_VOLUME_NORM (0x10000)
+#define PA_VOLUME_NORM ((pa_volume_t) 0x10000)
 
 /** Muted volume (0%) */
-#define PA_VOLUME_MUTED (0)
+#define PA_VOLUME_MUTED ((pa_volume_t) 0)
 
 /** A structure encapsulating a per-channel volume */
 typedef struct pa_cvolume {

commit 12c01e942d23bd477e14b467e66352e6ce0557a9
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sat Mar 15 15:19:40 2008 +0000

    commit glitch-free work
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2122 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/asyncmsgq.h b/src/pulsecore/asyncmsgq.h
index 5d3867b..575f760 100644
--- a/src/pulsecore/asyncmsgq.h
+++ b/src/pulsecore/asyncmsgq.h
@@ -56,6 +56,7 @@ 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);
diff --git a/src/pulsecore/cli-command.c b/src/pulsecore/cli-command.c
index 3110a27..73b6619 100644
--- a/src/pulsecore/cli-command.c
+++ b/src/pulsecore/cli-command.c
@@ -779,6 +779,7 @@ static int pa_cli_command_scache_list(pa_core *c, pa_tokenizer *t, pa_strbuf *bu
 static int pa_cli_command_scache_play(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
     const char *n, *sink_name;
     pa_sink *sink;
+    uint32_t idx;
 
     pa_core_assert_ref(c);
     pa_assert(t);
@@ -795,11 +796,13 @@ static int pa_cli_command_scache_play(pa_core *c, pa_tokenizer *t, pa_strbuf *bu
         return -1;
     }
 
-    if (pa_scache_play_item(c, n, sink, PA_VOLUME_NORM) < 0) {
+    if (pa_scache_play_item(c, n, sink, PA_VOLUME_NORM, NULL, &idx) < 0) {
         pa_strbuf_puts(buf, "Failed to play sample.\n");
         return -1;
     }
 
+    pa_strbuf_printf(buf, "Playing on sink input #%i\n", idx);
+
     return 0;
 }
 
diff --git a/src/pulsecore/cli-text.c b/src/pulsecore/cli-text.c
index b64cafe..8bb567b 100644
--- a/src/pulsecore/cli-text.c
+++ b/src/pulsecore/cli-text.c
@@ -41,6 +41,7 @@
 #include <pulsecore/core-scache.h>
 #include <pulsecore/autoload.h>
 #include <pulsecore/macro.h>
+#include <pulsecore/core-util.h>
 
 #include "cli-text.h"
 
@@ -78,10 +79,20 @@ char *pa_client_list_to_string(pa_core *c) {
     pa_strbuf_printf(s, "%u client(s) logged in.\n", pa_idxset_size(c->clients));
 
     for (client = pa_idxset_first(c->clients, &idx); client; client = pa_idxset_next(c->clients, &idx)) {
-        pa_strbuf_printf(s, "    index: %u\n\tname: <%s>\n\tdriver: <%s>\n", client->index, client->name, client->driver);
+        char *t;
+        pa_strbuf_printf(
+                s,
+                "    index: %u\n"
+                "\tdriver: <%s>\n",
+                client->index,
+                client->driver);
 
-        if (client->owner)
-            pa_strbuf_printf(s, "\towner module: <%u>\n", client->owner->index);
+        if (client->module)
+            pa_strbuf_printf(s, "\towner module: <%u>\n", client->module->index);
+
+        t = pa_proplist_to_string(client->proplist);
+        pa_strbuf_printf(s, "\tproperties:\n%s", t);
+        pa_xfree(t);
     }
 
     return pa_strbuf_tostring_free(s);
@@ -92,6 +103,7 @@ char *pa_sink_list_to_string(pa_core *c) {
     pa_sink *sink;
     uint32_t idx = PA_IDXSET_INVALID;
     static const char* const state_table[] = {
+        [PA_SINK_INIT] = "INIT",
         [PA_SINK_RUNNING] = "RUNNING",
         [PA_SINK_SUSPENDED] = "SUSPENDED",
         [PA_SINK_IDLE] = "IDLE",
@@ -104,14 +116,14 @@ char *pa_sink_list_to_string(pa_core *c) {
     pa_strbuf_printf(s, "%u sink(s) available.\n", pa_idxset_size(c->sinks));
 
     for (sink = pa_idxset_first(c->sinks, &idx); sink; sink = pa_idxset_next(c->sinks, &idx)) {
-        char ss[PA_SAMPLE_SPEC_SNPRINT_MAX], cv[PA_CVOLUME_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX];
+        char ss[PA_SAMPLE_SPEC_SNPRINT_MAX], cv[PA_CVOLUME_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX], *t;
 
         pa_strbuf_printf(
             s,
             "  %c index: %u\n"
             "\tname: <%s>\n"
             "\tdriver: <%s>\n"
-            "\tflags: %s%s%s%s\n"
+            "\tflags: %s%s%s%s%s%s\n"
             "\tstate: %s\n"
             "\tvolume: <%s>\n"
             "\tmute: <%i>\n"
@@ -125,7 +137,9 @@ char *pa_sink_list_to_string(pa_core *c) {
             sink->index,
             sink->name,
             sink->driver,
+            sink->flags & PA_SINK_HW_MUTE_CTRL ? "HW_MUTE_CTRL " : "",
             sink->flags & PA_SINK_HW_VOLUME_CTRL ? "HW_VOLUME_CTRL " : "",
+            sink->flags & PA_SINK_DECIBEL_VOLUME ? "DECIBEL_VOLUME " : "",
             sink->flags & PA_SINK_LATENCY ? "LATENCY " : "",
             sink->flags & PA_SINK_HARDWARE ? "HARDWARE " : "",
             sink->flags & PA_SINK_NETWORK ? "NETWORK " : "",
@@ -141,8 +155,10 @@ char *pa_sink_list_to_string(pa_core *c) {
 
         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);
+
+        t = pa_proplist_to_string(sink->proplist);
+        pa_strbuf_printf(s, "\tproperties:\n%s", t);
+        pa_xfree(t);
     }
 
     return pa_strbuf_tostring_free(s);
@@ -153,6 +169,7 @@ char *pa_source_list_to_string(pa_core *c) {
     pa_source *source;
     uint32_t idx = PA_IDXSET_INVALID;
     static const char* const state_table[] = {
+        [PA_SOURCE_INIT] = "INIT",
         [PA_SOURCE_RUNNING] = "RUNNING",
         [PA_SOURCE_SUSPENDED] = "SUSPENDED",
         [PA_SOURCE_IDLE] = "IDLE",
@@ -165,15 +182,14 @@ char *pa_source_list_to_string(pa_core *c) {
     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], cv[PA_CVOLUME_SNPRINT_MAX];
-
+        char ss[PA_SAMPLE_SPEC_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX], cv[PA_CVOLUME_SNPRINT_MAX], *t;
 
         pa_strbuf_printf(
             s,
             "  %c index: %u\n"
             "\tname: <%s>\n"
             "\tdriver: <%s>\n"
-            "\tflags: %s%s%s%s\n"
+            "\tflags: %s%s%s%s%s%s\n"
             "\tstate: %s\n"
             "\tvolume: <%s>\n"
             "\tmute: <%u>\n"
@@ -186,7 +202,9 @@ char *pa_source_list_to_string(pa_core *c) {
             source->index,
             source->name,
             source->driver,
+            source->flags & PA_SOURCE_HW_MUTE_CTRL ? "HW_MUTE_CTRL " : "",
             source->flags & PA_SOURCE_HW_VOLUME_CTRL ? "HW_VOLUME_CTRL " : "",
+            source->flags & PA_SOURCE_DECIBEL_VOLUME ? "DECIBEL_VOLUME " : "",
             source->flags & PA_SOURCE_LATENCY ? "LATENCY " : "",
             source->flags & PA_SOURCE_HARDWARE ? "HARDWARE " : "",
             source->flags & PA_SOURCE_NETWORK ? "NETWORK " : "",
@@ -203,8 +221,10 @@ char *pa_source_list_to_string(pa_core *c) {
             pa_strbuf_printf(s, "\tmonitor_of: <%u>\n", source->monitor_of->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);
+
+        t = pa_proplist_to_string(source->proplist);
+        pa_strbuf_printf(s, "\tproperties:\n%s", t);
+        pa_xfree(t);
     }
 
     return pa_strbuf_tostring_free(s);
@@ -216,6 +236,7 @@ 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[] = {
+        [PA_SOURCE_OUTPUT_INIT] = "INIT",
         [PA_SOURCE_OUTPUT_RUNNING] = "RUNNING",
         [PA_SOURCE_OUTPUT_CORKED] = "CORKED",
         [PA_SOURCE_OUTPUT_UNLINKED] = "UNLINKED"
@@ -227,16 +248,15 @@ char *pa_source_output_list_to_string(pa_core *c) {
     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];
+        char ss[PA_SAMPLE_SPEC_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX], *t;
 
         pa_assert(o->source);
 
         pa_strbuf_printf(
             s,
             "    index: %u\n"
-            "\tname: '%s'\n"
             "\tdriver: <%s>\n"
-            "\tflags: %s%s%s%s%s%s%s\n"
+            "\tflags: %s%s%s%s%s%s%s%s\n"
             "\tstate: %s\n"
             "\tsource: <%u> '%s'\n"
             "\tlatency: <%0.0f usec>\n"
@@ -244,10 +264,10 @@ char *pa_source_output_list_to_string(pa_core *c) {
             "\tchannel map: <%s>\n"
             "\tresample method: %s\n",
             o->index,
-            o->name,
             o->driver,
             o->flags & PA_SOURCE_OUTPUT_VARIABLE_RATE ? "VARIABLE_RATE " : "",
             o->flags & PA_SOURCE_OUTPUT_DONT_MOVE ? "DONT_MOVE " : "",
+            o->flags & PA_SOURCE_OUTPUT_START_CORKED ? "START_CORKED " : "",
             o->flags & PA_SOURCE_OUTPUT_NO_REMAP ? "NO_REMAP " : "",
             o->flags & PA_SOURCE_OUTPUT_NO_REMIX ? "NO_REMIX " : "",
             o->flags & PA_SOURCE_OUTPUT_FIX_FORMAT ? "FIX_FORMAT " : "",
@@ -262,7 +282,11 @@ char *pa_source_output_list_to_string(pa_core *c) {
         if (o->module)
             pa_strbuf_printf(s, "\towner module: <%u>\n", o->module->index);
         if (o->client)
-            pa_strbuf_printf(s, "\tclient: <%u> '%s'\n", o->client->index, o->client->name);
+            pa_strbuf_printf(s, "\tclient: <%u> '%s'\n", o->client->index, pa_strnull(pa_proplist_gets(o->client->proplist, PA_PROP_APPLICATION_NAME)));
+
+        t = pa_proplist_to_string(o->proplist);
+        pa_strbuf_printf(s, "\tproperties:\n%s", t);
+        pa_xfree(t);
     }
 
     return pa_strbuf_tostring_free(s);
@@ -273,6 +297,7 @@ 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[] = {
+        [PA_SINK_INPUT_INIT] = "INIT",
         [PA_SINK_INPUT_RUNNING] = "RUNNING",
         [PA_SINK_INPUT_DRAINED] = "DRAINED",
         [PA_SINK_INPUT_CORKED] = "CORKED",
@@ -285,16 +310,15 @@ char *pa_sink_input_list_to_string(pa_core *c) {
     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];
+        char ss[PA_SAMPLE_SPEC_SNPRINT_MAX], cv[PA_CVOLUME_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX], *t;
 
         pa_assert(i->sink);
 
         pa_strbuf_printf(
             s,
             "    index: %u\n"
-            "\tname: <%s>\n"
             "\tdriver: <%s>\n"
-            "\tflags: %s%s%s%s%s%s%s\n"
+            "\tflags: %s%s%s%s%s%s%s%s\n"
             "\tstate: %s\n"
             "\tsink: <%u> '%s'\n"
             "\tvolume: <%s>\n"
@@ -304,10 +328,10 @@ char *pa_sink_input_list_to_string(pa_core *c) {
             "\tchannel map: <%s>\n"
             "\tresample method: %s\n",
             i->index,
-            i->name,
             i->driver,
             i->flags & PA_SINK_INPUT_VARIABLE_RATE ? "VARIABLE_RATE " : "",
             i->flags & PA_SINK_INPUT_DONT_MOVE ? "DONT_MOVE " : "",
+            i->flags & PA_SINK_INPUT_START_CORKED ? "START_CORKED " : "",
             i->flags & PA_SINK_INPUT_NO_REMAP ? "NO_REMAP " : "",
             i->flags & PA_SINK_INPUT_NO_REMIX ? "NO_REMIX " : "",
             i->flags & PA_SINK_INPUT_FIX_FORMAT ? "FIX_FORMAT " : "",
@@ -325,7 +349,11 @@ char *pa_sink_input_list_to_string(pa_core *c) {
         if (i->module)
             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);
+            pa_strbuf_printf(s, "\tclient: <%u> '%s'\n", i->client->index, pa_strnull(pa_proplist_gets(i->client->proplist, PA_PROP_APPLICATION_NAME)));
+
+        t = pa_proplist_to_string(i->proplist);
+        pa_strbuf_printf(s, "\tproperties:\n%s", t);
+        pa_xfree(t);
     }
 
     return pa_strbuf_tostring_free(s);
@@ -345,7 +373,7 @@ char *pa_scache_list_to_string(pa_core *c) {
 
         for (e = pa_idxset_first(c->scache, &idx); e; e = pa_idxset_next(c->scache, &idx)) {
             double l = 0;
-            char ss[PA_SAMPLE_SPEC_SNPRINT_MAX] = "n/a", cv[PA_CVOLUME_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX] = "n/a";
+            char ss[PA_SAMPLE_SPEC_SNPRINT_MAX] = "n/a", cv[PA_CVOLUME_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX] = "n/a", *t;
 
             if (e->memchunk.memblock) {
                 pa_sample_spec_snprint(ss, sizeof(ss), &e->sample_spec);
@@ -371,8 +399,12 @@ char *pa_scache_list_to_string(pa_core *c) {
                 (long unsigned)(e->memchunk.memblock ? e->memchunk.length : 0),
                 l,
                 pa_cvolume_snprint(cv, sizeof(cv), &e->volume),
-                e->lazy ? "yes" : "no",
+                pa_yes_no(e->lazy),
                 e->filename ? e->filename : "n/a");
+
+            t = pa_proplist_to_string(e->proplist);
+            pa_strbuf_printf(s, "\tproperties:\n%s", t);
+            pa_xfree(t);
         }
     }
 
diff --git a/src/pulsecore/cli.c b/src/pulsecore/cli.c
index 85e0863..47712d3 100644
--- a/src/pulsecore/cli.c
+++ b/src/pulsecore/cli.c
@@ -82,7 +82,7 @@ pa_cli* pa_cli_new(pa_core *core, pa_iochannel *io, pa_module *m) {
     pa_assert_se(c->client = pa_client_new(core, __FILE__, cname));
     c->client->kill = client_kill;
     c->client->userdata = c;
-    c->client->owner = m;
+    c->client->module = m;
 
     pa_ioline_set_callback(c->line, line_callback, c);
     pa_ioline_puts(c->line, "Welcome to PulseAudio! Use \"help\" for usage information.\n"PROMPT);
diff --git a/src/pulsecore/client.c b/src/pulsecore/client.c
index 319b838..6a087d4 100644
--- a/src/pulsecore/client.c
+++ b/src/pulsecore/client.c
@@ -44,17 +44,19 @@ pa_client *pa_client_new(pa_core *core, const char *driver, const char *name) {
     pa_core_assert_ref(core);
 
     c = pa_xnew(pa_client, 1);
-    c->name = pa_xstrdup(name);
-    c->driver = pa_xstrdup(driver);
-    c->owner = NULL;
     c->core = core;
+    c->proplist = pa_proplist_new();
+    if (name)
+        pa_proplist_sets(c->proplist, PA_PROP_APPLICATION_NAME, name);
+    c->driver = pa_xstrdup(driver);
+    c->module = NULL;
 
     c->kill = NULL;
     c->userdata = NULL;
 
     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, pa_strnull(name));
     pa_subscription_post(core, PA_SUBSCRIPTION_EVENT_CLIENT|PA_SUBSCRIPTION_EVENT_NEW, c->index);
 
     pa_core_check_quit(core);
@@ -70,9 +72,9 @@ void pa_client_free(pa_client *c) {
 
     pa_core_check_quit(c->core);
 
-    pa_log_info("Freed %u \"%s\"", c->index, c->name);
+    pa_log_info("Freed %u \"%s\"", c->index, pa_strnull(pa_proplist_gets(c->proplist, PA_PROP_APPLICATION_NAME)));
     pa_subscription_post(c->core, PA_SUBSCRIPTION_EVENT_CLIENT|PA_SUBSCRIPTION_EVENT_REMOVE, c->index);
-    pa_xfree(c->name);
+    pa_proplist_free(c->proplist);
     pa_xfree(c->driver);
     pa_xfree(c);
 }
@@ -91,10 +93,7 @@ void pa_client_kill(pa_client *c) {
 void pa_client_set_name(pa_client *c, const char *name) {
     pa_assert(c);
 
-    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);
-
+    pa_log_info("Client %u changed name from \"%s\" to \"%s\"", c->index, pa_strnull(pa_proplist_gets(c->proplist, PA_PROP_APPLICATION_NAME)), name);
+    pa_proplist_sets(c->proplist, PA_PROP_APPLICATION_NAME, name);
     pa_subscription_post(c->core, PA_SUBSCRIPTION_EVENT_CLIENT|PA_SUBSCRIPTION_EVENT_CHANGE, c->index);
 }
diff --git a/src/pulsecore/client.h b/src/pulsecore/client.h
index 6d09b99..bff057e 100644
--- a/src/pulsecore/client.h
+++ b/src/pulsecore/client.h
@@ -28,6 +28,7 @@
 
 typedef struct pa_client pa_client;
 
+#include <pulse/proplist.h>
 #include <pulsecore/core.h>
 #include <pulsecore/module.h>
 
@@ -37,11 +38,12 @@ typedef struct pa_client pa_client;
 
 struct pa_client {
     uint32_t index;
-
-    pa_module *owner;
-    char *name, *driver;
     pa_core *core;
 
+    pa_proplist *proplist;
+    pa_module *module;
+    char *driver;
+
     void (*kill)(pa_client *c);
     void *userdata;
 };
diff --git a/src/pulsecore/core-scache.c b/src/pulsecore/core-scache.c
index 46444a9..4036a55 100644
--- a/src/pulsecore/core-scache.c
+++ b/src/pulsecore/core-scache.c
@@ -63,7 +63,7 @@
 
 #include "core-scache.h"
 
-#define UNLOAD_POLL_TIME 2
+#define UNLOAD_POLL_TIME 5
 
 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;
@@ -89,6 +89,8 @@ static void free_entry(pa_scache_entry *e) {
     pa_xfree(e->filename);
     if (e->memchunk.memblock)
         pa_memblock_unref(e->memchunk.memblock);
+    if (e->proplist)
+        pa_proplist_free(e->proplist);
     pa_xfree(e);
 }
 
@@ -103,6 +105,7 @@ static pa_scache_entry* scache_add_item(pa_core *c, const char *name) {
             pa_memblock_unref(e->memchunk.memblock);
 
         pa_xfree(e->filename);
+        pa_proplist_clear(e->proplist);
 
         pa_assert(e->core == c);
 
@@ -117,11 +120,10 @@ static pa_scache_entry* scache_add_item(pa_core *c, const char *name) {
 
         e->name = pa_xstrdup(name);
         e->core = c;
+        e->proplist = pa_proplist_new();
 
-        if (!c->scache) {
+        if (!c->scache)
             c->scache = pa_idxset_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
-            pa_assert(c->scache);
-        }
 
         pa_idxset_put(c->scache, e, &e->index);
 
@@ -132,7 +134,7 @@ static pa_scache_entry* scache_add_item(pa_core *c, const char *name) {
     e->memchunk.memblock = NULL;
     e->memchunk.index = e->memchunk.length = 0;
     e->filename = NULL;
-    e->lazy = 0;
+    e->lazy = FALSE;
     e->last_used_time = 0;
 
     memset(&e->sample_spec, 0, sizeof(e->sample_spec));
@@ -142,7 +144,7 @@ static pa_scache_entry* scache_add_item(pa_core *c, const char *name) {
     return e;
 }
 
-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) {
+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, pa_proplist *p, uint32_t *idx) {
     pa_scache_entry *e;
     char st[PA_SAMPLE_SPEC_SNPRINT_MAX];
     pa_channel_map tmap;
@@ -178,6 +180,9 @@ int pa_scache_add_item(pa_core *c, const char *name, const pa_sample_spec *ss, c
         pa_memblock_ref(e->memchunk.memblock);
     }
 
+    if (p)
+        pa_proplist_update(e->proplist, PA_UPDATE_REPLACE, p);
+
     if (idx)
         *idx = e->index;
 
@@ -208,7 +213,7 @@ int pa_scache_add_file(pa_core *c, const char *name, const char *filename, uint3
     if (pa_sound_file_load(c->mempool, filename, &ss, &map, &chunk) < 0)
         return -1;
 
-    r = pa_scache_add_item(c, name, &ss, &map, &chunk, idx);
+    r = pa_scache_add_item(c, name, &ss, &map, &chunk, NULL, idx);
     pa_memblock_unref(chunk.memblock);
 
     return r;
@@ -231,7 +236,7 @@ int pa_scache_add_file_lazy(pa_core *c, const char *name, const char *filename,
     if (!(e = scache_add_item(c, name)))
         return -1;
 
-    e->lazy = 1;
+    e->lazy = TRUE;
     e->filename = pa_xstrdup(filename);
 
     if (!c->scache_auto_unload_event) {
@@ -285,10 +290,11 @@ void pa_scache_free(pa_core *c) {
         c->mainloop->time_free(c->scache_auto_unload_event);
 }
 
-int pa_scache_play_item(pa_core *c, const char *name, pa_sink *sink, pa_volume_t volume) {
+int pa_scache_play_item(pa_core *c, const char *name, pa_sink *sink, pa_volume_t volume, pa_proplist *p, uint32_t *sink_input_idx) {
     pa_scache_entry *e;
     char *t;
     pa_cvolume r;
+    pa_proplist *merged;
 
     pa_assert(c);
     pa_assert(name);
@@ -312,17 +318,24 @@ int pa_scache_play_item(pa_core *c, const char *name, pa_sink *sink, pa_volume_t
 
     pa_log_debug("Playing sample \"%s\" on \"%s\"", name, sink->name);
 
-    t = pa_sprintf_malloc("sample:%s", name);
-
     pa_cvolume_set(&r, e->volume.channels, volume);
     pa_sw_cvolume_multiply(&r, &r, &e->volume);
 
-    if (pa_play_memchunk(sink, t, &e->sample_spec, &e->channel_map, &e->memchunk, &r) < 0) {
-        pa_xfree(t);
+    merged = pa_proplist_new();
+
+    t = pa_sprintf_malloc("sample:%s", name);
+    pa_proplist_sets(merged, PA_PROP_MEDIA_NAME, t);
+    pa_xfree(t);
+
+    pa_proplist_update(merged, PA_UPDATE_REPLACE, e->proplist);
+    pa_proplist_update(merged, PA_UPDATE_REPLACE, p);
+
+    if (pa_play_memchunk(sink, &e->sample_spec, &e->channel_map, &e->memchunk, &r, merged, sink_input_idx) < 0) {
+        pa_proplist_free(merged);
         return -1;
     }
 
-    pa_xfree(t);
+    pa_proplist_free(merged);
 
     if (e->lazy)
         time(&e->last_used_time);
@@ -330,7 +343,7 @@ 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) {
+int pa_scache_play_item_by_name(pa_core *c, const char *name, const char*sink_name, pa_bool_t autoload, pa_volume_t volume, pa_proplist *p, uint32_t *sink_input_idx) {
     pa_sink *sink;
 
     pa_assert(c);
@@ -339,10 +352,10 @@ int pa_scache_play_item_by_name(pa_core *c, const char *name, const char*sink_na
     if (!(sink = pa_namereg_get(c, sink_name, PA_NAMEREG_SINK, autoload)))
         return -1;
 
-    return pa_scache_play_item(c, name, sink, volume);
+    return pa_scache_play_item(c, name, sink, volume, p, sink_input_idx);
 }
 
-const char * pa_scache_get_name_by_id(pa_core *c, uint32_t id) {
+const char *pa_scache_get_name_by_id(pa_core *c, uint32_t id) {
     pa_scache_entry *e;
 
     pa_assert(c);
@@ -366,9 +379,10 @@ uint32_t pa_scache_get_id_by_name(pa_core *c, const char *name) {
     return e->index;
 }
 
-uint32_t pa_scache_total_size(pa_core *c) {
+size_t pa_scache_total_size(pa_core *c) {
     pa_scache_entry *e;
-    uint32_t idx, sum = 0;
+    uint32_t idx;
+    size_t sum = 0;
 
     pa_assert(c);
 
@@ -403,8 +417,7 @@ void pa_scache_unload_unused(pa_core *c) {
             continue;
 
         pa_memblock_unref(e->memchunk.memblock);
-        e->memchunk.memblock = NULL;
-        e->memchunk.index = e->memchunk.length = 0;
+        pa_memchunk_reset(&e->memchunk);
 
         pa_subscription_post(c, PA_SUBSCRIPTION_EVENT_SAMPLE_CACHE|PA_SUBSCRIPTION_EVENT_CHANGE, e->index);
     }
@@ -467,8 +480,9 @@ int pa_scache_add_directory_lazy(pa_core *c, const char *pathname) {
             pa_snprintf(p, sizeof(p), "%s/%s", pathname, e->d_name);
             add_file(c, p);
         }
+
+        closedir(dir);
     }
 
-    closedir(dir);
     return 0;
 }
diff --git a/src/pulsecore/core-scache.h b/src/pulsecore/core-scache.h
index ab7ec0e..31f3ff3 100644
--- a/src/pulsecore/core-scache.h
+++ b/src/pulsecore/core-scache.h
@@ -29,11 +29,12 @@
 #include <pulsecore/memchunk.h>
 #include <pulsecore/sink.h>
 
-#define PA_SCACHE_ENTRY_SIZE_MAX (1024*1024*2)
+#define PA_SCACHE_ENTRY_SIZE_MAX (1024*1024*16)
 
 typedef struct pa_scache_entry {
-    pa_core *core;
     uint32_t index;
+    pa_core *core;
+
     char *name;
 
     pa_cvolume volume;
@@ -43,25 +44,27 @@ typedef struct pa_scache_entry {
 
     char *filename;
 
-    int lazy;
+    pa_bool_t lazy;
     time_t last_used_time;
+
+    pa_proplist *proplist;
 } pa_scache_entry;
 
-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);
+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, pa_proplist *p, uint32_t *idx);
 int pa_scache_add_file(pa_core *c, const char *name, const char *filename, uint32_t *idx);
 int pa_scache_add_file_lazy(pa_core *c, const char *name, const char *filename, uint32_t *idx);
 
 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);
+int pa_scache_play_item(pa_core *c, const char *name, pa_sink *sink, pa_volume_t volume, pa_proplist *p, uint32_t *sink_input_idx);
+int pa_scache_play_item_by_name(pa_core *c, const char *name, const char*sink_name, pa_bool_t autoload, pa_volume_t volume, pa_proplist *p, uint32_t *sink_input_idx);
 void pa_scache_free(pa_core *c);
 
 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);
 
-uint32_t pa_scache_total_size(pa_core *c);
+size_t pa_scache_total_size(pa_core *c);
 
 void pa_scache_unload_unused(pa_core *c);
 
diff --git a/src/pulsecore/core.h b/src/pulsecore/core.h
index ce45e30..6be1a0c 100644
--- a/src/pulsecore/core.h
+++ b/src/pulsecore/core.h
@@ -43,16 +43,20 @@ typedef struct pa_core pa_core;
 #include <pulsecore/msgobject.h>
 
 typedef enum pa_core_hook {
-    PA_CORE_HOOK_SINK_NEW_POST,
+    PA_CORE_HOOK_SINK_NEW,
+    PA_CORE_HOOK_SINK_FIXATE,
+    PA_CORE_HOOK_SINK_PUT,
     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_SINK_PROPLIST_CHANGED,
+    PA_CORE_HOOK_SOURCE_NEW,
+    PA_CORE_HOOK_SOURCE_FIXATE,
+    PA_CORE_HOOK_SOURCE_PUT,
     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_SOURCE_PROPLIST_CHANGED,
     PA_CORE_HOOK_SINK_INPUT_NEW,
     PA_CORE_HOOK_SINK_INPUT_FIXATE,
     PA_CORE_HOOK_SINK_INPUT_PUT,
@@ -60,8 +64,8 @@ typedef enum pa_core_hook {
     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_SINK_INPUT_PROPLIST_CHANGED,
     PA_CORE_HOOK_SOURCE_OUTPUT_NEW,
     PA_CORE_HOOK_SOURCE_OUTPUT_FIXATE,
     PA_CORE_HOOK_SOURCE_OUTPUT_PUT,
@@ -69,8 +73,8 @@ typedef enum pa_core_hook {
     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_SOURCE_OUTPUT_PROPLIST_CHANGED,
     PA_CORE_HOOK_MAX
 } pa_core_hook_t;
 
diff --git a/src/pulsecore/envelope.c b/src/pulsecore/envelope.c
index 571f875..2f5da5a 100644
--- a/src/pulsecore/envelope.c
+++ b/src/pulsecore/envelope.c
@@ -381,7 +381,7 @@ static void envelope_merge(pa_envelope *e, int v) {
                 break;
 
             if (e->points[v].n_points >= e->points[v].n_allocated) {
-                e->points[v].n_allocated = MAX(e->points[v].n_points*2, PA_ENVELOPE_POINTS_MAX);
+                e->points[v].n_allocated = PA_MAX(e->points[v].n_points*2, PA_ENVELOPE_POINTS_MAX);
 
                 e->points[v].x = pa_xrealloc(e->points[v].x, sizeof(size_t) * e->points[v].n_allocated);
                 e->points[v].y.i = pa_xrealloc(e->points[v].y.i, sizeof(int32_t) * e->points[v].n_allocated);
diff --git a/src/pulsecore/envelope.h b/src/pulsecore/envelope.h
index 23be8f6..c54c137 100644
--- a/src/pulsecore/envelope.h
+++ b/src/pulsecore/envelope.h
@@ -29,7 +29,7 @@
 
 #include <pulse/sample.h>
 
-#define PA_ENVELOPE_POINTS_MAX 4
+#define PA_ENVELOPE_POINTS_MAX 4U
 
 typedef struct pa_envelope pa_envelope;
 typedef struct pa_envelope_item pa_envelope_item;
diff --git a/src/pulsecore/fdsem.c b/src/pulsecore/fdsem.c
index 59eec18..22d2a85 100644
--- a/src/pulsecore/fdsem.c
+++ b/src/pulsecore/fdsem.c
@@ -78,21 +78,19 @@ struct pa_fdsem {
 #ifdef HAVE_EVENTFD
     int efd;
 #endif
-    pa_atomic_t waiting;
-    pa_atomic_t signalled;
-    pa_atomic_t in_pipe;
+
+    pa_fdsem_data *data;
 };
 
 pa_fdsem *pa_fdsem_new(void) {
     pa_fdsem *f;
 
-    f = pa_xnew(pa_fdsem, 1);
+    f = pa_xmalloc(PA_ALIGN(sizeof(pa_fdsem)) + PA_ALIGN(sizeof(pa_fdsem_data)));
 
 #ifdef HAVE_EVENTFD
     if ((f->efd = eventfd(0)) >= 0) {
         pa_make_fd_cloexec(f->efd);
         f->fds[0] = f->fds[1] = -1;
-
     } else
 #endif
     {
@@ -105,9 +103,57 @@ pa_fdsem *pa_fdsem_new(void) {
         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);
+    f->data = (pa_fdsem_data*) ((uint8_t*) f + PA_ALIGN(sizeof(pa_fdsem)));
+
+    pa_atomic_store(&f->data->waiting, 0);
+    pa_atomic_store(&f->data->signalled, 0);
+    pa_atomic_store(&f->data->in_pipe, 0);
+
+    return f;
+}
+
+pa_fdsem *pa_fdsem_open_shm(pa_fdsem_data *data, int event_fd) {
+    pa_fdsem *f = NULL;
+
+    pa_assert(data);
+    pa_assert(event_fd >= 0);
+
+#ifdef HAVE_EVENTFD
+    f = pa_xnew(pa_fdsem, 1);
+
+    f->efd = event_fd;
+    pa_make_fd_cloexec(f->efd);
+    f->fds[0] = f->fds[1] = -1;
+    f->data = data;
+#endif
+
+    return f;
+}
+
+pa_fdsem *pa_fdsem_new_shm(pa_fdsem_data *data, int* event_fd) {
+    pa_fdsem *f = NULL;
+
+    pa_assert(data);
+    pa_assert(event_fd);
+
+#ifdef HAVE_EVENTFD
+
+    f = pa_xnew(pa_fdsem, 1);
+
+    if ((f->efd = eventfd(0)) < 0) {
+        pa_xfree(f);
+        return NULL;
+    }
+
+    pa_make_fd_cloexec(f->efd);
+    f->fds[0] = f->fds[1] = -1;
+    f->data = data;
+
+    pa_atomic_store(&f->data->waiting, 0);
+    pa_atomic_store(&f->data->signalled, 0);
+    pa_atomic_store(&f->data->in_pipe, 0);
+
+#endif
 
     return f;
 }
@@ -128,7 +174,7 @@ static void flush(pa_fdsem *f) {
     ssize_t r;
     pa_assert(f);
 
-    if (pa_atomic_load(&f->in_pipe) <= 0)
+    if (pa_atomic_load(&f->data->in_pipe) <= 0)
         return;
 
     do {
@@ -151,19 +197,19 @@ static void flush(pa_fdsem *f) {
             continue;
         }
 
-    } while (pa_atomic_sub(&f->in_pipe, r) > r);
+    } while (pa_atomic_sub(&f->data->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_cmpxchg(&f->data->signalled, 0, 1)) {
 
-        if (pa_atomic_load(&f->waiting)) {
+        if (pa_atomic_load(&f->data->waiting)) {
             ssize_t r;
             char x = 'x';
 
-            pa_atomic_inc(&f->in_pipe);
+            pa_atomic_inc(&f->data->in_pipe);
 
             for (;;) {
 
@@ -194,12 +240,12 @@ void pa_fdsem_wait(pa_fdsem *f) {
 
     flush(f);
 
-    if (pa_atomic_cmpxchg(&f->signalled, 1, 0))
+    if (pa_atomic_cmpxchg(&f->data->signalled, 1, 0))
         return;
 
-    pa_atomic_inc(&f->waiting);
+    pa_atomic_inc(&f->data->waiting);
 
-    while (!pa_atomic_cmpxchg(&f->signalled, 1, 0)) {
+    while (!pa_atomic_cmpxchg(&f->data->signalled, 1, 0)) {
         char x[10];
         ssize_t r;
 
@@ -221,10 +267,10 @@ void pa_fdsem_wait(pa_fdsem *f) {
             continue;
         }
 
-        pa_atomic_sub(&f->in_pipe, r);
+        pa_atomic_sub(&f->data->in_pipe, r);
     }
 
-    pa_assert_se(pa_atomic_dec(&f->waiting) >= 1);
+    pa_assert_se(pa_atomic_dec(&f->data->waiting) >= 1);
 }
 
 int pa_fdsem_try(pa_fdsem *f) {
@@ -232,7 +278,7 @@ int pa_fdsem_try(pa_fdsem *f) {
 
     flush(f);
 
-    if (pa_atomic_cmpxchg(&f->signalled, 1, 0))
+    if (pa_atomic_cmpxchg(&f->data->signalled, 1, 0))
         return 1;
 
     return 0;
@@ -254,13 +300,13 @@ int pa_fdsem_before_poll(pa_fdsem *f) {
 
     flush(f);
 
-    if (pa_atomic_cmpxchg(&f->signalled, 1, 0))
+    if (pa_atomic_cmpxchg(&f->data->signalled, 1, 0))
         return -1;
 
-    pa_atomic_inc(&f->waiting);
+    pa_atomic_inc(&f->data->waiting);
 
-    if (pa_atomic_cmpxchg(&f->signalled, 1, 0)) {
-        pa_assert_se(pa_atomic_dec(&f->waiting) >= 1);
+    if (pa_atomic_cmpxchg(&f->data->signalled, 1, 0)) {
+        pa_assert_se(pa_atomic_dec(&f->data->waiting) >= 1);
         return -1;
     }
     return 0;
@@ -269,11 +315,11 @@ int pa_fdsem_before_poll(pa_fdsem *f) {
 int pa_fdsem_after_poll(pa_fdsem *f) {
     pa_assert(f);
 
-    pa_assert_se(pa_atomic_dec(&f->waiting) >= 1);
+    pa_assert_se(pa_atomic_dec(&f->data->waiting) >= 1);
 
     flush(f);
 
-    if (pa_atomic_cmpxchg(&f->signalled, 1, 0))
+    if (pa_atomic_cmpxchg(&f->data->signalled, 1, 0))
         return 1;
 
     return 0;
diff --git a/src/pulsecore/fdsem.h b/src/pulsecore/fdsem.h
index f38ef20..f4f7b99 100644
--- a/src/pulsecore/fdsem.h
+++ b/src/pulsecore/fdsem.h
@@ -33,7 +33,15 @@
 
 typedef struct pa_fdsem pa_fdsem;
 
+typedef struct pa_fdsem_data {
+    pa_atomic_t waiting;
+    pa_atomic_t signalled;
+    pa_atomic_t in_pipe;
+} pa_fdsem_data;
+
 pa_fdsem *pa_fdsem_new(void);
+pa_fdsem *pa_fdsem_open_shm(pa_fdsem_data *data, int event_fd);
+pa_fdsem *pa_fdsem_new_shm(pa_fdsem_data *data, int* event_fd);
 void pa_fdsem_free(pa_fdsem *f);
 
 void pa_fdsem_post(pa_fdsem *f);
diff --git a/src/pulsecore/macro.h b/src/pulsecore/macro.h
index 41af19c..60ab025 100644
--- a/src/pulsecore/macro.h
+++ b/src/pulsecore/macro.h
@@ -65,19 +65,53 @@ static inline size_t pa_page_align(size_t l) {
 
 #define PA_ELEMENTSOF(x) (sizeof(x)/sizeof((x)[0]))
 
-#ifndef MAX
-#define MAX(a, b) ((a) > (b) ? (a) : (b))
+/* The users of PA_MIN and PA_MAX should be aware that these macros on
+ * non-GCC executed code with side effects twice. It is thus
+ * considered misuse to use code with side effects as arguments to MIN
+ * and MAX. */
+
+#ifdef __GNUC__
+#define PA_MAX(a,b)                             \
+    __extension__ ({ typeof(a) _a = (a);        \
+            typeof(b) _b = (b);                 \
+            _a > _b ? _a : _b;                  \
+        })
+#else
+#define PA_MAX(a, b) ((a) > (b) ? (a) : (b))
 #endif
 
-#ifndef MIN
-#define MIN(a, b) ((a) < (b) ? (a) : (b))
+#ifdef __GNUC__
+#define PA_MIN(a,b)                             \
+    __extension__ ({ typeof(a) _a = (a);        \
+            typeof(b) _b = (b);                 \
+            _a < _b ? _a : _b;                  \
+        })
+#else
+#define PA_MIN(a, b) ((a) < (b) ? (a) : (b))
 #endif
 
-#ifndef CLAMP
-#define CLAMP(x, low, high) (((x) > (high)) ? (high) : (((x) < (low)) ? (low) : (x)))
+#ifdef __GNUC__
+#define PA_CLAMP(x, low, high)                                          \
+    __extension__ ({ typeof(x) _x = (x);                                \
+            typeof(low) _low = (low);                                   \
+            typeof(high) _high = (high);                                \
+            ((_x > _high) ? _high : ((_x < _low) ? _low : _x));         \
+        })
+#else
+#define PA_CLAMP(x, low, high) (((x) > (high)) ? (high) : (((x) < (low)) ? (low) : (x)))
 #endif
 
+#ifdef __GNUC__
+#define PA_CLAMP_UNLIKELY(x, low, high)                                 \
+    __extension__ ({ typeof(x) _x = (x);                                \
+            typeof(low) _low = (low);                                   \
+            typeof(high) _high = (high);                                \
+            (PA_UNLIKELY(_x > _high) ? _high : (PA_UNLIKELY(_x < _low) ? _low : _x)); \
+        })
+#else
 #define PA_CLAMP_UNLIKELY(x, low, high) (PA_UNLIKELY((x) > (high)) ? (high) : (PA_UNLIKELY((x) < (low)) ? (low) : (x)))
+#endif
+
 /* We don't define a PA_CLAMP_LIKELY here, because it doesn't really
  * make sense: we cannot know if it is more likely that the values is
  * lower or greater than the boundaries.*/
diff --git a/src/pulsecore/mcalign.c b/src/pulsecore/mcalign.c
index 8ca7c96..e12f84f 100644
--- a/src/pulsecore/mcalign.c
+++ b/src/pulsecore/mcalign.c
@@ -197,7 +197,6 @@ int pa_mcalign_pop(pa_mcalign *m, pa_memchunk *c) {
 
     /* There's simply nothing */
     return -1;
-
 }
 
 size_t pa_mcalign_csize(pa_mcalign *m, size_t l) {
@@ -211,3 +210,11 @@ size_t pa_mcalign_csize(pa_mcalign *m, size_t l) {
 
     return (l/m->base)*m->base;
 }
+
+void pa_mcalign_flush(pa_mcalign *m) {
+    pa_memchunk chunk;
+    pa_assert(m);
+
+    while (pa_mcalign_pop(m, &chunk) >= 0)
+        pa_memblock_unref(chunk.memblock);
+}
diff --git a/src/pulsecore/mcalign.h b/src/pulsecore/mcalign.h
index 6ff8f94..6c8b8d5 100644
--- a/src/pulsecore/mcalign.h
+++ b/src/pulsecore/mcalign.h
@@ -79,4 +79,7 @@ int pa_mcalign_pop(pa_mcalign *m, pa_memchunk *c);
 /* If we pass l bytes in now, how many bytes would we get out? */
 size_t pa_mcalign_csize(pa_mcalign *m, size_t l);
 
+/* Flush what's still stored in the aligner */
+void pa_mcalign_flush(pa_mcalign *m);
+
 #endif
diff --git a/src/pulsecore/memblock.c b/src/pulsecore/memblock.c
index 99b5a13..b76980f 100644
--- a/src/pulsecore/memblock.c
+++ b/src/pulsecore/memblock.c
@@ -59,7 +59,7 @@ struct pa_memblock {
     pa_mempool *pool;
 
     pa_memblock_type_t type;
-    int read_only; /* boolean */
+    pa_bool_t read_only, is_silence;
 
     pa_atomic_ptr_t data;
     size_t length;
@@ -226,7 +226,8 @@ static pa_memblock *memblock_new_appended(pa_mempool *p, size_t length) {
     PA_REFCNT_INIT(b);
     b->pool = p;
     b->type = PA_MEMBLOCK_APPENDED;
-    b->read_only = 0;
+    b->read_only = FALSE;
+    b->is_silence = FALSE;
     pa_atomic_ptr_store(&b->data, (uint8_t*) b + PA_ALIGN(sizeof(pa_memblock)));
     b->length = length;
     pa_atomic_store(&b->n_acquired, 0);
@@ -330,7 +331,8 @@ pa_memblock *pa_memblock_new_pool(pa_mempool *p, size_t length) {
 
     PA_REFCNT_INIT(b);
     b->pool = p;
-    b->read_only = 0;
+    b->read_only = FALSE;
+    b->is_silence = FALSE;
     b->length = length;
     pa_atomic_store(&b->n_acquired, 0);
     pa_atomic_store(&b->please_signal, 0);
@@ -340,7 +342,7 @@ pa_memblock *pa_memblock_new_pool(pa_mempool *p, size_t length) {
 }
 
 /* No lock necessary */
-pa_memblock *pa_memblock_new_fixed(pa_mempool *p, void *d, size_t length, int read_only) {
+pa_memblock *pa_memblock_new_fixed(pa_mempool *p, void *d, size_t length, pa_bool_t read_only) {
     pa_memblock *b;
 
     pa_assert(p);
@@ -354,6 +356,7 @@ pa_memblock *pa_memblock_new_fixed(pa_mempool *p, void *d, size_t length, int re
     b->pool = p;
     b->type = PA_MEMBLOCK_FIXED;
     b->read_only = read_only;
+    b->is_silence = FALSE;
     pa_atomic_ptr_store(&b->data, d);
     b->length = length;
     pa_atomic_store(&b->n_acquired, 0);
@@ -364,7 +367,7 @@ pa_memblock *pa_memblock_new_fixed(pa_mempool *p, void *d, size_t length, int re
 }
 
 /* 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 *pa_memblock_new_user(pa_mempool *p, void *d, size_t length, pa_free_cb_t free_cb, pa_bool_t read_only) {
     pa_memblock *b;
 
     pa_assert(p);
@@ -379,6 +382,7 @@ pa_memblock *pa_memblock_new_user(pa_mempool *p, void *d, size_t length, void (*
     b->pool = p;
     b->type = PA_MEMBLOCK_USER;
     b->read_only = read_only;
+    b->is_silence = FALSE;
     pa_atomic_ptr_store(&b->data, d);
     b->length = length;
     pa_atomic_store(&b->n_acquired, 0);
@@ -391,7 +395,7 @@ pa_memblock *pa_memblock_new_user(pa_mempool *p, void *d, size_t length, void (*
 }
 
 /* No lock necessary */
-int pa_memblock_is_read_only(pa_memblock *b) {
+pa_bool_t pa_memblock_is_read_only(pa_memblock *b) {
     pa_assert(b);
     pa_assert(PA_REFCNT_VALUE(b) > 0);
 
@@ -399,13 +403,28 @@ int pa_memblock_is_read_only(pa_memblock *b) {
 }
 
 /* No lock necessary */
-int pa_memblock_ref_is_one(pa_memblock *b) {
+pa_bool_t pa_memblock_is_silence(pa_memblock *b) {
+    pa_assert(b);
+    pa_assert(PA_REFCNT_VALUE(b) > 0);
+
+    return b->is_silence;
+}
+
+/* No lock necessary */
+void pa_memblock_set_is_silence(pa_memblock *b, pa_bool_t v) {
+    pa_assert(b);
+    pa_assert(PA_REFCNT_VALUE(b) > 0);
+
+    b->is_silence = v;
+}
+
+/* No lock necessary */
+pa_bool_t pa_memblock_ref_is_one(pa_memblock *b) {
     int r;
 
     pa_assert(b);
 
-    r = PA_REFCNT_VALUE(b);
-    pa_assert(r > 0);
+    pa_assert_se((r = PA_REFCNT_VALUE(b)) > 0);
 
     return r == 1;
 }
@@ -767,7 +786,7 @@ int pa_mempool_get_shm_id(pa_mempool *p, uint32_t *id) {
 }
 
 /* No lock necessary */
-int pa_mempool_is_shared(pa_mempool *p) {
+pa_bool_t pa_mempool_is_shared(pa_mempool *p) {
     pa_assert(p);
 
     return !!p->memory.shared;
diff --git a/src/pulsecore/memblock.h b/src/pulsecore/memblock.h
index c704014..338d1a1 100644
--- a/src/pulsecore/memblock.h
+++ b/src/pulsecore/memblock.h
@@ -87,13 +87,13 @@ pa_memblock *pa_memblock_new(pa_mempool *, size_t length);
 pa_memblock *pa_memblock_new_pool(pa_mempool *, size_t length);
 
 /* Allocate a new memory block of type PA_MEMBLOCK_USER */
-pa_memblock *pa_memblock_new_user(pa_mempool *, void *data, size_t length, void (*free_cb)(void *p), int read_only);
+pa_memblock *pa_memblock_new_user(pa_mempool *, void *data, size_t length, pa_free_cb_t free_cb, pa_bool_t read_only);
 
 /* A special case of pa_memblock_new_user: take a memory buffer previously allocated with pa_xmalloc()  */
 #define pa_memblock_new_malloced(p,data,length) pa_memblock_new_user(p, data, length, pa_xfree, 0)
 
 /* Allocate a new memory block of type PA_MEMBLOCK_FIXED */
-pa_memblock *pa_memblock_new_fixed(pa_mempool *, void *data, size_t length, int read_only);
+pa_memblock *pa_memblock_new_fixed(pa_mempool *, void *data, size_t length, pa_bool_t read_only);
 
 void pa_memblock_unref(pa_memblock*b);
 pa_memblock* pa_memblock_ref(pa_memblock*b);
@@ -106,8 +106,11 @@ 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);
+pa_bool_t pa_memblock_is_read_only(pa_memblock *b);
+pa_bool_t pa_memblock_is_silence(pa_memblock *b);
+pa_bool_t pa_memblock_ref_is_one(pa_memblock *b);
+void pa_memblock_set_is_silence(pa_memblock *b, pa_bool_t v);
+
 void* pa_memblock_acquire(pa_memblock *b);
 void pa_memblock_release(pa_memblock *b);
 size_t pa_memblock_get_length(pa_memblock *b);
@@ -121,7 +124,7 @@ void pa_mempool_free(pa_mempool *p);
 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);
+pa_bool_t pa_mempool_is_shared(pa_mempool *p);
 size_t pa_mempool_block_size_max(pa_mempool *p);
 
 /* For recieving blocks from other nodes */
diff --git a/src/pulsecore/memblockq.c b/src/pulsecore/memblockq.c
index 8247fea..cc5e9e1 100644
--- a/src/pulsecore/memblockq.c
+++ b/src/pulsecore/memblockq.c
@@ -50,8 +50,9 @@ PA_STATIC_FLIST_DECLARE(list_items, 0, pa_xfree);
 
 struct pa_memblockq {
     struct list_item *blocks, *blocks_tail;
+    struct list_item *current_read, *current_write;
     unsigned n_blocks;
-    size_t maxlength, tlength, base, prebuf, minreq;
+    size_t maxlength, tlength, base, prebuf, minreq, maxrewind;
     int64_t read_index, write_index;
     pa_bool_t in_prebuf;
     pa_memblock *silence;
@@ -67,6 +68,7 @@ pa_memblockq* pa_memblockq_new(
         size_t base,
         size_t prebuf,
         size_t minreq,
+        size_t maxrewind,
         pa_memblock *silence) {
 
     pa_memblockq* bq;
@@ -75,27 +77,29 @@ pa_memblockq* pa_memblockq_new(
 
     bq = pa_xnew(pa_memblockq, 1);
     bq->blocks = bq->blocks_tail = NULL;
+    bq->current_read = bq->current_write = NULL;
     bq->n_blocks = 0;
 
     bq->base = base;
     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);
+    pa_log_debug("memblockq requested: maxlength=%lu, tlength=%lu, base=%lu, prebuf=%lu, minreq=%lu maxrewind=%lu",
+                 (unsigned long) maxlength, (unsigned long) tlength, (unsigned long) base, (unsigned long) prebuf, (unsigned long) minreq, (unsigned long) maxrewind);
 
-    bq->missing = bq->requested = bq->maxlength = bq->tlength = bq->prebuf = bq->minreq = 0;
+    bq->missing = bq->requested = bq->maxlength = bq->tlength = bq->prebuf = bq->minreq = bq->maxrewind = 0;
     bq->in_prebuf = TRUE;
 
     pa_memblockq_set_maxlength(bq, maxlength);
     pa_memblockq_set_tlength(bq, tlength);
     pa_memblockq_set_prebuf(bq, prebuf);
     pa_memblockq_set_minreq(bq, minreq);
+    pa_memblockq_set_maxrewind(bq, maxrewind);
 
-    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);
+    pa_log_debug("memblockq sanitized: maxlength=%lu, tlength=%lu, base=%lu, prebuf=%lu, minreq=%lu maxrewind=%lu",
+                 (unsigned long) bq->maxlength, (unsigned long) bq->tlength, (unsigned long) bq->base, (unsigned long) bq->prebuf, (unsigned long) bq->minreq, (unsigned long) bq->maxrewind);
 
     bq->silence = silence ? pa_memblock_ref(silence) : NULL;
-    bq->mcalign = NULL;
+    bq->mcalign = pa_mcalign_new(bq->base);
 
     return bq;
 }
@@ -114,6 +118,62 @@ void pa_memblockq_free(pa_memblockq* bq) {
     pa_xfree(bq);
 }
 
+static void fix_current_read(pa_memblockq *bq) {
+    pa_assert(bq);
+
+    if (PA_UNLIKELY(!bq->blocks)) {
+        bq->current_read = NULL;
+        return;
+    }
+
+    if (PA_UNLIKELY(!bq->current_read))
+        bq->current_read = bq->blocks;
+
+    /* Scan left */
+    while (PA_UNLIKELY(bq->current_read->index > bq->read_index))
+
+        if (bq->current_read->prev)
+            bq->current_read = bq->current_read->prev;
+        else
+            break;
+
+    /* Scan right */
+    while (PA_LIKELY(bq->current_read != NULL) && PA_UNLIKELY(bq->current_read->index + bq->current_read->chunk.length <= bq->read_index))
+        bq->current_read = bq->current_read->next;
+
+    /* At this point current_read will either point at or left of the
+       next block to play. It may be NULL in case everything in
+       the queue was already played */
+}
+
+static void fix_current_write(pa_memblockq *bq) {
+    pa_assert(bq);
+
+    if (PA_UNLIKELY(!bq->blocks)) {
+        bq->current_write = NULL;
+        return;
+    }
+
+    if (PA_UNLIKELY(!bq->current_write))
+        bq->current_write = bq->blocks_tail;
+
+    /* Scan right */
+    while (PA_UNLIKELY(bq->current_write->index + bq->current_write->chunk.length <= bq->write_index))
+
+        if (bq->current_write->next)
+            bq->current_write = bq->current_write->next;
+        else
+            break;
+
+    /* Scan left */
+    while (PA_LIKELY(bq->current_write != NULL) && PA_UNLIKELY(bq->current_write->index > bq->write_index))
+        bq->current_write = bq->current_write->prev;
+
+    /* At this point current_write will either point at or right of
+       the next block to write data to. It may be NULL in case
+       everything in the queue is still to be played */
+}
+
 static void drop_block(pa_memblockq *bq, struct list_item *q) {
     pa_assert(bq);
     pa_assert(q);
@@ -122,13 +182,23 @@ static void drop_block(pa_memblockq *bq, struct list_item *q) {
 
     if (q->prev)
         q->prev->next = q->next;
-    else
+    else {
+        pa_assert(bq->blocks == q);
         bq->blocks = q->next;
+    }
 
     if (q->next)
         q->next->prev = q->prev;
-    else
+    else {
+        pa_assert(bq->blocks_tail == q);
         bq->blocks_tail = q->prev;
+    }
+
+    if (bq->current_write == q)
+        bq->current_write = q->prev;
+
+    if (bq->current_read == q)
+        bq->current_read = q->next;
 
     pa_memblock_unref(q->chunk.memblock);
 
@@ -138,6 +208,16 @@ static void drop_block(pa_memblockq *bq, struct list_item *q) {
     bq->n_blocks--;
 }
 
+static void drop_backlog(pa_memblockq *bq) {
+    int64_t boundary;
+    pa_assert(bq);
+
+    boundary = bq->read_index - bq->maxrewind;
+
+    while (bq->blocks && (bq->blocks->index + bq->blocks->chunk.length <= boundary))
+        drop_block(bq, bq->blocks);
+}
+
 static pa_bool_t can_push(pa_memblockq *bq, size_t l) {
     int64_t end;
 
@@ -152,10 +232,10 @@ static pa_bool_t can_push(pa_memblockq *bq, size_t l) {
             return TRUE;
     }
 
-    end = bq->blocks_tail ? bq->blocks_tail->index + bq->blocks_tail->chunk.length : 0;
+    end = bq->blocks_tail ? bq->blocks_tail->index + bq->blocks_tail->chunk.length : bq->write_index;
 
     /* Make sure that the list doesn't get too long */
-    if (bq->write_index + (int64_t)l > end)
+    if (bq->write_index + l > end)
         if (bq->write_index + l - bq->read_index > bq->maxlength)
             return FALSE;
 
@@ -182,34 +262,32 @@ int pa_memblockq_push(pa_memblockq* bq, const pa_memchunk *uchunk) {
     old = bq->write_index;
     chunk = *uchunk;
 
-    if (bq->read_index > bq->write_index) {
+    fix_current_write(bq);
+    q = bq->current_write;
 
-        /* We currently have a buffer underflow, we need to drop some
-         * incoming data */
+    /* First we advance the q pointer right of where we want to
+     * write to */
 
-        size_t d = bq->read_index - bq->write_index;
-
-        if (chunk.length > d) {
-            chunk.index += d;
-            chunk.length -= d;
-            bq->write_index += d;
-        } else {
-            /* We drop the incoming data completely */
-            bq->write_index += chunk.length;
-            goto finish;
-        }
+    if (q) {
+        while (bq->write_index + chunk.length > q->index)
+            if (q->next)
+                q = q->next;
+            else
+                break;
     }
 
+    if (!q)
+        q = bq->blocks_tail;
+
     /* We go from back to front to look for the right place to add
      * this new entry. Drop data we will overwrite on the way */
 
-    q = bq->blocks_tail;
     while (q) {
 
-        if (bq->write_index >= q->index + (int64_t) q->chunk.length)
+        if (bq->write_index >= q->index + 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 + 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 &&
@@ -364,6 +442,7 @@ static pa_bool_t memblockq_check_prebuf(pa_memblockq *bq) {
 }
 
 int pa_memblockq_peek(pa_memblockq* bq, pa_memchunk *chunk) {
+    int64_t d;
     pa_assert(bq);
     pa_assert(chunk);
 
@@ -371,27 +450,35 @@ int pa_memblockq_peek(pa_memblockq* bq, pa_memchunk *chunk) {
     if (memblockq_check_prebuf(bq))
         return -1;
 
+    fix_current_read(bq);
+
     /* Do we need to spit out silence? */
-    if (!bq->blocks || bq->blocks->index > bq->read_index) {
+    if (!bq->current_read || bq->current_read->index > bq->read_index) {
 
         size_t length;
 
         /* How much silence shall we return? */
-        length = bq->blocks ? bq->blocks->index - bq->read_index : 0;
+        if (bq->current_read)
+            length = bq->current_read->index - bq->read_index;
+        else if (bq->write_index > bq->read_index)
+            length = (size_t) (bq->write_index - bq->read_index);
+        else
+            length = 0;
 
         /* We need to return silence, since no data is yet available */
         if (bq->silence) {
+            size_t l;
+
             chunk->memblock = pa_memblock_ref(bq->silence);
 
-            if (!length || length > pa_memblock_get_length(chunk->memblock))
-                length = pa_memblock_get_length(chunk->memblock);
+            l = pa_memblock_get_length(chunk->memblock);
+            chunk->length = (length <= 0 || length > l) ? l : length;
 
-            chunk->length = length;
         } else {
 
             /* If the memblockq is empty, return -1, otherwise return
              * the time to sleep */
-            if (!bq->blocks)
+            if (length <= 0)
                 return -1;
 
             chunk->memblock = NULL;
@@ -403,11 +490,14 @@ int pa_memblockq_peek(pa_memblockq* bq, pa_memchunk *chunk) {
     }
 
     /* Ok, let's pass real data to the caller */
-    pa_assert(bq->blocks->index == bq->read_index);
-
-    *chunk = bq->blocks->chunk;
+    *chunk = bq->current_read->chunk;
     pa_memblock_ref(chunk->memblock);
 
+    pa_assert(bq->read_index >= bq->current_read->index);
+    d = bq->read_index - bq->current_read->index;
+    chunk->index += d;
+    chunk->length -= d;
+
     return 0;
 }
 
@@ -424,42 +514,23 @@ void pa_memblockq_drop(pa_memblockq *bq, size_t length) {
         if (memblockq_check_prebuf(bq))
             break;
 
-        if (bq->blocks) {
-            size_t d;
-
-            pa_assert(bq->blocks->index >= bq->read_index);
-
-            d = (size_t) (bq->blocks->index - bq->read_index);
-
-            if (d >= length) {
-                /* The first block is too far in the future */
-
-                bq->read_index += length;
-                break;
-            } else {
-
-                length -= d;
-                bq->read_index += d;
-            }
+        fix_current_read(bq);
 
-            pa_assert(bq->blocks->index == bq->read_index);
+        if (bq->current_read) {
+            int64_t p, d;
 
-            if (bq->blocks->chunk.length <= length) {
-                /* We need to drop the full block */
+            /* We go through this piece by piece to make sure we don't
+             * drop more than allowed by prebuf */
 
-                length -= bq->blocks->chunk.length;
-                bq->read_index += bq->blocks->chunk.length;
+            p = bq->current_read->index + bq->current_read->chunk.length;
+            pa_assert(p >= bq->read_index);
+            d = p - bq->read_index;
 
-                drop_block(bq, bq->blocks);
-            } else {
-                /* Only the start of this block needs to be dropped */
+            if (d > length)
+                d = length;
 
-                bq->blocks->chunk.index += length;
-                bq->blocks->chunk.length -= length;
-                bq->blocks->index += length;
-                bq->read_index += length;
-                break;
-            }
+            bq->read_index += d;
+            length -= d;
 
         } else {
 
@@ -469,20 +540,22 @@ void pa_memblockq_drop(pa_memblockq *bq, size_t length) {
         }
     }
 
+    drop_backlog(bq);
+
     delta = bq->read_index - old;
     bq->missing += delta;
 }
 
-int pa_memblockq_is_readable(pa_memblockq *bq) {
+pa_bool_t pa_memblockq_is_readable(pa_memblockq *bq) {
     pa_assert(bq);
 
     if (memblockq_check_prebuf(bq))
-        return 0;
+        return FALSE;
 
     if (pa_memblockq_get_length(bq) <= 0)
-        return 0;
+        return FALSE;
 
-    return 1;
+    return TRUE;
 }
 
 size_t pa_memblockq_get_length(pa_memblockq *bq) {
@@ -506,12 +579,6 @@ size_t pa_memblockq_missing(pa_memblockq *bq) {
     return l >= bq->minreq ? l : 0;
 }
 
-size_t pa_memblockq_get_minreq(pa_memblockq *bq) {
-    pa_assert(bq);
-
-    return bq->minreq;
-}
-
 void pa_memblockq_seek(pa_memblockq *bq, int64_t offset, pa_seek_mode_t seek) {
     int64_t old, delta;
     pa_assert(bq);
@@ -535,6 +602,8 @@ void pa_memblockq_seek(pa_memblockq *bq, int64_t offset, pa_seek_mode_t seek) {
             pa_assert_not_reached();
     }
 
+    drop_backlog(bq);
+
     delta = bq->write_index - old;
 
     if (delta >= bq->requested) {
@@ -564,7 +633,7 @@ void pa_memblockq_flush(pa_memblockq *bq) {
 
     delta = bq->write_index - old;
 
-    if (delta > bq->requested) {
+    if (delta >= bq->requested) {
         delta -= bq->requested;
         bq->requested = 0;
     } else if (delta >= 0) {
@@ -581,13 +650,21 @@ size_t pa_memblockq_get_tlength(pa_memblockq *bq) {
     return bq->tlength;
 }
 
+size_t pa_memblockq_get_minreq(pa_memblockq *bq) {
+    pa_assert(bq);
+
+    return bq->minreq;
+}
+
 int64_t pa_memblockq_get_read_index(pa_memblockq *bq) {
     pa_assert(bq);
+
     return bq->read_index;
 }
 
 int64_t pa_memblockq_get_write_index(pa_memblockq *bq) {
     pa_assert(bq);
+
     return bq->write_index;
 }
 
@@ -600,9 +677,6 @@ int pa_memblockq_push_align(pa_memblockq* bq, const pa_memchunk *chunk) {
     if (bq->base == 1)
         return pa_memblockq_push(bq, chunk);
 
-    if (!bq->mcalign)
-        bq->mcalign = pa_mcalign_new(bq->base);
-
     if (!can_push(bq, pa_mcalign_csize(bq->mcalign, chunk->length)))
         return -1;
 
@@ -613,23 +687,15 @@ int pa_memblockq_push_align(pa_memblockq* bq, const pa_memchunk *chunk) {
         r = pa_memblockq_push(bq, &rchunk);
         pa_memblock_unref(rchunk.memblock);
 
-        if (r < 0)
+        if (r < 0) {
+            pa_mcalign_flush(bq->mcalign);
             return -1;
+        }
     }
 
     return 0;
 }
 
-void pa_memblockq_shorten(pa_memblockq *bq, size_t length) {
-    size_t l;
-    pa_assert(bq);
-
-    l = pa_memblockq_get_length(bq);
-
-    if (l > length)
-        pa_memblockq_drop(bq, l - length);
-}
-
 void pa_memblockq_prebuf_disable(pa_memblockq *bq) {
     pa_assert(bq);
 
@@ -639,7 +705,7 @@ void pa_memblockq_prebuf_disable(pa_memblockq *bq) {
 void pa_memblockq_prebuf_force(pa_memblockq *bq) {
     pa_assert(bq);
 
-    if (!bq->in_prebuf && bq->prebuf > 0)
+    if (bq->prebuf > 0)
         bq->in_prebuf = TRUE;
 }
 
@@ -710,7 +776,7 @@ void pa_memblockq_set_tlength(pa_memblockq *bq, size_t tlength) {
 void pa_memblockq_set_prebuf(pa_memblockq *bq, size_t prebuf) {
     pa_assert(bq);
 
-    bq->prebuf = (prebuf == (size_t) -1) ? bq->tlength/2 : prebuf;
+    bq->prebuf = (prebuf == (size_t) -1) ? bq->tlength : prebuf;
     bq->prebuf = ((bq->prebuf+bq->base-1)/bq->base)*bq->base;
 
     if (prebuf > 0 && bq->prebuf < bq->base)
@@ -737,3 +803,73 @@ void pa_memblockq_set_minreq(pa_memblockq *bq, size_t minreq) {
     if (bq->minreq < bq->base)
         bq->minreq = bq->base;
 }
+
+void pa_memblockq_set_maxrewind(pa_memblockq *bq, size_t maxrewind) {
+    pa_assert(bq);
+
+    bq->maxrewind = (maxrewind/bq->base)*bq->base;
+}
+
+void pa_memblockq_rewind(pa_memblockq *bq, size_t length) {
+    pa_assert(bq);
+    pa_assert(length % bq->base == 0);
+
+    bq->read_index -= length;
+    bq->missing -= length;
+}
+
+int pa_memblockq_splice(pa_memblockq *bq, pa_memblockq *source) {
+
+    pa_assert(bq);
+    pa_assert(source);
+
+    pa_memblockq_prebuf_disable(bq);
+
+    for (;;) {
+        pa_memchunk chunk;
+
+        if (pa_memblockq_peek(source, &chunk) < 0)
+            return 0;
+
+        pa_assert(chunk.length > 0);
+
+        if (chunk.memblock) {
+
+            if (pa_memblockq_push_align(bq, &chunk) < 0) {
+                pa_memblock_unref(chunk.memblock);
+                return -1;
+            }
+
+            pa_memblock_unref(chunk.memblock);
+        } else
+            pa_memblockq_seek(bq, chunk.length, PA_SEEK_RELATIVE);
+
+        pa_memblockq_drop(bq, chunk.length);
+    }
+}
+
+void pa_memblockq_willneed(pa_memblockq *bq) {
+    struct list_item *q;
+
+    pa_assert(bq);
+
+    fix_current_read(bq);
+
+    for (q = bq->current_read; q; q = q->next)
+        pa_memchunk_will_need(&q->chunk);
+}
+
+void pa_memblockq_set_silence(pa_memblockq *bq, pa_memblock *silence) {
+    pa_assert(bq);
+
+    if (bq->silence)
+        pa_memblock_unref(bq->silence);
+
+    bq->silence = silence ? pa_memblock_ref(silence) : NULL;
+}
+
+pa_bool_t pa_memblockq_is_empty(pa_memblockq *bq) {
+    pa_assert(bq);
+
+    return !bq->blocks;
+}
diff --git a/src/pulsecore/memblockq.h b/src/pulsecore/memblockq.h
index 46637f1..8610a1a 100644
--- a/src/pulsecore/memblockq.h
+++ b/src/pulsecore/memblockq.h
@@ -62,6 +62,8 @@ typedef struct pa_memblockq pa_memblockq;
    - minreq:    pa_memblockq_missing() will only return values greater
                 than this value. Pass 0 for the default.
 
+   - maxrewind: how many bytes of history to keep in the queue
+
    - silence:   return this memblock when reading unitialized data
 */
 pa_memblockq* pa_memblockq_new(
@@ -71,6 +73,7 @@ pa_memblockq* pa_memblockq_new(
         size_t base,
         size_t prebuf,
         size_t minreq,
+        size_t maxrewind,
         pa_memblock *silence);
 
 void pa_memblockq_free(pa_memblockq*bq);
@@ -95,7 +98,7 @@ int pa_memblockq_peek(pa_memblockq* bq, pa_memchunk *chunk);
 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);
+pa_bool_t pa_memblockq_is_readable(pa_memblockq *bq);
 
 /* Return the length of the queue in bytes */
 size_t pa_memblockq_get_length(pa_memblockq *bq);
@@ -107,6 +110,9 @@ size_t pa_memblockq_missing(pa_memblockq *bq);
  * this function, reset the internal counter to 0. */
 size_t pa_memblockq_pop_missing(pa_memblockq *bq);
 
+/* Directly moves the data from the source memblockq into bq */
+int pa_memblockq_splice(pa_memblockq *bq, pa_memblockq *source);
+
 /* Returns the minimal request value */
 size_t pa_memblockq_get_minreq(pa_memblockq *bq);
 
@@ -125,10 +131,8 @@ int64_t pa_memblockq_get_read_index(pa_memblockq *bq);
 /* Return the current write index */
 int64_t pa_memblockq_get_write_index(pa_memblockq *bq);
 
-/* Shorten the pa_memblockq to the specified length by dropping data
- * at the read end of the queue. The read index is increased until the
- * queue has the specified length */
-void pa_memblockq_shorten(pa_memblockq *bq, size_t length);
+/* Rewind the read index. If the history is shorter than the specified length we'll point to silence afterwards. */
+void pa_memblockq_rewind(pa_memblockq *bq, size_t length);
 
 /* Ignore prebuf for now */
 void pa_memblockq_prebuf_disable(pa_memblockq *bq);
@@ -142,10 +146,20 @@ size_t pa_memblockq_get_maxlength(pa_memblockq *bq);
 /* Return the prebuffer length in bytes */
 size_t pa_memblockq_get_prebuf(pa_memblockq *bq);
 
-/* Change metrics. */
-void pa_memblockq_set_maxlength(pa_memblockq *memblockq, size_t maxlength);
-void pa_memblockq_set_tlength(pa_memblockq *memblockq, size_t tlength);
-void pa_memblockq_set_prebuf(pa_memblockq *memblockq, size_t prebuf);
+/* Change metrics. Always call in order. */
+void pa_memblockq_set_maxlength(pa_memblockq *memblockq, size_t maxlength); /* might modify tlength, prebuf, minreq too */
+void pa_memblockq_set_tlength(pa_memblockq *memblockq, size_t tlength); /* might modify minreq, too */
+void pa_memblockq_set_prebuf(pa_memblockq *memblockq, size_t prebuf); /* might modify minreq, too */
 void pa_memblockq_set_minreq(pa_memblockq *memblockq, size_t minreq);
+void pa_memblockq_set_maxrewind(pa_memblockq *memblockq, size_t rewind); /* Set the maximum history size */
+void pa_memblockq_set_silence(pa_memblockq *memblockq, pa_memblock *silence);
+
+/* Call pa_memchunk_willneed() for every chunk in the queue from the current read pointer to the end */
+void pa_memblockq_willneed(pa_memblockq *bq);
+
+/* Check whether the memblockq is completely empty, i.e. no data
+ * neither left nor right of the read pointer, and hence no buffered
+ * data for the future nor data in the backlog. */
+pa_bool_t pa_memblockq_is_empty(pa_memblockq *bq);
 
 #endif
diff --git a/src/pulsecore/namereg.c b/src/pulsecore/namereg.c
index fe52038..1b0977d 100644
--- a/src/pulsecore/namereg.c
+++ b/src/pulsecore/namereg.c
@@ -179,7 +179,7 @@ void pa_namereg_unregister(pa_core *c, const char *name) {
     pa_xfree(e);
 }
 
-void* pa_namereg_get(pa_core *c, const char *name, pa_namereg_type_t type, int autoload) {
+void* pa_namereg_get(pa_core *c, const char *name, pa_namereg_type_t type, pa_bool_t autoload) {
     struct namereg_entry *e;
     uint32_t idx;
     pa_assert(c);
diff --git a/src/pulsecore/namereg.h b/src/pulsecore/namereg.h
index d0db9e8..0f5b4d4 100644
--- a/src/pulsecore/namereg.h
+++ b/src/pulsecore/namereg.h
@@ -39,7 +39,7 @@ void pa_namereg_free(pa_core *c);
 
 const char *pa_namereg_register(pa_core *c, const char *name, pa_namereg_type_t type, void *data, int fail);
 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);
+void* pa_namereg_get(pa_core *c, const char *name, pa_namereg_type_t type, pa_bool_t autoload);
 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);
diff --git a/src/pulsecore/native-common.h b/src/pulsecore/native-common.h
index 3ab2361..51f2b30 100644
--- a/src/pulsecore/native-common.h
+++ b/src/pulsecore/native-common.h
@@ -126,7 +126,7 @@ enum {
     PA_COMMAND_SUSPEND_SINK,
     PA_COMMAND_SUSPEND_SOURCE,
 
-    /* Supported since protocol v13 (0.9.8) */
+    /* Supported since protocol v12 (0.9.8) */
     PA_COMMAND_SET_PLAYBACK_STREAM_BUFFER_ATTR,
     PA_COMMAND_SET_RECORD_STREAM_BUFFER_ATTR,
 
@@ -139,6 +139,14 @@ enum {
     PA_COMMAND_PLAYBACK_STREAM_MOVED,
     PA_COMMAND_RECORD_STREAM_MOVED,
 
+    /* Supported since protocol v13 (0.9.10) */
+    PA_COMMAND_UPDATE_RECORD_STREAM_PROPLIST,
+    PA_COMMAND_UPDATE_PLAYBACK_STREAM_PROPLIST,
+    PA_COMMAND_UPDATE_CLIENT_PROPLIST,
+    PA_COMMAND_REMOVE_RECORD_STREAM_PROPLIST,
+    PA_COMMAND_REMOVE_PLAYBACK_STREAM_PROPLIST,
+    PA_COMMAND_REMOVE_CLIENT_PROPLIST,
+
     PA_COMMAND_MAX
 };
 
diff --git a/src/pulsecore/play-memblockq.c b/src/pulsecore/play-memblockq.c
index 5d3c2d3..bad60ae 100644
--- a/src/pulsecore/play-memblockq.c
+++ b/src/pulsecore/play-memblockq.c
@@ -34,6 +34,7 @@
 #include <pulsecore/sink-input.h>
 #include <pulsecore/gccmacro.h>
 #include <pulsecore/thread-mq.h>
+#include <pulsecore/sample-util.h>
 
 #include "play-memblockq.h"
 
@@ -59,7 +60,6 @@ static void memblockq_stream_unlink(memblockq_stream *u) {
         return;
 
     pa_sink_input_unlink(u->sink_input);
-
     pa_sink_input_unref(u->sink_input);
     u->sink_input = NULL;
 
@@ -70,8 +70,6 @@ static void memblockq_stream_free(pa_object *o) {
     memblockq_stream *u = MEMBLOCKQ_STREAM(o);
     pa_assert(u);
 
-    memblockq_stream_unlink(u);
-
     if (u->memblockq)
         pa_memblockq_free(u->memblockq);
 
@@ -92,15 +90,19 @@ static int memblockq_stream_process_msg(pa_msgobject *o, int code, void*userdata
 }
 
 static void sink_input_kill_cb(pa_sink_input *i) {
+    memblockq_stream *u;
+
     pa_sink_input_assert_ref(i);
+    u = MEMBLOCKQ_STREAM(i->userdata);
+    memblockq_stream_assert_ref(u);
 
-    memblockq_stream_unlink(MEMBLOCKQ_STREAM(i->userdata));
+    memblockq_stream_unlink(u);
 }
 
-static int sink_input_peek_cb(pa_sink_input *i, size_t length, pa_memchunk *chunk) {
+static int sink_input_pop_cb(pa_sink_input *i, size_t nbytes, pa_memchunk *chunk) {
     memblockq_stream *u;
 
-    pa_assert(i);
+    pa_sink_input_assert_ref(i);
     pa_assert(chunk);
     u = MEMBLOCKQ_STREAM(i->userdata);
     memblockq_stream_assert_ref(u);
@@ -109,36 +111,56 @@ static int sink_input_peek_cb(pa_sink_input *i, size_t length, pa_memchunk *chun
         return -1;
 
     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);
+
+        if (pa_sink_input_safe_to_remove(i)) {
+
+            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;
     }
 
+    pa_memblockq_drop(u->memblockq, chunk->length);
+
     return 0;
 }
 
-static void sink_input_drop_cb(pa_sink_input *i, size_t length) {
+static void sink_input_rewind_cb(pa_sink_input *i, size_t nbytes) {
+    memblockq_stream *u;
+
+    pa_sink_input_assert_ref(i);
+    pa_assert(nbytes > 0);
+    u = MEMBLOCKQ_STREAM(i->userdata);
+    memblockq_stream_assert_ref(u);
+
+    if (!u->memblockq)
+        return;
+
+    pa_memblockq_rewind(u->memblockq, nbytes);
+}
+
+static void sink_input_set_max_rewind(pa_sink_input *i, size_t nbytes) {
     memblockq_stream *u;
 
-    pa_assert(i);
-    pa_assert(length > 0);
+    pa_sink_input_assert_ref(i);
     u = MEMBLOCKQ_STREAM(i->userdata);
     memblockq_stream_assert_ref(u);
 
     if (!u->memblockq)
         return;
 
-    pa_memblockq_drop(u->memblockq, length);
+    pa_memblockq_set_maxrewind(u->memblockq, nbytes);
 }
 
 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) {
+        pa_cvolume *volume,
+        pa_proplist *p) {
 
     memblockq_stream *u = NULL;
     pa_sink_input_new_data data;
@@ -149,41 +171,35 @@ pa_sink_input* pa_memblockq_sink_input_new(
     /* 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 NULL;
-    }
-
-    if (volume && pa_cvolume_is_muted(volume)) {
-        pa_memblockq_free(q);
-        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;
+    u->memblockq = NULL;
 
     pa_sink_input_new_data_init(&data);
     data.sink = sink;
-    data.name = name;
     data.driver = __FILE__;
     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);
+    pa_proplist_update(data.proplist, PA_UPDATE_REPLACE, p);
 
-    if (!(u->sink_input = pa_sink_input_new(sink->core, &data, 0)))
+    u->sink_input = pa_sink_input_new(sink->core, &data, 0);
+    pa_sink_input_new_data_done(&data);
+
+    if (!u->sink_input)
         goto fail;
 
-    u->sink_input->peek = sink_input_peek_cb;
-    u->sink_input->drop = sink_input_drop_cb;
+    u->sink_input->pop = sink_input_pop_cb;
+    u->sink_input->rewind = sink_input_rewind_cb;
+    u->sink_input->set_max_rewind = sink_input_set_max_rewind;
     u->sink_input->kill = sink_input_kill_cb;
     u->sink_input->userdata = u;
 
     if (q)
-        pa_memblockq_prebuf_disable(q);
+        pa_memblockq_sink_input_set_queue(u->sink_input, q);
 
     /* The reference to u is dangling here, because we want
      * to keep this stream around until it is fully played. */
@@ -202,11 +218,12 @@ fail:
 
 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_cvolume *volume,
+        pa_proplist *p,
+        uint32_t *sink_input_index) {
 
     pa_sink_input *i;
 
@@ -214,10 +231,14 @@ int pa_play_memblockq(
     pa_assert(ss);
     pa_assert(q);
 
-    if (!(i = pa_memblockq_sink_input_new(sink, name, ss, map, q, volume)))
+    if (!(i = pa_memblockq_sink_input_new(sink, ss, map, q, volume, p)))
         return -1;
 
     pa_sink_input_put(i);
+
+    if (sink_input_index)
+        *sink_input_index = i->index;
+
     pa_sink_input_unref(i);
 
     return 0;
@@ -232,5 +253,20 @@ void pa_memblockq_sink_input_set_queue(pa_sink_input *i, pa_memblockq *q) {
 
     if (u->memblockq)
         pa_memblockq_free(u->memblockq);
-    u->memblockq = q;
+
+    if ((u->memblockq = q)) {
+        pa_memblock *silence;
+
+        pa_memblockq_set_prebuf(q, 0);
+
+        silence = pa_silence_memblock_new(
+                i->sink->core->mempool,
+                &i->sample_spec,
+                i->thread_info.resampler ? pa_resampler_max_block_size(i->thread_info.resampler) : 0);
+
+        pa_memblockq_set_silence(q, silence);
+        pa_memblock_unref(silence);
+
+        pa_memblockq_willneed(q);
+    }
 }
diff --git a/src/pulsecore/play-memblockq.h b/src/pulsecore/play-memblockq.h
index d879031..9ecf770 100644
--- a/src/pulsecore/play-memblockq.h
+++ b/src/pulsecore/play-memblockq.h
@@ -29,20 +29,21 @@
 
 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);
+        pa_cvolume *volume,
+        pa_proplist *p);
 
 void pa_memblockq_sink_input_set_queue(pa_sink_input *i, pa_memblockq *q);
 
 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 *cvolume);
+    pa_cvolume *cvolume,
+    pa_proplist *p,
+    uint32_t *sink_input_index);
 
 #endif
diff --git a/src/pulsecore/play-memchunk.c b/src/pulsecore/play-memchunk.c
index 6aaec56..c528b1d 100644
--- a/src/pulsecore/play-memchunk.c
+++ b/src/pulsecore/play-memchunk.c
@@ -34,163 +34,33 @@
 #include <pulsecore/sink-input.h>
 #include <pulsecore/gccmacro.h>
 #include <pulsecore/thread-mq.h>
+#include <pulsecore/play-memblockq.h>
 
 #include "play-memchunk.h"
 
-typedef struct memchunk_stream {
-    pa_msgobject parent;
-    pa_core *core;
-    pa_sink_input *sink_input;
-    pa_memchunk memchunk;
-} memchunk_stream;
-
-enum {
-    MEMCHUNK_STREAM_MESSAGE_UNLINK,
-};
-
-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 void memchunk_stream_free(pa_object *o) {
-    memchunk_stream *u = MEMCHUNK_STREAM(o);
-    pa_assert(u);
-
-    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);
-
-    switch (code) {
-        case MEMCHUNK_STREAM_MESSAGE_UNLINK:
-            memchunk_stream_unlink(u);
-            break;
-    }
-
-    return 0;
-}
-
-static void sink_input_kill_cb(pa_sink_input *i) {
-    pa_sink_input_assert_ref(i);
-
-    memchunk_stream_unlink(MEMCHUNK_STREAM(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);
-
-    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;
-    }
-
-    pa_assert(u->memchunk.memblock);
-    *chunk = u->memchunk;
-    pa_memblock_ref(chunk->memblock);
-
-    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(
         pa_sink *sink,
-        const char *name,
         const pa_sample_spec *ss,
         const pa_channel_map *map,
         const pa_memchunk *chunk,
-        pa_cvolume *volume) {
+        pa_cvolume *volume,
+        pa_proplist *p,
+        uint32_t *sink_input_index) {
 
-    memchunk_stream *u = NULL;
-    pa_sink_input_new_data data;
+    pa_memblockq *q;
+    int r;
 
     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.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 (!(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;
+    q = pa_memblockq_new(0, chunk->length, 0, pa_frame_size(ss), 0, 0, 0, NULL);
+    pa_assert_se(pa_memblockq_push(q, chunk) >= 0);
 
-    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. */
+    if ((r = pa_play_memblockq(sink, ss, map, q, volume, p, sink_input_index)) < 0) {
+        pa_memblockq_free(q);
+        return r;
+    }
 
     return 0;
-
-fail:
-    if (u)
-        memchunk_stream_unref(u);
-
-    return -1;
 }
-
diff --git a/src/pulsecore/play-memchunk.h b/src/pulsecore/play-memchunk.h
index 5afb094..f7c9d17 100644
--- a/src/pulsecore/play-memchunk.h
+++ b/src/pulsecore/play-memchunk.h
@@ -29,10 +29,11 @@
 
 int pa_play_memchunk(
     pa_sink *sink,
-    const char *name,
     const pa_sample_spec *ss,
     const pa_channel_map *map,
     const pa_memchunk *chunk,
-    pa_cvolume *cvolume);
+    pa_cvolume *cvolume,
+    pa_proplist *p,
+    uint32_t *sink_input_index);
 
 #endif
diff --git a/src/pulsecore/protocol-esound.c b/src/pulsecore/protocol-esound.c
index 004e535..972e8e1 100644
--- a/src/pulsecore/protocol-esound.c
+++ b/src/pulsecore/protocol-esound.c
@@ -149,8 +149,7 @@ typedef struct proto_handler {
     const char *description;
 } esd_proto_handler_info_t;
 
-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 int sink_input_pop_cb(pa_sink_input *i, size_t length, pa_memchunk *chunk);
 static void sink_input_kill_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);
@@ -410,14 +409,16 @@ static int esd_proto_stream_play(connection *c, PA_GCC_UNUSED esd_proto_t reques
     pa_assert(!c->sink_input && !c->input_memblockq);
 
     pa_sink_input_new_data_init(&sdata);
-    sdata.sink = sink;
     sdata.driver = __FILE__;
-    sdata.name = c->client->name;
-    pa_sink_input_new_data_set_sample_spec(&sdata, &ss);
     sdata.module = c->protocol->module;
     sdata.client = c->client;
+    sdata.sink = sink;
+    pa_proplist_update(sdata.proplist, PA_UPDATE_MERGE, c->client->proplist);
+    pa_sink_input_new_data_set_sample_spec(&sdata, &ss);
 
     c->sink_input = pa_sink_input_new(c->protocol->core, &sdata, 0);
+    pa_sink_input_new_data_done(&sdata);
+
     CHECK_VALIDITY(c->sink_input, "Failed to create sink input.");
 
     l = (size_t) (pa_bytes_per_second(&ss)*PLAYBACK_BUFFER_SECONDS);
@@ -428,13 +429,13 @@ static int esd_proto_stream_play(connection *c, PA_GCC_UNUSED esd_proto_t reques
             pa_frame_size(&ss),
             (size_t) -1,
             l/PLAYBACK_BUFFER_FRAGMENTS,
+            0,
             NULL);
     pa_iochannel_socket_set_rcvbuf(c->io, l/PLAYBACK_BUFFER_FRAGMENTS*2);
     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->pop = sink_input_pop_cb;
     c->sink_input->kill = sink_input_kill_cb;
     c->sink_input->userdata = c;
 
@@ -509,14 +510,16 @@ static int esd_proto_stream_record(connection *c, esd_proto_t request, const voi
     pa_assert(!c->output_memblockq && !c->source_output);
 
     pa_source_output_new_data_init(&sdata);
-    sdata.source = source;
     sdata.driver = __FILE__;
-    sdata.name = c->client->name;
-    pa_source_output_new_data_set_sample_spec(&sdata, &ss);
     sdata.module = c->protocol->module;
     sdata.client = c->client;
+    sdata.source = source;
+    pa_proplist_update(sdata.proplist, PA_UPDATE_MERGE, c->client->proplist);
+    pa_source_output_new_data_set_sample_spec(&sdata, &ss);
+
+    c->source_output = pa_source_output_new(c->protocol->core, &sdata, 0);
+    pa_source_output_new_data_done(&sdata);
 
-    c->source_output = pa_source_output_new(c->protocol->core, &sdata, 9);
     CHECK_VALIDITY(c->source_output, "Failed to create source_output.");
 
     l = (size_t) (pa_bytes_per_second(&ss)*RECORD_BUFFER_SECONDS);
@@ -527,6 +530,7 @@ static int esd_proto_stream_record(connection *c, esd_proto_t request, const voi
             pa_frame_size(&ss),
             1,
             0,
+            0,
             NULL);
     pa_iochannel_socket_set_sndbuf(c->io, l/RECORD_BUFFER_FRAGMENTS*2);
 
@@ -638,8 +642,8 @@ static int esd_proto_all_info(connection *c, esd_proto_t request, const void *da
         memset(name, 0, ESD_NAME_MAX); /* don't leak old data */
         if (conn->original_name)
             strncpy(name, conn->original_name, ESD_NAME_MAX);
-        else if (conn->client && conn->client->name)
-            strncpy(name, conn->client->name, ESD_NAME_MAX);
+        else if (conn->client && pa_proplist_gets(conn->client->proplist, PA_PROP_APPLICATION_NAME))
+            strncpy(name, pa_proplist_gets(conn->client->proplist, PA_PROP_APPLICATION_NAME), ESD_NAME_MAX);
         connection_write(c, name, ESD_NAME_MAX);
 
         /* rate */
@@ -800,7 +804,7 @@ static int esd_proto_sample_cache(connection *c, PA_GCC_UNUSED esd_proto_t reque
 
     c->state = ESD_CACHING_SAMPLE;
 
-    pa_scache_add_item(c->protocol->core, c->scache.name, NULL, NULL, NULL, &idx);
+    pa_scache_add_item(c->protocol->core, c->scache.name, NULL, NULL, NULL, c->client->proplist, &idx);
 
     idx += 1;
     connection_write(c, &idx, sizeof(uint32_t));
@@ -851,7 +855,7 @@ static int esd_proto_sample_free_or_play(connection *c, esd_proto_t request, con
             pa_sink *sink;
 
             if ((sink = pa_namereg_get(c->protocol->core, c->protocol->sink_name, PA_NAMEREG_SINK, 1)))
-                if (pa_scache_play_item(c->protocol->core, name, sink, PA_VOLUME_NORM) >= 0)
+                if (pa_scache_play_item(c->protocol->core, name, sink, PA_VOLUME_NORM, c->client->proplist, NULL) >= 0)
                     ok = idx + 1;
         } else {
             pa_assert(request == ESD_PROTO_SAMPLE_FREE);
@@ -992,7 +996,7 @@ static int do_read(connection *c) {
             uint32_t idx;
 
             c->scache.memchunk.index = 0;
-            pa_scache_add_item(c->protocol->core, c->scache.name, &c->scache.sample_spec, NULL, &c->scache.memchunk, &idx);
+            pa_scache_add_item(c->protocol->core, c->scache.name, &c->scache.sample_spec, NULL, &c->scache.memchunk, c->client->proplist, &idx);
 
             pa_memblock_unref(c->scache.memchunk.memblock);
             c->scache.memchunk.memblock = NULL;
@@ -1237,7 +1241,7 @@ static int sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int
 }
 
 /* Called from thread context */
-static int sink_input_peek_cb(pa_sink_input *i, size_t length, pa_memchunk *chunk) {
+static int sink_input_pop_cb(pa_sink_input *i, size_t length, pa_memchunk *chunk) {
     connection*c;
     int r;
 
@@ -1246,32 +1250,25 @@ static int sink_input_peek_cb(pa_sink_input *i, size_t length, pa_memchunk *chun
     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);
+    if ((r = pa_memblockq_peek(c->input_memblockq, chunk)) < 0) {
 
-    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"); */
+        if (c->dead && pa_sink_input_safe_to_remove(i))
+            pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(c), CONNECTION_MESSAGE_UNLINK_CONNECTION, NULL, 0, NULL, NULL);
+    } else {
+        size_t old, new;
 
-    old = pa_memblockq_missing(c->input_memblockq);
-    pa_memblockq_drop(c->input_memblockq, length);
-    new = pa_memblockq_missing(c->input_memblockq);
+        old = pa_memblockq_missing(c->input_memblockq);
+        pa_memblockq_drop(c->input_memblockq, chunk->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);
+        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);
+        }
     }
+
+    return r;
 }
 
 static void sink_input_kill_cb(pa_sink_input *i) {
@@ -1349,7 +1346,7 @@ static void on_connection(pa_socket_server*s, pa_iochannel *io, void *userdata)
     pa_iochannel_socket_peer_to_string(io, pname, sizeof(pname));
     pa_snprintf(cname, sizeof(cname), "EsounD client (%s)", pname);
     c->client = pa_client_new(p->core, __FILE__, cname);
-    c->client->owner = p->module;
+    c->client->module = p->module;
     c->client->kill = client_kill_cb;
     c->client->userdata = c;
 
diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c
index 4f58279..811cc80 100644
--- a/src/pulsecore/protocol-native.c
+++ b/src/pulsecore/protocol-native.c
@@ -98,17 +98,17 @@ typedef struct playback_stream {
 
     pa_sink_input *sink_input;
     pa_memblockq *memblockq;
-    int drain_request;
+    pa_bool_t drain_request;
     uint32_t drain_tag;
     uint32_t syncid;
-    int underrun;
+    pa_bool_t underrun;
 
     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;
+    size_t render_memblockq_length;
 } playback_stream;
 
 typedef struct upload_stream {
@@ -122,12 +122,13 @@ typedef struct upload_stream {
     char *name;
     pa_sample_spec sample_spec;
     pa_channel_map channel_map;
+    pa_proplist *proplist;
 } upload_stream;
 
 struct connection {
     pa_msgobject parent;
 
-    int authorized;
+    pa_bool_t authorized;
     uint32_t version;
     pa_protocol_native *protocol;
     pa_client *client;
@@ -162,11 +163,11 @@ static PA_DEFINE_CHECK_TYPE(connection, pa_msgobject);
 struct pa_protocol_native {
     pa_module *module;
     pa_core *core;
-    int public;
+    pa_bool_t public;
     pa_socket_server *server;
     pa_idxset *connections;
     uint8_t auth_cookie[PA_NATIVE_COOKIE_LENGTH];
-    int auth_cookie_in_property;
+    pa_bool_t auth_cookie_in_property;
 #ifdef HAVE_CREDS
     char *auth_group;
 #endif
@@ -199,8 +200,7 @@ enum {
     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 int sink_input_pop_cb(pa_sink_input *i, size_t length, pa_memchunk *chunk);
 static void sink_input_kill_cb(pa_sink_input *i);
 static void sink_input_suspend_cb(pa_sink_input *i, pa_bool_t suspend);
 static void sink_input_moved_cb(pa_sink_input *i);
@@ -254,6 +254,8 @@ static void command_move_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag
 static void command_suspend(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
 static void command_set_stream_buffer_attr(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
 static void command_update_stream_sample_rate(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
+static void command_update_proplist(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
+static void command_remove_proplist(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,
@@ -335,7 +337,15 @@ static const pa_pdispatch_cb_t command_table[PA_COMMAND_MAX] = {
     [PA_COMMAND_SET_RECORD_STREAM_BUFFER_ATTR] = command_set_stream_buffer_attr,
 
     [PA_COMMAND_UPDATE_PLAYBACK_STREAM_SAMPLE_RATE] = command_update_stream_sample_rate,
-    [PA_COMMAND_UPDATE_RECORD_STREAM_SAMPLE_RATE] = command_update_stream_sample_rate
+    [PA_COMMAND_UPDATE_RECORD_STREAM_SAMPLE_RATE] = command_update_stream_sample_rate,
+
+    [PA_COMMAND_UPDATE_RECORD_STREAM_PROPLIST] = command_update_proplist,
+    [PA_COMMAND_UPDATE_PLAYBACK_STREAM_PROPLIST] = command_update_proplist,
+    [PA_COMMAND_UPDATE_CLIENT_PROPLIST] = command_update_proplist,
+
+    [PA_COMMAND_REMOVE_RECORD_STREAM_PROPLIST] = command_remove_proplist,
+    [PA_COMMAND_REMOVE_PLAYBACK_STREAM_PROPLIST] = command_remove_proplist,
+    [PA_COMMAND_REMOVE_CLIENT_PROPLIST] = command_remove_proplist,
 };
 
 /* structure management */
@@ -359,6 +369,9 @@ static void upload_stream_free(pa_object *o) {
 
     pa_xfree(s->name);
 
+    if (s->proplist)
+        pa_proplist_free(s->proplist);
+
     if (s->memchunk.memblock)
         pa_memblock_unref(s->memchunk.memblock);
 
@@ -369,7 +382,9 @@ static upload_stream* upload_stream_new(
         connection *c,
         const pa_sample_spec *ss,
         const pa_channel_map *map,
-        const char *name, size_t length) {
+        const char *name,
+        size_t length,
+        pa_proplist *p) {
 
     upload_stream *s;
 
@@ -377,6 +392,7 @@ static upload_stream* upload_stream_new(
     pa_assert(ss);
     pa_assert(name);
     pa_assert(length > 0);
+    pa_assert(p);
 
     s = pa_msgobject_new(upload_stream);
     s->parent.parent.parent.free = upload_stream_free;
@@ -386,6 +402,8 @@ static upload_stream* upload_stream_new(
     s->name = pa_xstrdup(name);
     pa_memchunk_reset(&s->memchunk);
     s->length = length;
+    s->proplist = pa_proplist_copy(p);
+    pa_proplist_update(s->proplist, PA_UPDATE_MERGE, c->client->proplist);
 
     pa_idxset_put(c->output_streams, s, &s->index);
 
@@ -452,7 +470,8 @@ static record_stream* record_stream_new(
         const char *name,
         uint32_t *maxlength,
         uint32_t fragment_size,
-        pa_source_output_flags_t flags) {
+        pa_source_output_flags_t flags,
+        pa_proplist *p) {
 
     record_stream *s;
     pa_source_output *source_output;
@@ -464,17 +483,24 @@ static record_stream* record_stream_new(
     pa_assert(name);
     pa_assert(maxlength);
     pa_assert(*maxlength > 0);
+    pa_assert(p);
 
     pa_source_output_new_data_init(&data);
+
+    pa_proplist_update(data.proplist, PA_UPDATE_REPLACE, p);
+    pa_proplist_update(data.proplist, PA_UPDATE_MERGE, c->client->proplist);
+    data.driver = __FILE__;
     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);
 
-    if (!(source_output = pa_source_output_new(c->protocol->core, &data, flags)))
+    source_output = pa_source_output_new(c->protocol->core, &data, flags);
+
+    pa_source_output_new_data_done(&data);
+
+    if (!source_output)
         return NULL;
 
     s = pa_msgobject_new(record_stream);
@@ -496,6 +522,7 @@ static record_stream* record_stream_new(
             base = pa_frame_size(&s->source_output->sample_spec),
             1,
             0,
+            0,
             NULL);
 
     *maxlength = pa_memblockq_get_maxlength(s->memblockq);
@@ -633,7 +660,8 @@ static playback_stream* playback_stream_new(
         pa_cvolume *volume,
         uint32_t syncid,
         uint32_t *missing,
-        pa_sink_input_flags_t flags) {
+        pa_sink_input_flags_t flags,
+        pa_proplist *p) {
 
     playback_stream *s, *ssync;
     pa_sink_input *sink_input;
@@ -646,6 +674,7 @@ static playback_stream* playback_stream_new(
     pa_assert(ss);
     pa_assert(name);
     pa_assert(maxlength);
+    pa_assert(p);
 
     /* Find syncid group */
     for (ssync = pa_idxset_first(c->output_streams, &idx); ssync; ssync = pa_idxset_next(c->output_streams, &idx)) {
@@ -667,17 +696,23 @@ static playback_stream* playback_stream_new(
     }
 
     pa_sink_input_new_data_init(&data);
-    data.sink = sink;
+
+    pa_proplist_update(data.proplist, PA_UPDATE_REPLACE, p);
+    pa_proplist_update(data.proplist, PA_UPDATE_MERGE, c->client->proplist);
     data.driver = __FILE__;
-    data.name = name;
+    data.module = c->protocol->module;
+    data.client = c->client;
+    data.sink = sink;
     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);
-    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, flags)))
+    sink_input = pa_sink_input_new(c->protocol->core, &data, flags);
+
+    pa_sink_input_new_data_done(&data);
+
+    if (!sink_input)
         return NULL;
 
     s = pa_msgobject_new(playback_stream);
@@ -686,11 +721,10 @@ static playback_stream* playback_stream_new(
     s->connection = c;
     s->syncid = syncid;
     s->sink_input = sink_input;
-    s->underrun = 1;
+    s->underrun = TRUE;
 
     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->pop = sink_input_pop_cb;
     s->sink_input->kill = sink_input_kill_cb;
     s->sink_input->moved = sink_input_moved_cb;
     s->sink_input->suspend = sink_input_suspend_cb;
@@ -707,6 +741,7 @@ static playback_stream* playback_stream_new(
             pa_frame_size(&s->sink_input->sample_spec),
             *prebuf,
             *minreq,
+            0,
             silence);
 
     pa_memblock_unref(silence);
@@ -722,7 +757,7 @@ static playback_stream* playback_stream_new(
 
     s->minreq = pa_memblockq_get_minreq(s->memblockq);
     pa_atomic_store(&s->missing, 0);
-    s->drain_request = 0;
+    s->drain_request = FALSE;
 
     pa_idxset_put(c->output_streams, s, &s->index);
 
@@ -909,7 +944,7 @@ static int sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int
 
             request_bytes(s);
 
-            s->underrun = 0;
+            s->underrun = FALSE;
             return 0;
         }
 
@@ -921,7 +956,7 @@ static int sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int
                 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;
+                s->drain_request = TRUE;
             }
             request_bytes(s);
 
@@ -953,21 +988,21 @@ static int sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int
             }
 
             func(s->memblockq);
-            s->underrun = 0;
+            s->underrun = FALSE;
             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;
+                ssync->underrun = FALSE;
                 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;
+                ssync->underrun = FALSE;
                 request_bytes(ssync);
             }
 
@@ -978,7 +1013,7 @@ static int sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int
 
             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;
+            s->render_memblockq_length = pa_memblockq_get_length(s->sink_input->thread_info.render_memblockq);
             return 0;
 
         case PA_SINK_INPUT_MESSAGE_SET_STATE:
@@ -1002,7 +1037,7 @@ static int sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int
 }
 
 /* Called from thread context */
-static int sink_input_peek_cb(pa_sink_input *i, size_t length, pa_memchunk *chunk) {
+static int sink_input_pop_cb(pa_sink_input *i, size_t length, pa_memchunk *chunk) {
     playback_stream *s;
 
     pa_sink_input_assert_ref(i);
@@ -1010,42 +1045,23 @@ static int sink_input_peek_cb(pa_sink_input *i, size_t length, pa_memchunk *chun
     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");     */
-        return -1;
-    }
-
-/*     pa_log("peek: %u", chunk->length); */
 
-    request_bytes(s);
-
-    return 0;
-}
-
-/* Called from thread context */
-static void sink_input_drop_cb(pa_sink_input *i, size_t length) {
-    playback_stream *s;
-
-    pa_sink_input_assert_ref(i);
-    s = PLAYBACK_STREAM(i->userdata);
-    playback_stream_assert_ref(s);
-    pa_assert(length > 0);
-
-    pa_memblockq_drop(s->memblockq, length);
+        if (s->drain_request && pa_sink_input_safe_to_remove(i)) {
+            s->drain_request = FALSE;
+            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);
+        } else if (!s->underrun) {
+            s->underrun = TRUE;
+            pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(s), PLAYBACK_STREAM_MESSAGE_UNDERFLOW, NULL, 0, NULL, NULL);
+        }
 
-    if (s->drain_request && !pa_memblockq_is_readable(s->memblockq)) {
-        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);
+        return -1;
     }
 
+    pa_memblockq_drop(s->memblockq, chunk->length);
     request_bytes(s);
 
-/*     pa_log("after_drop: %u %u", pa_memblockq_get_length(s->memblockq), pa_memblockq_is_readable(s->memblockq)); */
+    return 0;
 }
 
 /* Called from main context */
@@ -1207,7 +1223,7 @@ static void command_create_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GC
     connection *c = CONNECTION(userdata);
     playback_stream *s;
     uint32_t maxlength, tlength, prebuf, minreq, sink_index, syncid, missing;
-    const char *name, *sink_name;
+    const char *name = NULL, *sink_name;
     pa_sample_spec ss;
     pa_channel_map map;
     pa_tagstruct *reply;
@@ -1216,29 +1232,45 @@ static void command_create_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GC
     int corked;
     int no_remap = 0, no_remix = 0, fix_format = 0, fix_rate = 0, fix_channels = 0, no_move = 0, variable_rate = 0;
     pa_sink_input_flags_t flags = 0;
+    pa_proplist *p;
 
     connection_assert_ref(c);
     pa_assert(t);
 
-    if (pa_tagstruct_get(
-            t,
-            PA_TAG_STRING, &name,
-            PA_TAG_SAMPLE_SPEC, &ss,
-            PA_TAG_CHANNEL_MAP, &map,
-            PA_TAG_U32, &sink_index,
-            PA_TAG_STRING, &sink_name,
-            PA_TAG_U32, &maxlength,
-            PA_TAG_BOOLEAN, &corked,
-            PA_TAG_U32, &tlength,
-            PA_TAG_U32, &prebuf,
-            PA_TAG_U32, &minreq,
-            PA_TAG_U32, &syncid,
-            PA_TAG_CVOLUME, &volume,
-            PA_TAG_INVALID) < 0 || !name) {
+    if ((c->version < 13 && (pa_tagstruct_gets(t, &name) < 0 || !name)) ||
+        pa_tagstruct_get(
+                t,
+                PA_TAG_SAMPLE_SPEC, &ss,
+                PA_TAG_CHANNEL_MAP, &map,
+                PA_TAG_U32, &sink_index,
+                PA_TAG_STRING, &sink_name,
+                PA_TAG_U32, &maxlength,
+                PA_TAG_BOOLEAN, &corked,
+                PA_TAG_U32, &tlength,
+                PA_TAG_U32, &prebuf,
+                PA_TAG_U32, &minreq,
+                PA_TAG_U32, &syncid,
+                PA_TAG_CVOLUME, &volume,
+                PA_TAG_INVALID) < 0) {
+
         protocol_error(c);
         return;
     }
 
+    CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
+    CHECK_VALIDITY(c->pstream, sink_index != PA_INVALID_INDEX || !sink_name || (*sink_name && pa_utf8_valid(sink_name)), tag, PA_ERR_INVALID);
+    CHECK_VALIDITY(c->pstream, pa_channel_map_valid(&map), tag, PA_ERR_INVALID);
+    CHECK_VALIDITY(c->pstream, pa_sample_spec_valid(&ss), tag, PA_ERR_INVALID);
+    CHECK_VALIDITY(c->pstream, pa_cvolume_valid(&volume), tag, PA_ERR_INVALID);
+    CHECK_VALIDITY(c->pstream, map.channels == ss.channels && volume.channels == ss.channels, tag, PA_ERR_INVALID);
+    CHECK_VALIDITY(c->pstream, maxlength > 0, tag, PA_ERR_INVALID);
+    CHECK_VALIDITY(c->pstream, maxlength <= MAX_MEMBLOCKQ_LENGTH, tag, PA_ERR_INVALID);
+
+    p = pa_proplist_new();
+
+    if (name)
+        pa_proplist_sets(p, PA_PROP_MEDIA_NAME, name);
+
     if (c->version >= 12)  {
         /* Since 0.9.8 the user can ask for a couple of additional flags */
 
@@ -1249,32 +1281,43 @@ static void command_create_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GC
             pa_tagstruct_get_boolean(t, &fix_channels) < 0 ||
             pa_tagstruct_get_boolean(t, &no_move) < 0 ||
             pa_tagstruct_get_boolean(t, &variable_rate) < 0) {
+
+            protocol_error(c);
+            pa_proplist_free(p);
+            return;
+        }
+    }
+
+    if (c->version >= 13) {
+
+        if (pa_tagstruct_get_proplist(t, p) < 0) {
             protocol_error(c);
+            pa_proplist_free(p);
             return;
         }
     }
 
     if (!pa_tagstruct_eof(t)) {
         protocol_error(c);
+        pa_proplist_free(p);
         return;
     }
 
-    CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
-    CHECK_VALIDITY(c->pstream, name && pa_utf8_valid(name), tag, PA_ERR_INVALID);
-    CHECK_VALIDITY(c->pstream, sink_index != PA_INVALID_INDEX || !sink_name || (*sink_name && pa_utf8_valid(name)), tag, PA_ERR_INVALID);
-    CHECK_VALIDITY(c->pstream, pa_channel_map_valid(&map), tag, PA_ERR_INVALID);
-    CHECK_VALIDITY(c->pstream, pa_sample_spec_valid(&ss), tag, PA_ERR_INVALID);
-    CHECK_VALIDITY(c->pstream, pa_cvolume_valid(&volume), tag, PA_ERR_INVALID);
-    CHECK_VALIDITY(c->pstream, map.channels == ss.channels && volume.channels == ss.channels, tag, PA_ERR_INVALID);
-    CHECK_VALIDITY(c->pstream, maxlength > 0, tag, PA_ERR_INVALID);
-    CHECK_VALIDITY(c->pstream, maxlength <= MAX_MEMBLOCKQ_LENGTH, tag, PA_ERR_INVALID);
-
     if (sink_index != PA_INVALID_INDEX) {
-        sink = pa_idxset_get_by_index(c->protocol->core->sinks, sink_index);
-        CHECK_VALIDITY(c->pstream, sink, tag, PA_ERR_NOENTITY);
+
+        if (!(sink = pa_idxset_get_by_index(c->protocol->core->sinks, sink_index))) {
+            pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY);
+            pa_proplist_free(p);
+            return;
+        }
+
     } else if (sink_name) {
-        sink = pa_namereg_get(c->protocol->core, sink_name, PA_NAMEREG_SINK, 1);
-        CHECK_VALIDITY(c->pstream, sink, tag, PA_ERR_NOENTITY);
+
+        if (!(sink = pa_namereg_get(c->protocol->core, sink_name, PA_NAMEREG_SINK, 1))) {
+            pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY);
+            pa_proplist_free(p);
+            return;
+        }
     }
 
     flags =
@@ -1287,7 +1330,9 @@ static void command_create_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GC
         (no_move ?  PA_SINK_INPUT_DONT_MOVE : 0) |
         (variable_rate ?  PA_SINK_INPUT_VARIABLE_RATE : 0);
 
-    s = playback_stream_new(c, sink, &ss, &map, name, &maxlength, &tlength, &prebuf, &minreq, &volume, syncid, &missing, flags);
+    s = playback_stream_new(c, sink, &ss, &map, name, &maxlength, &tlength, &prebuf, &minreq, &volume, syncid, &missing, flags, p);
+    pa_proplist_free(p);
+
     CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_INVALID);
 
     reply = reply_new(tag);
@@ -1395,11 +1440,12 @@ static void command_create_record_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_
     int corked;
     int no_remap = 0, no_remix = 0, fix_format = 0, fix_rate = 0, fix_channels = 0, no_move = 0, variable_rate = 0;
     pa_source_output_flags_t flags = 0;
+    pa_proplist *p;
 
     connection_assert_ref(c);
     pa_assert(t);
 
-    if (pa_tagstruct_gets(t, &name) < 0 ||
+    if ((c->version < 13 && (pa_tagstruct_gets(t, &name) < 0 || !name)) ||
         pa_tagstruct_get_sample_spec(t, &ss) < 0 ||
         pa_tagstruct_get_channel_map(t, &map) < 0 ||
         pa_tagstruct_getu32(t, &source_index) < 0 ||
@@ -1411,6 +1457,19 @@ static void command_create_record_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_
         return;
     }
 
+    CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
+    CHECK_VALIDITY(c->pstream, pa_sample_spec_valid(&ss), tag, PA_ERR_INVALID);
+    CHECK_VALIDITY(c->pstream, pa_channel_map_valid(&map), tag, PA_ERR_INVALID);
+    CHECK_VALIDITY(c->pstream, source_index != PA_INVALID_INDEX || !source_name || (*source_name && pa_utf8_valid(source_name)), tag, PA_ERR_INVALID);
+    CHECK_VALIDITY(c->pstream, map.channels == ss.channels, tag, PA_ERR_INVALID);
+    CHECK_VALIDITY(c->pstream, maxlength > 0, tag, PA_ERR_INVALID);
+    CHECK_VALIDITY(c->pstream, maxlength <= MAX_MEMBLOCKQ_LENGTH, tag, PA_ERR_INVALID);
+
+    p = pa_proplist_new();
+
+    if (name)
+        pa_proplist_sets(p, PA_PROP_MEDIA_NAME, name);
+
     if (c->version >= 12)  {
         /* Since 0.9.8 the user can ask for a couple of additional flags */
 
@@ -1421,16 +1480,45 @@ static void command_create_record_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_
             pa_tagstruct_get_boolean(t, &fix_channels) < 0 ||
             pa_tagstruct_get_boolean(t, &no_move) < 0 ||
             pa_tagstruct_get_boolean(t, &variable_rate) < 0) {
+
+            protocol_error(c);
+            pa_proplist_free(p);
+            return;
+        }
+    }
+
+    if (c->version >= 13) {
+
+        if (pa_tagstruct_get_proplist(t, p) < 0) {
             protocol_error(c);
+            pa_proplist_free(p);
             return;
         }
     }
 
     if (!pa_tagstruct_eof(t)) {
         protocol_error(c);
+        pa_proplist_free(p);
         return;
     }
 
+    if (source_index != PA_INVALID_INDEX) {
+
+        if (!(source = pa_idxset_get_by_index(c->protocol->core->sources, source_index))) {
+            pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY);
+            pa_proplist_free(p);
+            return;
+        }
+
+    } else if (source_name) {
+
+        if (!(source = pa_namereg_get(c->protocol->core, source_name, PA_NAMEREG_SOURCE, 1))) {
+            pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY);
+            pa_proplist_free(p);
+            return;
+        }
+    }
+
     flags =
         (corked ?  PA_SOURCE_OUTPUT_START_CORKED : 0) |
         (no_remap ?  PA_SOURCE_OUTPUT_NO_REMAP : 0) |
@@ -1441,24 +1529,9 @@ static void command_create_record_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_
         (no_move ?  PA_SOURCE_OUTPUT_DONT_MOVE : 0) |
         (variable_rate ?  PA_SOURCE_OUTPUT_VARIABLE_RATE : 0);
 
-    CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
-    CHECK_VALIDITY(c->pstream, name && pa_utf8_valid(name), tag, PA_ERR_INVALID);
-    CHECK_VALIDITY(c->pstream, pa_sample_spec_valid(&ss), tag, PA_ERR_INVALID);
-    CHECK_VALIDITY(c->pstream, pa_channel_map_valid(&map), tag, PA_ERR_INVALID);
-    CHECK_VALIDITY(c->pstream, source_index != PA_INVALID_INDEX || !source_name || (*source_name && pa_utf8_valid(source_name)), tag, PA_ERR_INVALID);
-    CHECK_VALIDITY(c->pstream, map.channels == ss.channels, tag, PA_ERR_INVALID);
-    CHECK_VALIDITY(c->pstream, maxlength > 0, tag, PA_ERR_INVALID);
-    CHECK_VALIDITY(c->pstream, maxlength <= MAX_MEMBLOCKQ_LENGTH, tag, PA_ERR_INVALID);
-
-    if (source_index != PA_INVALID_INDEX) {
-        source = pa_idxset_get_by_index(c->protocol->core->sources, source_index);
-        CHECK_VALIDITY(c->pstream, source, tag, PA_ERR_NOENTITY);
-    } else if (source_name) {
-        source = pa_namereg_get(c->protocol->core, source_name, PA_NAMEREG_SOURCE, 1);
-        CHECK_VALIDITY(c->pstream, source, tag, PA_ERR_NOENTITY);
-    }
+    s = record_stream_new(c, source, &ss, &map, name, &maxlength, fragment_size, flags, p);
+    pa_proplist_free(p);
 
-    s = record_stream_new(c, source, &ss, &map, name, &maxlength, fragment_size, flags);
     CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_INVALID);
 
     reply = reply_new(tag);
@@ -1511,6 +1584,7 @@ static void command_auth(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t
     connection *c = CONNECTION(userdata);
     const void*cookie;
     pa_tagstruct *reply;
+    char tmp[16];
 
     connection_assert_ref(c);
     pa_assert(t);
@@ -1528,6 +1602,9 @@ static void command_auth(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t
         return;
     }
 
+    pa_snprintf(tmp, sizeof(tmp), "%u", c->version);
+    pa_proplist_sets(c->client->proplist, "native-protocol.version", tmp);
+
     if (!c->authorized) {
         int success = 0;
 
@@ -1579,7 +1656,7 @@ static void command_auth(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t
             return;
         }
 
-        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;
@@ -1607,21 +1684,42 @@ 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) {
     connection *c = CONNECTION(userdata);
-    const char *name;
+    const char *name = NULL;
+    pa_proplist *p;
+    pa_tagstruct *reply;
 
     connection_assert_ref(c);
     pa_assert(t);
 
-    if (pa_tagstruct_gets(t, &name) < 0 ||
+    p = pa_proplist_new();
+
+    if ((c->version < 13 && pa_tagstruct_gets(t, &name) < 0) ||
+        (c->version >= 13 && pa_tagstruct_get_proplist(t, p) < 0) ||
         !pa_tagstruct_eof(t)) {
+
         protocol_error(c);
+        pa_proplist_free(p);
         return;
     }
 
-    CHECK_VALIDITY(c->pstream, name && pa_utf8_valid(name), tag, PA_ERR_INVALID);
+    if (name)
+        if (pa_proplist_sets(p, PA_PROP_APPLICATION_NAME, name) < 0) {
+            pa_pstream_send_error(c->pstream, tag, PA_ERR_INVALID);
+            pa_proplist_free(p);
+            return;
+        }
 
-    pa_client_set_name(c->client, name);
-    pa_pstream_send_simple_ack(c->pstream, tag);
+    pa_proplist_update(c->client->proplist, PA_UPDATE_REPLACE, p);
+    pa_proplist_free(p);
+
+    pa_subscription_post(c->protocol->core, PA_SUBSCRIPTION_EVENT_CLIENT|PA_SUBSCRIPTION_EVENT_CHANGE, c->client->index);
+
+    reply = reply_new(tag);
+
+    if (c->version >= 13)
+        pa_tagstruct_putu32(reply, c->client->index);
+
+    pa_pstream_send_tagstruct(c->pstream, reply);
 }
 
 static void command_lookup(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
@@ -1737,7 +1835,7 @@ static void command_get_playback_latency(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_
     reply = reply_new(tag);
 
     latency = pa_sink_get_latency(s->sink_input->sink);
-    latency += pa_bytes_to_usec(s->resampled_chunk_length, &s->sink_input->sample_spec);
+    latency += pa_bytes_to_usec(s->render_memblockq_length, &s->sink_input->sample_spec);
 
     pa_tagstruct_put_usec(reply, latency);
 
@@ -1786,19 +1884,19 @@ static void command_create_upload_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_
     connection *c = CONNECTION(userdata);
     upload_stream *s;
     uint32_t length;
-    const char *name;
+    const char *name = NULL;
     pa_sample_spec ss;
     pa_channel_map map;
     pa_tagstruct *reply;
+    pa_proplist *p;
 
     connection_assert_ref(c);
     pa_assert(t);
 
-    if (pa_tagstruct_gets(t, &name) < 0 ||
+    if ((c->version < 13 && pa_tagstruct_gets(t, &name) < 0) ||
         pa_tagstruct_get_sample_spec(t, &ss) < 0 ||
         pa_tagstruct_get_channel_map(t, &map) < 0 ||
-        pa_tagstruct_getu32(t, &length) < 0 ||
-        !pa_tagstruct_eof(t)) {
+        pa_tagstruct_getu32(t, &length) < 0) {
         protocol_error(c);
         return;
     }
@@ -1809,9 +1907,24 @@ static void command_create_upload_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_
     CHECK_VALIDITY(c->pstream, map.channels == ss.channels, tag, PA_ERR_INVALID);
     CHECK_VALIDITY(c->pstream, (length % pa_frame_size(&ss)) == 0 && length > 0, tag, PA_ERR_INVALID);
     CHECK_VALIDITY(c->pstream, length <= PA_SCACHE_ENTRY_SIZE_MAX, tag, PA_ERR_TOOLARGE);
-    CHECK_VALIDITY(c->pstream, name && *name && pa_utf8_valid(name), tag, PA_ERR_INVALID);
 
-    s = upload_stream_new(c, &ss, &map, name, length);
+    if (c->version < 13)
+        CHECK_VALIDITY(c->pstream, name && *name && pa_utf8_valid(name), tag, PA_ERR_INVALID);
+
+    p = pa_proplist_new();
+
+    if (c->version >= 13 && pa_tagstruct_get_proplist(t, p) < 0) {
+        protocol_error(c);
+        pa_proplist_free(p);
+        return;
+    }
+
+    if (c->version < 13)
+        pa_proplist_sets(p, PA_PROP_MEDIA_NAME, name);
+
+    s = upload_stream_new(c, &ss, &map, name, length, p);
+    pa_proplist_free(p);
+
     CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_INVALID);
 
     reply = reply_new(tag);
@@ -1841,7 +1954,7 @@ static void command_finish_upload_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_
     CHECK_VALIDITY(c->pstream, s, 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)
+    if (pa_scache_add_item(c->protocol->core, s->name, &s->sample_spec, &s->channel_map, &s->memchunk, s->proplist, &idx) < 0)
         pa_pstream_send_error(c->pstream, tag, PA_ERR_INTERNAL);
     else
         pa_pstream_send_simple_ack(c->pstream, tag);
@@ -1855,20 +1968,23 @@ static void command_play_sample(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED ui
     pa_volume_t volume;
     pa_sink *sink;
     const char *name, *sink_name;
+    uint32_t idx;
+    pa_proplist *p;
+    pa_tagstruct *reply;
 
     connection_assert_ref(c);
     pa_assert(t);
 
+    CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
+
     if (pa_tagstruct_getu32(t, &sink_index) < 0 ||
         pa_tagstruct_gets(t, &sink_name) < 0 ||
         pa_tagstruct_getu32(t, &volume) < 0 ||
-        pa_tagstruct_gets(t, &name) < 0 ||
-        !pa_tagstruct_eof(t)) {
+        pa_tagstruct_gets(t, &name) < 0) {
         protocol_error(c);
         return;
     }
 
-    CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
     CHECK_VALIDITY(c->pstream, sink_index != PA_INVALID_INDEX || !sink_name || (*sink_name && pa_utf8_valid(name)), tag, PA_ERR_INVALID);
     CHECK_VALIDITY(c->pstream, name && *name && pa_utf8_valid(name), tag, PA_ERR_INVALID);
 
@@ -1879,12 +1995,29 @@ static void command_play_sample(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED ui
 
     CHECK_VALIDITY(c->pstream, sink, tag, PA_ERR_NOENTITY);
 
-    if (pa_scache_play_item(c->protocol->core, name, sink, volume) < 0) {
+    p = pa_proplist_new();
+
+    if ((c->version >= 13 && pa_tagstruct_get_proplist(t, p) < 0) ||
+        !pa_tagstruct_eof(t)) {
+        protocol_error(c);
+        pa_proplist_free(p);
+        return;
+    }
+
+    if (pa_scache_play_item(c->protocol->core, name, sink, volume, p, &idx) < 0) {
         pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY);
+        pa_proplist_free(p);
         return;
     }
 
-    pa_pstream_send_simple_ack(c->pstream, tag);
+    pa_proplist_free(p);
+
+    reply = reply_new(tag);
+
+    if (c->version >= 13)
+        pa_tagstruct_putu32(reply, idx);
+
+    pa_pstream_send_tagstruct(c->pstream, reply);
 }
 
 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) {
@@ -1941,7 +2074,7 @@ static void sink_fill_tagstruct(connection *c, pa_tagstruct *t, pa_sink *sink) {
         t,
         PA_TAG_U32, sink->index,
         PA_TAG_STRING, sink->name,
-        PA_TAG_STRING, sink->description,
+        PA_TAG_STRING, pa_strnull(pa_proplist_gets(sink->proplist, PA_PROP_DEVICE_DESCRIPTION)),
         PA_TAG_SAMPLE_SPEC, &fixed_ss,
         PA_TAG_CHANNEL_MAP, &sink->channel_map,
         PA_TAG_U32, sink->module ? sink->module->index : PA_INVALID_INDEX,
@@ -1953,6 +2086,9 @@ static void sink_fill_tagstruct(connection *c, pa_tagstruct *t, pa_sink *sink) {
         PA_TAG_STRING, sink->driver,
         PA_TAG_U32, sink->flags,
         PA_TAG_INVALID);
+
+    if (c->version >= 13)
+        pa_tagstruct_put_proplist(t, sink->proplist);
 }
 
 static void source_fill_tagstruct(connection *c, pa_tagstruct *t, pa_source *source) {
@@ -1967,7 +2103,7 @@ static void source_fill_tagstruct(connection *c, pa_tagstruct *t, pa_source *sou
         t,
         PA_TAG_U32, source->index,
         PA_TAG_STRING, source->name,
-        PA_TAG_STRING, source->description,
+        PA_TAG_STRING, pa_strnull(pa_proplist_gets(source->proplist, PA_PROP_DEVICE_DESCRIPTION)),
         PA_TAG_SAMPLE_SPEC, &fixed_ss,
         PA_TAG_CHANNEL_MAP, &source->channel_map,
         PA_TAG_U32, source->module ? source->module->index : PA_INVALID_INDEX,
@@ -1979,16 +2115,23 @@ static void source_fill_tagstruct(connection *c, pa_tagstruct *t, pa_source *sou
         PA_TAG_STRING, source->driver,
         PA_TAG_U32, source->flags,
         PA_TAG_INVALID);
+
+    if (c->version >= 13)
+        pa_tagstruct_put_proplist(t, source->proplist);
 }
 
-static void client_fill_tagstruct(pa_tagstruct *t, pa_client *client) {
+static void client_fill_tagstruct(connection *c, pa_tagstruct *t, pa_client *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);
+    pa_tagstruct_puts(t, pa_strnull(pa_proplist_gets(client->proplist, PA_PROP_APPLICATION_NAME)));
+    pa_tagstruct_putu32(t, client->module ? client->module->index : PA_INVALID_INDEX);
     pa_tagstruct_puts(t, client->driver);
+
+    if (c->version >= 13)
+        pa_tagstruct_put_proplist(t, client->proplist);
+
 }
 
 static void module_fill_tagstruct(pa_tagstruct *t, pa_module *module) {
@@ -2011,7 +2154,7 @@ static void sink_input_fill_tagstruct(connection *c, pa_tagstruct *t, pa_sink_in
     fixup_sample_spec(c, &fixed_ss, &s->sample_spec);
 
     pa_tagstruct_putu32(t, s->index);
-    pa_tagstruct_puts(t, s->name);
+    pa_tagstruct_puts(t, pa_strnull(pa_proplist_gets(s->proplist, PA_PROP_MEDIA_NAME)));
     pa_tagstruct_putu32(t, s->module ? s->module->index : PA_INVALID_INDEX);
     pa_tagstruct_putu32(t, s->client ? s->client->index : PA_INVALID_INDEX);
     pa_tagstruct_putu32(t, s->sink->index);
@@ -2024,6 +2167,8 @@ static void sink_input_fill_tagstruct(connection *c, pa_tagstruct *t, pa_sink_in
     pa_tagstruct_puts(t, s->driver);
     if (c->version >= 11)
         pa_tagstruct_put_boolean(t, pa_sink_input_get_mute(s));
+    if (c->version >= 13)
+        pa_tagstruct_put_proplist(t, s->proplist);
 }
 
 static void source_output_fill_tagstruct(connection *c, pa_tagstruct *t, pa_source_output *s) {
@@ -2035,7 +2180,7 @@ static void source_output_fill_tagstruct(connection *c, pa_tagstruct *t, pa_sour
     fixup_sample_spec(c, &fixed_ss, &s->sample_spec);
 
     pa_tagstruct_putu32(t, s->index);
-    pa_tagstruct_puts(t, s->name);
+    pa_tagstruct_puts(t, pa_strnull(pa_proplist_gets(s->proplist, PA_PROP_MEDIA_NAME)));
     pa_tagstruct_putu32(t, s->module ? s->module->index : PA_INVALID_INDEX);
     pa_tagstruct_putu32(t, s->client ? s->client->index : PA_INVALID_INDEX);
     pa_tagstruct_putu32(t, s->source->index);
@@ -2045,6 +2190,9 @@ static void source_output_fill_tagstruct(connection *c, pa_tagstruct *t, pa_sour
     pa_tagstruct_put_usec(t, pa_source_get_latency(s->source));
     pa_tagstruct_puts(t, pa_resample_method_to_string(pa_source_output_get_resample_method(s)));
     pa_tagstruct_puts(t, s->driver);
+
+    if (c->version >= 13)
+        pa_tagstruct_put_proplist(t, s->proplist);
 }
 
 static void scache_fill_tagstruct(connection *c, pa_tagstruct *t, pa_scache_entry *e) {
@@ -2064,6 +2212,9 @@ static void scache_fill_tagstruct(connection *c, pa_tagstruct *t, pa_scache_entr
     pa_tagstruct_putu32(t, e->memchunk.length);
     pa_tagstruct_put_boolean(t, e->lazy);
     pa_tagstruct_puts(t, e->filename);
+
+    if (c->version >= 13)
+        pa_tagstruct_put_proplist(t, e->proplist);
 }
 
 static void command_get_info(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
@@ -2133,7 +2284,7 @@ static void command_get_info(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, u
     else if (source)
         source_fill_tagstruct(c, reply, source);
     else if (client)
-        client_fill_tagstruct(reply, client);
+        client_fill_tagstruct(c, reply, client);
     else if (module)
         module_fill_tagstruct(reply, module);
     else if (si)
@@ -2188,7 +2339,7 @@ static void command_get_info_list(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t comma
             else if (command == PA_COMMAND_GET_SOURCE_INFO_LIST)
                 source_fill_tagstruct(c, reply, p);
             else if (command == PA_COMMAND_GET_CLIENT_INFO_LIST)
-                client_fill_tagstruct(reply, p);
+                client_fill_tagstruct(c, reply, p);
             else if (command == PA_COMMAND_GET_MODULE_INFO_LIST)
                 module_fill_tagstruct(reply, p);
             else if (command == PA_COMMAND_GET_SINK_INPUT_INFO_LIST)
@@ -2660,6 +2811,168 @@ static void command_update_stream_sample_rate(pa_pdispatch *pd, uint32_t command
     pa_pstream_send_simple_ack(c->pstream, tag);
 }
 
+static void command_update_proplist(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
+    connection *c = CONNECTION(userdata);
+    uint32_t idx;
+    uint32_t mode;
+    pa_proplist *p;
+
+    connection_assert_ref(c);
+    pa_assert(t);
+
+    CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
+
+    p = pa_proplist_new();
+
+    if (command == PA_COMMAND_UPDATE_CLIENT_PROPLIST) {
+
+        if (pa_tagstruct_getu32(t, &mode) < 0 ||
+            pa_tagstruct_get_proplist(t, p) < 0 ||
+            !pa_tagstruct_eof(t)) {
+            protocol_error(c);
+            pa_proplist_free(p);
+            return;
+        }
+
+    } else {
+
+        if (pa_tagstruct_getu32(t, &idx) < 0 ||
+            pa_tagstruct_getu32(t, &mode) < 0 ||
+            pa_tagstruct_get_proplist(t, p) < 0 ||
+            !pa_tagstruct_eof(t)) {
+            protocol_error(c);
+            pa_proplist_free(p);
+            return;
+        }
+    }
+
+    CHECK_VALIDITY(c->pstream, mode == PA_UPDATE_SET || mode == PA_UPDATE_MERGE || mode == PA_UPDATE_REPLACE, tag, PA_ERR_INVALID);
+
+    if (command == PA_COMMAND_UPDATE_PLAYBACK_STREAM_PROPLIST) {
+        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, playback_stream_isinstance(s), tag, PA_ERR_NOENTITY);
+
+        pa_proplist_update(s->sink_input->proplist, mode, p);
+        pa_subscription_post(c->protocol->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, s->sink_input->index);
+
+    } else if (command == PA_COMMAND_UPDATE_RECORD_STREAM_PROPLIST) {
+        record_stream *s;
+
+        s = pa_idxset_get_by_index(c->record_streams, idx);
+        CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
+
+        pa_proplist_update(s->source_output->proplist, mode, p);
+        pa_subscription_post(c->protocol->core, PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_CHANGE, s->source_output->index);
+    } else {
+        pa_assert(command == PA_COMMAND_UPDATE_CLIENT_PROPLIST);
+
+        pa_proplist_update(c->client->proplist, mode, p);
+        pa_subscription_post(c->protocol->core, PA_SUBSCRIPTION_EVENT_CLIENT|PA_SUBSCRIPTION_EVENT_CHANGE, c->client->index);
+    }
+
+    pa_pstream_send_simple_ack(c->pstream, tag);
+}
+
+static void command_remove_proplist(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
+    connection *c = CONNECTION(userdata);
+    uint32_t idx;
+    unsigned changed = 0;
+    pa_proplist *p;
+    pa_strlist *l = NULL;
+
+    connection_assert_ref(c);
+    pa_assert(t);
+
+    CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
+
+    if (command != PA_COMMAND_REMOVE_CLIENT_PROPLIST) {
+
+        if (pa_tagstruct_getu32(t, &idx) < 0) {
+            protocol_error(c);
+            return;
+        }
+    }
+
+    if (command == PA_COMMAND_REMOVE_PLAYBACK_STREAM_PROPLIST) {
+        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, playback_stream_isinstance(s), tag, PA_ERR_NOENTITY);
+
+        p = s->sink_input->proplist;
+
+    } else if (command == PA_COMMAND_REMOVE_RECORD_STREAM_PROPLIST) {
+        record_stream *s;
+
+        s = pa_idxset_get_by_index(c->record_streams, idx);
+        CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
+
+        p = s->source_output->proplist;
+    } else {
+        pa_assert(command == PA_COMMAND_REMOVE_CLIENT_PROPLIST);
+
+        p = c->client->proplist;
+    }
+
+    for (;;) {
+        const char *k;
+
+        if (pa_tagstruct_gets(t, &k) < 0) {
+            protocol_error(c);
+            pa_strlist_free(l);
+            return;
+        }
+
+        if (!k)
+            break;
+
+        l = pa_strlist_prepend(l, k);
+    }
+
+    if (!pa_tagstruct_eof(t)) {
+        protocol_error(c);
+        pa_strlist_free(l);
+        return;
+    }
+
+    for (;;) {
+        char *z;
+
+        l = pa_strlist_pop(l, &z);
+
+        if (!z)
+            break;
+
+        changed += pa_proplist_unset(p, z) >= 0;
+        pa_xfree(z);
+    }
+
+    pa_pstream_send_simple_ack(c->pstream, tag);
+
+    if (changed) {
+        if (command == PA_COMMAND_REMOVE_PLAYBACK_STREAM_PROPLIST) {
+            playback_stream *s;
+
+            s = pa_idxset_get_by_index(c->output_streams, idx);
+            pa_subscription_post(c->protocol->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, s->sink_input->index);
+
+        } else if (command == PA_COMMAND_REMOVE_RECORD_STREAM_PROPLIST) {
+            record_stream *s;
+
+            s = pa_idxset_get_by_index(c->record_streams, idx);
+            pa_subscription_post(c->protocol->core, PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_CHANGE, s->source_output->index);
+
+        } else {
+            pa_assert(command == PA_COMMAND_REMOVE_CLIENT_PROPLIST);
+            pa_subscription_post(c->protocol->core, PA_SUBSCRIPTION_EVENT_CLIENT|PA_SUBSCRIPTION_EVENT_CHANGE, c->client->index);
+        }
+    }
+}
+
 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) {
     connection *c = CONNECTION(userdata);
     const char *s;
@@ -3246,11 +3559,11 @@ static void on_connection(PA_GCC_UNUSED pa_socket_server*s, pa_iochannel *io, vo
     c->parent.parent.free = connection_free;
     c->parent.process_msg = connection_process_msg;
 
-    c->authorized = !!p->public;
+    c->authorized = p->public;
 
     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) {
@@ -3268,7 +3581,7 @@ static void on_connection(PA_GCC_UNUSED pa_socket_server*s, pa_iochannel *io, vo
     c->client = pa_client_new(p->core, __FILE__, cname);
     c->client->kill = client_kill_cb;
     c->client->userdata = c;
-    c->client->owner = p->module;
+    c->client->module = p->module;
 
     c->pstream = pa_pstream_new(p->core->mainloop, io, p->core->mempool);
 
@@ -3301,12 +3614,12 @@ static void on_connection(PA_GCC_UNUSED pa_socket_server*s, pa_iochannel *io, vo
 static int load_key(pa_protocol_native*p, const char*fn) {
     pa_assert(p);
 
-    p->auth_cookie_in_property = 0;
+    p->auth_cookie_in_property = FALSE;
 
     if (!fn && pa_authkey_prop_get(p->core, PA_NATIVE_COOKIE_PROPERTY_NAME, p->auth_cookie, sizeof(p->auth_cookie)) >= 0) {
         pa_log_info("using already loaded auth cookie.");
         pa_authkey_prop_ref(p->core, PA_NATIVE_COOKIE_PROPERTY_NAME);
-        p->auth_cookie_in_property = 1;
+        p->auth_cookie_in_property = TRUE;
         return 0;
     }
 
@@ -3319,7 +3632,7 @@ static int load_key(pa_protocol_native*p, const char*fn) {
     pa_log_info("loading cookie from disk.");
 
     if (pa_authkey_prop_put(p->core, PA_NATIVE_COOKIE_PROPERTY_NAME, p->auth_cookie, sizeof(p->auth_cookie)) >= 0)
-        p->auth_cookie_in_property = 1;
+        p->auth_cookie_in_property = TRUE;
 
     return 0;
 }
diff --git a/src/pulsecore/protocol-simple.c b/src/pulsecore/protocol-simple.c
index 777def3..3ee2a05 100644
--- a/src/pulsecore/protocol-simple.c
+++ b/src/pulsecore/protocol-simple.c
@@ -343,7 +343,7 @@ static int sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int
 }
 
 /* Called from thread context */
-static int sink_input_peek_cb(pa_sink_input *i, size_t length, pa_memchunk *chunk) {
+static int sink_input_pop_cb(pa_sink_input *i, size_t length, pa_memchunk *chunk) {
     connection *c;
     int r;
 
@@ -352,34 +352,25 @@ static int sink_input_peek_cb(pa_sink_input *i, size_t length, pa_memchunk *chun
     connection_assert_ref(c);
     pa_assert(chunk);
 
-    r = pa_memblockq_peek(c->input_memblockq, chunk);
+    if ((r = pa_memblockq_peek(c->input_memblockq, chunk)) < 0) {
 
-/*     pa_log("peeked %u %i", r >= 0 ? chunk->length: 0, r); */
+        if (c->dead && pa_sink_input_safe_to_remove(i))
+            pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(c), CONNECTION_MESSAGE_UNLINK_CONNECTION, NULL, 0, NULL, NULL);
 
-    if (c->dead && r < 0)
-        pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(c), CONNECTION_MESSAGE_UNLINK_CONNECTION, NULL, 0, NULL, NULL);
+    } else {
+        size_t old, new;
 
-    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, chunk->length);
+        new = pa_memblockq_missing(c->input_memblockq);
 
-    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);
+        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);
+        }
     }
+
+    return r;
 }
 
 /* Called from main context */
@@ -477,29 +468,38 @@ static void on_connection(pa_socket_server*s, pa_iochannel *io, void *userdata)
 
     pa_iochannel_socket_peer_to_string(io, cname, sizeof(cname));
     pa_assert_se(c->client = pa_client_new(p->core, __FILE__, cname));
-    c->client->owner = p->module;
+    c->client->module = p->module;
     c->client->kill = client_kill_cb;
     c->client->userdata = c;
 
     if (p->mode & PLAYBACK) {
         pa_sink_input_new_data data;
         size_t l;
+        pa_sink *sink;
+
+        if (!(sink = pa_namereg_get(c->protocol->core, c->protocol->sink_name, PA_NAMEREG_SINK, TRUE))) {
+            pa_log("Failed to get sink.");
+            goto fail;
+        }
 
         pa_sink_input_new_data_init(&data);
         data.driver = __FILE__;
-        data.name = c->client->name;
-        pa_sink_input_new_data_set_sample_spec(&data, &p->sample_spec);
         data.module = p->module;
         data.client = c->client;
+        data.sink = sink;
+        pa_proplist_update(data.proplist, PA_UPDATE_MERGE, c->client->proplist);
+        pa_sink_input_new_data_set_sample_spec(&data, &p->sample_spec);
 
-        if (!(c->sink_input = pa_sink_input_new(p->core, &data, 0))) {
+        c->sink_input = pa_sink_input_new(p->core, &data, 0);
+        pa_sink_input_new_data_done(&data);
+
+        if (!c->sink_input) {
             pa_log("Failed to create sink input.");
             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->pop = sink_input_pop_cb;
         c->sink_input->kill = sink_input_kill_cb;
         c->sink_input->userdata = c;
 
@@ -511,6 +511,7 @@ static void on_connection(pa_socket_server*s, pa_iochannel *io, void *userdata)
                 pa_frame_size(&p->sample_spec),
                 (size_t) -1,
                 l/PLAYBACK_BUFFER_FRAGMENTS,
+                0,
                 NULL);
         pa_iochannel_socket_set_rcvbuf(io, l/PLAYBACK_BUFFER_FRAGMENTS*5);
         c->playback.fragment_size = l/PLAYBACK_BUFFER_FRAGMENTS;
@@ -523,15 +524,25 @@ static void on_connection(pa_socket_server*s, pa_iochannel *io, void *userdata)
     if (p->mode & RECORD) {
         pa_source_output_new_data data;
         size_t l;
+        pa_source *source;
+
+        if (!(source = pa_namereg_get(c->protocol->core, c->protocol->source_name, PA_NAMEREG_SOURCE, TRUE))) {
+            pa_log("Failed to get source.");
+            goto fail;
+        }
 
         pa_source_output_new_data_init(&data);
         data.driver = __FILE__;
-        data.name = c->client->name;
-        pa_source_output_new_data_set_sample_spec(&data, &p->sample_spec);
         data.module = p->module;
         data.client = c->client;
+        data.source = source;
+        pa_proplist_update(data.proplist, PA_UPDATE_MERGE, c->client->proplist);
+        pa_source_output_new_data_set_sample_spec(&data, &p->sample_spec);
+
+        c->source_output = pa_source_output_new(p->core, &data, 0);
+        pa_source_output_new_data_done(&data);
 
-        if (!(c->source_output = pa_source_output_new(p->core, &data, 0))) {
+        if (!c->source_output) {
             pa_log("Failed to create source output.");
             goto fail;
         }
@@ -548,6 +559,7 @@ static void on_connection(pa_socket_server*s, pa_iochannel *io, void *userdata)
                 pa_frame_size(&p->sample_spec),
                 1,
                 0,
+                0,
                 NULL);
         pa_iochannel_socket_set_sndbuf(io, l/RECORD_BUFFER_FRAGMENTS*2);
 
diff --git a/src/pulsecore/pstream.c b/src/pulsecore/pstream.c
index 9d32a36..97ac2b0 100644
--- a/src/pulsecore/pstream.c
+++ b/src/pulsecore/pstream.c
@@ -374,7 +374,7 @@ void pa_pstream_send_memblock(pa_pstream*p, uint32_t channel, int64_t offset, pa
             i = pa_xnew(struct item_info, 1);
         i->type = PA_PSTREAM_ITEM_MEMBLOCK;
 
-        n = MIN(length, bsm);
+        n = PA_MIN(length, bsm);
         i->chunk.index = chunk->index + idx;
         i->chunk.length = n;
         i->chunk.memblock = pa_memblock_ref(chunk->memblock);
diff --git a/src/pulsecore/resampler.c b/src/pulsecore/resampler.c
index fe7f1ad..3d7e536 100644
--- a/src/pulsecore/resampler.c
+++ b/src/pulsecore/resampler.c
@@ -47,7 +47,7 @@
 #include "resampler.h"
 
 /* Number of samples of extra space we allow the resamplers to return */
-#define EXTRA_SAMPLES 128
+#define EXTRA_FRAMES 128
 
 struct pa_resampler {
     pa_resample_method_t method;
@@ -79,6 +79,15 @@ struct pa_resampler {
         unsigned i_counter;
     } trivial;
 
+    struct { /* data specific to the peak finder pseudo resampler */
+        unsigned o_counter;
+        unsigned i_counter;
+
+        float max_f[PA_CHANNELS_MAX];
+        int16_t max_i[PA_CHANNELS_MAX];
+
+    } peaks;
+
 #ifdef HAVE_LIBSAMPLERATE
     struct { /* data specific to libsamplerate */
         SRC_STATE *state;
@@ -99,6 +108,7 @@ 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);
+static int peaks_init(pa_resampler*r);
 #ifdef HAVE_LIBSAMPLERATE
 static int libsamplerate_init(pa_resampler*r);
 #endif
@@ -144,7 +154,8 @@ static int (* const init_table[])(pa_resampler*r) = {
     [PA_RESAMPLER_SPEEX_FIXED_BASE+10]     = speex_init,
     [PA_RESAMPLER_FFMPEG]                  = ffmpeg_init,
     [PA_RESAMPLER_AUTO]                    = NULL,
-    [PA_RESAMPLER_COPY]                    = copy_init
+    [PA_RESAMPLER_COPY]                    = copy_init,
+    [PA_RESAMPLER_PEAKS]                   = peaks_init,
 };
 
 static inline size_t sample_size(pa_sample_format_t f) {
@@ -242,9 +253,9 @@ pa_resampler* pa_resampler_new(
     if ((method >= PA_RESAMPLER_SPEEX_FIXED_BASE && method <= PA_RESAMPLER_SPEEX_FIXED_MAX) ||
         (method == PA_RESAMPLER_FFMPEG))
         r->work_format = PA_SAMPLE_S16NE;
-    else if (method == PA_RESAMPLER_TRIVIAL || method == PA_RESAMPLER_COPY) {
+    else if (method == PA_RESAMPLER_TRIVIAL || method == PA_RESAMPLER_COPY || method == PA_RESAMPLER_PEAKS) {
 
-        if (r->map_required || a->format != b->format) {
+        if (r->map_required || a->format != b->format || method == PA_RESAMPLER_PEAKS) {
 
             if (a->format == PA_SAMPLE_S32NE || a->format == PA_SAMPLE_S32RE ||
                 a->format == PA_SAMPLE_FLOAT32NE || a->format == PA_SAMPLE_FLOAT32RE ||
@@ -347,6 +358,12 @@ size_t pa_resampler_request(pa_resampler *r, size_t out_length) {
     return (((out_length / r->o_fz)*r->i_ss.rate)/r->o_ss.rate) * r->i_fz;
 }
 
+size_t pa_resampler_result(pa_resampler *r, size_t in_length) {
+    pa_assert(r);
+
+    return (((in_length / r->i_fz)*r->o_ss.rate)/r->i_ss.rate) * r->o_fz;
+}
+
 size_t pa_resampler_max_block_size(pa_resampler *r) {
     size_t block_size_max;
     pa_sample_spec ss;
@@ -358,22 +375,17 @@ size_t pa_resampler_max_block_size(pa_resampler *r) {
 
     /* 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;
+    ss.channels = PA_MAX(r->i_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;
+    ss.format = PA_MAX(r->i_ss.format, r->o_ss.format);
+    ss.format = PA_MAX(ss.format, r->work_format);
 
-    if (r->o_ss.rate > ss.rate)
-        ss.rate = r->o_ss.rate;
+    ss.rate = PA_MAX(r->i_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;
+    return (((block_size_max/fs - EXTRA_FRAMES)*r->i_ss.rate)/ss.rate)*r->i_fz;
 }
 
 void pa_resampler_reset(pa_resampler *r) {
@@ -420,7 +432,8 @@ static const char * const resample_methods[] = {
     "speex-fixed-10",
     "ffmpeg",
     "auto",
-    "copy"
+    "copy",
+    "peaks"
 };
 
 const char *pa_resample_method_to_string(pa_resample_method_t m) {
@@ -1069,7 +1082,7 @@ static pa_memchunk *resample(pa_resampler *r, pa_memchunk *input) {
     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_frames = ((in_n_frames*r->o_ss.rate)/r->i_ss.rate)+EXTRA_FRAMES;
     out_n_samples = out_n_frames * r->o_ss.channels;
 
     r->buf3.index = 0;
@@ -1400,6 +1413,114 @@ static int trivial_init(pa_resampler*r) {
     return 0;
 }
 
+/* Peak finder implementation */
+
+static void peaks_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;
+    unsigned start = 0;
+
+    pa_assert(r);
+    pa_assert(input);
+    pa_assert(output);
+    pa_assert(out_n_frames);
+
+    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->peaks.o_counter++) {
+        unsigned j;
+
+        j = ((r->peaks.o_counter * r->i_ss.rate) / r->o_ss.rate);
+        j = j > r->peaks.i_counter ? j - r->peaks.i_counter : 0;
+
+        if (j >= in_n_frames)
+            break;
+
+        pa_assert(o_index * fz < pa_memblock_get_length(output->memblock));
+
+
+        if (r->work_format == PA_SAMPLE_S16NE) {
+            unsigned i, c;
+            int16_t *s = (int16_t*) ((uint8_t*) src + fz * j);
+            int16_t *d = (int16_t*) ((uint8_t*) dst + fz * o_index);
+
+            for (i = start; i <= j; i++)
+                for (c = 0; c < r->o_ss.channels; c++, s++) {
+                    int16_t n;
+
+                    n = *s < 0 ? -*s : *s;
+
+                    if (n > r->peaks.max_i[c])
+                        r->peaks.max_i[c] = n;
+                }
+
+            for (c = 0; c < r->o_ss.channels; c++, d++)
+                 *d = r->peaks.max_i[c];
+
+            memset(r->peaks.max_i, 0, sizeof(r->peaks.max_i));
+        } else {
+            unsigned i, c;
+            float *s = (float*) ((uint8_t*) src + fz * j);
+            float *d = (float*) ((uint8_t*) dst + fz * o_index);
+
+            pa_assert(r->work_format == PA_SAMPLE_FLOAT32NE);
+
+            for (i = start; i <= j; i++)
+                for (c = 0; c < r->o_ss.channels; c++, s++) {
+                    float n = fabsf(*s);
+
+                    if (n > r->peaks.max_f[c])
+                        r->peaks.max_f[c] = n;
+                }
+
+            for (c = 0; c < r->o_ss.channels; c++, d++)
+                *d = r->peaks.max_f[c];
+
+            memset(r->peaks.max_f, 0, sizeof(r->peaks.max_f));
+        }
+    }
+
+    pa_memblock_release(input->memblock);
+    pa_memblock_release(output->memblock);
+
+    *out_n_frames = o_index;
+
+    r->peaks.i_counter += in_n_frames;
+
+    /* Normalize counters */
+    while (r->peaks.i_counter >= r->i_ss.rate) {
+        pa_assert(r->peaks.o_counter >= r->o_ss.rate);
+
+        r->peaks.i_counter -= r->i_ss.rate;
+        r->peaks.o_counter -= r->o_ss.rate;
+    }
+}
+
+static void peaks_update_rates_or_reset(pa_resampler *r) {
+    pa_assert(r);
+
+    r->peaks.i_counter = 0;
+    r->peaks.o_counter = 0;
+}
+
+static int peaks_init(pa_resampler*r) {
+    pa_assert(r);
+
+    r->peaks.o_counter = r->peaks.i_counter = 0;
+    memset(r->peaks.max_i, 0, sizeof(r->peaks.max_i));
+    memset(r->peaks.max_f, 0, sizeof(r->peaks.max_f));
+
+    r->impl_resample = peaks_resample;
+    r->impl_update_rates = peaks_update_rates_or_reset;
+    r->impl_reset = peaks_update_rates_or_reset;
+
+    return 0;
+}
+
 /*** 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) {
diff --git a/src/pulsecore/resampler.h b/src/pulsecore/resampler.h
index 82d0108..8534f5b 100644
--- a/src/pulsecore/resampler.h
+++ b/src/pulsecore/resampler.h
@@ -46,6 +46,7 @@ typedef enum pa_resample_method {
     PA_RESAMPLER_FFMPEG,
     PA_RESAMPLER_AUTO, /* automatic select based on sample format */
     PA_RESAMPLER_COPY,
+    PA_RESAMPLER_PEAKS,
     PA_RESAMPLER_MAX
 } pa_resample_method_t;
 
@@ -69,6 +70,9 @@ 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);
 
+/* Inverse of pa_resampler_request() */
+size_t pa_resampler_result(pa_resampler *r, size_t in_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);
 
diff --git a/src/pulsecore/rtpoll.c b/src/pulsecore/rtpoll.c
index 8300826..f7773be 100644
--- a/src/pulsecore/rtpoll.c
+++ b/src/pulsecore/rtpoll.c
@@ -99,7 +99,7 @@ struct pa_rtpoll_item {
 
 PA_STATIC_FLIST_DECLARE(items, 0, pa_xfree);
 
-static void signal_handler_noop(int s) { }
+static void signal_handler_noop(int s) { write(2, "signal\n", 7); }
 
 pa_rtpoll *pa_rtpoll_new(void) {
     pa_rtpoll *p;
diff --git a/src/pulsecore/sample-util.c b/src/pulsecore/sample-util.c
index 4ea5d44..4a532f2 100644
--- a/src/pulsecore/sample-util.c
+++ b/src/pulsecore/sample-util.c
@@ -43,26 +43,25 @@
 #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;
+    pa_memblock *b;
+
     pa_assert(pool);
     pa_assert(spec);
 
     if (length <= 0)
-        length = pa_bytes_per_second(spec)/20; /* 50 ms */
+        length = PA_MIN(pa_bytes_per_second(spec)/20, /* 50 ms */
+                        pa_mempool_block_size_max(pool));
 
     if (length > PA_SILENCE_MAX)
         length = PA_SILENCE_MAX;
 
-    fs = pa_frame_size(spec);
+    length = pa_frame_align(length, spec);
 
-    length = (length+fs-1)/fs;
-
-    if (length <= 0)
-        length = 1;
+    b = pa_silence_memblock(pa_memblock_new(pool, length), spec);
 
-    length *= fs;
+    pa_memblock_set_is_silence(b, TRUE);
 
-    return pa_silence_memblock(pa_memblock_new(pool, length), spec);
+    return b;
 }
 
 pa_memblock *pa_silence_memblock(pa_memblock* b, const pa_sample_spec *spec) {
@@ -74,6 +73,7 @@ pa_memblock *pa_silence_memblock(pa_memblock* b, const pa_sample_spec *spec) {
     data = pa_memblock_acquire(b);
     pa_silence_memory(data, pa_memblock_get_length(b), spec);
     pa_memblock_release(b);
+
     return b;
 }
 
@@ -631,6 +631,9 @@ void pa_volume_memchunk(
     pa_assert(c->length % pa_frame_size(spec) == 0);
     pa_assert(volume);
 
+    if (pa_memblock_is_silence(c->memblock))
+        return;
+
     if (pa_cvolume_channels_equal_to(volume, PA_VOLUME_NORM))
         return;
 
diff --git a/src/pulsecore/shmasyncq.c b/src/pulsecore/shmasyncq.c
new file mode 100644
index 0000000..7af2985
--- /dev/null
+++ b/src/pulsecore/shmasyncq.c
@@ -0,0 +1,222 @@
+/* $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 "fdsem.h"
+
+/* 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_shmasyncq {
+    pa_fdsem *read_fdsem, *write_fdsem;
+    pa_shmasyncq_data *data;
+};
+
+static int is_power_of_two(unsigned size) {
+    return !(size & (size - 1));
+}
+
+static int reduce(pa_shmasyncq *l, int value) {
+    return value & (unsigned) (l->n_elements - 1);
+}
+
+static pa_atomic_t* get_cell(pa_shmasyncq *l, unsigned i) {
+    pa_assert(i < l->data->n_elements);
+
+    return (pa_atomic_t*) ((uint8*t) l->data + PA_ALIGN(sizeof(pa_shmasyncq_data)) + i * (PA_ALIGN(sizeof(pa_atomic_t)) + PA_ALIGN(element_size)))
+}
+
+static void *get_cell_data(pa_atomic_t *a) {
+    return (uint8_t*) a + PA_ALIGN(sizeof(atomic_t));
+}
+
+pa_shmasyncq *pa_shmasyncq_new(unsigned n_elements, size_t element_size, void *data, int fd[2]) {
+    pa_shmasyncq *l;
+
+    pa_assert(n_elements > 0);
+    pa_assert(is_power_of_two(n_elements));
+    pa_assert(element_size > 0);
+    pa_assert(data);
+    pa_assert(fd);
+
+    l = pa_xnew(pa_shmasyncq, 1);
+
+    l->data = data;
+    memset(data, 0, PA_SHMASYNCQ_SIZE(n_elements, element_size));
+
+    l->data->n_elements = n_elements;
+    l->data->element_size = element_size;
+
+    if (!(l->read_fdsem = pa_fdsem_new_shm(&d->read_fdsem_data, &fd[0]))) {
+        pa_xfree(l);
+        return NULL;
+    }
+
+    if (!(l->write_fdsem = pa_fdsem_new(&d->write_fdsem_data, &fd[1]))) {
+        pa_fdsem_free(l->read_fdsem);
+        pa_xfree(l);
+        return NULL;
+    }
+
+    return l;
+}
+
+void pa_shmasyncq_free(pa_shmasyncq *l, pa_free_cb_t free_cb) {
+    pa_assert(l);
+
+    if (free_cb) {
+        void *p;
+
+        while ((p = pa_shmasyncq_pop(l, 0)))
+            free_cb(p);
+    }
+
+    pa_fdsem_free(l->read_fdsem);
+    pa_fdsem_free(l->write_fdsem);
+    pa_xfree(l);
+}
+
+int pa_shmasyncq_push(pa_shmasyncq*l, void *p, int wait) {
+    int idx;
+    pa_atomic_ptr_t *cells;
+
+    pa_assert(l);
+    pa_assert(p);
+
+    cells = PA_SHMASYNCQ_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_shmasyncq_pop(pa_shmasyncq*l, int wait) {
+    int idx;
+    void *ret;
+    pa_atomic_ptr_t *cells;
+
+    pa_assert(l);
+
+    cells = PA_SHMASYNCQ_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_shmasyncq_get_fd(pa_shmasyncq *q) {
+    pa_assert(q);
+
+    return pa_fdsem_get(q->write_fdsem);
+}
+
+int pa_shmasyncq_before_poll(pa_shmasyncq *l) {
+    int idx;
+    pa_atomic_ptr_t *cells;
+
+    pa_assert(l);
+
+    cells = PA_SHMASYNCQ_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_shmasyncq_after_poll(pa_shmasyncq *l) {
+    pa_assert(l);
+
+    pa_fdsem_after_poll(l->write_fdsem);
+}
diff --git a/src/pulsecore/shmasyncq.h b/src/pulsecore/shmasyncq.h
new file mode 100644
index 0000000..ca35ffd
--- /dev/null
+++ b/src/pulsecore/shmasyncq.h
@@ -0,0 +1,62 @@
+#ifndef foopulseshmasyncqhfoo
+#define foopulseshmasyncqhfoo
+
+/* $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>
+#include <pulsecore/macro.h>
+
+/* Similar to pa_asyncq, but stores data in a shared memory segment */
+
+
+struct pa_shmasyncq_data {
+    unsigned n_elements;
+    size_t element_size;
+    unsigned read_idx;
+    unsigned write_idx;
+    pa_fdsem_data read_fdsem_data, write_fdsem_data;
+};
+
+#define PA_SHMASYNCQ_DEFAULT_N_ELEMENTS 128
+#define PA_SHMASYNCQ_SIZE(n_elements, element_size) (PA_ALIGN(sizeof(pa_shmasyncq_data)) + (((n_elements) * (PA_ALIGN(sizeof(pa_atomic_t)) + PA_ALIGN(element_size)))))
+#define PA_SHMASYNCQ_DEFAULT_SIZE(element_size) PA_SHMASYNCQ_SIZE(PA_SHMASYNCQ_DEFAULT_N_ELEMENTS, element_size)
+
+typedef struct pa_shmasyncq pa_shmasyncq;
+
+pa_shmasyncq *pa_shmasyncq_new(unsigned n_elements, size_t element_size, void *data, int fd[2]);
+void pa_shmasyncq_free(pa_shmasyncq* q, pa_free_cb_t free_cb);
+
+void* pa_shmasyncq_pop_begin(pa_shmasyncq *q, pa_bool_t wait);
+void pa_shmasyncq_pop_commit(pa_shmasyncq *q);
+
+int* pa_shmasyncq_push_begin(pa_shmasyncq *q, pa_bool_t wait);
+void pa_shmasyncq_push_commit(pa_shmasyncq *q);
+
+int pa_shmasyncq_get_fd(pa_shmasyncq *q);
+int pa_shmasyncq_before_poll(pa_shmasyncq *a);
+void pa_shmasyncq_after_poll(pa_shmasyncq *a);
+
+#endif
diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c
index 07ddb83..e15aa7b 100644
--- a/src/pulsecore/sink-input.c
+++ b/src/pulsecore/sink-input.c
@@ -41,8 +41,8 @@
 
 #include "sink-input.h"
 
+#define MEMBLOCKQ_MAXLENGTH (16*1024*1024)
 #define CONVERT_BUFFER_LENGTH (PA_PAGE_SIZE)
-#define SILENCE_BUFFER_LENGTH (PA_PAGE_SIZE*12)
 #define MOVE_BUFFER_LENGTH (PA_PAGE_SIZE*256)
 
 static PA_DEFINE_CHECK_TYPE(pa_sink_input, pa_msgobject);
@@ -54,10 +54,18 @@ pa_sink_input_new_data* pa_sink_input_new_data_init(pa_sink_input_new_data *data
 
     memset(data, 0, sizeof(*data));
     data->resample_method = PA_RESAMPLER_INVALID;
+    data->proplist = pa_proplist_new();
 
     return data;
 }
 
+void pa_sink_input_new_data_set_sample_spec(pa_sink_input_new_data *data, const pa_sample_spec *spec) {
+    pa_assert(data);
+
+    if ((data->sample_spec_is_set = !!spec))
+        data->sample_spec = *spec;
+}
+
 void pa_sink_input_new_data_set_channel_map(pa_sink_input_new_data *data, const pa_channel_map *map) {
     pa_assert(data);
 
@@ -72,18 +80,17 @@ void pa_sink_input_new_data_set_volume(pa_sink_input_new_data *data, const pa_cv
         data->volume = *volume;
 }
 
-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_muted(pa_sink_input_new_data *data, pa_bool_t mute) {
     pa_assert(data);
 
-    if ((data->sample_spec_is_set = !!spec))
-        data->sample_spec = *spec;
+    data->muted_is_set = TRUE;
+    data->muted = !!mute;
 }
 
-void pa_sink_input_new_data_set_muted(pa_sink_input_new_data *data, pa_bool_t mute) {
+void pa_sink_input_new_data_done(pa_sink_input_new_data *data) {
     pa_assert(data);
 
-    data->muted_is_set = TRUE;
-    data->muted = !!mute;
+    pa_proplist_free(data->proplist);
 }
 
 pa_sink_input* pa_sink_input_new(
@@ -94,6 +101,7 @@ pa_sink_input* pa_sink_input_new(
     pa_sink_input *i;
     pa_resampler *resampler = NULL;
     char st[PA_SAMPLE_SPEC_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX];
+    pa_memblock *silence;
 
     pa_assert(core);
     pa_assert(data);
@@ -102,7 +110,6 @@ pa_sink_input* pa_sink_input_new(
         return NULL;
 
     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);
@@ -132,6 +139,9 @@ pa_sink_input* pa_sink_input_new(
     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 = FALSE;
+
     if (flags & PA_SINK_INPUT_FIX_FORMAT)
         data->sample_spec.format = data->sink->sample_spec.format;
 
@@ -150,9 +160,6 @@ pa_sink_input* pa_sink_input_new(
     if (data->volume.channels != data->sample_spec.channels)
         pa_cvolume_set(&data->volume, data->sample_spec.channels, pa_cvolume_avg(&data->volume));
 
-    if (!data->muted_is_set)
-        data->muted = 0;
-
     if (data->resample_method == PA_RESAMPLER_INVALID)
         data->resample_method = core->resample_method;
 
@@ -192,7 +199,7 @@ pa_sink_input* pa_sink_input_new(
     i->core = core;
     i->state = PA_SINK_INPUT_INIT;
     i->flags = flags;
-    i->name = pa_xstrdup(data->name);
+    i->proplist = pa_proplist_copy(data->proplist);
     i->driver = pa_xstrdup(data->driver);
     i->module = data->module;
     i->sink = data->sink;
@@ -215,8 +222,9 @@ pa_sink_input* pa_sink_input_new(
     } else
         i->sync_next = i->sync_prev = NULL;
 
-    i->peek = NULL;
-    i->drop = NULL;
+    i->pop = NULL;
+    i->rewind = NULL;
+    i->set_max_rewind = NULL;
     i->kill = NULL;
     i->get_latency = NULL;
     i->attach = NULL;
@@ -226,22 +234,37 @@ pa_sink_input* pa_sink_input_new(
     i->userdata = NULL;
 
     i->thread_info.state = i->state;
+    i->thread_info.attached = FALSE;
     pa_atomic_store(&i->thread_info.drained, 1);
+    pa_atomic_store(&i->thread_info.render_memblockq_is_empty, 0);
     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;
+    i->thread_info.requested_sink_latency = 0;
+    i->thread_info.rewrite_nbytes = 0;
+    i->thread_info.ignore_rewind = FALSE;
+
+    silence = pa_silence_memblock_new(i->sink->core->mempool, &i->sink->sample_spec, 0);
+
+    i->thread_info.render_memblockq = pa_memblockq_new(
+            0,
+            MEMBLOCKQ_MAXLENGTH,
+            0,
+            pa_frame_size(&i->sink->sample_spec),
+            0,
+            1,
+            0,
+            silence);
+
+    pa_memblock_unref(silence);
 
     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 and channel map %s",
                 i->index,
-                i->name,
+                pa_strnull(pa_proplist_gets(i->proplist, PA_PROP_MEDIA_NAME)),
                 i->sink->name,
                 pa_sample_spec_snprint(st, sizeof(st), &i->sample_spec),
                 pa_channel_map_snprint(cm, sizeof(cm), &i->channel_map));
@@ -325,8 +348,9 @@ void pa_sink_input_unlink(pa_sink_input *i) {
     } else
         i->state = PA_SINK_INPUT_UNLINKED;
 
-    i->peek = NULL;
-    i->drop = NULL;
+    i->pop = NULL;
+    i->rewind = NULL;
+    i->set_max_rewind = NULL;
     i->kill = NULL;
     i->get_latency = NULL;
     i->attach = NULL;
@@ -352,20 +376,19 @@ static void sink_input_free(pa_object *o) {
     if (PA_SINK_INPUT_LINKED(i->state))
         pa_sink_input_unlink(i);
 
-    pa_log_info("Freeing output %u \"%s\"", i->index, i->name);
+    pa_log_info("Freeing input %u \"%s\"", i->index, pa_strnull(pa_proplist_gets(i->proplist, PA_PROP_MEDIA_NAME)));
 
     pa_assert(!i->thread_info.attached);
 
-    if (i->thread_info.resampled_chunk.memblock)
-        pa_memblock_unref(i->thread_info.resampled_chunk.memblock);
+    if (i->thread_info.render_memblockq)
+        pa_memblockq_free(i->thread_info.render_memblockq);
 
     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);
+    if (i->proplist)
+        pa_proplist_free(i->proplist);
 
-    pa_xfree(i->name);
     pa_xfree(i->driver);
     pa_xfree(i);
 }
@@ -374,8 +397,8 @@ void pa_sink_input_put(pa_sink_input *i) {
     pa_sink_input_assert_ref(i);
 
     pa_assert(i->state == PA_SINK_INPUT_INIT);
-    pa_assert(i->peek);
-    pa_assert(i->drop);
+    pa_assert(i->pop);
+    pa_assert(i->rewind);
 
     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;
@@ -384,8 +407,8 @@ void pa_sink_input_put(pa_sink_input *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_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i->sink), PA_SINK_MESSAGE_ADD_INPUT, i, 0, NULL);
 
     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);
@@ -419,85 +442,83 @@ pa_usec_t pa_sink_input_get_latency(pa_sink_input *i) {
 }
 
 /* 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;
+int pa_sink_input_peek(pa_sink_input *i, size_t slength /* in sink frames */, pa_memchunk *chunk, pa_cvolume *volume) {
+    pa_bool_t do_volume_adj_here;
+    pa_bool_t volume_is_norm;
+    size_t block_size_max_sink, block_size_max_sink_input;
+    size_t ilength;
 
     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(pa_frame_aligned(slength, &i->sink->sample_spec));
     pa_assert(chunk);
     pa_assert(volume);
 
-    if (!i->peek || !i->drop || i->thread_info.state == PA_SINK_INPUT_CORKED)
-        goto finish;
+    pa_log_debug("peek");
+
+    if (!i->pop || i->thread_info.state == PA_SINK_INPUT_CORKED)
+        return -1;
 
     pa_assert(i->thread_info.state == PA_SINK_INPUT_RUNNING || i->thread_info.state == PA_SINK_INPUT_DRAINED);
 
+    /* If there's still some rewrite request the handle, but the sink
+    didn't do this for us, we do it here. However, since the sink
+    apparently doesn't support rewinding, we pass 0 here. This still
+    allows rewinding through the render buffer. */
+    pa_sink_input_rewind(i, 0);
+
+    block_size_max_sink_input = i->thread_info.resampler ?
+        pa_resampler_max_block_size(i->thread_info.resampler) :
+        pa_frame_align(pa_mempool_block_size_max(i->sink->core->mempool), &i->sample_spec);
+
+    block_size_max_sink = pa_frame_align(pa_mempool_block_size_max(i->sink->core->mempool), &i->sink->sample_spec);
+
     /* 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->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->thread_info.silence_memblock);
-        chunk->index = 0;
-        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 (slength <= 0)
+        slength = pa_frame_align(CONVERT_BUFFER_LENGTH, &i->sink->sample_spec);
 
-    if (!i->thread_info.resampler) {
-        do_volume_adj_here = 0; /* FIXME??? */
-        ret = i->peek(i, length, chunk);
-        goto finish;
-    }
+    if (slength > block_size_max_sink)
+        slength = block_size_max_sink;
+
+    if (i->thread_info.resampler) {
+        ilength = pa_resampler_request(i->thread_info.resampler, slength);
+
+        if (ilength <= 0)
+            ilength = pa_frame_align(CONVERT_BUFFER_LENGTH, &i->sample_spec);
+    } else
+        ilength = slength;
+
+    if (ilength > block_size_max_sink_input)
+        ilength = block_size_max_sink_input;
+
+    /* If the channel maps of the sink and this stream differ, we need
+     * to adjust the volume *before* we resample. Otherwise we can do
+     * it after and leave it for the sink code */
 
     do_volume_adj_here = !pa_channel_map_equal(&i->channel_map, &i->sink->channel_map);
     volume_is_norm = pa_cvolume_is_norm(&i->thread_info.volume) && !i->thread_info.muted;
 
-    while (!i->thread_info.resampled_chunk.memblock) {
+    while (!pa_memblockq_is_readable(i->thread_info.render_memblockq)) {
         pa_memchunk tchunk;
-        size_t l, rmbs;
 
-        l = pa_resampler_request(i->thread_info.resampler, length);
+        /* There's nothing in our render queue. We need to fill it up
+         * with data from the implementor. */
 
-        if (l <= 0)
-            l = pa_frame_align(CONVERT_BUFFER_LENGTH, &i->sample_spec);
+        if (i->pop(i, ilength, &tchunk) < 0) {
+            pa_atomic_store(&i->thread_info.drained, 1);
 
-        rmbs = pa_resampler_max_block_size(i->thread_info.resampler);
-        if (l > rmbs)
-            l = rmbs;
+            /* OK, we got no data from the implementor, so let's just skip ahead */
+            pa_memblockq_seek(i->thread_info.render_memblockq, slength, PA_SEEK_RELATIVE_ON_READ);
+            break;
+        }
 
-        if ((ret = i->peek(i, l, &tchunk)) < 0)
-            goto finish;
+        pa_atomic_store(&i->thread_info.drained, 0);
 
         pa_assert(tchunk.length > 0);
+        pa_assert(tchunk.memblock);
 
-        if (tchunk.length > l)
-            tchunk.length = l;
-
-        i->drop(i, tchunk.length);
+        if (tchunk.length > block_size_max_sink_input)
+            tchunk.length = block_size_max_sink_input;
 
         /* It might be necessary to adjust the volume here */
         if (do_volume_adj_here && !volume_is_norm) {
@@ -509,137 +530,146 @@ int pa_sink_input_peek(pa_sink_input *i, size_t length, pa_memchunk *chunk, pa_c
                 pa_volume_memchunk(&tchunk, &i->thread_info.sample_spec, &i->thread_info.volume);
         }
 
-        pa_resampler_run(i->thread_info.resampler, &tchunk, &i->thread_info.resampled_chunk);
+        if (!i->thread_info.resampler)
+            pa_memblockq_push_align(i->thread_info.render_memblockq, &tchunk);
+        else {
+            pa_memchunk rchunk;
+            pa_resampler_run(i->thread_info.resampler, &tchunk, &rchunk);
+
+            if (rchunk.memblock) {
+                pa_memblockq_push_align(i->thread_info.render_memblockq, &rchunk);
+                pa_memblock_unref(rchunk.memblock);
+            }
+        }
+
         pa_memblock_unref(tchunk.memblock);
     }
 
-    pa_assert(i->thread_info.resampled_chunk.memblock);
-    pa_assert(i->thread_info.resampled_chunk.length > 0);
+    pa_assert_se(pa_memblockq_peek(i->thread_info.render_memblockq, chunk) >= 0);
 
-    *chunk = i->thread_info.resampled_chunk;
-    pa_memblock_ref(i->thread_info.resampled_chunk.memblock);
+    pa_assert(chunk->length > 0);
+    pa_assert(chunk->memblock);
 
-    ret = 0;
+    if (chunk->length > block_size_max_sink)
+        chunk->length = block_size_max_sink;
 
-finish:
+    /* Let's see if we had to apply the volume adjustment ourselves,
+     * or if this can be done by the sink for us */
 
-    if (ret >= 0)
-        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
-         * ourselves, or if this can be done by the sink for us */
-
-        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 if (i->thread_info.muted)
-            /* We've both the same channel map, so let's have the sink do the adjustment for us*/
-            pa_cvolume_mute(volume, i->sink->sample_spec.channels);
-        else
-            *volume = i->thread_info.volume;
-    }
+    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 if (i->thread_info.muted)
+        /* We've both the same channel map, so let's have the sink do the adjustment for us*/
+        pa_cvolume_mute(volume, i->sink->sample_spec.channels);
+    else
+        *volume = i->thread_info.volume;
+
+    pa_atomic_store(&i->thread_info.render_memblockq_is_empty, pa_memblockq_is_empty(i->thread_info.render_memblockq));
 
-    return ret;
+    return 0;
 }
 
 /* Called from thread context */
-void pa_sink_input_drop(pa_sink_input *i, size_t length) {
+void pa_sink_input_drop(pa_sink_input *i, size_t nbytes /* in sink sample spec */) {
+
     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);
+    pa_assert(pa_frame_aligned(nbytes, &i->sink->sample_spec));
+    pa_assert(nbytes > 0);
 
-    if (!i->peek || !i->drop || i->thread_info.state == PA_SINK_INPUT_CORKED)
+    if (i->thread_info.state == PA_SINK_INPUT_CORKED)
         return;
 
-    if (i->thread_info.move_silence > 0) {
+    /* If there's still some rewrite request the handle, but the sink
+    didn't do this for us, we do it here. However, since the sink
+    apparently doesn't support rewinding, we pass 0 here. This still
+    allows rewinding through the render buffer. */
+    if (i->thread_info.rewrite_nbytes > 0)
+        pa_sink_input_rewind(i, 0);
 
-        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;
-            }
-        }
+    pa_memblockq_drop(i->thread_info.render_memblockq, nbytes);
 
-        if (length <= 0)
-            return;
-    }
+    pa_atomic_store(&i->thread_info.render_memblockq_is_empty, pa_memblockq_is_empty(i->thread_info.render_memblockq));
+}
 
-    if (i->thread_info.resampled_chunk.memblock) {
-        size_t l = length;
+/* Called from thread context */
+void pa_sink_input_rewind(pa_sink_input *i, size_t nbytes /* in sink sample spec */) {
+    pa_sink_input_assert_ref(i);
 
-        if (l > i->thread_info.resampled_chunk.length)
-            l = i->thread_info.resampled_chunk.length;
+    pa_assert(PA_SINK_INPUT_LINKED(i->thread_info.state));
+    pa_assert(pa_frame_aligned(nbytes, &i->sink->sample_spec));
 
-        i->thread_info.resampled_chunk.index += l;
-        i->thread_info.resampled_chunk.length -= l;
+    pa_log_debug("rewind(%u, %u)", nbytes, i->thread_info.rewrite_nbytes);
 
-        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);
-        }
+    if (i->thread_info.state == PA_SINK_INPUT_CORKED)
+        return;
 
-        length -= l;
+    if (i->thread_info.ignore_rewind) {
+        i->thread_info.rewrite_nbytes = 0;
+        i->thread_info.ignore_rewind = FALSE;
+        return;
     }
 
-    if (length > 0) {
+    if (nbytes > 0)
+        pa_log_debug("Have to rewind %u bytes.", nbytes);
 
-        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. */
+    if (i->thread_info.rewrite_nbytes > 0) {
+        size_t max_rewrite;
 
-            while (length > 0) {
-                pa_memchunk chunk;
-                pa_cvolume volume;
+        /* Calculate how much make sense to rewrite at most */
+        if ((max_rewrite = nbytes + pa_memblockq_get_length(i->thread_info.render_memblockq)) > 0) {
+            size_t amount, r;
 
-                if (pa_sink_input_peek(i, length, &chunk, &volume) >= 0) {
-                    size_t l;
+            /* Transform into local domain */
+            if (i->thread_info.resampler)
+                max_rewrite = pa_resampler_request(i->thread_info.resampler, max_rewrite);
 
-                    pa_memblock_unref(chunk.memblock);
+            /* Calculate how much of the rewinded data should actually be rewritten */
+            amount = PA_MIN(max_rewrite, i->thread_info.rewrite_nbytes);
 
-                    l = chunk.length;
-                    if (l > length)
-                        l = length;
+            /* Convert back to to sink domain */
+            r = i->thread_info.resampler ? pa_resampler_result(i->thread_info.resampler, amount) : amount;
 
-                    pa_sink_input_drop(i, l);
-                    length -= l;
+            /* Ok, now update the write pointer */
+            pa_memblockq_seek(i->thread_info.render_memblockq, -r, PA_SEEK_RELATIVE);
 
-                } else {
-                    size_t l;
+            /* Tell the implementor */
+            if (i->rewind)
+                i->rewind(i, amount);
 
-                    l = pa_resampler_request(i->thread_info.resampler, length);
+            /* And reset the resampler */
+            if (i->thread_info.resampler)
+                pa_resampler_reset(i->thread_info.resampler);
+        }
 
-                    /* Hmmm, peeking failed, so let's at least drop
-                     * the right amount of data */
 
-                    if (l > 0)
-                        if (i->drop)
-                            i->drop(i, l);
+        i->thread_info.rewrite_nbytes = 0;
+    }
 
-                    break;
-                }
-            }
+    if (nbytes > 0)
+        pa_memblockq_rewind(i->thread_info.render_memblockq, nbytes);
+}
 
-        } else {
+/* Called from thread context */
+void pa_sink_input_set_max_rewind(pa_sink_input *i, size_t nbytes  /* in the sink's sample spec */) {
+    pa_sink_input_assert_ref(i);
 
-            /* We have no resampler, hence let's just drop the data */
+    pa_assert(PA_SINK_INPUT_LINKED(i->thread_info.state));
+    pa_assert(pa_frame_aligned(nbytes, &i->sink->sample_spec));
 
-            if (i->drop)
-                i->drop(i, length);
-        }
-    }
+    pa_memblockq_set_maxrewind(i->thread_info.render_memblockq, nbytes);
+
+    if (i->set_max_rewind)
+        i->set_max_rewind(i, i->thread_info.resampler ? pa_resampler_request(i->thread_info.resampler, nbytes) : nbytes);
+}
+
+void pa_sink_input_set_requested_latency(pa_sink_input *i, pa_usec_t usec) {
+    pa_sink_input_assert_ref(i);
+    pa_assert(PA_SINK_INPUT_LINKED(i->state));
+
+    pa_asyncmsgq_post(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_SET_REQUESTED_LATENCY, NULL, (int64_t) usec, NULL, NULL);
 }
 
 void pa_sink_input_set_volume(pa_sink_input *i, const pa_cvolume *volume) {
@@ -707,19 +737,24 @@ int 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) {
+    const char *old;
     pa_sink_input_assert_ref(i);
 
-    if (!i->name && !name)
+    if (!name && !pa_proplist_contains(i->proplist, PA_PROP_MEDIA_NAME))
         return;
 
-    if (i->name && name && !strcmp(i->name, name))
+    old = pa_proplist_gets(i->proplist, PA_PROP_MEDIA_NAME);
+
+    if (old && name && !strcmp(old, name))
         return;
 
-    pa_xfree(i->name);
-    i->name = pa_xstrdup(name);
+    if (name)
+        pa_proplist_sets(i->proplist, PA_PROP_MEDIA_NAME, name);
+    else
+        pa_proplist_unset(i->proplist, PA_PROP_MEDIA_NAME);
 
     if (PA_SINK_INPUT_LINKED(i->state)) {
-        pa_hook_fire(&i->sink->core->hooks[PA_CORE_HOOK_SINK_INPUT_NAME_CHANGED], i);
+        pa_hook_fire(&i->sink->core->hooks[PA_CORE_HOOK_SINK_INPUT_PROPLIST_CHANGED], i);
         pa_subscription_post(i->sink->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index);
     }
 }
@@ -829,20 +864,29 @@ int pa_sink_input_move_to(pa_sink_input *i, pa_sink *dest, int immediately) {
         /* Okey, let's move it */
 
         if (info.buffer_bytes > 0) {
+            pa_proplist *p;
+
+            p = pa_proplist_new();
+            pa_proplist_sets(p, PA_PROP_MEDIA_NAME, "Ghost For Moved Stream");
+            pa_proplist_sets(p, PA_PROP_MEDIA_ROLE, "routing");
 
             info.ghost_sink_input = pa_memblockq_sink_input_new(
                     origin,
-                    "Ghost Stream",
                     &origin->sample_spec,
                     &origin->channel_map,
                     NULL,
-                    NULL);
+                    NULL,
+                    p);
+
+            pa_proplist_free(p);
 
-            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 (info.ghost_sink_input) {
+                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;
 
-            info.buffer = pa_memblockq_new(0, MOVE_BUFFER_LENGTH, 0, pa_frame_size(&origin->sample_spec), 0, 0, NULL);
+                info.buffer = pa_memblockq_new(0, MOVE_BUFFER_LENGTH, 0, pa_frame_size(&origin->sample_spec), 0, 0, 0, NULL);
+            }
         }
     }
 
@@ -867,34 +911,26 @@ int pa_sink_input_move_to(pa_sink_input *i, pa_sink *dest, int immediately) {
 
     /* Replace resampler */
     if (new_resampler != i->thread_info.resampler) {
+        pa_memblock *silence;
+
         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->thread_info.silence_memblock) {
-            pa_memblock_unref(i->thread_info.silence_memblock);
-            i->thread_info.silence_memblock = NULL;
-        }
-    }
 
-    /* Dump already resampled data */
-    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);
+        silence = pa_silence_memblock_new(i->sink->core->mempool, &dest->sample_spec, new_resampler ? pa_resampler_max_block_size(new_resampler) : 0);
+        pa_memblockq_set_silence(i->thread_info.render_memblockq, silence);
+        pa_memblock_unref(silence);
+
     }
 
+    pa_memblockq_flush(i->thread_info.render_memblockq);
+
     /* 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);
+    if (!immediately)
+        pa_memblockq_seek(i->thread_info.render_memblockq, pa_usec_to_bytes(silence_usec, &dest->sample_spec), PA_SEEK_RELATIVE);
 
     pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i->sink), PA_SINK_MESSAGE_ADD_INPUT, i, 0, NULL);
 
@@ -924,20 +960,18 @@ int pa_sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int64_t
     switch (code) {
         case PA_SINK_INPUT_MESSAGE_SET_VOLUME:
             i->thread_info.volume = *((pa_cvolume*) userdata);
+            pa_sink_input_request_rewrite(i, 0);
             return 0;
 
         case PA_SINK_INPUT_MESSAGE_SET_MUTE:
             i->thread_info.muted = PA_PTR_TO_UINT(userdata);
+            pa_sink_input_request_rewrite(i, 0);
             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);
+            *r += pa_bytes_to_usec(pa_memblockq_get_length(i->thread_info.render_memblockq), &i->sink->sample_spec);
 
             return 0;
         }
@@ -974,6 +1008,13 @@ int pa_sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int64_t
 
             return 0;
         }
+
+        case PA_SINK_INPUT_MESSAGE_SET_REQUESTED_LATENCY:
+
+            i->thread_info.requested_sink_latency = (pa_usec_t) offset;
+            pa_sink_invalidate_requested_latency(i->sink);
+
+            return 0;
     }
 
     return -1;
@@ -987,3 +1028,38 @@ pa_sink_input_state_t pa_sink_input_get_state(pa_sink_input *i) {
 
     return i->state;
 }
+
+pa_bool_t pa_sink_input_safe_to_remove(pa_sink_input *i) {
+    pa_sink_input_assert_ref(i);
+
+    if (i->state == PA_SINK_INPUT_RUNNING || i->state == PA_SINK_INPUT_DRAINED || i->state == PA_SINK_INPUT_CORKED)
+        return pa_atomic_load(&i->thread_info.render_memblockq_is_empty);
+
+    return TRUE;
+}
+
+void pa_sink_input_request_rewrite(pa_sink_input *i, size_t nbytes  /* in our sample spec */) {
+    size_t l, lbq;
+
+    pa_sink_input_assert_ref(i);
+
+    lbq = pa_memblockq_get_length(i->thread_info.render_memblockq);
+
+    if (nbytes <= 0) {
+        nbytes =
+            i->thread_info.resampler ?
+            pa_resampler_request(i->thread_info.resampler, i->sink->thread_info.max_rewind + lbq) :
+            (i->sink->thread_info.max_rewind + lbq);
+    }
+
+    i->thread_info.rewrite_nbytes = PA_MAX(nbytes, i->thread_info.rewrite_nbytes);
+
+    /* Transform to sink domain */
+    l = i->thread_info.resampler ? pa_resampler_result(i->thread_info.resampler, nbytes) : nbytes;
+
+    if (l <= 0)
+        return;
+
+    if (l > lbq)
+        pa_sink_request_rewind(i->sink, l - lbq);
+}
diff --git a/src/pulsecore/sink-input.h b/src/pulsecore/sink-input.h
index 8975db9..c74b891 100644
--- a/src/pulsecore/sink-input.h
+++ b/src/pulsecore/sink-input.h
@@ -73,7 +73,8 @@ struct pa_sink_input {
     pa_sink_input_state_t state;
     pa_sink_input_flags_t flags;
 
-    char *name, *driver;                /* may be NULL */
+    pa_proplist *proplist;
+    char *driver;                       /* may be NULL */
     pa_module *module;                  /* may be NULL */
     pa_client *client;                  /* may be NULL */
 
@@ -87,17 +88,26 @@ struct pa_sink_input {
     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);
+    pa_resample_method_t resample_method;
 
-    /* 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);
+    /* Returns the chunk of audio data and drops it from the
+     * queue. Returns -1 on failure. Called from IO thread context. If
+     * data needs to be generated from scratch then please in the
+     * specified length request_nbytes. 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 (*pop) (pa_sink_input *i, size_t request_nbytes, pa_memchunk *chunk);
+
+    /* Rewind the queue by the specified number of bytes. Called just
+     * before peek() if it is called at all. Only called if the sink
+     * input driver ever plans to call
+     * pa_sink_input_request_rewrite(). Called from IO context. */
+    void (*rewind) (pa_sink_input *i, size_t nbytes);
+
+    /* Called whenever the maximum rewindable size of the sink
+     * changes. Called from UI context. */
+    void (*set_max_rewind) (pa_sink_input *i, size_t nbytes); /* may be NULL */
 
     /* If non-NULL this function is called when the input is first
      * connected to a sink or when the rtpoll/asyncmsgq fields
@@ -128,29 +138,28 @@ struct pa_sink_input {
     instead. */
     pa_usec_t (*get_latency) (pa_sink_input *i); /* may be NULL */
 
-    pa_resample_method_t resample_method;
-
     struct {
         pa_sink_input_state_t state;
-        pa_atomic_t drained;
+        pa_atomic_t drained, render_memblockq_is_empty;
 
         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 */
+        /* We maintain a history of resampled audio data here. */
+        pa_memblockq *render_memblockq;
+        size_t rewrite_nbytes;
+        pa_bool_t ignore_rewind;
 
         pa_sink_input *sync_prev, *sync_next;
 
         pa_cvolume volume;
         pa_bool_t muted;
+
+        /* The requested latency for the sink */
+        pa_usec_t requested_sink_latency;
     } thread_info;
 
     void *userdata;
@@ -165,11 +174,14 @@ enum {
     PA_SINK_INPUT_MESSAGE_GET_LATENCY,
     PA_SINK_INPUT_MESSAGE_SET_RATE,
     PA_SINK_INPUT_MESSAGE_SET_STATE,
+    PA_SINK_INPUT_MESSAGE_SET_REQUESTED_LATENCY,
     PA_SINK_INPUT_MESSAGE_MAX
 };
 
 typedef struct pa_sink_input_new_data {
-    const char *name, *driver;
+    pa_proplist *proplist;
+
+    const char *driver;
     pa_module *module;
     pa_client *client;
 
@@ -190,16 +202,17 @@ typedef struct pa_sink_input_new_data {
     pa_sink_input *sync_base;
 } pa_sink_input_new_data;
 
-typedef struct pa_sink_input_move_hook_data {
-    pa_sink_input *sink_input;
-    pa_sink *destination;
-} pa_sink_input_move_hook_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);
+void pa_sink_input_new_data_done(pa_sink_input_new_data *data);
+
+typedef struct pa_sink_input_move_hook_data {
+    pa_sink_input *sink_input;
+    pa_sink *destination;
+} pa_sink_input_move_hook_data;
 
 /* To be called by the implementing module only */
 
@@ -213,7 +226,19 @@ void pa_sink_input_unlink(pa_sink_input* i);
 
 void pa_sink_input_set_name(pa_sink_input *i, const char *name);
 
-/* Callable by everyone */
+void pa_sink_input_set_requested_latency(pa_sink_input *i, pa_usec_t usec);
+
+/* Request that the specified number of bytes already written out to
+the hw device is rewritten, if possible. If this function is used you
+need to supply the ->rewind() function pointer. Please note that this
+is only a kind request. The sink driver may not be able to fulfill it
+fully -- or at all. If the request for a rewrite was successful, the
+sink driver will call ->rewind() and pass the number of bytes that
+could be rewound in the HW device. This functionality is required for
+implementing the "zero latency" write-through functionality. */
+void pa_sink_input_request_rewrite(pa_sink_input *i, size_t nbytes);
+
+/* Callable by everyone from main thread*/
 
 /* External code may request disconnection with this function */
 void pa_sink_input_kill(pa_sink_input*i);
@@ -235,10 +260,14 @@ 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 */
+pa_bool_t pa_sink_input_safe_to_remove(pa_sink_input *i);
+/* To be used exclusively by the sink driver IO 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);
+void pa_sink_input_rewind(pa_sink_input *i, size_t nbytes /* in the sink's sample spec */);
+void pa_sink_input_set_max_rewind(pa_sink_input *i, size_t nbytes  /* in the sink's sample spec */);
+
 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 {
@@ -248,4 +277,5 @@ typedef struct pa_sink_input_move_info {
     size_t buffer_bytes;
 } pa_sink_input_move_info;
 
+
 #endif
diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c
index 9adb609..cded6ba 100644
--- a/src/pulsecore/sink.c
+++ b/src/pulsecore/sink.c
@@ -47,42 +47,105 @@
 
 #define MAX_MIX_CHANNELS 32
 #define MIX_BUFFER_LENGTH (PA_PAGE_SIZE)
-#define SILENCE_BUFFER_LENGTH (PA_PAGE_SIZE*12)
 
 static PA_DEFINE_CHECK_TYPE(pa_sink, pa_msgobject);
 
 static void sink_free(pa_object *s);
 
+pa_sink_new_data* pa_sink_new_data_init(pa_sink_new_data *data) {
+    pa_assert(data);
+
+    memset(data, 0, sizeof(*data));
+    data->proplist = pa_proplist_new();
+
+    return data;
+}
+
+void pa_sink_new_data_set_name(pa_sink_new_data *data, const char *name) {
+    pa_assert(data);
+
+    pa_xfree(data->name);
+    data->name = pa_xstrdup(name);
+}
+
+void pa_sink_new_data_set_sample_spec(pa_sink_new_data *data, const pa_sample_spec *spec) {
+    pa_assert(data);
+
+    if ((data->sample_spec_is_set = !!spec))
+        data->sample_spec = *spec;
+}
+
+void pa_sink_new_data_set_channel_map(pa_sink_new_data *data, const pa_channel_map *map) {
+    pa_assert(data);
+
+    if ((data->channel_map_is_set = !!map))
+        data->channel_map = *map;
+}
+
+void pa_sink_new_data_set_volume(pa_sink_new_data *data, const pa_cvolume *volume) {
+    pa_assert(data);
+
+    if ((data->volume_is_set = !!volume))
+        data->volume = *volume;
+}
+
+void pa_sink_new_data_set_muted(pa_sink_new_data *data, pa_bool_t mute) {
+    pa_assert(data);
+
+    data->muted_is_set = TRUE;
+    data->muted = !!mute;
+}
+
+void pa_sink_new_data_done(pa_sink_new_data *data) {
+    pa_assert(data);
+
+    pa_xfree(data->name);
+    pa_proplist_free(data->proplist);
+}
+
 pa_sink* pa_sink_new(
         pa_core *core,
-        const char *driver,
-        const char *name,
-        int fail,
-        const pa_sample_spec *spec,
-        const pa_channel_map *map) {
+        pa_sink_new_data *data,
+        pa_sink_flags_t flags) {
 
     pa_sink *s;
-    char *n = NULL;
-    char st[256];
-    pa_channel_map tmap;
+    char *d;
+    const char *name;
+    char st[PA_SAMPLE_SPEC_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX];
+    pa_source_new_data source_data;
 
     pa_assert(core);
-    pa_assert(name);
-    pa_assert(spec);
+    pa_assert(data);
+
+    if (pa_hook_fire(&core->hooks[PA_CORE_HOOK_SINK_NEW], data) < 0)
+        return NULL;
+
+    pa_return_null_if_fail(!data->driver || pa_utf8_valid(data->driver));
+    pa_return_null_if_fail(data->name && pa_utf8_valid(data->name) && data->name[0]);
+
+    pa_return_null_if_fail(data->sample_spec_is_set && pa_sample_spec_valid(&data->sample_spec));
+
+    if (!data->channel_map_is_set)
+        pa_return_null_if_fail(pa_channel_map_init_auto(&data->channel_map, data->sample_spec.channels, PA_CHANNEL_MAP_DEFAULT));
+
+    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);
 
-    pa_return_null_if_fail(pa_sample_spec_valid(spec));
+    if (!data->volume_is_set)
+        pa_cvolume_reset(&data->volume, data->sample_spec.channels);
 
-    if (!map)
-        pa_return_null_if_fail((map = pa_channel_map_init_auto(&tmap, spec->channels, PA_CHANNEL_MAP_DEFAULT)));
+    pa_return_null_if_fail(pa_cvolume_valid(&data->volume));
+    pa_return_null_if_fail(data->volume.channels == data->sample_spec.channels);
 
-    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);
+    if (!data->muted_is_set)
+        data->muted = FALSE;
+
+    if (pa_hook_fire(&core->hooks[PA_CORE_HOOK_SINK_FIXATE], data) < 0)
+        return NULL;
 
     s = pa_msgobject_new(pa_sink);
 
-    if (!(name = pa_namereg_register(core, name, PA_NAMEREG_SINK, s, fail))) {
+    if (!(name = pa_namereg_register(core, data->name, PA_NAMEREG_SINK, s, data->namereg_fail))) {
         pa_xfree(s);
         return NULL;
     }
@@ -92,20 +155,20 @@ pa_sink* pa_sink_new(
 
     s->core = core;
     s->state = PA_SINK_INIT;
-    s->flags = 0;
+    s->flags = flags;
     s->name = pa_xstrdup(name);
-    s->description = NULL;
-    s->driver = pa_xstrdup(driver);
-    s->module = NULL;
+    s->proplist = pa_proplist_copy(data->proplist);
+    s->driver = pa_xstrdup(data->driver);
+    s->module = data->module;
 
-    s->sample_spec = *spec;
-    s->channel_map = *map;
+    s->sample_spec = data->sample_spec;
+    s->channel_map = data->channel_map;
 
     s->inputs = pa_idxset_new(NULL, NULL);
     s->n_corked = 0;
 
-    pa_cvolume_reset(&s->volume, spec->channels);
-    s->muted = FALSE;
+    s->volume = data->volume;
+    s->muted = data->muted;
     s->refresh_volume = s->refresh_mute = FALSE;
 
     s->get_latency = NULL;
@@ -114,35 +177,53 @@ pa_sink* pa_sink_new(
     s->set_mute = NULL;
     s->get_mute = NULL;
     s->set_state = NULL;
+    s->request_rewind = NULL;
+    s->update_requested_latency = NULL;
     s->userdata = NULL;
 
     s->asyncmsgq = NULL;
     s->rtpoll = NULL;
-    s->silence = NULL;
+    s->silence = pa_silence_memblock_new(core->mempool, &s->sample_spec, 0);
+
+    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;
+    s->thread_info.rewind_nbytes = 0;
+    s->thread_info.max_rewind = 0;
+    s->thread_info.requested_latency_valid = TRUE;
+    s->thread_info.requested_latency = 0;
 
     pa_assert_se(pa_idxset_put(core->sinks, s, &s->index) >= 0);
 
-    pa_sample_spec_snprint(st, sizeof(st), spec);
-    pa_log_info("Created sink %u \"%s\" with sample spec \"%s\"", s->index, s->name, st);
+    pa_log_info("Created sink %u \"%s\" with sample spec %s and channel map %s",
+                s->index,
+                s->name,
+                pa_sample_spec_snprint(st, sizeof(st), &s->sample_spec),
+                pa_channel_map_snprint(cm, sizeof(cm), &s->channel_map));
 
-    n = pa_sprintf_malloc("%s.monitor", name);
+    pa_source_new_data_init(&source_data);
+    pa_source_new_data_set_sample_spec(&source_data, &s->sample_spec);
+    pa_source_new_data_set_channel_map(&source_data, &s->channel_map);
+    source_data.name = pa_sprintf_malloc("%s.monitor", name);
+    source_data.driver = data->driver;
 
-    if (!(s->monitor_source = pa_source_new(core, driver, n, 0, spec, map)))
-        pa_log_warn("Failed to create monitor source.");
-    else {
-        char *d;
-        s->monitor_source->monitor_of = s;
-        d = pa_sprintf_malloc("Monitor Source of %s", s->name);
-        pa_source_set_description(s->monitor_source, d);
-        pa_xfree(d);
-    }
+    d = pa_sprintf_malloc("Monitor Source of %s", s->name);
+    pa_proplist_sets(data->proplist, PA_PROP_DEVICE_DESCRIPTION, d);
+    pa_xfree(d);
+    pa_proplist_sets(data->proplist, PA_PROP_DEVICE_CLASS, "monitor");
 
-    pa_xfree(n);
+    s->monitor_source = pa_source_new(core, &source_data, 0);
 
-    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;
+    pa_source_new_data_done(&source_data);
+
+    if (!s->monitor_source) {
+        pa_sink_unlink(s);
+        pa_sink_unref(s);
+        return NULL;
+    }
+
+    s->monitor_source->monitor_of = s;
 
     return s;
 }
@@ -193,12 +274,22 @@ void pa_sink_put(pa_sink* s) {
     pa_assert(s->asyncmsgq);
     pa_assert(s->rtpoll);
 
+    if (s->get_volume && s->set_volume)
+        s->flags |= PA_SINK_HW_VOLUME_CTRL;
+    else
+        s->flags = (s->flags & ~PA_SINK_HW_VOLUME_CTRL) | PA_SINK_DECIBEL_VOLUME;
+
+    if (s->get_mute && s->set_mute)
+        s->flags |= PA_SINK_HW_MUTE_CTRL;
+    else
+        s->flags &= ~PA_SINK_HW_MUTE_CTRL;
+
     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);
+    pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SINK_PUT], s);
 }
 
 void pa_sink_unlink(pa_sink* s) {
@@ -241,6 +332,8 @@ void pa_sink_unlink(pa_sink* s) {
     s->set_mute = NULL;
     s->get_mute = NULL;
     s->set_state = NULL;
+    s->request_rewind = NULL;
+    s->update_requested_latency = NULL;
 
     if (s->monitor_source)
         pa_source_unlink(s->monitor_source);
@@ -279,8 +372,11 @@ static void sink_free(pa_object *o) {
         pa_memblock_unref(s->silence);
 
     pa_xfree(s->name);
-    pa_xfree(s->description);
     pa_xfree(s->driver);
+
+    if (s->proplist)
+        pa_proplist_free(s->proplist);
+
     pa_xfree(s);
 }
 
@@ -330,6 +426,26 @@ void pa_sink_ping(pa_sink *s) {
     pa_asyncmsgq_post(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_PING, NULL, 0, NULL, NULL);
 }
 
+void pa_sink_process_rewind(pa_sink *s) {
+    pa_sink_input *i;
+    void *state = NULL;
+    pa_sink_assert_ref(s);
+    pa_assert(PA_SINK_LINKED(s->state));
+
+    if (s->thread_info.rewind_nbytes <= 0)
+        return;
+
+    pa_log_debug("Processing rewind...");
+
+    while ((i = pa_hashmap_iterate(s->thread_info.inputs, &state, NULL))) {
+        pa_sink_input_assert_ref(i);
+
+        pa_sink_input_rewind(i, s->thread_info.rewind_nbytes);
+    }
+
+    s->thread_info.rewind_nbytes = 0;
+}
+
 static unsigned fill_mix_info(pa_sink *s, size_t length, pa_mix_info *info, unsigned maxinfo) {
     pa_sink_input *i;
     unsigned n = 0;
@@ -344,6 +460,11 @@ static unsigned fill_mix_info(pa_sink *s, size_t length, pa_mix_info *info, unsi
         if (pa_sink_input_peek(i, length, &info->chunk, &info->volume) < 0)
             continue;
 
+        if (pa_memblock_is_silence(info->chunk.memblock)) {
+            pa_memblock_unref(info->chunk.memblock);
+            continue;
+        }
+
         info->userdata = pa_sink_input_ref(i);
 
         pa_assert(info->chunk.memblock);
@@ -427,6 +548,8 @@ void pa_sink_render(pa_sink*s, size_t length, pa_memchunk *result) {
 
     pa_sink_ref(s);
 
+    s->thread_info.rewind_nbytes = 0;
+
     if (length <= 0)
         length = pa_frame_align(MIX_BUFFER_LENGTH, &s->sample_spec);
 
@@ -440,19 +563,8 @@ void pa_sink_render(pa_sink*s, size_t length, pa_memchunk *result) {
 
     if (n == 0) {
 
-        if (length > SILENCE_BUFFER_LENGTH)
-            length = pa_frame_align(SILENCE_BUFFER_LENGTH, &s->sample_spec);
-
-        pa_assert(length > 0);
-
-        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->length = PA_MIN(pa_memblock_get_length(s->silence), length);
         result->index = 0;
 
     } else if (n == 1) {
@@ -506,11 +618,13 @@ void pa_sink_render_into(pa_sink*s, pa_memchunk *target) {
 
     pa_sink_ref(s);
 
+    s->thread_info.rewind_nbytes = 0;
+
     n = s->thread_info.state == PA_SINK_RUNNING ? fill_mix_info(s, target->length, info, MAX_MIX_CHANNELS) : 0;
 
-    if (n == 0) {
+    if (n == 0)
         pa_silence_memchunk(target, &s->sample_spec);
-    } else if (n == 1) {
+    else if (n == 1) {
         if (target->length > info[0].chunk.length)
             target->length = info[0].chunk.length;
 
@@ -573,6 +687,8 @@ void pa_sink_render_into_full(pa_sink *s, pa_memchunk *target) {
 
     pa_sink_ref(s);
 
+    s->thread_info.rewind_nbytes = 0;
+
     l = target->length;
     d = 0;
     while (l > 0) {
@@ -596,6 +712,8 @@ void pa_sink_render_full(pa_sink *s, size_t length, pa_memchunk *result) {
     pa_assert(pa_frame_aligned(length, &s->sample_spec));
     pa_assert(result);
 
+    s->thread_info.rewind_nbytes = 0;
+
     /*** This needs optimization ***/
 
     result->index = 0;
@@ -614,6 +732,8 @@ void pa_sink_skip(pa_sink *s, size_t length) {
     pa_assert(length > 0);
     pa_assert(pa_frame_aligned(length, &s->sample_spec));
 
+    s->thread_info.rewind_nbytes = 0;
+
     if (pa_source_used_by(s->monitor_source)) {
         pa_memchunk chunk;
 
@@ -644,6 +764,8 @@ pa_usec_t pa_sink_get_latency(pa_sink *s) {
     pa_sink_assert_ref(s);
     pa_assert(PA_SINK_LINKED(s->state));
 
+    /* The returned value is supposed to be in the time domain of the sound card! */
+
     if (!PA_SINK_OPENED(s->state))
         return 0;
 
@@ -735,43 +857,34 @@ pa_bool_t pa_sink_get_mute(pa_sink *s) {
     return s->muted;
 }
 
-void pa_sink_set_module(pa_sink *s, pa_module *m) {
-    pa_sink_assert_ref(s);
-
-    if (s->module == m)
-        return;
-
-    s->module = m;
-
-    if (s->monitor_source)
-        pa_source_set_module(s->monitor_source, m);
-
-    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) {
+    const char *old;
     pa_sink_assert_ref(s);
 
-    if (!description && !s->description)
+    if (!description && !pa_proplist_contains(s->proplist, PA_PROP_DEVICE_DESCRIPTION))
         return;
 
-    if (description && s->description && !strcmp(description, s->description))
+    old = pa_proplist_gets(s->proplist, PA_PROP_DEVICE_DESCRIPTION);
+
+    if (old && description && !strcmp(old, description))
         return;
 
-    pa_xfree(s->description);
-    s->description = pa_xstrdup(description);
+    if (description)
+        pa_proplist_sets(s->proplist, PA_PROP_DEVICE_DESCRIPTION, description);
+    else
+        pa_proplist_unset(s->proplist, PA_PROP_DEVICE_DESCRIPTION);
 
     if (s->monitor_source) {
         char *n;
 
-        n = pa_sprintf_malloc("Monitor Source of %s", s->description? s->description : s->name);
+        n = pa_sprintf_malloc("Monitor Source of %s", description ? description : s->name);
         pa_source_set_description(s->monitor_source, n);
         pa_xfree(n);
     }
 
     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);
+        pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SINK_PROPLIST_CHANGED], s);
     }
 }
 
@@ -817,6 +930,7 @@ int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offse
 
         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
@@ -835,6 +949,8 @@ int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offse
                 i->thread_info.sync_next->thread_info.sync_prev = i;
             }
 
+            pa_sink_input_set_max_rewind(i, s->thread_info.max_rewind);
+
             pa_assert(!i->thread_info.attached);
             i->thread_info.attached = TRUE;
 
@@ -845,6 +961,11 @@ int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offse
              * ghost sink input handling a few lines down at
              * PA_SINK_MESSAGE_REMOVE_INPUT_AND_BUFFER, too. */
 
+            pa_sink_invalidate_requested_latency(s);
+
+/*             i->thread_info.ignore_rewind = TRUE; */
+/*             pa_sink_request_rewind(s, 0); */
+
             return 0;
         }
 
@@ -881,6 +1002,10 @@ int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offse
             if (pa_hashmap_remove(s->thread_info.inputs, PA_UINT32_TO_PTR(i->index)))
                 pa_sink_input_unref(i);
 
+            pa_sink_invalidate_requested_latency(s);
+
+/*             pa_sink_request_rewind(s, 0); */
+
             return 0;
         }
 
@@ -899,6 +1024,7 @@ int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offse
 
             pa_assert(info->sink_input->thread_info.attached);
             info->sink_input->thread_info.attached = FALSE;
+            pa_sink_invalidate_requested_latency(info->sink_input->sink);
 
             if (info->ghost_sink_input) {
                 pa_assert(info->buffer_bytes > 0);
@@ -934,9 +1060,8 @@ int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offse
                     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);
+                /* Add the remaining already resampled chunks to the buffer */
+                pa_memblockq_splice(info->buffer, info->sink_input->thread_info.render_memblockq);
 
                 pa_memblockq_sink_input_set_queue(info->ghost_sink_input, info->buffer);
 
@@ -952,22 +1077,33 @@ int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offse
                 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_sink_input_set_max_rewind(info->ghost_sink_input, s->thread_info.max_rewind);
+
                 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);
+
             }
 
+            pa_sink_invalidate_requested_latency(s);
+
+            pa_sink_request_rewind(s, 0);
+
             return 0;
         }
 
         case PA_SINK_MESSAGE_SET_VOLUME:
             s->thread_info.soft_volume = *((pa_cvolume*) userdata);
+
+            pa_sink_request_rewind(s, 0);
             return 0;
 
         case PA_SINK_MESSAGE_SET_MUTE:
             s->thread_info.soft_muted = PA_PTR_TO_UINT(userdata);
+
+            pa_sink_request_rewind(s, 0);
             return 0;
 
         case PA_SINK_MESSAGE_GET_VOLUME:
@@ -1064,3 +1200,73 @@ void pa_sink_attach_within_thread(pa_sink *s) {
     if (s->monitor_source)
         pa_source_attach_within_thread(s->monitor_source);
 }
+
+void pa_sink_request_rewind(pa_sink*s, size_t nbytes) {
+    pa_sink_assert_ref(s);
+    pa_assert(PA_SINK_LINKED(s->thread_info.state));
+
+    if (nbytes <= 0)
+        nbytes = s->thread_info.max_rewind;
+
+    nbytes = PA_MIN(nbytes, s->thread_info.max_rewind);
+
+    if (nbytes <= s->thread_info.rewind_nbytes)
+        return;
+
+    s->thread_info.rewind_nbytes = nbytes;
+
+    if (s->request_rewind)
+        s->request_rewind(s);
+}
+
+pa_usec_t pa_sink_get_requested_latency(pa_sink *s) {
+    pa_usec_t result = 0;
+    pa_sink_input *i;
+    void *state = NULL;
+
+    pa_sink_assert_ref(s);
+
+    if (s->thread_info.requested_latency_valid)
+        return s->thread_info.requested_latency;
+
+    while ((i = pa_hashmap_iterate(s->thread_info.inputs, &state, NULL)))
+
+        if (i->thread_info.requested_sink_latency > 0 &&
+            (!result || result > i->thread_info.requested_sink_latency))
+            result = i->thread_info.requested_sink_latency;
+
+    s->thread_info.requested_latency = result;
+    s->thread_info.requested_latency_valid = TRUE;
+
+    return result;
+}
+
+void pa_sink_set_max_rewind(pa_sink *s, size_t max_rewind) {
+    pa_sink_input *i;
+    void *state = NULL;
+
+    pa_sink_assert_ref(s);
+    pa_assert(PA_SINK_LINKED(s->thread_info.state));
+
+    if (max_rewind == s->thread_info.max_rewind)
+        return;
+
+    s->thread_info.max_rewind = max_rewind;
+
+    while ((i = pa_hashmap_iterate(s->thread_info.inputs, &state, NULL)))
+        pa_sink_input_set_max_rewind(i, s->thread_info.max_rewind);
+}
+
+void pa_sink_invalidate_requested_latency(pa_sink *s) {
+
+    pa_sink_assert_ref(s);
+    pa_assert(PA_SINK_LINKED(s->thread_info.state));
+
+    if (!s->thread_info.requested_latency_valid)
+        return;
+
+    s->thread_info.requested_latency_valid = FALSE;
+
+    if (s->update_requested_latency)
+        s->update_requested_latency(s);
+}
diff --git a/src/pulsecore/sink.h b/src/pulsecore/sink.h
index e996930..3f16995 100644
--- a/src/pulsecore/sink.h
+++ b/src/pulsecore/sink.h
@@ -69,7 +69,8 @@ struct pa_sink {
     pa_sink_flags_t flags;
 
     char *name;
-    char *description, *driver;            /* may be NULL */
+    char *driver;                           /* may be NULL */
+    pa_proplist *proplist;
 
     pa_module *module;                      /* may be NULL */
 
@@ -85,16 +86,20 @@ struct pa_sink {
     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;
 
+    pa_memblock *silence;
+
+    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 */
+    void (*request_rewind)(pa_sink *s);        /* dito */
+    void (*update_requested_latency)(pa_sink *s); /* dito */
+
     /* Contains copies of the above data so that the real-time worker
      * thread can work without access locking */
     struct {
@@ -102,9 +107,17 @@ struct pa_sink {
         pa_hashmap *inputs;
         pa_cvolume soft_volume;
         pa_bool_t soft_muted;
-    } thread_info;
 
-    pa_memblock *silence;
+        pa_bool_t requested_latency_valid;
+        size_t requested_latency;
+
+        /* The number of bytes we need keep around to be able to satisfy
+         * every DMA buffer rewrite */
+        size_t max_rewind;
+
+        /* Maximum of what clients requested to rewind in this cycle */
+        size_t rewind_nbytes;
+    } thread_info;
 
     void *userdata;
 };
@@ -128,20 +141,43 @@ typedef enum pa_sink_message {
     PA_SINK_MESSAGE_MAX
 } pa_sink_message_t;
 
+typedef struct pa_sink_new_data {
+    char *name;
+    pa_bool_t namereg_fail;
+    pa_proplist *proplist;
+
+    const char *driver;
+    pa_module *module;
+
+    pa_sample_spec sample_spec;
+    pa_bool_t sample_spec_is_set;
+    pa_channel_map channel_map;
+    pa_bool_t channel_map_is_set;
+
+    pa_cvolume volume;
+    pa_bool_t volume_is_set;
+    pa_bool_t muted;
+    pa_bool_t muted_is_set;
+} pa_sink_new_data;
+
+pa_sink_new_data* pa_sink_new_data_init(pa_sink_new_data *data);
+void pa_sink_new_data_set_name(pa_sink_new_data *data, const char *name);
+void pa_sink_new_data_set_sample_spec(pa_sink_new_data *data, const pa_sample_spec *spec);
+void pa_sink_new_data_set_channel_map(pa_sink_new_data *data, const pa_channel_map *map);
+void pa_sink_new_data_set_volume(pa_sink_new_data *data, const pa_cvolume *volume);
+void pa_sink_new_data_set_muted(pa_sink_new_data *data, pa_bool_t mute);
+void pa_sink_new_data_done(pa_sink_new_data *data);
+
 /* 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);
+        pa_sink_new_data *data,
+        pa_sink_flags_t flags);
 
 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);
@@ -151,12 +187,15 @@ void pa_sink_attach(pa_sink *s);
 
 /* May be called by everyone, from main context */
 
+/* The returned value is supposed to be in the time domain of the sound card! */
 pa_usec_t pa_sink_get_latency(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_rewind(pa_sink *s, size_t length);
+
 /* 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 */
@@ -173,11 +212,12 @@ unsigned pa_sink_used_by(pa_sink *s); /* Number of connected streams which are n
 
 /* To be called exclusively by the sink driver, from IO context */
 
+void pa_sink_process_rewind(pa_sink *s);
+
 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);
@@ -185,4 +225,14 @@ int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offse
 void pa_sink_attach_within_thread(pa_sink *s);
 void pa_sink_detach_within_thread(pa_sink *s);
 
+pa_usec_t pa_sink_get_requested_latency(pa_sink *s);
+
+void pa_sink_set_max_rewind(pa_sink *s, size_t max_rewind);
+
+/* To be called exclusively by sink input drivers, from IO context */
+
+void pa_sink_request_rewind(pa_sink*s, size_t nbytes);
+
+void pa_sink_invalidate_requested_latency(pa_sink *s);
+
 #endif
diff --git a/src/pulsecore/sound-file-stream.c b/src/pulsecore/sound-file-stream.c
index bb1f3e9..60c2560 100644
--- a/src/pulsecore/sound-file-stream.c
+++ b/src/pulsecore/sound-file-stream.c
@@ -41,17 +41,21 @@
 #include <pulsecore/log.h>
 #include <pulsecore/thread-mq.h>
 #include <pulsecore/core-util.h>
+#include <pulsecore/sample-util.h>
 
 #include "sound-file-stream.h"
 
+#define MEMBLOCKQ_MAXLENGTH (16*1024*1024)
+
 typedef struct file_stream {
     pa_msgobject parent;
     pa_core *core;
-    SNDFILE *sndfile;
     pa_sink_input *sink_input;
-    pa_memchunk memchunk;
+
+    SNDFILE *sndfile;
     sf_count_t (*readf_function)(SNDFILE *sndfile, void *ptr, sf_count_t frames);
-    size_t drop;
+
+    pa_memblockq *memblockq;
 } file_stream;
 
 enum {
@@ -69,7 +73,6 @@ static void file_stream_unlink(file_stream *u) {
         return;
 
     pa_sink_input_unlink(u->sink_input);
-
     pa_sink_input_unref(u->sink_input);
     u->sink_input = NULL;
 
@@ -81,10 +84,8 @@ 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->memblockq)
+        pa_memblockq_free(u->memblockq);
 
     if (u->sndfile)
         sf_close(u->sndfile);
@@ -106,116 +107,122 @@ static int file_stream_process_msg(pa_msgobject *o, int code, void*userdata, int
 }
 
 static void sink_input_kill_cb(pa_sink_input *i) {
+    file_stream *u;
+
     pa_sink_input_assert_ref(i);
+    u = FILE_STREAM(i->userdata);
+    file_stream_assert_ref(u);
 
-    file_stream_unlink(FILE_STREAM(i->userdata));
+    file_stream_unlink(u);
 }
 
-static int sink_input_peek_cb(pa_sink_input *i, size_t length, pa_memchunk *chunk) {
+static int sink_input_pop_cb(pa_sink_input *i, size_t length, pa_memchunk *chunk) {
     file_stream *u;
 
-    pa_assert(i);
+    pa_sink_input_assert_ref(i);
     pa_assert(chunk);
     u = FILE_STREAM(i->userdata);
     file_stream_assert_ref(u);
 
-    if (!u->sndfile)
+    if (!u->memblockq)
         return -1;
 
-    for (;;) {
-
-        if (!u->memchunk.memblock) {
+    pa_log_debug("pop: %lu", (unsigned long) length);
 
-            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);
+    for (;;) {
+        pa_memchunk tchunk;
 
-                p = pa_memblock_acquire(u->memchunk.memblock);
-                n = u->readf_function(u->sndfile, p, length/fs);
-                pa_memblock_release(u->memchunk.memblock);
+        if (pa_memblockq_peek(u->memblockq, chunk) >= 0) {
+            pa_memblockq_drop(u->memblockq, chunk->length);
+            return 0;
+        }
 
-                if (n <= 0)
-                    n = 0;
+        if (!u->sndfile)
+            break;
 
-                u->memchunk.length = n * fs;
-            } else {
-                sf_count_t n;
-                void *p;
+        tchunk.memblock = pa_memblock_new(i->sink->core->mempool, length);
+        tchunk.index = 0;
 
-                p = pa_memblock_acquire(u->memchunk.memblock);
-                n = sf_read_raw(u->sndfile, p, length);
-                pa_memblock_release(u->memchunk.memblock);
+        if (u->readf_function) {
+            sf_count_t n;
+            void *p;
+            size_t fs = pa_frame_size(&i->sample_spec);
 
-                if (n <= 0)
-                    n = 0;
+            p = pa_memblock_acquire(tchunk.memblock);
+            n = u->readf_function(u->sndfile, p, length/fs);
+            pa_memblock_release(tchunk.memblock);
 
-                u->memchunk.length = n;
-            }
+            if (n <= 0)
+                n = 0;
 
-            if (u->memchunk.length <= 0) {
+            tchunk.length = n * fs;
 
-                pa_memblock_unref(u->memchunk.memblock);
-                pa_memchunk_reset(&u->memchunk);
+        } else {
+            sf_count_t n;
+            void *p;
 
-                pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(u), FILE_STREAM_MESSAGE_UNLINK, NULL, 0, NULL, NULL);
+            p = pa_memblock_acquire(tchunk.memblock);
+            n = sf_read_raw(u->sndfile, p, length);
+            pa_memblock_release(tchunk.memblock);
 
-                sf_close(u->sndfile);
-                u->sndfile = NULL;
+            if (n <= 0)
+                n = 0;
 
-                return -1;
-            }
+            tchunk.length = n;
         }
 
-        pa_assert(u->memchunk.memblock);
-        pa_assert(u->memchunk.length > 0);
+        if (tchunk.length <= 0) {
+
+            pa_memblock_unref(tchunk.memblock);
 
-        if (u->drop < u->memchunk.length) {
-            u->memchunk.index += u->drop;
-            u->memchunk.length -= u->drop;
-            u->drop = 0;
+            sf_close(u->sndfile);
+            u->sndfile = NULL;
             break;
         }
 
-        u->drop -= u->memchunk.length;
-        pa_memblock_unref(u->memchunk.memblock);
-        pa_memchunk_reset(&u->memchunk);
+        pa_memblockq_push(u->memblockq, &tchunk);
+        pa_memblock_unref(tchunk.memblock);
     }
 
-    *chunk = u->memchunk;
-    pa_memblock_ref(chunk->memblock);
+    pa_log_debug("peek fail");
 
-    pa_assert(chunk->length > 0);
-    pa_assert(u->drop <= 0);
+    if (pa_sink_input_safe_to_remove(i)) {
+        pa_log_debug("completed to play");
 
-    return 0;
+        pa_memblockq_free(u->memblockq);
+        u->memblockq = NULL;
+
+        pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(u), FILE_STREAM_MESSAGE_UNLINK, NULL, 0, NULL, NULL);
+    }
+
+    return -1;
 }
 
-static void sink_input_drop_cb(pa_sink_input *i, size_t length) {
+static void sink_input_rewind_cb(pa_sink_input *i, size_t nbytes) {
     file_stream *u;
 
-    pa_assert(i);
-    pa_assert(length > 0);
+    pa_sink_input_assert_ref(i);
+    pa_assert(nbytes > 0);
     u = FILE_STREAM(i->userdata);
     file_stream_assert_ref(u);
 
-    if (u->memchunk.memblock) {
+    if (!u->memblockq)
+        return;
 
-        if (length < u->memchunk.length) {
-            u->memchunk.index += length;
-            u->memchunk.length -= length;
-            return;
-        }
+    pa_memblockq_rewind(u->memblockq, nbytes);
+}
 
-        length -= u->memchunk.length;
-        pa_memblock_unref(u->memchunk.memblock);
-        pa_memchunk_reset(&u->memchunk);
-    }
+static void sink_input_set_max_rewind(pa_sink_input *i, size_t nbytes) {
+    file_stream *u;
 
-    u->drop += length;
+    pa_sink_input_assert_ref(i);
+    u = FILE_STREAM(i->userdata);
+    file_stream_assert_ref(u);
+
+    if (!u->memblockq)
+        return;
+
+    pa_memblockq_set_maxrewind(u->memblockq, nbytes);
 }
 
 int pa_play_file(
@@ -228,6 +235,7 @@ int pa_play_file(
     pa_sample_spec ss;
     pa_sink_input_new_data data;
     int fd;
+    pa_memblock *silence;
 
     pa_assert(sink);
     pa_assert(fname);
@@ -237,10 +245,8 @@ int pa_play_file(
     u->parent.process_msg = file_stream_process_msg;
     u->core = sink->core;
     u->sink_input = NULL;
-    pa_memchunk_reset(&u->memchunk);
     u->sndfile = NULL;
     u->readf_function = NULL;
-    u->drop = 0;
 
     memset(&sfinfo, 0, sizeof(sfinfo));
 
@@ -312,18 +318,31 @@ int pa_play_file(
     pa_sink_input_new_data_init(&data);
     data.sink = sink;
     data.driver = __FILE__;
-    data.name = fname;
     pa_sink_input_new_data_set_sample_spec(&data, &ss);
     pa_sink_input_new_data_set_volume(&data, volume);
+    pa_proplist_sets(data.proplist, PA_PROP_MEDIA_NAME, fname);
+    pa_proplist_sets(data.proplist, PA_PROP_MEDIA_FILENAME, fname);
+
+    u->sink_input = pa_sink_input_new(sink->core, &data, 0);
+    pa_sink_input_new_data_done(&data);
 
-    if (!(u->sink_input = pa_sink_input_new(sink->core, &data, 0)))
+    if (!u->sink_input)
         goto fail;
 
-    u->sink_input->peek = sink_input_peek_cb;
-    u->sink_input->drop = sink_input_drop_cb;
+    u->sink_input->pop = sink_input_pop_cb;
+    u->sink_input->rewind = sink_input_rewind_cb;
+    u->sink_input->set_max_rewind = sink_input_set_max_rewind;
     u->sink_input->kill = sink_input_kill_cb;
     u->sink_input->userdata = u;
 
+    silence = pa_silence_memblock_new(
+            u->core->mempool,
+            &u->sink_input->sample_spec,
+            u->sink_input->thread_info.resampler ? pa_resampler_max_block_size(u->sink_input->thread_info.resampler) : 0);
+
+    u->memblockq = pa_memblockq_new(0, MEMBLOCKQ_MAXLENGTH, 0, pa_frame_size(&u->sink_input->sample_spec), 1, 1, 0, silence);
+    pa_memblock_unref(silence);
+
     pa_sink_input_put(u->sink_input);
 
     /* The reference to u is dangling here, because we want to keep
diff --git a/src/pulsecore/source-output.c b/src/pulsecore/source-output.c
index 88c1146..45a8d74 100644
--- a/src/pulsecore/source-output.c
+++ b/src/pulsecore/source-output.c
@@ -32,6 +32,7 @@
 #include <pulse/utf8.h>
 #include <pulse/xmalloc.h>
 
+#include <pulsecore/sample-util.h>
 #include <pulsecore/core-subscribe.h>
 #include <pulsecore/log.h>
 #include <pulsecore/namereg.h>
@@ -47,9 +48,18 @@ pa_source_output_new_data* pa_source_output_new_data_init(pa_source_output_new_d
 
     memset(data, 0, sizeof(*data));
     data->resample_method = PA_RESAMPLER_INVALID;
+    data->proplist = pa_proplist_new();
+
     return data;
 }
 
+void pa_source_output_new_data_set_sample_spec(pa_source_output_new_data *data, const pa_sample_spec *spec) {
+    pa_assert(data);
+
+    if ((data->sample_spec_is_set = !!spec))
+        data->sample_spec = *spec;
+}
+
 void pa_source_output_new_data_set_channel_map(pa_source_output_new_data *data, const pa_channel_map *map) {
     pa_assert(data);
 
@@ -57,11 +67,10 @@ void pa_source_output_new_data_set_channel_map(pa_source_output_new_data *data,
         data->channel_map = *map;
 }
 
-void pa_source_output_new_data_set_sample_spec(pa_source_output_new_data *data, const pa_sample_spec *spec) {
+void pa_source_output_new_data_done(pa_source_output_new_data *data) {
     pa_assert(data);
 
-    if ((data->sample_spec_is_set = !!spec))
-        data->sample_spec = *spec;
+    pa_proplist_free(data->proplist);
 }
 
 pa_source_output* pa_source_output_new(
@@ -80,7 +89,6 @@ pa_source_output* pa_source_output_new(
         return NULL;
 
     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);
@@ -156,7 +164,7 @@ pa_source_output* pa_source_output_new(
     o->core = core;
     o->state = PA_SOURCE_OUTPUT_INIT;
     o->flags = flags;
-    o->name = pa_xstrdup(data->name);
+    o->proplist = pa_proplist_copy(data->proplist);
     o->driver = pa_xstrdup(data->driver);
     o->module = data->module;
     o->source = data->source;
@@ -179,13 +187,14 @@ pa_source_output* pa_source_output_new(
     o->thread_info.attached = FALSE;
     o->thread_info.sample_spec = o->sample_spec;
     o->thread_info.resampler = resampler;
+    o->thread_info.requested_source_latency = 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 output %u \"%s\" on %s with sample spec %s and channel map %s",
                 o->index,
-                o->name,
+                pa_strnull(pa_proplist_gets(o->proplist, PA_PROP_MEDIA_NAME)),
                 o->source->name,
                 pa_sample_spec_snprint(st, sizeof(st), &o->sample_spec),
                 pa_channel_map_snprint(cm, sizeof(cm), &o->channel_map));
@@ -210,7 +219,6 @@ static int source_output_set_state(pa_source_output *o, pa_source_output_state_t
         o->source->n_corked++;
 
     pa_source_update_status(o->source);
-
     o->state = state;
 
     if (state != PA_SOURCE_OUTPUT_UNLINKED)
@@ -269,14 +277,16 @@ static void source_output_free(pa_object* mo) {
     if (PA_SOURCE_OUTPUT_LINKED(o->state))
         pa_source_output_unlink(o);
 
-    pa_log_info("Freeing output %u \"%s\"", o->index, o->name);
+    pa_log_info("Freeing output %u \"%s\"", o->index, pa_strnull(pa_proplist_gets(o->proplist, PA_PROP_MEDIA_NAME)));
 
     pa_assert(!o->thread_info.attached);
 
     if (o->thread_info.resampler)
         pa_resampler_free(o->thread_info.resampler);
 
-    pa_xfree(o->name);
+    if (o->proplist)
+        pa_proplist_free(o->proplist);
+
     pa_xfree(o->driver);
     pa_xfree(o);
 }
@@ -292,11 +302,10 @@ void pa_source_output_put(pa_source_output *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_asyncmsgq_send(o->source->asyncmsgq, PA_MSGOBJECT(o->source), PA_SOURCE_MESSAGE_ADD_OUTPUT, o, 0, NULL);
 
     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);
 }
 
@@ -330,7 +339,7 @@ void pa_source_output_push(pa_source_output *o, const pa_memchunk *chunk) {
     pa_source_output_assert_ref(o);
     pa_assert(PA_SOURCE_OUTPUT_LINKED(o->thread_info.state));
     pa_assert(chunk);
-    pa_assert(chunk->length);
+    pa_assert(pa_frame_aligned(chunk->length, &o->source->sample_spec));
 
     if (!o->push || o->state == PA_SOURCE_OUTPUT_CORKED)
         return;
@@ -351,6 +360,14 @@ void pa_source_output_push(pa_source_output *o, const pa_memchunk *chunk) {
     pa_memblock_unref(rchunk.memblock);
 }
 
+void pa_source_output_set_requested_latency(pa_source_output *o, pa_usec_t usec) {
+    pa_source_output_assert_ref(o);
+    pa_assert(PA_SOURCE_OUTPUT_LINKED(o->state));
+
+    pa_asyncmsgq_post(o->source->asyncmsgq, PA_MSGOBJECT(o), PA_SOURCE_OUTPUT_MESSAGE_SET_REQUESTED_LATENCY, NULL, (int64_t) usec, NULL, NULL);
+}
+
+
 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));
@@ -375,19 +392,24 @@ int pa_source_output_set_rate(pa_source_output *o, uint32_t rate) {
 }
 
 void pa_source_output_set_name(pa_source_output *o, const char *name) {
+    const char *old;
     pa_source_output_assert_ref(o);
 
-    if (!o->name && !name)
+    old = pa_proplist_gets(o->proplist, PA_PROP_MEDIA_NAME);
+
+    if (!old && !name)
         return;
 
-    if (o->name && name && !strcmp(o->name, name))
+    if (old && name && !strcmp(old, name))
         return;
 
-    pa_xfree(o->name);
-    o->name = pa_xstrdup(name);
+    if (name)
+        pa_proplist_sets(o->proplist, PA_PROP_MEDIA_NAME, name);
+    else
+        pa_proplist_unset(o->proplist, PA_PROP_MEDIA_NAME);
 
     if (PA_SOURCE_OUTPUT_LINKED(o->state)) {
-        pa_hook_fire(&o->source->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_NAME_CHANGED], o);
+        pa_hook_fire(&o->source->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_PROPLIST_CHANGED], o);
         pa_subscription_post(o->source->core, PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_CHANGE, o->index);
     }
 }
@@ -509,6 +531,13 @@ int pa_source_output_process_msg(pa_msgobject *mo, int code, void *userdata, int
 
             return 0;
         }
+
+        case PA_SOURCE_OUTPUT_MESSAGE_SET_REQUESTED_LATENCY:
+
+            o->thread_info.requested_source_latency = (pa_usec_t) offset;
+            pa_source_invalidate_requested_latency(o->source);
+
+            return 0;
     }
 
     return -1;
diff --git a/src/pulsecore/source-output.h b/src/pulsecore/source-output.h
index d6da8d0..dc95217 100644
--- a/src/pulsecore/source-output.h
+++ b/src/pulsecore/source-output.h
@@ -62,10 +62,12 @@ struct pa_source_output {
 
     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_proplist *proplist;
+    char *driver;                         /* may be NULL */
     pa_module *module;                    /* may be NULL */
     pa_client *client;                    /* may be NULL */
 
@@ -74,6 +76,8 @@ struct pa_source_output {
     pa_sample_spec sample_spec;
     pa_channel_map channel_map;
 
+    pa_resample_method_t resample_method;
+
     /* Pushes a new memchunk into the output. Called from IO thread
      * context. */
     void (*push)(pa_source_output *o, const pa_memchunk *chunk);
@@ -87,13 +91,13 @@ struct pa_source_output {
     void (*detach) (pa_source_output *o);           /* may be NULL */
 
     /* If non-NULL called whenever the the source this output is attached
-     * to changes. Called from main context */
-    void (*moved) (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, pa_bool_t b);   /* may be NULL */
 
+    /* If non-NULL called whenever the the source this output is attached
+     * to changes. Called from main context */
+    void (*moved) (pa_source_output *o);   /* may be NULL */
+
     /* Supposed to unlink and destroy this stream. Called from main
      * context. */
     void (*kill)(pa_source_output* o);              /* may be NULL */
@@ -104,8 +108,6 @@ struct pa_source_output {
     thread instead. */
     pa_usec_t (*get_latency) (pa_source_output *o); /* may be NULL */
 
-    pa_resample_method_t resample_method;
-
     struct {
         pa_source_output_state_t state;
 
@@ -114,6 +116,9 @@ struct pa_source_output {
         pa_sample_spec sample_spec;
 
         pa_resampler* resampler;              /* may be NULL */
+
+        /* The requested latency for the source */
+        pa_usec_t requested_source_latency;
     } thread_info;
 
     void *userdata;
@@ -126,11 +131,14 @@ enum {
     PA_SOURCE_OUTPUT_MESSAGE_GET_LATENCY,
     PA_SOURCE_OUTPUT_MESSAGE_SET_RATE,
     PA_SOURCE_OUTPUT_MESSAGE_SET_STATE,
+    PA_SOURCE_OUTPUT_MESSAGE_SET_REQUESTED_LATENCY,
     PA_SOURCE_OUTPUT_MESSAGE_MAX
 };
 
 typedef struct pa_source_output_new_data {
-    const char *name, *driver;
+    pa_proplist *proplist;
+
+    const char *driver;
     pa_module *module;
     pa_client *client;
 
@@ -152,7 +160,7 @@ typedef struct pa_source_output_move_hook_data {
 pa_source_output_new_data* pa_source_output_new_data_init(pa_source_output_new_data *data);
 void pa_source_output_new_data_set_sample_spec(pa_source_output_new_data *data, const pa_sample_spec *spec);
 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);
+void pa_source_output_new_data_done(pa_source_output_new_data *data);
 
 /* To be called by the implementing module only */
 
@@ -166,6 +174,8 @@ void pa_source_output_unlink(pa_source_output*o);
 
 void pa_source_output_set_name(pa_source_output *i, const char *name);
 
+void pa_source_output_set_requested_latency(pa_source_output *i, pa_usec_t usec);
+
 /* Callable by everyone */
 
 /* External code may request disconnection with this funcion */
@@ -186,6 +196,7 @@ int pa_source_output_move_to(pa_source_output *o, pa_source *dest);
 /* 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
diff --git a/src/pulsecore/source.c b/src/pulsecore/source.c
index d707ad8..cc1c531 100644
--- a/src/pulsecore/source.c
+++ b/src/pulsecore/source.c
@@ -45,35 +45,97 @@ static PA_DEFINE_CHECK_TYPE(pa_source, pa_msgobject);
 
 static void source_free(pa_object *o);
 
+pa_source_new_data* pa_source_new_data_init(pa_source_new_data *data) {
+    pa_assert(data);
+
+    memset(data, 0, sizeof(*data));
+    data->proplist = pa_proplist_new();
+
+    return data;
+}
+
+void pa_source_new_data_set_name(pa_source_new_data *data, const char *name) {
+    pa_assert(data);
+
+    pa_xfree(data->name);
+    data->name = pa_xstrdup(name);
+}
+
+void pa_source_new_data_set_sample_spec(pa_source_new_data *data, const pa_sample_spec *spec) {
+    pa_assert(data);
+
+    if ((data->sample_spec_is_set = !!spec))
+        data->sample_spec = *spec;
+}
+
+void pa_source_new_data_set_channel_map(pa_source_new_data *data, const pa_channel_map *map) {
+    pa_assert(data);
+
+    if ((data->channel_map_is_set = !!map))
+        data->channel_map = *map;
+}
+
+void pa_source_new_data_set_volume(pa_source_new_data *data, const pa_cvolume *volume) {
+    pa_assert(data);
+
+    if ((data->volume_is_set = !!volume))
+        data->volume = *volume;
+}
+
+void pa_source_new_data_set_muted(pa_source_new_data *data, pa_bool_t mute) {
+    pa_assert(data);
+
+    data->muted_is_set = TRUE;
+    data->muted = !!mute;
+}
+
+void pa_source_new_data_done(pa_source_new_data *data) {
+    pa_assert(data);
+
+    pa_xfree(data->name);
+    pa_proplist_free(data->proplist);
+}
+
 pa_source* pa_source_new(
         pa_core *core,
-        const char *driver,
-        const char *name,
-        int fail,
-        const pa_sample_spec *spec,
-        const pa_channel_map *map) {
+        pa_source_new_data *data,
+        pa_source_flags_t flags) {
 
     pa_source *s;
-    char st[256];
-    pa_channel_map tmap;
+    const char *name;
+    char st[PA_SAMPLE_SPEC_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX];
 
     pa_assert(core);
-    pa_assert(name);
-    pa_assert(spec);
 
-    pa_return_null_if_fail(pa_sample_spec_valid(spec));
+    if (pa_hook_fire(&core->hooks[PA_CORE_HOOK_SOURCE_NEW], data) < 0)
+        return NULL;
+
+    pa_return_null_if_fail(!data->driver || pa_utf8_valid(data->driver));
+    pa_return_null_if_fail(data->name && pa_utf8_valid(data->name) && data->name[0]);
+
+    pa_return_null_if_fail(data->sample_spec_is_set && pa_sample_spec_valid(&data->sample_spec));
 
-    if (!map)
-        pa_return_null_if_fail(map = pa_channel_map_init_auto(&tmap, spec->channels, PA_CHANNEL_MAP_DEFAULT));
+    if (!data->channel_map_is_set)
+        pa_return_null_if_fail(pa_channel_map_init_auto(&data->channel_map, data->sample_spec.channels, PA_CHANNEL_MAP_DEFAULT));
 
-    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);
+    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);
+
+    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 = FALSE;
+
+    if (pa_hook_fire(&core->hooks[PA_CORE_HOOK_SOURCE_FIXATE], data) < 0)
+        return NULL;
 
     s = pa_msgobject_new(pa_source);
 
-    if (!(name = pa_namereg_register(core, name, PA_NAMEREG_SOURCE, s, fail))) {
+    if (!(name = pa_namereg_register(core, data->name, PA_NAMEREG_SOURCE, s, data->namereg_fail))) {
         pa_xfree(s);
         return NULL;
     }
@@ -83,21 +145,21 @@ pa_source* pa_source_new(
 
     s->core = core;
     s->state = PA_SOURCE_INIT;
-    s->flags = 0;
+    s->flags = flags;
     s->name = pa_xstrdup(name);
-    s->description = NULL;
-    s->driver = pa_xstrdup(driver);
-    s->module = NULL;
+    s->proplist = pa_proplist_copy(data->proplist);
+    s->driver = pa_xstrdup(data->driver);
+    s->module = data->module;
 
-    s->sample_spec = *spec;
-    s->channel_map = *map;
+    s->sample_spec = data->sample_spec;
+    s->channel_map = data->channel_map;
 
     s->outputs = pa_idxset_new(NULL, NULL);
     s->n_corked = 0;
     s->monitor_of = NULL;
 
-    pa_cvolume_reset(&s->volume, spec->channels);
-    s->muted = FALSE;
+    s->volume = data->volume;
+    s->muted = data->muted;
     s->refresh_volume = s->refresh_muted = FALSE;
 
     s->get_latency = NULL;
@@ -106,20 +168,26 @@ pa_source* pa_source_new(
     s->set_mute = NULL;
     s->get_mute = NULL;
     s->set_state = NULL;
+    s->update_requested_latency = NULL;
     s->userdata = NULL;
 
     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 source %u \"%s\" with sample spec \"%s\"", s->index, s->name, st);
-
     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;
+    s->thread_info.requested_latency_valid = TRUE;
+    s->thread_info.requested_latency = 0;
+
+    pa_assert_se(pa_idxset_put(core->sources, s, &s->index) >= 0);
+
+    pa_log_info("Created source %u \"%s\" with sample spec %s and channel map %s",
+                s->index,
+                s->name,
+                pa_sample_spec_snprint(st, sizeof(st), &s->sample_spec),
+                pa_channel_map_snprint(cm, sizeof(cm), &s->channel_map));
 
     return s;
 }
@@ -170,10 +238,26 @@ void pa_source_put(pa_source *s) {
     pa_assert(s->rtpoll);
     pa_assert(s->asyncmsgq);
 
+    if (s->get_volume && s->set_volume)
+        s->flags |= PA_SOURCE_HW_VOLUME_CTRL;
+    else {
+        s->get_volume = NULL;
+        s->set_volume = NULL;
+        s->flags = (s->flags & ~PA_SOURCE_HW_VOLUME_CTRL) | PA_SOURCE_DECIBEL_VOLUME;
+    }
+
+    if (s->get_mute && s->set_mute)
+        s->flags |= PA_SOURCE_HW_MUTE_CTRL;
+    else {
+        s->get_mute = NULL;
+        s->set_mute = NULL;
+        s->flags &= ~PA_SOURCE_HW_MUTE_CTRL;
+    }
+
     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);
+    pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SOURCE_PUT], s);
 }
 
 void pa_source_unlink(pa_source *s) {
@@ -211,6 +295,7 @@ void pa_source_unlink(pa_source *s) {
     s->set_mute = NULL;
     s->get_mute = NULL;
     s->set_state = NULL;
+    s->update_requested_latency = NULL;
 
     if (linked) {
         pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE | PA_SUBSCRIPTION_EVENT_REMOVE, s->index);
@@ -238,8 +323,11 @@ static void source_free(pa_object *o) {
     pa_hashmap_free(s->thread_info.outputs, NULL, NULL);
 
     pa_xfree(s->name);
-    pa_xfree(s->description);
     pa_xfree(s->driver);
+
+    if (s->proplist)
+        pa_proplist_free(s->proplist);
+
     pa_xfree(s);
 }
 
@@ -400,32 +488,25 @@ pa_bool_t pa_source_get_mute(pa_source *s) {
     return s->muted;
 }
 
-void pa_source_set_module(pa_source *s, pa_module *m) {
-    pa_source_assert_ref(s);
-
-    if (m == s->module)
-        return;
-
-    s->module = m;
-
-    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) {
+    const char *old;
     pa_source_assert_ref(s);
 
-    if (!description && !s->description)
+    if (!description && !pa_proplist_contains(s->proplist, PA_PROP_DEVICE_DESCRIPTION))
         return;
 
-    if (description && s->description && !strcmp(description, s->description))
+    old = pa_proplist_gets(s->proplist, PA_PROP_DEVICE_DESCRIPTION);
+    if (old && description && !strcmp(old, description))
         return;
 
-    pa_xfree(s->description);
-    s->description = pa_xstrdup(description);
+    if (description)
+        pa_proplist_sets(s->proplist, PA_PROP_DEVICE_DESCRIPTION, description);
+    else
+        pa_proplist_unset(s->proplist, PA_PROP_DEVICE_DESCRIPTION);
 
     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);
+        pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SOURCE_PROPLIST_CHANGED], s);
     }
 }
 
@@ -470,6 +551,7 @@ int pa_source_process_msg(pa_msgobject *object, int code, void *userdata, int64_
     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);
@@ -478,6 +560,8 @@ int pa_source_process_msg(pa_msgobject *object, int code, void *userdata, int64_
             if (o->attach)
                 o->attach(o);
 
+            pa_source_invalidate_requested_latency(s);
+
             return 0;
         }
 
@@ -493,6 +577,8 @@ int pa_source_process_msg(pa_msgobject *object, int code, void *userdata, int64_
             if (pa_hashmap_remove(s->thread_info.outputs, PA_UINT32_TO_PTR(o->index)))
                 pa_source_output_unref(o);
 
+            pa_source_invalidate_requested_latency(s);
+
             return 0;
         }
 
@@ -590,5 +676,40 @@ void pa_source_attach_within_thread(pa_source *s) {
     while ((o = pa_hashmap_iterate(s->thread_info.outputs, &state, NULL)))
         if (o->attach)
             o->attach(o);
+}
+
+pa_usec_t pa_source_get_requested_latency(pa_source *s) {
+    pa_usec_t result = 0;
+    pa_source_output *o;
+    void *state = NULL;
+
+    pa_source_assert_ref(s);
+
+    if (s->thread_info.requested_latency_valid)
+        return s->thread_info.requested_latency;
+
+    while ((o = pa_hashmap_iterate(s->thread_info.outputs, &state, NULL)))
+
+        if (o->thread_info.requested_source_latency > 0 &&
+            (!result || result > o->thread_info.requested_source_latency))
+            result = o->thread_info.requested_source_latency;
+
+    s->thread_info.requested_latency = result;
+    s->thread_info.requested_latency_valid = TRUE;
+
+    return result;
+}
+
+void pa_source_invalidate_requested_latency(pa_source *s) {
+
+    pa_source_assert_ref(s);
+    pa_assert(PA_SOURCE_LINKED(s->thread_info.state));
+
+    if (!s->thread_info.requested_latency_valid)
+        return;
+
+    s->thread_info.requested_latency_valid = FALSE;
 
+    if (s->update_requested_latency)
+        s->update_requested_latency(s);
 }
diff --git a/src/pulsecore/source.h b/src/pulsecore/source.h
index bd0a912..c880d3c 100644
--- a/src/pulsecore/source.h
+++ b/src/pulsecore/source.h
@@ -71,7 +71,8 @@ struct pa_source {
     pa_source_flags_t flags;
 
     char *name;
-    char *description, *driver;              /* may be NULL */
+    char *driver;                             /* may be NULL */
+    pa_proplist *proplist;
 
     pa_module *module;                        /* may be NULL */
 
@@ -87,15 +88,16 @@ struct pa_source {
     pa_bool_t refresh_volume;
     pa_bool_t refresh_muted;
 
+    pa_asyncmsgq *asyncmsgq;
+    pa_rtpoll *rtpoll;
+
     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 */
-
-    pa_asyncmsgq *asyncmsgq;
-    pa_rtpoll *rtpoll;
+    void (*update_requested_latency)(pa_source *s); /* dito */
 
     /* Contains copies of the above data so that the real-time worker
      * thread can work without access locking */
@@ -104,6 +106,9 @@ struct pa_source {
         pa_hashmap *outputs;
         pa_cvolume soft_volume;
         pa_bool_t soft_muted;
+
+        pa_bool_t requested_latency_valid;
+        size_t requested_latency;
     } thread_info;
 
     void *userdata;
@@ -127,20 +132,43 @@ typedef enum pa_source_message {
     PA_SOURCE_MESSAGE_MAX
 } pa_source_message_t;
 
+typedef struct pa_source_new_data {
+    char *name;
+    pa_bool_t namereg_fail;
+    pa_proplist *proplist;
+
+    const char *driver;
+    pa_module *module;
+
+    pa_sample_spec sample_spec;
+    pa_bool_t sample_spec_is_set;
+    pa_channel_map channel_map;
+    pa_bool_t channel_map_is_set;
+
+    pa_cvolume volume;
+    pa_bool_t volume_is_set;
+    pa_bool_t muted;
+    pa_bool_t muted_is_set;
+} pa_source_new_data;
+
+pa_source_new_data* pa_source_new_data_init(pa_source_new_data *data);
+void pa_source_new_data_set_name(pa_source_new_data *data, const char *name);
+void pa_source_new_data_set_sample_spec(pa_source_new_data *data, const pa_sample_spec *spec);
+void pa_source_new_data_set_channel_map(pa_source_new_data *data, const pa_channel_map *map);
+void pa_source_new_data_set_volume(pa_source_new_data *data, const pa_cvolume *volume);
+void pa_source_new_data_set_muted(pa_source_new_data *data, pa_bool_t mute);
+void pa_source_new_data_done(pa_source_new_data *data);
+
 /* 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);
+        pa_source_new_data *data,
+        pa_source_flags_t flags);
 
 void pa_source_put(pa_source *s);
 void pa_source_unlink(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);
@@ -176,4 +204,10 @@ int pa_source_process_msg(pa_msgobject *o, int code, void *userdata, int64_t, pa
 void pa_source_attach_within_thread(pa_source *s);
 void pa_source_detach_within_thread(pa_source *s);
 
+pa_usec_t pa_source_get_requested_latency(pa_source *s);
+
+/* To be called exclusively by source output drivers, from IO context */
+
+void pa_source_invalidate_requested_latency(pa_source *s);
+
 #endif
diff --git a/src/pulsecore/tagstruct.c b/src/pulsecore/tagstruct.c
index 556fe80..0017c38 100644
--- a/src/pulsecore/tagstruct.c
+++ b/src/pulsecore/tagstruct.c
@@ -42,12 +42,14 @@
 
 #include "tagstruct.h"
 
+#define MAX_TAG_SIZE (64*1024)
+
 struct pa_tagstruct {
     uint8_t *data;
     size_t length, allocated;
     size_t rindex;
 
-    int dynamic;
+    pa_bool_t dynamic;
 };
 
 pa_tagstruct *pa_tagstruct_new(const uint8_t* data, size_t length) {
@@ -254,6 +256,32 @@ void pa_tagstruct_put_cvolume(pa_tagstruct *t, const pa_cvolume *cvolume) {
     }
 }
 
+void pa_tagstruct_put_proplist(pa_tagstruct *t, pa_proplist *p) {
+    void *state = NULL;
+    pa_assert(t);
+    pa_assert(p);
+
+    extend(t, 1);
+
+    t->data[t->length++] = PA_TAG_PROPLIST;
+
+    for (;;) {
+        const char *k;
+        const void *d;
+        size_t l;
+
+        if (!(k = pa_proplist_iterate(p, &state)))
+            break;
+
+        pa_tagstruct_puts(t, k);
+        pa_assert_se(pa_proplist_get(p, k, &d, &l) >= 0);
+        pa_tagstruct_putu32(t, (uint32_t) l);
+        pa_tagstruct_put_arbitrary(t, d, l);
+    }
+
+    pa_tagstruct_puts(t, NULL);
+}
+
 int pa_tagstruct_gets(pa_tagstruct*t, const char **s) {
     int error = 0;
     size_t n;
@@ -529,6 +557,57 @@ int pa_tagstruct_get_cvolume(pa_tagstruct *t, pa_cvolume *cvolume) {
     return 0;
 }
 
+int pa_tagstruct_get_proplist(pa_tagstruct *t, pa_proplist *p) {
+    size_t saved_rindex;
+
+    pa_assert(t);
+    pa_assert(p);
+
+    if (t->rindex+1 > t->length)
+        return -1;
+
+    if (t->data[t->rindex] != PA_TAG_PROPLIST)
+        return -1;
+
+    saved_rindex = t->rindex;
+
+    for (;;) {
+        const char *k;
+        void *d;
+        uint32_t length;
+
+        if (pa_tagstruct_gets(t, &k) < 0)
+            goto fail;
+
+        if (!k)
+            break;
+
+        if (pa_tagstruct_getu32(t, &length) < 0)
+            goto fail;
+
+        if (length > MAX_TAG_SIZE)
+            goto fail;
+
+        d = pa_xmalloc(length);
+
+        if (pa_tagstruct_get_arbitrary(t, d, length) < 0)
+            goto fail;
+
+        if (pa_proplist_set(p, k, d, length) < 0) {
+            pa_xfree(d);
+            goto fail;
+        }
+
+        pa_xfree(d);
+    }
+
+    return 0;
+
+fail:
+    t->rindex = saved_rindex;
+    return -1;
+}
+
 void pa_tagstruct_put(pa_tagstruct *t, ...) {
     va_list va;
     pa_assert(t);
@@ -591,6 +670,9 @@ void pa_tagstruct_put(pa_tagstruct *t, ...) {
                 pa_tagstruct_put_cvolume(t, va_arg(va, pa_cvolume *));
                 break;
 
+            case PA_TAG_PROPLIST:
+                pa_tagstruct_put_proplist(t, va_arg(va, pa_proplist *));
+
             default:
                 pa_assert_not_reached();
         }
@@ -662,6 +744,9 @@ int pa_tagstruct_get(pa_tagstruct *t, ...) {
                 ret = pa_tagstruct_get_cvolume(t, va_arg(va, pa_cvolume *));
                 break;
 
+            case PA_TAG_PROPLIST:
+                ret = pa_tagstruct_get_proplist(t, va_arg(va, pa_proplist *));
+
             default:
                 pa_assert_not_reached();
         }
diff --git a/src/pulsecore/tagstruct.h b/src/pulsecore/tagstruct.h
index e9bb9ac..3b2ce7b 100644
--- a/src/pulsecore/tagstruct.h
+++ b/src/pulsecore/tagstruct.h
@@ -32,6 +32,7 @@
 #include <pulse/sample.h>
 #include <pulse/channelmap.h>
 #include <pulse/volume.h>
+#include <pulse/proplist.h>
 
 typedef struct pa_tagstruct pa_tagstruct;
 
@@ -51,7 +52,8 @@ enum {
     PA_TAG_TIMEVAL = 'T',
     PA_TAG_USEC = 'U'  /* 64bit unsigned */,
     PA_TAG_CHANNEL_MAP = 'm',
-    PA_TAG_CVOLUME = 'v'
+    PA_TAG_CVOLUME = 'v',
+    PA_TAG_PROPLIST = 'P'
 };
 
 pa_tagstruct *pa_tagstruct_new(const uint8_t* data, size_t length);
@@ -75,6 +77,7 @@ void pa_tagstruct_put_timeval(pa_tagstruct*t, const struct timeval *tv);
 void pa_tagstruct_put_usec(pa_tagstruct*t, pa_usec_t u);
 void pa_tagstruct_put_channel_map(pa_tagstruct *t, const pa_channel_map *map);
 void pa_tagstruct_put_cvolume(pa_tagstruct *t, const pa_cvolume *cvolume);
+void pa_tagstruct_put_proplist(pa_tagstruct *t, pa_proplist *p);
 
 int pa_tagstruct_get(pa_tagstruct *t, ...);
 
@@ -90,6 +93,7 @@ int pa_tagstruct_get_timeval(pa_tagstruct*t, struct timeval *tv);
 int pa_tagstruct_get_usec(pa_tagstruct*t, pa_usec_t *u);
 int pa_tagstruct_get_channel_map(pa_tagstruct *t, pa_channel_map *map);
 int pa_tagstruct_get_cvolume(pa_tagstruct *t, pa_cvolume *v);
+int pa_tagstruct_get_proplist(pa_tagstruct *t, pa_proplist *p);
 
 
 #endif
diff --git a/src/pulsecore/time-smoother.c b/src/pulsecore/time-smoother.c
index 4cebded..b44aaa5 100644
--- a/src/pulsecore/time-smoother.c
+++ b/src/pulsecore/time-smoother.c
@@ -332,6 +332,8 @@ void pa_smoother_put(pa_smoother *s, pa_usec_t x, pa_usec_t y) {
     s->py = y + s->dp *s->adjust_time;
 
     s->abc_valid = FALSE;
+
+    pa_log_debug("put(%llu | %llu) = %llu", x + s->time_offset, x, y);
 }
 
 pa_usec_t pa_smoother_get(pa_smoother *s, pa_usec_t x) {
@@ -350,6 +352,9 @@ pa_usec_t pa_smoother_get(pa_smoother *s, pa_usec_t x) {
     pa_assert(x >= s->ex);
 
     estimate(s, x, &y, NULL);
+
+    pa_log_debug("get(%llu | %llu) = %llu", x + s->time_offset, x, y);
+
     return y;
 }
 
@@ -357,6 +362,8 @@ void pa_smoother_set_time_offset(pa_smoother *s, pa_usec_t offset) {
     pa_assert(s);
 
     s->time_offset = offset;
+
+    pa_log_debug("offset(%llu)", offset);
 }
 
 void pa_smoother_pause(pa_smoother *s, pa_usec_t x) {
@@ -365,6 +372,8 @@ void pa_smoother_pause(pa_smoother *s, pa_usec_t x) {
     if (s->paused)
         return;
 
+    pa_log_debug("pause(%llu)", x);
+
     s->paused = TRUE;
     s->pause_time = x;
 }
@@ -377,6 +386,31 @@ void pa_smoother_resume(pa_smoother *s, pa_usec_t x) {
 
     pa_assert(x >= s->pause_time);
 
+    pa_log_debug("resume(%llu)", x);
+
     s->paused = FALSE;
     s->time_offset += x - s->pause_time;
 }
+
+pa_usec_t pa_smoother_translate(pa_smoother *s, pa_usec_t x, pa_usec_t y_delay) {
+    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;
+
+    pa_assert(x >= s->time_offset);
+    x -= s->time_offset;
+
+    pa_assert(x >= s->ex);
+
+    estimate(s, x, &ney, &nde);
+
+    pa_log_debug("translate(%llu) = %llu (%0.2f)", (unsigned long long) y_delay, (unsigned long long) ((double) y_delay / s->dp), s->dp);
+
+    return (pa_usec_t) ((double) y_delay / s->dp);
+}
diff --git a/src/pulsecore/time-smoother.h b/src/pulsecore/time-smoother.h
index 8b8512e..85d9f0f 100644
--- a/src/pulsecore/time-smoother.h
+++ b/src/pulsecore/time-smoother.h
@@ -29,13 +29,19 @@
 
 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);
+pa_smoother* pa_smoother_new(pa_usec_t x_adjust_time, pa_usec_t x_history_time, pa_bool_t monotonic);
 void pa_smoother_free(pa_smoother* s);
 
+/* Adds a new value to our dataset. x = local/system time, y = remote time */
 void pa_smoother_put(pa_smoother *s, pa_usec_t x, pa_usec_t y);
+
+/* Returns an interpolated value based on the dataset. x = local/system time, return value = remote time */
 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);
+/* Translates a time span from the remote time domain to the local one. x = local/system time when to estimate, y_delay = remote time span */
+pa_usec_t pa_smoother_translate(pa_smoother *s, pa_usec_t x, pa_usec_t y_delay);
+
+void pa_smoother_set_time_offset(pa_smoother *s, pa_usec_t x_offset);
 
 void pa_smoother_pause(pa_smoother *s, pa_usec_t x);
 void pa_smoother_resume(pa_smoother *s, pa_usec_t x);

commit ebecf3d3e19ac56f507ce771d5c455198280a80c
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sat Mar 15 15:21:26 2008 +0000

    commit glitch-free work
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2123 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/tests/memblockq-test.c b/src/tests/memblockq-test.c
index 25ea399..402c857 100644
--- a/src/tests/memblockq-test.c
+++ b/src/tests/memblockq-test.c
@@ -31,6 +31,30 @@
 #include <pulsecore/memblockq.h>
 #include <pulsecore/log.h>
 
+static void dump(pa_memblockq *bq) {
+    printf(">");
+
+    for (;;) {
+        pa_memchunk out;
+        char *e;
+        size_t n;
+        void *q;
+
+        if (pa_memblockq_peek(bq, &out) < 0)
+            break;
+
+        q = pa_memblock_acquire(out.memblock);
+        for (e = (char*) q + 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.length);
+    }
+
+    printf("<\n");
+}
+
 int main(int argc, char *argv[]) {
     int ret;
 
@@ -46,7 +70,7 @@ int main(int argc, char *argv[]) {
     silence = pa_memblock_new_fixed(p, (char*)  "__", 2, 1);
     assert(silence);
 
-    bq = pa_memblockq_new(0, 40, 10, 2, 4, 4, silence);
+    bq = pa_memblockq_new(0, 40, 10, 2, 4, 4, 40, silence);
     assert(bq);
 
     chunk1.memblock = pa_memblock_new_fixed(p, (char*) "11", 2, 1);
@@ -72,13 +96,13 @@ int main(int argc, char *argv[]) {
     ret = pa_memblockq_push(bq, &chunk1);
     assert(ret == 0);
 
-    ret = pa_memblockq_push(bq, &chunk1);
+    ret = pa_memblockq_push(bq, &chunk2);
     assert(ret == 0);
 
-    ret = pa_memblockq_push(bq, &chunk2);
+    ret = pa_memblockq_push(bq, &chunk3);
     assert(ret == 0);
 
-    ret = pa_memblockq_push(bq, &chunk2);
+    ret = pa_memblockq_push(bq, &chunk4);
     assert(ret == 0);
 
     pa_memblockq_seek(bq, -6, 0);
@@ -86,7 +110,7 @@ int main(int argc, char *argv[]) {
     assert(ret == 0);
 
     pa_memblockq_seek(bq, -2, 0);
-    ret = pa_memblockq_push(bq, &chunk3);
+    ret = pa_memblockq_push(bq, &chunk1);
     assert(ret == 0);
 
     pa_memblockq_seek(bq, -10, 0);
@@ -119,28 +143,13 @@ int main(int argc, char *argv[]) {
     ret = pa_memblockq_push(bq, &chunk3);
     assert(ret == 0);
 
-    pa_memblockq_shorten(bq, pa_memblockq_get_length(bq)-2);
-
-    printf(">");
-
-    for (;;) {
-        pa_memchunk out;
-        char *e;
-        size_t n;
-
-        if (pa_memblockq_peek(bq, &out) < 0)
-            break;
+    pa_memblockq_seek(bq, 30, PA_SEEK_RELATIVE);
 
-        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);
+    dump(bq);
 
-        pa_memblock_unref(out.memblock);
-        pa_memblockq_drop(bq, out.length);
-    }
+    pa_memblockq_rewind(bq, 52);
 
-    printf("<\n");
+    dump(bq);
 
     pa_memblockq_free(bq);
     pa_memblock_unref(silence);
@@ -149,5 +158,7 @@ int main(int argc, char *argv[]) {
     pa_memblock_unref(chunk3.memblock);
     pa_memblock_unref(chunk4.memblock);
 
+    pa_mempool_free(p);
+
     return 0;
 }

commit d6bd152b4d5072f8af22644b7e2cdfa427a7fb86
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sat Mar 15 15:21:41 2008 +0000

    commit glitch-free work
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2124 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/alsa-util.c b/src/modules/alsa-util.c
index 6afec3b..d899eae 100644
--- a/src/modules/alsa-util.c
+++ b/src/modules/alsa-util.c
@@ -27,6 +27,7 @@
 #endif
 
 #include <sys/types.h>
+#include <limits.h>
 #include <asoundlib.h>
 
 #include <pulse/sample.h>
@@ -290,16 +291,22 @@ int pa_alsa_set_hw_params(
         pa_sample_spec *ss,
         uint32_t *periods,
         snd_pcm_uframes_t *period_size,
+        snd_pcm_uframes_t tsched_size,
         pa_bool_t *use_mmap,
+        pa_bool_t *use_tsched,
         pa_bool_t require_exact_channel_number) {
 
     int ret = -1;
+    snd_pcm_uframes_t _period_size = *period_size;
+    unsigned int _periods = *periods;
     snd_pcm_uframes_t buffer_size;
     unsigned int r = ss->rate;
     unsigned int c = ss->channels;
     pa_sample_format_t f = ss->format;
     snd_pcm_hw_params_t *hwparams;
     pa_bool_t _use_mmap = use_mmap && *use_mmap;
+    pa_bool_t _use_tsched = use_tsched && *use_tsched;
+    int dir;
 
     pa_assert(pcm_handle);
     pa_assert(ss);
@@ -308,8 +315,6 @@ int pa_alsa_set_hw_params(
 
     snd_pcm_hw_params_alloca(&hwparams);
 
-    buffer_size = *periods * *period_size;
-
     if ((ret = snd_pcm_hw_params_any(pcm_handle, hwparams)) < 0)
         goto finish;
 
@@ -330,12 +335,19 @@ int pa_alsa_set_hw_params(
     } else if ((ret = snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0)
         goto finish;
 
+    if (!_use_mmap)
+        _use_tsched = FALSE;
+
     if ((ret = set_format(pcm_handle, hwparams, &f)) < 0)
         goto finish;
 
     if ((ret = snd_pcm_hw_params_set_rate_near(pcm_handle, hwparams, &r, NULL)) < 0)
         goto finish;
 
+    /* Adjust the buffer sizes, if we didn't get the rate we were asking for */
+    _period_size = (snd_pcm_uframes_t) (((uint64_t) _period_size * r) / ss->rate);
+    tsched_size = (snd_pcm_uframes_t) (((uint64_t) tsched_size * r) / ss->rate);
+
     if (require_exact_channel_number) {
         if ((ret = snd_pcm_hw_params_set_channels(pcm_handle, hwparams, c)) < 0)
             goto finish;
@@ -344,10 +356,32 @@ int pa_alsa_set_hw_params(
             goto finish;
     }
 
-    if ((*period_size > 0 && (ret = snd_pcm_hw_params_set_period_size_near(pcm_handle, hwparams, period_size, NULL)) < 0) ||
-        (*periods > 0 && (ret = snd_pcm_hw_params_set_buffer_size_near(pcm_handle, hwparams, &buffer_size)) < 0))
+    if (_use_tsched) {
+        _period_size = tsched_size;
+        _periods = 1;
+
+        pa_assert_se(snd_pcm_hw_params_get_buffer_size_max(hwparams, &buffer_size) == 0);
+        pa_log_debug("Maximum hw buffer size is %u ms", (unsigned) buffer_size * 1000 / r);
+    }
+
+    buffer_size = _periods * _period_size;
+
+    if ((ret = snd_pcm_hw_params_set_periods_integer(pcm_handle, hwparams)) < 0)
         goto finish;
 
+    if (_periods > 0) {
+        dir = 1;
+        if ((ret = snd_pcm_hw_params_set_periods_near(pcm_handle, hwparams, &_periods, &dir)) < 0) {
+            dir = -1;
+            if ((ret = snd_pcm_hw_params_set_periods_near(pcm_handle, hwparams, &_periods, &dir)) < 0)
+                goto finish;
+        }
+    }
+
+    if (_period_size > 0)
+        if ((ret = snd_pcm_hw_params_set_buffer_size_near(pcm_handle, hwparams, &buffer_size)) < 0)
+            goto finish;
+
     if  ((ret = snd_pcm_hw_params(pcm_handle, hwparams)) < 0)
         goto finish;
 
@@ -363,8 +397,8 @@ int pa_alsa_set_hw_params(
     if ((ret = snd_pcm_prepare(pcm_handle)) < 0)
         goto finish;
 
-    if ((ret = snd_pcm_hw_params_get_buffer_size(hwparams, &buffer_size)) < 0 ||
-        (ret = snd_pcm_hw_params_get_period_size(hwparams, period_size, NULL)) < 0)
+    if ((ret = snd_pcm_hw_params_get_period_size(hwparams, &_period_size, &dir)) < 0 ||
+        (ret = snd_pcm_hw_params_get_periods(hwparams, &_periods, &dir)) < 0)
         goto finish;
 
     /* If the sample rate deviates too much, we need to resample */
@@ -373,14 +407,18 @@ int pa_alsa_set_hw_params(
     ss->channels = c;
     ss->format = f;
 
-    pa_assert(buffer_size > 0);
-    pa_assert(*period_size > 0);
-    *periods = buffer_size / *period_size;
-    pa_assert(*periods > 0);
+    pa_assert(_periods > 0);
+    pa_assert(_period_size > 0);
+
+    *periods = _periods;
+    *period_size = _period_size;
 
     if (use_mmap)
         *use_mmap = _use_mmap;
 
+    if (use_tsched)
+        *use_tsched = _use_tsched;
+
     ret = 0;
 
 finish:
@@ -388,7 +426,7 @@ finish:
     return ret;
 }
 
-int pa_alsa_set_sw_params(snd_pcm_t *pcm) {
+int pa_alsa_set_sw_params(snd_pcm_t *pcm, size_t avail_min) {
     snd_pcm_sw_params_t *swparams;
     int err;
 
@@ -411,6 +449,11 @@ int pa_alsa_set_sw_params(snd_pcm_t *pcm) {
         return err;
     }
 
+    if ((err = snd_pcm_sw_params_set_avail_min(pcm, swparams, avail_min)) < 0) {
+        pa_log_error("snd_pcm_sw_params_set_avail_min() failed: %s", 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;
@@ -477,7 +520,9 @@ snd_pcm_t *pa_alsa_open_by_device_id(
         int mode,
         uint32_t *nfrags,
         snd_pcm_uframes_t *period_size,
-        pa_bool_t *use_mmap) {
+        snd_pcm_uframes_t tsched_size,
+        pa_bool_t *use_mmap,
+        pa_bool_t *use_tsched) {
 
     int i;
     int direction = 1;
@@ -536,7 +581,7 @@ snd_pcm_t *pa_alsa_open_by_device_id(
         try_ss.rate = ss->rate;
         try_ss.format = ss->format;
 
-        if ((err = pa_alsa_set_hw_params(pcm_handle, &try_ss, nfrags, period_size, use_mmap, TRUE)) < 0) {
+        if ((err = pa_alsa_set_hw_params(pcm_handle, &try_ss, nfrags, period_size, tsched_size, use_mmap, use_tsched, TRUE)) < 0) {
             pa_log_info("PCM device %s refused our hw parameters: %s", d, snd_strerror(err));
             pa_xfree(d);
             snd_pcm_close(pcm_handle);
@@ -554,7 +599,7 @@ snd_pcm_t *pa_alsa_open_by_device_id(
 
     d = pa_sprintf_malloc("hw:%s", dev_id);
     pa_log_debug("Trying %s as last resort...", d);
-    pcm_handle = pa_alsa_open_by_device_string(d, dev, ss, map, mode, nfrags, period_size, use_mmap);
+    pcm_handle = pa_alsa_open_by_device_string(d, dev, ss, map, mode, nfrags, period_size, tsched_size, use_mmap, use_tsched);
     pa_xfree(d);
 
     return pcm_handle;
@@ -568,7 +613,9 @@ snd_pcm_t *pa_alsa_open_by_device_string(
         int mode,
         uint32_t *nfrags,
         snd_pcm_uframes_t *period_size,
-        pa_bool_t *use_mmap) {
+        snd_pcm_uframes_t tsched_size,
+        pa_bool_t *use_mmap,
+        pa_bool_t *use_tsched) {
 
     int err;
     char *d;
@@ -591,7 +638,7 @@ snd_pcm_t *pa_alsa_open_by_device_string(
             return NULL;
         }
 
-        if ((err = pa_alsa_set_hw_params(pcm_handle, ss, nfrags, period_size, use_mmap, FALSE)) < 0) {
+        if ((err = pa_alsa_set_hw_params(pcm_handle, ss, nfrags, period_size, tsched_size, use_mmap, use_tsched, FALSE)) < 0) {
 
             if (err == -EPERM) {
                 /* Hmm, some hw is very exotic, so we retry with plug, if without it didn't work */
@@ -773,7 +820,7 @@ int pa_alsa_calc_mixer_map(snd_mixer_elem_t *elem, const pa_channel_map *channel
         }
 
         if ((is_mono && mono_used) || (!is_mono && alsa_channel_used[id])) {
-            pa_log_info("Channel map has duplicate channel '%s', failling back to software volume control.", pa_channel_position_to_string(channel_map->map[i]));
+            pa_log_info("Channel map has duplicate channel '%s', falling back to software volume control.", pa_channel_position_to_string(channel_map->map[i]));
             return -1;
         }
 
@@ -793,7 +840,57 @@ int pa_alsa_calc_mixer_map(snd_mixer_elem_t *elem, const pa_channel_map *channel
         }
     }
 
-    pa_log_info("All %u channels can be mapped to mixer channels. Using hardware volume control.", channel_map->channels);
+    pa_log_info("All %u channels can be mapped to mixer channels.", channel_map->channels);
 
     return 0;
 }
+
+void pa_alsa_0dB_playback(snd_mixer_elem_t *elem) {
+    long min, max, v;
+
+    pa_assert(elem);
+
+    /* Try to enable 0 dB if possible. If ALSA cannot do dB, then use
+     * raw volume levels and fix them to 75% */
+
+    if (snd_mixer_selem_set_playback_dB_all(elem, 0, -1) >= 0)
+        return;
+
+    if (snd_mixer_selem_set_playback_dB_all(elem, 0, 1) >= 0)
+        return;
+
+    if (snd_mixer_selem_get_playback_volume_range(elem, &min, &max) < 0)
+        return;
+
+    v = min + ((max - min) * 3) / 4; /* 75% */
+
+    if (v <= min)
+        v = max;
+
+    snd_mixer_selem_set_playback_volume_all(elem, v);
+}
+
+void pa_alsa_0dB_capture(snd_mixer_elem_t *elem) {
+    long min, max, v;
+
+    pa_assert(elem);
+
+    /* Try to enable 0 dB if possible. If ALSA cannot do dB, then use
+     * raw volume levels and fix them to 75% */
+
+    if (snd_mixer_selem_set_capture_dB_all(elem, 0, -1) >= 0)
+        return;
+
+    if (snd_mixer_selem_set_capture_dB_all(elem, 0, 1) >= 0)
+        return;
+
+    if (snd_mixer_selem_get_capture_volume_range(elem, &min, &max) < 0)
+        return;
+
+    v = min + ((max - min) * 3) / 4; /* 75% */
+
+    if (v <= min)
+        v = max;
+
+    snd_mixer_selem_set_capture_volume_all(elem, v);
+}
diff --git a/src/modules/module-alsa-sink.c b/src/modules/module-alsa-sink.c
index 14aef7c..7e60cea 100644
--- a/src/modules/module-alsa-sink.c
+++ b/src/modules/module-alsa-sink.c
@@ -32,6 +32,7 @@
 
 #include <pulse/xmalloc.h>
 #include <pulse/util.h>
+#include <pulse/timeval.h>
 
 #include <pulsecore/core.h>
 #include <pulsecore/module.h>
@@ -46,6 +47,8 @@
 #include <pulsecore/core-error.h>
 #include <pulsecore/thread-mq.h>
 #include <pulsecore/rtpoll.h>
+#include <pulsecore/rtclock.h>
+#include <pulsecore/time-smoother.h>
 
 #include "alsa-util.h"
 #include "module-alsa-sink-symdef.h"
@@ -59,14 +62,19 @@ PA_MODULE_USAGE(
         "device=<ALSA device> "
         "device_id=<ALSA device id> "
         "format=<sample format> "
-        "channels=<number of channels> "
         "rate=<sample rate> "
+        "channels=<number of channels> "
+        "channel_map=<channel map> "
         "fragments=<number of fragments> "
         "fragment_size=<fragment size> "
-        "channel_map=<channel map> "
-        "mmap=<enable memory mapping?>");
+        "mmap=<enable memory mapping?> "
+        "tsched=<enable system timer based scheduling mode?> "
+        "tsched_buffer_size=<buffer size when using timer based scheduling> "
+        "tsched_buffer_watermark=<lower fill watermark>");
 
 #define DEFAULT_DEVICE "default"
+#define DEFAULT_TSCHED_BUFFER_USEC (3*PA_USEC_PER_SEC)
+#define DEFAULT_TSCHED_WATERMARK_USEC (20*PA_USEC_PER_MSEC)
 
 struct userdata {
     pa_core *core;
@@ -83,33 +91,43 @@ struct userdata {
     snd_mixer_t *mixer_handle;
     snd_mixer_elem_t *mixer_elem;
     long hw_volume_max, hw_volume_min;
+    long hw_dB_max, hw_dB_min;
+    pa_bool_t hw_dB_supported;
 
-    size_t frame_size, fragment_size, hwbuf_size;
+    size_t frame_size, fragment_size, hwbuf_size, tsched_watermark;
     unsigned nfragments;
     pa_memchunk memchunk;
 
     char *device_name;
 
-    pa_bool_t use_mmap;
+    pa_bool_t use_mmap, use_tsched;
 
     pa_bool_t first;
 
     pa_rtpoll_item *alsa_rtpoll_item;
 
     snd_mixer_selem_channel_id_t mixer_map[SND_MIXER_SCHN_LAST];
+
+    pa_smoother *smoother;
+    int64_t frame_index;
+
+    snd_pcm_sframes_t hwbuf_unused_frames;
 };
 
 static const char* const valid_modargs[] = {
+    "sink_name",
     "device",
     "device_id",
-    "sink_name",
     "format",
-    "channels",
     "rate",
+    "channels",
+    "channel_map",
     "fragments",
     "fragment_size",
-    "channel_map",
     "mmap",
+    "tsched",
+    "tsched_buffer_size",
+    "tsched_buffer_watermark",
     NULL
 };
 
@@ -127,7 +145,12 @@ static int mmap_write(struct userdata *u) {
         const snd_pcm_channel_area_t *areas;
         snd_pcm_uframes_t offset, frames;
 
-        if ((n = snd_pcm_avail_update(u->pcm_handle)) < 0) {
+        /* First we determine how many samples are missing to fill the
+         * buffer up to 100% */
+
+        if (PA_UNLIKELY((n = snd_pcm_avail_update(u->pcm_handle)) < 0)) {
+
+            pa_log_debug("snd_pcm_avail_update: %s", snd_strerror(n));
 
             if (n == -EPIPE) {
                 pa_log_debug("snd_pcm_avail_update: Buffer underrun!");
@@ -144,14 +167,17 @@ static int mmap_write(struct userdata *u) {
             return -1;
         }
 
-/*         pa_log("Got request for %i samples", (int) n); */
+        /* We only use part of the buffer that matches our
+         * dynamically requested latency */
 
-        if (n <= 0)
+        if (PA_UNLIKELY(n <= u->hwbuf_unused_frames))
             return work_done;
 
-        frames = n;
+        frames = n = n - u->hwbuf_unused_frames;
+
+        if (PA_UNLIKELY((err = snd_pcm_mmap_begin(u->pcm_handle, &areas, &offset, &frames)) < 0)) {
 
-        if ((err = snd_pcm_mmap_begin(u->pcm_handle, &areas, &offset, &frames)) < 0) {
+            pa_log_debug("snd_pcm_mmap_begin: %s", snd_strerror(err));
 
             if (err == -EPIPE) {
                 pa_log_debug("snd_pcm_mmap_begin: Buffer underrun!");
@@ -188,7 +214,9 @@ static int mmap_write(struct userdata *u) {
          * a little bit longer around? */
         pa_memblock_unref_fixed(chunk.memblock);
 
-        if ((err = snd_pcm_mmap_commit(u->pcm_handle, offset, frames)) < 0) {
+        if (PA_UNLIKELY((err = snd_pcm_mmap_commit(u->pcm_handle, offset, frames)) < 0)) {
+
+            pa_log_debug("snd_pcm_mmap_commit: %s", snd_strerror(err));
 
             if (err == -EPIPE) {
                 pa_log_debug("snd_pcm_mmap_commit: Buffer underrun!");
@@ -207,10 +235,12 @@ static int mmap_write(struct userdata *u) {
 
         work_done = 1;
 
-        if (frames >= (snd_pcm_uframes_t) n)
-            return work_done;
+        u->frame_index += frames;
 
-/*         pa_log("wrote %i samples", (int) frames); */
+        pa_log_debug("wrote %llu frames", (unsigned long long) frames);
+
+        if (PA_LIKELY(frames >= (snd_pcm_uframes_t) n))
+            return work_done;
     }
 }
 
@@ -225,54 +255,60 @@ static int unix_write(struct userdata *u) {
 
     for (;;) {
         void *p;
-        snd_pcm_sframes_t t;
-        ssize_t l;
+        snd_pcm_sframes_t n, frames;
         int err;
 
-        if ((err = snd_pcm_status(u->pcm_handle, status)) < 0) {
+        if (PA_UNLIKELY((err = snd_pcm_status(u->pcm_handle, status)) < 0)) {
             pa_log("Failed to query DSP status data: %s", snd_strerror(err));
             return -1;
         }
 
-        if (snd_pcm_status_get_avail_max(status)*u->frame_size >= u->hwbuf_size)
+        if (PA_UNLIKELY(snd_pcm_status_get_avail_max(status)*u->frame_size >= u->hwbuf_size))
             pa_log_debug("Buffer underrun!");
 
-        l = snd_pcm_status_get_avail(status) * u->frame_size;
+        n = snd_pcm_status_get_avail(status);
 
-/*         pa_log("%u bytes to write", l); */
+        /* We only use part of the buffer that matches our
+         * dynamically requested latency */
 
-        if (l <= 0)
+        if (PA_UNLIKELY(n <= u->hwbuf_unused_frames))
             return work_done;
 
+        n -= u->hwbuf_unused_frames;
+
         if (u->memchunk.length <= 0)
-            pa_sink_render(u->sink, l, &u->memchunk);
+            pa_sink_render(u->sink, n * u->frame_size, &u->memchunk);
 
         pa_assert(u->memchunk.length > 0);
 
+        frames = u->memchunk.length / u->frame_size;
+
+        if (frames > n)
+            frames = n;
+
         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);
+        frames = snd_pcm_writei(u->pcm_handle, (const uint8_t*) p + u->memchunk.index, frames);
         pa_memblock_release(u->memchunk.memblock);
 
-/*         pa_log("wrote %i bytes of %u (%u)", t*u->frame_size, u->memchunk.length, l); */
+        pa_assert(frames != 0);
 
-        pa_assert(t != 0);
+        if (PA_UNLIKELY(frames < 0)) {
 
-        if (t < 0) {
+            if (frames == -EPIPE)
+                pa_log_debug("snd_pcm_avail_update: Buffer underrun!");
 
-            if ((t = snd_pcm_recover(u->pcm_handle, t, 1)) == 0)
+            if ((frames = snd_pcm_recover(u->pcm_handle, frames, 1)) == 0)
                 continue;
 
-            if (t == -EAGAIN) {
-                pa_log_debug("EAGAIN");
+            if (frames == -EAGAIN)
                 return work_done;
-            } else {
-                pa_log("Failed to write data to DSP: %s", snd_strerror(t));
-                return -1;
-            }
+
+            pa_log("Failed to write data to DSP: %s", snd_strerror(frames));
+            return -1;
         }
 
-        u->memchunk.index += t * u->frame_size;
-        u->memchunk.length -= t * u->frame_size;
+        u->memchunk.index += frames * u->frame_size;
+        u->memchunk.length -= frames * u->frame_size;
 
         if (u->memchunk.length <= 0) {
             pa_memblock_unref(u->memchunk.memblock);
@@ -281,29 +317,51 @@ static int unix_write(struct userdata *u) {
 
         work_done = 1;
 
-        if (t * u->frame_size >= (unsigned) l)
+        u->frame_index += frames;
+
+        if (PA_LIKELY(frames >= n))
             return work_done;
     }
 }
 
-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;
+static int update_smoother(struct userdata *u) {
+    snd_pcm_sframes_t delay;
+    int64_t frames;
     int err;
-
-    snd_pcm_status_alloca(&status);
+    pa_usec_t now1, now2;
 
     pa_assert(u);
     pa_assert(u->pcm_handle);
 
-    if ((err = snd_pcm_status(u->pcm_handle, status)) < 0)
+    /* Let's update the time smoother */
+    snd_pcm_avail_update(u->pcm_handle);
+
+    if (PA_UNLIKELY((err = snd_pcm_delay(u->pcm_handle, &delay)) < 0)) {
         pa_log("Failed to get delay: %s", snd_strerror(err));
-    else
-        frames = snd_pcm_status_get_delay(status);
+        return -1;
+    }
+
+    frames = u->frame_index - delay;
+
+    pa_log_debug("frame_index = %llu, delay = %llu, p = %llu", (unsigned long long) u->frame_index, (unsigned long long) delay, (unsigned long long) frames);
 
-    if (frames > 0)
-        r = pa_bytes_to_usec(frames * u->frame_size, &u->sink->sample_spec);
+    now1 = pa_rtclock_usec();
+    now2 = pa_bytes_to_usec(frames * u->frame_size, &u->sink->sample_spec);
+    pa_smoother_put(u->smoother, now1, now2);
+
+    return 0;
+}
+
+static pa_usec_t sink_get_latency(struct userdata *u) {
+    pa_usec_t r = 0;
+    int64_t delay;
+
+    pa_assert(u);
+
+    delay = u->frame_index - pa_smoother_get(u->smoother, pa_rtclock_usec());
+
+    if (delay > 0)
+        r = pa_bytes_to_usec(delay * u->frame_size, &u->sink->sample_spec);
 
     if (u->memchunk.memblock)
         r += pa_bytes_to_usec(u->memchunk.length, &u->sink->sample_spec);
@@ -342,6 +400,8 @@ static int suspend(struct userdata *u) {
     pa_assert(u);
     pa_assert(u->pcm_handle);
 
+    pa_smoother_pause(u->smoother, pa_rtclock_usec());
+
     /* Let's suspend */
     snd_pcm_drain(u->pcm_handle);
     snd_pcm_close(u->pcm_handle);
@@ -357,10 +417,61 @@ static int suspend(struct userdata *u) {
     return 0;
 }
 
+static pa_usec_t hw_sleep_time(struct userdata *u) {
+    pa_usec_t usec, wm;
+
+    pa_assert(u);
+
+    usec = pa_sink_get_requested_latency(u->sink);
+
+    if (usec <= 0)
+        usec = pa_bytes_to_usec(u->hwbuf_size, &u->sink->sample_spec);
+
+    pa_log_debug("hw buffer time: %u ms", (unsigned) (usec / PA_USEC_PER_MSEC));
+
+    wm = pa_bytes_to_usec(u->tsched_watermark, &u->sink->sample_spec);
+
+    if (usec >= wm)
+        usec -= wm;
+    else
+        usec /= 2;
+
+    pa_log_debug("after watermark: %u ms", (unsigned) (usec / PA_USEC_PER_MSEC));
+
+    return usec;
+}
+
+static int update_sw_params(struct userdata *u) {
+    size_t avail_min;
+    int err;
+
+    pa_assert(u);
+
+    if (u->use_tsched) {
+        pa_usec_t usec;
+
+        usec = hw_sleep_time(u);
+
+        avail_min = pa_usec_to_bytes(usec, &u->sink->sample_spec);
+
+        if (avail_min <= 0)
+            avail_min = 1;
+
+    } else
+        avail_min = 1;
+
+    if ((err = pa_alsa_set_sw_params(u->pcm_handle, avail_min)) < 0) {
+        pa_log("Failed to set software parameters: %s", snd_strerror(err));
+        return err;
+    }
+
+    return 0;
+}
+
 static int unsuspend(struct userdata *u) {
     pa_sample_spec ss;
     int err;
-    pa_bool_t b;
+    pa_bool_t b, d;
     unsigned nfrags;
     snd_pcm_uframes_t period_size;
 
@@ -379,13 +490,14 @@ static int unsuspend(struct userdata *u) {
     nfrags = u->nfragments;
     period_size = u->fragment_size / u->frame_size;
     b = u->use_mmap;
+    d = u->use_tsched;
 
-    if ((err = pa_alsa_set_hw_params(u->pcm_handle, &ss, &nfrags, &period_size, &b, TRUE)) < 0) {
+    if ((err = pa_alsa_set_hw_params(u->pcm_handle, &ss, &nfrags, &period_size, u->hwbuf_size / u->frame_size, &b, &d, TRUE)) < 0) {
         pa_log("Failed to set hardware parameters: %s", snd_strerror(err));
         goto fail;
     }
 
-    if (b != u->use_mmap) {
+    if (b != u->use_mmap || d != u->use_tsched) {
         pa_log_warn("Resume failed, couldn't get original access mode.");
         goto fail;
     }
@@ -400,10 +512,8 @@ static int unsuspend(struct userdata *u) {
         goto fail;
     }
 
-    if ((err = pa_alsa_set_sw_params(u->pcm_handle)) < 0) {
-        pa_log("Failed to set software parameters: %s", snd_strerror(err));
+    if (update_sw_params(u) < 0)
         goto fail;
-    }
 
     if (build_pollfd(u) < 0)
         goto fail;
@@ -425,6 +535,29 @@ fail:
     return -1;
 }
 
+static void update_hwbuf_unused_frames(struct userdata *u) {
+    pa_usec_t usec;
+    size_t b;
+
+    pa_assert(u);
+
+    if ((usec = pa_sink_get_requested_latency(u->sink)) <= 0) {
+        /* Use the full buffer if noone asked us for anything
+         * specific */
+        u->hwbuf_unused_frames = 0;
+        return;
+    }
+
+    b = pa_usec_to_bytes(usec, &u->sink->sample_spec);
+
+    /* We need at least one sample in our buffer */
+
+    if (PA_UNLIKELY(b < u->frame_size))
+        b = u->frame_size;
+
+    u->hwbuf_unused_frames = PA_LIKELY(b < u->hwbuf_size) ? ((u->hwbuf_size - b) / u->frame_size) : 0;
+}
+
 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;
 
@@ -474,6 +607,14 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
             }
 
             break;
+
+        case PA_SINK_MESSAGE_ADD_INPUT:
+        case PA_SINK_MESSAGE_REMOVE_INPUT:
+        case PA_SINK_MESSAGE_REMOVE_INPUT_AND_BUFFER: {
+            int r = pa_sink_process_msg(o, code, data, offset, chunk);
+            update_hwbuf_unused_frames(u);
+            return r;
+        }
     }
 
     return pa_sink_process_msg(o, code, data, offset, chunk);
@@ -505,18 +646,24 @@ static int sink_get_volume_cb(pa_sink *s) {
     pa_assert(u->mixer_elem);
 
     for (i = 0; i < s->sample_spec.channels; i++) {
-        long set_vol, vol;
+        long alsa_vol;
 
         pa_assert(snd_mixer_selem_has_playback_channel(u->mixer_elem, u->mixer_map[i]));
 
-        if ((err = snd_mixer_selem_get_playback_volume(u->mixer_elem, u->mixer_map[i], &vol)) < 0)
-            goto fail;
+        if (u->hw_dB_supported) {
+
+            if ((err = snd_mixer_selem_get_playback_dB(u->mixer_elem, u->mixer_map[i], &alsa_vol)) >= 0) {
+                s->volume.values[i] = pa_sw_volume_from_dB(alsa_vol / 100.0);
+                continue;
+            }
+
+            u->hw_dB_supported = FALSE;
+        }
 
-        set_vol = (long) roundf(((float) s->volume.values[i] * (u->hw_volume_max - u->hw_volume_min)) / PA_VOLUME_NORM) + u->hw_volume_min;
+        if ((err = snd_mixer_selem_get_playback_volume(u->mixer_elem, u->mixer_map[i], &alsa_vol)) < 0)
+            goto fail;
 
-        /* Try to avoid superfluous volume changes */
-        if (set_vol != vol)
-            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));
+        s->volume.values[i] = (pa_volume_t) roundf(((float) (alsa_vol - u->hw_volume_min) * PA_VOLUME_NORM) / (u->hw_volume_max - u->hw_volume_min));
     }
 
     return 0;
@@ -524,8 +671,6 @@ static int sink_get_volume_cb(pa_sink *s) {
 fail:
     pa_log_error("Unable to read volume: %s", snd_strerror(err));
 
-    s->get_volume = NULL;
-    s->set_volume = NULL;
     return -1;
 }
 
@@ -543,15 +688,31 @@ static int sink_set_volume_cb(pa_sink *s) {
 
         pa_assert(snd_mixer_selem_has_playback_channel(u->mixer_elem, u->mixer_map[i]));
 
-        vol = s->volume.values[i];
+        vol = PA_MIN(s->volume.values[i], PA_VOLUME_NORM);
+
+        if (u->hw_dB_supported) {
+            alsa_vol = (long) (pa_sw_volume_to_dB(vol) * 100);
+            alsa_vol = PA_CLAMP_UNLIKELY(alsa_vol, u->hw_dB_min, u->hw_dB_max);
+
+            if ((err = snd_mixer_selem_set_playback_dB(u->mixer_elem, u->mixer_map[i], alsa_vol, -1)) >= 0) {
 
-        if (vol > PA_VOLUME_NORM)
-            vol = PA_VOLUME_NORM;
+                if (snd_mixer_selem_get_playback_dB(u->mixer_elem, u->mixer_map[i], &alsa_vol) >= 0)
+                    s->volume.values[i] = pa_sw_volume_from_dB(alsa_vol / 100.0);
+
+                continue;
+            }
+
+            u->hw_dB_supported = FALSE;
+        }
 
         alsa_vol = (long) roundf(((float) vol * (u->hw_volume_max - u->hw_volume_min)) / PA_VOLUME_NORM) + u->hw_volume_min;
+        alsa_vol = PA_CLAMP_UNLIKELY(alsa_vol, u->hw_volume_min, u->hw_volume_max);
 
         if ((err = snd_mixer_selem_set_playback_volume(u->mixer_elem, u->mixer_map[i], alsa_vol)) < 0)
             goto fail;
+
+        if (snd_mixer_selem_get_playback_volume(u->mixer_elem, u->mixer_map[i], &alsa_vol) >= 0)
+            s->volume.values[i] = (pa_volume_t) roundf(((float) (alsa_vol - u->hw_volume_min) * PA_VOLUME_NORM) / (u->hw_volume_max - u->hw_volume_min));
     }
 
     return 0;
@@ -559,8 +720,6 @@ static int sink_set_volume_cb(pa_sink *s) {
 fail:
     pa_log_error("Unable to set volume: %s", snd_strerror(err));
 
-    s->get_volume = NULL;
-    s->set_volume = NULL;
     return -1;
 }
 
@@ -573,9 +732,6 @@ static int sink_get_mute_cb(pa_sink *s) {
 
     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_mute = NULL;
-        s->set_mute = NULL;
         return -1;
     }
 
@@ -593,15 +749,20 @@ static int sink_set_mute_cb(pa_sink *s) {
 
     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_mute = NULL;
-        s->set_mute = NULL;
         return -1;
     }
 
     return 0;
 }
 
+static void sink_update_requested_latency_cb(pa_sink *s) {
+    struct userdata *u = s->userdata;
+
+    pa_assert(u);
+
+    update_sw_params(u);
+}
+
 static void thread_func(void *userdata) {
     struct userdata *u = userdata;
 
@@ -615,13 +776,50 @@ static void thread_func(void *userdata) {
     pa_thread_mq_install(&u->thread_mq);
     pa_rtpoll_install(u->rtpoll);
 
+    update_hwbuf_unused_frames(u);
+
     for (;;) {
         int ret;
 
+        pa_log_debug("loop");
+
         /* Render some data and write it to the dsp */
         if (PA_SINK_OPENED(u->sink->thread_info.state)) {
             int work_done = 0;
 
+            if (u->sink->thread_info.rewind_nbytes > 0 && u->use_tsched) {
+                snd_pcm_sframes_t frames, limit, unused;
+
+                pa_log_debug("Requested to rewind %lu bytes.", (unsigned long) u->sink->thread_info.rewind_nbytes);
+
+                frames = u->sink->thread_info.rewind_nbytes / u->frame_size;
+
+                if ((unused = snd_pcm_avail_update(u->pcm_handle)) < 0) {
+                    pa_log("snd_pcm_avail_update() failed: %s", snd_strerror(unused));
+                    goto fail;
+                }
+
+                limit = (u->hwbuf_size / u->frame_size) - unused;
+
+                if (frames > limit)
+                    frames = limit;
+
+                pa_log_debug("Limited to %lu bytes.", (unsigned long) frames * u->frame_size);
+
+                if ((frames = snd_pcm_rewind(u->pcm_handle, frames)) < 0) {
+                    pa_log("snd_pcm_rewind() failed: %s", snd_strerror(frames));
+                    goto fail;
+                }
+
+                if ((u->sink->thread_info.rewind_nbytes = frames * u->frame_size) <= 0)
+                    pa_log_info("Tried rewind, but was apparently not possible.");
+                else {
+                    u->frame_index -= frames;
+                    pa_log_debug("Rewound %lu bytes.", (unsigned long) u->sink->thread_info.rewind_nbytes);
+                    pa_sink_process_rewind(u->sink);
+                }
+            }
+
             if (u->use_mmap) {
                 if ((work_done = mmap_write(u)) < 0)
                     goto fail;
@@ -630,12 +828,46 @@ static void thread_func(void *userdata) {
                     goto fail;
             }
 
-            if (work_done && u->first) {
-                pa_log_info("Starting playback.");
-                snd_pcm_start(u->pcm_handle);
-                u->first = FALSE;
-                continue;
+            pa_log_debug("work_done = %i", work_done);
+
+            if (work_done) {
+
+                if (u->first) {
+                    pa_log_info("Starting playback.");
+                    snd_pcm_start(u->pcm_handle);
+                    u->first = FALSE;
+
+                    pa_smoother_resume(u->smoother, pa_rtclock_usec());
+                }
+
+                if (update_smoother(u) < 0)
+                    goto fail;
             }
+
+            if (u->use_tsched) {
+                pa_usec_t usec, cusec;
+
+                /* OK, the playback buffer is now full, let's
+                 * calculate when to wake up next */
+
+                usec = hw_sleep_time(u);
+
+                pa_log_debug("Waking up in %0.2fms (sound card clock).", (double) usec / PA_USEC_PER_MSEC);
+
+                /* Convert from the sound card time domain to the
+                 * system time domain */
+                cusec = pa_smoother_translate(u->smoother, pa_rtclock_usec(), usec);
+
+                pa_log_debug("Waking up in %0.2fms (system clock).", (double) cusec / PA_USEC_PER_MSEC);
+
+                /* We don't trust the conversion, so we wake up whatever comes first */
+                pa_rtpoll_set_timer_relative(u->rtpoll, PA_MIN(usec, cusec));
+            }
+
+        } else if (u->use_tsched) {
+
+            /* OK, we're in an invalid state, let's disable our timers */
+            pa_rtpoll_set_timer_disabled(u->rtpoll);
         }
 
         /* Hmm, nothing to do. Let's sleep */
@@ -697,6 +929,8 @@ static void thread_func(void *userdata) {
                         break;
                 }
             }
+
+            pa_log_debug("alsa revents = %i", revents);
         }
     }
 
@@ -717,16 +951,23 @@ int pa__init(pa_module*m) {
     const char *dev_id;
     pa_sample_spec ss;
     pa_channel_map map;
-    uint32_t nfrags, frag_size;
-    snd_pcm_uframes_t period_size;
+    uint32_t nfrags, hwbuf_size, frag_size, tsched_size, tsched_watermark;
+    snd_pcm_uframes_t period_frames, tsched_frames;
     size_t frame_size;
     snd_pcm_info_t *pcm_info = NULL;
     int err;
-    char *t;
     const char *name;
     char *name_buf = NULL;
-    int namereg_fail;
-    pa_bool_t use_mmap = TRUE, b;
+    pa_bool_t namereg_fail;
+    pa_bool_t use_mmap = TRUE, b, use_tsched = TRUE, d;
+    pa_usec_t usec;
+    pa_sink_new_data data;
+    static const char * const class_table[SND_PCM_CLASS_LAST+1] = {
+        [SND_PCM_CLASS_GENERIC] = "sound",
+        [SND_PCM_CLASS_MULTI] = NULL,
+        [SND_PCM_CLASS_MODEM] = "modem",
+        [SND_PCM_CLASS_DIGITIZER] = NULL
+    };
 
     snd_pcm_info_alloca(&pcm_info);
 
@@ -746,35 +987,60 @@ int pa__init(pa_module*m) {
     frame_size = pa_frame_size(&ss);
 
     nfrags = m->core->default_n_fragments;
-    frag_size = pa_usec_to_bytes(m->core->default_fragment_size_msec*1000, &ss);
+    frag_size = pa_usec_to_bytes(m->core->default_fragment_size_msec*PA_USEC_PER_MSEC, &ss);
     if (frag_size <= 0)
         frag_size = frame_size;
+    tsched_size = pa_usec_to_bytes(DEFAULT_TSCHED_BUFFER_USEC, &ss);
+    tsched_watermark = pa_usec_to_bytes(DEFAULT_TSCHED_WATERMARK_USEC, &ss);
 
-    if (pa_modargs_get_value_u32(ma, "fragments", &nfrags) < 0 || pa_modargs_get_value_u32(ma, "fragment_size", &frag_size) < 0) {
+    if (pa_modargs_get_value_u32(ma, "fragments", &nfrags) < 0 ||
+        pa_modargs_get_value_u32(ma, "fragment_size", &frag_size) < 0 ||
+        pa_modargs_get_value_u32(ma, "tsched_buffer_size", &tsched_size) < 0 ||
+        pa_modargs_get_value_u32(ma, "tsched_buffer_watermark", &tsched_watermark) < 0) {
         pa_log("Failed to parse buffer metrics");
         goto fail;
     }
-    period_size = frag_size/frame_size;
+
+    hwbuf_size = frag_size * nfrags;
+    period_frames = frag_size/frame_size;
+    tsched_frames = tsched_size/frame_size;
 
     if (pa_modargs_get_value_boolean(ma, "mmap", &use_mmap) < 0) {
         pa_log("Failed to parse mmap argument.");
         goto fail;
     }
 
+    if (pa_modargs_get_value_boolean(ma, "tsched", &use_tsched) < 0) {
+        pa_log("Failed to parse timer_scheduling argument.");
+        goto fail;
+    }
+
+    if (use_tsched && !pa_rtclock_hrtimer()) {
+        pa_log("Disabling timer-based scheduling because high-resolution timers are not available from the kernel.");
+        use_tsched = FALSE;
+    }
+
     u = pa_xnew0(struct userdata, 1);
     u->core = m->core;
     u->module = m;
     m->userdata = u;
     u->use_mmap = use_mmap;
+    u->use_tsched = use_tsched;
     u->first = TRUE;
     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);
 
+    u->smoother = pa_smoother_new(DEFAULT_TSCHED_BUFFER_USEC*2, DEFAULT_TSCHED_BUFFER_USEC*2, TRUE);
+    usec = pa_rtclock_usec();
+    pa_smoother_set_time_offset(u->smoother, usec);
+    pa_smoother_pause(u->smoother, usec);
+
     snd_config_update_free_global();
 
     b = use_mmap;
+    d = use_tsched;
 
     if ((dev_id = pa_modargs_get_value(ma, "device_id", NULL))) {
 
@@ -783,8 +1049,8 @@ int pa__init(pa_module*m) {
                       &u->device_name,
                       &ss, &map,
                       SND_PCM_STREAM_PLAYBACK,
-                      &nfrags, &period_size,
-                      &b)))
+                      &nfrags, &period_frames, tsched_frames,
+                      &b, &d)))
 
             goto fail;
 
@@ -795,8 +1061,8 @@ int pa__init(pa_module*m) {
                       &u->device_name,
                       &ss, &map,
                       SND_PCM_STREAM_PLAYBACK,
-                      &nfrags, &period_size,
-                      &b)))
+                      &nfrags, &period_frames, tsched_frames,
+                      &b, &d)))
             goto fail;
 
     }
@@ -806,22 +1072,25 @@ int pa__init(pa_module*m) {
 
     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;
+        u->use_mmap = use_mmap = FALSE;
+    }
+
+    if (use_tsched && (!b || !d)) {
+        pa_log_info("Cannot enabled timer-based scheduling, falling back to sound IRQ scheduling.");
+        u->use_tsched = use_tsched = FALSE;
     }
 
     if (u->use_mmap)
         pa_log_info("Successfully enabled mmap() mode.");
 
+    if (u->use_tsched)
+        pa_log_info("Successfully enabled timer-based scheduling 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_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);
 
@@ -853,13 +1122,31 @@ int pa__init(pa_module*m) {
     }
 
     if ((name = pa_modargs_get_value(ma, "sink_name", NULL)))
-        namereg_fail = 1;
+        namereg_fail = TRUE;
     else {
         name = name_buf = pa_sprintf_malloc("alsa_output.%s", u->device_name);
-        namereg_fail = 0;
+        namereg_fail = FALSE;
     }
 
-    u->sink = pa_sink_new(m->core, __FILE__, name, namereg_fail, &ss, &map);
+    pa_sink_new_data_init(&data);
+    data.driver = __FILE__;
+    data.module = m;
+    pa_sink_new_data_set_name(&data, name);
+    data.namereg_fail = namereg_fail;
+    pa_sink_new_data_set_sample_spec(&data, &ss);
+    pa_sink_new_data_set_channel_map(&data, &map);
+
+    pa_proplist_sets(data.proplist, PA_PROP_DEVICE_STRING, u->device_name);
+    pa_proplist_sets(data.proplist, PA_PROP_DEVICE_API, "alsa");
+    pa_proplist_sets(data.proplist, PA_PROP_DEVICE_DESCRIPTION, snd_pcm_info_get_name(pcm_info));
+
+    if (class_table[snd_pcm_info_get_class(pcm_info)])
+        pa_proplist_sets(data.proplist, PA_PROP_DEVICE_CLASS, class_table[snd_pcm_info_get_class(pcm_info)]);
+
+    pa_proplist_sets(data.proplist, PA_PROP_DEVICE_ACCESS_MODE, u->use_tsched ? "mmap_rewrite" : (u->use_mmap ? "mmap" : "serial"));
+
+    u->sink = pa_sink_new(m->core, &data, PA_SINK_HARDWARE|PA_SINK_LATENCY);
+    pa_sink_new_data_done(&data);
     pa_xfree(name_buf);
 
     if (!u->sink) {
@@ -868,26 +1155,35 @@ int pa__init(pa_module*m) {
     }
 
     u->sink->parent.process_msg = sink_process_msg;
+    u->sink->update_requested_latency = sink_update_requested_latency_cb;
     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",
-                                    u->device_name,
-                                    snd_pcm_info_get_name(pcm_info),
-                                    use_mmap ? " via DMA" : ""));
-    pa_xfree(t);
-
-    u->sink->flags = PA_SINK_HARDWARE|PA_SINK_LATENCY;
 
     u->frame_size = frame_size;
-    u->fragment_size = frag_size = period_size * frame_size;
+    u->fragment_size = frag_size = period_frames * frame_size;
     u->nfragments = nfrags;
     u->hwbuf_size = u->fragment_size * nfrags;
+    u->hwbuf_unused_frames = 0;
+    u->tsched_watermark = tsched_watermark;
+    u->frame_index = 0;
+    u->hw_dB_supported = FALSE;
+    u->hw_dB_min = u->hw_dB_max = 0;
+    u->hw_volume_min = u->hw_volume_max = 0;
+
+    u->sink->thread_info.max_rewind = use_tsched ? u->hwbuf_size : 0;
+
+    pa_log_info("Using %u fragments of size %lu bytes, buffer time is %0.2fms",
+                nfrags, (long unsigned) u->fragment_size,
+                (double) pa_bytes_to_usec(u->hwbuf_size, &ss) / PA_USEC_PER_MSEC);
 
-    pa_log_info("Using %u fragments of size %lu bytes.", nfrags, (long unsigned) u->fragment_size);
+    if (use_tsched)
+        pa_log_info("Time scheduling watermark is %0.2fms",
+                    (double) pa_bytes_to_usec(u->tsched_watermark, &ss) / PA_USEC_PER_MSEC);
+
+    if (update_sw_params(u) < 0)
+        goto fail;
 
     pa_memchunk_reset(&u->memchunk);
 
@@ -895,17 +1191,71 @@ int pa__init(pa_module*m) {
         pa_assert(u->mixer_elem);
 
         if (snd_mixer_selem_has_playback_volume(u->mixer_elem))
-            if (pa_alsa_calc_mixer_map(u->mixer_elem, &map, u->mixer_map, TRUE) >= 0) {
-                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);
-                u->sink->flags |= PA_SINK_HW_VOLUME_CTRL;
+
+            if (pa_alsa_calc_mixer_map(u->mixer_elem, &map, u->mixer_map, TRUE) >= 0 &&
+                snd_mixer_selem_get_playback_volume_range(u->mixer_elem, &u->hw_volume_min, &u->hw_volume_max) >= 0) {
+
+                pa_bool_t suitable = TRUE;
+
+                pa_log_info("Volume ranges from %li to %li.", u->hw_volume_min, u->hw_volume_max);
+
+                if (u->hw_volume_min > u->hw_volume_max) {
+
+                    pa_log_info("Minimal volume %li larger than maximum volume %li. Strange stuff Falling back to software volume control.", u->hw_volume_min, u->hw_volume_max);
+                    suitable = FALSE;
+
+                } else if (u->hw_volume_max - u->hw_volume_min < 3) {
+
+                    pa_log_info("Device has less than 4 volume levels. Falling back to software volume control.");
+                    suitable = FALSE;
+
+                } else if (snd_mixer_selem_get_playback_dB_range(u->mixer_elem, &u->hw_dB_min, &u->hw_dB_max) >= 0) {
+
+                    pa_log_info("Volume ranges from %0.2f dB to %0.2f dB.", u->hw_dB_min/100.0, u->hw_dB_max/100.0);
+
+                    /* Let's see if this thing actually is useful for muting */
+                    if (u->hw_dB_min > -6000) {
+                        pa_log_info("Device cannot attenuate for more than -60 dB (only %0.2f dB supported), falling back to software volume control.", ((double) u->hw_dB_min) / 100);
+
+                        suitable = FALSE;
+                    } else if (u->hw_dB_max < 0) {
+
+                        pa_log_info("Device is still attenuated at maximum volume setting (%0.2f dB is maximum). Strange stuff. Falling back to software volume control.", ((double) u->hw_dB_max) / 100);
+                        suitable = FALSE;
+
+                    } else if (u->hw_dB_min >= u->hw_dB_max) {
+
+                        pa_log_info("Minimal dB (%0.2f) larger or equal to maximum dB (%0.2f). Strange stuff. Falling back to software volume control.", ((double) u->hw_dB_min) / 100, ((double) u->hw_dB_max) / 100);
+                        suitable = FALSE;
+
+                    } else {
+
+                        if (u->hw_dB_max > 0) {
+                            /* dB > 0 means overamplification, and clipping, we don't want that here */
+                            pa_log_info("Device can do overamplification for %0.2f dB. Limiting to 0 db", ((double) u->hw_dB_max) / 100);
+                            u->hw_dB_max = 0;
+                        }
+
+                        u->hw_dB_supported = TRUE;
+                    }
+                }
+
+                if (suitable) {
+                    u->sink->get_volume = sink_get_volume_cb;
+                    u->sink->set_volume = sink_set_volume_cb;
+                    u->sink->flags |= PA_SINK_HW_VOLUME_CTRL | (u->hw_dB_supported ? PA_SINK_DECIBEL_VOLUME : 0);
+                    pa_log_info("Using hardware volume control. %s dB scale.", u->hw_dB_supported ? "Using" : "Not using");
+
+                } else {
+                    pa_log_info("Using software volume control. Trying to reset sound card to 0 dB.");
+                    pa_alsa_0dB_playback(u->mixer_elem);
+                }
             }
 
         if (snd_mixer_selem_has_playback_switch(u->mixer_elem)) {
             u->sink->get_mute = sink_get_mute_cb;
             u->sink->set_mute = sink_set_mute_cb;
-            u->sink->flags |= PA_SINK_HW_VOLUME_CTRL;
+            u->sink->flags |= PA_SINK_HW_MUTE_CTRL;
         }
 
         u->mixer_fdl = pa_alsa_fdlist_new();
@@ -926,10 +1276,21 @@ int pa__init(pa_module*m) {
     }
 
     /* Get initial mixer settings */
-    if (u->sink->get_volume)
-        u->sink->get_volume(u->sink);
-    if (u->sink->get_mute)
-        u->sink->get_mute(u->sink);
+    if (data.volume_is_set) {
+        if (u->sink->set_volume)
+            u->sink->set_volume(u->sink);
+    } else {
+        if (u->sink->get_volume)
+            u->sink->get_volume(u->sink);
+    }
+
+    if (data.muted_is_set) {
+        if (u->sink->set_mute)
+            u->sink->set_mute(u->sink);
+    } else {
+        if (u->sink->get_mute)
+            u->sink->get_mute(u->sink);
+    }
 
     pa_sink_put(u->sink);
 
@@ -988,6 +1349,9 @@ void pa__done(pa_module*m) {
         snd_pcm_close(u->pcm_handle);
     }
 
+    if (u->smoother)
+        pa_smoother_free(u->smoother);
+
     pa_xfree(u->device_name);
     pa_xfree(u);
 
diff --git a/src/modules/module-alsa-source.c b/src/modules/module-alsa-source.c
index 23a2f92..b2d0d43 100644
--- a/src/modules/module-alsa-source.c
+++ b/src/modules/module-alsa-source.c
@@ -32,6 +32,7 @@
 
 #include <pulse/xmalloc.h>
 #include <pulse/util.h>
+#include <pulse/timeval.h>
 
 #include <pulsecore/core-error.h>
 #include <pulsecore/core.h>
@@ -47,6 +48,8 @@
 #include <pulsecore/core-error.h>
 #include <pulsecore/thread-mq.h>
 #include <pulsecore/rtpoll.h>
+#include <pulsecore/time-smoother.h>
+#include <pulsecore/rtclock.h>
 
 #include "alsa-util.h"
 #include "module-alsa-source-symdef.h"
@@ -60,14 +63,19 @@ PA_MODULE_USAGE(
         "device=<ALSA device> "
         "device_id=<ALSA device id> "
         "format=<sample format> "
-        "channels=<number of channels> "
         "rate=<sample rate> "
+        "channels=<number of channels> "
+        "channel_map=<channel map> "
         "fragments=<number of fragments> "
         "fragment_size=<fragment size> "
-        "channel_map=<channel map> "
-        "mmap=<enable memory mapping?>");
+        "mmap=<enable memory mapping?> "
+        "tsched=<enable system timer based scheduling mode?> "
+        "tsched_buffer_size=<buffer size when using timer based scheduling> "
+        "tsched_buffer_watermark=<upper fill watermark>");
 
 #define DEFAULT_DEVICE "default"
+#define DEFAULT_TSCHED_BUFFER_USEC (2*PA_USEC_PER_SEC)
+#define DEFAULT_TSCHED_WATERMARK_USEC (10*PA_USEC_PER_MSEC)
 
 struct userdata {
     pa_core *core;
@@ -85,29 +93,35 @@ struct userdata {
     snd_mixer_elem_t *mixer_elem;
     long hw_volume_max, hw_volume_min;
 
-    size_t frame_size, fragment_size, hwbuf_size;
+    size_t frame_size, fragment_size, hwbuf_size, tsched_watermark;
     unsigned nfragments;
 
     char *device_name;
 
-    pa_bool_t use_mmap;
+    pa_bool_t use_mmap, use_tsched;
 
     pa_rtpoll_item *alsa_rtpoll_item;
 
     snd_mixer_selem_channel_id_t mixer_map[SND_MIXER_SCHN_LAST];
+
+    pa_smoother *smoother;
+    int64_t frame_index;
 };
 
 static const char* const valid_modargs[] = {
+    "source_name",
     "device",
     "device_id",
-    "source_name",
-    "channels",
-    "rate",
     "format",
+    "rate",
+    "channels",
+    "channel_map",
     "fragments",
     "fragment_size",
-    "channel_map",
     "mmap",
+    "tsched",
+    "tsched_buffer_size",
+    "tsched_buffer_watermark",
     NULL
 };
 
@@ -125,7 +139,7 @@ static int mmap_read(struct userdata *u) {
         pa_memchunk chunk;
         void *p;
 
-        if ((n = snd_pcm_avail_update(u->pcm_handle)) < 0) {
+        if (PA_UNLIKELY((n = snd_pcm_avail_update(u->pcm_handle)) < 0)) {
 
             if (n == -EPIPE)
                 pa_log_debug("snd_pcm_avail_update: Buffer underrun!");
@@ -140,14 +154,12 @@ static int mmap_read(struct userdata *u) {
             return -1;
         }
 
-/*         pa_log("Got request for %i samples", (int) n); */
-
-        if (n <= 0)
+        if (PA_UNLIKELY(n <= 0))
             return work_done;
 
         frames = n;
 
-        if ((err = snd_pcm_mmap_begin(u->pcm_handle, &areas, &offset, &frames)) < 0) {
+        if (PA_UNLIKELY((err = snd_pcm_mmap_begin(u->pcm_handle, &areas, &offset, &frames)) < 0)) {
 
             if (err == -EPIPE)
                 pa_log_debug("snd_pcm_mmap_begin: Buffer underrun!");
@@ -182,7 +194,7 @@ static int mmap_read(struct userdata *u) {
          * a little bit longer around? */
         pa_memblock_unref_fixed(chunk.memblock);
 
-        if ((err = snd_pcm_mmap_commit(u->pcm_handle, offset, frames)) < 0) {
+        if (PA_UNLIKELY((err = snd_pcm_mmap_commit(u->pcm_handle, offset, frames)) < 0)) {
 
             if (err == -EPIPE)
                 pa_log_debug("snd_pcm_mmap_commit: Buffer underrun!");
@@ -199,7 +211,10 @@ static int mmap_read(struct userdata *u) {
 
         work_done = 1;
 
-/*         pa_log("wrote %i samples", (int) frames); */
+        u->frame_index += frames;
+
+        if (PA_LIKELY(frames >= (snd_pcm_uframes_t) n))
+            return work_done;
     }
 }
 
@@ -214,87 +229,98 @@ static int unix_read(struct userdata *u) {
 
     for (;;) {
         void *p;
-        snd_pcm_sframes_t t, k;
-        ssize_t l;
+        snd_pcm_sframes_t n, frames;
         int err;
         pa_memchunk chunk;
 
-        if ((err = snd_pcm_status(u->pcm_handle, status)) < 0) {
+        if (PA_UNLIKELY((err = snd_pcm_status(u->pcm_handle, status)) < 0)) {
             pa_log("Failed to query DSP status data: %s", snd_strerror(err));
             return -1;
         }
 
-        if (snd_pcm_status_get_avail_max(status)*u->frame_size >= u->hwbuf_size)
+        if (PA_UNLIKELY(snd_pcm_status_get_avail_max(status)*u->frame_size >= u->hwbuf_size))
             pa_log_debug("Buffer overrun!");
 
-        l = snd_pcm_status_get_avail(status) * u->frame_size;
+        n = snd_pcm_status_get_avail(status);
 
-        if (l <= 0)
+        if (PA_UNLIKELY(n <= 0))
             return work_done;
 
         chunk.memblock = pa_memblock_new(u->core->mempool, (size_t) -1);
 
-        k = pa_memblock_get_length(chunk.memblock);
-
-        if (k > l)
-            k = l;
+        frames = pa_memblock_get_length(chunk.memblock) / u->frame_size;
 
-        k = (k/u->frame_size)*u->frame_size;
+        if (frames > n)
+            frames = n;
 
         p = pa_memblock_acquire(chunk.memblock);
-        t = snd_pcm_readi(u->pcm_handle, (uint8_t*) p, k / u->frame_size);
+        frames = snd_pcm_readi(u->pcm_handle, (uint8_t*) p, frames);
         pa_memblock_release(chunk.memblock);
 
-/*                     pa_log("wrote %i bytes of %u (%u)", t*u->frame_size, u->memchunk.length, l);   */
+        pa_assert(frames != 0);
 
-        pa_assert(t != 0);
-
-        if (t < 0) {
+        if (PA_UNLIKELY(frames < 0)) {
             pa_memblock_unref(chunk.memblock);
 
-            if ((t = snd_pcm_recover(u->pcm_handle, t, 1)) == 0)
+            if ((frames = snd_pcm_recover(u->pcm_handle, frames, 1)) == 0)
                 continue;
 
-            if (t == -EAGAIN) {
-                pa_log_debug("EAGAIN");
+            if (frames == -EAGAIN)
                 return work_done;
-            } else {
-                pa_log("Failed to read data from DSP: %s", snd_strerror(t));
-                return -1;
-            }
+
+            pa_log("Failed to read data from DSP: %s", snd_strerror(frames));
+            return -1;
         }
 
         chunk.index = 0;
-        chunk.length = t * u->frame_size;
+        chunk.length = frames * u->frame_size;
 
         pa_source_post(u->source, &chunk);
         pa_memblock_unref(chunk.memblock);
 
         work_done = 1;
 
-        if (t * u->frame_size >= (unsigned) l)
+        u->frame_index += frames;
+
+        if (PA_LIKELY(frames >= n))
             return work_done;
     }
 }
 
-static pa_usec_t source_get_latency(struct userdata *u) {
-    pa_usec_t r = 0;
+static int update_smoother(struct userdata *u) {
     snd_pcm_status_t *status;
-    snd_pcm_sframes_t frames = 0;
+    int64_t frames;
     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)
+    snd_pcm_status_alloca(&status);
+
+    /* Let's update the time smoother */
+
+    if (PA_UNLIKELY((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);
+        return -1;
+    }
+
+    frames = u->frame_index + snd_pcm_status_get_delay(status);
+
+    pa_smoother_put(u->smoother, pa_rtclock_usec(), pa_bytes_to_usec(frames * u->frame_size, &u->source->sample_spec));
+
+    return 0;
+}
+
+static pa_usec_t source_get_latency(struct userdata *u) {
+    pa_usec_t r = 0;
+    int64_t delay;
+
+    pa_assert(u);
 
-    if (frames > 0)
-        r = pa_bytes_to_usec(frames * u->frame_size, &u->source->sample_spec);
+    delay = pa_smoother_get(u->smoother, pa_rtclock_usec()) - u->frame_index;
+
+    if (delay > 0)
+        r = pa_bytes_to_usec(delay * u->frame_size, &u->source->sample_spec);
 
     return r;
 }
@@ -330,6 +356,8 @@ static int suspend(struct userdata *u) {
     pa_assert(u);
     pa_assert(u->pcm_handle);
 
+    pa_smoother_pause(u->smoother, pa_rtclock_usec());
+
     /* Let's suspend */
     snd_pcm_close(u->pcm_handle);
     u->pcm_handle = NULL;
@@ -344,10 +372,55 @@ static int suspend(struct userdata *u) {
     return 0;
 }
 
+static pa_usec_t hw_sleep_time(struct userdata *u) {
+    pa_usec_t usec;
+
+    pa_assert(u);
+
+    usec = pa_source_get_requested_latency(u->source);
+
+    if (usec <= 0)
+        usec = pa_bytes_to_usec(u->hwbuf_size, &u->source->sample_spec);
+
+    if (usec >= u->tsched_watermark)
+        usec -= u->tsched_watermark;
+    else
+        usec /= 2;
+
+    return usec;
+}
+
+static int update_sw_params(struct userdata *u) {
+    size_t avail_min;
+    int err;
+
+    pa_assert(u);
+
+    if (u->use_tsched) {
+        pa_usec_t usec;
+
+        usec = hw_sleep_time(u);
+
+        avail_min = pa_usec_to_bytes(usec, &u->source->sample_spec);
+
+        if (avail_min <= 0)
+            avail_min = 1;
+
+    } else
+        avail_min = 1;
+
+    if ((err = pa_alsa_set_sw_params(u->pcm_handle, avail_min)) < 0) {
+        pa_log("Failed to set software parameters: %s", snd_strerror(err));
+        return err;
+    }
+
+    return 0;
+}
+
 static int unsuspend(struct userdata *u) {
     pa_sample_spec ss;
     int err;
-    pa_bool_t b;
+    pa_bool_t b, d;
     unsigned nfrags;
     snd_pcm_uframes_t period_size;
 
@@ -366,13 +439,14 @@ static int unsuspend(struct userdata *u) {
     nfrags = u->nfragments;
     period_size = u->fragment_size / u->frame_size;
     b = u->use_mmap;
+    d = u->use_tsched;
 
-    if ((err = pa_alsa_set_hw_params(u->pcm_handle, &ss, &nfrags, &period_size, &b, TRUE)) < 0) {
+    if ((err = pa_alsa_set_hw_params(u->pcm_handle, &ss, &nfrags, &period_size, u->hwbuf_size / u->frame_size, &b, &d, TRUE)) < 0) {
         pa_log("Failed to set hardware parameters: %s", snd_strerror(err));
         goto fail;
     }
 
-    if (b != u->use_mmap) {
+    if (b != u->use_mmap || d != u->use_tsched) {
         pa_log_warn("Resume failed, couldn't get original access mode.");
         goto fail;
     }
@@ -387,17 +461,17 @@ static int unsuspend(struct userdata *u) {
         goto fail;
     }
 
-    if ((err = pa_alsa_set_sw_params(u->pcm_handle)) < 0) {
-        pa_log("Failed to set software parameters: %s", snd_strerror(err));
+    if (update_sw_params(u) < 0)
         goto fail;
-    }
 
     if (build_pollfd(u) < 0)
         goto fail;
 
+    /* FIXME: We need to reload the volume somehow */
+
     snd_pcm_start(u->pcm_handle);
 
-    /* FIXME: We need to reload the volume somehow */
+    pa_smoother_resume(u->smoother, pa_rtclock_usec());
 
     pa_log_info("Resumed successfully...");
 
@@ -609,15 +683,39 @@ static void thread_func(void *userdata) {
 
         /* Read some data and pass it to the sources */
         if (PA_SOURCE_OPENED(u->source->thread_info.state)) {
+            int work_done = 0;
 
             if (u->use_mmap) {
-                if (mmap_read(u) < 0)
+                if ((work_done = mmap_read(u)) < 0)
                     goto fail;
 
             } else {
-                if (unix_read(u) < 0)
+                if ((work_done = unix_read(u) < 0))
                     goto fail;
             }
+
+            if (update_smoother(u) < 0)
+                goto fail;
+
+            if (u->use_tsched && work_done) {
+                pa_usec_t usec, cusec;
+
+                /* OK, the capture buffer is now empty, let's
+                 * calculate when to wake up next */
+
+                usec = hw_sleep_time(u);
+
+                pa_log_debug("Waking up in %0.2fms (sound card clock).", (double) usec / PA_USEC_PER_MSEC);
+
+                /* Convert from the sound card time domain to the
+                 * system time domain */
+                cusec = pa_smoother_translate(u->smoother, pa_rtclock_usec(), usec);
+
+                pa_log_debug("Waking up in %0.2fms (system clock).", (double) cusec / PA_USEC_PER_MSEC);
+
+                /* We don't trust the conversion, so we wake up whatever comes first */
+                pa_rtpoll_set_timer_relative(u->rtpoll, PA_MIN(usec, cusec));
+            }
         }
 
         /* Hmm, nothing to do. Let's sleep */
@@ -699,16 +797,22 @@ int pa__init(pa_module*m) {
     const char *dev_id;
     pa_sample_spec ss;
     pa_channel_map map;
-    uint32_t nfrags, frag_size;
-    snd_pcm_uframes_t period_size;
+    uint32_t nfrags, frag_size, tsched_size, tsched_watermark;
+    snd_pcm_uframes_t period_frames, tsched_frames;
     size_t frame_size;
     snd_pcm_info_t *pcm_info = NULL;
     int err;
-    char *t;
     const char *name;
     char *name_buf = NULL;
-    int namereg_fail;
-    pa_bool_t use_mmap = TRUE, b;
+    pa_bool_t namereg_fail;
+    pa_bool_t use_mmap = TRUE, b, use_tsched = TRUE, d;
+    pa_source_new_data data;
+    static const char * const class_table[SND_PCM_CLASS_LAST+1] = {
+        [SND_PCM_CLASS_GENERIC] = "sound",
+        [SND_PCM_CLASS_MULTI] = NULL,
+        [SND_PCM_CLASS_MODEM] = "modem",
+        [SND_PCM_CLASS_DIGITIZER] = NULL
+    };
 
     snd_pcm_info_alloca(&pcm_info);
 
@@ -728,34 +832,55 @@ int pa__init(pa_module*m) {
     frame_size = pa_frame_size(&ss);
 
     nfrags = m->core->default_n_fragments;
-    frag_size = pa_usec_to_bytes(m->core->default_fragment_size_msec*1000, &ss);
+    frag_size = pa_usec_to_bytes(m->core->default_fragment_size_msec*PA_USEC_PER_MSEC, &ss);
     if (frag_size <= 0)
         frag_size = frame_size;
+    tsched_size = pa_usec_to_bytes(DEFAULT_TSCHED_BUFFER_USEC, &ss);
+    tsched_watermark = pa_usec_to_bytes(DEFAULT_TSCHED_WATERMARK_USEC, &ss);
 
-    if (pa_modargs_get_value_u32(ma, "fragments", &nfrags) < 0 || pa_modargs_get_value_u32(ma, "fragment_size", &frag_size) < 0) {
+    if (pa_modargs_get_value_u32(ma, "fragments", &nfrags) < 0 ||
+        pa_modargs_get_value_u32(ma, "fragment_size", &frag_size) < 0 ||
+        pa_modargs_get_value_u32(ma, "tsched_buffer_size", &tsched_size) < 0 ||
+        pa_modargs_get_value_u32(ma, "tsched_buffer_watermark", &tsched_watermark) < 0) {
         pa_log("Failed to parse buffer metrics");
         goto fail;
     }
-    period_size = frag_size/frame_size;
+
+    period_frames = frag_size/frame_size;
+    tsched_frames = tsched_size/frame_size;
 
     if (pa_modargs_get_value_boolean(ma, "mmap", &use_mmap) < 0) {
         pa_log("Failed to parse mmap argument.");
         goto fail;
     }
 
+    if (pa_modargs_get_value_boolean(ma, "tsched", &use_tsched) < 0) {
+        pa_log("Failed to parse timer_scheduling argument.");
+        goto fail;
+    }
+
+    if (use_tsched && !pa_rtclock_hrtimer()) {
+        pa_log("Disabling timer-based scheduling because high-resolution timers are not available from the kernel.");
+        use_tsched = FALSE;
+    }
+
     u = pa_xnew0(struct userdata, 1);
     u->core = m->core;
     u->module = m;
     m->userdata = u;
     u->use_mmap = use_mmap;
+    u->use_tsched = use_tsched;
     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);
+    u->smoother = pa_smoother_new(DEFAULT_TSCHED_WATERMARK_USEC, DEFAULT_TSCHED_WATERMARK_USEC, TRUE);
+    pa_smoother_set_time_offset(u->smoother, pa_rtclock_usec());
 
     snd_config_update_free_global();
 
     b = use_mmap;
+    d = use_tsched;
 
     if ((dev_id = pa_modargs_get_value(ma, "device_id", NULL))) {
 
@@ -764,8 +889,8 @@ int pa__init(pa_module*m) {
                       &u->device_name,
                       &ss, &map,
                       SND_PCM_STREAM_CAPTURE,
-                      &nfrags, &period_size,
-                      &b)))
+                      &nfrags, &period_frames, tsched_frames,
+                      &b, &d)))
             goto fail;
 
     } else {
@@ -775,8 +900,8 @@ int pa__init(pa_module*m) {
                       &u->device_name,
                       &ss, &map,
                       SND_PCM_STREAM_CAPTURE,
-                      &nfrags, &period_size,
-                      &b)))
+                      &nfrags, &period_frames, tsched_frames,
+                      &b, &d)))
             goto fail;
     }
 
@@ -788,18 +913,24 @@ int pa__init(pa_module*m) {
         u->use_mmap = use_mmap = b;
     }
 
+    if (use_tsched && (!b || !d)) {
+        pa_log_info("Cannot enabled timer-based scheduling, falling back to sound IRQ scheduling.");
+        u->use_tsched = use_tsched = FALSE;
+    }
+
     if (u->use_mmap)
         pa_log_info("Successfully enabled mmap() mode.");
 
+    if (u->use_tsched)
+        pa_log_info("Successfully enabled timer-based scheduling 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_sw_params(u->pcm_handle)) < 0) {
-        pa_log("Failed to set software parameters: %s", snd_strerror(err));
+    if (update_sw_params(u) < 0)
         goto fail;
-    }
 
     /* ALSA might tweak the sample spec, so recalculate the frame size */
     frame_size = pa_frame_size(&ss);
@@ -832,13 +963,31 @@ int pa__init(pa_module*m) {
     }
 
     if ((name = pa_modargs_get_value(ma, "source_name", NULL)))
-        namereg_fail = 1;
+        namereg_fail = TRUE;
     else {
         name = name_buf = pa_sprintf_malloc("alsa_input.%s", u->device_name);
-        namereg_fail = 0;
+        namereg_fail = FALSE;
     }
 
-    u->source = pa_source_new(m->core, __FILE__, name, namereg_fail, &ss, &map);
+    pa_source_new_data_init(&data);
+    data.driver = __FILE__;
+    data.module = m;
+    pa_source_new_data_set_name(&data, name);
+    data.namereg_fail = namereg_fail;
+    pa_source_new_data_set_sample_spec(&data, &ss);
+    pa_source_new_data_set_channel_map(&data, &map);
+
+    pa_proplist_sets(data.proplist, PA_PROP_DEVICE_STRING, u->device_name);
+    pa_proplist_sets(data.proplist, PA_PROP_DEVICE_API, "alsa");
+    pa_proplist_sets(data.proplist, PA_PROP_DEVICE_DESCRIPTION, snd_pcm_info_get_name(pcm_info));
+
+    if (class_table[snd_pcm_info_get_class(pcm_info)])
+        pa_proplist_sets(data.proplist, PA_PROP_DEVICE_CLASS, class_table[snd_pcm_info_get_class(pcm_info)]);
+
+    pa_proplist_sets(data.proplist, PA_PROP_DEVICE_ACCESS_MODE, u->use_tsched ? "mmap_rewrite" : (u->use_mmap ? "mmap" : "serial"));
+
+    u->source = pa_source_new(m->core, &data, PA_SOURCE_HARDWARE|PA_SOURCE_LATENCY);
+    pa_source_new_data_done(&data);
     pa_xfree(name_buf);
 
     if (!u->source) {
@@ -849,22 +998,15 @@ int pa__init(pa_module*m) {
     u->source->parent.process_msg = source_process_msg;
     u->source->userdata = u;
 
-    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",
-                                      u->device_name,
-                                      snd_pcm_info_get_name(pcm_info),
-                                      use_mmap ? " via DMA" : ""));
-    pa_xfree(t);
-
-    u->source->flags = PA_SOURCE_HARDWARE|PA_SOURCE_LATENCY;
 
     u->frame_size = frame_size;
-    u->fragment_size = frag_size = period_size * frame_size;
+    u->fragment_size = frag_size = period_frames * frame_size;
     u->nfragments = nfrags;
     u->hwbuf_size = u->fragment_size * nfrags;
+    u->tsched_watermark = tsched_watermark;
+    u->frame_index = 0;
 
     pa_log_info("Using %u fragments of size %lu bytes.", nfrags, (long unsigned) u->fragment_size);
 
@@ -961,6 +1103,9 @@ void pa__done(pa_module*m) {
         snd_pcm_close(u->pcm_handle);
     }
 
+    if (u->smoother)
+        pa_smoother_free(u->smoother);
+
     pa_xfree(u->device_name);
     pa_xfree(u);
 
diff --git a/src/modules/module-combine.c b/src/modules/module-combine.c
index 996cd4f..0b17bc5 100644
--- a/src/modules/module-combine.c
+++ b/src/modules/module-combine.c
@@ -66,7 +66,7 @@ PA_MODULE_USAGE(
         "channel_map=<channel map>");
 
 #define DEFAULT_SINK_NAME "combined"
-#define MEMBLOCKQ_MAXLENGTH (1024*170)
+#define MEMBLOCKQ_MAXLENGTH (1024*1024*16)
 
 #define DEFAULT_ADJUST_TIME 10
 
@@ -139,7 +139,7 @@ enum {
 };
 
 enum {
-    SINK_INPUT_MESSAGE_POST = PA_SINK_INPUT_MESSAGE_MAX
+    SINK_INPUT_MESSAGE_POST = PA_SINK_INPUT_MESSAGE_MAX,
 };
 
 static void output_free(struct output *o);
@@ -203,10 +203,10 @@ static void adjust_rates(struct userdata *u) {
             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)) {
-            pa_log_warn("[%s] sample rates too different, not adjusting (%u vs. %u).", o->sink_input->name, base_rate, r);
+            pa_log_warn("[%s] sample rates too different, not adjusting (%u vs. %u).", pa_proplist_gets(o->sink_input->proplist, PA_PROP_MEDIA_NAME), base_rate, r);
             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_log_info("[%s] new rate is %u Hz; ratio is %0.3f; latency is %0.0f usec.", pa_proplist_gets(o->sink_input->proplist, PA_PROP_MEDIA_NAME), r, (double) r / base_rate, (float) o->total_latency);
             pa_sink_input_set_rate(o->sink_input, r);
         }
     }
@@ -250,6 +250,10 @@ static void thread_func(void *userdata) {
         if (u->sink->thread_info.state == PA_SINK_RUNNING && !u->thread_info.active_outputs) {
             struct timeval now;
 
+            /* Just rewind if necessary, since we are in NULL mode, we
+             * don't have to pass this on */
+            pa_sink_process_rewind(u->sink);
+
             pa_rtclock_get(&now);
 
             if (!u->thread_info.in_null_mode || pa_timeval_cmp(&u->thread_info.timestamp, &now) <= 0) {
@@ -354,27 +358,20 @@ static void request_memblock(struct output *o, size_t length) {
 }
 
 /* Called from I/O thread context */
-static int sink_input_peek_cb(pa_sink_input *i, size_t length, pa_memchunk *chunk) {
+static int sink_input_pop_cb(pa_sink_input *i, size_t nbytes, pa_memchunk *chunk) {
     struct output *o;
 
     pa_sink_input_assert_ref(i);
     pa_assert_se(o = i->userdata);
 
     /* If necessary, get some new data */
-    request_memblock(o, length);
-
-    return pa_memblockq_peek(o->memblockq, chunk);
-}
-
-/* Called from I/O thread context */
-static void sink_input_drop_cb(pa_sink_input *i, size_t length) {
-    struct output *o;
+    request_memblock(o, nbytes);
 
-    pa_sink_input_assert_ref(i);
-    pa_assert(length > 0);
-    pa_assert_se(o = i->userdata);
+    if (pa_memblockq_peek(o->memblockq, chunk) < 0)
+        return -1;
 
-    pa_memblockq_drop(o->memblockq, length);
+    pa_memblockq_drop(o->memblockq, chunk->length);
+    return 0;
 }
 
 /* Called from I/O thread context */
@@ -440,6 +437,7 @@ static int sink_input_process_msg(pa_msgobject *obj, int code, void *data, int64
                 pa_memblockq_flush(o->memblockq);
 
             break;
+
     }
 
     return pa_sink_input_process_msg(obj, code, data, offset, chunk);
@@ -665,10 +663,10 @@ static void update_description(struct userdata *u) {
         char *e;
 
         if (first) {
-            e = pa_sprintf_malloc("%s %s", t, o->sink->description);
+            e = pa_sprintf_malloc("%s %s", t, pa_strnull(pa_proplist_gets(o->sink->proplist, PA_PROP_DEVICE_DESCRIPTION)));
             first = 0;
         } else
-            e = pa_sprintf_malloc("%s, %s", t, o->sink->description);
+            e = pa_sprintf_malloc("%s, %s", t, pa_strnull(pa_proplist_gets(o->sink->proplist, PA_PROP_DEVICE_DESCRIPTION)));
 
         pa_xfree(t);
         t = e;
@@ -723,12 +721,12 @@ static int output_create_sink_input(struct output *o) {
     if (o->sink_input)
         return 0;
 
-    t = pa_sprintf_malloc("Simultaneous output on %s", o->sink->description);
+    t = pa_sprintf_malloc("Simultaneous output on %s", pa_strnull(pa_proplist_gets(o->sink->proplist, PA_PROP_DEVICE_DESCRIPTION)));
 
     pa_sink_input_new_data_init(&data);
     data.sink = o->sink;
     data.driver = __FILE__;
-    data.name = t;
+    pa_proplist_sets(data.proplist, PA_PROP_DEVICE_DESCRIPTION, 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;
@@ -736,14 +734,15 @@ static int output_create_sink_input(struct output *o) {
 
     o->sink_input = pa_sink_input_new(o->userdata->core, &data, PA_SINK_INPUT_VARIABLE_RATE|PA_SINK_INPUT_DONT_MOVE);
 
+    pa_sink_input_new_data_done(&data);
+
     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->pop = sink_input_pop_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;
@@ -775,6 +774,7 @@ static struct output *output_new(struct userdata *u, pa_sink *sink) {
             pa_frame_size(&u->sink->sample_spec),
             1,
             0,
+            0,
             NULL);
 
     pa_assert_se(pa_idxset_put(u->outputs, o, NULL) == 0);
@@ -920,6 +920,7 @@ int pa__init(pa_module*m) {
     pa_channel_map map;
     struct output *o;
     uint32_t idx;
+    pa_sink_new_data data;
 
     pa_assert(m);
 
@@ -1003,7 +1004,19 @@ int pa__init(pa_module*m) {
         goto fail;
     }
 
-    if (!(u->sink = pa_sink_new(m->core, __FILE__, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss, &map))) {
+    pa_sink_new_data_init(&data);
+    data.name = pa_xstrdup(pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME));
+    data.namereg_fail = FALSE;
+    data.driver = __FILE__;
+    data.module = m;
+    pa_sink_new_data_set_sample_spec(&data, &ss);
+    pa_sink_new_data_set_channel_map(&data, &map);
+    pa_proplist_sets(data.proplist, PA_PROP_DEVICE_DESCRIPTION, "Simultaneous Output");
+
+    u->sink = pa_sink_new(m->core, &data, PA_SINK_LATENCY);
+    pa_sink_new_data_done(&data);
+
+    if (!u->sink) {
         pa_log("Failed to create sink");
         goto fail;
     }
@@ -1013,9 +1026,6 @@ int pa__init(pa_module*m) {
     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, "Simultaneous output");
     pa_sink_set_rtpoll(u->sink, u->rtpoll);
     pa_sink_set_asyncmsgq(u->sink, u->thread_mq.inq);
 
@@ -1075,7 +1085,7 @@ int pa__init(pa_module*m) {
             }
         }
 
-        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);
+        u->sink_new_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_PUT], (pa_hook_cb_t) sink_new_hook_cb, u);
     }
 
     u->sink_unlink_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_UNLINK], (pa_hook_cb_t) sink_unlink_hook_cb, u);
diff --git a/src/modules/module-esound-sink.c b/src/modules/module-esound-sink.c
index f9bea63..51c76dc 100644
--- a/src/modules/module-esound-sink.c
+++ b/src/modules/module-esound-sink.c
@@ -508,6 +508,7 @@ int pa__init(pa_module*m) {
     char *t;
     const char *espeaker;
     uint32_t key;
+    pa_sink_new_data data;
 
     pa_assert(m);
 
@@ -554,16 +555,23 @@ int pa__init(pa_module*m) {
     u->state = STATE_AUTH;
     u->latency = 0;
 
-    if (!(u->sink = pa_sink_new(m->core, __FILE__, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss, NULL))) {
+    pa_sink_new_data_init(&data);
+    data.driver = __FILE__;
+    data.module = m;
+    pa_sink_new_data_set_name(&data, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME));
+    pa_sink_new_data_set_sample_spec(&data, &ss);
+
+    u->sink = pa_sink_new(m->core, &data, PA_SINK_LATENCY|PA_SINK_NETWORK);
+    pa_sink_new_data_done(&data);
+
+    if (!u->sink) {
         pa_log("Failed to create sink.");
         goto fail;
     }
 
     u->sink->parent.process_msg = sink_process_msg;
     u->sink->userdata = u;
-    u->sink->flags = PA_SINK_LATENCY|PA_SINK_NETWORK;
 
-    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);
 
diff --git a/src/modules/module-hal-detect.c b/src/modules/module-hal-detect.c
index 832bc73..44b31a5 100644
--- a/src/modules/module-hal-detect.c
+++ b/src/modules/module-hal-detect.c
@@ -372,7 +372,7 @@ static int hal_device_add_all(struct userdata *u, const char *capability) {
                 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);
+                    pa_scache_play_item_by_name(u->core, "pulse-coldplug", d->sink_name, FALSE, PA_VOLUME_NORM, NULL, NULL);
                 count++;
             }
         }
@@ -412,7 +412,7 @@ static void device_added_time_cb(pa_mainloop_api *ea, pa_time_event *ev, const s
                 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_scache_play_item_by_name(td->u->core, "pulse-hotplug", d->sink_name, FALSE, PA_VOLUME_NORM, NULL, NULL);
             }
         }
     }
@@ -575,7 +575,7 @@ static DBusHandlerResult filter_cb(DBusConnection *bus, DBusMessage *message, vo
                         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);
+                                pa_scache_play_item_by_name(u->core, "pulse-access", d->sink_name, FALSE, PA_VOLUME_NORM, NULL, NULL);
                             else
                                 d->acl_race_fix = 1;
 
@@ -643,7 +643,7 @@ static DBusHandlerResult filter_cb(DBusConnection *bus, DBusMessage *message, vo
                     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);
+                            pa_scache_play_item_by_name(u->core, "pulse-access", d->sink_name, FALSE, PA_VOLUME_NORM, NULL, NULL);
                     }
                 }
             }
diff --git a/src/modules/module-jack-sink.c b/src/modules/module-jack-sink.c
index a42aa9e..80a14a6 100644
--- a/src/modules/module-jack-sink.c
+++ b/src/modules/module-jack-sink.c
@@ -277,6 +277,7 @@ int pa__init(pa_module*m) {
     unsigned i;
     const char **ports = NULL, **p;
     char *t;
+    pa_sink_new_data data;
 
     pa_assert(m);
 
@@ -355,20 +356,32 @@ int pa__init(pa_module*m) {
         }
     }
 
-    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.");
+    pa_sink_new_data_init(&data);
+    data.driver = __FILE__;
+    data.module = m;
+    pa_sink_new_data_set_name(&data, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME));
+    pa_sink_new_data_set_sample_spec(&data, &ss);
+    pa_sink_new_data_set_channel_map(&data, &map);
+    pa_proplist_sets(data.proplist, PA_PROP_DEVICE_API, "jack");
+    if (server_name)
+        pa_proplist_sets(data.proplist, PA_PROP_DEVICE_STRING, server_name);
+    pa_proplist_sets(data.proplist, PA_PROP_DEVICE_DESCRIPTION, t = pa_sprintf_malloc("Jack sink (%s)", jack_get_client_name(u->client)));
+    pa_xfree(t);
+    pa_proplist_sets(data.proplist, "jack.client_name", jack_get_client_name(u->client));
+
+    u->sink = pa_sink_new(m->core, &data, PA_SINK_LATENCY);
+    pa_sink_new_data_done(&data);
+
+    if (!u->sink) {
+        pa_log("Failed to create sink.");
         goto fail;
     }
 
     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);
-    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);
diff --git a/src/modules/module-jack-source.c b/src/modules/module-jack-source.c
index 4ee08bf..a687563 100644
--- a/src/modules/module-jack-source.c
+++ b/src/modules/module-jack-source.c
@@ -254,6 +254,7 @@ int pa__init(pa_module*m) {
     unsigned i;
     const char **ports = NULL, **p;
     char *t;
+    pa_source_new_data data;
 
     pa_assert(m);
 
@@ -326,20 +327,32 @@ int pa__init(pa_module*m) {
         }
     }
 
-    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.");
+    pa_source_new_data_init(&data);
+    data.driver = __FILE__;
+    data.module = m;
+    pa_source_new_data_set_name(&data, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME));
+    pa_source_new_data_set_sample_spec(&data, &ss);
+    pa_source_new_data_set_channel_map(&data, &map);
+    pa_proplist_sets(data.proplist, PA_PROP_DEVICE_API, "jack");
+    if (server_name)
+        pa_proplist_sets(data.proplist, PA_PROP_DEVICE_STRING, server_name);
+    pa_proplist_sets(data.proplist, PA_PROP_DEVICE_DESCRIPTION, t = pa_sprintf_malloc("Jack source (%s)", jack_get_client_name(u->client)));
+    pa_xfree(t);
+    pa_proplist_sets(data.proplist, "jack.client_name", jack_get_client_name(u->client));
+
+    u->source = pa_source_new(m->core, &data, PA_SOURCE_LATENCY);
+    pa_source_new_data_done(&data);
+
+    if (!u->source) {
+        pa_log("Failed to create source.");
         goto fail;
     }
 
     u->source->parent.process_msg = source_process_msg;
     u->source->userdata = u;
-    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);
 
     jack_set_process_callback(u->client, jack_process, u);
     jack_on_shutdown(u->client, jack_shutdown, u);
diff --git a/src/modules/module-ladspa-sink.c b/src/modules/module-ladspa-sink.c
index b31037b..696b6ea 100644
--- a/src/modules/module-ladspa-sink.c
+++ b/src/modules/module-ladspa-sink.c
@@ -78,8 +78,6 @@ struct userdata {
     /* 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[] = {
@@ -107,7 +105,7 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
             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);
+            *((pa_usec_t*) data) = usec /* + pa_bytes_to_usec(u->memchunk.length, &u->sink->sample_spec) */;
             return 0;
         }
     }
@@ -129,12 +127,35 @@ static int sink_set_state(pa_sink *s, pa_sink_state_t state) {
 }
 
 /* Called from I/O thread context */
+static void sink_request_rewind(pa_sink *s) {
+    struct userdata *u;
+
+    pa_sink_assert_ref(s);
+    pa_assert_se(u = s->userdata);
+
+    /* Just hand this one over to the master sink */
+    pa_sink_input_request_rewrite(u->sink_input, s->thread_info.rewind_nbytes);
+}
+
+/* Called from I/O thread context */
+static void sink_update_requested_latency(pa_sink *s) {
+    struct userdata *u;
+
+    pa_sink_assert_ref(s);
+    pa_assert_se(u = s->userdata);
+
+    /* Just hand this one over to the master sink */
+    u->sink_input->thread_info.requested_sink_latency = pa_sink_get_requested_latency(s);
+    pa_sink_invalidate_requested_latency(u->master);
+}
+
+/* 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);
+            *((pa_usec_t*) data) = 0 /*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 */
@@ -145,87 +166,76 @@ static int sink_input_process_msg(pa_msgobject *o, int code, void *data, int64_t
 }
 
 /* Called from I/O thread context */
-static int sink_input_peek_cb(pa_sink_input *i, size_t length, pa_memchunk *chunk) {
+static int sink_input_pop_cb(pa_sink_input *i, size_t nbytes, pa_memchunk *chunk) {
     struct userdata *u;
+    float *src, *dst;
+    size_t fs;
+    unsigned n, c;
+    pa_memchunk tchunk;
 
     pa_sink_input_assert_ref(i);
+    pa_assert(chunk);
     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, nbytes, &tchunk);
 
-        pa_sink_render(u->sink, length, &tchunk);
+    fs = pa_frame_size(&i->sample_spec);
+    n = tchunk.length / fs;
 
-        fs = pa_frame_size(&i->sample_spec);
-        n = tchunk.length / fs;
+    pa_assert(n > 0);
 
-        pa_assert(n > 0);
+    chunk->memblock = pa_memblock_new(i->sink->core->mempool, tchunk.length);
+    chunk->index = 0;
+    chunk->length = tchunk.length;
 
-        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(chunk->memblock);
 
-        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;
 
-        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 = PA_CLAMP_UNLIKELY(*p, -1.0, 1.0);
 
-            p = src + c;
-            q = u->input;
-            for (j = 0; j < n; j++, p += u->channels, q++)
-                *q = PA_CLAMP_UNLIKELY(*p, -1.0, 1.0);
+        u->descriptor->run(u->handle[c], n);
 
-            u->descriptor->run(u->handle[c], n);
-
-            q = u->output;
-            p = dst + c;
-            for (j = 0; j < n; j++, q++, p += u->channels)
-                *p = PA_CLAMP_UNLIKELY(*q, -1.0, 1.0);
-        }
-
-        pa_memblock_release(tchunk.memblock);
-        pa_memblock_release(u->memchunk.memblock);
-
-        pa_memblock_unref(tchunk.memblock);
+        q = u->output;
+        p = dst + c;
+        for (j = 0; j < n; j++, q++, p += u->channels)
+            *p = PA_CLAMP_UNLIKELY(*q, -1.0, 1.0);
     }
 
-    pa_assert(u->memchunk.length > 0);
-    pa_assert(u->memchunk.memblock);
+    pa_memblock_release(tchunk.memblock);
+    pa_memblock_release(chunk->memblock);
 
-    *chunk = u->memchunk;
-    pa_memblock_ref(chunk->memblock);
+    pa_memblock_unref(tchunk.memblock);
 
     return 0;
 }
 
 /* Called from I/O thread context */
-static void sink_input_drop_cb(pa_sink_input *i, size_t length) {
+static void sink_input_rewind_cb(pa_sink_input *i, size_t nbytes) {
     struct userdata *u;
 
     pa_sink_input_assert_ref(i);
     pa_assert_se(u = i->userdata);
-    pa_assert(length > 0);
+    pa_assert(nbytes > 0);
 
-    if (u->memchunk.memblock) {
+    u->sink->thread_info.rewind_nbytes = nbytes;
+    pa_sink_process_rewind(u->sink);
+}
 
-        if (length < u->memchunk.length) {
-            u->memchunk.index += length;
-            u->memchunk.length -= length;
-            return;
-        }
+/* Called from I/O thread context */
+static void sink_input_set_max_rewind_cb(pa_sink_input *i, size_t nbytes) {
+    struct userdata *u;
 
-        pa_memblock_unref(u->memchunk.memblock);
-        length -= u->memchunk.length;
-        pa_memchunk_reset(&u->memchunk);
-    }
+    pa_sink_input_assert_ref(i);
+    pa_assert_se(u = i->userdata);
 
-    if (length > 0)
-        pa_sink_skip(u->sink, length);
+    pa_sink_set_max_rewind(u->sink, nbytes);
 }
 
 /* Called from I/O thread context */
@@ -275,8 +285,10 @@ int pa__init(pa_module*m) {
     pa_channel_map map;
     pa_modargs *ma;
     char *t;
+    const char *z;
     pa_sink *master;
-    pa_sink_input_new_data data;
+    pa_sink_input_new_data sink_input_data;
+    pa_sink_new_data sink_data;
     const char *plugin, *label;
     LADSPA_Descriptor_Function descriptor_func;
     const char *e, *cdata;
@@ -284,7 +296,6 @@ int pa__init(pa_module*m) {
     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);
 
@@ -325,7 +336,8 @@ int pa__init(pa_module*m) {
     u->module = m;
     m->userdata = u;
     u->master = master;
-    pa_memchunk_reset(&u->memchunk);
+    u->sink = NULL;
+    u->sink_input = NULL;
 
     if (!(e = getenv("LADSPA_PATH")))
         e = LADSPA_PATH;
@@ -583,40 +595,65 @@ int pa__init(pa_module*m) {
         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_sink_new_data_init(&sink_data);
+    sink_data.driver = __FILE__;
+    sink_data.module = m;
+    if (!(sink_data.name = pa_xstrdup(pa_modargs_get_value(ma, "sink_name", NULL))))
+        sink_data.name = pa_sprintf_malloc("%s.ladspa", master->name);
+    sink_data.namereg_fail = FALSE;
+    pa_sink_new_data_set_sample_spec(&sink_data, &ss);
+    pa_sink_new_data_set_channel_map(&sink_data, &map);
+    z = pa_proplist_gets(master->proplist, PA_PROP_DEVICE_DESCRIPTION);
+    pa_proplist_sets(sink_data.proplist, PA_PROP_DEVICE_DESCRIPTION, t = pa_sprintf_malloc("LADSPA Plugin %s on %s", label, z ? z : master->name));
+    pa_xfree(t);
+    pa_proplist_sets(sink_data.proplist, PA_PROP_DEVICE_MASTER_DEVICE, master->name);
+    pa_proplist_sets(sink_data.proplist, "device.ladspa.module", plugin);
+    pa_proplist_sets(sink_data.proplist, "device.ladspa.label", d->Label);
+    pa_proplist_sets(sink_data.proplist, "device.ladspa.name", d->Name);
+    pa_proplist_sets(sink_data.proplist, "device.ladspa.maker", d->Maker);
+    pa_proplist_sets(sink_data.proplist, "device.ladspa.copyright", d->Copyright);
+    pa_proplist_sets(sink_data.proplist, "device.ladspa.unique_id", t = pa_sprintf_malloc("%lu", (unsigned long) d->UniqueID));
+    pa_xfree(t);
+
+    u->sink = pa_sink_new(m->core, &sink_data, 0);
+    pa_sink_new_data_done(&sink_data);
+
+    if (!u->sink) {
         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->update_requested_latency = sink_update_requested_latency;
+    u->sink->request_rewind = sink_request_rewind;
     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)))
+    pa_sink_input_new_data_init(&sink_input_data);
+    sink_input_data.driver = __FILE__;
+    sink_input_data.module = m;
+    sink_input_data.sink = u->master;
+    pa_proplist_sets(sink_input_data.proplist, PA_PROP_MEDIA_NAME, "LADSPA Stream");
+    pa_proplist_sets(sink_input_data.proplist, PA_PROP_MEDIA_ROLE, "routing");
+    pa_sink_input_new_data_set_sample_spec(&sink_input_data, &ss);
+    pa_sink_input_new_data_set_channel_map(&sink_input_data, &map);
+
+    u->sink_input = pa_sink_input_new(m->core, &sink_input_data, PA_SINK_INPUT_DONT_MOVE);
+    pa_sink_input_new_data_done(&sink_input_data);
+
+    if (!u->sink_input)
         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->pop = sink_input_pop_cb;
+    u->sink_input->rewind = sink_input_rewind_cb;
+    u->sink_input->set_max_rewind = sink_input_set_max_rewind_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;
@@ -628,7 +665,6 @@ int pa__init(pa_module*m) {
     pa_modargs_free(ma);
 
     pa_xfree(use_default);
-    pa_xfree(default_sink_name);
 
     return 0;
 
@@ -637,7 +673,6 @@ fail:
         pa_modargs_free(ma);
 
     pa_xfree(use_default);
-    pa_xfree(default_sink_name);
 
     pa__done(m);
 
@@ -663,9 +698,6 @@ void pa__done(pa_module*m) {
         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)
diff --git a/src/modules/module-match.c b/src/modules/module-match.c
index ed5f307..0411dcd 100644
--- a/src/modules/module-match.c
+++ b/src/modules/module-match.c
@@ -166,6 +166,7 @@ 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;
+    const char *n;
 
     pa_assert(c);
     pa_assert(u);
@@ -176,13 +177,13 @@ static void callback(pa_core *c, pa_subscription_event_type_t t, uint32_t idx, v
     if (!(si = pa_idxset_get_by_index(c->sink_inputs, idx)))
         return;
 
-    if (!si->name)
+    if (!(n = pa_proplist_gets(si->proplist, PA_PROP_MEDIA_NAME)))
         return;
 
     for (r = u->rules; r; r = r->next) {
-        if (!regexec(&r->regex, si->name, 0, NULL, 0)) {
+        if (!regexec(&r->regex, n, 0, NULL, 0)) {
             pa_cvolume cv;
-            pa_log_debug("changing volume of sink input '%s' to 0x%03x", si->name, r->volume);
+            pa_log_debug("changing volume of sink input '%s' to 0x%03x", n, r->volume);
             pa_cvolume_set(&cv, si->sample_spec.channels, r->volume);
             pa_sink_input_set_volume(si, &cv);
         }
diff --git a/src/modules/module-null-sink.c b/src/modules/module-null-sink.c
index de35fff..6e59c62 100644
--- a/src/modules/module-null-sink.c
+++ b/src/modules/module-null-sink.c
@@ -169,6 +169,7 @@ int pa__init(pa_module*m) {
     pa_sample_spec ss;
     pa_channel_map map;
     pa_modargs *ma = NULL;
+    pa_sink_new_data data;
 
     pa_assert(m);
 
@@ -191,7 +192,18 @@ int pa__init(pa_module*m) {
     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(m->core, __FILE__, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss, &map))) {
+    pa_sink_new_data_init(&data);
+    data.driver = __FILE__;
+    data.module = m;
+    pa_sink_new_data_set_name(&data, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME));
+    pa_sink_new_data_set_sample_spec(&data, &ss);
+    pa_sink_new_data_set_channel_map(&data, &map);
+    pa_proplist_sets(data.proplist, PA_PROP_DEVICE_DESCRIPTION, pa_modargs_get_value(ma, "description", "NULL sink"));
+
+    u->sink = pa_sink_new(m->core, &data, 0);
+    pa_sink_new_data_done(&data);
+
+    if (!u->sink) {
         pa_log("Failed to create sink.");
         goto fail;
     }
@@ -200,10 +212,8 @@ int pa__init(pa_module*m) {
     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);
-    pa_sink_set_description(u->sink, pa_modargs_get_value(ma, "description", "NULL sink"));
 
     u->block_size = pa_bytes_per_second(&ss) / 20; /* 50 ms */
     if (u->block_size <= 0)
diff --git a/src/modules/module-oss.c b/src/modules/module-oss.c
index a7df8a0..149c70d 100644
--- a/src/modules/module-oss.c
+++ b/src/modules/module-oss.c
@@ -1143,9 +1143,9 @@ int pa__init(pa_module*m) {
     pa_sample_spec ss;
     pa_channel_map map;
     pa_modargs *ma = NULL;
-    char hwdesc[64], *t;
+    char hwdesc[64];
     const char *name;
-    int namereg_fail;
+    pa_bool_t namereg_fail;
 
     pa_assert(m);
 
@@ -1258,6 +1258,7 @@ int pa__init(pa_module*m) {
     u->out_hwbuf_size = u->out_nfrags * u->out_fragment_size;
 
     if (mode != O_WRONLY) {
+        pa_source_new_data data;
         char *name_buf = NULL;
 
         if (use_mmap) {
@@ -1270,14 +1271,28 @@ int pa__init(pa_module*m) {
         }
 
         if ((name = pa_modargs_get_value(ma, "source_name", NULL)))
-            namereg_fail = 1;
+            namereg_fail = TRUE;
         else {
             name = name_buf = pa_sprintf_malloc("oss_input.%s", pa_path_get_filename(dev));
-            namereg_fail = 0;
+            namereg_fail = FALSE;
         }
 
-        u->source = pa_source_new(m->core, __FILE__, name, namereg_fail, &ss, &map);
+        pa_source_new_data_init(&data);
+        data.driver = __FILE__;
+        data.module = m;
+        pa_source_new_data_set_name(&data, name);
+        data.namereg_fail = namereg_fail;
+        pa_source_new_data_set_sample_spec(&data, &ss);
+        pa_source_new_data_set_channel_map(&data, &map);
+        pa_proplist_sets(data.proplist, PA_PROP_DEVICE_STRING, dev);
+        pa_proplist_sets(data.proplist, PA_PROP_DEVICE_API, "oss");
+        pa_proplist_sets(data.proplist, PA_PROP_DEVICE_DESCRIPTION, hwdesc[0] ? hwdesc : dev);
+        pa_proplist_sets(data.proplist, PA_PROP_DEVICE_ACCESS_MODE, use_mmap ? "mmap" : "serial");
+
+        u->source = pa_source_new(m->core, &data, PA_SOURCE_HARDWARE|PA_SOURCE_LATENCY);
+        pa_source_new_data_done(&data);
         pa_xfree(name_buf);
+
         if (!u->source) {
             pa_log("Failed to create source object");
             goto fail;
@@ -1286,18 +1301,8 @@ int pa__init(pa_module*m) {
         u->source->parent.process_msg = source_process_msg;
         u->source->userdata = u;
 
-        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->flags = PA_SOURCE_HARDWARE|PA_SOURCE_LATENCY;
         u->source->refresh_volume = TRUE;
 
         if (use_mmap)
@@ -1305,6 +1310,7 @@ int pa__init(pa_module*m) {
     }
 
     if (mode != O_RDONLY) {
+        pa_sink_new_data data;
         char *name_buf = NULL;
 
         if (use_mmap) {
@@ -1331,8 +1337,22 @@ int pa__init(pa_module*m) {
             namereg_fail = 0;
         }
 
-        u->sink = pa_sink_new(m->core, __FILE__, name, namereg_fail, &ss, &map);
+        pa_sink_new_data_init(&data);
+        data.driver = __FILE__;
+        data.module = m;
+        pa_sink_new_data_set_name(&data, name);
+        data.namereg_fail = namereg_fail;
+        pa_sink_new_data_set_sample_spec(&data, &ss);
+        pa_sink_new_data_set_channel_map(&data, &map);
+        pa_proplist_sets(data.proplist, PA_PROP_DEVICE_STRING, dev);
+        pa_proplist_sets(data.proplist, PA_PROP_DEVICE_API, "oss");
+        pa_proplist_sets(data.proplist, PA_PROP_DEVICE_DESCRIPTION, hwdesc[0] ? hwdesc : dev);
+        pa_proplist_sets(data.proplist, PA_PROP_DEVICE_ACCESS_MODE, use_mmap ? "mmap" : "serial");
+
+        u->sink = pa_sink_new(m->core, &data, PA_SINK_HARDWARE|PA_SINK_LATENCY);
+        pa_sink_new_data_done(&data);
         pa_xfree(name_buf);
+
         if (!u->sink) {
             pa_log("Failed to create sink object");
             goto fail;
@@ -1341,18 +1361,8 @@ int pa__init(pa_module*m) {
         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(
-                                        "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->flags = PA_SINK_HARDWARE|PA_SINK_LATENCY;
         u->sink->refresh_volume = TRUE;
 
         if (use_mmap)
diff --git a/src/modules/module-pipe-sink.c b/src/modules/module-pipe-sink.c
index e720c8a..73a5211 100644
--- a/src/modules/module-pipe-sink.c
+++ b/src/modules/module-pipe-sink.c
@@ -207,6 +207,7 @@ int pa__init(pa_module*m) {
     pa_modargs *ma;
     char *t;
     struct pollfd *pollfd;
+    pa_sink_new_data data;
 
     pa_assert(m);
 
@@ -251,20 +252,29 @@ int pa__init(pa_module*m) {
         goto fail;
     }
 
-    if (!(u->sink = pa_sink_new(m->core, __FILE__, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss, &map))) {
+    pa_sink_new_data_init(&data);
+    data.driver = __FILE__;
+    data.module = m;
+    pa_sink_new_data_set_name(&data, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME));
+    pa_proplist_sets(data.proplist, PA_PROP_DEVICE_STRING, u->filename);
+    pa_proplist_sets(data.proplist, PA_PROP_DEVICE_DESCRIPTION, t = pa_sprintf_malloc("Unix FIFO sink %s", u->filename));
+    pa_xfree(t);
+    pa_sink_new_data_set_sample_spec(&data, &ss);
+    pa_sink_new_data_set_channel_map(&data, &map);
+
+    u->sink = pa_sink_new(m->core, &data, PA_SINK_LATENCY);
+    pa_sink_new_data_done(&data);
+
+    if (!u->sink) {
         pa_log("Failed to create sink.");
         goto fail;
     }
 
     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);
-    pa_sink_set_description(u->sink, t = pa_sprintf_malloc("Unix FIFO sink '%s'", u->filename));
-    pa_xfree(t);
 
     u->rtpoll_item = pa_rtpoll_item_new(u->rtpoll, PA_RTPOLL_NEVER, 1);
     pollfd = pa_rtpoll_item_get_pollfd(u->rtpoll_item, NULL);
diff --git a/src/modules/module-pipe-source.c b/src/modules/module-pipe-source.c
index 0293564..cf88c82 100644
--- a/src/modules/module-pipe-source.c
+++ b/src/modules/module-pipe-source.c
@@ -184,6 +184,7 @@ int pa__init(pa_module*m) {
     pa_modargs *ma;
     char *t;
     struct pollfd *pollfd;
+    pa_source_new_data data;
 
     pa_assert(m);
 
@@ -228,19 +229,28 @@ int pa__init(pa_module*m) {
         goto fail;
     }
 
-    if (!(u->source = pa_source_new(m->core, __FILE__, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME), 0, &ss, &map))) {
+    pa_source_new_data_init(&data);
+    data.driver = __FILE__;
+    data.module = m;
+    pa_source_new_data_set_name(&data, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME));
+    pa_proplist_sets(data.proplist, PA_PROP_DEVICE_STRING, u->filename);
+    pa_proplist_sets(data.proplist, PA_PROP_DEVICE_DESCRIPTION, t = pa_sprintf_malloc("Unix FIFO source %s", u->filename));
+    pa_xfree(t);
+    pa_source_new_data_set_sample_spec(&data, &ss);
+    pa_source_new_data_set_channel_map(&data, &map);
+
+    u->source = pa_source_new(m->core, &data, 0);
+    pa_source_new_data_done(&data);
+
+    if (!u->source) {
         pa_log("Failed to create source.");
         goto fail;
     }
 
     u->source->userdata = u;
-    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->rtpoll_item = pa_rtpoll_item_new(u->rtpoll, PA_RTPOLL_NEVER, 1);
     pollfd = pa_rtpoll_item_get_pollfd(u->rtpoll_item, NULL);
diff --git a/src/modules/module-remap-sink.c b/src/modules/module-remap-sink.c
index 39a9245..1c97a82 100644
--- a/src/modules/module-remap-sink.c
+++ b/src/modules/module-remap-sink.c
@@ -59,8 +59,6 @@ struct userdata {
 
     pa_sink *sink, *master;
     pa_sink_input *sink_input;
-
-    pa_memchunk memchunk;
 };
 
 static const char* const valid_modargs[] = {
@@ -86,7 +84,7 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
             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);
+            *((pa_usec_t*) data) = usec/* + pa_bytes_to_usec(u->memchunk.length, &u->sink->sample_spec)*/;
             return 0;
         }
     }
@@ -108,12 +106,34 @@ static int sink_set_state(pa_sink *s, pa_sink_state_t state) {
 }
 
 /* Called from I/O thread context */
+static void sink_request_rewind(pa_sink *s) {
+    struct userdata *u;
+
+    pa_sink_assert_ref(s);
+    pa_assert_se(u = s->userdata);
+
+    pa_sink_input_request_rewrite(u->sink_input, s->thread_info.rewind_nbytes);
+}
+
+/* Called from I/O thread context */
+static void sink_update_requested_latency(pa_sink *s) {
+    struct userdata *u;
+
+    pa_sink_assert_ref(s);
+    pa_assert_se(u = s->userdata);
+
+    /* Just hand this one over to the master sink */
+    u->sink_input->thread_info.requested_sink_latency = pa_sink_get_requested_latency(s);
+    pa_sink_invalidate_requested_latency(u->master);
+}
+
+/* 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);
+            *((pa_usec_t*) data) = 0; /*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 */
@@ -123,45 +143,41 @@ static int sink_input_process_msg(pa_msgobject *o, int code, void *data, int64_t
     return pa_sink_input_process_msg(o, code, data, offset, chunk);
 }
 
+static void sink_input_rewind_cb(pa_sink_input *i, size_t nbytes);
+
 /* Called from I/O thread context */
-static int sink_input_peek_cb(pa_sink_input *i, size_t length, pa_memchunk *chunk) {
+static int sink_input_pop_cb(pa_sink_input *i, size_t nbytes, pa_memchunk *chunk) {
     struct userdata *u;
 
     pa_sink_input_assert_ref(i);
+    pa_assert(chunk);
     pa_assert_se(u = i->userdata);
 
-    if (!u->memchunk.memblock)
-        pa_sink_render(u->sink, length, &u->memchunk);
+    pa_sink_render(u->sink, nbytes, chunk);
 
-    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) {
+static void sink_input_rewind_cb(pa_sink_input *i, size_t nbytes) {
     struct userdata *u;
 
     pa_sink_input_assert_ref(i);
     pa_assert_se(u = i->userdata);
-    pa_assert(length > 0);
+    pa_assert(nbytes > 0);
 
-    if (u->memchunk.memblock) {
+    u->sink->thread_info.rewind_nbytes = nbytes;
+    pa_sink_process_rewind(u->sink);
+}
 
-        if (length < u->memchunk.length) {
-            u->memchunk.index += length;
-            u->memchunk.length -= length;
-            return;
-        }
+/* Called from I/O thread context */
+static void sink_input_set_max_rewind_cb(pa_sink_input *i, size_t nbytes) {
+    struct userdata *u;
 
-        pa_memblock_unref(u->memchunk.memblock);
-        length -= u->memchunk.length;
-        pa_memchunk_reset(&u->memchunk);
-    }
+    pa_sink_input_assert_ref(i);
+    pa_assert_se(u = i->userdata);
 
-    if (length > 0)
-        pa_sink_skip(u->sink, length);
+    pa_sink_set_max_rewind(u->sink, nbytes);
 }
 
 /* Called from I/O thread context */
@@ -211,9 +227,10 @@ int pa__init(pa_module*m) {
     pa_channel_map sink_map, stream_map;
     pa_modargs *ma;
     char *t;
+    const char *k;
     pa_sink *master;
-    pa_sink_input_new_data data;
-    char *default_sink_name = NULL;
+    pa_sink_input_new_data sink_input_data;
+    pa_sink_new_data sink_data;
 
     pa_assert(m);
 
@@ -245,47 +262,68 @@ int pa__init(pa_module*m) {
         goto fail;
     }
 
+    if (pa_channel_map_equal(&stream_map, &master->channel_map))
+        pa_log_warn("No remapping configured, proceeding nonetheless!");
+
     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);
+    u->sink = NULL;
+    u->sink_input = NULL;
 
     /* 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_sink_new_data_init(&sink_data);
+    sink_data.driver = __FILE__;
+    sink_data.module = m;
+    if (!(sink_data.name = pa_xstrdup(pa_modargs_get_value(ma, "sink_name", NULL))))
+        sink_data.name = pa_sprintf_malloc("%s.remapped", master->name);
+    pa_sink_new_data_set_sample_spec(&sink_data, &ss);
+    pa_sink_new_data_set_channel_map(&sink_data, &sink_map);
+    k = pa_proplist_gets(master->proplist, PA_PROP_DEVICE_DESCRIPTION);
+    pa_proplist_sets(sink_data.proplist, PA_PROP_DEVICE_DESCRIPTION, t = pa_sprintf_malloc("Remapped %s", k ? k : master->name));
+    pa_xfree(t);
+    pa_proplist_sets(sink_data.proplist, PA_PROP_DEVICE_MASTER_DEVICE, master->name);
+
+    u->sink = pa_sink_new(m->core, &sink_data, 0);
+    pa_sink_new_data_done(&sink_data);
+
+    if (!u->sink) {
         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->update_requested_latency = sink_update_requested_latency;
+    u->sink->request_rewind = sink_request_rewind;
     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)))
+    pa_sink_input_new_data_init(&sink_input_data);
+    sink_input_data.driver = __FILE__;
+    sink_input_data.module = m;
+    sink_input_data.sink = u->master;
+    pa_proplist_sets(sink_input_data.proplist, PA_PROP_MEDIA_NAME, "Remapped Stream");
+    pa_proplist_sets(sink_input_data.proplist, PA_PROP_MEDIA_ROLE, "routing");
+    pa_sink_input_new_data_set_sample_spec(&sink_input_data, &ss);
+    pa_sink_input_new_data_set_channel_map(&sink_input_data, &stream_map);
+
+    u->sink_input = pa_sink_input_new(m->core, &sink_input_data, PA_SINK_INPUT_DONT_MOVE);
+    pa_sink_input_new_data_done(&sink_input_data);
+
+    if (!u->sink_input)
         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->pop = sink_input_pop_cb;
+    u->sink_input->rewind = sink_input_rewind_cb;
+    u->sink_input->set_max_rewind = sink_input_set_max_rewind_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;
@@ -295,7 +333,6 @@ int pa__init(pa_module*m) {
     pa_sink_input_put(u->sink_input);
 
     pa_modargs_free(ma);
-    pa_xfree(default_sink_name);
 
     return 0;
 
@@ -305,8 +342,6 @@ fail:
 
     pa__done(m);
 
-    pa_xfree(default_sink_name);
-
     return -1;
 }
 
@@ -328,8 +363,5 @@ void pa__done(pa_module*m) {
         pa_sink_unref(u->sink);
     }
 
-    if (u->memchunk.memblock)
-        pa_memblock_unref(u->memchunk.memblock);
-
     pa_xfree(u);
 }
diff --git a/src/modules/module-rescue-streams.c b/src/modules/module-rescue-streams.c
index 12957c9..dda5473 100644
--- a/src/modules/module-rescue-streams.c
+++ b/src/modules/module-rescue-streams.c
@@ -76,11 +76,11 @@ static pa_hook_result_t sink_hook_callback(pa_core *c, pa_sink *sink, void* user
 
     while ((i = pa_idxset_first(sink->inputs, NULL))) {
         if (pa_sink_input_move_to(i, target, 1) < 0) {
-            pa_log_warn("Failed to move sink input %u \"%s\" to %s.", i->index, i->name, target->name);
+            pa_log_warn("Failed to move sink input %u \"%s\" to %s.", i->index, pa_proplist_gets(i->proplist, PA_PROP_APPLICATION_NAME), target->name);
             return PA_HOOK_OK;
         }
 
-        pa_log_info("Sucessfully moved sink input %u \"%s\" to %s.", i->index, i->name, target->name);
+        pa_log_info("Sucessfully moved sink input %u \"%s\" to %s.", i->index, pa_proplist_gets(i->proplist, PA_PROP_APPLICATION_NAME), target->name);
     }
 
 
@@ -116,11 +116,11 @@ static pa_hook_result_t source_hook_callback(pa_core *c, pa_source *source, void
 
     while ((o = pa_idxset_first(source->outputs, NULL))) {
         if (pa_source_output_move_to(o, target) < 0) {
-            pa_log_warn("Failed to move source output %u \"%s\" to %s.", o->index, o->name, target->name);
+            pa_log_warn("Failed to move source output %u \"%s\" to %s.", o->index, pa_proplist_gets(o->proplist, PA_PROP_APPLICATION_NAME), target->name);
             return PA_HOOK_OK;
         }
 
-        pa_log_info("Sucessfully moved source output %u \"%s\" to %s.", o->index, o->name, target->name);
+        pa_log_info("Sucessfully moved source output %u \"%s\" to %s.", o->index, pa_proplist_gets(o->proplist, PA_PROP_APPLICATION_NAME), target->name);
     }
 
 
diff --git a/src/modules/module-sine.c b/src/modules/module-sine.c
index 41d9a51..f6718fd 100644
--- a/src/modules/module-sine.c
+++ b/src/modules/module-sine.c
@@ -59,44 +59,25 @@ static const char* const valid_modargs[] = {
     NULL,
 };
 
-static int sink_input_peek_cb(pa_sink_input *i, size_t length, pa_memchunk *chunk) {
+static int sink_input_pop_cb(pa_sink_input *i, size_t nbytes, pa_memchunk *chunk) {
     struct userdata *u;
 
-    pa_assert(i);
-    u = i->userdata;
-    pa_assert(u);
+    pa_sink_input_assert_ref(i);
+    pa_assert_se(u = i->userdata);
     pa_assert(chunk);
 
     chunk->memblock = pa_memblock_ref(u->memblock);
-    chunk->index = u->peek_index;
-    chunk->length = pa_memblock_get_length(u->memblock) - u->peek_index;
+    chunk->length = pa_memblock_get_length(chunk->memblock);
+    chunk->index = 0;
 
     return 0;
 }
 
-static void sink_input_drop_cb(pa_sink_input *i, size_t length) {
-    struct userdata *u;
-    size_t l;
-
-    pa_assert(i);
-    u = i->userdata;
-    pa_assert(u);
-    pa_assert(length > 0);
-
-    u->peek_index += length;
-
-    l = pa_memblock_get_length(u->memblock);
-
-    while (u->peek_index >= l)
-        u->peek_index -= l;
-}
-
 static void sink_input_kill_cb(pa_sink_input *i) {
     struct userdata *u;
 
-    pa_assert(i);
-    u = i->userdata;
-    pa_assert(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);
@@ -156,20 +137,23 @@ int pa__init(pa_module*m) {
     calc_sine(p, pa_memblock_get_length(u->memblock), frequency);
     pa_memblock_release(u->memblock);
 
-    pa_snprintf(t, sizeof(t), "Sine Generator at %u Hz", frequency);
+    pa_snprintf(t, sizeof(t), "%u Hz Sine", frequency);
 
     pa_sink_input_new_data_init(&data);
     data.sink = sink;
     data.driver = __FILE__;
-    data.name = t;
+    pa_proplist_sets(data.proplist, PA_PROP_MEDIA_NAME, t);
+    pa_proplist_sets(data.proplist, PA_PROP_MEDIA_ROLE, "abstract");
     pa_sink_input_new_data_set_sample_spec(&data, &ss);
     data.module = m;
 
-    if (!(u->sink_input = pa_sink_input_new(m->core, &data, 0)))
+    u->sink_input = pa_sink_input_new(m->core, &data, 0);
+    pa_sink_input_new_data_done(&data);
+
+    if (!u->sink_input)
         goto fail;
 
-    u->sink_input->peek = sink_input_peek_cb;
-    u->sink_input->drop = sink_input_drop_cb;
+    u->sink_input->pop = sink_input_pop_cb;
     u->sink_input->kill = sink_input_kill_cb;
     u->sink_input->userdata = u;
 
diff --git a/src/modules/module-suspend-on-idle.c b/src/modules/module-suspend-on-idle.c
index 4c260d7..ef8239d 100644
--- a/src/modules/module-suspend-on-idle.c
+++ b/src/modules/module-suspend-on-idle.c
@@ -367,8 +367,8 @@ int pa__init(pa_module*m) {
     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_new_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_PUT], (pa_hook_cb_t) device_new_hook_cb, u);
+    u->source_new_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_PUT], (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);
diff --git a/src/modules/module-tunnel.c b/src/modules/module-tunnel.c
index a53e393..2da2d13 100644
--- a/src/modules/module-tunnel.c
+++ b/src/modules/module-tunnel.c
@@ -1294,6 +1294,11 @@ int pa__init(pa_module*m) {
     pa_sample_spec ss;
     pa_channel_map map;
     char *t, *dn = NULL;
+#ifdef TUNNEL_SINK
+    pa_sink_new_data data;
+#else
+    pa_source_new_data data;
+#endif
 
     pa_assert(m);
 
@@ -1354,7 +1359,18 @@ int pa__init(pa_module*m) {
     if (!(dn = pa_xstrdup(pa_modargs_get_value(ma, "sink_name", NULL))))
         dn = pa_sprintf_malloc("tunnel.%s", u->server_name);
 
-    if (!(u->sink = pa_sink_new(m->core, __FILE__, dn, 1, &ss, &map))) {
+    pa_sink_new_data_init(&data);
+    data.driver = __FILE__;
+    data.module = m;
+    data.namereg_fail = TRUE;
+    pa_sink_new_data_set_name(&data, dn);
+    pa_sink_new_data_set_sample_spec(&data, &ss);
+    pa_sink_new_data_set_channel_map(&data, &map);
+
+    u->sink = pa_sink_new(m->core, &data, PA_SINK_NETWORK|PA_SINK_LATENCY|PA_SINK_HW_VOLUME_CTRL);
+    pa_sink_new_data_done(&data);
+
+    if (!u->sink) {
         pa_log("Failed to create sink.");
         goto fail;
     }
@@ -1367,9 +1383,7 @@ int pa__init(pa_module*m) {
     u->sink->get_mute = sink_get_mute;
     u->sink->set_volume = sink_set_volume;
     u->sink->set_mute = sink_set_mute;
-    u->sink->flags = PA_SINK_NETWORK|PA_SINK_LATENCY|PA_SINK_HW_VOLUME_CTRL;
 
-    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("%s%s%s", u->sink_name ? u->sink_name : "", u->sink_name ? " on " : "", u->server_name));
@@ -1380,7 +1394,18 @@ int pa__init(pa_module*m) {
     if (!(dn = pa_xstrdup(pa_modargs_get_value(ma, "source_name", NULL))))
         dn = pa_sprintf_malloc("tunnel.%s", u->server_name);
 
-    if (!(u->source = pa_source_new(m->core, __FILE__, dn, 1, &ss, &map))) {
+    pa_source_new_data_init(&data);
+    data.driver = __FILE__;
+    data.module = m;
+    data.namereg_fail = TRUE;
+    pa_source_new_data_set_name(&data, dn);
+    pa_source_new_data_set_sample_spec(&data, &ss);
+    pa_source_new_data_set_channel_map(&data, &map);
+
+    u->source = pa_source_new(m->core, &data, PA_SOURCE_NETWORK|PA_SOURCE_LATENCY);
+    pa_source_new_data_done(&data);
+
+    if (!u->source) {
         pa_log("Failed to create source.");
         goto fail;
     }
@@ -1389,9 +1414,7 @@ int pa__init(pa_module*m) {
     u->source->userdata = u;
     u->source->set_state = source_set_state;
     u->source->get_latency = source_get_latency;
-    u->source->flags = PA_SOURCE_NETWORK|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("%s%s%s", u->source_name ? u->source_name : "", u->source_name ? " on " : "", u->server_name));
diff --git a/src/modules/module-volume-restore.c b/src/modules/module-volume-restore.c
index 192a2a7..0dc8dcf 100644
--- a/src/modules/module-volume-restore.c
+++ b/src/modules/module-volume-restore.c
@@ -115,7 +115,7 @@ static pa_cvolume* parse_volume(const char *s, pa_cvolume *v) {
 
         k = strtol(p, &p, 0);
 
-        if (k < PA_VOLUME_MUTED)
+        if (k < (long) PA_VOLUME_MUTED)
             return NULL;
 
         v->values[i] = (pa_volume_t) k;
@@ -280,10 +280,10 @@ finish:
 static char* client_name(pa_client *c) {
     char *t, *e;
 
-    if (!c->name || !c->driver)
+    if (!pa_proplist_gets(c->proplist, PA_PROP_APPLICATION_NAME) || !c->driver)
         return NULL;
 
-    t = pa_sprintf_malloc("%s$%s", c->driver, c->name);
+    t = pa_sprintf_malloc("%s$%s", c->driver, pa_proplist_gets(c->proplist, PA_PROP_APPLICATION_NAME));
     t[strcspn(t, "\n\r#")] = 0;
 
     if (!*t) {
diff --git a/src/modules/module-x11-bell.c b/src/modules/module-x11-bell.c
index 87c6849..761b82a 100644
--- a/src/modules/module-x11-bell.c
+++ b/src/modules/module-x11-bell.c
@@ -81,7 +81,7 @@ static int x11_event_callback(pa_x11_wrapper *w, XEvent *e, void *userdata) {
 
     bne = (XkbBellNotifyEvent*) e;
 
-    if (pa_scache_play_item_by_name(u->core, u->scache_item, u->sink_name, (bne->percent*PA_VOLUME_NORM)/100, 1) < 0) {
+    if (pa_scache_play_item_by_name(u->core, u->scache_item, u->sink_name, TRUE, (bne->percent*PA_VOLUME_NORM)/100, NULL, NULL) < 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);
     }
diff --git a/src/modules/module-zeroconf-publish.c b/src/modules/module-zeroconf-publish.c
index 46969a2..6ed8e3d 100644
--- a/src/modules/module-zeroconf-publish.c
+++ b/src/modules/module-zeroconf-publish.c
@@ -115,7 +115,7 @@ static void get_service_data(struct service *s, pa_sample_spec *ret_ss, pa_chann
         *ret_ss = sink->sample_spec;
         *ret_map = sink->channel_map;
         *ret_name = sink->name;
-        *ret_description = sink->description;
+        *ret_description = pa_strnull(pa_proplist_gets(sink->proplist, PA_PROP_DEVICE_DESCRIPTION));
         *ret_subtype = sink->flags & PA_SINK_HARDWARE ? SUBTYPE_HARDWARE : SUBTYPE_VIRTUAL;
 
     } else if (pa_source_isinstance(s->device)) {
@@ -124,7 +124,7 @@ static void get_service_data(struct service *s, pa_sample_spec *ret_ss, pa_chann
         *ret_ss = source->sample_spec;
         *ret_map = source->channel_map;
         *ret_name = source->name;
-        *ret_description = source->description;
+        *ret_description = pa_strnull(pa_proplist_gets(source->proplist, PA_PROP_DEVICE_DESCRIPTION));
         *ret_subtype = source->monitor_of ? SUBTYPE_MONITOR : (source->flags & PA_SOURCE_HARDWARE ? SUBTYPE_HARDWARE : SUBTYPE_VIRTUAL);
 
     } else
@@ -304,10 +304,10 @@ static struct service *get_service(struct userdata *u, pa_object *device) {
     s->device = device;
 
     if (pa_sink_isinstance(device)) {
-        if (!(n = PA_SINK(device)->description))
+        if (!(n = pa_proplist_gets(PA_SINK(device)->proplist, PA_PROP_DEVICE_DESCRIPTION)))
             n = PA_SINK(device)->name;
     } else {
-        if (!(n = PA_SOURCE(device)->description))
+        if (!(n = pa_proplist_gets(PA_SOURCE(device)->proplist, PA_PROP_DEVICE_DESCRIPTION)))
             n = PA_SOURCE(device)->name;
     }
 
@@ -578,11 +578,11 @@ int pa__init(pa_module*m) {
 
     u->services = pa_hashmap_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
 
-    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_new_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_PUT], (pa_hook_cb_t) device_new_or_changed_cb, u);
+    u->sink_changed_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_PROPLIST_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_new_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_PUT], (pa_hook_cb_t) device_new_or_changed_cb, u);
+    u->source_changed_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_PROPLIST_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;

commit b5c5064a594a4930d9b82752116cce5a11bdd81b
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sat Mar 15 15:24:36 2008 +0000

    commit glitch-free work
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2125 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/Makefile.am b/src/Makefile.am
index a3bb4d0..df2638c 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -695,7 +695,8 @@ libpulsecore_la_SOURCES = \
 		pulse/utf8.c pulse/utf8.h \
 		pulse/util.c pulse/util.h \
 		pulse/volume.c pulse/volume.h \
-		pulse/xmalloc.c pulse/xmalloc.h
+		pulse/xmalloc.c pulse/xmalloc.h \
+		pulse/proplist.c pulse/proplist.h
 
 # Pure core stuff (some are shared in libpulse though).
 libpulsecore_la_SOURCES += \
diff --git a/src/modules/alsa-util.h b/src/modules/alsa-util.h
index 53d9a2f..62c1d43 100644
--- a/src/modules/alsa-util.h
+++ b/src/modules/alsa-util.h
@@ -43,10 +43,12 @@ int pa_alsa_set_hw_params(
         pa_sample_spec *ss,
         uint32_t *periods,
         snd_pcm_uframes_t *period_size,
+        snd_pcm_uframes_t tsched_size,
         pa_bool_t *use_mmap,
+        pa_bool_t *use_tsched,
         pa_bool_t require_exact_channel_number);
 
-int pa_alsa_set_sw_params(snd_pcm_t *pcm);
+int pa_alsa_set_sw_params(snd_pcm_t *pcm, size_t avail_min);
 
 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);
@@ -59,7 +61,9 @@ snd_pcm_t *pa_alsa_open_by_device_id(
         int mode,
         uint32_t *nfrags,
         snd_pcm_uframes_t *period_size,
-        pa_bool_t *use_mmap);
+        snd_pcm_uframes_t tsched_size,
+        pa_bool_t *use_mmap,
+        pa_bool_t *use_tsched);
 
 snd_pcm_t *pa_alsa_open_by_device_string(
         const char *device,
@@ -69,8 +73,13 @@ snd_pcm_t *pa_alsa_open_by_device_string(
         int mode,
         uint32_t *nfrags,
         snd_pcm_uframes_t *period_size,
-        pa_bool_t *use_mmap);
+        snd_pcm_uframes_t tsched_size,
+        pa_bool_t *use_mmap,
+        pa_bool_t *use_tsched);
 
 int pa_alsa_calc_mixer_map(snd_mixer_elem_t *elem, const pa_channel_map *channel_map, snd_mixer_selem_channel_id_t mixer_map[], pa_bool_t playback);
 
+void pa_alsa_0dB_playback(snd_mixer_elem_t *elem);
+void pa_alsa_0dB_capture(snd_mixer_elem_t *elem);
+
 #endif
diff --git a/src/modules/rtp/module-rtp-recv.c b/src/modules/rtp/module-rtp-recv.c
index d8e7a78..be54c38 100644
--- a/src/modules/rtp/module-rtp-recv.c
+++ b/src/modules/rtp/module-rtp-recv.c
@@ -133,21 +133,17 @@ static int sink_input_process_msg(pa_msgobject *o, int code, void *data, int64_t
 }
 
 /* Called from I/O thread context */
-static int sink_input_peek(pa_sink_input *i, size_t length, pa_memchunk *chunk) {
+static int sink_input_pop(pa_sink_input *i, size_t length, pa_memchunk *chunk) {
     struct session *s;
     pa_sink_input_assert_ref(i);
     pa_assert_se(s = i->userdata);
 
-    return pa_memblockq_peek(s->memblockq, chunk);
-}
+    if (pa_memblockq_peek(s->memblockq, chunk) < 0)
+        return -1;
 
-/* Called from I/O thread context */
-static void sink_input_drop(pa_sink_input *i, size_t length) {
-    struct session *s;
-    pa_sink_input_assert_ref(i);
-    pa_assert_se(s = i->userdata);
+    pa_memblockq_drop(s->memblockq, chunk->length);
 
-    pa_memblockq_drop(s->memblockq, length);
+    return 0;
 }
 
 /* Called from main context */
@@ -354,12 +350,13 @@ static struct session *session_new(struct userdata *u, const pa_sdp_info *sdp_in
     pa_sink_input_new_data_init(&data);
     data.sink = sink;
     data.driver = __FILE__;
-    data.name = c;
+    pa_proplist_sets(data.proplist, PA_PROP_MEDIA_NAME, c);
+    pa_xfree(c);
     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->module->core, &data, 0);
-    pa_xfree(c);
+    pa_sink_input_new_data_done(&data);
 
     if (!s->sink_input) {
         pa_log("Failed to create sink input.");
@@ -369,8 +366,7 @@ static struct session *session_new(struct userdata *u, const pa_sdp_info *sdp_in
     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->pop = sink_input_pop;
     s->sink_input->kill = sink_input_kill;
     s->sink_input->attach = sink_input_attach;
     s->sink_input->detach = sink_input_detach;
@@ -387,6 +383,7 @@ static struct session *session_new(struct userdata *u, const pa_sdp_info *sdp_in
             pa_frame_size(&s->sink_input->sample_spec),
             pa_bytes_per_second(&s->sink_input->sample_spec)/10+1,
             0,
+            0,
             silence);
 
     pa_memblock_unref(silence);
diff --git a/src/modules/rtp/module-rtp-send.c b/src/modules/rtp/module-rtp-send.c
index 95ff15d..a441753 100644
--- a/src/modules/rtp/module-rtp-send.c
+++ b/src/modules/rtp/module-rtp-send.c
@@ -288,14 +288,17 @@ int pa__init(pa_module*m) {
     pa_make_fd_cloexec(sap_fd);
 
     pa_source_output_new_data_init(&data);
-    data.name = "RTP Monitor Stream";
+    pa_proplist_sets(data.proplist, PA_PROP_MEDIA_NAME, "RTP Monitor Stream");
     data.driver = __FILE__;
     data.module = m;
     data.source = s;
     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(m->core, &data, 0))) {
+    o = pa_source_output_new(m->core, &data, 0);
+    pa_source_output_new_data_done(&data);
+
+    if (!o) {
         pa_log("failed to create source output.");
         goto fail;
     }
@@ -318,6 +321,7 @@ int pa__init(pa_module*m) {
             pa_frame_size(&ss),
             1,
             0,
+            0,
             NULL);
 
     u->mtu = mtu;

commit 106ddb9211a98dec764ca45ca02b46c31354e631
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sat Mar 15 15:26:03 2008 +0000

    remaining bits and pieces
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2126 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/PROTOCOL b/PROTOCOL
index 497fa47..40863fc 100644
--- a/PROTOCOL
+++ b/PROTOCOL
@@ -78,3 +78,42 @@ New opcodes for notifications:
  PA_COMMAND_CAPTURE_STREAM_SUSPENDED
  PA_COMMAND_PLAYBACK_STREAM_MOVED
  PA_COMMAND_CAPTURE_STREAM_MOVED
+
+### v13, implemented  by >= 0.9.10
+
+New fields for PA_COMMAND_CREATE_PLAYBACK_STREAM, PA_COMMAND_CREATE_RECORD_STREAM request at the end:
+
+ peak_detect (bool)
+
+Replace field "name" for PA_COMMAND_CREATE_PLAYBACK_STREAM, PA_COMMAND_CREATE_RECORD_STREAM at the end:
+
+ proplist
+
+Replace field "name" for PA_COMMAND_SET_CLIENT_NAME request at the end:
+
+ proplist
+
+On response of PA_COMMAND_SET_CLIENT_NAME:
+
+ client_index
+
+New proplist field for sink, source, sink input, source output introspection opcodes and at the end:
+
+ proplist
+
+New opcodes for proplist modifications
+
+  PA_COMMAND_UPDATE_RECORD_STREAM_PROPLIST
+  PA_COMMAND_UPDATE_PLAYBACK_STREAM_PROPLIST
+  PA_COMMAND_UPDATE_CLIENT_PROPLIST
+  PA_COMMAND_REMOVE_RECORD_STREAM_PROPLIST
+  PA_COMMAND_REMOVE_PLAYBACK_STREAM_PROPLIST
+  PA_COMMAND_REMOVE_CLIENT_PROPLIST
+
+New field for PA_COMMAND_PLAY_SAMPLE:
+
+  proplist
+ 
+New field for PA_COMMAND_PLAY_SAMPLE response:
+
+  idx
diff --git a/configure.ac b/configure.ac
index ba8f2c9..748e8f0 100644
--- a/configure.ac
+++ b/configure.ac
@@ -257,6 +257,7 @@ AC_CHECK_TYPES(ssize_t, , [AC_DEFINE([ssize_t], [signed long],
 AC_TYPE_OFF_T
 AC_TYPE_SIGNAL
 AC_TYPE_UID_T
+AC_CHECK_DECLS(environ)
 
 AC_CHECK_DEFINE([SIGXCPU], [signal.h], [
 HAVE_SIGXCPU=1

commit 05a7f5d5bfa1c211725a75610919c8a2c0e0e89a
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Mar 27 21:15:29 2008 +0000

    bump revision
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/prepare-0.9.10@2136 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/configure.ac b/configure.ac
index 2c2a7a9..aad98fa 100644
--- a/configure.ac
+++ b/configure.ac
@@ -26,7 +26,7 @@ AC_PREREQ(2.57)
 
 m4_define(PA_MAJOR, [0])
 m4_define(PA_MINOR, [9])
-m4_define(PA_MICRO, [9])
+m4_define(PA_MICRO, [10])
 
 AC_INIT([pulseaudio], PA_MAJOR.PA_MINOR.PA_MICRO,[mzchyfrnhqvb (at) 0pointer (dot) net])
 AC_CONFIG_SRCDIR([src/daemon/main.c])

commit c59a90c6c16177c8b87b31529318a308e9de04f7
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Mar 27 21:20:07 2008 +0000

    merge r2078 from trunk
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/prepare-0.9.10@2137 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/core-util.c b/src/pulsecore/core-util.c
index fb032f2..61d04c2 100644
--- a/src/pulsecore/core-util.c
+++ b/src/pulsecore/core-util.c
@@ -1129,8 +1129,15 @@ FILE *pa_open_config_file(const char *global, const char *local, const char *env
 
         if ((e = getenv("PULSE_CONFIG_PATH")))
             fn = lfn = pa_sprintf_malloc("%s/%s", e, local);
-        else if (pa_get_home_dir(h, sizeof(h)))
+        else if (pa_get_home_dir(h, sizeof(h))) {
+            char *d;
+
+            d = pa_sprintf_malloc("%s/.pulse", h);
+            mkdir(d, 0755);
+            pa_xfree(d);
+
             fn = lfn = pa_sprintf_malloc("%s/.pulse/%s", h, local);
+        }
 
         if (lfn) {
             FILE *f;

commit 8d5ee5054b3d595adbcefaa2b01108de430666d1
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Mar 27 21:20:56 2008 +0000

    merge r2074 from trunk
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/prepare-0.9.10@2138 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulse/stream.c b/src/pulse/stream.c
index 9242082..cd70cdc 100644
--- a/src/pulse/stream.c
+++ b/src/pulse/stream.c
@@ -586,7 +586,7 @@ void pa_create_stream_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED
         }
     }
 
-    if (s->context->version >= 12) {
+    if (s->context->version >= 12 && s->direction != PA_STREAM_UPLOAD) {
         pa_sample_spec ss;
         pa_channel_map cm;
         const char *dn = NULL;

commit e721ecd4ff73b3c277609c52150e9cc1547d488e
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Mar 27 21:21:24 2008 +0000

    merge r2073 from trunk
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/prepare-0.9.10@2139 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/Makefile.am b/src/Makefile.am
index 158560d..2d710d4 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -604,7 +604,7 @@ noinst_LTLIBRARIES = libspeex-resampler-fixed.la libspeex-resampler-float.la lib
 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_CPPFLAGS = $(AM_CPPFLAGS) -DRANDOM_PREFIX=paspfl -DOUTSIDE_SPEEX -DFLOATING_POINT
 libspeex_resampler_float_la_SOURCES = pulsecore/speex/resample.c pulsecore/speex/speex_resampler.h pulsecore/speex/arch.h
 
 libffmpeg_resampler_la_CPPFLAGS = $(AM_CPPFLAGS)
diff --git a/src/pulsecore/speex/arch.h b/src/pulsecore/speex/arch.h
index 4be693c..9987c8f 100644
--- a/src/pulsecore/speex/arch.h
+++ b/src/pulsecore/speex/arch.h
@@ -35,6 +35,45 @@
 #ifndef ARCH_H
 #define ARCH_H
 
+#ifndef SPEEX_VERSION
+#define SPEEX_MAJOR_VERSION 1         /**< Major Speex version. */
+#define SPEEX_MINOR_VERSION 1         /**< Minor Speex version. */
+#define SPEEX_MICRO_VERSION 15        /**< Micro Speex version. */
+#define SPEEX_EXTRA_VERSION ""        /**< Extra Speex version. */
+#define SPEEX_VERSION "speex-1.2beta3"  /**< Speex version string. */
+#endif
+
+/* A couple test to catch stupid option combinations */
+#ifdef FIXED_POINT
+
+#ifdef FLOATING_POINT
+#error You cannot compile as floating point and fixed point at the same time
+#endif
+#ifdef _USE_SSE
+#error SSE is only for floating-point
+#endif
+#if ((defined (ARM4_ASM)||defined (ARM4_ASM)) && defined(BFIN_ASM)) || (defined (ARM4_ASM)&&defined(ARM5E_ASM))
+#error Make up your mind. What CPU do you have?
+#endif
+#ifdef VORBIS_PSYCHO
+#error Vorbis-psy model currently not implemented in fixed-point
+#endif
+
+#else
+
+#ifndef FLOATING_POINT
+#error You now need to define either FIXED_POINT or FLOATING_POINT
+#endif
+#if defined (ARM4_ASM) || defined(ARM5E_ASM) || defined(BFIN_ASM)
+#error I suppose you can have a [ARM4/ARM5E/Blackfin] that has float instructions?
+#endif
+#ifdef FIXED_POINT_DEBUG
+#error "Don't you think enabling fixed-point is a good thing to do if you want to debug that?"
+#endif
+
+
+#endif
+
 #ifndef OUTSIDE_SPEEX
 #include "speex/speex_types.h"
 #endif
@@ -68,6 +107,7 @@ typedef spx_word32_t spx_sig_t;
 #define LPC_SHIFT    13
 #define LSP_SHIFT    13
 #define SIG_SHIFT    14
+#define GAIN_SHIFT   6
 
 #define VERY_SMALL 0
 #define VERY_LARGE32 ((spx_word32_t)2147483647)
@@ -111,9 +151,6 @@ typedef float spx_word32_t;
 #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
@@ -194,4 +231,11 @@ typedef float spx_word32_t;
 
 #endif
 
+
+
+#ifdef FIXED_DEBUG
+long long spx_mips=0;
+#endif
+
+
 #endif
diff --git a/src/pulsecore/speex/resample.c b/src/pulsecore/speex/resample.c
index bf1f88b..1e59200 100644
--- a/src/pulsecore/speex/resample.c
+++ b/src/pulsecore/speex/resample.c
@@ -37,17 +37,23 @@
       - 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
+   Warning: This resampler is relatively new. Although I think I got rid of
+   all the major bugs and I don't expect the API to change anymore, there
+   may be something I've missed. So use with caution.
+
+   This algorithm is based on this original resampling algorithm:
+   Smith, Julius O. Digital Audio Resampling Home Page
+   Center for Computer Research in Music and Acoustics (CCRMA),
+   Stanford University, 2007.
+   Web published at http://www-ccrma.stanford.edu/~jos/resample/.
+
+   There is one main difference, though. This resampler uses cubic
+   interpolation instead of linear interpolation in the above paper. This
+   makes the table much smaller and makes it possible to compute that table
+   on a per-stream basis. In turn, being able to tweak the table for each
+   stream makes it possible to both reduce complexity on simple ratios
+   (e.g. 2/3), and get rid of the rounding operations in the inner loop.
+   The latter both reduces CPU time and makes the algorithm more SIMD-friendly.
 */
 
 #ifdef HAVE_CONFIG_H
@@ -64,7 +70,8 @@ static void speex_free (void *ptr) {free(ptr);}
 #else /* OUTSIDE_SPEEX */
 
 #include "speex/speex_resampler.h"
-#include "misc.h"
+#include "arch.h"
+#include "os_support.h"
 #endif /* OUTSIDE_SPEEX */
 
 #include <math.h>

commit aceb80043f9a36cabb944166a5c6b1e882056436
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Mar 27 21:21:59 2008 +0000

    merge r2075 from trunk
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/prepare-0.9.10@2140 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/configure.ac b/configure.ac
index aad98fa..467cf04 100644
--- a/configure.ac
+++ b/configure.ac
@@ -881,11 +881,11 @@ if test "x${polkit}" != xno ; then
         [
             HAVE_POLKIT=1
             saved_LIBS="$LIBS"
-            LIBS="$LIBS POLKIT_LIBS"
+            LIBS="$LIBS $POLKIT_LIBS"
             AC_CHECK_FUNCS(polkit_context_is_caller_authorized)
             LIBS="$saved_LIBS"
             AC_DEFINE([HAVE_POLKIT], 1, [Have PolicyKit])
-            policydir=`pkg-config --variable prefix`/usr/share/PolicyKit/policy/
+            policydir=`pkg-config polkit-dbus --variable prefix`/share/PolicyKit/policy/
             AC_SUBST(policydir)
         ],
         [

commit 5e1324981fc18542e3152000115d0693db33079e
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Mar 27 21:22:29 2008 +0000

    merge r2076 from trunk
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/prepare-0.9.10@2141 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/configure.ac b/configure.ac
index 467cf04..7e86fdf 100644
--- a/configure.ac
+++ b/configure.ac
@@ -836,7 +836,7 @@ if test "x$HAVE_HAL" = x1 ; then
    dbus=yes
 fi
 
-if test "x${dbus}" != xno ; then
+if test "x${dbus}" != xno || test "x${bluez}" != xno || "x${hal}" != xno ; then
 
     PKG_CHECK_MODULES(DBUS, [ dbus-1 >= 1.0.0 ],
         [
diff --git a/src/Makefile.am b/src/Makefile.am
index 2d710d4..dc3ba4f 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1424,8 +1424,8 @@ module_jack_source_la_CFLAGS = $(AM_CFLAGS) $(JACK_CFLAGS)
 # HAL
 libdbus_util_la_SOURCES = modules/dbus-util.c modules/dbus-util.h
 libdbus_util_la_LDFLAGS = -avoid-version
-libdbus_util_la_LIBADD = $(AM_LIBADD) $(HAL_LIBS) libpulsecore.la
-libdbus_util_la_CFLAGS = $(AM_CFLAGS) $(HAL_CFLAGS)
+libdbus_util_la_LIBADD = $(AM_LIBADD) $(DBUS_LIBS) libpulsecore.la
+libdbus_util_la_CFLAGS = $(AM_CFLAGS) $(DBUS_CFLAGS)
 
 module_hal_detect_la_SOURCES = modules/module-hal-detect.c
 module_hal_detect_la_LDFLAGS = -module -avoid-version

commit a86a48c489c84781328d7eb5ced94692679b7d8b
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Mar 27 21:22:59 2008 +0000

    merge r2077 from trunk
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/prepare-0.9.10@2142 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/configure.ac b/configure.ac
index 7e86fdf..30a1471 100644
--- a/configure.ac
+++ b/configure.ac
@@ -79,6 +79,10 @@ esac
 
 #### Checks for programs. ####
 
+# mkdir -p
+
+AC_PROG_MKDIR_P
+
 # CC
 
 AC_PROG_CC
diff --git a/src/Makefile.am b/src/Makefile.am
index dc3ba4f..84649c4 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1151,9 +1151,9 @@ EXTRA_DIST += $(SYMDEF_FILES)
 BUILT_SOURCES += $(SYMDEF_FILES)
 
 $(SYMDEF_FILES): modules/module-defs.h.m4
-	-mkdir modules
-	-mkdir modules/gconf
-	-mkdir modules/rtp
+	$(MKDIR_P) modules
+	$(MKDIR_P) modules/gconf
+	$(MKDIR_P) modules/rtp
 	$(M4) -Dfname="$@" $< > $@
 
 # Simple protocol

commit 0e23606cf9bf8141f24fed9158dd36e6ba8e20ac
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Mar 27 21:24:03 2008 +0000

    merge r2079 from trunk
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/prepare-0.9.10@2143 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/endianmacros.h b/src/pulsecore/endianmacros.h
index 05d3262..6b80246 100644
--- a/src/pulsecore/endianmacros.h
+++ b/src/pulsecore/endianmacros.h
@@ -47,12 +47,20 @@
 #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
 
+static inline float PA_FLOAT32_SWAP(float x) {
+    uint32_t i = *(uint32_t*) &x;
+    i = PA_UINT32_SWAP(i);
+    return *(float*) &i;
+}
+
 #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 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)
 
+#define PA_MAYBE_FLOAT32_SWAP(c,x) ((c) ? PA_FLOAT32_SWAP(x) : x)
+
 #ifdef WORDS_BIGENDIAN
  #define PA_INT16_FROM_LE(x) PA_INT16_SWAP(x)
  #define PA_INT16_FROM_BE(x) ((int16_t)(x))
@@ -77,6 +85,9 @@
 
  #define PA_UINT32_TO_LE(x) PA_UINT32_SWAP(x)
  #define PA_UINT32_TO_BE(x) ((uint32_t)(x))
+
+ #define PA_FLOAT32_TO_LE(x) PA_FLOAT32_SWAP(x)
+ #define PA_FLOAT32_TO_BE(x) ((float) (x))
 #else
  #define PA_INT16_FROM_LE(x) ((int16_t)(x))
  #define PA_INT16_FROM_BE(x) PA_INT16_SWAP(x)
@@ -101,6 +112,9 @@
 
  #define PA_UINT32_TO_LE(x) ((uint32_t)(x))
  #define PA_UINT32_TO_BE(x) PA_UINT32_SWAP(x)
+
+ #define PA_FLOAT32_TO_LE(x) ((float) (x))
+ #define PA_FLOAT32_TO_BE(x) PA_FLOAT32_SWAP(x)
 #endif
 
 #endif

commit cefa0eb9d9d32a90678253d7a22887ef65a2c535
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Mar 27 21:24:48 2008 +0000

    merge r2081 from trunk
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/prepare-0.9.10@2144 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulse/context.c b/src/pulse/context.c
index bc960e2..7243a29 100644
--- a/src/pulse/context.c
+++ b/src/pulse/context.c
@@ -50,12 +50,12 @@
 #include <netdb.h>
 #endif
 
-#include "../pulsecore/winsock.h"
-
-#include <pulsecore/core-error.h>
 #include <pulse/version.h>
 #include <pulse/xmalloc.h>
 
+#include <pulsecore/winsock.h>
+#include <pulsecore/core-error.h>
+
 #include <pulsecore/native-common.h>
 #include <pulsecore/pdispatch.h>
 #include <pulsecore/pstream.h>

commit d0551273646b1f26126a5311db4efd4e4cd847f1
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Mar 27 23:16:29 2008 +0000

    merge r2083 from trunk
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/prepare-0.9.10@2147 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/configure.ac b/configure.ac
index 30a1471..aa0922e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -982,6 +982,12 @@ fi
 AC_SUBST(PA_ACCESS_GROUP)
 AC_DEFINE_UNQUOTED(PA_ACCESS_GROUP,"$PA_ACCESS_GROUP", [Access group])
 
+AC_ARG_WITH(peruser_esound, AS_HELP_STRING([--with-peruser-esound-socket], [Use per-user esound socket directory, like /tmp/.esd-UID/socket.]))
+
+if test "x$with_peruser_esound" = "xyes"; then
+   AC_DEFINE([USE_PERUSER_ESOUND_SOCKET], [1], [Define this if you want per-user esound socket directories])
+fi
+
 #### PulseAudio system runtime dir ####
 PA_SYSTEM_RUNTIME_PATH="${localstatedir}/run/pulse"
 AC_SUBST(PA_SYSTEM_RUNTIME_PATH)
diff --git a/src/modules/module-protocol-stub.c b/src/modules/module-protocol-stub.c
index 207e266..a9bd850 100644
--- a/src/modules/module-protocol-stub.c
+++ b/src/modules/module-protocol-stub.c
@@ -218,7 +218,11 @@ int pa__init(pa_module*m) {
     char tmp[PATH_MAX];
 
 #if defined(USE_PROTOCOL_ESOUND)
-    char tmp2[PATH_MAX];
+#if defined(USE_PERUSER_ESOUND_SOCKET)
+    char esdsocketpath[PATH_MAX];
+#else
+    const char esdsocketpath[] = "/tmp/.esd/socket";
+#endif
 #endif
 #endif
 
@@ -265,8 +269,10 @@ int pa__init(pa_module*m) {
 
 #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));
+#if defined(USE_PERUSER_ESOUND_SOCKET)
+    snprintf(esdsocketpath, sizeof(esdsocketpath), "/tmp/.esd-%lu/socket", (unsigned long) getuid());
+#endif
+    pa_runtime_path(pa_modargs_get_value(ma, "socket", esdsocketpath), tmp, sizeof(tmp));
     u->socket_path = pa_xstrdup(tmp);
 
     /* This socket doesn't reside in our own runtime dir but in

commit 66d9e87391449497699d05f0ea24efc595c4a7ac
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Mar 27 23:17:13 2008 +0000

    merge r2145 from trunk
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/prepare-0.9.10@2148 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/configure.ac b/configure.ac
index aa0922e..89910ad 100644
--- a/configure.ac
+++ b/configure.ac
@@ -982,10 +982,20 @@ fi
 AC_SUBST(PA_ACCESS_GROUP)
 AC_DEFINE_UNQUOTED(PA_ACCESS_GROUP,"$PA_ACCESS_GROUP", [Access group])
 
-AC_ARG_WITH(peruser_esound, AS_HELP_STRING([--with-peruser-esound-socket], [Use per-user esound socket directory, like /tmp/.esd-UID/socket.]))
+AC_ARG_ENABLE(
+        per_user_esound_socket,
+        AS_HELP_STRING([--disable-per-user-esound-socket], [Use per-user esound socket directory, like /tmp/.esd-UID/socket.]),
+        [
+            case "${enableval}" in
+                yes) per_user_esound_socket=1 ;;
+                no) per_user_esound_socket=0 ;;
+                *) AC_MSG_ERROR(bad value ${enableval} for --disable-per-user-esound-socket) ;;
+            esac
+        ],
+        [per_user_esound_socket=1])
 
-if test "x$with_peruser_esound" = "xyes"; then
-   AC_DEFINE([USE_PERUSER_ESOUND_SOCKET], [1], [Define this if you want per-user esound socket directories])
+if test "x$per_user_esound_socket" = "x1"; then
+   AC_DEFINE([USE_PER_USER_ESOUND_SOCKET], [1], [Define this if you want per-user esound socket directories])
 fi
 
 #### PulseAudio system runtime dir ####
@@ -1119,32 +1129,38 @@ if test "x${HAVE_POLKIT}" = "x1" ; then
    ENABLE_POLKIT=yes
 fi
 
+ENABLE_PER_USER_ESOUND_SOCKET=no
+if test "x$per_user_esound_socket" = "x1" ; then
+   ENABLE_PER_USER_ESOUND_SOCKET=yes
+fi
+
 echo "
  ---{ $PACKAGE_NAME $VERSION }---
 
-    prefix:                 ${prefix}
-    sysconfdir:             ${sysconfdir}
-    localstatedir:          ${localstatedir}
-    System Runtime Path:    ${PA_SYSTEM_RUNTIME_PATH}
-    Compiler:               ${CC}
-    CFLAGS:                 ${CFLAGS}
-    Have X11:               ${ENABLE_X11}
-    Enable OSS:             ${ENABLE_OSS}
-    Enable Alsa:            ${ENABLE_ALSA}
-    Enable Solaris:         ${ENABLE_SOLARIS}
-    Enable GLib 2.0:        ${ENABLE_GLIB20}
-    Enable GConf:           ${ENABLE_GCONF}
-    Enable Avahi:           ${ENABLE_AVAHI}
-    Enable Jack:            ${ENABLE_JACK}
-    Enable Async DNS:       ${ENABLE_LIBASYNCNS}
-    Enable LIRC:            ${ENABLE_LIRC}
-    Enable HAL:             ${ENABLE_HAL}
-    Enable BlueZ:           ${ENABLE_BLUEZ}
-    Enable TCP Wrappers:    ${ENABLE_TCPWRAP}
-    Enable libsamplerate:   ${ENABLE_LIBSAMPLERATE}
-    Enable PolicyKit:       ${ENABLE_POLKIT}
-    System User:            ${PA_SYSTEM_USER}
-    System Group:           ${PA_SYSTEM_GROUP}
-    Realtime Group:         ${PA_REALTIME_GROUP}
-    Access Group:           ${PA_ACCESS_GROUP}
+    prefix:                        ${prefix}
+    sysconfdir:                    ${sysconfdir}
+    localstatedir:                 ${localstatedir}
+    System Runtime Path:           ${PA_SYSTEM_RUNTIME_PATH}
+    Compiler:                      ${CC}
+    CFLAGS:                        ${CFLAGS}
+    Have X11:                      ${ENABLE_X11}
+    Enable OSS:                    ${ENABLE_OSS}
+    Enable Alsa:                   ${ENABLE_ALSA}
+    Enable Solaris:                ${ENABLE_SOLARIS}
+    Enable GLib 2.0:               ${ENABLE_GLIB20}
+    Enable GConf:                  ${ENABLE_GCONF}
+    Enable Avahi:                  ${ENABLE_AVAHI}
+    Enable Jack:                   ${ENABLE_JACK}
+    Enable Async DNS:              ${ENABLE_LIBASYNCNS}
+    Enable LIRC:                   ${ENABLE_LIRC}
+    Enable HAL:                    ${ENABLE_HAL}
+    Enable BlueZ:                  ${ENABLE_BLUEZ}
+    Enable TCP Wrappers:           ${ENABLE_TCPWRAP}
+    Enable libsamplerate:          ${ENABLE_LIBSAMPLERATE}
+    Enable PolicyKit:              ${ENABLE_POLKIT}
+    System User:                   ${PA_SYSTEM_USER}
+    System Group:                  ${PA_SYSTEM_GROUP}
+    Realtime Group:                ${PA_REALTIME_GROUP}
+    Access Group:                  ${PA_ACCESS_GROUP}
+    Enable per-user EsounD socket: ${ENABLE_PER_USER_ESOUND_SOCKET}
 "
diff --git a/src/modules/module-protocol-stub.c b/src/modules/module-protocol-stub.c
index a9bd850..600201b 100644
--- a/src/modules/module-protocol-stub.c
+++ b/src/modules/module-protocol-stub.c
@@ -218,7 +218,7 @@ int pa__init(pa_module*m) {
     char tmp[PATH_MAX];
 
 #if defined(USE_PROTOCOL_ESOUND)
-#if defined(USE_PERUSER_ESOUND_SOCKET)
+#if defined(USE_PER_USER_ESOUND_SOCKET)
     char esdsocketpath[PATH_MAX];
 #else
     const char esdsocketpath[] = "/tmp/.esd/socket";
@@ -269,9 +269,10 @@ int pa__init(pa_module*m) {
 
 #if defined(USE_PROTOCOL_ESOUND)
 
-#if defined(USE_PERUSER_ESOUND_SOCKET)
+#if defined(USE_PER_USER_ESOUND_SOCKET)
     snprintf(esdsocketpath, sizeof(esdsocketpath), "/tmp/.esd-%lu/socket", (unsigned long) getuid());
 #endif
+
     pa_runtime_path(pa_modargs_get_value(ma, "socket", esdsocketpath), tmp, sizeof(tmp));
     u->socket_path = pa_xstrdup(tmp);
 

commit f10b531df0dccc39c4340b9725e4bde74fbde8c7
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Mar 27 23:18:08 2008 +0000

    merge r2084 from trunk
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/prepare-0.9.10@2149 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/cli-command.c b/src/pulsecore/cli-command.c
index 9bd1b50..3110a27 100644
--- a/src/pulsecore/cli-command.c
+++ b/src/pulsecore/cli-command.c
@@ -1363,7 +1363,7 @@ int pa_cli_command_execute_line(pa_core *c, const char *s, pa_strbuf *buf, pa_bo
 }
 
 int pa_cli_command_execute_file(pa_core *c, const char *fn, pa_strbuf *buf, pa_bool_t *fail) {
-    char line[256];
+    char line[1024];
     FILE *f = NULL;
     int ifstate = IFSTATE_NONE;
     int ret = -1;

commit 9f0045a9657c790a80546efb3134e496d9574271
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Mar 27 23:18:27 2008 +0000

    merge r2090 from trunk
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/prepare-0.9.10@2150 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/gccmacro.h b/src/pulsecore/gccmacro.h
index f164665..f94a8c4 100644
--- a/src/pulsecore/gccmacro.h
+++ b/src/pulsecore/gccmacro.h
@@ -79,7 +79,7 @@
 
 #ifndef PA_LIKELY
 #ifdef __GNUC__
-#define PA_LIKELY(x) (__builtin_expect((x),1))
+#define PA_LIKELY(x) (__builtin_expect(!!(x),1))
 #define PA_UNLIKELY(x) (__builtin_expect((x),0))
 #else
 #define PA_LIKELY(x) (x)

commit db208e34d375f8ec6eac9abaabf6fa40e93366c7
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Mar 27 23:18:52 2008 +0000

    merge r2091 from trunk
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/prepare-0.9.10@2151 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-ladspa-sink.c b/src/modules/module-ladspa-sink.c
index 50cdc45..d4351b2 100644
--- a/src/modules/module-ladspa-sink.c
+++ b/src/modules/module-ladspa-sink.c
@@ -396,7 +396,7 @@ int pa__init(pa_module*m) {
             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]);
+            pa_log_debug("Ignored control output port \"%s\".", d->PortNames[p]);
         }
     }
 

commit cc59e76b736fb122a0747e6707ebbee34ea6e64f
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Mar 27 23:22:57 2008 +0000

    merge r2092,r2093,r2094,r2152 from trunk
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/prepare-0.9.10@2153 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-ladspa-sink.c b/src/modules/module-ladspa-sink.c
index d4351b2..fcfeffd 100644
--- a/src/modules/module-ladspa-sink.c
+++ b/src/modules/module-ladspa-sink.c
@@ -441,7 +441,7 @@ int pa__init(pa_module*m) {
         use_default = pa_xnew(pa_bool_t, n_control);
         p = 0;
 
-        while ((k = pa_split(cdata, ",", &state))) {
+        while ((k = pa_split(cdata, ",", &state)) && p < n_control) {
             float f;
 
             if (*k == 0) {
@@ -458,15 +458,24 @@ int pa__init(pa_module*m) {
 
             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;
         }
 
+        /* The previous loop doesn't take the last control value into account
+           if it is left empty, so we do it here. */
+        if (*cdata == 0 || cdata[strlen(cdata) - 1] == ',') {
+            if (p < n_control)
+                use_default[p] = TRUE;
+            p++;
+        }
+
+        if (p > n_control || k) {
+            pa_log("Too many control values passed, %lu expected.", n_control);
+            pa_xfree(k);
+            goto fail;
+        }
+
         if (p < n_control) {
             pa_log("Not enough control values passed, %lu expected, %lu passed.", n_control, p);
             goto fail;

commit 9dfbfceea3e2a2767e23753b509d32b7b8ca90aa
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Mar 27 23:23:24 2008 +0000

    merge r2095 from trunk
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/prepare-0.9.10@2154 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/rtpoll.c b/src/pulsecore/rtpoll.c
index 354c4c0..8300826 100644
--- a/src/pulsecore/rtpoll.c
+++ b/src/pulsecore/rtpoll.c
@@ -161,8 +161,10 @@ void pa_rtpoll_install(pa_rtpoll *p) {
     p->installed = 1;
 
 #ifdef HAVE_PPOLL
+# ifdef __linux__
     if (p->dont_use_ppoll)
         return;
+# endif
 
     if ((p->rtsig = pa_rtsig_get_for_thread()) < 0) {
         pa_log_warn("Failed to reserve POSIX realtime signal.");
diff --git a/src/tests/rtpoll-test.c b/src/tests/rtpoll-test.c
index 3ab992a..e649377 100644
--- a/src/tests/rtpoll-test.c
+++ b/src/tests/rtpoll-test.c
@@ -49,7 +49,9 @@ int main(int argc, char *argv[]) {
     pa_rtpoll_item *i, *w;
     struct pollfd *pollfd;
 
+#ifdef SIGRTMIN
     pa_rtsig_configure(SIGRTMIN+10, SIGRTMAX);
+#endif
 
     p = pa_rtpoll_new();
 

commit 640033ae24a627ef4c84513b891ddbc31bad82b5
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Mar 27 23:23:58 2008 +0000

    merge r2096 from trunk
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/prepare-0.9.10@2155 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-tunnel.c b/src/modules/module-tunnel.c
index 05cece7..a53e393 100644
--- a/src/modules/module-tunnel.c
+++ b/src/modules/module-tunnel.c
@@ -129,6 +129,8 @@ static void command_subscribe_event(pa_pdispatch *pd, uint32_t command, uint32_t
 static void command_stream_killed(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
 static void command_overflow(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
 static void command_underflow(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 void command_moved(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] = {
 #ifdef TUNNEL_SINK
@@ -139,6 +141,10 @@ static const pa_pdispatch_cb_t command_table[PA_COMMAND_MAX] = {
     [PA_COMMAND_UNDERFLOW] = command_underflow,
     [PA_COMMAND_PLAYBACK_STREAM_KILLED] = command_stream_killed,
     [PA_COMMAND_RECORD_STREAM_KILLED] = command_stream_killed,
+    [PA_COMMAND_PLAYBACK_STREAM_SUSPENDED] = command_suspend,
+    [PA_COMMAND_RECORD_STREAM_SUSPENDED] = command_suspend,
+    [PA_COMMAND_PLAYBACK_STREAM_MOVED] = command_moved,
+    [PA_COMMAND_RECORD_STREAM_MOVED] = command_moved,
 };
 
 struct userdata {
@@ -226,6 +232,28 @@ static void command_underflow(pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command,
     pa_log_warn("Server signalled buffer underrun.");
 }
 
+static void command_suspend(pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) {
+    struct userdata *u = userdata;
+
+    pa_assert(pd);
+    pa_assert(t);
+    pa_assert(u);
+    pa_assert(u->pdispatch == pd);
+
+    pa_log_debug("Server reports a stream suspension.");
+}
+
+static void command_moved(pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) {
+    struct userdata *u = userdata;
+
+    pa_assert(pd);
+    pa_assert(t);
+    pa_assert(u);
+    pa_assert(u->pdispatch == pd);
+
+    pa_log_debug("Server reports a stream move.");
+}
+
 static void stream_cork(struct userdata *u, pa_bool_t cork) {
     pa_tagstruct *t;
     pa_assert(u);
@@ -1058,6 +1086,18 @@ static void setup_complete_callback(pa_pdispatch *pd, uint32_t command, uint32_t
     pa_tagstruct_putu32(reply, u->fragsize);
 #endif
 
+    /* New flags added in 0.9.8 */
+    if (u->version >= 12) {
+        /* TODO: set these to useful values */
+        pa_tagstruct_put_boolean(reply, FALSE); /*no_remap*/
+        pa_tagstruct_put_boolean(reply, FALSE); /*no_remix*/
+        pa_tagstruct_put_boolean(reply, FALSE); /*fix_format*/
+        pa_tagstruct_put_boolean(reply, FALSE); /*fix_rate*/
+        pa_tagstruct_put_boolean(reply, FALSE); /*fix_channels*/
+        pa_tagstruct_put_boolean(reply, FALSE); /*no_move*/
+        pa_tagstruct_put_boolean(reply, FALSE); /*variable_rate*/
+    }
+
     pa_pstream_send_tagstruct(u->pstream, reply);
     pa_pdispatch_register_reply(u->pdispatch, tag, DEFAULT_TIMEOUT, create_stream_callback, u, NULL);
 

commit 27353094f4672d9c6e6c0a4d1c27847625632963
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Mar 27 23:24:27 2008 +0000

    merge r2097 from trunk
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/prepare-0.9.10@2156 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c
index 46405f1..4f58279 100644
--- a/src/pulsecore/protocol-native.c
+++ b/src/pulsecore/protocol-native.c
@@ -1069,6 +1069,9 @@ static void sink_input_suspend_cb(pa_sink_input *i, pa_bool_t suspend) {
     s = PLAYBACK_STREAM(i->userdata);
     playback_stream_assert_ref(s);
 
+    if (s->connection->version < 12)
+      return;
+
     t = pa_tagstruct_new(NULL, 0);
     pa_tagstruct_putu32(t, PA_COMMAND_PLAYBACK_STREAM_SUSPENDED);
     pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
@@ -1086,6 +1089,9 @@ static void sink_input_moved_cb(pa_sink_input *i) {
     s = PLAYBACK_STREAM(i->userdata);
     playback_stream_assert_ref(s);
 
+    if (s->connection->version < 12)
+      return;
+
     t = pa_tagstruct_new(NULL, 0);
     pa_tagstruct_putu32(t, PA_COMMAND_PLAYBACK_STREAM_MOVED);
     pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
@@ -1142,6 +1148,9 @@ static void source_output_suspend_cb(pa_source_output *o, pa_bool_t suspend) {
     s = RECORD_STREAM(o->userdata);
     record_stream_assert_ref(s);
 
+    if (s->connection->version < 12)
+      return;
+
     t = pa_tagstruct_new(NULL, 0);
     pa_tagstruct_putu32(t, PA_COMMAND_RECORD_STREAM_SUSPENDED);
     pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
@@ -1159,6 +1168,9 @@ static void source_output_moved_cb(pa_source_output *o) {
     s = RECORD_STREAM(o->userdata);
     record_stream_assert_ref(s);
 
+    if (s->connection->version < 12)
+      return;
+
     t = pa_tagstruct_new(NULL, 0);
     pa_tagstruct_putu32(t, PA_COMMAND_RECORD_STREAM_MOVED);
     pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */

commit a451de1384534014712a1b926d5a23c5e52b276d
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Mar 27 23:25:08 2008 +0000

    merge r2098 from trunk
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/prepare-0.9.10@2157 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulse/sample.h b/src/pulse/sample.h
index 8f9f173..f0b839f 100644
--- a/src/pulse/sample.h
+++ b/src/pulse/sample.h
@@ -27,6 +27,7 @@
 
 #include <inttypes.h>
 #include <sys/types.h>
+#include <sys/param.h>
 #include <math.h>
 
 #include <pulse/cdecl.h>
@@ -104,6 +105,14 @@
 
 PA_C_DECL_BEGIN
 
+#if !defined(WORDS_BIGENDIAN)
+#if defined(__BYTE_ORDER)
+#if __BYTE_ORDER == __BIG_ENDIAN
+#define WORDS_BIGENDIAN
+#endif
+#endif
+#endif
+
 /** Maximum number of allowed channels */
 #define PA_CHANNELS_MAX 32
 

commit b0a20498dbdaf0af981f5351b6295a33a3fa7121
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Mar 27 23:27:34 2008 +0000

    merge r2104 from trunk
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/prepare-0.9.10@2158 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/daemon/cmdline.c b/src/daemon/cmdline.c
index cfd2c84..f1e1282 100644
--- a/src/daemon/cmdline.c
+++ b/src/daemon/cmdline.c
@@ -70,7 +70,7 @@ enum {
 };
 
 /* Tabel for getopt_long() */
-static struct option long_options[] = {
+static const struct option long_options[] = {
     {"help",                        0, 0, ARG_HELP},
     {"version",                     0, 0, ARG_VERSION},
     {"dump-conf",                   0, 0, ARG_DUMP_CONF},

commit b79c6b6bc0546f6e1c3b032f67d244c68ba20808
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Mar 27 23:29:32 2008 +0000

    merge r2105 from trunk
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/prepare-0.9.10@2159 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/alsa-util.c b/src/modules/alsa-util.c
index 40170e9..6afec3b 100644
--- a/src/modules/alsa-util.c
+++ b/src/modules/alsa-util.c
@@ -615,8 +615,10 @@ snd_pcm_t *pa_alsa_open_by_device_string(
 
         *dev = d;
 
-        if (ss->channels != map->channels)
+        if (ss->channels != map->channels) {
+            pa_assert_se(pa_channel_map_init_auto(map, ss->channels, PA_CHANNEL_MAP_AUX));
             pa_channel_map_init_auto(map, ss->channels, PA_CHANNEL_MAP_ALSA);
+        }
 
         return pcm_handle;
     }
diff --git a/src/modules/module-combine.c b/src/modules/module-combine.c
index dd81653..996cd4f 100644
--- a/src/modules/module-combine.c
+++ b/src/modules/module-combine.c
@@ -988,8 +988,10 @@ int pa__init(pa_module*m) {
 
     if (master_sink && ss.channels == master_sink->sample_spec.channels)
         map = master_sink->channel_map;
-    else
+    else {
+        pa_assert_se(pa_channel_map_init_auto(&map, ss.channels, PA_CHANNEL_MAP_AUX));
         pa_channel_map_init_auto(&map, ss.channels, PA_CHANNEL_MAP_DEFAULT);
+    }
 
     if ((pa_modargs_get_channel_map(ma, NULL, &map) < 0)) {
         pa_log("Invalid channel map.");
diff --git a/src/modules/module-jack-sink.c b/src/modules/module-jack-sink.c
index 46e128c..a42aa9e 100644
--- a/src/modules/module-jack-sink.c
+++ b/src/modules/module-jack-sink.c
@@ -333,6 +333,7 @@ int pa__init(pa_module*m) {
         goto fail;
     }
 
+    pa_assert_se(pa_channel_map_init_auto(&map, channels, PA_CHANNEL_MAP_AUX));
     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.");
diff --git a/src/modules/module-jack-source.c b/src/modules/module-jack-source.c
index f81c719..4ee08bf 100644
--- a/src/modules/module-jack-source.c
+++ b/src/modules/module-jack-source.c
@@ -304,6 +304,7 @@ int pa__init(pa_module*m) {
         goto fail;
     }
 
+    pa_assert_se(pa_channel_map_init_auto(&map, channels, PA_CHANNEL_MAP_AUX));
     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.");
diff --git a/src/modules/module-zeroconf-discover.c b/src/modules/module-zeroconf-discover.c
index 061560c..4e76f44 100644
--- a/src/modules/module-zeroconf-discover.c
+++ b/src/modules/module-zeroconf-discover.c
@@ -164,6 +164,7 @@ static void resolver_cb(
         pa_module *m;
 
         ss = u->core->default_sample_spec;
+        pa_assert_se(pa_channel_map_init_auto(&cm, ss.channels, PA_CHANNEL_MAP_AUX));
         pa_channel_map_init_auto(&cm, ss.channels, PA_CHANNEL_MAP_DEFAULT);
 
         for (l = txt; l; l = l->next) {
@@ -189,8 +190,10 @@ static void resolver_cb(
             avahi_free(value);
         }
 
-        if (!channel_map_set && cm.channels != ss.channels)
+        if (!channel_map_set && cm.channels != ss.channels) {
+            pa_assert_se(pa_channel_map_init_auto(&cm, ss.channels, PA_CHANNEL_MAP_AUX));
             pa_channel_map_init_auto(&cm, ss.channels, PA_CHANNEL_MAP_DEFAULT);
+        }
 
         if (!pa_sample_spec_valid(&ss)) {
             pa_log("Service '%s' contains an invalid sample specification.", name);
diff --git a/src/pulse/stream.c b/src/pulse/stream.c
index cd70cdc..c44323f 100644
--- a/src/pulse/stream.c
+++ b/src/pulse/stream.c
@@ -46,6 +46,7 @@
 pa_stream *pa_stream_new(pa_context *c, const char *name, const pa_sample_spec *ss, const pa_channel_map *map) {
     pa_stream *s;
     int i;
+    pa_channel_map tmap;
 
     pa_assert(c);
     pa_assert(PA_REFCNT_VALUE(c) >= 1);
@@ -54,6 +55,9 @@ pa_stream *pa_stream_new(pa_context *c, const char *name, const pa_sample_spec *
     PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 12 || (ss->format != PA_SAMPLE_S32LE || ss->format != PA_SAMPLE_S32NE), PA_ERR_NOTSUPPORTED);
     PA_CHECK_VALIDITY_RETURN_NULL(c, !map || (pa_channel_map_valid(map) && map->channels == ss->channels), PA_ERR_INVALID);
 
+    if (!map)
+        PA_CHECK_VALIDITY_RETURN_NULL(c, map = pa_channel_map_init_auto(&tmap, ss->channels, PA_CHANNEL_MAP_DEFAULT), PA_ERR_INVALID);
+
     s = pa_xnew(pa_stream, 1);
     PA_REFCNT_INIT(s);
     s->context = c;
@@ -81,13 +85,9 @@ pa_stream *pa_stream_new(pa_context *c, const char *name, const pa_sample_spec *
     s->direction = PA_STREAM_NODIRECTION;
     s->name = pa_xstrdup(name);
     s->sample_spec = *ss;
+    s->channel_map = *map;
     s->flags = 0;
 
-    if (map)
-        s->channel_map = *map;
-    else
-        pa_channel_map_init_auto(&s->channel_map, ss->channels, PA_CHANNEL_MAP_DEFAULT);
-
     s->channel = 0;
     s->channel_valid = 0;
     s->syncid = c->csyncid++;
diff --git a/src/pulsecore/core-scache.c b/src/pulsecore/core-scache.c
index 732d90d..46444a9 100644
--- a/src/pulsecore/core-scache.c
+++ b/src/pulsecore/core-scache.c
@@ -145,9 +145,16 @@ 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];
+    pa_channel_map tmap;
 
     pa_assert(c);
     pa_assert(name);
+    pa_assert(!ss || pa_sample_spec_valid(ss));
+    pa_assert(!map || (pa_channel_map_valid(map) && ss && ss->channels == map->channels));
+
+    if (ss && !map)
+        if (!(map = pa_channel_map_init_auto(&tmap, ss->channels, PA_CHANNEL_MAP_DEFAULT)))
+            return -1;
 
     if (chunk && chunk->length > PA_SCACHE_ENTRY_SIZE_MAX)
         return -1;
@@ -155,9 +162,11 @@ int pa_scache_add_item(pa_core *c, const char *name, const pa_sample_spec *ss, c
     if (!(e = scache_add_item(c, name)))
         return -1;
 
+    memset(&e->sample_spec, 0, sizeof(e->sample_spec));
+    pa_channel_map_init(&e->channel_map);
+
     if (ss) {
         e->sample_spec = *ss;
-        pa_channel_map_init_auto(&e->channel_map, ss->channels, PA_CHANNEL_MAP_DEFAULT);
         e->volume.channels = e->sample_spec.channels;
     }
 
diff --git a/src/pulsecore/resampler.c b/src/pulsecore/resampler.c
index 429759f..7a93cee 100644
--- a/src/pulsecore/resampler.c
+++ b/src/pulsecore/resampler.c
@@ -215,13 +215,13 @@ pa_resampler* pa_resampler_new(
 
     if (am)
         r->i_cm = *am;
-    else
-        pa_channel_map_init_auto(&r->i_cm, r->i_ss.channels, PA_CHANNEL_MAP_DEFAULT);
+    else if (!pa_channel_map_init_auto(&r->i_cm, r->i_ss.channels, PA_CHANNEL_MAP_DEFAULT))
+        goto fail;
 
     if (bm)
         r->o_cm = *bm;
-    else
-        pa_channel_map_init_auto(&r->o_cm, r->o_ss.channels, PA_CHANNEL_MAP_DEFAULT);
+    else if (!pa_channel_map_init_auto(&r->o_cm, r->o_ss.channels, PA_CHANNEL_MAP_DEFAULT))
+        goto fail;
 
     r->i_fz = pa_frame_size(a);
     r->o_fz = pa_frame_size(b);
diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c
index ec0914e..07ddb83 100644
--- a/src/pulsecore/sink-input.c
+++ b/src/pulsecore/sink-input.c
@@ -120,7 +120,7 @@ pa_sink_input* pa_sink_input_new(
         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);
+            pa_return_null_if_fail(pa_channel_map_init_auto(&data->channel_map, data->sample_spec.channels, PA_CHANNEL_MAP_DEFAULT));
     }
 
     pa_return_null_if_fail(pa_channel_map_valid(&data->channel_map));
diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c
index fcc91cb..9adb609 100644
--- a/src/pulsecore/sink.c
+++ b/src/pulsecore/sink.c
@@ -73,7 +73,7 @@ pa_sink* pa_sink_new(
     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);
+        pa_return_null_if_fail((map = pa_channel_map_init_auto(&tmap, spec->channels, PA_CHANNEL_MAP_DEFAULT)));
 
     pa_return_null_if_fail(map && pa_channel_map_valid(map));
     pa_return_null_if_fail(map->channels == spec->channels);
diff --git a/src/pulsecore/sound-file.c b/src/pulsecore/sound-file.c
index 7e88734..3e6f683 100644
--- a/src/pulsecore/sound-file.c
+++ b/src/pulsecore/sound-file.c
@@ -119,7 +119,10 @@ int pa_sound_file_load(
     }
 
     if (map)
-        pa_channel_map_init_auto(map, ss->channels, PA_CHANNEL_MAP_DEFAULT);
+        if (!pa_channel_map_init_auto(map, ss->channels, PA_CHANNEL_MAP_DEFAULT)) {
+            pa_log("Unsupported channel map in file %s", fname);
+            goto finish;
+        }
 
     if ((l = pa_frame_size(ss) * sfinfo.frames) > PA_SCACHE_ENTRY_SIZE_MAX) {
         pa_log("File too large");
diff --git a/src/pulsecore/source-output.c b/src/pulsecore/source-output.c
index 576ddcf..88c1146 100644
--- a/src/pulsecore/source-output.c
+++ b/src/pulsecore/source-output.c
@@ -97,7 +97,7 @@ pa_source_output* pa_source_output_new(
         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);
+            pa_return_null_if_fail(pa_channel_map_init_auto(&data->channel_map, data->sample_spec.channels, PA_CHANNEL_MAP_DEFAULT));
     }
 
     pa_return_null_if_fail(pa_channel_map_valid(&data->channel_map));
diff --git a/src/pulsecore/source.c b/src/pulsecore/source.c
index 5fd65ce..d707ad8 100644
--- a/src/pulsecore/source.c
+++ b/src/pulsecore/source.c
@@ -64,7 +64,7 @@ pa_source* pa_source_new(
     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);
+        pa_return_null_if_fail(map = pa_channel_map_init_auto(&tmap, spec->channels, PA_CHANNEL_MAP_DEFAULT));
 
     pa_return_null_if_fail(map && pa_channel_map_valid(map));
     pa_return_null_if_fail(map->channels == spec->channels);

commit e704fd358c093adab7f0a6d3631315f1c91289d2
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Mar 27 23:30:23 2008 +0000

    merge r2106 from trunk
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/prepare-0.9.10@2160 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/utils/padsp.c b/src/utils/padsp.c
index b48af93..cb57ff8 100644
--- a/src/utils/padsp.c
+++ b/src/utils/padsp.c
@@ -1443,18 +1443,18 @@ fail:
 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);
+    debug(DEBUG_LEVEL_VERBOSE, __FILE__": open(%s)\n", filename?filename:"NULL");
 
     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 (filename && 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 (filename && 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 (filename && sndstat_cloak_enable() && strcmp(filename, "/dev/sndstat") == 0)
         r = sndstat_open(flags, &_errno);
     else {
         function_exit();
@@ -2371,18 +2371,13 @@ int close(int fd) {
 
 int access(const char *pathname, int mode) {
 
-    if (!pathname) {
-        /* Firefox needs this. See #27 */
-        errno = EFAULT;
-        return -1;
-    }
-
-    debug(DEBUG_LEVEL_VERBOSE, __FILE__": access(%s)\n", pathname);
+    debug(DEBUG_LEVEL_VERBOSE, __FILE__": access(%s)\n", pathname?pathname:"NULL");
 
-    if (strcmp(pathname, "/dev/dsp") != 0 &&
-        strcmp(pathname, "/dev/adsp") != 0 &&
-        strcmp(pathname, "/dev/sndstat") != 0 &&
-        strcmp(pathname, "/dev/mixer") != 0) {
+    if (!pathname ||
+        ( strcmp(pathname, "/dev/dsp") != 0 &&
+          strcmp(pathname, "/dev/adsp") != 0 &&
+          strcmp(pathname, "/dev/sndstat") != 0 &&
+          strcmp(pathname, "/dev/mixer") != 0 )) {
         LOAD_ACCESS_FUNC();
         return _access(pathname, mode);
     }
@@ -2406,16 +2401,13 @@ int stat(const char *pathname, struct stat *buf) {
 #endif
     int ret;
 
-    if (!pathname || !buf) {
-        errno = EFAULT;
-        return -1;
-    }
-
-    if (strcmp(pathname, "/dev/dsp") != 0 &&
-        strcmp(pathname, "/dev/adsp") != 0 &&
-        strcmp(pathname, "/dev/sndstat") != 0 &&
-        strcmp(pathname, "/dev/mixer") != 0) {
-        debug(DEBUG_LEVEL_VERBOSE, __FILE__": stat(%s)\n", pathname);
+    if (!pathname ||
+        !buf ||
+        ( strcmp(pathname, "/dev/dsp") != 0 &&
+          strcmp(pathname, "/dev/adsp") != 0 &&
+          strcmp(pathname, "/dev/sndstat") != 0 &&
+          strcmp(pathname, "/dev/mixer") != 0 )) {
+        debug(DEBUG_LEVEL_VERBOSE, __FILE__": stat(%s)\n", pathname?pathname:"NULL");
         LOAD_STAT_FUNC();
         return _stat(pathname, buf);
     }
@@ -2464,17 +2456,14 @@ int stat64(const char *pathname, struct stat64 *buf) {
     struct stat oldbuf;
     int ret;
 
-    if (!pathname || !buf) {
-        errno = EFAULT;
-        return -1;
-    }
-
-    debug(DEBUG_LEVEL_VERBOSE, __FILE__": stat64(%s)\n", pathname);
+    debug(DEBUG_LEVEL_VERBOSE, __FILE__": stat64(%s)\n", pathname?pathname:"NULL");
 
-    if (strcmp(pathname, "/dev/dsp") != 0 &&
-        strcmp(pathname, "/dev/adsp") != 0 &&
-        strcmp(pathname, "/dev/sndstat") != 0 &&
-        strcmp(pathname, "/dev/mixer") != 0) {
+    if (!pathname ||
+        !buf ||
+        ( strcmp(pathname, "/dev/dsp") != 0 &&
+          strcmp(pathname, "/dev/adsp") != 0 &&
+          strcmp(pathname, "/dev/sndstat") != 0 &&
+          strcmp(pathname, "/dev/mixer") != 0 )) {
         LOAD_STAT64_FUNC();
         return _stat64(pathname, buf);
     }
@@ -2504,7 +2493,7 @@ int open64(const char *filename, int flags, ...) {
     va_list args;
     mode_t mode = 0;
 
-    debug(DEBUG_LEVEL_VERBOSE, __FILE__": open64(%s)\n", filename);
+    debug(DEBUG_LEVEL_VERBOSE, __FILE__": open64(%s)\n", filename?filename:"NULL");
 
     if (flags & O_CREAT) {
         va_start(args, flags);
@@ -2515,10 +2504,11 @@ int open64(const char *filename, int flags, ...) {
         va_end(args);
     }
 
-    if (strcmp(filename, "/dev/dsp") != 0 &&
-        strcmp(filename, "/dev/adsp") != 0 &&
-        strcmp(filename, "/dev/sndstat") != 0 &&
-        strcmp(filename, "/dev/mixer") != 0) {
+    if (!filename ||
+        ( strcmp(filename, "/dev/dsp") != 0 &&
+          strcmp(filename, "/dev/adsp") != 0 &&
+          strcmp(filename, "/dev/sndstat") != 0 &&
+          strcmp(filename, "/dev/mixer") != 0 )) {
         LOAD_OPEN64_FUNC();
         return _open64(filename, flags, mode);
     }
@@ -2531,17 +2521,14 @@ int open64(const char *filename, int flags, ...) {
 #ifdef _STAT_VER
 
 int __xstat(int ver, const char *pathname, struct stat *buf) {
-    if (!pathname || !buf) {
-        errno = EFAULT;
-        return -1;
-    }
-
-    debug(DEBUG_LEVEL_VERBOSE, __FILE__": __xstat(%s)\n", pathname);
-
-    if (strcmp(pathname, "/dev/dsp") != 0 &&
-        strcmp(pathname, "/dev/adsp") != 0 &&
-        strcmp(pathname, "/dev/sndstat") != 0 &&
-        strcmp(pathname, "/dev/mixer") != 0) {
+    debug(DEBUG_LEVEL_VERBOSE, __FILE__": __xstat(%s)\n", pathname?pathname:"NULL");
+
+    if (!pathname ||
+        !buf ||
+        ( strcmp(pathname, "/dev/dsp") != 0 &&
+          strcmp(pathname, "/dev/adsp") != 0 &&
+          strcmp(pathname, "/dev/sndstat") != 0 &&
+          strcmp(pathname, "/dev/mixer") != 0 )) {
         LOAD_XSTAT_FUNC();
         return ___xstat(ver, pathname, buf);
     }
@@ -2557,17 +2544,14 @@ int __xstat(int ver, const char *pathname, struct stat *buf) {
 #ifdef HAVE_OPEN64
 
 int __xstat64(int ver, const char *pathname, struct stat64 *buf) {
-    if (!pathname || !buf) {
-        errno = EFAULT;
-        return -1;
-    }
-
-    debug(DEBUG_LEVEL_VERBOSE, __FILE__": __xstat64(%s)\n", pathname);
-
-    if (strcmp(pathname, "/dev/dsp") != 0 &&
-        strcmp(pathname, "/dev/adsp") != 0 &&
-        strcmp(pathname, "/dev/sndstat") != 0 &&
-        strcmp(pathname, "/dev/mixer") != 0) {
+    debug(DEBUG_LEVEL_VERBOSE, __FILE__": __xstat64(%s)\n", pathname?pathname:"NULL");
+
+    if (!pathname ||
+        !buf ||
+        ( strcmp(pathname, "/dev/dsp") != 0 &&
+          strcmp(pathname, "/dev/adsp") != 0 &&
+          strcmp(pathname, "/dev/sndstat") != 0 &&
+          strcmp(pathname, "/dev/mixer") != 0 )) {
         LOAD_XSTAT64_FUNC();
         return ___xstat64(ver, pathname, buf);
     }
@@ -2589,12 +2573,14 @@ FILE* fopen(const char *filename, const char *mode) {
     int fd;
     mode_t m;
 
-    debug(DEBUG_LEVEL_VERBOSE, __FILE__": fopen(%s)\n", filename);
+    debug(DEBUG_LEVEL_VERBOSE, __FILE__": fopen(%s)\n", filename?filename:"NULL");
 
-    if (strcmp(filename, "/dev/dsp") != 0 &&
-        strcmp(filename, "/dev/adsp") != 0 &&
-        strcmp(filename, "/dev/sndstat") != 0 &&
-        strcmp(filename, "/dev/mixer") != 0) {
+    if (!filename ||
+        !mode ||
+        ( strcmp(filename, "/dev/dsp") != 0 &&
+          strcmp(filename, "/dev/adsp") != 0 &&
+          strcmp(filename, "/dev/sndstat") != 0 &&
+          strcmp(filename, "/dev/mixer") != 0 )) {
         LOAD_FOPEN_FUNC();
         return _fopen(filename, mode);
     }
@@ -2630,12 +2616,14 @@ FILE* fopen(const char *filename, const char *mode) {
 
 FILE *fopen64(const char *filename, const char *mode) {
 
-    debug(DEBUG_LEVEL_VERBOSE, __FILE__": fopen64(%s)\n", filename);
+    debug(DEBUG_LEVEL_VERBOSE, __FILE__": fopen64(%s)\n", filename?filename:"NULL");
 
-    if (strcmp(filename, "/dev/dsp") != 0 &&
-        strcmp(filename, "/dev/adsp") != 0 &&
-        strcmp(filename, "/dev/sndstat") != 0 &&
-        strcmp(filename, "/dev/mixer") != 0) {
+    if (!filename ||
+        !mode ||
+        ( strcmp(filename, "/dev/dsp") != 0 &&
+          strcmp(filename, "/dev/adsp") != 0 &&
+          strcmp(filename, "/dev/sndstat") != 0 &&
+          strcmp(filename, "/dev/mixer") != 0 )) {
         LOAD_FOPEN64_FUNC();
         return _fopen64(filename, mode);
     }

commit ec39786f2fcd15df044fe4cebe0654d561ac2bc9
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Mar 27 23:31:09 2008 +0000

    merge r2107 from trunk
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/prepare-0.9.10@2161 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/daemon/main.c b/src/daemon/main.c
index 236819e..acc2f02 100644
--- a/src/daemon/main.c
+++ b/src/daemon/main.c
@@ -596,13 +596,13 @@ int main(int argc, char *argv[]) {
         int tty_fd;
 
         if (pa_stdio_acquire() < 0) {
-            pa_log("failed to acquire stdio.");
+            pa_log("Failed to acquire stdio.");
             goto finish;
         }
 
 #ifdef HAVE_FORK
         if (pipe(daemon_pipe) < 0) {
-            pa_log("failed to create pipe.");
+            pa_log("Failed to create pipe.");
             goto finish;
         }
 
@@ -704,6 +704,7 @@ int main(int argc, char *argv[]) {
     signal(SIGPIPE, SIG_IGN);
 #endif
 
+    pa_log_info("This is PulseAudio " PACKAGE_VERSION);
     pa_log_info("Page size is %lu bytes", (unsigned long) PA_PAGE_SIZE);
 
     if (pa_rtclock_hrtimer())

commit bc582401e0316b5cc8db9112335389fee6ed4cfc
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Mar 27 23:31:29 2008 +0000

    merge r2108 from trunk
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/prepare-0.9.10@2162 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/configure.ac b/configure.ac
index 89910ad..8fbdb23 100644
--- a/configure.ac
+++ b/configure.ac
@@ -277,6 +277,7 @@ AC_SEARCH_LIBS([sched_setscheduler], [rt])
 AC_SEARCH_LIBS([dlopen], [dl])
 AC_SEARCH_LIBS([shm_open], [rt])
 AC_SEARCH_LIBS([inet_ntop], [nsl])
+AC_SEARCH_LIBS([timer_create], [rt])
 
 # BSD
 AC_SEARCH_LIBS([connect], [socket])

commit 39de4dd53f37deaddce3e24965dba2042b945b5b
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Mar 27 23:31:55 2008 +0000

    merge r2109 from trunk
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/prepare-0.9.10@2163 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/man/pasuspender.1.xml.in b/man/pasuspender.1.xml.in
index 8a73343..406dfe6 100644
--- a/man/pasuspender.1.xml.in
+++ b/man/pasuspender.1.xml.in
@@ -38,6 +38,13 @@ USA.
     applications access them directly. <file>pasuspender</file> will
     suspend access to the audio devices, fork a child process, and
     when the child process terminates, resume access again.</p>
+
+    <p>Make sure to include <opt>--</opt> in
+    your <file>pasuspender</file> command line before passing the
+    subprocess command line (as shown
+    above). Otherwise <file>pasuspender</file> itself might end up
+    interpreting the command line switches and options you intended to
+    pass to the subprocess.</p>
   </description>
 
   <options>

commit 5045d26c48197de11e15b60f1e67771c3644995d
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Mar 27 23:32:57 2008 +0000

    merge r2110 from trunk
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/prepare-0.9.10@2164 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/shm.c b/src/pulsecore/shm.c
index 6882e7f..7c764e3 100644
--- a/src/pulsecore/shm.c
+++ b/src/pulsecore/shm.c
@@ -318,6 +318,7 @@ int pa_shm_attach_ro(pa_shm *m, unsigned id) {
 
 int pa_shm_cleanup(void) {
 
+#ifdef HAVE_SHM_OPEN
 #ifdef SHM_PATH
     DIR *d;
     struct dirent *de;
@@ -375,7 +376,8 @@ int pa_shm_cleanup(void) {
     }
 
     closedir(d);
-#endif
+#endif /* SHM_PATH */
+#endif /* HAVE_SHM_OPEN */
 
     return 0;
 }

commit 1eb7239764ff1c2cd1d6ec7269f620a6c3f8cbc9
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Mar 27 23:33:18 2008 +0000

    merge r2111 from trunk
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/prepare-0.9.10@2165 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/daemon/main.c b/src/daemon/main.c
index acc2f02..7823180 100644
--- a/src/daemon/main.c
+++ b/src/daemon/main.c
@@ -333,6 +333,7 @@ int main(int argc, char *argv[]) {
     int valid_pid_file = 0;
     gid_t gid = (gid_t) -1;
     pa_bool_t allow_realtime, allow_high_priority;
+    pa_bool_t ltdl_init = FALSE;
 
 #ifdef OS_IS_WIN32
     pa_time_event *timer;
@@ -504,6 +505,7 @@ int main(int argc, char *argv[]) {
 
     LTDL_SET_PRELOADED_SYMBOLS();
     pa_ltdl_init();
+    ltdl_init = TRUE;
 
     if (conf->dl_search_path)
         lt_dlsetsearchpath(conf->dl_search_path);
@@ -837,7 +839,8 @@ finish:
     WSACleanup();
 #endif
 
-    pa_ltdl_done();
+    if (ltdl_init)
+        pa_ltdl_done();
 
 #ifdef HAVE_DBUS
     dbus_shutdown();

commit 184dda8bc32da816916d9ef5838cda89aa975d29
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Mar 27 23:33:40 2008 +0000

    merge r2112 from trunk
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/prepare-0.9.10@2166 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/autoload.h b/src/pulsecore/autoload.h
index 2899586..8a3522a 100644
--- a/src/pulsecore/autoload.h
+++ b/src/pulsecore/autoload.h
@@ -37,7 +37,7 @@ typedef struct pa_autoload_entry {
     uint32_t index;
     char *name;
     pa_namereg_type_t type; /* Type of the autoload entry */
-    int in_action; /* Currently loaded */
+    int in_action; /* The module is currently being loaded */
     char *module, *argument;
 } pa_autoload_entry;
 

commit cca3f49cd049370e89b95d43ccd527305592d380
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Mar 27 23:35:06 2008 +0000

    merge r2113,r2214,r2115 from trunk
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/prepare-0.9.10@2167 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/configure.ac b/configure.ac
index 8fbdb23..e263109 100644
--- a/configure.ac
+++ b/configure.ac
@@ -172,6 +172,12 @@ AC_SUBST(LTDLINCL)
 AC_SUBST(LIBLTDL)
 AC_CONFIG_SUBDIRS(libltdl)
 
+old_LIBS=$LIBS
+LIBS="$LIBS $LIBLTDL"
+AC_CHECK_FUNCS([lt_dlmutex_register])
+LIBS=$old_LIBS
+AC_CHECK_TYPES([struct lt_user_dlloader, lt_dladvise], , , [#include <ltdl.h>])
+
 if test "x$enable_ltdl_install" = "xno" && test "x$ac_cv_lib_ltdl_lt_dlinit" = "xno" ; then
     AC_MSG_ERROR([[
 
diff --git a/src/daemon/ltdl-bind-now.c b/src/daemon/ltdl-bind-now.c
index 6025c6e..6915fe0 100644
--- a/src/daemon/ltdl-bind-now.c
+++ b/src/daemon/ltdl-bind-now.c
@@ -34,6 +34,11 @@
 #include <sys/dl.h>
 #endif
 
+#ifndef HAVE_STRUCT_LT_USER_DLLOADER
+/* Only used with ltdl 2.2 */
+#include <string.h>
+#endif
+
 #include <ltdl.h>
 
 #include <pulsecore/macro.h>
@@ -85,7 +90,11 @@ static const char *libtool_get_error(void) {
   to set $LT_BIND_NOW before starting the pulsaudio binary.
 */
 
+#ifndef HAVE_LT_DLADVISE
 static lt_module bind_now_open(lt_user_data d, const char *fname) {
+#else
+  static lt_module bind_now_open(lt_user_data d, const char *fname, lt_dladvise advise) {
+#endif
     lt_module m;
 
     pa_assert(fname);
@@ -129,19 +138,27 @@ static lt_ptr bind_now_find_sym(lt_user_data d, lt_module m, const char *symbol)
 void pa_ltdl_init(void) {
 
 #ifdef PA_BIND_NOW
+# ifdef HAVE_STRUCT_LT_USER_DLLOADER
     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
     };
+# else
+    static const lt_dlvtable *dlopen_loader;
+    static lt_dlvtable bindnow_loader;
+# endif
 #endif
 
     pa_assert_se(lt_dlinit() == 0);
     pa_assert_se(libtool_mutex = pa_mutex_new(TRUE, FALSE));
+#ifdef HAVE_LT_DLMUTEX_REGISTER
     pa_assert_se(lt_dlmutex_register(libtool_lock, libtool_unlock, libtool_set_error, libtool_get_error) == 0);
+#endif
 
 #ifdef PA_BIND_NOW
+# ifdef HAVE_STRUCT_LT_USER_DLLOADER
 
     if (!(place = lt_dlloader_find("dlopen")))
         place = lt_dlloader_next(NULL);
@@ -149,6 +166,26 @@ void pa_ltdl_init(void) {
     /* 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.");
+# else
+    /* Already initialised */
+    if ( dlopen_loader != NULL ) return;
+
+    if (!(dlopen_loader = lt_dlloader_find("dlopen"))) {
+      pa_log_warn("Failed to find original dlopen loader.");
+      return;
+    }
+
+    memcpy(&bindnow_loader, dlopen_loader, sizeof(bindnow_loader));
+    bindnow_loader.name = "bind-now-loader";
+    bindnow_loader.module_open = bind_now_open;
+    bindnow_loader.module_close = bind_now_close;
+    bindnow_loader.find_sym = bind_now_find_sym;
+    bindnow_loader.priority = LT_DLLOADER_PREPEND;
+
+    /* Add our BIND_NOW loader as the default module loader. */
+    if (lt_dlloader_add(&bindnow_loader) != 0)
+        pa_log_warn("Failed to add bind-now-loader.");
+# endif
 #endif
 }
 

commit 28b7ddce71bb2a7e348d50ec399e2fde840c5735
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Mar 27 23:36:32 2008 +0000

    merge r2116 from trunk
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/prepare-0.9.10@2168 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/daemon/PulseAudio.policy b/src/daemon/PulseAudio.policy
index 55ebbf9..cf9499e 100644
--- a/src/daemon/PulseAudio.policy
+++ b/src/daemon/PulseAudio.policy
@@ -32,7 +32,7 @@ USA.
     <defaults>
       <allow_any>no</allow_any>
       <allow_inactive>no</allow_inactive>
-      <allow_active>auth_admin_keep_always</allow_active>
+      <allow_active>no</allow_active>
     </defaults>
   </action>
 
@@ -42,7 +42,7 @@ USA.
     <defaults>
       <allow_any>no</allow_any>
       <allow_inactive>no</allow_inactive>
-      <allow_active>auth_admin_keep_always</allow_active>
+      <allow_active>no</allow_active>
     </defaults>
   </action>
 

commit daaf70bb3aeb9f10bcd51402d51c0e30f84ae190
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Mar 27 23:36:59 2008 +0000

    merge r2117 from trunk
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/prepare-0.9.10@2169 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/utils/pactl.c b/src/utils/pactl.c
index 4519b13..4381d9d 100644
--- a/src/utils/pactl.c
+++ b/src/utils/pactl.c
@@ -281,7 +281,7 @@ static void get_module_info_callback(pa_context *c, const pa_module_info *i, int
            "Auto unload: %s\n",
            i->index,
            i->name,
-           i->argument,
+           i->argument ? i->argument : "",
            i->n_used != PA_INVALID_INDEX ? t : "n/a",
            i->auto_unload ? "yes" : "no");
 }

commit 46cd2253ab7cca81884e70bba3b6a80246e9f48b
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Mar 27 23:37:23 2008 +0000

    merge r2127 from trunk
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/prepare-0.9.10@2170 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/configure.ac b/configure.ac
index e263109..9da5430 100644
--- a/configure.ac
+++ b/configure.ac
@@ -125,6 +125,43 @@ if test "x$GCC" = "xyes" ; then
     done
 fi
 
+# Native atomic operation support
+AC_ARG_ENABLE([atomic-arm-linux-helpers],
+    AC_HELP_STRING([--disable-atomic-arm-linux-helpers], [use inline asm or libatomic_ops instead]),
+        [
+            case "${enableval}" in
+                yes) atomic_arm_linux_helpers=yes ;;
+                no) atomic_arm_linux_helpers=no ;;
+                *) AC_MSG_ERROR(bad value ${enableval} for --disable-atomic-arm-linux-helpers) ;;
+            esac
+        ],
+        [atomic_arm_linux_helpers=auto])
+
+AC_ARG_ENABLE([atomic-arm-memory-barrier],
+    AC_HELP_STRING([--enable-atomic-arm-memory-barrier], [only really needed in SMP arm systems]),
+        [
+            case "${enableval}" in
+                yes) AC_DEFINE_UNQUOTED(ATOMIC_ARM_MEMORY_BARRIER_ENABLED, 1, [Enable memory barriers]) ;;
+                no) ;;
+                *) AC_MSG_ERROR(bad value ${enableval} for --disable-atomic-arm-linux-helpers) ;;
+            esac
+        ],)
+
+AC_MSG_CHECKING([target operating system])
+case $host in
+    	*-*-linux*)
+	    AC_MSG_RESULT([linux]) 
+	    pulse_target_os=linux
+    	;;
+	*)
+	    AC_MSG_RESULT([unknown]) 	   
+	    pulse_target_os=unknown
+	;;
+esac
+
+# If everything else fails use libatomic_ops
+need_libatomic_ops=yes
+
 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
@@ -133,8 +170,53 @@ 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])
+    need_libatomic_ops=no
 else
     AC_MSG_RESULT([no])
+    # HW specific atomic ops stuff 
+    AC_MSG_CHECKING([architecture for native atomic operations])
+    case $host_cpu in	
+        arm*)
+	    AC_MSG_RESULT([arm])
+	    AC_MSG_CHECKING([whether we can use Linux kernel helpers])
+	    # The Linux kernel helper functions have been there since 2.6.16. However
+  	    # compile time checking for kernel version in cross compile environment 
+	    # (which is usually the case for arm cpu) is tricky (or impossible).
+	    if test "x$pulse_target_os" = "xlinux" && test "x$atomic_arm_linux_helpers" != "xno"; then
+	        AC_MSG_RESULT([yes])
+        	AC_DEFINE_UNQUOTED(ATOMIC_ARM_LINUX_HELPERS, 1, [special arm linux implementation])
+    		need_libatomic_ops=no
+	    else
+	       AC_MSG_RESULT([no])
+	       AC_MSG_CHECKING([compiler support for arm inline asm atomic operations])
+	       AC_LANG_CONFTEST([[int main() 
+	       { 
+                   volatile int a=0;
+	           int o=0, n=1, r;
+	           asm volatile ("ldrex	%0, [%1]\n"
+			 	 "subs	%0, %0, %2\n"
+			 	 "strexeq %0, %3, [%1]\n"
+			 	 : "=&r" (r)
+			 	 : "r" (&a), "Ir" (o), "r" (n)
+			 	 : "cc");
+                   return (a==1 ? 0 : -1);
+	       }]])
+	       $CC conftest.c $CFLAGS -o conftest > /dev/null 2>&1 
+	       ret=$?
+	       rm -f conftest.o conftest
+	       if test $ret -eq 0 ; then
+	       	   AC_DEFINE([ATOMIC_ARM_INLINE_ASM], 1, [Have ARMv6 instructions.])
+	    	   AC_MSG_RESULT([yes])
+		   need_libatomic_ops=no
+	       else
+	    	   AC_MSG_RESULT([no])	       
+               fi
+	   fi
+      	;;
+        *)
+	    AC_MSG_RESULT([unknown])
+        ;;
+    esac
 fi
 
 AC_MSG_CHECKING([whether $CC knows __thread])
@@ -412,13 +494,19 @@ AC_SUBST(LIBSNDFILE_LIBS)
 
 #### atomic-ops ###
 
-AC_CHECK_HEADERS([atomic_ops.h], [], [
-AC_MSG_ERROR([*** libatomic-ops headers not found])
-])
-
-# Win32 does not need the lib and breaks horribly if we try to include it
-if test "x$os_is_win32" != "x1" ; then
-    LIBS="$LIBS -latomic_ops"
+AC_MSG_CHECKING([whether we need libatomic_ops])		
+if test "x$need_libatomic_ops" = "xyes"; then
+   AC_MSG_RESULT([yes])
+   AC_CHECK_HEADERS([atomic_ops.h], [], [
+   AC_MSG_ERROR([*** libatomic-ops headers not found])
+   ])
+
+   # Win32 does not need the lib and breaks horribly if we try to include it
+   if test "x$os_is_win32" != "x1" ; then
+       LIBS="$LIBS -latomic_ops"
+   fi
+else
+   AC_MSG_RESULT([no])
 fi
 
 #### Libsamplerate support (optional) ####
diff --git a/src/pulsecore/atomic.h b/src/pulsecore/atomic.h
index c2c9988..ad3dca3 100644
--- a/src/pulsecore/atomic.h
+++ b/src/pulsecore/atomic.h
@@ -36,7 +36,7 @@
  * On gcc >= 4.1 we use the builtin atomic functions. otherwise we use
  * libatomic_ops
  */
-
+#
 #ifndef PACKAGE
 #error "Please include config.h before including this file!"
 #endif
@@ -182,6 +182,235 @@ static inline int pa_atomic_ptr_cmpxchg(pa_atomic_ptr_t *a, void *old_p, void* n
     return result;
 }
 
+#elif defined(ATOMIC_ARM_INLINE_ASM)
+
+/*
+   These should only be enabled if we have ARMv6 or better.
+*/
+
+typedef struct pa_atomic {
+    volatile int value;
+} pa_atomic_t;
+
+#define PA_ATOMIC_INIT(v) { .value = (v) }
+
+static inline void pa_memory_barrier(void) {
+#ifdef ATOMIC_ARM_MEMORY_BARRIER_ENABLED
+    asm volatile ("mcr  p15, 0, r0, c7, c10, 5  @ dmb");
+#endif
+}
+
+static inline int pa_atomic_load(const pa_atomic_t *a) {
+    pa_memory_barrier();
+    return a->value;
+}
+
+static inline void pa_atomic_store(pa_atomic_t *a, int i) {
+    a->value = i;
+    pa_memory_barrier();
+}
+
+/* Returns the previously set value */
+static inline int pa_atomic_add(pa_atomic_t *a, int i) {
+    unsigned long not_exclusive;
+    int new_val, old_val;
+
+    pa_memory_barrier();
+    do {
+        asm volatile ("ldrex    %0, [%3]\n"
+                      "add      %2, %0, %4\n"
+                      "strex    %1, %2, [%3]\n"
+                      : "=&r" (old_val), "=&r" (not_exclusive), "=&r" (new_val)
+                      : "r" (&a->value), "Ir" (i)
+                      : "cc");
+    } while(not_exclusive);
+    pa_memory_barrier();
+
+    return old_val;
+}
+
+/* Returns the previously set value */
+static inline int pa_atomic_sub(pa_atomic_t *a, int i) {
+    unsigned long not_exclusive;
+    int new_val, old_val;
+
+    pa_memory_barrier();
+    do {
+        asm volatile ("ldrex    %0, [%3]\n"
+                      "sub      %2, %0, %4\n"
+                      "strex    %1, %2, [%3]\n"
+                      : "=&r" (old_val), "=&r" (not_exclusive), "=&r" (new_val)
+                      : "r" (&a->value), "Ir" (i)
+                      : "cc");
+    } while(not_exclusive);
+    pa_memory_barrier();
+
+    return old_val;
+}
+
+static inline int pa_atomic_inc(pa_atomic_t *a) {
+    return pa_atomic_add(a, 1);
+}
+
+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) {
+    unsigned long not_equal, not_exclusive;
+
+    pa_memory_barrier();
+    do {
+        asm volatile ("ldrex    %0, [%2]\n"
+                      "subs     %0, %0, %3\n"
+                      "mov      %1, %0\n"
+                      "strexeq %0, %4, [%2]\n"
+                      : "=&r" (not_exclusive), "=&r" (not_equal)
+                      : "r" (&a->value), "Ir" (old_i), "r" (new_i)
+                      : "cc");
+    } while(not_exclusive && !not_equal);
+    pa_memory_barrier();
+
+    return !not_equal;
+}
+
+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) {
+    pa_memory_barrier();
+    return (void*) a->value;
+}
+
+static inline void pa_atomic_ptr_store(pa_atomic_ptr_t *a, void *p) {
+    a->value = (unsigned long) p;
+    pa_memory_barrier();
+}
+
+static inline int pa_atomic_ptr_cmpxchg(pa_atomic_ptr_t *a, void *old_p, void* new_p) {
+    unsigned long not_equal, not_exclusive;
+
+    pa_memory_barrier();
+    do {
+        asm volatile ("ldrex    %0, [%2]\n"
+                      "subs     %0, %0, %3\n"
+                      "mov      %1, %0\n"
+                      "strexeq %0, %4, [%2]\n"
+                      : "=&r" (not_exclusive), "=&r" (not_equal)
+                      : "r" (&a->value), "Ir" (old_p), "r" (new_p)
+                      : "cc");
+    } while(not_exclusive && !not_equal);
+    pa_memory_barrier();
+
+    return !not_equal;
+}
+
+#elif defined(ATOMIC_ARM_LINUX_HELPERS)
+
+/* See file arch/arm/kernel/entry-armv.S in your kernel sources for more
+   information about these functions. The arm kernel helper functions first
+   appeared in 2.6.16.
+   Apply --disable-atomic-arm-linux-helpers flag to confugure if you prefere
+   inline asm implementation or you have an obsolete Linux kernel.
+*/
+/* Memory barrier */
+typedef void (__kernel_dmb_t)(void);
+#define __kernel_dmb (*(__kernel_dmb_t *)0xffff0fa0)
+
+static inline void pa_memory_barrier(void) {
+#ifndef ATOMIC_ARM_MEMORY_BARRIER_ENABLED
+    __kernel_dmb();
+#endif
+}
+
+/* Atomic exchange (__kernel_cmpxchg_t contains memory barriers if needed) */
+typedef int (__kernel_cmpxchg_t)(int oldval, int newval, volatile int *ptr);
+#define __kernel_cmpxchg (*(__kernel_cmpxchg_t *)0xffff0fc0)
+
+/* This is just to get rid of all warnings */
+typedef int (__kernel_cmpxchg_u_t)(unsigned long oldval, unsigned long newval, volatile unsigned long *ptr);
+#define __kernel_cmpxchg_u (*(__kernel_cmpxchg_u_t *)0xffff0fc0)
+
+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) {
+    pa_memory_barrier();
+    return a->value;
+}
+
+static inline void pa_atomic_store(pa_atomic_t *a, int i) {
+    a->value = i;
+    pa_memory_barrier();
+}
+
+/* Returns the previously set value */
+static inline int pa_atomic_add(pa_atomic_t *a, int i) {
+    int old_val;
+    do {
+        old_val = a->value;
+    } while(__kernel_cmpxchg(old_val, old_val + i, &a->value));
+    return old_val;
+}
+
+/* Returns the previously set value */
+static inline int pa_atomic_sub(pa_atomic_t *a, int i) {
+    int old_val;
+    do {
+        old_val = a->value;
+    } while(__kernel_cmpxchg(old_val, old_val - i, &a->value));
+    return old_val;
+}
+
+/* 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) {
+    int failed = 1;
+    do {
+      failed = __kernel_cmpxchg(old_i, new_i, &a->value);
+    } while(failed && a->value == old_i);
+    return !failed;
+}
+
+typedef struct pa_atomic_ptr {
+    volatile unsigned long value;
+} pa_atomic_ptr_t;
+
+#define PA_ATOMIC_PTR_INIT(v) { .value = (unsigned long) (v) }
+
+static inline void* pa_atomic_ptr_load(const pa_atomic_ptr_t *a) {
+    pa_memory_barrier();
+    return (void*) a->value;
+}
+
+static inline void pa_atomic_ptr_store(pa_atomic_ptr_t *a, void *p) {
+    a->value = (unsigned long) p;
+    pa_memory_barrier();
+}
+
+static inline int pa_atomic_ptr_cmpxchg(pa_atomic_ptr_t *a, void *old_p, void* new_p) {
+    int failed = 1;
+    do {
+        failed = __kernel_cmpxchg_u((unsigned long) old_p, (unsigned long) new_p, &a->value);
+    } while(failed && a->value == old_p);
+    return !failed;
+}
+
 #else
 
 /* libatomic_ops based implementation */

commit a1ec3d7c9d5f6e3e077257cf55c1e686d3614158
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Mar 27 23:37:46 2008 +0000

    merge r2128 from trunk
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/prepare-0.9.10@2171 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/daemon/cpulimit.c b/src/daemon/cpulimit.c
index b77dd44..620a93a 100644
--- a/src/daemon/cpulimit.c
+++ b/src/daemon/cpulimit.c
@@ -151,7 +151,7 @@ static void signal_handler(int sig) {
 
     } else if (phase == PHASE_SOFT) {
         write_err("Hard CPU time limit exhausted, terminating forcibly.\n");
-        _exit(1); /* Forced exit */
+        abort(); /* Forced exit */
     }
 
     errno = saved_errno;

commit 02840a3c9248b9cbe06e7a1cd12f30596a491476
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Mar 27 23:38:05 2008 +0000

    merge r2129 from trunk
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/prepare-0.9.10@2172 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/daemon/PulseAudio.policy b/src/daemon/PulseAudio.policy
index cf9499e..507a2cb 100644
--- a/src/daemon/PulseAudio.policy
+++ b/src/daemon/PulseAudio.policy
@@ -25,6 +25,9 @@ USA.
 -->
 
 <policyconfig>
+  <vendor>The PulseAudio Project</vendor>
+  <vendor_url>http://pulseaudio.org/</vendor_url>
+  <icon_name>audio-card</icon_name>
 
   <action id="org.pulseaudio.acquire-real-time">
     <description>Real-time scheduling for the PulseAudio daemon</description>

commit edd1a509d3cc6d5a14bbbde8a8044e7ef5c8347a
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Mar 27 23:38:28 2008 +0000

    merge r2130 from trunk
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/prepare-0.9.10@2173 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/Makefile.am b/src/Makefile.am
index 84649c4..b782f15 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -103,7 +103,7 @@ EXTRA_DIST = \
 		modules/module-defs.h.m4 \
 		daemon/pulseaudio-module-xsmp.desktop \
 		map-file \
-		daemon/PulseAudio.policy
+		daemon/org.pulseaudio.policy
 
 pulseconf_DATA = \
 		default.pa \
@@ -154,7 +154,7 @@ endif
 
 if HAVE_POLKIT
 
-policy_DATA = daemon/PulseAudio.policy
+policy_DATA = daemon/org.pulseaudio.policy
 
 pulseaudio_SOURCES += daemon/polkit.c daemon/polkit.h
 pulseaudio_CFLAGS += $(POLKIT_CFLAGS)
diff --git a/src/daemon/PulseAudio.policy b/src/daemon/PulseAudio.policy
deleted file mode 100644
index 507a2cb..0000000
--- a/src/daemon/PulseAudio.policy
+++ /dev/null
@@ -1,52 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?><!--*-nxml-*-->
-<!DOCTYPE policyconfig PUBLIC
- "-//freedesktop//DTD PolicyKit Policy Configuration 1.0//EN"
- "http://www.freedesktop.org/standards/PolicyKit/1.0/policyconfig.dtd">
-
-<!-- $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.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.
--->
-
-<policyconfig>
-  <vendor>The PulseAudio Project</vendor>
-  <vendor_url>http://pulseaudio.org/</vendor_url>
-  <icon_name>audio-card</icon_name>
-
-  <action id="org.pulseaudio.acquire-real-time">
-    <description>Real-time scheduling for the PulseAudio daemon</description>
-    <message>System policy prevents PulseAudio from acquiring real-time scheduling.</message>
-    <defaults>
-      <allow_any>no</allow_any>
-      <allow_inactive>no</allow_inactive>
-      <allow_active>no</allow_active>
-    </defaults>
-  </action>
-
-  <action id="org.pulseaudio.acquire-high-priority">
-    <description>High-priority scheduling (negative Unix nice level) for the PulseAudio daemon</description>
-    <message>System policy prevents PulseAudio from acquiring high-priority scheduling.</message>
-    <defaults>
-      <allow_any>no</allow_any>
-      <allow_inactive>no</allow_inactive>
-      <allow_active>no</allow_active>
-    </defaults>
-  </action>
-
-</policyconfig>
diff --git a/src/daemon/org.pulseaudio.policy b/src/daemon/org.pulseaudio.policy
new file mode 100644
index 0000000..507a2cb
--- /dev/null
+++ b/src/daemon/org.pulseaudio.policy
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="UTF-8"?><!--*-nxml-*-->
+<!DOCTYPE policyconfig PUBLIC
+ "-//freedesktop//DTD PolicyKit Policy Configuration 1.0//EN"
+ "http://www.freedesktop.org/standards/PolicyKit/1.0/policyconfig.dtd">
+
+<!-- $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.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.
+-->
+
+<policyconfig>
+  <vendor>The PulseAudio Project</vendor>
+  <vendor_url>http://pulseaudio.org/</vendor_url>
+  <icon_name>audio-card</icon_name>
+
+  <action id="org.pulseaudio.acquire-real-time">
+    <description>Real-time scheduling for the PulseAudio daemon</description>
+    <message>System policy prevents PulseAudio from acquiring real-time scheduling.</message>
+    <defaults>
+      <allow_any>no</allow_any>
+      <allow_inactive>no</allow_inactive>
+      <allow_active>no</allow_active>
+    </defaults>
+  </action>
+
+  <action id="org.pulseaudio.acquire-high-priority">
+    <description>High-priority scheduling (negative Unix nice level) for the PulseAudio daemon</description>
+    <message>System policy prevents PulseAudio from acquiring high-priority scheduling.</message>
+    <defaults>
+      <allow_any>no</allow_any>
+      <allow_inactive>no</allow_inactive>
+      <allow_active>no</allow_active>
+    </defaults>
+  </action>
+
+</policyconfig>

commit 95422a8d21115cdc78c816b2480b7ec048eb8f51
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Mar 27 23:38:46 2008 +0000

    merge r2131 from trunk
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/prepare-0.9.10@2174 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/configure.ac b/configure.ac
index 9da5430..c71d1d1 100644
--- a/configure.ac
+++ b/configure.ac
@@ -150,11 +150,11 @@ AC_ARG_ENABLE([atomic-arm-memory-barrier],
 AC_MSG_CHECKING([target operating system])
 case $host in
     	*-*-linux*)
-	    AC_MSG_RESULT([linux]) 
+	    AC_MSG_RESULT([linux])
 	    pulse_target_os=linux
     	;;
 	*)
-	    AC_MSG_RESULT([unknown]) 	   
+	    AC_MSG_RESULT([unknown])
 	    pulse_target_os=unknown
 	;;
 esac
@@ -173,14 +173,14 @@ if test $ret -eq 0 ; then
     need_libatomic_ops=no
 else
     AC_MSG_RESULT([no])
-    # HW specific atomic ops stuff 
+    # HW specific atomic ops stuff
     AC_MSG_CHECKING([architecture for native atomic operations])
-    case $host_cpu in	
+    case $host_cpu in
         arm*)
 	    AC_MSG_RESULT([arm])
 	    AC_MSG_CHECKING([whether we can use Linux kernel helpers])
 	    # The Linux kernel helper functions have been there since 2.6.16. However
-  	    # compile time checking for kernel version in cross compile environment 
+  	    # compile time checking for kernel version in cross compile environment
 	    # (which is usually the case for arm cpu) is tricky (or impossible).
 	    if test "x$pulse_target_os" = "xlinux" && test "x$atomic_arm_linux_helpers" != "xno"; then
 	        AC_MSG_RESULT([yes])
@@ -189,8 +189,8 @@ else
 	    else
 	       AC_MSG_RESULT([no])
 	       AC_MSG_CHECKING([compiler support for arm inline asm atomic operations])
-	       AC_LANG_CONFTEST([[int main() 
-	       { 
+	       AC_LANG_CONFTEST([[int main()
+	       {
                    volatile int a=0;
 	           int o=0, n=1, r;
 	           asm volatile ("ldrex	%0, [%1]\n"
@@ -201,7 +201,7 @@ else
 			 	 : "cc");
                    return (a==1 ? 0 : -1);
 	       }]])
-	       $CC conftest.c $CFLAGS -o conftest > /dev/null 2>&1 
+	       $CC conftest.c $CFLAGS -o conftest > /dev/null 2>&1
 	       ret=$?
 	       rm -f conftest.o conftest
 	       if test $ret -eq 0 ; then
@@ -209,7 +209,7 @@ else
 	    	   AC_MSG_RESULT([yes])
 		   need_libatomic_ops=no
 	       else
-	    	   AC_MSG_RESULT([no])	       
+	    	   AC_MSG_RESULT([no])
                fi
 	   fi
       	;;
@@ -494,7 +494,7 @@ AC_SUBST(LIBSNDFILE_LIBS)
 
 #### atomic-ops ###
 
-AC_MSG_CHECKING([whether we need libatomic_ops])		
+AC_MSG_CHECKING([whether we need libatomic_ops])
 if test "x$need_libatomic_ops" = "xyes"; then
    AC_MSG_RESULT([yes])
    AC_CHECK_HEADERS([atomic_ops.h], [], [
@@ -976,13 +976,9 @@ AC_ARG_ENABLE([polkit],
 
 if test "x${polkit}" != xno ; then
 
-    PKG_CHECK_MODULES(POLKIT, [ polkit-dbus ],
+    PKG_CHECK_MODULES(POLKIT, [ polkit-dbus >= 0.7 ],
         [
             HAVE_POLKIT=1
-            saved_LIBS="$LIBS"
-            LIBS="$LIBS $POLKIT_LIBS"
-            AC_CHECK_FUNCS(polkit_context_is_caller_authorized)
-            LIBS="$saved_LIBS"
             AC_DEFINE([HAVE_POLKIT], 1, [Have PolicyKit])
             policydir=`pkg-config polkit-dbus --variable prefix`/share/PolicyKit/policy/
             AC_SUBST(policydir)
diff --git a/src/daemon/polkit.c b/src/daemon/polkit.c
index 362c519..ce7c83e 100644
--- a/src/daemon/polkit.c
+++ b/src/daemon/polkit.c
@@ -38,59 +38,6 @@
 
 #include "polkit.h"
 
-static pa_bool_t show_grant_dialog(const char *action_id) {
-    DBusError dbus_error;
-    DBusConnection *bus = NULL;
-    DBusMessage *m = NULL, *reply = NULL;
-    pa_bool_t r = FALSE;
-    uint32_t xid = 0;
-    int verdict;
-
-    dbus_error_init(&dbus_error);
-
-    if (!(bus = dbus_bus_get(DBUS_BUS_SESSION, &dbus_error))) {
-        pa_log_error("Cannot connect to session bus: %s", dbus_error.message);
-        goto finish;
-    }
-
-    if (!(m = dbus_message_new_method_call("org.gnome.PolicyKit", "/org/gnome/PolicyKit/Manager", "org.gnome.PolicyKit.Manager", "ShowDialog"))) {
-        pa_log_error("Failed to allocate D-Bus message.");
-        goto finish;
-    }
-
-    if (!(dbus_message_append_args(m, DBUS_TYPE_STRING, &action_id, DBUS_TYPE_UINT32, &xid, DBUS_TYPE_INVALID))) {
-        pa_log_error("Failed to append arguments to D-Bus message.");
-        goto finish;
-    }
-
-    if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &dbus_error))) {
-        pa_log_warn("Failed to show grant dialog: %s", dbus_error.message);
-        goto finish;
-    }
-
-    if (!(dbus_message_get_args(reply, &dbus_error, DBUS_TYPE_BOOLEAN, &verdict, DBUS_TYPE_INVALID))) {
-        pa_log_warn("Malformed response from grant manager: %s", dbus_error.message);
-        goto finish;
-    }
-
-    r = !!verdict;
-
-finish:
-
-    if (bus)
-        dbus_connection_unref(bus);
-
-    dbus_error_free(&dbus_error);
-
-    if (m)
-        dbus_message_unref(m);
-
-    if (reply)
-        dbus_message_unref(reply);
-
-    return r;
-}
-
 int pa_polkit_check(const char *action_id) {
     int ret = -1;
     DBusError dbus_error;
@@ -161,35 +108,32 @@ int pa_polkit_check(const char *action_id) {
 
     for (;;) {
 
-#ifdef HAVE_POLKIT_CONTEXT_IS_CALLER_AUTHORIZED
         polkit_result = polkit_context_is_caller_authorized(context, action, caller, TRUE, &polkit_error);
 
         if (polkit_error_is_set(polkit_error)) {
             pa_log_error("Could not determine whether caller is authorized: %s", polkit_error_get_error_message(polkit_error));
             goto finish;
         }
-#else
-
-        polkit_result = polkit_context_can_caller_do_action(context, action, caller);
-
-#endif
 
         if (polkit_result == POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH ||
             polkit_result == POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_KEEP_SESSION ||
             polkit_result == POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_KEEP_ALWAYS ||
-#ifdef POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_ONE_SHOT
             polkit_result == POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_ONE_SHOT ||
-#endif
             polkit_result == POLKIT_RESULT_ONLY_VIA_SELF_AUTH ||
             polkit_result == POLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_SESSION ||
-            polkit_result == POLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_ALWAYS
-#ifdef POLKIT_RESULT_ONLY_VIA_SELF_AUTH_ONE_SHOT
-            || polkit_result == POLKIT_RESULT_ONLY_VIA_SELF_AUTH_ONE_SHOT
-#endif
+            polkit_result == POLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_ALWAYS ||
+            polkit_result == POLKIT_RESULT_ONLY_VIA_SELF_AUTH_ONE_SHOT
         ) {
 
-            if (show_grant_dialog(action_id))
-                continue;
+            if (polkit_auth_obtain(action_id, 0, getpid(), &dbus_error)) {
+                polkit_result = POLKIT_RESULT_YES;
+                break;
+            }
+
+            if (dbus_error_is_set(&dbus_error)) {
+                pa_log_error("Cannot obtain auth: %s", dbus_error.message);
+                goto finish;
+            }
         }
 
         break;

commit ac820293389b195332ac072240bd0930cdb305ec
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Mar 27 23:39:10 2008 +0000

    merge r2132 from trunk
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/prepare-0.9.10@2175 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/daemon/daemon.conf.in b/src/daemon/daemon.conf.in
index d664962..e4cfb82 100644
--- a/src/daemon/daemon.conf.in
+++ b/src/daemon/daemon.conf.in
@@ -38,7 +38,7 @@
 ; module-idle-time = 20
 ; scache-idle-time = 20
 
-; dl-search-path = @PA_DLSEARCHPATH@
+; dl-search-path = (depends on architecture)
 
 ; default-script-file = @PA_DEFAULT_CONFIG_FILE@
 
diff --git a/src/daemon/default.pa.in b/src/daemon/default.pa.in
index 597993c..56904f5 100755
--- a/src/daemon/default.pa.in
+++ b/src/daemon/default.pa.in
@@ -37,7 +37,7 @@ load-sample-lazy pulse-hotplug /usr/share/sounds/startup3.wav
 #load-module module-pipe-sink
 
 ### Automatically load driver modules depending on the hardware available
-.ifexists @PA_DLSEARCHPATH@/module-hal-detect at PA_SOEXT@
+.ifexists module-hal-detect at PA_SOEXT@
 load-module module-hal-detect
 .else
 ### Alternatively use the static hardware detection module (for systems that
@@ -79,7 +79,7 @@ load-module module-suspend-on-idle
 #load-module module-x11-bell sample=x11-bell
 
 ### Publish connection data in the X11 root window
-.ifexists @PA_DLSEARCHPATH@/module-x11-publish at PA_SOEXT@
+.ifexists module-x11-publish at PA_SOEXT@
 load-module module-x11-publish
 .endif
 
@@ -91,7 +91,7 @@ load-module module-x11-publish
 ### 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 at PA_SOEXT@
+.ifexists module-gconf at PA_SOEXT@
 load-module module-gconf
 .endif
 
diff --git a/src/pulsecore/cli-command.c b/src/pulsecore/cli-command.c
index 3110a27..423c3f2 100644
--- a/src/pulsecore/cli-command.c
+++ b/src/pulsecore/cli-command.c
@@ -31,6 +31,7 @@
 #include <stdlib.h>
 #include <errno.h>
 #include <unistd.h>
+#include <ltdl.h>
 
 #include <pulse/xmalloc.h>
 
@@ -1315,8 +1316,35 @@ int pa_cli_command_execute_line_stateful(pa_core *c, const char *s, pa_strbuf *b
                 } else {
                     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");
+                    /* Search DL_SEARCH_PATH unless the filename is absolute */
+                    if (filename[0] == PA_PATH_SEP_CHAR) {
+
+                        *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 {
+                        const char *paths, *state = NULL;
+                        char *p;
+
+                        if (!(paths = lt_dlgetsearchpath()))
+                            return -1;
+
+                        while ((p = pa_split(paths, ":", &state))) {
+                            char *pathname;
+
+                            pathname = pa_sprintf_malloc("%s" PA_PATH_SEP "%s", p, filename);
+                            pa_xfree(p);
+
+                            *ifstate = access(pathname, F_OK) == 0 ? IFSTATE_TRUE : IFSTATE_FALSE;
+                            pa_log_debug("Checking for existance of '%s': %s", pathname, *ifstate == IFSTATE_TRUE ? "success" : "failure");
+
+                            pa_xfree(pathname);
+
+                            if (*ifstate == IFSTATE_TRUE)
+                                break;
+                        }
+                    }
+
                 }
             } else {
                 pa_strbuf_printf(buf, "Invalid meta command: %s\n", cs);

commit e5e9ed6d721d5c4758176c468af939578064203f
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Mar 27 23:40:40 2008 +0000

    merge r2133 from trunk
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/prepare-0.9.10@2176 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/protocol-esound.c b/src/pulsecore/protocol-esound.c
index 004e535..f963f2a 100644
--- a/src/pulsecore/protocol-esound.c
+++ b/src/pulsecore/protocol-esound.c
@@ -72,7 +72,7 @@
 #define RECORD_BUFFER_SECONDS (5)
 #define RECORD_BUFFER_FRAGMENTS (100)
 
-#define MAX_CACHE_SAMPLE_SIZE (1024000)
+#define MAX_CACHE_SAMPLE_SIZE (2048000)
 
 #define SCACHE_PREFIX "esound."
 

commit 2b593d2fca2e7fb5ee84109cad45c54e3808f95e
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Mar 27 23:41:03 2008 +0000

    merge r2134 from trunk
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/prepare-0.9.10@2177 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/daemon/default.pa.in b/src/daemon/default.pa.in
index 56904f5..c1324a0 100755
--- a/src/daemon/default.pa.in
+++ b/src/daemon/default.pa.in
@@ -46,7 +46,9 @@ load-module module-detect
 .endif
 
 ### Load several protocols
+.ifexists module-esound-protocol-unix at PA_SOEXT@
 load-module module-esound-protocol-unix
+.endif
 load-module module-native-protocol-unix
 
 ### Network access (may be configured with paprefs, so leave this commented
@@ -80,7 +82,9 @@ load-module module-suspend-on-idle
 
 ### Publish connection data in the X11 root window
 .ifexists module-x11-publish at PA_SOEXT@
+.nofail
 load-module module-x11-publish
+.fail
 .endif
 
 ### Register ourselves in the X11 session manager
@@ -92,7 +96,9 @@ load-module module-x11-publish
 ### Please keep in mind that the modules configured by paprefs might conflict with manually
 ### loaded modules.
 .ifexists module-gconf at PA_SOEXT@
+.nofail
 load-module module-gconf
+.fail
 .endif
 
 ### Make some devices default

commit e21a69eb0bb3d0fbf301e35eee75a32c20114477
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Mar 27 23:41:34 2008 +0000

    merge r2146 from trunk
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/prepare-0.9.10@2178 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/bt-proximity-helper.c b/src/modules/bt-proximity-helper.c
index d80cc0c..5f042c3 100644
--- a/src/modules/bt-proximity-helper.c
+++ b/src/modules/bt-proximity-helper.c
@@ -1,35 +1,29 @@
 /* $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 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.
-***/
-
 /*
  * Small SUID helper that allows us to ping a BT device. Borrows
- * heavily from bluez-utils' l2ping, which is licensed as GPL2+, too
+ * heavily from bluez-utils' l2ping, which is licensed as GPL2+
  * and comes with a copyright like this:
  *
  *  Copyright (C) 2000-2001  Qualcomm Incorporated
  *  Copyright (C) 2002-2003  Maxim Krasnyansky <maxk at qualcomm.com>
  *  Copyright (C) 2002-2007  Marcel Holtmann <marcel at holtmann.org>
  *
+ *
+ *  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
  */
 
 #ifdef HAVE_CONFIG_H

commit 4ddc3271e16d893c4743ce9470601a42fd3cd936
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Mar 27 23:47:09 2008 +0000

    initialize gconf module before we publish our X11 credentials -- because gconf might cause network support enabled in the first place
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/prepare-0.9.10@2179 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/daemon/default.pa.in b/src/daemon/default.pa.in
index c1324a0..064a6cc 100755
--- a/src/daemon/default.pa.in
+++ b/src/daemon/default.pa.in
@@ -80,13 +80,6 @@ load-module module-suspend-on-idle
 ### Load X11 bell module
 #load-module module-x11-bell sample=x11-bell
 
-### Publish connection data in the X11 root window
-.ifexists module-x11-publish at PA_SOEXT@
-.nofail
-load-module module-x11-publish
-.fail
-.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
@@ -101,6 +94,13 @@ load-module module-gconf
 .fail
 .endif
 
+### Publish connection data in the X11 root window
+.ifexists module-x11-publish at PA_SOEXT@
+.nofail
+load-module module-x11-publish
+.fail
+.endif
+
 ### Make some devices default
 #set-default-sink output
 #set-default-source input

commit b0dc80de547d9834e837768a8cb1ccd064effeb5
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Mar 28 00:47:31 2008 +0000

    work around yet another solaris braindamage
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/prepare-0.9.10@2182 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/utils/pactl.c b/src/utils/pactl.c
index 4381d9d..674eaee 100644
--- a/src/utils/pactl.c
+++ b/src/utils/pactl.c
@@ -486,7 +486,7 @@ static void get_autoload_info_callback(pa_context *c, const pa_autoload_info *i,
            i->name,
            i->type == PA_AUTOLOAD_SINK ? "sink" : "source",
            i->module,
-           i->argument);
+           i->argument ? i->argument : "");
 }
 
 static void simple_callback(pa_context *c, int success, void *userdata) {

commit 2599213a72dddd385629387f93fba89d0510f322
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Mar 28 00:51:36 2008 +0000

    Fix ioctl() definition for solaris compat. Patch from yippi. Closes #253
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/prepare-0.9.10@2183 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/utils/padsp.c b/src/utils/padsp.c
index cb57ff8..d3f034d 100644
--- a/src/utils/padsp.c
+++ b/src/utils/padsp.c
@@ -2307,7 +2307,11 @@ fail:
     return ret;
 }
 
+#ifdef sun
+int ioctl(int fd, int request, ...) {
+#else
 int ioctl(int fd, unsigned long request, ...) {
+#endif
     fd_info *i;
     va_list args;
     void *argp;

commit 8e60b01a5ec5d49c75b73401f652d73a004ae805
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Mar 28 17:03:25 2008 +0000

    actually set lennart to the user name, not the group name. Set lennart too.
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/prepare-0.9.10@2184 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/daemon/main.c b/src/daemon/main.c
index 7823180..678ee52 100644
--- a/src/daemon/main.c
+++ b/src/daemon/main.c
@@ -242,7 +242,8 @@ static int change_user(void) {
     }
 
     set_env("USER", PA_SYSTEM_USER);
-    set_env("LOGNAME", PA_SYSTEM_GROUP);
+    set_env("USERNAME", PA_SYSTEM_USER);
+    set_env("LOGNAME", PA_SYSTEM_USER);
     set_env("HOME", PA_SYSTEM_RUNTIME_PATH);
 
     /* Relevant for pa_runtime_path() */

commit 13b99517ab131e013e3cdb7b50a2c80cdadc75f5
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Mar 28 17:12:01 2008 +0000

    if we are run as root, always use 'root' as username, regardless of any env vars
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/prepare-0.9.10@2185 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulse/util.c b/src/pulse/util.c
index d3ac9f6..b6f57b9 100644
--- a/src/pulse/util.c
+++ b/src/pulse/util.c
@@ -65,7 +65,7 @@
 #include "util.h"
 
 char *pa_get_user_name(char *s, size_t l) {
-    char *p;
+    const char *p;
     char buf[1024];
 
 #ifdef HAVE_PWD_H
@@ -75,7 +75,10 @@ char *pa_get_user_name(char *s, size_t l) {
     pa_assert(s);
     pa_assert(l > 0);
 
-    if (!(p = getenv("USER")) && !(p = getenv("LOGNAME")) && !(p = getenv("USERNAME"))) {
+    if (!(p = (getuid() == 0 ? "root" : NULL)) &&
+        !(p = getenv("USER")) &&
+        !(p = getenv("LOGNAME")) &&
+        !(p = getenv("USERNAME"))) {
 #ifdef HAVE_PWD_H
 
 #ifdef HAVE_GETPWUID_R

commit fad6b41678346816d1bcf550c25c4c38e7c79543
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Mar 28 18:01:01 2008 +0000

    don't segfault when module-tunnel is used without a sink_name/source_name parameter. Closes #197
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/prepare-0.9.10@2186 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-tunnel.c b/src/modules/module-tunnel.c
index a53e393..62dac5d 100644
--- a/src/modules/module-tunnel.c
+++ b/src/modules/module-tunnel.c
@@ -723,7 +723,7 @@ static void sink_info_cb(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint3
         goto fail;
     }
 
-    if (strcmp(name, u->sink_name))
+    if (!u->sink_name || strcmp(name, u->sink_name))
         return;
 
     pa_xfree(u->device_description);
@@ -836,7 +836,7 @@ static void source_info_cb(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uin
         goto fail;
     }
 
-    if (strcmp(name, u->source_name))
+    if (!u->source_name || strcmp(name, u->source_name))
         return;
 
     pa_xfree(u->device_description);

commit 0a108eca65f478c231c9c58f3922316c79227835
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Mar 28 18:09:25 2008 +0000

    don't fail on init if the default device does not exist and .nofail is active
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/prepare-0.9.10@2187 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/daemon/main.c b/src/daemon/main.c
index 678ee52..6b0c81d 100644
--- a/src/daemon/main.c
+++ b/src/daemon/main.c
@@ -779,7 +779,7 @@ int main(int argc, char *argv[]) {
     c->disallow_module_loading = !!conf->disallow_module_loading;
 
     if (r < 0 && conf->fail) {
-        pa_log("failed to initialize daemon.");
+        pa_log("Failed to initialize daemon.");
 #ifdef HAVE_FORK
         if (conf->daemonize)
             pa_loop_write(daemon_pipe[1], &retval, sizeof(retval), NULL);
@@ -793,16 +793,19 @@ int main(int argc, char *argv[]) {
     } else {
 
         retval = 0;
+
+        if (c->default_sink_name &&
+            pa_namereg_get(c, c->default_sink_name, PA_NAMEREG_SINK, 1) == NULL) {
+            pa_log_error("%s : Default sink name (%s) does not exist in name register.", __FILE__, c->default_sink_name);
+            retval = !!conf->fail;
+        }
+
 #ifdef HAVE_FORK
         if (conf->daemonize)
             pa_loop_write(daemon_pipe[1], &retval, sizeof(retval), NULL);
 #endif
 
-        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);
-            retval = 1;
-        } else {
+        if (!retval) {
             pa_log_info("Daemon startup complete.");
             if (pa_mainloop_run(mainloop, &retval) < 0)
                 retval = 1;

commit a3b83119e9bf854066bbd22a0ee8386a9e96d861
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sat Mar 29 00:31:10 2008 +0000

    merge r2187 from trunk
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/prepare-0.9.10@2188 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c
index 4f58279..174342e 100644
--- a/src/pulsecore/protocol-native.c
+++ b/src/pulsecore/protocol-native.c
@@ -1177,6 +1177,7 @@ static void source_output_moved_cb(pa_source_output *o) {
     pa_tagstruct_putu32(t, s->index);
     pa_tagstruct_putu32(t, o->source->index);
     pa_tagstruct_puts(t, o->source->name);
+    pa_tagstruct_put_boolean(t, pa_source_get_state(o->source) == PA_SOURCE_SUSPENDED);
     pa_pstream_send_tagstruct(s->connection->pstream, t);
 }
 

commit 1c8269415757a5d953931e67f3d6133a9735531c
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sat Mar 29 00:42:58 2008 +0000

    bump soname
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/prepare-0.9.10@2189 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/configure.ac b/configure.ac
index c71d1d1..2ac56ed 100644
--- a/configure.ac
+++ b/configure.ac
@@ -41,7 +41,7 @@ AC_SUBST(PA_PROTOCOL_VERSION, 12)
 
 # The stable ABI for client applications, for the version info x:y:z
 # always will hold y=z
-AC_SUBST(LIBPULSE_VERSION_INFO, [4:0:4])
+AC_SUBST(LIBPULSE_VERSION_INFO, [4:1:4])
 
 # A simplified, synchronous, ABI-stable interface for client
 # applications, for the version info x:y:z always will hold y=z
@@ -58,7 +58,7 @@ AC_SUBST(LIBPULSE_MAINLOOP_GLIB_VERSION_INFO, [0:3:0])
 # An internally used, ABI-unstable library that contains the
 # PulseAudio core, SONAMEs are bumped on every release, version info
 # suffix will always be 0:0
-AC_SUBST(LIBPULSECORE_VERSION_INFO, [5:0:0])
+AC_SUBST(LIBPULSECORE_VERSION_INFO, [5:1:0])
 
 AC_CANONICAL_HOST
 

commit ed5528f907fad850f6fa66a5573aa5b151c0856b
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sat Mar 29 22:09:52 2008 +0000

    require autoconf 2.60 since we use AC_PROG_MKDIR_P
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/prepare-0.9.10@2190 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/configure.ac b/configure.ac
index 2ac56ed..7f62cb2 100644
--- a/configure.ac
+++ b/configure.ac
@@ -22,7 +22,7 @@
 # along with PulseAudio; if not, write to the Free Software Foundation,
 # Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
 
-AC_PREREQ(2.57)
+AC_PREREQ(2.60)
 
 m4_define(PA_MAJOR, [0])
 m4_define(PA_MINOR, [9])

commit 829197db5247f039b09ef5a9f8000c7aede5c863
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sat Mar 29 23:09:48 2008 +0000

    fix compiler warning
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/prepare-0.9.10@2191 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/tests/smoother-test.c b/src/tests/smoother-test.c
index caa7df7..0816e76 100644
--- a/src/tests/smoother-test.c
+++ b/src/tests/smoother-test.c
@@ -71,7 +71,7 @@ int main(int argc, char*argv[]) {
             u += 2;
         }
 
-        printf("%llu\t%llu\n", x/PA_USEC_PER_MSEC, pa_smoother_get(s, x)/PA_USEC_PER_MSEC);
+        printf("%llu\t%llu\n", (unsigned long long) (x/PA_USEC_PER_MSEC), (unsigned long long) (pa_smoother_get(s, x)/PA_USEC_PER_MSEC));
     }
 
     pa_smoother_free(s);

commit dbf9037ca3d0488988776416bfeb9a5bb23c0c73
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sun Mar 30 00:38:47 2008 +0000

    avoid name clash with libc's remove() function
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/prepare-0.9.10@2192 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/hashmap.c b/src/pulsecore/hashmap.c
index f558966..c9d5632 100644
--- a/src/pulsecore/hashmap.c
+++ b/src/pulsecore/hashmap.c
@@ -71,7 +71,7 @@ pa_hashmap *pa_hashmap_new(pa_hash_func_t hash_func, pa_compare_func_t compare_f
     return h;
 }
 
-static void remove(pa_hashmap *h, struct hashmap_entry *e) {
+static void remove_entry(pa_hashmap *h, struct hashmap_entry *e) {
     pa_assert(h);
     pa_assert(e);
 
@@ -103,7 +103,7 @@ void pa_hashmap_free(pa_hashmap*h, void (*free_func)(void *p, void *userdata), v
     while (h->first_entry) {
         if (free_func)
             free_func(h->first_entry->value, userdata);
-        remove(h, h->first_entry);
+        remove_entry(h, h->first_entry);
     }
 
     pa_xfree(h->data);
@@ -182,7 +182,7 @@ void* pa_hashmap_remove(pa_hashmap *h, const void *key) {
         return NULL;
 
     data = e->value;
-    remove(h, e);
+    remove_entry(h, e);
     return data;
 }
 
@@ -220,7 +220,7 @@ void* pa_hashmap_steal_first(pa_hashmap *h) {
         return NULL;
 
     data = h->first_entry->value;
-    remove(h, h->first_entry);
+    remove_entry(h, h->first_entry);
     return data;
 }
 

commit 68b131d9ac21177810c807e10120077af742c7b4
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sun Mar 30 00:39:57 2008 +0000

    make pa_drop_caps() abort on failure
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/prepare-0.9.10@2193 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/daemon/caps.c b/src/daemon/caps.c
index 44ee355..af59338 100644
--- a/src/daemon/caps.c
+++ b/src/daemon/caps.c
@@ -90,8 +90,8 @@ int pa_limit_caps(void) {
     cap_t caps;
     cap_value_t nice_cap = CAP_SYS_NICE;
 
-    caps = cap_init();
-    pa_assert(caps);
+    pa_assert_se(caps = cap_init());
+
     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);
@@ -113,28 +113,15 @@ fail:
 }
 
 /* Drop all capabilities, effectively becoming a normal user */
-int pa_drop_caps(void) {
+void pa_drop_caps(void) {
     cap_t caps;
-    int r = -1;
 
-    caps = cap_init();
-    pa_assert(caps);
+    pa_assert_se(prctl(PR_SET_KEEPCAPS, 0, 0, 0, 0) == 0);
 
+    pa_assert_se(caps = cap_init());
     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));
-        goto fail;
-    }
-
-    r = 0;
-
-fail:
+    pa_assert_se(cap_set_proc(caps) == 0);
     cap_free(caps);
-
-    return r;
 }
 
 #else
diff --git a/src/daemon/caps.h b/src/daemon/caps.h
index 4cd0957..91c8841 100644
--- a/src/daemon/caps.h
+++ b/src/daemon/caps.h
@@ -25,7 +25,7 @@
 ***/
 
 void pa_drop_root(void);
+void pa_drop_caps(void);
 int pa_limit_caps(void);
-int pa_drop_caps(void);
 
 #endif

commit cf37df412df86891285d2e720c16042133a87553
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sun Mar 30 01:42:34 2008 +0000

    rework pa_assert_se() to make sure it never gets optmized away, even if NDEBUG is defined
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/prepare-0.9.10@2194 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/macro.h b/src/pulsecore/macro.h
index 41af19c..ba53817 100644
--- a/src/pulsecore/macro.h
+++ b/src/pulsecore/macro.h
@@ -29,6 +29,8 @@
 #include <assert.h>
 #include <limits.h>
 #include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
 
 #include <pulsecore/log.h>
 #include <pulsecore/gccmacro.h>
@@ -103,35 +105,47 @@ typedef int pa_bool_t;
 #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_if_fail(expr)                                         \
+    do {                                                                \
+        if (PA_UNLIKELY(!(expr))) {                                     \
+            pa_log_debug("Assertion '%s' failed at %s:%u, function %s.\n", #expr , __FILE__, __LINE__, PA_PRETTY_FUNCTION); \
+            return;                                                     \
+        }                                                               \
+    } while(FALSE)
+
+#define pa_return_val_if_fail(expr, val)                                \
+    do {                                                                \
+        if (PA_UNLIKELY(!(expr))) {                                     \
+            pa_log_debug("Assertion '%s' failed at %s:%u, function %s.\n", #expr , __FILE__, __LINE__, PA_PRETTY_FUNCTION); \
+            return (val);                                               \
+        }                                                               \
+    } while(FALSE)
 
 #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 */
+/* An assert which guarantees side effects of x, i.e. is never
+ * optimized away */
+#define pa_assert_se(expr)                                              \
+    do {                                                                \
+        if (PA_UNLIKELY(!(expr))) {                                     \
+            pa_log_error("Assertion '%s' failed at %s:%u, function %s(). Aborting.", #expr , __FILE__, __LINE__, PA_PRETTY_FUNCTION); \
+            abort();                                                    \
+        }                                                               \
+    } while (FALSE)
+
+/* An assert that may be optimized away by defining NDEBUG */
 #ifdef NDEBUG
-#define pa_assert_se(x) x
+#define pa_assert(expr) do {} while (FALSE)
 #else
-#define pa_assert_se(x) pa_assert(x)
+#define pa_assert(expr) pa_assert_se(expr)
 #endif
 
+#define pa_assert_not_reached()                                         \
+    do {                                                                \
+        pa_log_error("Code should not be reached at %s:%u, function %s(). Aborting.", __FILE__, __LINE__, PA_PRETTY_FUNCTION); \
+        abort();                                                        \
+    } while (FALSE)
+
 #define PA_PTR_TO_UINT(p) ((unsigned int) (unsigned long) (p))
 #define PA_UINT_TO_PTR(u) ((void*) (unsigned long) (u))
 

commit 3e314b7379fe09fb66859ba2b1251f2519da5122
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sun Mar 30 01:43:15 2008 +0000

    fix buildsystem to provide pa_log() in all binaries
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/prepare-0.9.10@2195 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/Makefile.am b/src/Makefile.am
index b782f15..64e9b9a 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -64,7 +64,7 @@ AM_LIBADD = $(PTHREAD_LIBS)
 AM_LDADD = $(PTHREAD_LIBS)
 
 # Only required on some platforms but defined for all to avoid errors
-AM_LDFLAGS = -Wl,-no-undefined -ffunction-sections -fdata-sections -Wl,--gc-sections
+AM_LDFLAGS = -Wl,-no-undefined -Wl,--gc-sections
 
 if STATIC_BINS
 BINLDFLAGS = -static
@@ -202,7 +202,7 @@ 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_SOURCES = utils/pasuspender.c pulsecore/core-util.c pulsecore/core-util.h pulsecore/core-error.c pulsecore/core-error.h pulsecore/log.c pulsecore/log.h pulsecore/once.c pulsecore/once.h $(PA_THREAD_OBJS)
 pasuspender_LDADD = $(AM_LDADD) libpulse.la $(LIBSNDFILE_LIBS)
 pasuspender_CFLAGS = $(AM_CFLAGS) $(LIBSNDFILE_CFLAGS)
 pasuspender_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS)
@@ -273,7 +273,7 @@ mainloop_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS)
 
 thread_mainloop_test_SOURCES = tests/thread-mainloop-test.c
 thread_mainloop_test_CFLAGS = $(AM_CFLAGS)
-thread_mainloop_test_LDADD = $(AM_LDADD) libpulse.la
+thread_mainloop_test_LDADD = $(AM_LDADD) libpulsecore.la libpulse.la
 thread_mainloop_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS)
 
 utf8_test_SOURCES = tests/utf8-test.c
@@ -563,7 +563,14 @@ libpulse_la_CFLAGS += $(LIBASYNCNS_CFLAGS)
 libpulse_la_LIBADD += $(LIBASYNCNS_LIBS)
 endif
 
-libpulse_simple_la_SOURCES = pulse/simple.c pulse/simple.h
+libpulse_simple_la_SOURCES = \
+		pulse/simple.c pulse/simple.h	\
+		pulsecore/log.c pulsecore/log.h \
+		pulsecore/core-util.c pulsecore/core-util.h  \
+		pulsecore/core-error.c pulsecore/core-error.h \
+		pulsecore/once.c pulsecore/once.h \
+		$(PA_THREAD_OBJS)
+
 libpulse_simple_la_CFLAGS = $(AM_CFLAGS)
 libpulse_simple_la_LIBADD = $(AM_LIBADD) libpulse.la
 libpulse_simple_la_LDFLAGS = -version-info $(LIBPULSE_SIMPLE_VERSION_INFO) -Wl,-version-script=$(srcdir)/map-file
@@ -573,7 +580,13 @@ libpulse_browse_la_CFLAGS = $(AM_CFLAGS) $(AVAHI_CFLAGS)
 libpulse_browse_la_LIBADD = $(AM_LIBADD) libpulse.la $(AVAHI_LIBS)
 libpulse_browse_la_LDFLAGS = -version-info $(LIBPULSE_BROWSE_VERSION_INFO) -Wl,-version-script=$(srcdir)/map-file
 
-libpulse_mainloop_glib_la_SOURCES = pulse/glib-mainloop.h pulse/glib-mainloop.c
+libpulse_mainloop_glib_la_SOURCES = \
+		pulse/glib-mainloop.h pulse/glib-mainloop.c \
+		pulsecore/log.c pulsecore/log.h \
+		pulsecore/core-util.c pulsecore/core-util.h  \
+		pulsecore/core-error.c pulsecore/core-error.h \
+		pulsecore/once.c pulsecore/once.h \
+		$(PA_THREAD_OBJS)
 libpulse_mainloop_glib_la_CFLAGS = $(AM_CFLAGS) $(GLIB20_CFLAGS)
 libpulse_mainloop_glib_la_LIBADD = $(AM_LIBADD) libpulse.la $(GLIB20_LIBS)
 libpulse_mainloop_glib_la_LDFLAGS = -version-info $(LIBPULSE_MAINLOOP_GLIB_VERSION_INFO) -Wl,-version-script=$(srcdir)/map-file

commit ecf643966111387953cbfd0bce7f39b6c3d8116a
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Mar 31 23:08:01 2008 +0000

    catch up with trunk HEAD (i.e. 2118:2213)
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2214 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/configure.ac b/configure.ac
index 748e8f0..112f632 100644
--- a/configure.ac
+++ b/configure.ac
@@ -5,7 +5,7 @@
 
 # This file is part of PulseAudio.
 #
-# Copyright 2004-2006 Lennart Poettering
+# Copyright 2004-2008 Lennart Poettering
 # Copyright 2006-2007 Pierre Ossman <ossman at cendio.se> for Cendio AB
 #
 # PulseAudio is free software; you can redistribute it and/or modify it
@@ -22,11 +22,11 @@
 # along with PulseAudio; if not, write to the Free Software Foundation,
 # Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
 
-AC_PREREQ(2.57)
+AC_PREREQ(2.60)
 
 m4_define(PA_MAJOR, [0])
 m4_define(PA_MINOR, [9])
-m4_define(PA_MICRO, [8])
+m4_define(PA_MICRO, [10])
 
 AC_INIT([pulseaudio], PA_MAJOR.PA_MINOR.PA_MICRO,[mzchyfrnhqvb (at) 0pointer (dot) net])
 AC_CONFIG_SRCDIR([src/daemon/main.c])
@@ -41,7 +41,7 @@ AC_SUBST(PA_PROTOCOL_VERSION, 12)
 
 # The stable ABI for client applications, for the version info x:y:z
 # always will hold y=z
-AC_SUBST(LIBPULSE_VERSION_INFO, [4:0:4])
+AC_SUBST(LIBPULSE_VERSION_INFO, [4:1:4])
 
 # A simplified, synchronous, ABI-stable interface for client
 # applications, for the version info x:y:z always will hold y=z
@@ -58,7 +58,7 @@ AC_SUBST(LIBPULSE_MAINLOOP_GLIB_VERSION_INFO, [0:3:0])
 # An internally used, ABI-unstable library that contains the
 # PulseAudio core, SONAMEs are bumped on every release, version info
 # suffix will always be 0:0
-AC_SUBST(LIBPULSECORE_VERSION_INFO, [5:0:0])
+AC_SUBST(LIBPULSECORE_VERSION_INFO, [5:1:0])
 
 AC_CANONICAL_HOST
 
@@ -125,6 +125,43 @@ if test "x$GCC" = "xyes" ; then
     done
 fi
 
+# Native atomic operation support
+AC_ARG_ENABLE([atomic-arm-linux-helpers],
+    AC_HELP_STRING([--disable-atomic-arm-linux-helpers], [use inline asm or libatomic_ops instead]),
+        [
+            case "${enableval}" in
+                yes) atomic_arm_linux_helpers=yes ;;
+                no) atomic_arm_linux_helpers=no ;;
+                *) AC_MSG_ERROR(bad value ${enableval} for --disable-atomic-arm-linux-helpers) ;;
+            esac
+        ],
+        [atomic_arm_linux_helpers=auto])
+
+AC_ARG_ENABLE([atomic-arm-memory-barrier],
+    AC_HELP_STRING([--enable-atomic-arm-memory-barrier], [only really needed in SMP arm systems]),
+        [
+            case "${enableval}" in
+                yes) AC_DEFINE_UNQUOTED(ATOMIC_ARM_MEMORY_BARRIER_ENABLED, 1, [Enable memory barriers]) ;;
+                no) ;;
+                *) AC_MSG_ERROR(bad value ${enableval} for --disable-atomic-arm-linux-helpers) ;;
+            esac
+        ],)
+
+AC_MSG_CHECKING([target operating system])
+case $host in
+    	*-*-linux*)
+	    AC_MSG_RESULT([linux])
+	    pulse_target_os=linux
+    	;;
+	*)
+	    AC_MSG_RESULT([unknown])
+	    pulse_target_os=unknown
+	;;
+esac
+
+# If everything else fails use libatomic_ops
+need_libatomic_ops=yes
+
 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
@@ -133,8 +170,53 @@ 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])
+    need_libatomic_ops=no
 else
     AC_MSG_RESULT([no])
+    # HW specific atomic ops stuff
+    AC_MSG_CHECKING([architecture for native atomic operations])
+    case $host_cpu in
+        arm*)
+	    AC_MSG_RESULT([arm])
+	    AC_MSG_CHECKING([whether we can use Linux kernel helpers])
+	    # The Linux kernel helper functions have been there since 2.6.16. However
+  	    # compile time checking for kernel version in cross compile environment
+	    # (which is usually the case for arm cpu) is tricky (or impossible).
+	    if test "x$pulse_target_os" = "xlinux" && test "x$atomic_arm_linux_helpers" != "xno"; then
+	        AC_MSG_RESULT([yes])
+        	AC_DEFINE_UNQUOTED(ATOMIC_ARM_LINUX_HELPERS, 1, [special arm linux implementation])
+    		need_libatomic_ops=no
+	    else
+	       AC_MSG_RESULT([no])
+	       AC_MSG_CHECKING([compiler support for arm inline asm atomic operations])
+	       AC_LANG_CONFTEST([[int main()
+	       {
+                   volatile int a=0;
+	           int o=0, n=1, r;
+	           asm volatile ("ldrex	%0, [%1]\n"
+			 	 "subs	%0, %0, %2\n"
+			 	 "strexeq %0, %3, [%1]\n"
+			 	 : "=&r" (r)
+			 	 : "r" (&a), "Ir" (o), "r" (n)
+			 	 : "cc");
+                   return (a==1 ? 0 : -1);
+	       }]])
+	       $CC conftest.c $CFLAGS -o conftest > /dev/null 2>&1
+	       ret=$?
+	       rm -f conftest.o conftest
+	       if test $ret -eq 0 ; then
+	       	   AC_DEFINE([ATOMIC_ARM_INLINE_ASM], 1, [Have ARMv6 instructions.])
+	    	   AC_MSG_RESULT([yes])
+		   need_libatomic_ops=no
+	       else
+	    	   AC_MSG_RESULT([no])
+               fi
+	   fi
+      	;;
+        *)
+	    AC_MSG_RESULT([unknown])
+        ;;
+    esac
 fi
 
 AC_MSG_CHECKING([whether $CC knows __thread])
@@ -413,13 +495,19 @@ AC_SUBST(LIBSNDFILE_LIBS)
 
 #### atomic-ops ###
 
-AC_CHECK_HEADERS([atomic_ops.h], [], [
-AC_MSG_ERROR([*** libatomic-ops headers not found])
-])
-
-# Win32 does not need the lib and breaks horribly if we try to include it
-if test "x$os_is_win32" != "x1" ; then
-    LIBS="$LIBS -latomic_ops"
+AC_MSG_CHECKING([whether we need libatomic_ops])
+if test "x$need_libatomic_ops" = "xyes"; then
+   AC_MSG_RESULT([yes])
+   AC_CHECK_HEADERS([atomic_ops.h], [], [
+   AC_MSG_ERROR([*** libatomic-ops headers not found])
+   ])
+
+   # Win32 does not need the lib and breaks horribly if we try to include it
+   if test "x$os_is_win32" != "x1" ; then
+       LIBS="$LIBS -latomic_ops"
+   fi
+else
+   AC_MSG_RESULT([no])
 fi
 
 #### Libsamplerate support (optional) ####
@@ -889,13 +977,9 @@ AC_ARG_ENABLE([polkit],
 
 if test "x${polkit}" != xno ; then
 
-    PKG_CHECK_MODULES(POLKIT, [ polkit-dbus ],
+    PKG_CHECK_MODULES(POLKIT, [ polkit-dbus >= 0.7 ],
         [
             HAVE_POLKIT=1
-            saved_LIBS="$LIBS"
-            LIBS="$LIBS $POLKIT_LIBS"
-            AC_CHECK_FUNCS(polkit_context_is_caller_authorized)
-            LIBS="$saved_LIBS"
             AC_DEFINE([HAVE_POLKIT], 1, [Have PolicyKit])
             policydir=`pkg-config polkit-dbus --variable prefix`/share/PolicyKit/policy/
             AC_SUBST(policydir)
@@ -990,10 +1074,20 @@ fi
 AC_SUBST(PA_ACCESS_GROUP)
 AC_DEFINE_UNQUOTED(PA_ACCESS_GROUP,"$PA_ACCESS_GROUP", [Access group])
 
-AC_ARG_WITH(peruser_esound, AS_HELP_STRING([--with-peruser-esound-socket], [Use per-user esound socket directory, like /tmp/.esd-UID/socket.]))
+AC_ARG_ENABLE(
+        per_user_esound_socket,
+        AS_HELP_STRING([--disable-per-user-esound-socket], [Use global esound socket directory /tmp/.esd/socket.]),
+        [
+            case "${enableval}" in
+                yes) per_user_esound_socket=1 ;;
+                no) per_user_esound_socket=0 ;;
+                *) AC_MSG_ERROR(bad value ${enableval} for --disable-per-user-esound-socket) ;;
+            esac
+        ],
+        [per_user_esound_socket=1])
 
-if test "x$with_peruser_esound" = "xyes"; then
-   AC_DEFINE([USE_PERUSER_ESOUND_SOCKET], [1], [Define this if you want per-user esound socket directories])
+if test "x$per_user_esound_socket" = "x1"; then
+   AC_DEFINE([USE_PER_USER_ESOUND_SOCKET], [1], [Define this if you want per-user esound socket directories])
 fi
 
 #### PulseAudio system runtime dir ####
@@ -1127,32 +1221,38 @@ if test "x${HAVE_POLKIT}" = "x1" ; then
    ENABLE_POLKIT=yes
 fi
 
+ENABLE_PER_USER_ESOUND_SOCKET=no
+if test "x$per_user_esound_socket" = "x1" ; then
+   ENABLE_PER_USER_ESOUND_SOCKET=yes
+fi
+
 echo "
  ---{ $PACKAGE_NAME $VERSION }---
 
-    prefix:                 ${prefix}
-    sysconfdir:             ${sysconfdir}
-    localstatedir:          ${localstatedir}
-    System Runtime Path:    ${PA_SYSTEM_RUNTIME_PATH}
-    Compiler:               ${CC}
-    CFLAGS:                 ${CFLAGS}
-    Have X11:               ${ENABLE_X11}
-    Enable OSS:             ${ENABLE_OSS}
-    Enable Alsa:            ${ENABLE_ALSA}
-    Enable Solaris:         ${ENABLE_SOLARIS}
-    Enable GLib 2.0:        ${ENABLE_GLIB20}
-    Enable GConf:           ${ENABLE_GCONF}
-    Enable Avahi:           ${ENABLE_AVAHI}
-    Enable Jack:            ${ENABLE_JACK}
-    Enable Async DNS:       ${ENABLE_LIBASYNCNS}
-    Enable LIRC:            ${ENABLE_LIRC}
-    Enable HAL:             ${ENABLE_HAL}
-    Enable BlueZ:           ${ENABLE_BLUEZ}
-    Enable TCP Wrappers:    ${ENABLE_TCPWRAP}
-    Enable libsamplerate:   ${ENABLE_LIBSAMPLERATE}
-    Enable PolicyKit:       ${ENABLE_POLKIT}
-    System User:            ${PA_SYSTEM_USER}
-    System Group:           ${PA_SYSTEM_GROUP}
-    Realtime Group:         ${PA_REALTIME_GROUP}
-    Access Group:           ${PA_ACCESS_GROUP}
+    prefix:                        ${prefix}
+    sysconfdir:                    ${sysconfdir}
+    localstatedir:                 ${localstatedir}
+    System Runtime Path:           ${PA_SYSTEM_RUNTIME_PATH}
+    Compiler:                      ${CC}
+    CFLAGS:                        ${CFLAGS}
+    Have X11:                      ${ENABLE_X11}
+    Enable OSS:                    ${ENABLE_OSS}
+    Enable Alsa:                   ${ENABLE_ALSA}
+    Enable Solaris:                ${ENABLE_SOLARIS}
+    Enable GLib 2.0:               ${ENABLE_GLIB20}
+    Enable GConf:                  ${ENABLE_GCONF}
+    Enable Avahi:                  ${ENABLE_AVAHI}
+    Enable Jack:                   ${ENABLE_JACK}
+    Enable Async DNS:              ${ENABLE_LIBASYNCNS}
+    Enable LIRC:                   ${ENABLE_LIRC}
+    Enable HAL:                    ${ENABLE_HAL}
+    Enable BlueZ:                  ${ENABLE_BLUEZ}
+    Enable TCP Wrappers:           ${ENABLE_TCPWRAP}
+    Enable libsamplerate:          ${ENABLE_LIBSAMPLERATE}
+    Enable PolicyKit:              ${ENABLE_POLKIT}
+    System User:                   ${PA_SYSTEM_USER}
+    System Group:                  ${PA_SYSTEM_GROUP}
+    Realtime Group:                ${PA_REALTIME_GROUP}
+    Access Group:                  ${PA_ACCESS_GROUP}
+    Enable per-user EsounD socket: ${ENABLE_PER_USER_ESOUND_SOCKET}
 "
diff --git a/src/Makefile.am b/src/Makefile.am
index df2638c..e537e97 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -64,7 +64,7 @@ AM_LIBADD = $(PTHREAD_LIBS)
 AM_LDADD = $(PTHREAD_LIBS)
 
 # Only required on some platforms but defined for all to avoid errors
-AM_LDFLAGS = -Wl,-no-undefined -ffunction-sections -fdata-sections -Wl,--gc-sections
+AM_LDFLAGS = -Wl,-no-undefined -Wl,--gc-sections
 
 if STATIC_BINS
 BINLDFLAGS = -static
@@ -103,7 +103,7 @@ EXTRA_DIST = \
 		modules/module-defs.h.m4 \
 		daemon/pulseaudio-module-xsmp.desktop \
 		map-file \
-		daemon/PulseAudio.policy
+		daemon/org.pulseaudio.policy
 
 pulseconf_DATA = \
 		default.pa \
@@ -154,7 +154,7 @@ endif
 
 if HAVE_POLKIT
 
-policy_DATA = daemon/PulseAudio.policy
+policy_DATA = daemon/org.pulseaudio.policy
 
 pulseaudio_SOURCES += daemon/polkit.c daemon/polkit.h
 pulseaudio_CFLAGS += $(POLKIT_CFLAGS)
@@ -202,7 +202,7 @@ 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_SOURCES = utils/pasuspender.c pulsecore/core-util.c pulsecore/core-util.h pulsecore/core-error.c pulsecore/core-error.h pulsecore/log.c pulsecore/log.h pulsecore/once.c pulsecore/once.h $(PA_THREAD_OBJS)
 pasuspender_LDADD = $(AM_LDADD) libpulse.la $(LIBSNDFILE_LIBS)
 pasuspender_CFLAGS = $(AM_CFLAGS) $(LIBSNDFILE_CFLAGS)
 pasuspender_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS)
@@ -275,7 +275,7 @@ mainloop_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS)
 
 thread_mainloop_test_SOURCES = tests/thread-mainloop-test.c
 thread_mainloop_test_CFLAGS = $(AM_CFLAGS)
-thread_mainloop_test_LDADD = $(AM_LDADD) libpulse.la
+thread_mainloop_test_LDADD = $(AM_LDADD) libpulsecore.la libpulse.la
 thread_mainloop_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS)
 
 utf8_test_SOURCES = tests/utf8-test.c
@@ -577,7 +577,14 @@ libpulse_la_CFLAGS += $(LIBASYNCNS_CFLAGS)
 libpulse_la_LIBADD += $(LIBASYNCNS_LIBS)
 endif
 
-libpulse_simple_la_SOURCES = pulse/simple.c pulse/simple.h
+libpulse_simple_la_SOURCES = \
+		pulse/simple.c pulse/simple.h	\
+		pulsecore/log.c pulsecore/log.h \
+		pulsecore/core-util.c pulsecore/core-util.h  \
+		pulsecore/core-error.c pulsecore/core-error.h \
+		pulsecore/once.c pulsecore/once.h \
+		$(PA_THREAD_OBJS)
+
 libpulse_simple_la_CFLAGS = $(AM_CFLAGS)
 libpulse_simple_la_LIBADD = $(AM_LIBADD) libpulse.la
 libpulse_simple_la_LDFLAGS = -version-info $(LIBPULSE_SIMPLE_VERSION_INFO) -Wl,-version-script=$(srcdir)/map-file
@@ -587,7 +594,13 @@ libpulse_browse_la_CFLAGS = $(AM_CFLAGS) $(AVAHI_CFLAGS)
 libpulse_browse_la_LIBADD = $(AM_LIBADD) libpulse.la $(AVAHI_LIBS)
 libpulse_browse_la_LDFLAGS = -version-info $(LIBPULSE_BROWSE_VERSION_INFO) -Wl,-version-script=$(srcdir)/map-file
 
-libpulse_mainloop_glib_la_SOURCES = pulse/glib-mainloop.h pulse/glib-mainloop.c
+libpulse_mainloop_glib_la_SOURCES = \
+		pulse/glib-mainloop.h pulse/glib-mainloop.c \
+		pulsecore/log.c pulsecore/log.h \
+		pulsecore/core-util.c pulsecore/core-util.h  \
+		pulsecore/core-error.c pulsecore/core-error.h \
+		pulsecore/once.c pulsecore/once.h \
+		$(PA_THREAD_OBJS)
 libpulse_mainloop_glib_la_CFLAGS = $(AM_CFLAGS) $(GLIB20_CFLAGS)
 libpulse_mainloop_glib_la_LIBADD = $(AM_LIBADD) libpulse.la $(GLIB20_LIBS)
 libpulse_mainloop_glib_la_LDFLAGS = -version-info $(LIBPULSE_MAINLOOP_GLIB_VERSION_INFO) -Wl,-version-script=$(srcdir)/map-file
diff --git a/src/daemon/PulseAudio.policy b/src/daemon/PulseAudio.policy
deleted file mode 100644
index cf9499e..0000000
--- a/src/daemon/PulseAudio.policy
+++ /dev/null
@@ -1,49 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?><!--*-nxml-*-->
-<!DOCTYPE policyconfig PUBLIC
- "-//freedesktop//DTD PolicyKit Policy Configuration 1.0//EN"
- "http://www.freedesktop.org/standards/PolicyKit/1.0/policyconfig.dtd">
-
-<!-- $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.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.
--->
-
-<policyconfig>
-
-  <action id="org.pulseaudio.acquire-real-time">
-    <description>Real-time scheduling for the PulseAudio daemon</description>
-    <message>System policy prevents PulseAudio from acquiring real-time scheduling.</message>
-    <defaults>
-      <allow_any>no</allow_any>
-      <allow_inactive>no</allow_inactive>
-      <allow_active>no</allow_active>
-    </defaults>
-  </action>
-
-  <action id="org.pulseaudio.acquire-high-priority">
-    <description>High-priority scheduling (negative Unix nice level) for the PulseAudio daemon</description>
-    <message>System policy prevents PulseAudio from acquiring high-priority scheduling.</message>
-    <defaults>
-      <allow_any>no</allow_any>
-      <allow_inactive>no</allow_inactive>
-      <allow_active>no</allow_active>
-    </defaults>
-  </action>
-
-</policyconfig>
diff --git a/src/daemon/caps.c b/src/daemon/caps.c
index 44ee355..d78e968 100644
--- a/src/daemon/caps.c
+++ b/src/daemon/caps.c
@@ -90,8 +90,8 @@ int pa_limit_caps(void) {
     cap_t caps;
     cap_value_t nice_cap = CAP_SYS_NICE;
 
-    caps = cap_init();
-    pa_assert(caps);
+    pa_assert_se(caps = cap_init());
+
     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);
@@ -113,28 +113,15 @@ fail:
 }
 
 /* Drop all capabilities, effectively becoming a normal user */
-int pa_drop_caps(void) {
+void pa_drop_caps(void) {
     cap_t caps;
-    int r = -1;
 
-    caps = cap_init();
-    pa_assert(caps);
+    pa_assert_se(prctl(PR_SET_KEEPCAPS, 0, 0, 0, 0) == 0);
 
+    pa_assert_se(caps = cap_init());
     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));
-        goto fail;
-    }
-
-    r = 0;
-
-fail:
+    pa_assert_se(cap_set_proc(caps) == 0);
     cap_free(caps);
-
-    return r;
 }
 
 #else
@@ -144,9 +131,8 @@ int pa_limit_caps(void) {
     return 0;
 }
 
-int pa_drop_caps(void) {
+void pa_drop_caps(void) {
     pa_drop_root();
-    return 0;
 }
 
 #endif
diff --git a/src/daemon/caps.h b/src/daemon/caps.h
index 4cd0957..91c8841 100644
--- a/src/daemon/caps.h
+++ b/src/daemon/caps.h
@@ -25,7 +25,7 @@
 ***/
 
 void pa_drop_root(void);
+void pa_drop_caps(void);
 int pa_limit_caps(void);
-int pa_drop_caps(void);
 
 #endif
diff --git a/src/daemon/cpulimit.c b/src/daemon/cpulimit.c
index b77dd44..620a93a 100644
--- a/src/daemon/cpulimit.c
+++ b/src/daemon/cpulimit.c
@@ -151,7 +151,7 @@ static void signal_handler(int sig) {
 
     } else if (phase == PHASE_SOFT) {
         write_err("Hard CPU time limit exhausted, terminating forcibly.\n");
-        _exit(1); /* Forced exit */
+        abort(); /* Forced exit */
     }
 
     errno = saved_errno;
diff --git a/src/daemon/daemon.conf.in b/src/daemon/daemon.conf.in
index d664962..e4cfb82 100644
--- a/src/daemon/daemon.conf.in
+++ b/src/daemon/daemon.conf.in
@@ -38,7 +38,7 @@
 ; module-idle-time = 20
 ; scache-idle-time = 20
 
-; dl-search-path = @PA_DLSEARCHPATH@
+; dl-search-path = (depends on architecture)
 
 ; default-script-file = @PA_DEFAULT_CONFIG_FILE@
 
diff --git a/src/daemon/default.pa.in b/src/daemon/default.pa.in
index 597993c..064a6cc 100755
--- a/src/daemon/default.pa.in
+++ b/src/daemon/default.pa.in
@@ -37,7 +37,7 @@ load-sample-lazy pulse-hotplug /usr/share/sounds/startup3.wav
 #load-module module-pipe-sink
 
 ### Automatically load driver modules depending on the hardware available
-.ifexists @PA_DLSEARCHPATH@/module-hal-detect at PA_SOEXT@
+.ifexists module-hal-detect at PA_SOEXT@
 load-module module-hal-detect
 .else
 ### Alternatively use the static hardware detection module (for systems that
@@ -46,7 +46,9 @@ load-module module-detect
 .endif
 
 ### Load several protocols
+.ifexists module-esound-protocol-unix at PA_SOEXT@
 load-module module-esound-protocol-unix
+.endif
 load-module module-native-protocol-unix
 
 ### Network access (may be configured with paprefs, so leave this commented
@@ -78,11 +80,6 @@ load-module module-suspend-on-idle
 ### Load X11 bell module
 #load-module module-x11-bell sample=x11-bell
 
-### Publish connection data in the X11 root window
-.ifexists @PA_DLSEARCHPATH@/module-x11-publish at 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
@@ -91,8 +88,17 @@ load-module module-x11-publish
 ### 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 at PA_SOEXT@
+.ifexists module-gconf at PA_SOEXT@
+.nofail
 load-module module-gconf
+.fail
+.endif
+
+### Publish connection data in the X11 root window
+.ifexists module-x11-publish at PA_SOEXT@
+.nofail
+load-module module-x11-publish
+.fail
 .endif
 
 ### Make some devices default
diff --git a/src/daemon/main.c b/src/daemon/main.c
index 7823180..6b0c81d 100644
--- a/src/daemon/main.c
+++ b/src/daemon/main.c
@@ -242,7 +242,8 @@ static int change_user(void) {
     }
 
     set_env("USER", PA_SYSTEM_USER);
-    set_env("LOGNAME", PA_SYSTEM_GROUP);
+    set_env("USERNAME", PA_SYSTEM_USER);
+    set_env("LOGNAME", PA_SYSTEM_USER);
     set_env("HOME", PA_SYSTEM_RUNTIME_PATH);
 
     /* Relevant for pa_runtime_path() */
@@ -778,7 +779,7 @@ int main(int argc, char *argv[]) {
     c->disallow_module_loading = !!conf->disallow_module_loading;
 
     if (r < 0 && conf->fail) {
-        pa_log("failed to initialize daemon.");
+        pa_log("Failed to initialize daemon.");
 #ifdef HAVE_FORK
         if (conf->daemonize)
             pa_loop_write(daemon_pipe[1], &retval, sizeof(retval), NULL);
@@ -792,16 +793,19 @@ int main(int argc, char *argv[]) {
     } else {
 
         retval = 0;
+
+        if (c->default_sink_name &&
+            pa_namereg_get(c, c->default_sink_name, PA_NAMEREG_SINK, 1) == NULL) {
+            pa_log_error("%s : Default sink name (%s) does not exist in name register.", __FILE__, c->default_sink_name);
+            retval = !!conf->fail;
+        }
+
 #ifdef HAVE_FORK
         if (conf->daemonize)
             pa_loop_write(daemon_pipe[1], &retval, sizeof(retval), NULL);
 #endif
 
-        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);
-            retval = 1;
-        } else {
+        if (!retval) {
             pa_log_info("Daemon startup complete.");
             if (pa_mainloop_run(mainloop, &retval) < 0)
                 retval = 1;
diff --git a/src/daemon/org.pulseaudio.policy b/src/daemon/org.pulseaudio.policy
new file mode 100644
index 0000000..507a2cb
--- /dev/null
+++ b/src/daemon/org.pulseaudio.policy
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="UTF-8"?><!--*-nxml-*-->
+<!DOCTYPE policyconfig PUBLIC
+ "-//freedesktop//DTD PolicyKit Policy Configuration 1.0//EN"
+ "http://www.freedesktop.org/standards/PolicyKit/1.0/policyconfig.dtd">
+
+<!-- $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.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.
+-->
+
+<policyconfig>
+  <vendor>The PulseAudio Project</vendor>
+  <vendor_url>http://pulseaudio.org/</vendor_url>
+  <icon_name>audio-card</icon_name>
+
+  <action id="org.pulseaudio.acquire-real-time">
+    <description>Real-time scheduling for the PulseAudio daemon</description>
+    <message>System policy prevents PulseAudio from acquiring real-time scheduling.</message>
+    <defaults>
+      <allow_any>no</allow_any>
+      <allow_inactive>no</allow_inactive>
+      <allow_active>no</allow_active>
+    </defaults>
+  </action>
+
+  <action id="org.pulseaudio.acquire-high-priority">
+    <description>High-priority scheduling (negative Unix nice level) for the PulseAudio daemon</description>
+    <message>System policy prevents PulseAudio from acquiring high-priority scheduling.</message>
+    <defaults>
+      <allow_any>no</allow_any>
+      <allow_inactive>no</allow_inactive>
+      <allow_active>no</allow_active>
+    </defaults>
+  </action>
+
+</policyconfig>
diff --git a/src/daemon/polkit.c b/src/daemon/polkit.c
index 362c519..ce7c83e 100644
--- a/src/daemon/polkit.c
+++ b/src/daemon/polkit.c
@@ -38,59 +38,6 @@
 
 #include "polkit.h"
 
-static pa_bool_t show_grant_dialog(const char *action_id) {
-    DBusError dbus_error;
-    DBusConnection *bus = NULL;
-    DBusMessage *m = NULL, *reply = NULL;
-    pa_bool_t r = FALSE;
-    uint32_t xid = 0;
-    int verdict;
-
-    dbus_error_init(&dbus_error);
-
-    if (!(bus = dbus_bus_get(DBUS_BUS_SESSION, &dbus_error))) {
-        pa_log_error("Cannot connect to session bus: %s", dbus_error.message);
-        goto finish;
-    }
-
-    if (!(m = dbus_message_new_method_call("org.gnome.PolicyKit", "/org/gnome/PolicyKit/Manager", "org.gnome.PolicyKit.Manager", "ShowDialog"))) {
-        pa_log_error("Failed to allocate D-Bus message.");
-        goto finish;
-    }
-
-    if (!(dbus_message_append_args(m, DBUS_TYPE_STRING, &action_id, DBUS_TYPE_UINT32, &xid, DBUS_TYPE_INVALID))) {
-        pa_log_error("Failed to append arguments to D-Bus message.");
-        goto finish;
-    }
-
-    if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &dbus_error))) {
-        pa_log_warn("Failed to show grant dialog: %s", dbus_error.message);
-        goto finish;
-    }
-
-    if (!(dbus_message_get_args(reply, &dbus_error, DBUS_TYPE_BOOLEAN, &verdict, DBUS_TYPE_INVALID))) {
-        pa_log_warn("Malformed response from grant manager: %s", dbus_error.message);
-        goto finish;
-    }
-
-    r = !!verdict;
-
-finish:
-
-    if (bus)
-        dbus_connection_unref(bus);
-
-    dbus_error_free(&dbus_error);
-
-    if (m)
-        dbus_message_unref(m);
-
-    if (reply)
-        dbus_message_unref(reply);
-
-    return r;
-}
-
 int pa_polkit_check(const char *action_id) {
     int ret = -1;
     DBusError dbus_error;
@@ -161,35 +108,32 @@ int pa_polkit_check(const char *action_id) {
 
     for (;;) {
 
-#ifdef HAVE_POLKIT_CONTEXT_IS_CALLER_AUTHORIZED
         polkit_result = polkit_context_is_caller_authorized(context, action, caller, TRUE, &polkit_error);
 
         if (polkit_error_is_set(polkit_error)) {
             pa_log_error("Could not determine whether caller is authorized: %s", polkit_error_get_error_message(polkit_error));
             goto finish;
         }
-#else
-
-        polkit_result = polkit_context_can_caller_do_action(context, action, caller);
-
-#endif
 
         if (polkit_result == POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH ||
             polkit_result == POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_KEEP_SESSION ||
             polkit_result == POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_KEEP_ALWAYS ||
-#ifdef POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_ONE_SHOT
             polkit_result == POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_ONE_SHOT ||
-#endif
             polkit_result == POLKIT_RESULT_ONLY_VIA_SELF_AUTH ||
             polkit_result == POLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_SESSION ||
-            polkit_result == POLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_ALWAYS
-#ifdef POLKIT_RESULT_ONLY_VIA_SELF_AUTH_ONE_SHOT
-            || polkit_result == POLKIT_RESULT_ONLY_VIA_SELF_AUTH_ONE_SHOT
-#endif
+            polkit_result == POLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_ALWAYS ||
+            polkit_result == POLKIT_RESULT_ONLY_VIA_SELF_AUTH_ONE_SHOT
         ) {
 
-            if (show_grant_dialog(action_id))
-                continue;
+            if (polkit_auth_obtain(action_id, 0, getpid(), &dbus_error)) {
+                polkit_result = POLKIT_RESULT_YES;
+                break;
+            }
+
+            if (dbus_error_is_set(&dbus_error)) {
+                pa_log_error("Cannot obtain auth: %s", dbus_error.message);
+                goto finish;
+            }
         }
 
         break;
diff --git a/src/modules/bt-proximity-helper.c b/src/modules/bt-proximity-helper.c
index d80cc0c..5f042c3 100644
--- a/src/modules/bt-proximity-helper.c
+++ b/src/modules/bt-proximity-helper.c
@@ -1,35 +1,29 @@
 /* $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 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.
-***/
-
 /*
  * Small SUID helper that allows us to ping a BT device. Borrows
- * heavily from bluez-utils' l2ping, which is licensed as GPL2+, too
+ * heavily from bluez-utils' l2ping, which is licensed as GPL2+
  * and comes with a copyright like this:
  *
  *  Copyright (C) 2000-2001  Qualcomm Incorporated
  *  Copyright (C) 2002-2003  Maxim Krasnyansky <maxk at qualcomm.com>
  *  Copyright (C) 2002-2007  Marcel Holtmann <marcel at holtmann.org>
  *
+ *
+ *  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
  */
 
 #ifdef HAVE_CONFIG_H
diff --git a/src/modules/module-ladspa-sink.c b/src/modules/module-ladspa-sink.c
index 696b6ea..1ba2b48 100644
--- a/src/modules/module-ladspa-sink.c
+++ b/src/modules/module-ladspa-sink.c
@@ -484,8 +484,7 @@ int pa__init(pa_module*m) {
 
         if (p > n_control || k) {
             pa_log("Too many control values passed, %lu expected.", n_control);
-            if (k)
-                pa_xfree(k);
+            pa_xfree(k);
             goto fail;
         }
 
diff --git a/src/modules/module-protocol-stub.c b/src/modules/module-protocol-stub.c
index a9bd850..600201b 100644
--- a/src/modules/module-protocol-stub.c
+++ b/src/modules/module-protocol-stub.c
@@ -218,7 +218,7 @@ int pa__init(pa_module*m) {
     char tmp[PATH_MAX];
 
 #if defined(USE_PROTOCOL_ESOUND)
-#if defined(USE_PERUSER_ESOUND_SOCKET)
+#if defined(USE_PER_USER_ESOUND_SOCKET)
     char esdsocketpath[PATH_MAX];
 #else
     const char esdsocketpath[] = "/tmp/.esd/socket";
@@ -269,9 +269,10 @@ int pa__init(pa_module*m) {
 
 #if defined(USE_PROTOCOL_ESOUND)
 
-#if defined(USE_PERUSER_ESOUND_SOCKET)
+#if defined(USE_PER_USER_ESOUND_SOCKET)
     snprintf(esdsocketpath, sizeof(esdsocketpath), "/tmp/.esd-%lu/socket", (unsigned long) getuid());
 #endif
+
     pa_runtime_path(pa_modargs_get_value(ma, "socket", esdsocketpath), tmp, sizeof(tmp));
     u->socket_path = pa_xstrdup(tmp);
 
diff --git a/src/modules/module-tunnel.c b/src/modules/module-tunnel.c
index 2da2d13..5483be3 100644
--- a/src/modules/module-tunnel.c
+++ b/src/modules/module-tunnel.c
@@ -723,7 +723,7 @@ static void sink_info_cb(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint3
         goto fail;
     }
 
-    if (strcmp(name, u->sink_name))
+    if (!u->sink_name || strcmp(name, u->sink_name))
         return;
 
     pa_xfree(u->device_description);
@@ -836,7 +836,7 @@ static void source_info_cb(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uin
         goto fail;
     }
 
-    if (strcmp(name, u->source_name))
+    if (!u->source_name || strcmp(name, u->source_name))
         return;
 
     pa_xfree(u->device_description);
diff --git a/src/pulse/util.c b/src/pulse/util.c
index d3ac9f6..b6f57b9 100644
--- a/src/pulse/util.c
+++ b/src/pulse/util.c
@@ -65,7 +65,7 @@
 #include "util.h"
 
 char *pa_get_user_name(char *s, size_t l) {
-    char *p;
+    const char *p;
     char buf[1024];
 
 #ifdef HAVE_PWD_H
@@ -75,7 +75,10 @@ char *pa_get_user_name(char *s, size_t l) {
     pa_assert(s);
     pa_assert(l > 0);
 
-    if (!(p = getenv("USER")) && !(p = getenv("LOGNAME")) && !(p = getenv("USERNAME"))) {
+    if (!(p = (getuid() == 0 ? "root" : NULL)) &&
+        !(p = getenv("USER")) &&
+        !(p = getenv("LOGNAME")) &&
+        !(p = getenv("USERNAME"))) {
 #ifdef HAVE_PWD_H
 
 #ifdef HAVE_GETPWUID_R
diff --git a/src/pulsecore/atomic.h b/src/pulsecore/atomic.h
index c2c9988..ad3dca3 100644
--- a/src/pulsecore/atomic.h
+++ b/src/pulsecore/atomic.h
@@ -36,7 +36,7 @@
  * On gcc >= 4.1 we use the builtin atomic functions. otherwise we use
  * libatomic_ops
  */
-
+#
 #ifndef PACKAGE
 #error "Please include config.h before including this file!"
 #endif
@@ -182,6 +182,235 @@ static inline int pa_atomic_ptr_cmpxchg(pa_atomic_ptr_t *a, void *old_p, void* n
     return result;
 }
 
+#elif defined(ATOMIC_ARM_INLINE_ASM)
+
+/*
+   These should only be enabled if we have ARMv6 or better.
+*/
+
+typedef struct pa_atomic {
+    volatile int value;
+} pa_atomic_t;
+
+#define PA_ATOMIC_INIT(v) { .value = (v) }
+
+static inline void pa_memory_barrier(void) {
+#ifdef ATOMIC_ARM_MEMORY_BARRIER_ENABLED
+    asm volatile ("mcr  p15, 0, r0, c7, c10, 5  @ dmb");
+#endif
+}
+
+static inline int pa_atomic_load(const pa_atomic_t *a) {
+    pa_memory_barrier();
+    return a->value;
+}
+
+static inline void pa_atomic_store(pa_atomic_t *a, int i) {
+    a->value = i;
+    pa_memory_barrier();
+}
+
+/* Returns the previously set value */
+static inline int pa_atomic_add(pa_atomic_t *a, int i) {
+    unsigned long not_exclusive;
+    int new_val, old_val;
+
+    pa_memory_barrier();
+    do {
+        asm volatile ("ldrex    %0, [%3]\n"
+                      "add      %2, %0, %4\n"
+                      "strex    %1, %2, [%3]\n"
+                      : "=&r" (old_val), "=&r" (not_exclusive), "=&r" (new_val)
+                      : "r" (&a->value), "Ir" (i)
+                      : "cc");
+    } while(not_exclusive);
+    pa_memory_barrier();
+
+    return old_val;
+}
+
+/* Returns the previously set value */
+static inline int pa_atomic_sub(pa_atomic_t *a, int i) {
+    unsigned long not_exclusive;
+    int new_val, old_val;
+
+    pa_memory_barrier();
+    do {
+        asm volatile ("ldrex    %0, [%3]\n"
+                      "sub      %2, %0, %4\n"
+                      "strex    %1, %2, [%3]\n"
+                      : "=&r" (old_val), "=&r" (not_exclusive), "=&r" (new_val)
+                      : "r" (&a->value), "Ir" (i)
+                      : "cc");
+    } while(not_exclusive);
+    pa_memory_barrier();
+
+    return old_val;
+}
+
+static inline int pa_atomic_inc(pa_atomic_t *a) {
+    return pa_atomic_add(a, 1);
+}
+
+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) {
+    unsigned long not_equal, not_exclusive;
+
+    pa_memory_barrier();
+    do {
+        asm volatile ("ldrex    %0, [%2]\n"
+                      "subs     %0, %0, %3\n"
+                      "mov      %1, %0\n"
+                      "strexeq %0, %4, [%2]\n"
+                      : "=&r" (not_exclusive), "=&r" (not_equal)
+                      : "r" (&a->value), "Ir" (old_i), "r" (new_i)
+                      : "cc");
+    } while(not_exclusive && !not_equal);
+    pa_memory_barrier();
+
+    return !not_equal;
+}
+
+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) {
+    pa_memory_barrier();
+    return (void*) a->value;
+}
+
+static inline void pa_atomic_ptr_store(pa_atomic_ptr_t *a, void *p) {
+    a->value = (unsigned long) p;
+    pa_memory_barrier();
+}
+
+static inline int pa_atomic_ptr_cmpxchg(pa_atomic_ptr_t *a, void *old_p, void* new_p) {
+    unsigned long not_equal, not_exclusive;
+
+    pa_memory_barrier();
+    do {
+        asm volatile ("ldrex    %0, [%2]\n"
+                      "subs     %0, %0, %3\n"
+                      "mov      %1, %0\n"
+                      "strexeq %0, %4, [%2]\n"
+                      : "=&r" (not_exclusive), "=&r" (not_equal)
+                      : "r" (&a->value), "Ir" (old_p), "r" (new_p)
+                      : "cc");
+    } while(not_exclusive && !not_equal);
+    pa_memory_barrier();
+
+    return !not_equal;
+}
+
+#elif defined(ATOMIC_ARM_LINUX_HELPERS)
+
+/* See file arch/arm/kernel/entry-armv.S in your kernel sources for more
+   information about these functions. The arm kernel helper functions first
+   appeared in 2.6.16.
+   Apply --disable-atomic-arm-linux-helpers flag to confugure if you prefere
+   inline asm implementation or you have an obsolete Linux kernel.
+*/
+/* Memory barrier */
+typedef void (__kernel_dmb_t)(void);
+#define __kernel_dmb (*(__kernel_dmb_t *)0xffff0fa0)
+
+static inline void pa_memory_barrier(void) {
+#ifndef ATOMIC_ARM_MEMORY_BARRIER_ENABLED
+    __kernel_dmb();
+#endif
+}
+
+/* Atomic exchange (__kernel_cmpxchg_t contains memory barriers if needed) */
+typedef int (__kernel_cmpxchg_t)(int oldval, int newval, volatile int *ptr);
+#define __kernel_cmpxchg (*(__kernel_cmpxchg_t *)0xffff0fc0)
+
+/* This is just to get rid of all warnings */
+typedef int (__kernel_cmpxchg_u_t)(unsigned long oldval, unsigned long newval, volatile unsigned long *ptr);
+#define __kernel_cmpxchg_u (*(__kernel_cmpxchg_u_t *)0xffff0fc0)
+
+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) {
+    pa_memory_barrier();
+    return a->value;
+}
+
+static inline void pa_atomic_store(pa_atomic_t *a, int i) {
+    a->value = i;
+    pa_memory_barrier();
+}
+
+/* Returns the previously set value */
+static inline int pa_atomic_add(pa_atomic_t *a, int i) {
+    int old_val;
+    do {
+        old_val = a->value;
+    } while(__kernel_cmpxchg(old_val, old_val + i, &a->value));
+    return old_val;
+}
+
+/* Returns the previously set value */
+static inline int pa_atomic_sub(pa_atomic_t *a, int i) {
+    int old_val;
+    do {
+        old_val = a->value;
+    } while(__kernel_cmpxchg(old_val, old_val - i, &a->value));
+    return old_val;
+}
+
+/* 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) {
+    int failed = 1;
+    do {
+      failed = __kernel_cmpxchg(old_i, new_i, &a->value);
+    } while(failed && a->value == old_i);
+    return !failed;
+}
+
+typedef struct pa_atomic_ptr {
+    volatile unsigned long value;
+} pa_atomic_ptr_t;
+
+#define PA_ATOMIC_PTR_INIT(v) { .value = (unsigned long) (v) }
+
+static inline void* pa_atomic_ptr_load(const pa_atomic_ptr_t *a) {
+    pa_memory_barrier();
+    return (void*) a->value;
+}
+
+static inline void pa_atomic_ptr_store(pa_atomic_ptr_t *a, void *p) {
+    a->value = (unsigned long) p;
+    pa_memory_barrier();
+}
+
+static inline int pa_atomic_ptr_cmpxchg(pa_atomic_ptr_t *a, void *old_p, void* new_p) {
+    int failed = 1;
+    do {
+        failed = __kernel_cmpxchg_u((unsigned long) old_p, (unsigned long) new_p, &a->value);
+    } while(failed && a->value == old_p);
+    return !failed;
+}
+
 #else
 
 /* libatomic_ops based implementation */
diff --git a/src/pulsecore/cli-command.c b/src/pulsecore/cli-command.c
index 73b6619..20510fc 100644
--- a/src/pulsecore/cli-command.c
+++ b/src/pulsecore/cli-command.c
@@ -31,6 +31,7 @@
 #include <stdlib.h>
 #include <errno.h>
 #include <unistd.h>
+#include <ltdl.h>
 
 #include <pulse/xmalloc.h>
 
@@ -1318,8 +1319,35 @@ int pa_cli_command_execute_line_stateful(pa_core *c, const char *s, pa_strbuf *b
                 } else {
                     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");
+                    /* Search DL_SEARCH_PATH unless the filename is absolute */
+                    if (filename[0] == PA_PATH_SEP_CHAR) {
+
+                        *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 {
+                        const char *paths, *state = NULL;
+                        char *p;
+
+                        if (!(paths = lt_dlgetsearchpath()))
+                            return -1;
+
+                        while ((p = pa_split(paths, ":", &state))) {
+                            char *pathname;
+
+                            pathname = pa_sprintf_malloc("%s" PA_PATH_SEP "%s", p, filename);
+                            pa_xfree(p);
+
+                            *ifstate = access(pathname, F_OK) == 0 ? IFSTATE_TRUE : IFSTATE_FALSE;
+                            pa_log_debug("Checking for existance of '%s': %s", pathname, *ifstate == IFSTATE_TRUE ? "success" : "failure");
+
+                            pa_xfree(pathname);
+
+                            if (*ifstate == IFSTATE_TRUE)
+                                break;
+                        }
+                    }
+
                 }
             } else {
                 pa_strbuf_printf(buf, "Invalid meta command: %s\n", cs);
diff --git a/src/pulsecore/hashmap.c b/src/pulsecore/hashmap.c
index f558966..c9d5632 100644
--- a/src/pulsecore/hashmap.c
+++ b/src/pulsecore/hashmap.c
@@ -71,7 +71,7 @@ pa_hashmap *pa_hashmap_new(pa_hash_func_t hash_func, pa_compare_func_t compare_f
     return h;
 }
 
-static void remove(pa_hashmap *h, struct hashmap_entry *e) {
+static void remove_entry(pa_hashmap *h, struct hashmap_entry *e) {
     pa_assert(h);
     pa_assert(e);
 
@@ -103,7 +103,7 @@ void pa_hashmap_free(pa_hashmap*h, void (*free_func)(void *p, void *userdata), v
     while (h->first_entry) {
         if (free_func)
             free_func(h->first_entry->value, userdata);
-        remove(h, h->first_entry);
+        remove_entry(h, h->first_entry);
     }
 
     pa_xfree(h->data);
@@ -182,7 +182,7 @@ void* pa_hashmap_remove(pa_hashmap *h, const void *key) {
         return NULL;
 
     data = e->value;
-    remove(h, e);
+    remove_entry(h, e);
     return data;
 }
 
@@ -220,7 +220,7 @@ void* pa_hashmap_steal_first(pa_hashmap *h) {
         return NULL;
 
     data = h->first_entry->value;
-    remove(h, h->first_entry);
+    remove_entry(h, h->first_entry);
     return data;
 }
 
diff --git a/src/pulsecore/macro.h b/src/pulsecore/macro.h
index 60ab025..1bf2cfb 100644
--- a/src/pulsecore/macro.h
+++ b/src/pulsecore/macro.h
@@ -29,6 +29,8 @@
 #include <assert.h>
 #include <limits.h>
 #include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
 
 #include <pulsecore/log.h>
 #include <pulsecore/gccmacro.h>
@@ -137,35 +139,47 @@ typedef int pa_bool_t;
 #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_if_fail(expr)                                         \
+    do {                                                                \
+        if (PA_UNLIKELY(!(expr))) {                                     \
+            pa_log_debug("Assertion '%s' failed at %s:%u, function %s.\n", #expr , __FILE__, __LINE__, PA_PRETTY_FUNCTION); \
+            return;                                                     \
+        }                                                               \
+    } while(FALSE)
+
+#define pa_return_val_if_fail(expr, val)                                \
+    do {                                                                \
+        if (PA_UNLIKELY(!(expr))) {                                     \
+            pa_log_debug("Assertion '%s' failed at %s:%u, function %s.\n", #expr , __FILE__, __LINE__, PA_PRETTY_FUNCTION); \
+            return (val);                                               \
+        }                                                               \
+    } while(FALSE)
 
 #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 */
+/* An assert which guarantees side effects of x, i.e. is never
+ * optimized away */
+#define pa_assert_se(expr)                                              \
+    do {                                                                \
+        if (PA_UNLIKELY(!(expr))) {                                     \
+            pa_log_error("Assertion '%s' failed at %s:%u, function %s(). Aborting.", #expr , __FILE__, __LINE__, PA_PRETTY_FUNCTION); \
+            abort();                                                    \
+        }                                                               \
+    } while (FALSE)
+
+/* An assert that may be optimized away by defining NDEBUG */
 #ifdef NDEBUG
-#define pa_assert_se(x) x
+#define pa_assert(expr) do {} while (FALSE)
 #else
-#define pa_assert_se(x) pa_assert(x)
+#define pa_assert(expr) pa_assert_se(expr)
 #endif
 
+#define pa_assert_not_reached()                                         \
+    do {                                                                \
+        pa_log_error("Code should not be reached at %s:%u, function %s(). Aborting.", __FILE__, __LINE__, PA_PRETTY_FUNCTION); \
+        abort();                                                        \
+    } while (FALSE)
+
 #define PA_PTR_TO_UINT(p) ((unsigned int) (unsigned long) (p))
 #define PA_UINT_TO_PTR(u) ((void*) (unsigned long) (u))
 
diff --git a/src/pulsecore/protocol-esound.c b/src/pulsecore/protocol-esound.c
index 972e8e1..59a4208 100644
--- a/src/pulsecore/protocol-esound.c
+++ b/src/pulsecore/protocol-esound.c
@@ -72,7 +72,7 @@
 #define RECORD_BUFFER_SECONDS (5)
 #define RECORD_BUFFER_FRAGMENTS (100)
 
-#define MAX_CACHE_SAMPLE_SIZE (1024000)
+#define MAX_CACHE_SAMPLE_SIZE (2048000)
 
 #define SCACHE_PREFIX "esound."
 
diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c
index 811cc80..0ac3ec1 100644
--- a/src/pulsecore/protocol-native.c
+++ b/src/pulsecore/protocol-native.c
@@ -1193,6 +1193,7 @@ static void source_output_moved_cb(pa_source_output *o) {
     pa_tagstruct_putu32(t, s->index);
     pa_tagstruct_putu32(t, o->source->index);
     pa_tagstruct_puts(t, o->source->name);
+    pa_tagstruct_put_boolean(t, pa_source_get_state(o->source) == PA_SOURCE_SUSPENDED);
     pa_pstream_send_tagstruct(s->connection->pstream, t);
 }
 
diff --git a/src/tests/smoother-test.c b/src/tests/smoother-test.c
index caa7df7..0816e76 100644
--- a/src/tests/smoother-test.c
+++ b/src/tests/smoother-test.c
@@ -71,7 +71,7 @@ int main(int argc, char*argv[]) {
             u += 2;
         }
 
-        printf("%llu\t%llu\n", x/PA_USEC_PER_MSEC, pa_smoother_get(s, x)/PA_USEC_PER_MSEC);
+        printf("%llu\t%llu\n", (unsigned long long) (x/PA_USEC_PER_MSEC), (unsigned long long) (pa_smoother_get(s, x)/PA_USEC_PER_MSEC));
     }
 
     pa_smoother_free(s);
diff --git a/src/utils/pactl.c b/src/utils/pactl.c
index 4381d9d..674eaee 100644
--- a/src/utils/pactl.c
+++ b/src/utils/pactl.c
@@ -486,7 +486,7 @@ static void get_autoload_info_callback(pa_context *c, const pa_autoload_info *i,
            i->name,
            i->type == PA_AUTOLOAD_SINK ? "sink" : "source",
            i->module,
-           i->argument);
+           i->argument ? i->argument : "");
 }
 
 static void simple_callback(pa_context *c, int success, void *userdata) {
diff --git a/src/utils/padsp.c b/src/utils/padsp.c
index cb57ff8..d3f034d 100644
--- a/src/utils/padsp.c
+++ b/src/utils/padsp.c
@@ -2307,7 +2307,11 @@ fail:
     return ret;
 }
 
+#ifdef sun
+int ioctl(int fd, int request, ...) {
+#else
 int ioctl(int fd, unsigned long request, ...) {
+#endif
     fd_info *i;
     va_list args;
     void *argp;

commit cdfcf6654cb826682812e9d1096dcfbac77900eb
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Apr 3 13:40:55 2008 +0000

    - deprecate autoload stuff
    - allow setting of the requested latency of a sink input/source output before _put() is called
    - allow sinks/sources to have a "minimal" latency which applies to all requested latencies by sink inputs/source outputs
    - add new client library flags PA_STREAM_ADJUST_LATENCY, PA_STREAM_START_MUTED
    - allow client library to fill in 0 to buffer_attr fields
    - update module-alsa-source following module-alsa-sink
    - other cleanups and fixes
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2215 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/PROTOCOL b/PROTOCOL
index 40863fc..74c08b4 100644
--- a/PROTOCOL
+++ b/PROTOCOL
@@ -79,7 +79,7 @@ New opcodes for notifications:
  PA_COMMAND_PLAYBACK_STREAM_MOVED
  PA_COMMAND_CAPTURE_STREAM_MOVED
 
-### v13, implemented  by >= 0.9.10
+### v13, implemented  by >= 0.9.11
 
 New fields for PA_COMMAND_CREATE_PLAYBACK_STREAM, PA_COMMAND_CREATE_RECORD_STREAM request at the end:
 
@@ -113,7 +113,14 @@ New opcodes for proplist modifications
 New field for PA_COMMAND_PLAY_SAMPLE:
 
   proplist
- 
+
 New field for PA_COMMAND_PLAY_SAMPLE response:
 
   idx
+
+New field for PA_COMMAND_CREATE_PLAYBACK_STREAM at the end:
+
+  start_muted
+
+Buffer attributes for PA_COMMAND_CREATE_PLAYBACK_STREAM and
+PA_COMMAND_CREATE_RECORD_STREAM may now be 0 for default values.
diff --git a/src/modules/module-alsa-sink.c b/src/modules/module-alsa-sink.c
index 7e60cea..1dccf67 100644
--- a/src/modules/module-alsa-sink.c
+++ b/src/modules/module-alsa-sink.c
@@ -73,8 +73,8 @@ PA_MODULE_USAGE(
         "tsched_buffer_watermark=<lower fill watermark>");
 
 #define DEFAULT_DEVICE "default"
-#define DEFAULT_TSCHED_BUFFER_USEC (3*PA_USEC_PER_SEC)
-#define DEFAULT_TSCHED_WATERMARK_USEC (20*PA_USEC_PER_MSEC)
+#define DEFAULT_TSCHED_BUFFER_USEC (2*PA_USEC_PER_SEC)
+#define DEFAULT_TSCHED_WATERMARK_USEC (10*PA_USEC_PER_MSEC)
 
 struct userdata {
     pa_core *core;
@@ -325,7 +325,7 @@ static int unix_write(struct userdata *u) {
 }
 
 static int update_smoother(struct userdata *u) {
-    snd_pcm_sframes_t delay;
+    snd_pcm_sframes_t delay  = 0;
     int64_t frames;
     int err;
     pa_usec_t now1, now2;
@@ -334,6 +334,7 @@ static int update_smoother(struct userdata *u) {
     pa_assert(u->pcm_handle);
 
     /* Let's update the time smoother */
+
     snd_pcm_avail_update(u->pcm_handle);
 
     if (PA_UNLIKELY((err = snd_pcm_delay(u->pcm_handle, &delay)) < 0)) {
@@ -441,6 +442,31 @@ static pa_usec_t hw_sleep_time(struct userdata *u) {
     return usec;
 }
 
+static void update_hwbuf_unused_frames(struct userdata *u) {
+    pa_usec_t usec;
+    size_t b;
+
+    pa_assert(u);
+
+    if ((usec = pa_sink_get_requested_latency(u->sink)) <= 0) {
+        /* Use the full buffer if noone asked us for anything
+         * specific */
+        u->hwbuf_unused_frames = 0;
+        return;
+    }
+
+    b = pa_usec_to_bytes(usec, &u->sink->sample_spec);
+
+    /* We need at least one sample in our buffer */
+
+    if (PA_UNLIKELY(b < u->frame_size))
+        b = u->frame_size;
+
+    u->hwbuf_unused_frames =
+        PA_LIKELY(b < u->hwbuf_size) ?
+        ((u->hwbuf_size - b) / u->frame_size) : 0;
+}
+
 static int update_sw_params(struct userdata *u) {
     size_t avail_min;
     int err;
@@ -465,6 +491,8 @@ static int update_sw_params(struct userdata *u) {
         return err;
     }
 
+    update_hwbuf_unused_frames(u);
+
     return 0;
 }
 
@@ -535,29 +563,6 @@ fail:
     return -1;
 }
 
-static void update_hwbuf_unused_frames(struct userdata *u) {
-    pa_usec_t usec;
-    size_t b;
-
-    pa_assert(u);
-
-    if ((usec = pa_sink_get_requested_latency(u->sink)) <= 0) {
-        /* Use the full buffer if noone asked us for anything
-         * specific */
-        u->hwbuf_unused_frames = 0;
-        return;
-    }
-
-    b = pa_usec_to_bytes(usec, &u->sink->sample_spec);
-
-    /* We need at least one sample in our buffer */
-
-    if (PA_UNLIKELY(b < u->frame_size))
-        b = u->frame_size;
-
-    u->hwbuf_unused_frames = PA_LIKELY(b < u->hwbuf_size) ? ((u->hwbuf_size - b) / u->frame_size) : 0;
-}
-
 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;
 
@@ -608,13 +613,13 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
 
             break;
 
-        case PA_SINK_MESSAGE_ADD_INPUT:
-        case PA_SINK_MESSAGE_REMOVE_INPUT:
-        case PA_SINK_MESSAGE_REMOVE_INPUT_AND_BUFFER: {
-            int r = pa_sink_process_msg(o, code, data, offset, chunk);
-            update_hwbuf_unused_frames(u);
-            return r;
-        }
+/*         case PA_SINK_MESSAGE_ADD_INPUT: */
+/*         case PA_SINK_MESSAGE_REMOVE_INPUT: */
+/*         case PA_SINK_MESSAGE_REMOVE_INPUT_AND_BUFFER: { */
+/*             int r = pa_sink_process_msg(o, code, data, offset, chunk); */
+/*             update_hwbuf_unused_frames(u); */
+/*             return r; */
+/*         } */
     }
 
     return pa_sink_process_msg(o, code, data, offset, chunk);
@@ -703,6 +708,7 @@ static int sink_set_volume_cb(pa_sink *s) {
             }
 
             u->hw_dB_supported = FALSE;
+
         }
 
         alsa_vol = (long) roundf(((float) vol * (u->hw_volume_max - u->hw_volume_min)) / PA_VOLUME_NORM) + u->hw_volume_min;
@@ -776,7 +782,7 @@ static void thread_func(void *userdata) {
     pa_thread_mq_install(&u->thread_mq);
     pa_rtpoll_install(u->rtpoll);
 
-    update_hwbuf_unused_frames(u);
+/*     update_hwbuf_unused_frames(u); */
 
     for (;;) {
         int ret;
@@ -1174,6 +1180,9 @@ int pa__init(pa_module*m) {
 
     u->sink->thread_info.max_rewind = use_tsched ? u->hwbuf_size : 0;
 
+    if (!use_tsched)
+        u->sink->min_latency = pa_bytes_to_usec(u->hwbuf_size, &ss);
+
     pa_log_info("Using %u fragments of size %lu bytes, buffer time is %0.2fms",
                 nfrags, (long unsigned) u->fragment_size,
                 (double) pa_bytes_to_usec(u->hwbuf_size, &ss) / PA_USEC_PER_MSEC);
diff --git a/src/modules/module-alsa-source.c b/src/modules/module-alsa-source.c
index b2d0d43..af20f81 100644
--- a/src/modules/module-alsa-source.c
+++ b/src/modules/module-alsa-source.c
@@ -92,6 +92,8 @@ struct userdata {
     snd_mixer_t *mixer_handle;
     snd_mixer_elem_t *mixer_elem;
     long hw_volume_max, hw_volume_min;
+    long hw_dB_max, hw_dB_min;
+    pa_bool_t hw_dB_supported;
 
     size_t frame_size, fragment_size, hwbuf_size, tsched_watermark;
     unsigned nfragments;
@@ -288,25 +290,28 @@ static int unix_read(struct userdata *u) {
 }
 
 static int update_smoother(struct userdata *u) {
-    snd_pcm_status_t *status;
+    snd_pcm_sframes_t delay = 0;
     int64_t frames;
     int err;
+    pa_usec_t now1, now2;
 
     pa_assert(u);
     pa_assert(u->pcm_handle);
 
-    snd_pcm_status_alloca(&status);
-
     /* Let's update the time smoother */
 
-    if (PA_UNLIKELY((err = snd_pcm_status(u->pcm_handle, status)) < 0)) {
+    snd_pcm_avail_update(u->pcm_handle);
+
+    if (PA_UNLIKELY((err = snd_pcm_delay(u->pcm_handle, &delay)) < 0)) {
         pa_log("Failed to get delay: %s", snd_strerror(err));
         return -1;
     }
 
-    frames = u->frame_index + snd_pcm_status_get_delay(status);
+    frames = u->frame_index + delay;
 
-    pa_smoother_put(u->smoother, pa_rtclock_usec(), pa_bytes_to_usec(frames * u->frame_size, &u->source->sample_spec));
+    now1 = pa_rtclock_usec();
+    now2 = pa_bytes_to_usec(frames * u->frame_size, &u->source->sample_spec);
+    pa_smoother_put(u->smoother, now1, now2);
 
     return 0;
 }
@@ -373,7 +378,7 @@ static int suspend(struct userdata *u) {
 }
 
 static pa_usec_t hw_sleep_time(struct userdata *u) {
-    pa_usec_t usec;
+    pa_usec_t wm, usec;
 
     pa_assert(u);
 
@@ -382,11 +387,17 @@ static pa_usec_t hw_sleep_time(struct userdata *u) {
     if (usec <= 0)
         usec = pa_bytes_to_usec(u->hwbuf_size, &u->source->sample_spec);
 
-    if (usec >= u->tsched_watermark)
-        usec -= u->tsched_watermark;
+    pa_log_debug("hw buffer time: %u ms", (unsigned) (usec / PA_USEC_PER_MSEC));
+
+    wm = pa_bytes_to_usec(u->tsched_watermark, &u->source->sample_spec);
+
+    if (usec >= wm)
+        usec -= wm;
     else
         usec /= 2;
 
+    pa_log_debug("after watermark: %u ms", (unsigned) (usec / PA_USEC_PER_MSEC));
+
     return usec;
 }
 
@@ -470,7 +481,6 @@ static int unsuspend(struct userdata *u) {
     /* FIXME: We need to reload the volume somehow */
 
     snd_pcm_start(u->pcm_handle);
-
     pa_smoother_resume(u->smoother, pa_rtclock_usec());
 
     pa_log_info("Resumed successfully...");
@@ -568,18 +578,24 @@ static int source_get_volume_cb(pa_source *s) {
     pa_assert(u->mixer_elem);
 
     for (i = 0; i < s->sample_spec.channels; i++) {
-        long set_vol, vol;
+        long alsa_vol;
 
         pa_assert(snd_mixer_selem_has_capture_channel(u->mixer_elem, u->mixer_map[i]));
 
-        if ((err = snd_mixer_selem_get_capture_volume(u->mixer_elem, u->mixer_map[i], &vol)) < 0)
-            goto fail;
+        if (u->hw_dB_supported) {
 
-        set_vol = (long) roundf(((float) s->volume.values[i] * (u->hw_volume_max - u->hw_volume_min)) / PA_VOLUME_NORM) + u->hw_volume_min;
+            if ((err = snd_mixer_selem_get_capture_dB(u->mixer_elem, u->mixer_map[i], &alsa_vol)) >= 0) {
+                s->volume.values[i] = pa_sw_volume_from_dB(alsa_vol / 100.0);
+                continue;
+            }
+
+            u->hw_dB_supported = FALSE;
+        }
 
-        /* Try to avoid superfluous volume changes */
-        if (set_vol != vol)
-            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));
+        if ((err = snd_mixer_selem_get_capture_volume(u->mixer_elem, u->mixer_map[i], &alsa_vol)) < 0)
+            goto fail;
+
+        s->volume.values[i] = (pa_volume_t) roundf(((float) (alsa_vol - u->hw_volume_min) * PA_VOLUME_NORM) / (u->hw_volume_max - u->hw_volume_min));
     }
 
     return 0;
@@ -587,8 +603,6 @@ static int source_get_volume_cb(pa_source *s) {
 fail:
     pa_log_error("Unable to read volume: %s", snd_strerror(err));
 
-    s->get_volume = NULL;
-    s->set_volume = NULL;
     return -1;
 }
 
@@ -604,17 +618,36 @@ static int source_set_volume_cb(pa_source *s) {
         long alsa_vol;
         pa_volume_t vol;
 
+
         pa_assert(snd_mixer_selem_has_capture_channel(u->mixer_elem, u->mixer_map[i]));
 
-        vol = s->volume.values[i];
+        vol = PA_MIN(s->volume.values[i], PA_VOLUME_NORM);
+
+        if (u->hw_dB_supported) {
+            alsa_vol = (long) (pa_sw_volume_to_dB(vol) * 100);
+            alsa_vol = PA_CLAMP_UNLIKELY(alsa_vol, u->hw_dB_min, u->hw_dB_max);
+
+
+            if ((err = snd_mixer_selem_set_capture_dB(u->mixer_elem, u->mixer_map[i], alsa_vol, -1)) >= 0) {
+
+                if (snd_mixer_selem_get_capture_dB(u->mixer_elem, u->mixer_map[i], &alsa_vol) >= 0)
+                    s->volume.values[i] = pa_sw_volume_from_dB(alsa_vol / 100.0);
+
+                continue;
+            }
+
+            u->hw_dB_supported = FALSE;
+        }
 
-        if (vol > PA_VOLUME_NORM)
-            vol = PA_VOLUME_NORM;
 
         alsa_vol = (long) roundf(((float) vol * (u->hw_volume_max - u->hw_volume_min)) / PA_VOLUME_NORM) + u->hw_volume_min;
+        alsa_vol = PA_CLAMP_UNLIKELY(alsa_vol, u->hw_volume_min, u->hw_volume_max);
 
         if ((err = snd_mixer_selem_set_capture_volume(u->mixer_elem, u->mixer_map[i], alsa_vol)) < 0)
             goto fail;
+
+        if (snd_mixer_selem_get_capture_volume(u->mixer_elem, u->mixer_map[i], &alsa_vol) >= 0)
+            s->volume.values[i] = (pa_volume_t) roundf(((float) (alsa_vol - u->hw_volume_min) * PA_VOLUME_NORM) / (u->hw_volume_max - u->hw_volume_min));
     }
 
     return 0;
@@ -622,8 +655,6 @@ static int source_set_volume_cb(pa_source *s) {
 fail:
     pa_log_error("Unable to set volume: %s", snd_strerror(err));
 
-    s->get_volume = NULL;
-    s->set_volume = NULL;
     return -1;
 }
 
@@ -636,9 +667,6 @@ static int source_get_mute_cb(pa_source *s) {
 
     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_mute = NULL;
-        s->set_mute = NULL;
         return -1;
     }
 
@@ -656,15 +684,20 @@ static int source_set_mute_cb(pa_source *s) {
 
     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_mute = NULL;
-        s->set_mute = NULL;
         return -1;
     }
 
     return 0;
 }
 
+static void source_update_requested_latency_cb(pa_source *s) {
+    struct userdata *u = s->userdata;
+
+    pa_assert(u);
+
+    update_sw_params(u);
+}
+
 static void thread_func(void *userdata) {
     struct userdata *u = userdata;
 
@@ -694,10 +727,11 @@ static void thread_func(void *userdata) {
                     goto fail;
             }
 
-            if (update_smoother(u) < 0)
-                goto fail;
+            if (work_done)
+                if (update_smoother(u) < 0)
+                    goto fail;
 
-            if (u->use_tsched && work_done) {
+            if (u->use_tsched) {
                 pa_usec_t usec, cusec;
 
                 /* OK, the capture buffer is now empty, let's
@@ -716,6 +750,10 @@ static void thread_func(void *userdata) {
                 /* We don't trust the conversion, so we wake up whatever comes first */
                 pa_rtpoll_set_timer_relative(u->rtpoll, PA_MIN(usec, cusec));
             }
+        } else if (u->use_tsched) {
+
+            /* OK, we're in an invalid state, let's disable our timers */
+            pa_rtpoll_set_timer_disabled(u->rtpoll);
         }
 
         /* Hmm, nothing to do. Let's sleep */
@@ -797,7 +835,7 @@ int pa__init(pa_module*m) {
     const char *dev_id;
     pa_sample_spec ss;
     pa_channel_map map;
-    uint32_t nfrags, frag_size, tsched_size, tsched_watermark;
+    uint32_t nfrags, hwbuf_size, frag_size, tsched_size, tsched_watermark;
     snd_pcm_uframes_t period_frames, tsched_frames;
     size_t frame_size;
     snd_pcm_info_t *pcm_info = NULL;
@@ -846,6 +884,7 @@ int pa__init(pa_module*m) {
         goto fail;
     }
 
+    hwbuf_size = frag_size * nfrags;
     period_frames = frag_size/frame_size;
     tsched_frames = tsched_size/frame_size;
 
@@ -874,6 +913,7 @@ int pa__init(pa_module*m) {
     u->rtpoll = pa_rtpoll_new();
     u->alsa_rtpoll_item = NULL;
     pa_rtpoll_item_new_asyncmsgq(u->rtpoll, PA_RTPOLL_EARLY, u->thread_mq.inq);
+
     u->smoother = pa_smoother_new(DEFAULT_TSCHED_WATERMARK_USEC, DEFAULT_TSCHED_WATERMARK_USEC, TRUE);
     pa_smoother_set_time_offset(u->smoother, pa_rtclock_usec());
 
@@ -929,9 +969,6 @@ int pa__init(pa_module*m) {
         goto fail;
     }
 
-    if (update_sw_params(u) < 0)
-        goto fail;
-
     /* ALSA might tweak the sample spec, so recalculate the frame size */
     frame_size = pa_frame_size(&ss);
 
@@ -996,6 +1033,7 @@ int pa__init(pa_module*m) {
     }
 
     u->source->parent.process_msg = source_process_msg;
+    u->source->update_requested_latency = source_update_requested_latency_cb;
     u->source->userdata = u;
 
     pa_source_set_asyncmsgq(u->source, u->thread_mq.inq);
@@ -1007,24 +1045,85 @@ int pa__init(pa_module*m) {
     u->hwbuf_size = u->fragment_size * nfrags;
     u->tsched_watermark = tsched_watermark;
     u->frame_index = 0;
+    u->hw_dB_supported = FALSE;
+    u->hw_dB_min = u->hw_dB_max = 0;
+    u->hw_volume_min = u->hw_volume_max = 0;
+
+    if (!use_tsched)
+        u->source->min_latency = pa_bytes_to_usec(u->hwbuf_size, &ss);
+
+    pa_log_info("Using %u fragments of size %lu bytes, buffer time is %0.2fms",
+                nfrags, (long unsigned) u->fragment_size,
+                (double) pa_bytes_to_usec(u->hwbuf_size, &ss) / PA_USEC_PER_MSEC);
+
+    if (use_tsched)
+        pa_log_info("Time scheduling watermark is %0.2fms",
+                    (double) pa_bytes_to_usec(u->tsched_watermark, &ss) / PA_USEC_PER_MSEC);
 
-    pa_log_info("Using %u fragments of size %lu bytes.", nfrags, (long unsigned) u->fragment_size);
+    if (update_sw_params(u) < 0)
+        goto fail;
 
     if (u->mixer_handle) {
         pa_assert(u->mixer_elem);
 
         if (snd_mixer_selem_has_capture_volume(u->mixer_elem))
-            if (pa_alsa_calc_mixer_map(u->mixer_elem, &map, u->mixer_map, FALSE) >= 0) {
-                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);
-                u->source->flags |= PA_SOURCE_HW_VOLUME_CTRL;
+            if (pa_alsa_calc_mixer_map(u->mixer_elem, &map, u->mixer_map, FALSE) >= 0 &&
+                snd_mixer_selem_get_capture_volume_range(u->mixer_elem, &u->hw_volume_min, &u->hw_volume_max) >= 0) {
+
+                pa_bool_t suitable = TRUE;
+
+                pa_log_info("Volume ranges from %li to %li.", u->hw_volume_min, u->hw_volume_max);
+
+                if (u->hw_volume_min > u->hw_volume_max) {
+
+                    pa_log_info("Minimal volume %li larger than maximum volume %li. Strange stuff Falling back to software volume control.", u->hw_volume_min, u->hw_volume_max);
+                    suitable = FALSE;
+
+                } else if (u->hw_volume_max - u->hw_volume_min < 3) {
+
+                    pa_log_info("Device has less than 4 volume levels. Falling back to software volume control.");
+                    suitable = FALSE;
+
+                } else if (snd_mixer_selem_get_playback_dB_range(u->mixer_elem, &u->hw_dB_min, &u->hw_dB_max) >= 0) {
+
+                    pa_log_info("Volume ranges from %0.2f dB to %0.2f dB.", u->hw_dB_min/100.0, u->hw_dB_max/100.0);
+
+                    /* Let's see if this thing actually is useful for muting */
+                    if (u->hw_dB_min > -6000) {
+                        pa_log_info("Device cannot attenuate for more than -60 dB (only %0.2f dB supported), falling back to software volume control.", ((double) u->hw_dB_min) / 100);
+
+                        suitable = FALSE;
+                    } else if (u->hw_dB_max < 0) {
+
+                        pa_log_info("Device is still attenuated at maximum volume setting (%0.2f dB is maximum). Strange stuff. Falling back to software volume control.", ((double) u->hw_dB_max) / 100);
+                        suitable = FALSE;
+
+                    } else if (u->hw_dB_min >= u->hw_dB_max) {
+
+                        pa_log_info("Minimal dB (%0.2f) larger or equal to maximum dB (%0.2f). Strange stuff. Falling back to software volume control.", ((double) u->hw_dB_min) / 100, ((double) u->hw_dB_max) / 100);
+                        suitable = FALSE;
+
+                    } else
+                        u->hw_dB_supported = TRUE;
+                }
+
+                if (suitable) {
+                    u->source->get_volume = source_get_volume_cb;
+                    u->source->set_volume = source_set_volume_cb;
+                    u->source->flags |= PA_SOURCE_HW_VOLUME_CTRL | (u->hw_dB_supported ? PA_SOURCE_DECIBEL_VOLUME : 0);
+                    pa_log_info("Using hardware volume control. %s dB scale.", u->hw_dB_supported ? "Using" : "Not using");
+
+                } else {
+                    pa_log_info("Using software volume control. Trying to reset sound card to 0 dB.");
+                    pa_alsa_0dB_capture(u->mixer_elem);
+                }
             }
 
+
         if (snd_mixer_selem_has_capture_switch(u->mixer_elem)) {
             u->source->get_mute = source_get_mute_cb;
             u->source->set_mute = source_set_mute_cb;
-            u->source->flags |= PA_SOURCE_HW_VOLUME_CTRL;
+            u->source->flags |= PA_SOURCE_HW_MUTE_CTRL;
         }
 
         u->mixer_fdl = pa_alsa_fdlist_new();
@@ -1044,10 +1143,21 @@ int pa__init(pa_module*m) {
         goto fail;
     }
     /* Get initial mixer settings */
-    if (u->source->get_volume)
-        u->source->get_volume(u->source);
-    if (u->source->get_mute)
-        u->source->get_mute(u->source);
+    if (data.volume_is_set) {
+        if (u->source->set_volume)
+            u->source->set_volume(u->source);
+    } else {
+        if (u->source->get_volume)
+            u->source->get_volume(u->source);
+    }
+
+    if (data.muted_is_set) {
+        if (u->source->set_mute)
+            u->source->set_mute(u->source);
+    } else {
+        if (u->source->get_mute)
+            u->source->get_mute(u->source);
+    }
 
     pa_source_put(u->source);
 
diff --git a/src/modules/oss-util.c b/src/modules/oss-util.c
index 9598fee..e29f0ed 100644
--- a/src/modules/oss-util.c
+++ b/src/modules/oss-util.c
@@ -251,7 +251,7 @@ int pa_oss_set_fragments(int fd, int nfrags, int frag_size) {
     return 0;
 }
 
-int pa_oss_get_volume(int fd, int mixer, const pa_sample_spec *ss, pa_cvolume *volume) {
+int pa_oss_get_volume(int fd, unsigned long mixer, const pa_sample_spec *ss, pa_cvolume *volume) {
     char cv[PA_CVOLUME_SNPRINT_MAX];
     unsigned vol;
 
@@ -273,7 +273,7 @@ int pa_oss_get_volume(int fd, int mixer, const pa_sample_spec *ss, pa_cvolume *v
     return 0;
 }
 
-int pa_oss_set_volume(int fd, long mixer, const pa_sample_spec *ss, const pa_cvolume *volume) {
+int pa_oss_set_volume(int fd, unsigned long mixer, const pa_sample_spec *ss, const pa_cvolume *volume) {
     char cv[PA_CVOLUME_SNPRINT_MAX];
     unsigned vol;
     pa_volume_t l, r;
diff --git a/src/modules/oss-util.h b/src/modules/oss-util.h
index 259a622..8fea805 100644
--- a/src/modules/oss-util.h
+++ b/src/modules/oss-util.h
@@ -33,8 +33,8 @@ 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_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_set_volume(int fd, unsigned long mixer, const pa_sample_spec *ss, const pa_cvolume *volume);
+int pa_oss_get_volume(int fd, unsigned long mixer, const pa_sample_spec *ss, pa_cvolume *volume);
 
 int pa_oss_get_hw_description(const char *dev, char *name, size_t l);
 
diff --git a/src/pulse/def.h b/src/pulse/def.h
index edda792..ae76660 100644
--- a/src/pulse/def.h
+++ b/src/pulse/def.h
@@ -210,16 +210,68 @@ typedef enum pa_stream_flags {
                                      * on older servers. \since
                                      * 0.9.8 */
     PA_STREAM_PEAK_DETECT = 2048, /**< Find peaks instead of
-                                   * resampling. \since 0.9.9 */
+                                   * resampling. \since 0.9.11 */
+
+    PA_STREAM_START_MUTED = 4096,  /**< Create in muted state. \since 0.9.11 */
+
+
+    PA_STREAM_ADJUST_LATENCY = 8192, /**< Try to adjust the latency of
+                                      * the sink/source based on the
+                                      * requested buffer metrics and
+                                      * adjust buffer metrics
+                                      * accordingly. \since 0.9.11 */
 } pa_stream_flags_t;
 
 /** Playback and record buffer metrics */
 typedef struct pa_buffer_attr {
-    uint32_t maxlength;      /**< Maximum length of the buffer */
-    uint32_t tlength;        /**< Playback only: target length of the buffer. The server tries to assure that at least tlength bytes are always available in the buffer */
-    uint32_t prebuf;         /**< Playback only: pre-buffering. The server does not start with playback before at least prebug bytes are available in the buffer */
-    uint32_t minreq;         /**< Playback only: minimum request. The server does not request less than minreq bytes from the client, instead waints until the buffer is free enough to request more bytes at once */
-    uint32_t fragsize;       /**< Recording only: fragment size. The server sends data in blocks of fragsize bytes size. Large values deminish interactivity with other operations on the connection context but decrease control overhead. */
+    uint32_t maxlength;      /**< Maximum length of the
+                              * buffer. Setting this to 0 will
+                              * initialize this to the maximum value
+                              * supported by server, which is
+                              * recommended. */
+    uint32_t tlength;        /**< Playback only: target length of the
+                              * buffer. The server tries to assure
+                              * that at least tlength bytes are always
+                              * available in the buffer. It is
+                              * recommended to set this to 0, which
+                              * will initialize this to a value that
+                              * is deemed sensible by the
+                              * server. However, this value will
+                              * default to something like 2s, i.e. for
+                              * applications that have specific
+                              * latency requirements this value should
+                              * be set to the maximum latency that the
+                              * application can deal with.  */
+    uint32_t prebuf;         /**< Playback only: pre-buffering. The
+                              * server does not start with playback
+                              * before at least prebug bytes are
+                              * available in the buffer. It is
+                              * recommended to set this to 0, which
+                              * will initialize this to the same value
+                              * as tlength, whatever that may be. */
+    uint32_t minreq;         /**< Playback only: minimum request. The
+                              * server does not request less than
+                              * minreq bytes from the client, instead
+                              * waits until the buffer is free enough
+                              * to request more bytes at once. It is
+                              * recommended to set this to 0, which
+                              * will initialize this to a value that
+                              * is deemed sensible by the server. */
+    uint32_t fragsize;       /**< Recording only: fragment size. The
+                              * server sends data in blocks of
+                              * fragsize bytes size. Large values
+                              * deminish interactivity with other
+                              * operations on the connection context
+                              * but decrease control overhead. It is
+                              * recommended to set this to 0, which
+                              * will initialize this to a value that
+                              * is deemed sensible by the
+                              * server. However, this value will
+                              * default to something like 2s, i.e. for
+                              * applications that have specific
+                              * latency requirements this value should
+                              * be set to the maximum latency that the
+                              * application can deal with. */
 } pa_buffer_attr;
 
 /** Error values as used by pa_context_errno(). Use pa_strerror() to convert these values to human readable strings */
@@ -299,7 +351,9 @@ typedef enum pa_subscription_event_type {
  * source_usec+buffer_usec+transport_usec-sink_usec. (Take care of
  * sign issues!) When connected to a monitor source sink_usec contains
  * the latency of the owning sink. The two latency estimations
- * described here are implemented in pa_stream_get_latency().*/
+ * described here are implemented in pa_stream_get_latency(). Please
+ * note that this structure can be extended as part of evolutionary
+ * API updates at any time in any new release.*/
 typedef struct pa_timing_info {
     struct timeval timestamp; /**< The time when this timing info structure was current */
     int synchronized_clocks;  /**< Non-zero if the local and the
@@ -346,6 +400,11 @@ typedef struct pa_timing_info {
                                * want to use it. Consider using
                                * PA_SEEK_RELATIVE_ON_READ
                                * instead. \since 0.8 */
+
+    pa_usec_t max_sink_usec;   /**< The static configure latency for
+                                * the sink. \since 0.9.10 */
+    pa_usec_t max_source_usec; /**< The static configure latency for
+                                * the source. \since 0.9.10 */
 } pa_timing_info;
 
 /** A structure for the spawn api. This may be used to integrate auto
diff --git a/src/pulse/introspect.c b/src/pulse/introspect.c
index 4b282bd..633ee55 100644
--- a/src/pulse/introspect.c
+++ b/src/pulse/introspect.c
@@ -149,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;
+            pa_bool_t mute = FALSE;
 
             memset(&i, 0, sizeof(i));
             i.proplist = pa_proplist_new();
@@ -160,7 +161,7 @@ static void context_get_sink_info_callback(pa_pdispatch *pd, uint32_t command, P
                 pa_tagstruct_get_channel_map(t, &i.channel_map) < 0 ||
                 pa_tagstruct_getu32(t, &i.owner_module) < 0 ||
                 pa_tagstruct_get_cvolume(t, &i.volume) < 0 ||
-                pa_tagstruct_get_boolean(t, &i.mute) < 0 ||
+                pa_tagstruct_get_boolean(t, &mute) < 0 ||
                 pa_tagstruct_getu32(t, &i.monitor_source) < 0 ||
                 pa_tagstruct_gets(t, &i.monitor_source_name) < 0 ||
                 pa_tagstruct_get_usec(t, &i.latency) < 0 ||
@@ -173,6 +174,7 @@ static void context_get_sink_info_callback(pa_pdispatch *pd, uint32_t command, P
                 goto finish;
             }
 
+            i.mute = (int) mute;
             i.flags = (pa_sink_flags_t) flags;
 
             if (o->callback) {
@@ -266,6 +268,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;
+            pa_bool_t mute = FALSE;
 
             memset(&i, 0, sizeof(i));
             i.proplist = pa_proplist_new();
@@ -277,7 +280,7 @@ static void context_get_source_info_callback(pa_pdispatch *pd, uint32_t command,
                 pa_tagstruct_get_channel_map(t, &i.channel_map) < 0 ||
                 pa_tagstruct_getu32(t, &i.owner_module) < 0 ||
                 pa_tagstruct_get_cvolume(t, &i.volume) < 0 ||
-                pa_tagstruct_get_boolean(t, &i.mute) < 0 ||
+                pa_tagstruct_get_boolean(t, &mute) < 0 ||
                 pa_tagstruct_getu32(t, &i.monitor_of_sink) < 0 ||
                 pa_tagstruct_gets(t, &i.monitor_of_sink_name) < 0 ||
                 pa_tagstruct_get_usec(t, &i.latency) < 0 ||
@@ -290,6 +293,7 @@ static void context_get_source_info_callback(pa_pdispatch *pd, uint32_t command,
                 goto finish;
             }
 
+            i.mute = (int) mute;
             i.flags = (pa_source_flags_t) flags;
 
             if (o->callback) {
@@ -464,17 +468,20 @@ static void context_get_module_info_callback(pa_pdispatch *pd, uint32_t command,
 
         while (!pa_tagstruct_eof(t)) {
             pa_module_info i;
+            pa_bool_t auto_unload = FALSE;
             memset(&i, 0, sizeof(i));
 
             if (pa_tagstruct_getu32(t, &i.index) < 0 ||
                 pa_tagstruct_gets(t, &i.name) < 0 ||
                 pa_tagstruct_gets(t, &i.argument) < 0 ||
                 pa_tagstruct_getu32(t, &i.n_used) < 0 ||
-                pa_tagstruct_get_boolean(t, &i.auto_unload) < 0) {
+                pa_tagstruct_get_boolean(t, &auto_unload) < 0) {
                 pa_context_fail(o->context, PA_ERR_PROTOCOL);
                 goto finish;
             }
 
+            i.auto_unload = (int) auto_unload;
+
             if (o->callback) {
                 pa_module_info_cb_t cb = (pa_module_info_cb_t) o->callback;
                 cb(o->context, &i, 0, o->userdata);
@@ -540,6 +547,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;
+            pa_bool_t mute = FALSE;
 
             memset(&i, 0, sizeof(i));
             i.proplist = pa_proplist_new();
@@ -556,7 +564,7 @@ static void context_get_sink_input_info_callback(pa_pdispatch *pd, uint32_t comm
                 pa_tagstruct_get_usec(t, &i.sink_usec) < 0 ||
                 pa_tagstruct_gets(t, &i.resample_method) < 0 ||
                 pa_tagstruct_gets(t, &i.driver) < 0 ||
-                (o->context->version >= 11 && pa_tagstruct_get_boolean(t, &i.mute) < 0) ||
+                (o->context->version >= 11 && pa_tagstruct_get_boolean(t, &mute) < 0) ||
                 (o->context->version >= 13 && pa_tagstruct_get_proplist(t, i.proplist) < 0)) {
 
                 pa_context_fail(o->context, PA_ERR_PROTOCOL);
@@ -564,6 +572,8 @@ static void context_get_sink_input_info_callback(pa_pdispatch *pd, uint32_t comm
                 goto finish;
             }
 
+            i.mute = (int) mute;
+
             if (o->callback) {
                 pa_sink_input_info_cb_t cb = (pa_sink_input_info_cb_t) o->callback;
                 cb(o->context, &i, 0, o->userdata);
@@ -961,6 +971,7 @@ static void context_get_sample_info_callback(pa_pdispatch *pd, uint32_t command,
 
         while (!pa_tagstruct_eof(t)) {
             pa_sample_info i;
+            pa_bool_t lazy = FALSE;
 
             memset(&i, 0, sizeof(i));
             i.proplist = pa_proplist_new();
@@ -972,7 +983,7 @@ static void context_get_sample_info_callback(pa_pdispatch *pd, uint32_t command,
                 pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 ||
                 pa_tagstruct_get_channel_map(t, &i.channel_map) < 0 ||
                 pa_tagstruct_getu32(t, &i.bytes) < 0 ||
-                pa_tagstruct_get_boolean(t, &i.lazy) < 0 ||
+                pa_tagstruct_get_boolean(t, &lazy) < 0 ||
                 pa_tagstruct_gets(t, &i.filename) < 0 ||
                 (o->context->version >= 13 && pa_tagstruct_get_proplist(t, i.proplist) < 0)) {
 
@@ -980,6 +991,8 @@ static void context_get_sample_info_callback(pa_pdispatch *pd, uint32_t command,
                 goto finish;
             }
 
+            i.lazy = (int) lazy;
+
             if (o->callback) {
                 pa_sample_info_cb_t cb = (pa_sample_info_cb_t) o->callback;
                 cb(o->context, &i, 0, o->userdata);
@@ -1192,6 +1205,8 @@ finish:
     pa_operation_unref(o);
 }
 
+PA_WARN_REFERENCE(pa_context_get_autoload_info_by_name, "Autoload will no longer be implemented by future versions of the PulseAudio server.");
+
 pa_operation* pa_context_get_autoload_info_by_name(pa_context *c, const char *name, pa_autoload_type_t type, pa_autoload_info_cb_t cb, void *userdata) {
     pa_tagstruct *t;
     pa_operation *o;
@@ -1216,6 +1231,8 @@ pa_operation* pa_context_get_autoload_info_by_name(pa_context *c, const char *na
     return o;
 }
 
+PA_WARN_REFERENCE(pa_context_get_autoload_info_by_index, "Autoload will no longer be implemented by future versions of the PulseAudio server.");
+
 pa_operation* pa_context_get_autoload_info_by_index(pa_context *c, uint32_t idx, pa_autoload_info_cb_t cb, void *userdata) {
     pa_tagstruct *t;
     pa_operation *o;
@@ -1238,10 +1255,15 @@ pa_operation* pa_context_get_autoload_info_by_index(pa_context *c, uint32_t idx,
     return o;
 }
 
+
+PA_WARN_REFERENCE(pa_context_get_autoload_info_list, "Autoload will no longer be implemented by future versions of the PulseAudio server.");
+
 pa_operation* pa_context_get_autoload_info_list(pa_context *c, pa_autoload_info_cb_t cb, void *userdata) {
     return pa_context_send_simple_command(c, PA_COMMAND_GET_AUTOLOAD_INFO_LIST, context_get_autoload_info_callback, (pa_operation_cb_t) cb, userdata);
 }
 
+PA_WARN_REFERENCE(pa_context_add_autoload, "Autoload will no longer be implemented by future versions of the PulseAudio server.");
+
 pa_operation* pa_context_add_autoload(pa_context *c, const char *name, pa_autoload_type_t type, const char *module, const char*argument, pa_context_index_cb_t cb, void* userdata) {
     pa_operation *o;
     pa_tagstruct *t;
@@ -1268,6 +1290,8 @@ pa_operation* pa_context_add_autoload(pa_context *c, const char *name, pa_autolo
     return o;
 }
 
+PA_WARN_REFERENCE(pa_context_remove_autoload_by_name, "Autoload will no longer be implemented by future versions of the PulseAudio server.");
+
 pa_operation* pa_context_remove_autoload_by_name(pa_context *c, const char *name, pa_autoload_type_t type, pa_context_success_cb_t cb, void* userdata) {
     pa_operation *o;
     pa_tagstruct *t;
@@ -1291,6 +1315,8 @@ pa_operation* pa_context_remove_autoload_by_name(pa_context *c, const char *name
     return o;
 }
 
+PA_WARN_REFERENCE(pa_context_remove_autoload_by_index, "Autoload will no longer be implemented by future versions of the PulseAudio server.");
+
 pa_operation* pa_context_remove_autoload_by_index(pa_context *c, uint32_t idx, pa_context_success_cb_t cb, void* userdata) {
     pa_operation *o;
     pa_tagstruct *t;
diff --git a/src/pulse/introspect.h b/src/pulse/introspect.h
index 91f738d..bc78996 100644
--- a/src/pulse/introspect.h
+++ b/src/pulse/introspect.h
@@ -212,7 +212,11 @@ PA_C_DECL_BEGIN
 #define PA_PORT_ANALOG_5_1 "analog-5-1"
 #define PA_PORT_ANALOG_4_0 "analog-4-0"
 
-/** Stores information about sinks */
+/** @{ \name Sinks */
+
+/** Stores information about sinks. Please note that this structure
+ * can be extended as part of evolutionary API updates at any time in
+ * any new release. */
 typedef struct pa_sink_info {
     const char *name;                  /**< Name of the sink */
     uint32_t index;                    /**< Index of the sink */
@@ -224,10 +228,11 @@ typedef struct pa_sink_info {
     int mute;                          /**< Mute switch of the sink \since 0.8 */
     uint32_t monitor_source;           /**< Index of the monitor source connected to this sink */
     const char *monitor_source_name;   /**< The name of the monitor source */
-    pa_usec_t latency;                 /**< Length of filled playback buffer of this sink */
+    pa_usec_t latency;                 /**< Length of queued audio in the output buffer. */
     const char *driver;                /**< Driver name. \since 0.8 */
     pa_sink_flags_t flags;             /**< Flags \since 0.8 */
-    pa_proplist *proplist;             /**< Property list \since 0.9.10 */
+    pa_proplist *proplist;             /**< Property list \since 0.9.11 */
+    pa_usec_t max_latency;             /**< The static latency this device has been configured to. \since 0.9.11 */
 } pa_sink_info;
 
 /** Callback prototype for pa_context_get_sink_info_by_name() and friends */
@@ -242,7 +247,31 @@ pa_operation* pa_context_get_sink_info_by_index(pa_context *c, uint32_t id, pa_s
 /** Get the complete sink list */
 pa_operation* pa_context_get_sink_info_list(pa_context *c, pa_sink_info_cb_t cb, void *userdata);
 
-/** Stores information about sources */
+/** Set the volume of a sink device specified by its index */
+pa_operation* pa_context_set_sink_volume_by_index(pa_context *c, uint32_t idx, const pa_cvolume *volume, pa_context_success_cb_t cb, void *userdata);
+
+/** Set the volume of a sink device specified by its name */
+pa_operation* pa_context_set_sink_volume_by_name(pa_context *c, const char *name, const pa_cvolume *volume, pa_context_success_cb_t cb, void *userdata);
+
+/** Set the mute switch of a sink device specified by its index \since 0.8 */
+pa_operation* pa_context_set_sink_mute_by_index(pa_context *c, uint32_t idx, int mute, pa_context_success_cb_t cb, void *userdata);
+
+/** Set the mute switch of a sink device specified by its name \since 0.8 */
+pa_operation* pa_context_set_sink_mute_by_name(pa_context *c, const char *name, int mute, 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);
+
+/** @} */
+
+/** @{ \name Sources */
+
+/** Stores information about sources. Please note that this structure
+ * can be extended as part of evolutionary API updates at any time in
+ * any new release. */
 typedef struct pa_source_info {
     const char *name;                   /**< Name of the source */
     uint32_t index;                     /**< Index of the source */
@@ -258,6 +287,7 @@ typedef struct pa_source_info {
     const char *driver;                 /**< Driver name \since 0.8 */
     pa_source_flags_t flags;            /**< Flags \since 0.8 */
     pa_proplist *proplist;              /**< Property list \since 0.9.10 */
+    pa_usec_t max_latency;              /**< The static latency this device has been configured to. \since 0.9.11 */
 } pa_source_info;
 
 /** Callback prototype for pa_context_get_source_info_by_name() and friends */
@@ -272,7 +302,25 @@ pa_operation* pa_context_get_source_info_by_index(pa_context *c, uint32_t id, pa
 /** Get the complete source list */
 pa_operation* pa_context_get_source_info_list(pa_context *c, pa_source_info_cb_t cb, void *userdata);
 
-/** Server information */
+/** 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);
+
+/** Set the volume of a source device specified by its name \since 0.8 */
+pa_operation* pa_context_set_source_volume_by_name(pa_context *c, const char *name, const pa_cvolume *volume, pa_context_success_cb_t cb, void *userdata);
+
+/** Set the mute switch of a source device specified by its index \since 0.8 */
+pa_operation* pa_context_set_source_mute_by_index(pa_context *c, uint32_t idx, int mute, pa_context_success_cb_t cb, void *userdata);
+
+/** Set the mute switch of a source device specified by its name \since 0.8 */
+pa_operation* pa_context_set_source_mute_by_name(pa_context *c, const char *name, int mute, pa_context_success_cb_t cb, void *userdata);
+
+/** @} */
+
+/** @{ \name Server */
+
+/** Server information. Please note that this structure can be
+ * extended as part of evolutionary API updates at any time in any new
+ * release. */
 typedef struct pa_server_info {
     const char *user_name;              /**< User name of the daemon process */
     const char *host_name;              /**< Host name the daemon is running on */
@@ -290,7 +338,13 @@ typedef void (*pa_server_info_cb_t) (pa_context *c, const pa_server_info*i, void
 /** Get some information about the server */
 pa_operation* pa_context_get_server_info(pa_context *c, pa_server_info_cb_t cb, void *userdata);
 
-/** Stores information about modules */
+/** @} */
+
+/** @{ \name Modules */
+
+/** Stores information about modules. Please note that this structure
+ * can be extended as part of evolutionary API updates at any time in
+ * any new release. */
 typedef struct pa_module_info {
     uint32_t index;                     /**< Index of the module */
     const char*name,                    /**< Name of the module */
@@ -308,7 +362,22 @@ pa_operation* pa_context_get_module_info(pa_context *c, uint32_t idx, pa_module_
 /** Get the complete list of currently loaded modules */
 pa_operation* pa_context_get_module_info_list(pa_context *c, pa_module_info_cb_t cb, void *userdata);
 
-/** Stores information about clients */
+/** Callback prototype for pa_context_load_module() */
+typedef void (*pa_context_index_cb_t)(pa_context *c, uint32_t idx, void *userdata);
+
+/** Load a module. \since 0.5 */
+pa_operation* pa_context_load_module(pa_context *c, const char*name, const char *argument, pa_context_index_cb_t cb, void *userdata);
+
+/** Unload a module. \since 0.5 */
+pa_operation* pa_context_unload_module(pa_context *c, uint32_t idx, pa_context_success_cb_t cb, void *userdata);
+
+/** @} */
+
+/** @{ \name Clients */
+
+/** Stores information about clients. Please note that this structure
+ * can be extended as part of evolutionary API updates at any time in
+ * any new release. */
 typedef struct pa_client_info {
     uint32_t index;                      /**< Index of this client */
     const char *name;                    /**< Name of this client */
@@ -326,7 +395,16 @@ pa_operation* pa_context_get_client_info(pa_context *c, uint32_t idx, pa_client_
 /** Get the complete client list */
 pa_operation* pa_context_get_client_info_list(pa_context *c, pa_client_info_cb_t cb, void *userdata);
 
-/** Stores information about sink inputs */
+/** Kill a client. \since 0.5 */
+pa_operation* pa_context_kill_client(pa_context *c, uint32_t idx, pa_context_success_cb_t cb, void *userdata);
+
+/** @} */
+
+/** @{ \name Sink Inputs */
+
+/** Stores information about sink inputs. Please note that this structure
+ * can be extended as part of evolutionary API updates at any time in
+ * any new release. */
 typedef struct pa_sink_input_info {
     uint32_t index;                      /**< Index of the sink input */
     const char *name;                    /**< Name of the sink input */
@@ -353,7 +431,28 @@ pa_operation* pa_context_get_sink_input_info(pa_context *c, uint32_t idx, pa_sin
 /** Get the complete sink input list */
 pa_operation* pa_context_get_sink_input_info_list(pa_context *c, pa_sink_input_info_cb_t cb, void *userdata);
 
-/** Stores information about source outputs */
+/** Move the specified sink input to a different sink. \since 0.9.5 */
+pa_operation* pa_context_move_sink_input_by_name(pa_context *c, uint32_t idx, char *sink_name, pa_context_success_cb_t cb, void* userdata);
+
+/** Move the specified sink input to a different sink. \since 0.9.5 */
+pa_operation* pa_context_move_sink_input_by_index(pa_context *c, uint32_t idx, uint32_t sink_idx, pa_context_success_cb_t cb, void* userdata);
+
+/** 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);
+
+/** Kill a sink input. \since 0.5 */
+pa_operation* pa_context_kill_sink_input(pa_context *c, uint32_t idx, pa_context_success_cb_t cb, void *userdata);
+
+/** @} */
+
+/** @{ \name Source Outputs */
+
+/** Stores information about source outputs. Please note that this structure
+ * can be extended as part of evolutionary API updates at any time in
+ * any new release. */
 typedef struct pa_source_output_info {
     uint32_t index;                      /**< Index of the sink input */
     const char *name;                    /**< Name of the sink input */
@@ -378,37 +477,28 @@ pa_operation* pa_context_get_source_output_info(pa_context *c, uint32_t idx, pa_
 /** Get the complete list of source outputs */
 pa_operation* pa_context_get_source_output_info_list(pa_context *c, pa_source_output_info_cb_t cb, void *userdata);
 
-/** Set the volume of a sink device specified by its index */
-pa_operation* pa_context_set_sink_volume_by_index(pa_context *c, uint32_t idx, const pa_cvolume *volume, pa_context_success_cb_t cb, void *userdata);
-
-/** Set the volume of a sink device specified by its name */
-pa_operation* pa_context_set_sink_volume_by_name(pa_context *c, const char *name, const pa_cvolume *volume, pa_context_success_cb_t cb, void *userdata);
-
-/** Set the mute switch of a sink device specified by its index \since 0.8 */
-pa_operation* pa_context_set_sink_mute_by_index(pa_context *c, uint32_t idx, int mute, pa_context_success_cb_t cb, void *userdata);
-
-/** Set the mute switch of a sink device specified by its name \since 0.8 */
-pa_operation* pa_context_set_sink_mute_by_name(pa_context *c, const char *name, int mute, pa_context_success_cb_t cb, void *userdata);
+/** Move the specified source output to a different source. \since 0.9.5 */
+pa_operation* pa_context_move_source_output_by_name(pa_context *c, uint32_t idx, char *source_name, pa_context_success_cb_t cb, void* userdata);
 
-/** 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);
+/** 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);
 
-/** 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);
+/** 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);
 
-/** 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);
+/** 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);
 
-/** Set the volume of a source device specified by its name \since 0.8 */
-pa_operation* pa_context_set_source_volume_by_name(pa_context *c, const char *name, const pa_cvolume *volume, pa_context_success_cb_t cb, void *userdata);
+/** Kill a source output. \since 0.5 */
+pa_operation* pa_context_kill_source_output(pa_context *c, uint32_t idx, pa_context_success_cb_t cb, void *userdata);
 
-/** Set the mute switch of a source device specified by its index \since 0.8 */
-pa_operation* pa_context_set_source_mute_by_index(pa_context *c, uint32_t idx, int mute, pa_context_success_cb_t cb, void *userdata);
+/** @} */
 
-/** Set the mute switch of a source device specified by its name \since 0.8 */
-pa_operation* pa_context_set_source_mute_by_name(pa_context *c, const char *name, int mute, pa_context_success_cb_t cb, void *userdata);
+/** @{ \name Statistics */
 
-/** Memory block statistics */
+/** Memory block statistics. Please note that this structure
+ * can be extended as part of evolutionary API updates at any time in
+ * any new release. */
 typedef struct pa_stat_info {
     uint32_t memblock_total;           /**< Currently allocated memory blocks */
     uint32_t memblock_total_size;      /**< Currentl total size of allocated memory blocks */
@@ -423,7 +513,13 @@ typedef void (*pa_stat_info_cb_t) (pa_context *c, const pa_stat_info *i, void *u
 /** Get daemon memory block statistics */
 pa_operation* pa_context_stat(pa_context *c, pa_stat_info_cb_t cb, void *userdata);
 
-/** Stores information about sample cache entries */
+/** @} */
+
+/** @{ \name Cached Samples */
+
+/** Stores information about sample cache entries. Please note that this structure
+ * can be extended as part of evolutionary API updates at any time in
+ * any new release. */
 typedef struct pa_sample_info {
     uint32_t index;                       /**< Index of this entry */
     const char *name;                     /**< Name of this entry */
@@ -449,23 +545,11 @@ pa_operation* pa_context_get_sample_info_by_index(pa_context *c, uint32_t idx, p
 /** Get the complete list of samples stored in the daemon. */
 pa_operation* pa_context_get_sample_info_list(pa_context *c, pa_sample_info_cb_t cb, void *userdata);
 
-/** Kill a client. \since 0.5 */
-pa_operation* pa_context_kill_client(pa_context *c, uint32_t idx, pa_context_success_cb_t cb, void *userdata);
-
-/** Kill a sink input. \since 0.5 */
-pa_operation* pa_context_kill_sink_input(pa_context *c, uint32_t idx, pa_context_success_cb_t cb, void *userdata);
-
-/** Kill a source output. \since 0.5 */
-pa_operation* pa_context_kill_source_output(pa_context *c, uint32_t idx, pa_context_success_cb_t cb, void *userdata);
-
-/** Callback prototype for pa_context_load_module() and pa_context_add_autoload() */
-typedef void (*pa_context_index_cb_t)(pa_context *c, uint32_t idx, void *userdata);
+/** @} */
 
-/** Load a module. \since 0.5 */
-pa_operation* pa_context_load_module(pa_context *c, const char*name, const char *argument, pa_context_index_cb_t cb, void *userdata);
+/** \cond fulldocs */
 
-/** Unload a module. \since 0.5 */
-pa_operation* pa_context_unload_module(pa_context *c, uint32_t idx, pa_context_success_cb_t cb, void *userdata);
+/** @{ \name Autoload Entries */
 
 /** Type of an autoload entry. \since 0.5 */
 typedef enum pa_autoload_type {
@@ -473,7 +557,9 @@ typedef enum pa_autoload_type {
     PA_AUTOLOAD_SOURCE = 1
 } pa_autoload_type_t;
 
-/** Stores information about autoload entries. \since 0.5 */
+/** Stores information about autoload entries. Please note that this structure
+ * can be extended as part of evolutionary API updates at any time in
+ * any new release. \since 0.5 */
 typedef struct pa_autoload_info {
     uint32_t index;               /**< Index of this autoload entry */
     const char *name;             /**< Name of the sink or source */
@@ -503,29 +589,9 @@ pa_operation* pa_context_remove_autoload_by_name(pa_context *c, const char *name
 /** Remove an autoload entry. \since 0.6 */
 pa_operation* pa_context_remove_autoload_by_index(pa_context *c, uint32_t idx, pa_context_success_cb_t cb, void* userdata);
 
-/** Move the specified sink input to a different sink. \since 0.9.5 */
-pa_operation* pa_context_move_sink_input_by_name(pa_context *c, uint32_t idx, char *sink_name, pa_context_success_cb_t cb, void* userdata);
-
-/** Move the specified sink input to a different sink. \since 0.9.5 */
-pa_operation* pa_context_move_sink_input_by_index(pa_context *c, uint32_t idx, uint32_t sink_idx, pa_context_success_cb_t cb, void* userdata);
+/** @} */
 
-/** Move the specified source output to a different source. \since 0.9.5 */
-pa_operation* pa_context_move_source_output_by_name(pa_context *c, uint32_t idx, char *source_name, pa_context_success_cb_t cb, void* userdata);
-
-/** 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);
+/** \endcond */
 
 PA_C_DECL_END
 
diff --git a/src/pulse/stream.c b/src/pulse/stream.c
index 321f222..fb96523 100644
--- a/src/pulse/stream.c
+++ b/src/pulse/stream.c
@@ -292,7 +292,7 @@ void pa_command_stream_moved(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED u
     pa_stream *s;
     uint32_t channel;
     const char *dn;
-    int suspended;
+    pa_bool_t suspended;
     uint32_t di;
 
     pa_assert(pd);
@@ -342,7 +342,7 @@ void pa_command_stream_suspended(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUS
     pa_context *c = userdata;
     pa_stream *s;
     uint32_t channel;
-    int suspended;
+    pa_bool_t suspended;
 
     pa_assert(pd);
     pa_assert(command == PA_COMMAND_PLAYBACK_STREAM_SUSPENDED || command == PA_COMMAND_RECORD_STREAM_SUSPENDED);
@@ -543,15 +543,31 @@ static void create_stream_complete(pa_stream *s) {
     }
 }
 
-static void automatic_buffer_attr(pa_buffer_attr *attr, pa_sample_spec *ss) {
+static void automatic_buffer_attr(pa_stream *s, pa_buffer_attr *attr, const pa_sample_spec *ss) {
+    pa_assert(s);
     pa_assert(attr);
     pa_assert(ss);
 
-    attr->tlength = pa_bytes_per_second(ss)/2;
-    attr->maxlength = (attr->tlength*3)/2;
-    attr->minreq = attr->tlength/50;
-    attr->prebuf = attr->tlength - attr->minreq;
-    attr->fragsize = attr->tlength/50;
+    if (s->context->version >= 13)
+        return;
+
+    /* Version older than 0.9.10 didn't do server side buffer_attr
+     * selection, hence we have to fake it on the client side */
+
+    if (!attr->maxlength <= 0)
+        attr->maxlength = 4*1024*1024; /* 4MB is the maximum queue length PulseAudio <= 0.9.9 supported. */
+
+    if (!attr->tlength <= 0)
+        attr->tlength = pa_bytes_per_second(ss)*2; /* 2s of buffering */
+
+    if (!attr->minreq <= 0)
+        attr->minreq = (9*attr->tlength)/10; /* Ask for more data when there are only 200ms left in the playback buffer */
+
+    if (!attr->prebuf)
+        attr->prebuf = attr->tlength; /* Start to play only when the playback is fully filled up once */
+
+    if (!attr->fragsize)
+        attr->fragsize  = attr->tlength; /* Pass data to the app only when the buffer is filled up once */
 }
 
 void pa_create_stream_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) {
@@ -601,7 +617,7 @@ void pa_create_stream_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED
         pa_sample_spec ss;
         pa_channel_map cm;
         const char *dn = NULL;
-        int suspended;
+        pa_bool_t suspended;
 
         if (pa_tagstruct_get_sample_spec(t, &ss) < 0 ||
             pa_tagstruct_get_channel_map(t, &cm) < 0 ||
@@ -631,7 +647,8 @@ void pa_create_stream_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED
             pa_buffer_attr attr;
             pa_operation *o;
 
-            automatic_buffer_attr(&attr, &ss);
+            memset(&attr, 0, sizeof(attr));
+            automatic_buffer_attr(s, &attr, &ss);
 
             /* If we need to update the buffer metrics, we wait for
              * the the OK for that call before we go to
@@ -718,7 +735,9 @@ static int create_stream(
                                               PA_STREAM_FIX_CHANNELS|
                                               PA_STREAM_DONT_MOVE|
                                               PA_STREAM_VARIABLE_RATE|
-                                              PA_STREAM_PEAK_DETECT)), PA_ERR_INVALID);
+                                              PA_STREAM_PEAK_DETECT|
+                                              PA_STREAM_START_MUTED|
+                                              PA_STREAM_ADJUST_LATENCY)), PA_ERR_INVALID);
 
     PA_CHECK_VALIDITY(s->context, s->context->version >= 12 || !(flags & PA_STREAM_VARIABLE_RATE), PA_ERR_NOTSUPPORTED);
     PA_CHECK_VALIDITY(s->context, s->context->version >= 13 || !(flags & PA_STREAM_PEAK_DETECT), PA_ERR_NOTSUPPORTED);
@@ -727,6 +746,8 @@ static int create_stream(
      * when they are passed but actually not supported. This makes
      * client development easier */
 
+    PA_CHECK_VALIDITY(s->context, direction != PA_STREAM_PLAYBACK || !(flags & (PA_STREAM_START_MUTED)), PA_ERR_INVALID);
+    PA_CHECK_VALIDITY(s->context, direction != PA_STREAM_RECORD || !(flags & (PA_STREAM_PEAK_DETECT)), PA_ERR_INVALID);
     PA_CHECK_VALIDITY(s->context, !volume || volume->channels == s->sample_spec.channels, PA_ERR_INVALID);
     PA_CHECK_VALIDITY(s->context, !sync_stream || (direction == PA_STREAM_PLAYBACK && sync_stream->direction == PA_STREAM_PLAYBACK), PA_ERR_INVALID);
 
@@ -742,15 +763,12 @@ static int create_stream(
         s->buffer_attr = *attr;
         s->manual_buffer_attr = TRUE;
     } else {
-        /* 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/50;
-        s->buffer_attr.prebuf = s->buffer_attr.tlength - s->buffer_attr.minreq;
-        s->buffer_attr.fragsize = s->buffer_attr.tlength/50;
+        memset(&s->buffer_attr, 0, sizeof(s->buffer_attr));
         s->manual_buffer_attr = FALSE;
     }
 
+    automatic_buffer_attr(s, &s->buffer_attr, &s->sample_spec);
+
     if (!dev)
         dev = s->direction == PA_STREAM_PLAYBACK ? s->context->conf->default_sink : s->context->conf->default_source;
 
@@ -805,11 +823,16 @@ static int create_stream(
 
     if (s->context->version >= 13) {
 
+        if (s->direction == PA_STREAM_PLAYBACK)
+            pa_tagstruct_put_boolean(t, flags & PA_STREAM_START_MUTED);
+        else
+            pa_tagstruct_put_boolean(t, flags & PA_STREAM_PEAK_DETECT);
+
         pa_init_proplist(s->proplist);
 
         pa_tagstruct_put(
                 t,
-                PA_TAG_BOOLEAN, flags & PA_STREAM_PEAK_DETECT,
+                PA_TAG_BOOLEAN, flags & PA_STREAM_ADJUST_LATENCY,
                 PA_TAG_PROPLIST, s->proplist,
                 PA_TAG_INVALID);
     }
@@ -1023,6 +1046,7 @@ static void stream_get_timing_info_callback(pa_pdispatch *pd, uint32_t command,
     pa_operation *o = userdata;
     struct timeval local, remote, now;
     pa_timing_info *i;
+    pa_bool_t playing = FALSE;
 
     pa_assert(pd);
     pa_assert(o);
@@ -1047,7 +1071,7 @@ static void stream_get_timing_info_callback(pa_pdispatch *pd, uint32_t command,
 
     } else if (pa_tagstruct_get_usec(t, &i->sink_usec) < 0 ||
                pa_tagstruct_get_usec(t, &i->source_usec) < 0 ||
-               pa_tagstruct_get_boolean(t, &i->playing) < 0 ||
+               pa_tagstruct_get_boolean(t, &playing) < 0 ||
                pa_tagstruct_get_timeval(t, &local) < 0 ||
                pa_tagstruct_get_timeval(t, &remote) < 0 ||
                pa_tagstruct_gets64(t, &i->write_index) < 0 ||
@@ -1058,6 +1082,7 @@ static void stream_get_timing_info_callback(pa_pdispatch *pd, uint32_t command,
 
     } else {
         o->stream->timing_info_valid = 1;
+        i->playing = (int) playing;
 
         pa_gettimeofday(&now);
 
diff --git a/src/pulsecore/cli-command.c b/src/pulsecore/cli-command.c
index 20510fc..ca4be59 100644
--- a/src/pulsecore/cli-command.c
+++ b/src/pulsecore/cli-command.c
@@ -155,10 +155,10 @@ static const struct command commands[] = {
     { "load-sample-dir-lazy",    pa_cli_command_scache_load_dir,    "Lazily load all files in a directory into the sample cache (args: pathname)", 2},
     { "play-file",               pa_cli_command_play_file,          "Play a sound file (args: filename, sink|index)", 3},
     { "list-autoload",           pa_cli_command_autoload_list,      "List autoload entries", 1},
-    { "add-autoload-sink",       pa_cli_command_autoload_add,       "Add autoload entry for a sink (args: sink, module name, arguments)", 4},
-    { "add-autoload-source",     pa_cli_command_autoload_add,       "Add autoload entry for a source (args: source, module name, arguments)", 4},
-    { "remove-autoload-sink",    pa_cli_command_autoload_remove,    "Remove autoload entry for a sink (args: name)", 2},
-    { "remove-autoload-source",  pa_cli_command_autoload_remove,    "Remove autoload entry for a source (args: name)", 2},
+    { "add-autoload-sink",       pa_cli_command_autoload_add,       NULL /*"Add autoload entry for a sink (args: sink, module name, arguments)"*/, 4},
+    { "add-autoload-source",     pa_cli_command_autoload_add,       NULL /*"Add autoload entry for a source (args: source, module name, arguments)"*/, 4},
+    { "remove-autoload-sink",    pa_cli_command_autoload_remove,    NULL /*"Remove autoload entry for a sink (args: name)"*/, 2},
+    { "remove-autoload-source",  pa_cli_command_autoload_remove,    NULL /*"Remove autoload entry for a source (args: name)"*/, 2},
     { "dump",                    pa_cli_command_dump,               "Dump daemon configuration", 1},
     { "list-props",              pa_cli_command_list_props,         NULL, 1},
     { "move-sink-input",         pa_cli_command_move_sink_input,    "Move sink input to another sink (args: index, sink)", 3},
@@ -367,7 +367,7 @@ static int pa_cli_command_info(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_b
     pa_cli_command_sink_inputs(c, t, buf, fail);
     pa_cli_command_source_outputs(c, t, buf, fail);
     pa_cli_command_scache_list(c, t, buf, fail);
-    pa_cli_command_autoload_list(c, t, buf, fail);
+/*     pa_cli_command_autoload_list(c, t, buf, fail); */
     return 0;
 }
 
@@ -905,6 +905,8 @@ static int pa_cli_command_autoload_add(pa_core *c, pa_tokenizer *t, pa_strbuf *b
     pa_assert(buf);
     pa_assert(fail);
 
+    pa_log_warn("Autoload will no longer be implemented by future versions of the PulseAudio server.");
+
     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");
         return -1;
@@ -923,6 +925,8 @@ static int pa_cli_command_autoload_remove(pa_core *c, pa_tokenizer *t, pa_strbuf
     pa_assert(buf);
     pa_assert(fail);
 
+    pa_log_warn("Autoload will no longer be implemented by future versions of the PulseAudio server.");
+
     if (!(name = pa_tokenizer_get(t, 1))) {
         pa_strbuf_puts(buf, "You need to specify a device name\n");
         return -1;
@@ -944,6 +948,8 @@ static int pa_cli_command_autoload_list(pa_core *c, pa_tokenizer *t, pa_strbuf *
     pa_assert(buf);
     pa_assert(fail);
 
+    pa_log_warn("Autoload will no longer be implemented by future versions of the PulseAudio server.");
+
     pa_assert_se(s = pa_autoload_list_to_string(c));
     pa_strbuf_puts(buf, s);
     pa_xfree(s);
diff --git a/src/pulsecore/macro.h b/src/pulsecore/macro.h
index 1bf2cfb..a301bba 100644
--- a/src/pulsecore/macro.h
+++ b/src/pulsecore/macro.h
@@ -204,4 +204,17 @@ static inline const char *pa_strnull(const char *x) {
     return x ? x : "(null)";
 }
 
+#ifdef __GNUC__
+
+#define PA_WARN_REFERENCE(sym,msg)              \
+    __asm__(".section .gnu.warning.sym");       \
+    __asm__(".asciz \"msg\"");                  \
+    __asm__(".previous")
+
+#else
+
+#define PA_WARN_REFERENCE(sym,msg)
+
+#endif
+
 #endif
diff --git a/src/pulsecore/memblockq.c b/src/pulsecore/memblockq.c
index cc5e9e1..1d9583e 100644
--- a/src/pulsecore/memblockq.c
+++ b/src/pulsecore/memblockq.c
@@ -138,7 +138,7 @@ static void fix_current_read(pa_memblockq *bq) {
             break;
 
     /* Scan right */
-    while (PA_LIKELY(bq->current_read != NULL) && PA_UNLIKELY(bq->current_read->index + bq->current_read->chunk.length <= bq->read_index))
+    while (PA_LIKELY(bq->current_read != NULL) && PA_UNLIKELY(bq->current_read->index + (int64_t) bq->current_read->chunk.length <= bq->read_index))
         bq->current_read = bq->current_read->next;
 
     /* At this point current_read will either point at or left of the
@@ -158,7 +158,7 @@ static void fix_current_write(pa_memblockq *bq) {
         bq->current_write = bq->blocks_tail;
 
     /* Scan right */
-    while (PA_UNLIKELY(bq->current_write->index + bq->current_write->chunk.length <= bq->write_index))
+    while (PA_UNLIKELY(bq->current_write->index + (int64_t) bq->current_write->chunk.length <= bq->write_index))
 
         if (bq->current_write->next)
             bq->current_write = bq->current_write->next;
@@ -214,7 +214,7 @@ static void drop_backlog(pa_memblockq *bq) {
 
     boundary = bq->read_index - bq->maxrewind;
 
-    while (bq->blocks && (bq->blocks->index + bq->blocks->chunk.length <= boundary))
+    while (bq->blocks && (bq->blocks->index + (int64_t) bq->blocks->chunk.length <= boundary))
         drop_block(bq, bq->blocks);
 }
 
@@ -232,10 +232,10 @@ static pa_bool_t can_push(pa_memblockq *bq, size_t l) {
             return TRUE;
     }
 
-    end = bq->blocks_tail ? bq->blocks_tail->index + bq->blocks_tail->chunk.length : bq->write_index;
+    end = bq->blocks_tail ? bq->blocks_tail->index + (int64_t) bq->blocks_tail->chunk.length : bq->write_index;
 
     /* Make sure that the list doesn't get too long */
-    if (bq->write_index + l > end)
+    if (bq->write_index + (int64_t) l > end)
         if (bq->write_index + l - bq->read_index > bq->maxlength)
             return FALSE;
 
@@ -269,7 +269,7 @@ int pa_memblockq_push(pa_memblockq* bq, const pa_memchunk *uchunk) {
      * write to */
 
     if (q) {
-        while (bq->write_index + chunk.length > q->index)
+        while (bq->write_index + (int64_t) chunk.length > q->index)
             if (q->next)
                 q = q->next;
             else
@@ -284,10 +284,10 @@ int pa_memblockq_push(pa_memblockq* bq, const pa_memchunk *uchunk) {
 
     while (q) {
 
-        if (bq->write_index >= q->index + 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 + 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 &&
@@ -407,7 +407,7 @@ finish:
 
     delta = bq->write_index - old;
 
-    if (delta >= bq->requested) {
+    if (delta >= (int64_t) bq->requested) {
         delta -= bq->requested;
         bq->requested = 0;
     } else {
@@ -526,7 +526,7 @@ void pa_memblockq_drop(pa_memblockq *bq, size_t length) {
             pa_assert(p >= bq->read_index);
             d = p - bq->read_index;
 
-            if (d > length)
+            if (d > (int64_t) length)
                 d = length;
 
             bq->read_index += d;
@@ -606,7 +606,7 @@ void pa_memblockq_seek(pa_memblockq *bq, int64_t offset, pa_seek_mode_t seek) {
 
     delta = bq->write_index - old;
 
-    if (delta >= bq->requested) {
+    if (delta >= (int64_t) bq->requested) {
         delta -= bq->requested;
         bq->requested = 0;
     } else if (delta >= 0) {
@@ -633,7 +633,7 @@ void pa_memblockq_flush(pa_memblockq *bq) {
 
     delta = bq->write_index - old;
 
-    if (delta >= bq->requested) {
+    if (delta >= (int64_t) bq->requested) {
         delta -= bq->requested;
         bq->requested = 0;
     } else if (delta >= 0) {
diff --git a/src/pulsecore/module.c b/src/pulsecore/module.c
index ae140ff..8e5bd2d 100644
--- a/src/pulsecore/module.c
+++ b/src/pulsecore/module.c
@@ -109,8 +109,8 @@ pa_module* pa_module_load(pa_core *c, const char *name, const char *argument) {
     m->userdata = NULL;
     m->core = c;
     m->n_used = -1;
-    m->auto_unload = 0;
-    m->unload_requested = 0;
+    m->auto_unload = FALSE;
+    m->unload_requested = FALSE;
 
     if (m->init(m) < 0) {
         pa_log_error("Failed to load  module \"%s\" (argument: \"%s\"): initialization failed.", name, argument ? argument : "");
@@ -281,7 +281,7 @@ static void defer_cb(pa_mainloop_api*api, pa_defer_event *e, void *userdata) {
 void pa_module_unload_request(pa_module *m) {
     pa_assert(m);
 
-    m->unload_requested = 1;
+    m->unload_requested = TRUE;
 
     if (!m->core->module_defer_unload_event)
         m->core->module_defer_unload_event = m->core->mainloop->defer_new(m->core->mainloop, defer_cb, m->core);
diff --git a/src/pulsecore/module.h b/src/pulsecore/module.h
index 25f122d..68c7238 100644
--- a/src/pulsecore/module.h
+++ b/src/pulsecore/module.h
@@ -45,10 +45,10 @@ struct pa_module {
     void *userdata;
 
     int n_used;
-    int auto_unload;
+    pa_bool_t auto_unload;
     time_t last_used_time;
 
-    int unload_requested;
+    pa_bool_t unload_requested;
 };
 
 pa_module* pa_module_load(pa_core *c, const char *name, const char*argument);
diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c
index 0ac3ec1..59d1612 100644
--- a/src/pulsecore/protocol-native.c
+++ b/src/pulsecore/protocol-native.c
@@ -71,6 +71,8 @@
 #define MAX_CONNECTIONS 64
 
 #define MAX_MEMBLOCKQ_LENGTH (4*1024*1024) /* 4MB */
+#define DEFAULT_TLENGTH_MSEC 2000 /* 2s */
+#define DEFAULT_FRAGSIZE_MSEC DEFAULT_TLENGTH_MSEC
 
 typedef struct connection connection;
 struct pa_protocol_native;
@@ -469,9 +471,10 @@ static record_stream* record_stream_new(
         pa_channel_map *map,
         const char *name,
         uint32_t *maxlength,
-        uint32_t fragment_size,
+        uint32_t *fragsize,
         pa_source_output_flags_t flags,
-        pa_proplist *p) {
+        pa_proplist *p,
+        pa_bool_t adjust_latency) {
 
     record_stream *s;
     pa_source_output *source_output;
@@ -482,7 +485,6 @@ static record_stream* record_stream_new(
     pa_assert(ss);
     pa_assert(name);
     pa_assert(maxlength);
-    pa_assert(*maxlength > 0);
     pa_assert(p);
 
     pa_source_output_new_data_init(&data);
@@ -508,6 +510,7 @@ static record_stream* record_stream_new(
     s->parent.process_msg = record_stream_process_msg;
     s->connection = c;
     s->source_output = source_output;
+
     s->source_output->push = source_output_push_cb;
     s->source_output->kill = source_output_kill_cb;
     s->source_output->get_latency = source_output_get_latency_cb;
@@ -515,11 +518,36 @@ static record_stream* record_stream_new(
     s->source_output->suspend = source_output_suspend_cb;
     s->source_output->userdata = s;
 
+    if (*maxlength <= 0 || *maxlength > MAX_MEMBLOCKQ_LENGTH)
+        *maxlength = MAX_MEMBLOCKQ_LENGTH;
+    if (*fragsize <= 0)
+        *fragsize = pa_usec_to_bytes(DEFAULT_FRAGSIZE_MSEC*1000, &source_output->sample_spec);
+
+    if (adjust_latency) {
+        pa_usec_t fragsize_usec, source_latency;
+
+        /* So, the user asked us to adjust the latency according to
+         * the what the source can provide. Half the latency will be
+         * spent on the hw buffer, half of it in the async buffer
+         * queue we maintain for each client. */
+
+        fragsize_usec = pa_bytes_to_usec(*fragsize, &source_output->sample_spec);
+
+        source_latency = pa_source_output_set_requested_latency(source_output, fragsize_usec/2);
+
+        if (fragsize_usec >= source_latency*2)
+            fragsize_usec -= source_latency;
+        else
+            fragsize_usec = source_latency;
+
+        *fragsize = pa_usec_to_bytes(fragsize_usec, &source_output->sample_spec);
+    }
+
     s->memblockq = pa_memblockq_new(
             0,
             *maxlength,
             0,
-            base = pa_frame_size(&s->source_output->sample_spec),
+            base = pa_frame_size(&source_output->sample_spec),
             1,
             0,
             0,
@@ -527,13 +555,15 @@ static record_stream* record_stream_new(
 
     *maxlength = pa_memblockq_get_maxlength(s->memblockq);
 
-    s->fragment_size = (fragment_size/base)*base;
+    s->fragment_size = (*fragsize/base)*base;
     if (s->fragment_size <= 0)
         s->fragment_size = base;
 
     if (s->fragment_size > *maxlength)
         s->fragment_size = *maxlength;
 
+    *fragsize = s->fragment_size;
+
     *ss = s->source_output->sample_spec;
     *map = s->source_output->channel_map;
 
@@ -658,10 +688,12 @@ static playback_stream* playback_stream_new(
         uint32_t *prebuf,
         uint32_t *minreq,
         pa_cvolume *volume,
+        pa_bool_t muted,
         uint32_t syncid,
         uint32_t *missing,
         pa_sink_input_flags_t flags,
-        pa_proplist *p) {
+        pa_proplist *p,
+        pa_bool_t adjust_latency) {
 
     playback_stream *s, *ssync;
     pa_sink_input *sink_input;
@@ -674,6 +706,11 @@ static playback_stream* playback_stream_new(
     pa_assert(ss);
     pa_assert(name);
     pa_assert(maxlength);
+    pa_assert(tlength);
+    pa_assert(prebuf);
+    pa_assert(minreq);
+    pa_assert(volume);
+    pa_assert(missing);
     pa_assert(p);
 
     /* Find syncid group */
@@ -706,6 +743,7 @@ static playback_stream* playback_stream_new(
     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);
+    pa_sink_input_new_data_set_muted(&data, muted);
     data.sync_base = ssync ? ssync->sink_input : NULL;
 
     sink_input = pa_sink_input_new(c->protocol->core, &data, flags);
@@ -732,13 +770,49 @@ static playback_stream* playback_stream_new(
 
     start_index = ssync ? pa_memblockq_get_read_index(ssync->memblockq) : 0;
 
-    silence = pa_silence_memblock_new(c->protocol->core->mempool, &s->sink_input->sample_spec, 0);
+    if (*maxlength <= 0 || *maxlength > MAX_MEMBLOCKQ_LENGTH)
+        *maxlength = MAX_MEMBLOCKQ_LENGTH;
+    if (*tlength <= 0)
+        *tlength = pa_usec_to_bytes(DEFAULT_TLENGTH_MSEC*1000, &sink_input->sample_spec);
+    if (*minreq <= 0)
+        *minreq = (*tlength*9)/10;
+    if (*prebuf <= 0)
+        *prebuf = *tlength;
+
+    if (adjust_latency) {
+        pa_usec_t tlength_usec, minreq_usec, sink_latency;
+
+        /* So, the user asked us to adjust the latency according to
+         * the what the sink can provide. Half the latency will be
+         * spent on the hw buffer, half of it in the async buffer
+         * queue we maintain for each client. */
+
+        tlength_usec = pa_bytes_to_usec(*tlength, &sink_input->sample_spec);
+        minreq_usec = pa_bytes_to_usec(*minreq, &sink_input->sample_spec);
+
+        sink_latency = pa_sink_input_set_requested_latency(sink_input, tlength_usec/2);
+
+        if (tlength_usec >= sink_latency*2)
+            tlength_usec -= sink_latency;
+        else
+            tlength_usec = sink_latency;
+
+        if (minreq_usec >= sink_latency*2)
+            minreq_usec -= sink_latency;
+        else
+            minreq_usec = sink_latency;
+
+        *tlength = pa_usec_to_bytes(tlength_usec, &sink_input->sample_spec);
+        *minreq = pa_usec_to_bytes(minreq_usec, &sink_input->sample_spec);
+    }
+
+    silence = pa_silence_memblock_new(c->protocol->core->mempool, &sink_input->sample_spec, 0);
 
     s->memblockq = pa_memblockq_new(
             start_index,
             *maxlength,
             *tlength,
-            pa_frame_size(&s->sink_input->sample_spec),
+            pa_frame_size(&sink_input->sample_spec),
             *prebuf,
             *minreq,
             0,
@@ -762,7 +836,6 @@ static playback_stream* playback_stream_new(
     pa_idxset_put(c->output_streams, s, &s->index);
 
     pa_sink_input_put(s->sink_input);
-
     return s;
 }
 
@@ -1230,8 +1303,18 @@ static void command_create_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GC
     pa_tagstruct *reply;
     pa_sink *sink = NULL;
     pa_cvolume volume;
-    int corked;
-    int no_remap = 0, no_remix = 0, fix_format = 0, fix_rate = 0, fix_channels = 0, no_move = 0, variable_rate = 0;
+    pa_bool_t
+        corked = FALSE,
+        no_remap = FALSE,
+        no_remix = FALSE,
+        fix_format = FALSE,
+        fix_rate = FALSE,
+        fix_channels = FALSE,
+        no_move = FALSE,
+        variable_rate = FALSE,
+        muted = FALSE,
+        adjust_latency = FALSE;
+
     pa_sink_input_flags_t flags = 0;
     pa_proplist *p;
 
@@ -1264,8 +1347,6 @@ static void command_create_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GC
     CHECK_VALIDITY(c->pstream, pa_sample_spec_valid(&ss), tag, PA_ERR_INVALID);
     CHECK_VALIDITY(c->pstream, pa_cvolume_valid(&volume), tag, PA_ERR_INVALID);
     CHECK_VALIDITY(c->pstream, map.channels == ss.channels && volume.channels == ss.channels, tag, PA_ERR_INVALID);
-    CHECK_VALIDITY(c->pstream, maxlength > 0, tag, PA_ERR_INVALID);
-    CHECK_VALIDITY(c->pstream, maxlength <= MAX_MEMBLOCKQ_LENGTH, tag, PA_ERR_INVALID);
 
     p = pa_proplist_new();
 
@@ -1291,7 +1372,9 @@ static void command_create_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GC
 
     if (c->version >= 13) {
 
-        if (pa_tagstruct_get_proplist(t, p) < 0) {
+        if (pa_tagstruct_get_boolean(t, &muted) < 0 ||
+            pa_tagstruct_get_boolean(t, &adjust_latency) < 0 ||
+            pa_tagstruct_get_proplist(t, p) < 0) {
             protocol_error(c);
             pa_proplist_free(p);
             return;
@@ -1331,7 +1414,7 @@ static void command_create_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GC
         (no_move ?  PA_SINK_INPUT_DONT_MOVE : 0) |
         (variable_rate ?  PA_SINK_INPUT_VARIABLE_RATE : 0);
 
-    s = playback_stream_new(c, sink, &ss, &map, name, &maxlength, &tlength, &prebuf, &minreq, &volume, syncid, &missing, flags, p);
+    s = playback_stream_new(c, sink, &ss, &map, name, &maxlength, &tlength, &prebuf, &minreq, &volume, muted, syncid, &missing, flags, p, adjust_latency);
     pa_proplist_free(p);
 
     CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_INVALID);
@@ -1438,8 +1521,16 @@ static void command_create_record_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_
     pa_channel_map map;
     pa_tagstruct *reply;
     pa_source *source = NULL;
-    int corked;
-    int no_remap = 0, no_remix = 0, fix_format = 0, fix_rate = 0, fix_channels = 0, no_move = 0, variable_rate = 0;
+    pa_bool_t
+        corked = FALSE,
+        no_remap = FALSE,
+        no_remix = FALSE,
+        fix_format = FALSE,
+        fix_rate = FALSE,
+        fix_channels = FALSE,
+        no_move = FALSE,
+        variable_rate = FALSE,
+        adjust_latency = FALSE;
     pa_source_output_flags_t flags = 0;
     pa_proplist *p;
 
@@ -1463,8 +1554,6 @@ static void command_create_record_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_
     CHECK_VALIDITY(c->pstream, pa_channel_map_valid(&map), tag, PA_ERR_INVALID);
     CHECK_VALIDITY(c->pstream, source_index != PA_INVALID_INDEX || !source_name || (*source_name && pa_utf8_valid(source_name)), tag, PA_ERR_INVALID);
     CHECK_VALIDITY(c->pstream, map.channels == ss.channels, tag, PA_ERR_INVALID);
-    CHECK_VALIDITY(c->pstream, maxlength > 0, tag, PA_ERR_INVALID);
-    CHECK_VALIDITY(c->pstream, maxlength <= MAX_MEMBLOCKQ_LENGTH, tag, PA_ERR_INVALID);
 
     p = pa_proplist_new();
 
@@ -1490,7 +1579,8 @@ static void command_create_record_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_
 
     if (c->version >= 13) {
 
-        if (pa_tagstruct_get_proplist(t, p) < 0) {
+        if (pa_tagstruct_get_boolean(t, &adjust_latency) < 0 ||
+            pa_tagstruct_get_proplist(t, p) < 0) {
             protocol_error(c);
             pa_proplist_free(p);
             return;
@@ -1530,7 +1620,7 @@ static void command_create_record_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_
         (no_move ?  PA_SOURCE_OUTPUT_DONT_MOVE : 0) |
         (variable_rate ?  PA_SOURCE_OUTPUT_VARIABLE_RATE : 0);
 
-    s = record_stream_new(c, source, &ss, &map, name, &maxlength, fragment_size, flags, p);
+    s = record_stream_new(c, source, &ss, &map, name, &maxlength, &fragment_size, flags, p, adjust_latency);
     pa_proplist_free(p);
 
     CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_INVALID);
@@ -1544,7 +1634,7 @@ static void command_create_record_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_
         /* Since 0.9 we support sending the buffer metrics back to the client */
 
         pa_tagstruct_putu32(reply, (uint32_t) maxlength);
-        pa_tagstruct_putu32(reply, (uint32_t) s->fragment_size);
+        pa_tagstruct_putu32(reply, (uint32_t) fragment_size);
     }
 
     if (c->version >= 12) {
@@ -1873,7 +1963,7 @@ static void command_get_record_latency(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UN
     reply = reply_new(tag);
     pa_tagstruct_put_usec(reply, s->source_output->source->monitor_of ? pa_sink_get_latency(s->source_output->source->monitor_of) : 0);
     pa_tagstruct_put_usec(reply, pa_source_get_latency(s->source_output->source));
-    pa_tagstruct_put_boolean(reply, 0);
+    pa_tagstruct_put_boolean(reply, FALSE);
     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));
@@ -2511,7 +2601,7 @@ static void command_set_mute(
 
     connection *c = CONNECTION(userdata);
     uint32_t idx;
-    int mute;
+    pa_bool_t mute;
     pa_sink *sink = NULL;
     pa_source *source = NULL;
     pa_sink_input *si = NULL;
@@ -2574,7 +2664,7 @@ static void command_set_mute(
 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) {
     connection *c = CONNECTION(userdata);
     uint32_t idx;
-    int b;
+    pa_bool_t b;
     playback_stream *s;
 
     connection_assert_ref(c);
@@ -2641,7 +2731,7 @@ static void command_cork_record_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UN
     connection *c = CONNECTION(userdata);
     uint32_t idx;
     record_stream *s;
-    int b;
+    pa_bool_t b;
 
     connection_assert_ref(c);
     pa_assert(t);
@@ -2719,8 +2809,14 @@ static void command_set_stream_buffer_attr(pa_pdispatch *pd, uint32_t command, u
             return;
         }
 
-        CHECK_VALIDITY(c->pstream, maxlength > 0, tag, PA_ERR_INVALID);
-        CHECK_VALIDITY(c->pstream, maxlength <= MAX_MEMBLOCKQ_LENGTH, tag, PA_ERR_INVALID);
+        if (maxlength <= 0 || maxlength > MAX_MEMBLOCKQ_LENGTH)
+            maxlength = MAX_MEMBLOCKQ_LENGTH;
+        if (tlength <= 0)
+            tlength = pa_usec_to_bytes(DEFAULT_TLENGTH_MSEC*1000, &s->sink_input->sample_spec);
+        if (minreq <= 0)
+            minreq = (tlength*9)/10;
+        if (prebuf <= 0)
+            prebuf = tlength;
 
         pa_memblockq_set_maxlength(s->memblockq, maxlength);
         pa_memblockq_set_tlength(s->memblockq, tlength);
@@ -2751,8 +2847,10 @@ static void command_set_stream_buffer_attr(pa_pdispatch *pd, uint32_t command, u
             return;
         }
 
-        CHECK_VALIDITY(c->pstream, maxlength > 0, tag, PA_ERR_INVALID);
-        CHECK_VALIDITY(c->pstream, maxlength <= MAX_MEMBLOCKQ_LENGTH, tag, PA_ERR_INVALID);
+        if (maxlength <= 0 || maxlength > MAX_MEMBLOCKQ_LENGTH)
+            maxlength = MAX_MEMBLOCKQ_LENGTH;
+        if (fragsize <= 0)
+            fragsize = pa_usec_to_bytes(DEFAULT_FRAGSIZE_MSEC*1000, &s->source_output->sample_spec);
 
         pa_memblockq_set_maxlength(s->memblockq, maxlength);
 
@@ -3336,7 +3434,7 @@ static void command_suspend(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa
     connection *c = CONNECTION(userdata);
     uint32_t idx = PA_INVALID_INDEX;
     const char *name = NULL;
-    int b;
+    pa_bool_t b;
 
     connection_assert_ref(c);
     pa_assert(t);
diff --git a/src/pulsecore/shm.c b/src/pulsecore/shm.c
index 7c764e3..59341f0 100644
--- a/src/pulsecore/shm.c
+++ b/src/pulsecore/shm.c
@@ -282,7 +282,9 @@ int pa_shm_attach_ro(pa_shm *m, unsigned id) {
         goto fail;
     }
 
-    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) {
+    if (st.st_size <= 0 ||
+        st.st_size > (off_t) (MAX_SHM_SIZE+PA_ALIGN(sizeof(struct shm_marker))) ||
+        PA_ALIGN((size_t) st.st_size) != (size_t) st.st_size) {
         pa_log("Invalid shared memory segment size");
         goto fail;
     }
diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c
index e15aa7b..de69945 100644
--- a/src/pulsecore/sink-input.c
+++ b/src/pulsecore/sink-input.c
@@ -665,11 +665,18 @@ void pa_sink_input_set_max_rewind(pa_sink_input *i, size_t nbytes  /* in the sin
         i->set_max_rewind(i, i->thread_info.resampler ? pa_resampler_request(i->thread_info.resampler, nbytes) : nbytes);
 }
 
-void pa_sink_input_set_requested_latency(pa_sink_input *i, pa_usec_t usec) {
+pa_usec_t pa_sink_input_set_requested_latency(pa_sink_input *i, pa_usec_t usec) {
     pa_sink_input_assert_ref(i);
-    pa_assert(PA_SINK_INPUT_LINKED(i->state));
 
-    pa_asyncmsgq_post(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_SET_REQUESTED_LATENCY, NULL, (int64_t) usec, NULL, NULL);
+    if (usec < i->sink->min_latency)
+        usec = i->sink->min_latency;
+
+    if (PA_SINK_INPUT_LINKED(i->state))
+        pa_asyncmsgq_post(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_SET_REQUESTED_LATENCY, NULL, (int64_t) usec, NULL, NULL);
+    else
+        i->thread_info.requested_sink_latency = usec;
+
+    return usec;
 }
 
 void pa_sink_input_set_volume(pa_sink_input *i, const pa_cvolume *volume) {
diff --git a/src/pulsecore/sink-input.h b/src/pulsecore/sink-input.h
index c74b891..62464ca 100644
--- a/src/pulsecore/sink-input.h
+++ b/src/pulsecore/sink-input.h
@@ -226,7 +226,7 @@ void pa_sink_input_unlink(pa_sink_input* i);
 
 void pa_sink_input_set_name(pa_sink_input *i, const char *name);
 
-void pa_sink_input_set_requested_latency(pa_sink_input *i, pa_usec_t usec);
+pa_usec_t pa_sink_input_set_requested_latency(pa_sink_input *i, pa_usec_t usec);
 
 /* Request that the specified number of bytes already written out to
 the hw device is rewritten, if possible. If this function is used you
diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c
index cded6ba..39ce83f 100644
--- a/src/pulsecore/sink.c
+++ b/src/pulsecore/sink.c
@@ -33,6 +33,7 @@
 #include <pulse/introspect.h>
 #include <pulse/utf8.h>
 #include <pulse/xmalloc.h>
+#include <pulse/timeval.h>
 
 #include <pulsecore/sink-input.h>
 #include <pulsecore/namereg.h>
@@ -47,6 +48,7 @@
 
 #define MAX_MIX_CHANNELS 32
 #define MIX_BUFFER_LENGTH (PA_PAGE_SIZE)
+#define DEFAULT_MIN_LATENCY (4*PA_USEC_PER_MSEC)
 
 static PA_DEFINE_CHECK_TYPE(pa_sink, pa_msgobject);
 
@@ -185,6 +187,8 @@ pa_sink* pa_sink_new(
     s->rtpoll = NULL;
     s->silence = pa_silence_memblock_new(core->mempool, &s->sample_spec, 0);
 
+    s->min_latency = DEFAULT_MIN_LATENCY;
+
     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;
diff --git a/src/pulsecore/sink.h b/src/pulsecore/sink.h
index 3f16995..23f02c4 100644
--- a/src/pulsecore/sink.h
+++ b/src/pulsecore/sink.h
@@ -91,6 +91,8 @@ struct pa_sink {
 
     pa_memblock *silence;
 
+    pa_usec_t min_latency; /* we won't go below this latency setting */
+
     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 */
diff --git a/src/pulsecore/source-output.c b/src/pulsecore/source-output.c
index 45a8d74..d6c2a2b 100644
--- a/src/pulsecore/source-output.c
+++ b/src/pulsecore/source-output.c
@@ -360,13 +360,20 @@ void pa_source_output_push(pa_source_output *o, const pa_memchunk *chunk) {
     pa_memblock_unref(rchunk.memblock);
 }
 
-void pa_source_output_set_requested_latency(pa_source_output *o, pa_usec_t usec) {
+pa_usec_t pa_source_output_set_requested_latency(pa_source_output *o, pa_usec_t usec) {
     pa_source_output_assert_ref(o);
     pa_assert(PA_SOURCE_OUTPUT_LINKED(o->state));
 
-    pa_asyncmsgq_post(o->source->asyncmsgq, PA_MSGOBJECT(o), PA_SOURCE_OUTPUT_MESSAGE_SET_REQUESTED_LATENCY, NULL, (int64_t) usec, NULL, NULL);
-}
+    if (usec < o->source->min_latency)
+        usec = o->source->min_latency;
 
+    if (PA_SOURCE_OUTPUT_LINKED(o->state))
+        pa_asyncmsgq_post(o->source->asyncmsgq, PA_MSGOBJECT(o), PA_SOURCE_OUTPUT_MESSAGE_SET_REQUESTED_LATENCY, NULL, (int64_t) usec, NULL, NULL);
+    else
+        o->thread_info.requested_source_latency = usec;
+
+    return usec;
+}
 
 void pa_source_output_cork(pa_source_output *o, pa_bool_t b) {
     pa_source_output_assert_ref(o);
diff --git a/src/pulsecore/source-output.h b/src/pulsecore/source-output.h
index dc95217..0a2286b 100644
--- a/src/pulsecore/source-output.h
+++ b/src/pulsecore/source-output.h
@@ -174,7 +174,7 @@ void pa_source_output_unlink(pa_source_output*o);
 
 void pa_source_output_set_name(pa_source_output *i, const char *name);
 
-void pa_source_output_set_requested_latency(pa_source_output *i, pa_usec_t usec);
+pa_usec_t pa_source_output_set_requested_latency(pa_source_output *i, pa_usec_t usec);
 
 /* Callable by everyone */
 
diff --git a/src/pulsecore/source.c b/src/pulsecore/source.c
index cc1c531..b150d8a 100644
--- a/src/pulsecore/source.c
+++ b/src/pulsecore/source.c
@@ -32,6 +32,7 @@
 
 #include <pulse/utf8.h>
 #include <pulse/xmalloc.h>
+#include <pulse/timeval.h>
 
 #include <pulsecore/source-output.h>
 #include <pulsecore/namereg.h>
@@ -41,6 +42,8 @@
 
 #include "source.h"
 
+#define DEFAULT_MIN_LATENCY (4*PA_USEC_PER_MSEC)
+
 static PA_DEFINE_CHECK_TYPE(pa_source, pa_msgobject);
 
 static void source_free(pa_object *o);
@@ -162,6 +165,8 @@ pa_source* pa_source_new(
     s->muted = data->muted;
     s->refresh_volume = s->refresh_muted = FALSE;
 
+    s->min_latency = DEFAULT_MIN_LATENCY;
+
     s->get_latency = NULL;
     s->set_volume = NULL;
     s->get_volume = NULL;
diff --git a/src/pulsecore/source.h b/src/pulsecore/source.h
index c880d3c..3ec8320 100644
--- a/src/pulsecore/source.h
+++ b/src/pulsecore/source.h
@@ -91,6 +91,8 @@ struct pa_source {
     pa_asyncmsgq *asyncmsgq;
     pa_rtpoll *rtpoll;
 
+    pa_usec_t min_latency; /* we won't go below this latency setting */
+
     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 */
diff --git a/src/pulsecore/tagstruct.c b/src/pulsecore/tagstruct.c
index 0017c38..92bace2 100644
--- a/src/pulsecore/tagstruct.c
+++ b/src/pulsecore/tagstruct.c
@@ -163,7 +163,7 @@ void pa_tagstruct_put_arbitrary(pa_tagstruct *t, const void *p, size_t length) {
     t->length += 5+length;
 }
 
-void pa_tagstruct_put_boolean(pa_tagstruct*t, int b) {
+void pa_tagstruct_put_boolean(pa_tagstruct*t, pa_bool_t b) {
     pa_assert(t);
 
     extend(t, 1);
@@ -407,7 +407,7 @@ const uint8_t* pa_tagstruct_data(pa_tagstruct*t, size_t *l) {
     return t->data;
 }
 
-int pa_tagstruct_get_boolean(pa_tagstruct*t, int *b) {
+int pa_tagstruct_get_boolean(pa_tagstruct*t, pa_bool_t *b) {
     pa_assert(t);
     pa_assert(b);
 
@@ -415,9 +415,9 @@ int pa_tagstruct_get_boolean(pa_tagstruct*t, int *b) {
         return -1;
 
     if (t->data[t->rindex] == PA_TAG_BOOLEAN_TRUE)
-        *b = 1;
+        *b = TRUE;
     else if (t->data[t->rindex] == PA_TAG_BOOLEAN_FALSE)
-        *b = 0;
+        *b = FALSE;
     else
         return -1;
 
@@ -725,7 +725,7 @@ int pa_tagstruct_get(pa_tagstruct *t, ...) {
 
             case PA_TAG_BOOLEAN_TRUE:
             case PA_TAG_BOOLEAN_FALSE:
-                ret = pa_tagstruct_get_boolean(t, va_arg(va, int*));
+                ret = pa_tagstruct_get_boolean(t, va_arg(va, pa_bool_t*));
                 break;
 
             case PA_TAG_TIMEVAL:
diff --git a/src/pulsecore/tagstruct.h b/src/pulsecore/tagstruct.h
index 3b2ce7b..8846b30 100644
--- a/src/pulsecore/tagstruct.h
+++ b/src/pulsecore/tagstruct.h
@@ -72,7 +72,7 @@ void pa_tagstruct_putu64(pa_tagstruct*t, uint64_t i);
 void pa_tagstruct_puts64(pa_tagstruct*t, int64_t i);
 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);
-void pa_tagstruct_put_boolean(pa_tagstruct*t, int b);
+void pa_tagstruct_put_boolean(pa_tagstruct*t, pa_bool_t b);
 void pa_tagstruct_put_timeval(pa_tagstruct*t, const struct timeval *tv);
 void pa_tagstruct_put_usec(pa_tagstruct*t, pa_usec_t u);
 void pa_tagstruct_put_channel_map(pa_tagstruct *t, const pa_channel_map *map);
@@ -88,7 +88,7 @@ int pa_tagstruct_getu64(pa_tagstruct*t, uint64_t *i);
 int pa_tagstruct_gets64(pa_tagstruct*t, int64_t *i);
 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);
-int pa_tagstruct_get_boolean(pa_tagstruct *t, int *b);
+int pa_tagstruct_get_boolean(pa_tagstruct *t, pa_bool_t *b);
 int pa_tagstruct_get_timeval(pa_tagstruct*t, struct timeval *tv);
 int pa_tagstruct_get_usec(pa_tagstruct*t, pa_usec_t *u);
 int pa_tagstruct_get_channel_map(pa_tagstruct *t, pa_channel_map *map);

commit 122861f75eb0bda396a2a6e13fa4074a6d50d353
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Apr 4 16:04:29 2008 +0000

    mark libpulse-browse as obsolete
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2216 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/doxygen/doxygen.conf.in b/doxygen/doxygen.conf.in
index 81923a9..8ccf667 100644
--- a/doxygen/doxygen.conf.in
+++ b/doxygen/doxygen.conf.in
@@ -417,7 +417,7 @@ WARN_LOGFILE           =
 # directories like "/usr/src/myproject". Separate the files or directories 
 # with spaces.
 
-INPUT                  = ../src/pulse/context.h ../src/pulse/stream.h ../src/pulse/pulseaudio.h ../src/pulse/sample.h ../src/pulse/def.h ../src/pulse/subscribe.h ../src/pulse/introspect.h ../src/pulse/scache.h ../src/pulse/mainloop-api.h ../src/pulse/glib-mainloop.h ../src/pulse/mainloop.h ../src/pulse/mainloop-signal.h ../src/pulse/error.h ../src/pulse/operation.h ../src/pulse/simple.h ../src/pulse/version.h ../src/pulse/volume.h ../src/pulse/channelmap.h ../src/pulse/thread-mainloop.h ../src/pulse/xmalloc.h ../src/pulse/utf8.h ../src/pulse/util.h ../src/pulse/timeval.h ../src/pulse/browser.h
+INPUT                  = ../src/pulse/context.h ../src/pulse/stream.h ../src/pulse/pulseaudio.h ../src/pulse/sample.h ../src/pulse/def.h ../src/pulse/subscribe.h ../src/pulse/introspect.h ../src/pulse/scache.h ../src/pulse/mainloop-api.h ../src/pulse/glib-mainloop.h ../src/pulse/mainloop.h ../src/pulse/mainloop-signal.h ../src/pulse/error.h ../src/pulse/operation.h ../src/pulse/simple.h ../src/pulse/version.h ../src/pulse/volume.h ../src/pulse/channelmap.h ../src/pulse/thread-mainloop.h ../src/pulse/xmalloc.h ../src/pulse/utf8.h ../src/pulse/util.h ../src/pulse/timeval.h
 
 # If the value of the INPUT tag contains directories, you can use the 
 # FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp 
diff --git a/src/pulse/browser.c b/src/pulse/browser.c
index 55e0b2c..5e4aa87 100644
--- a/src/pulse/browser.c
+++ b/src/pulse/browser.c
@@ -313,10 +313,15 @@ static void client_callback(AvahiClient *s, AvahiClientState state, void *userda
 
 static void browser_free(pa_browser *b);
 
+
+PA_WARN_REFERENCE(pa_browser_new, "libpulse-browse is being phased out.");
+
 pa_browser *pa_browser_new(pa_mainloop_api *mainloop) {
     return pa_browser_new_full(mainloop, PA_BROWSE_FOR_SERVERS|PA_BROWSE_FOR_SINKS|PA_BROWSE_FOR_SOURCES, NULL);
 }
 
+PA_WARN_REFERENCE(pa_browser_new_full, "libpulse-browse is being phased out.");
+
 pa_browser *pa_browser_new_full(pa_mainloop_api *mainloop, pa_browse_flags_t flags, const char **error_string) {
     pa_browser *b;
     int error;
@@ -420,6 +425,8 @@ static void browser_free(pa_browser *b) {
     pa_xfree(b);
 }
 
+PA_WARN_REFERENCE(pa_browser_ref, "libpulse-browse is being phased out.");
+
 pa_browser *pa_browser_ref(pa_browser *b) {
     pa_assert(b);
     pa_assert(PA_REFCNT_VALUE(b) >= 1);
@@ -428,6 +435,8 @@ pa_browser *pa_browser_ref(pa_browser *b) {
     return b;
 }
 
+PA_WARN_REFERENCE(pa_browser_unref, "libpulse-browse is being phased out.");
+
 void pa_browser_unref(pa_browser *b) {
     pa_assert(b);
     pa_assert(PA_REFCNT_VALUE(b) >= 1);
@@ -436,6 +445,8 @@ void pa_browser_unref(pa_browser *b) {
         browser_free(b);
 }
 
+PA_WARN_REFERENCE(pa_browser_set_callback, "libpulse-browse is being phased out.");
+
 void pa_browser_set_callback(pa_browser *b, pa_browse_cb_t cb, void *userdata) {
     pa_assert(b);
     pa_assert(PA_REFCNT_VALUE(b) >= 1);
@@ -444,6 +455,8 @@ void pa_browser_set_callback(pa_browser *b, pa_browse_cb_t cb, void *userdata) {
     b->userdata = userdata;
 }
 
+PA_WARN_REFERENCE(pa_browser_set_error_callback, "libpulse-browse is being phased out.");
+
 void pa_browser_set_error_callback(pa_browser *b, pa_browser_error_cb_t cb, void *userdata) {
     pa_assert(b);
     pa_assert(PA_REFCNT_VALUE(b) >= 1);

commit 064aa1243c202dd99179ebe34f7ed92ef6f40d12
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Apr 4 16:05:15 2008 +0000

    drop support for periodic timers, cleanup code a bit
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2217 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/rtpoll.c b/src/pulsecore/rtpoll.c
index f7773be..7403508 100644
--- a/src/pulsecore/rtpoll.c
+++ b/src/pulsecore/rtpoll.c
@@ -63,7 +63,6 @@ struct pa_rtpoll {
 
     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;
@@ -139,7 +138,6 @@ pa_rtpoll *pa_rtpoll_new(void) {
     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;
 
@@ -368,15 +366,13 @@ int pa_rtpoll_run(pa_rtpoll *p, pa_bool_t wait) {
     if (p->rebuild_needed)
         rtpoll_rebuild(p);
 
+    memset(&timeout, 0, sizeof(timeout));
+
     /* Calculate timeout */
-    if (!wait || p->quit) {
-        timeout.tv_sec = 0;
-        timeout.tv_usec = 0;
-    } else if (p->timer_enabled) {
+    if (wait && !p->quit && 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));
     }
@@ -391,14 +387,14 @@ int pa_rtpoll_run(pa_rtpoll *p, pa_bool_t wait) {
         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);
+        r = ppoll(p->pollfd, p->n_pollfd_used, (!wait || p->quit || 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);
+        r = poll(p->pollfd, p->n_pollfd_used, (!wait || p->quit || p->timer_enabled) ? (timeout.tv_sec*1000) + (timeout.tv_usec / 1000) : -1);
 
     if (r < 0) {
         if (errno == EAGAIN || errno == EINTR)
@@ -409,21 +405,6 @@ int pa_rtpoll_run(pa_rtpoll *p, pa_bool_t wait) {
         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) {
 
@@ -489,15 +470,8 @@ static void update_timer(pa_rtpoll *p) {
 
                 /* Make sure that 0,0 is not understood as
                  * "disarming" */
-                if (its.it_value.tv_sec == 0)
+                if (its.it_value.tv_sec == 0 && its.it_value.tv_nsec == 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);
@@ -515,18 +489,6 @@ void pa_rtpoll_set_timer_absolute(pa_rtpoll *p, const struct timeval *ts) {
     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);
@@ -535,7 +497,6 @@ 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) {
     pa_assert(p);
 
-    p->period = 0;
     pa_rtclock_get(&p->next_elapse);
     pa_timeval_add(&p->next_elapse, usec);
     p->timer_enabled = TRUE;
@@ -546,7 +507,6 @@ void pa_rtpoll_set_timer_relative(pa_rtpoll *p, pa_usec_t usec) {
 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;
 
diff --git a/src/pulsecore/rtpoll.h b/src/pulsecore/rtpoll.h
index 02f5c7c..f7f96e6 100644
--- a/src/pulsecore/rtpoll.h
+++ b/src/pulsecore/rtpoll.h
@@ -75,7 +75,6 @@ void pa_rtpoll_install(pa_rtpoll *p);
 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);
 

commit b9c10f2c56fc34b5ff99b0a9b3959b4d37586a39
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Apr 4 16:06:47 2008 +0000

    propery calculate min_avail in frames instead of bytes. don't use device_id= parameter in alsa modules if parameter wasn't specified
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2218 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/alsa-util.c b/src/modules/alsa-util.c
index d899eae..38ea863 100644
--- a/src/modules/alsa-util.c
+++ b/src/modules/alsa-util.c
@@ -426,7 +426,7 @@ finish:
     return ret;
 }
 
-int pa_alsa_set_sw_params(snd_pcm_t *pcm, size_t avail_min) {
+int pa_alsa_set_sw_params(snd_pcm_t *pcm, snd_pcm_uframes_t avail_min) {
     snd_pcm_sw_params_t *swparams;
     int err;
 
diff --git a/src/modules/alsa-util.h b/src/modules/alsa-util.h
index 62c1d43..dee955f 100644
--- a/src/modules/alsa-util.h
+++ b/src/modules/alsa-util.h
@@ -48,7 +48,7 @@ int pa_alsa_set_hw_params(
         pa_bool_t *use_tsched,
         pa_bool_t require_exact_channel_number);
 
-int pa_alsa_set_sw_params(snd_pcm_t *pcm, size_t avail_min);
+int pa_alsa_set_sw_params(snd_pcm_t *pcm, snd_pcm_uframes_t avail_min);
 
 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);
diff --git a/src/modules/module-alsa-sink.c b/src/modules/module-alsa-sink.c
index 1dccf67..cd3ebcc 100644
--- a/src/modules/module-alsa-sink.c
+++ b/src/modules/module-alsa-sink.c
@@ -74,7 +74,7 @@ PA_MODULE_USAGE(
 
 #define DEFAULT_DEVICE "default"
 #define DEFAULT_TSCHED_BUFFER_USEC (2*PA_USEC_PER_SEC)
-#define DEFAULT_TSCHED_WATERMARK_USEC (10*PA_USEC_PER_MSEC)
+#define DEFAULT_TSCHED_WATERMARK_USEC (100*PA_USEC_PER_MSEC)
 
 struct userdata {
     pa_core *core;
@@ -160,8 +160,10 @@ static int mmap_write(struct userdata *u) {
             if ((err = snd_pcm_recover(u->pcm_handle, n, 1)) == 0)
                 continue;
 
-            if (err == -EAGAIN)
+            if (err == -EAGAIN) {
+                pa_log_debug("EAGAIN");
                 return work_done;
+            }
 
             pa_log("snd_pcm_avail_update: %s", snd_strerror(err));
             return -1;
@@ -187,8 +189,10 @@ static int mmap_write(struct userdata *u) {
             if ((err = snd_pcm_recover(u->pcm_handle, err, 1)) == 0)
                 continue;
 
-            if (err == -EAGAIN)
+            if (err == -EAGAIN) {
+                pa_log_debug("EAGAIN");
                 return work_done;
+            }
 
             pa_log("Failed to write data to DSP: %s", snd_strerror(err));
             return -1;
@@ -226,8 +230,10 @@ static int mmap_write(struct userdata *u) {
             if ((err = snd_pcm_recover(u->pcm_handle, err, 1)) == 0)
                 continue;
 
-            if (err == -EAGAIN)
+            if (err == -EAGAIN) {
+                pa_log_debug("EAGAIN");
                 return work_done;
+            }
 
             pa_log("Failed to write data to DSP: %s", snd_strerror(err));
             return -1;
@@ -300,8 +306,10 @@ static int unix_write(struct userdata *u) {
             if ((frames = snd_pcm_recover(u->pcm_handle, frames, 1)) == 0)
                 continue;
 
-            if (frames == -EAGAIN)
+            if (frames == -EAGAIN) {
+                pa_log_debug("EAGAIN");
                 return work_done;
+            }
 
             pa_log("Failed to write data to DSP: %s", snd_strerror(frames));
             return -1;
@@ -468,7 +476,7 @@ static void update_hwbuf_unused_frames(struct userdata *u) {
 }
 
 static int update_sw_params(struct userdata *u) {
-    size_t avail_min;
+    snd_pcm_uframes_t avail_min;
     int err;
 
     pa_assert(u);
@@ -478,7 +486,7 @@ static int update_sw_params(struct userdata *u) {
 
         usec = hw_sleep_time(u);
 
-        avail_min = pa_usec_to_bytes(usec, &u->sink->sample_spec);
+        avail_min = pa_usec_to_bytes(usec, &u->sink->sample_spec) / u->frame_size;
 
         if (avail_min <= 0)
             avail_min = 1;
@@ -486,6 +494,10 @@ static int update_sw_params(struct userdata *u) {
     } else
         avail_min = 1;
 
+    avail_min = (snd_pcm_uframes_t) -1;
+
+    pa_log("setting avail_min=%lu", (unsigned long) avail_min);
+
     if ((err = pa_alsa_set_sw_params(u->pcm_handle, avail_min)) < 0) {
         pa_log("Failed to set software parameters: %s", snd_strerror(err));
         return err;
@@ -493,6 +505,8 @@ static int update_sw_params(struct userdata *u) {
 
     update_hwbuf_unused_frames(u);
 
+    pa_log("hwbuf_unused_frames=%lu", (unsigned long) u->hwbuf_unused_frames);
+
     return 0;
 }
 
@@ -810,19 +824,26 @@ static void thread_func(void *userdata) {
                 if (frames > limit)
                     frames = limit;
 
-                pa_log_debug("Limited to %lu bytes.", (unsigned long) frames * u->frame_size);
+                frames = 0;
 
-                if ((frames = snd_pcm_rewind(u->pcm_handle, frames)) < 0) {
-                    pa_log("snd_pcm_rewind() failed: %s", snd_strerror(frames));
-                    goto fail;
-                }
+                if (frames > 0) {
+
+                    pa_log_debug("Limited to %lu bytes.", (unsigned long) frames * u->frame_size);
+
+                    if ((frames = snd_pcm_rewind(u->pcm_handle, frames)) < 0) {
+                        pa_log("snd_pcm_rewind() failed: %s", snd_strerror(frames));
+                        goto fail;
+                    }
 
-                if ((u->sink->thread_info.rewind_nbytes = frames * u->frame_size) <= 0)
-                    pa_log_info("Tried rewind, but was apparently not possible.");
-                else {
-                    u->frame_index -= frames;
-                    pa_log_debug("Rewound %lu bytes.", (unsigned long) u->sink->thread_info.rewind_nbytes);
-                    pa_sink_process_rewind(u->sink);
+                    if ((u->sink->thread_info.rewind_nbytes = frames * u->frame_size) <= 0)
+                        pa_log_info("Tried rewind, but was apparently not possible.");
+                    else {
+                        u->frame_index -= frames;
+                        pa_log_debug("Rewound %lu bytes.", (unsigned long) u->sink->thread_info.rewind_nbytes);
+                        pa_sink_process_rewind(u->sink);
+                    }
+                } else {
+                    pa_log_debug("Mhmm, actually there is nothing to rewind.");
                 }
             }
 
@@ -851,7 +872,7 @@ static void thread_func(void *userdata) {
             }
 
             if (u->use_tsched) {
-                pa_usec_t usec, cusec;
+                pa_usec_t usec, cusec, sleep_usec;
 
                 /* OK, the playback buffer is now full, let's
                  * calculate when to wake up next */
@@ -866,8 +887,12 @@ static void thread_func(void *userdata) {
 
                 pa_log_debug("Waking up in %0.2fms (system clock).", (double) cusec / PA_USEC_PER_MSEC);
 
+                sleep_usec = PA_MIN(usec, cusec);
+
+                pa_log_debug("Waking up in %0.2fms (smaller value).", (double) sleep_usec / PA_USEC_PER_MSEC);
+
                 /* We don't trust the conversion, so we wake up whatever comes first */
-                pa_rtpoll_set_timer_relative(u->rtpoll, PA_MIN(usec, cusec));
+                pa_rtpoll_set_timer_relative(u->rtpoll, sleep_usec);
             }
 
         } else if (u->use_tsched) {
@@ -1107,7 +1132,7 @@ int pa__init(pa_module*m) {
 
         if (pa_alsa_prepare_mixer(u->mixer_handle, u->device_name) >= 0)
             found = TRUE;
-        else {
+        else if (dev_id) {
             char *md = pa_sprintf_malloc("hw:%s", dev_id);
 
             if (strcmp(u->device_name, md))
diff --git a/src/modules/module-alsa-source.c b/src/modules/module-alsa-source.c
index af20f81..901e342 100644
--- a/src/modules/module-alsa-source.c
+++ b/src/modules/module-alsa-source.c
@@ -979,7 +979,7 @@ int pa__init(pa_module*m) {
 
         if (pa_alsa_prepare_mixer(u->mixer_handle, u->device_name) >= 0)
             found = TRUE;
-        else {
+        else if (dev_id) {
             char *md = pa_sprintf_malloc("hw:%s", dev_id);
 
             if (strcmp(u->device_name, md))

commit 98b0152d7c9fe219448edfd61777b8f7357da25c
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Apr 7 16:46:13 2008 +0000

    add utility functions to dump alsa PCM state
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2219 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/alsa-util.c b/src/modules/alsa-util.c
index 38ea863..c8f594a 100644
--- a/src/modules/alsa-util.c
+++ b/src/modules/alsa-util.c
@@ -894,3 +894,46 @@ void pa_alsa_0dB_capture(snd_mixer_elem_t *elem) {
 
     snd_mixer_selem_set_capture_volume_all(elem, v);
 }
+
+void pa_alsa_dump(snd_pcm_t *pcm) {
+    int err;
+    snd_output_t *out;
+
+    pa_assert(pcm);
+
+    pa_assert_se(snd_output_buffer_open(&out) == 0);
+
+    if ((err = snd_pcm_dump(pcm, out)) < 0)
+        pa_log_debug("snd_pcm_dump(): %s", snd_strerror(err));
+    else {
+        char *s = NULL;
+        snd_output_buffer_string(out, &s);
+        pa_log_debug("snd_pcm_dump():\n%s", pa_strnull(s));
+    }
+
+    pa_assert_se(snd_output_close(out) == 0);
+}
+
+void pa_alsa_dump_status(snd_pcm_t *pcm) {
+    int err;
+    snd_output_t *out;
+    snd_pcm_status_t *status;
+
+    pa_assert(pcm);
+
+    snd_pcm_status_alloca(&status);
+
+    pa_assert_se(snd_output_buffer_open(&out) == 0);
+
+    pa_assert_se(snd_pcm_status(pcm, status) == 0);
+
+    if ((err = snd_pcm_status_dump(status, out)) < 0)
+        pa_log_debug("snd_pcm_dump(): %s", snd_strerror(err));
+    else {
+        char *s = NULL;
+        snd_output_buffer_string(out, &s);
+        pa_log_debug("snd_pcm_dump():\n%s", pa_strnull(s));
+    }
+
+    pa_assert_se(snd_output_close(out) == 0);
+}
diff --git a/src/modules/alsa-util.h b/src/modules/alsa-util.h
index dee955f..0e536f1 100644
--- a/src/modules/alsa-util.h
+++ b/src/modules/alsa-util.h
@@ -82,4 +82,7 @@ int pa_alsa_calc_mixer_map(snd_mixer_elem_t *elem, const pa_channel_map *channel
 void pa_alsa_0dB_playback(snd_mixer_elem_t *elem);
 void pa_alsa_0dB_capture(snd_mixer_elem_t *elem);
 
+void pa_alsa_dump(snd_pcm_t *pcm);
+void pa_alsa_dump_status(snd_pcm_t *pcm);
+
 #endif

commit c84a64cf322844b7c4c78dbcc32b1fa1a461af1b
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Apr 7 16:47:27 2008 +0000

    fix bug where we silently dropped data that didn't fit into one mempool tile
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2220 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c
index de69945..989e2ae 100644
--- a/src/pulsecore/sink-input.c
+++ b/src/pulsecore/sink-input.c
@@ -517,29 +517,38 @@ int pa_sink_input_peek(pa_sink_input *i, size_t slength /* in sink frames */, pa
         pa_assert(tchunk.length > 0);
         pa_assert(tchunk.memblock);
 
-        if (tchunk.length > block_size_max_sink_input)
-            tchunk.length = block_size_max_sink_input;
+        while (tchunk.length > 0) {
+            pa_memchunk wchunk;
 
-        /* It might be necessary to adjust the volume here */
-        if (do_volume_adj_here && !volume_is_norm) {
-            pa_memchunk_make_writable(&tchunk, 0);
+            wchunk = tchunk;
 
-            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);
-        }
+            if (wchunk.length > block_size_max_sink_input)
+                wchunk.length = block_size_max_sink_input;
 
-        if (!i->thread_info.resampler)
-            pa_memblockq_push_align(i->thread_info.render_memblockq, &tchunk);
-        else {
-            pa_memchunk rchunk;
-            pa_resampler_run(i->thread_info.resampler, &tchunk, &rchunk);
+            /* It might be necessary to adjust the volume here */
+            if (do_volume_adj_here && !volume_is_norm) {
+                pa_memchunk_make_writable(&wchunk, 0);
 
-            if (rchunk.memblock) {
-                pa_memblockq_push_align(i->thread_info.render_memblockq, &rchunk);
-                pa_memblock_unref(rchunk.memblock);
+                if (i->thread_info.muted)
+                    pa_silence_memchunk(&wchunk, &i->thread_info.sample_spec);
+                else
+                    pa_volume_memchunk(&wchunk, &i->thread_info.sample_spec, &i->thread_info.volume);
             }
+
+            if (!i->thread_info.resampler)
+                pa_memblockq_push_align(i->thread_info.render_memblockq, &wchunk);
+            else {
+                pa_memchunk rchunk;
+                pa_resampler_run(i->thread_info.resampler, &wchunk, &rchunk);
+
+                if (rchunk.memblock) {
+                    pa_memblockq_push_align(i->thread_info.render_memblockq, &rchunk);
+                    pa_memblock_unref(rchunk.memblock);
+                }
+            }
+
+            tchunk.index += wchunk.length;
+            tchunk.length -= wchunk.length;
         }
 
         pa_memblock_unref(tchunk.memblock);

commit b3b8a63c507a9f3dec1414510348c92d168813f5
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Apr 7 17:19:51 2008 +0000

    call snd_pcm_hwsync() expclicitly before we access any of the status fields, since this seems to be necessary. try to find the right mixer device via the card index
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2221 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-alsa-sink.c b/src/modules/module-alsa-sink.c
index cd3ebcc..70a94ee 100644
--- a/src/modules/module-alsa-sink.c
+++ b/src/modules/module-alsa-sink.c
@@ -74,7 +74,7 @@ PA_MODULE_USAGE(
 
 #define DEFAULT_DEVICE "default"
 #define DEFAULT_TSCHED_BUFFER_USEC (2*PA_USEC_PER_SEC)
-#define DEFAULT_TSCHED_WATERMARK_USEC (100*PA_USEC_PER_MSEC)
+#define DEFAULT_TSCHED_WATERMARK_USEC (10*PA_USEC_PER_MSEC)
 
 struct userdata {
     pa_core *core;
@@ -145,6 +145,8 @@ static int mmap_write(struct userdata *u) {
         const snd_pcm_channel_area_t *areas;
         snd_pcm_uframes_t offset, frames;
 
+        snd_pcm_hwsync(u->pcm_handle);
+
         /* First we determine how many samples are missing to fill the
          * buffer up to 100% */
 
@@ -152,20 +154,20 @@ static int mmap_write(struct userdata *u) {
 
             pa_log_debug("snd_pcm_avail_update: %s", snd_strerror(n));
 
-            if (n == -EPIPE) {
-                pa_log_debug("snd_pcm_avail_update: Buffer underrun!");
-                u->first = TRUE;
-            }
-
-            if ((err = snd_pcm_recover(u->pcm_handle, n, 1)) == 0)
-                continue;
-
             if (err == -EAGAIN) {
                 pa_log_debug("EAGAIN");
                 return work_done;
             }
 
-            pa_log("snd_pcm_avail_update: %s", snd_strerror(err));
+            if (n == -EPIPE)
+                pa_log_debug("snd_pcm_avail_update: Buffer underrun!");
+
+            if ((err = snd_pcm_recover(u->pcm_handle, n, 1)) == 0) {
+                u->first = TRUE;
+                continue;
+            }
+
+            pa_log("snd_pcm_recover: %s", snd_strerror(err));
             return -1;
         }
 
@@ -181,19 +183,19 @@ static int mmap_write(struct userdata *u) {
 
             pa_log_debug("snd_pcm_mmap_begin: %s", snd_strerror(err));
 
-            if (err == -EPIPE) {
-                pa_log_debug("snd_pcm_mmap_begin: Buffer underrun!");
-                u->first = TRUE;
-            }
-
-            if ((err = snd_pcm_recover(u->pcm_handle, err, 1)) == 0)
-                continue;
-
             if (err == -EAGAIN) {
                 pa_log_debug("EAGAIN");
                 return work_done;
             }
 
+            if (err == -EPIPE)
+                pa_log_debug("snd_pcm_mmap_begin: Buffer underrun!");
+
+            if ((err = snd_pcm_recover(u->pcm_handle, err, 1)) == 0) {
+                u->first = TRUE;
+                continue;
+            }
+
             pa_log("Failed to write data to DSP: %s", snd_strerror(err));
             return -1;
         }
@@ -222,19 +224,19 @@ static int mmap_write(struct userdata *u) {
 
             pa_log_debug("snd_pcm_mmap_commit: %s", snd_strerror(err));
 
-            if (err == -EPIPE) {
-                pa_log_debug("snd_pcm_mmap_commit: Buffer underrun!");
-                u->first = TRUE;
-            }
-
-            if ((err = snd_pcm_recover(u->pcm_handle, err, 1)) == 0)
-                continue;
-
             if (err == -EAGAIN) {
                 pa_log_debug("EAGAIN");
                 return work_done;
             }
 
+            if (err == -EPIPE)
+                pa_log_debug("snd_pcm_mmap_commit: Buffer underrun!");
+
+            if ((err = snd_pcm_recover(u->pcm_handle, err, 1)) == 0) {
+                u->first = TRUE;
+                continue;
+            }
+
             pa_log("Failed to write data to DSP: %s", snd_strerror(err));
             return -1;
         }
@@ -264,6 +266,8 @@ static int unix_write(struct userdata *u) {
         snd_pcm_sframes_t n, frames;
         int err;
 
+        snd_pcm_hwsync(u->pcm_handle);
+
         if (PA_UNLIKELY((err = snd_pcm_status(u->pcm_handle, status)) < 0)) {
             pa_log("Failed to query DSP status data: %s", snd_strerror(err));
             return -1;
@@ -300,15 +304,17 @@ static int unix_write(struct userdata *u) {
 
         if (PA_UNLIKELY(frames < 0)) {
 
+            if (frames == -EAGAIN) {
+                pa_log_debug("EAGAIN");
+                return work_done;
+            }
+
             if (frames == -EPIPE)
                 pa_log_debug("snd_pcm_avail_update: Buffer underrun!");
 
-            if ((frames = snd_pcm_recover(u->pcm_handle, frames, 1)) == 0)
+            if ((frames = snd_pcm_recover(u->pcm_handle, frames, 1)) == 0) {
+                u->first = TRUE;
                 continue;
-
-            if (frames == -EAGAIN) {
-                pa_log_debug("EAGAIN");
-                return work_done;
             }
 
             pa_log("Failed to write data to DSP: %s", snd_strerror(frames));
@@ -332,7 +338,7 @@ static int unix_write(struct userdata *u) {
     }
 }
 
-static int update_smoother(struct userdata *u) {
+static void update_smoother(struct userdata *u) {
     snd_pcm_sframes_t delay  = 0;
     int64_t frames;
     int err;
@@ -343,11 +349,12 @@ static int update_smoother(struct userdata *u) {
 
     /* Let's update the time smoother */
 
+    snd_pcm_hwsync(u->pcm_handle);
     snd_pcm_avail_update(u->pcm_handle);
 
     if (PA_UNLIKELY((err = snd_pcm_delay(u->pcm_handle, &delay)) < 0)) {
-        pa_log("Failed to get delay: %s", snd_strerror(err));
-        return -1;
+        pa_log_warn("Failed to get delay: %s", snd_strerror(err));
+        return;
     }
 
     frames = u->frame_index - delay;
@@ -357,8 +364,6 @@ static int update_smoother(struct userdata *u) {
     now1 = pa_rtclock_usec();
     now2 = pa_bytes_to_usec(frames * u->frame_size, &u->sink->sample_spec);
     pa_smoother_put(u->smoother, now1, now2);
-
-    return 0;
 }
 
 static pa_usec_t sink_get_latency(struct userdata *u) {
@@ -814,6 +819,7 @@ static void thread_func(void *userdata) {
 
                 frames = u->sink->thread_info.rewind_nbytes / u->frame_size;
 
+                snd_pcm_hwsync(u->pcm_handle);
                 if ((unused = snd_pcm_avail_update(u->pcm_handle)) < 0) {
                     pa_log("snd_pcm_avail_update() failed: %s", snd_strerror(unused));
                     goto fail;
@@ -867,12 +873,11 @@ static void thread_func(void *userdata) {
                     pa_smoother_resume(u->smoother, pa_rtclock_usec());
                 }
 
-                if (update_smoother(u) < 0)
-                    goto fail;
+                update_smoother(u);
             }
 
             if (u->use_tsched) {
-                pa_usec_t usec, cusec, sleep_usec;
+                pa_usec_t usec, cusec;
 
                 /* OK, the playback buffer is now full, let's
                  * calculate when to wake up next */
@@ -887,19 +892,14 @@ static void thread_func(void *userdata) {
 
                 pa_log_debug("Waking up in %0.2fms (system clock).", (double) cusec / PA_USEC_PER_MSEC);
 
-                sleep_usec = PA_MIN(usec, cusec);
-
-                pa_log_debug("Waking up in %0.2fms (smaller value).", (double) sleep_usec / PA_USEC_PER_MSEC);
-
                 /* We don't trust the conversion, so we wake up whatever comes first */
-                pa_rtpoll_set_timer_relative(u->rtpoll, sleep_usec);
+                pa_rtpoll_set_timer_relative(u->rtpoll, PA_MIN(usec, cusec));
             }
 
-        } else if (u->use_tsched) {
+        } else if (u->use_tsched)
 
             /* OK, we're in an invalid state, let's disable our timers */
             pa_rtpoll_set_timer_disabled(u->rtpoll);
-        }
 
         /* Hmm, nothing to do. Let's sleep */
         if ((ret = pa_rtpoll_run(u->rtpoll, 1)) < 0)
@@ -923,6 +923,7 @@ static void thread_func(void *userdata) {
             }
 
             if (revents & (POLLERR|POLLNVAL|POLLHUP)) {
+                snd_pcm_state_t state;
 
                 if (revents & POLLERR)
                     pa_log_warn("Got POLLERR from ALSA");
@@ -931,9 +932,12 @@ static void thread_func(void *userdata) {
                 if (revents & POLLHUP)
                     pa_log_warn("Got POLLHUP from ALSA");
 
+                state = snd_pcm_state(u->pcm_handle);
+                pa_log_warn("PCM state is %s", snd_pcm_state_name(state));
+
                 /* Try to recover from this error */
 
-                switch (snd_pcm_state(u->pcm_handle)) {
+                switch (state) {
 
                     case SND_PCM_STATE_XRUN:
                         if ((err = snd_pcm_recover(u->pcm_handle, -EPIPE, 1)) != 0) {
@@ -959,6 +963,8 @@ static void thread_func(void *userdata) {
                         }
                         break;
                 }
+
+                u->first = TRUE;
             }
 
             pa_log_debug("alsa revents = %i", revents);
@@ -1132,14 +1138,25 @@ int pa__init(pa_module*m) {
 
         if (pa_alsa_prepare_mixer(u->mixer_handle, u->device_name) >= 0)
             found = TRUE;
-        else if (dev_id) {
-            char *md = pa_sprintf_malloc("hw:%s", dev_id);
+        else {
+            snd_pcm_info_t *info;
+
+            snd_pcm_info_alloca(&info);
+
+            if (snd_pcm_info(u->pcm_handle, info) >= 0) {
+                char *md;
+                int card;
 
-            if (strcmp(u->device_name, md))
-                if (pa_alsa_prepare_mixer(u->mixer_handle, md) >= 0)
-                    found = TRUE;
+                if ((card = snd_pcm_info_get_card(info)) >= 0) {
 
-            pa_xfree(md);
+                    md = pa_sprintf_malloc("hw:%i", card);
+
+                    if (strcmp(u->device_name, md))
+                        if (pa_alsa_prepare_mixer(u->mixer_handle, md) >= 0)
+                            found = TRUE;
+                    pa_xfree(md);
+                }
+            }
         }
 
         if (found)
@@ -1304,6 +1321,8 @@ int pa__init(pa_module*m) {
     } else
         u->mixer_fdl = NULL;
 
+    pa_alsa_dump(u->pcm_handle);
+
     if (!(u->thread = pa_thread_new(thread_func, u))) {
         pa_log("Failed to create thread.");
         goto fail;
diff --git a/src/modules/module-alsa-source.c b/src/modules/module-alsa-source.c
index 901e342..a074bc6 100644
--- a/src/modules/module-alsa-source.c
+++ b/src/modules/module-alsa-source.c
@@ -141,18 +141,26 @@ static int mmap_read(struct userdata *u) {
         pa_memchunk chunk;
         void *p;
 
+        snd_pcm_hwsync(u->pcm_handle);
+
         if (PA_UNLIKELY((n = snd_pcm_avail_update(u->pcm_handle)) < 0)) {
 
+            pa_log_debug("snd_pcm_avail_update: %s", snd_strerror(n));
+
+            if (err == -EAGAIN) {
+                pa_log_debug("EAGAIN");
+                return work_done;
+            }
+
             if (n == -EPIPE)
                 pa_log_debug("snd_pcm_avail_update: Buffer underrun!");
 
-            if ((err = snd_pcm_recover(u->pcm_handle, n, 1)) == 0)
+            if ((err = snd_pcm_recover(u->pcm_handle, n, 1)) == 0) {
+                snd_pcm_start(u->pcm_handle);
                 continue;
+            }
 
-            if (err == -EAGAIN)
-                return work_done;
-
-            pa_log("snd_pcm_avail_update: %s", snd_strerror(err));
+            pa_log("snd_pcm_recover: %s", snd_strerror(err));
             return -1;
         }
 
@@ -163,14 +171,20 @@ static int mmap_read(struct userdata *u) {
 
         if (PA_UNLIKELY((err = snd_pcm_mmap_begin(u->pcm_handle, &areas, &offset, &frames)) < 0)) {
 
+            pa_log_debug("snd_pcm_mmap_begin: %s", snd_strerror(err));
+
+            if (err == -EAGAIN) {
+                pa_log_debug("EAGAIN");
+                return work_done;
+            }
+
             if (err == -EPIPE)
                 pa_log_debug("snd_pcm_mmap_begin: Buffer underrun!");
 
-            if ((err = snd_pcm_recover(u->pcm_handle, err, 1)) == 0)
+            if ((err = snd_pcm_recover(u->pcm_handle, err, 1)) == 0) {
+                snd_pcm_start(u->pcm_handle);
                 continue;
-
-            if (err == -EAGAIN)
-                return work_done;
+            }
 
             pa_log("Failed to write data to DSP: %s", snd_strerror(err));
             return -1;
@@ -198,14 +212,20 @@ static int mmap_read(struct userdata *u) {
 
         if (PA_UNLIKELY((err = snd_pcm_mmap_commit(u->pcm_handle, offset, frames)) < 0)) {
 
+            pa_log_debug("snd_pcm_mmap_commit: %s", snd_strerror(err));
+
+            if (err == -EAGAIN) {
+                pa_log_debug("EAGAIN");
+                return work_done;
+            }
+
             if (err == -EPIPE)
                 pa_log_debug("snd_pcm_mmap_commit: Buffer underrun!");
 
-            if ((err = snd_pcm_recover(u->pcm_handle, err, 1)) == 0)
+            if ((err = snd_pcm_recover(u->pcm_handle, err, 1)) == 0) {
+                snd_pcm_start(u->pcm_handle);
                 continue;
-
-            if (err == -EAGAIN)
-                return work_done;
+            }
 
             pa_log("Failed to write data to DSP: %s", snd_strerror(err));
             return -1;
@@ -215,6 +235,8 @@ static int mmap_read(struct userdata *u) {
 
         u->frame_index += frames;
 
+        pa_log_debug("read %llu frames", (unsigned long long) frames);
+
         if (PA_LIKELY(frames >= (snd_pcm_uframes_t) n))
             return work_done;
     }
@@ -235,6 +257,8 @@ static int unix_read(struct userdata *u) {
         int err;
         pa_memchunk chunk;
 
+        snd_pcm_hwsync(u->pcm_handle);
+
         if (PA_UNLIKELY((err = snd_pcm_status(u->pcm_handle, status)) < 0)) {
             pa_log("Failed to query DSP status data: %s", snd_strerror(err));
             return -1;
@@ -264,12 +288,18 @@ static int unix_read(struct userdata *u) {
         if (PA_UNLIKELY(frames < 0)) {
             pa_memblock_unref(chunk.memblock);
 
+            if (frames == -EAGAIN) {
+                pa_log_debug("EAGAIN");
+                return work_done;
+            }
+
+            if (frames == -EPIPE)
+                pa_log_debug("snd_pcm_avail_update: Buffer overrun!");
+
             if ((frames = snd_pcm_recover(u->pcm_handle, frames, 1)) == 0)
+                snd_pcm_start(u->pcm_handle);
                 continue;
 
-            if (frames == -EAGAIN)
-                return work_done;
-
             pa_log("Failed to read data from DSP: %s", snd_strerror(frames));
             return -1;
         }
@@ -289,7 +319,7 @@ static int unix_read(struct userdata *u) {
     }
 }
 
-static int update_smoother(struct userdata *u) {
+static void update_smoother(struct userdata *u) {
     snd_pcm_sframes_t delay = 0;
     int64_t frames;
     int err;
@@ -300,11 +330,12 @@ static int update_smoother(struct userdata *u) {
 
     /* Let's update the time smoother */
 
+    snd_pcm_hwsync(u->pcm_handle);
     snd_pcm_avail_update(u->pcm_handle);
 
     if (PA_UNLIKELY((err = snd_pcm_delay(u->pcm_handle, &delay)) < 0)) {
-        pa_log("Failed to get delay: %s", snd_strerror(err));
-        return -1;
+        pa_log_warn("Failed to get delay: %s", snd_strerror(err));
+        return;
     }
 
     frames = u->frame_index + delay;
@@ -312,8 +343,6 @@ static int update_smoother(struct userdata *u) {
     now1 = pa_rtclock_usec();
     now2 = pa_bytes_to_usec(frames * u->frame_size, &u->source->sample_spec);
     pa_smoother_put(u->smoother, now1, now2);
-
-    return 0;
 }
 
 static pa_usec_t source_get_latency(struct userdata *u) {
@@ -728,8 +757,7 @@ static void thread_func(void *userdata) {
             }
 
             if (work_done)
-                if (update_smoother(u) < 0)
-                    goto fail;
+                update_smoother(u);
 
             if (u->use_tsched) {
                 pa_usec_t usec, cusec;
@@ -750,11 +778,10 @@ static void thread_func(void *userdata) {
                 /* We don't trust the conversion, so we wake up whatever comes first */
                 pa_rtpoll_set_timer_relative(u->rtpoll, PA_MIN(usec, cusec));
             }
-        } else if (u->use_tsched) {
+        } else if (u->use_tsched)
 
             /* OK, we're in an invalid state, let's disable our timers */
             pa_rtpoll_set_timer_disabled(u->rtpoll);
-        }
 
         /* Hmm, nothing to do. Let's sleep */
         if ((ret = pa_rtpoll_run(u->rtpoll, 1)) < 0)
@@ -778,6 +805,7 @@ static void thread_func(void *userdata) {
             }
 
             if (revents & (POLLERR|POLLNVAL|POLLHUP)) {
+                snd_pcm_state_t state;
 
                 if (revents & POLLERR)
                     pa_log_warn("Got POLLERR from ALSA");
@@ -786,9 +814,12 @@ static void thread_func(void *userdata) {
                 if (revents & POLLHUP)
                     pa_log_warn("Got POLLHUP from ALSA");
 
+                state = snd_pcm_state(u->pcm_handle);
+                pa_log_warn("PCM state is %s", snd_pcm_state_name(state));
+
                 /* Try to recover from this error */
 
-                switch (snd_pcm_state(u->pcm_handle)) {
+                switch (state) {
 
                     case SND_PCM_STATE_XRUN:
                         if ((err = snd_pcm_recover(u->pcm_handle, -EPIPE, 1)) != 0) {
@@ -814,6 +845,8 @@ static void thread_func(void *userdata) {
                         }
                         break;
                 }
+
+                snd_pcm_start(u->pcm_handle);
             }
         }
     }
@@ -979,14 +1012,25 @@ int pa__init(pa_module*m) {
 
         if (pa_alsa_prepare_mixer(u->mixer_handle, u->device_name) >= 0)
             found = TRUE;
-        else if (dev_id) {
-            char *md = pa_sprintf_malloc("hw:%s", dev_id);
+        else {
+            snd_pcm_info_t* info;
+
+            snd_pcm_info_alloca(&info);
 
-            if (strcmp(u->device_name, md))
-                if (pa_alsa_prepare_mixer(u->mixer_handle, md) >= 0)
-                    found = TRUE;
+            if (snd_pcm_info(u->pcm_handle, info) >= 0) {
+                char *md;
+                int card;
 
-            pa_xfree(md);
+                if ((card = snd_pcm_info_get_card(info)) >= 0) {
+
+                    md = pa_sprintf_malloc("hw:%i", card);
+
+                    if (strcmp(u->device_name, md))
+                        if (pa_alsa_prepare_mixer(u->mixer_handle, md) >= 0)
+                            found = TRUE;
+                    pa_xfree(md);
+                }
+            }
         }
 
         if (found)
@@ -1138,6 +1182,8 @@ int pa__init(pa_module*m) {
     } else
         u->mixer_fdl = NULL;
 
+    pa_alsa_dump(u->pcm_handle);
+
     if (!(u->thread = pa_thread_new(thread_func, u))) {
         pa_log("Failed to create thread.");
         goto fail;

commit 3138928504d58c7924b0477b4ec3a6ac6205eaa2
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Apr 9 01:14:33 2008 +0000

    include proplist.h in doxygen docs
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2222 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/doxygen/doxygen.conf.in b/doxygen/doxygen.conf.in
index 8ccf667..a45dc2d 100644
--- a/doxygen/doxygen.conf.in
+++ b/doxygen/doxygen.conf.in
@@ -417,7 +417,7 @@ WARN_LOGFILE           =
 # directories like "/usr/src/myproject". Separate the files or directories 
 # with spaces.
 
-INPUT                  = ../src/pulse/context.h ../src/pulse/stream.h ../src/pulse/pulseaudio.h ../src/pulse/sample.h ../src/pulse/def.h ../src/pulse/subscribe.h ../src/pulse/introspect.h ../src/pulse/scache.h ../src/pulse/mainloop-api.h ../src/pulse/glib-mainloop.h ../src/pulse/mainloop.h ../src/pulse/mainloop-signal.h ../src/pulse/error.h ../src/pulse/operation.h ../src/pulse/simple.h ../src/pulse/version.h ../src/pulse/volume.h ../src/pulse/channelmap.h ../src/pulse/thread-mainloop.h ../src/pulse/xmalloc.h ../src/pulse/utf8.h ../src/pulse/util.h ../src/pulse/timeval.h
+INPUT                  = ../src/pulse/context.h ../src/pulse/stream.h ../src/pulse/pulseaudio.h ../src/pulse/sample.h ../src/pulse/def.h ../src/pulse/subscribe.h ../src/pulse/introspect.h ../src/pulse/scache.h ../src/pulse/mainloop-api.h ../src/pulse/glib-mainloop.h ../src/pulse/mainloop.h ../src/pulse/mainloop-signal.h ../src/pulse/error.h ../src/pulse/operation.h ../src/pulse/simple.h ../src/pulse/version.h ../src/pulse/volume.h ../src/pulse/channelmap.h ../src/pulse/thread-mainloop.h ../src/pulse/xmalloc.h ../src/pulse/utf8.h ../src/pulse/util.h ../src/pulse/timeval.h ../src/pulse/proplist.h
 
 # If the value of the INPUT tag contains directories, you can use the 
 # FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp 

commit 0f9e977110fbde443a27ade932ee487e79f0c5b9
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Apr 9 01:14:59 2008 +0000

    bump protocol version
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2223 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/configure.ac b/configure.ac
index 112f632..76ce327 100644
--- a/configure.ac
+++ b/configure.ac
@@ -26,7 +26,7 @@ AC_PREREQ(2.60)
 
 m4_define(PA_MAJOR, [0])
 m4_define(PA_MINOR, [9])
-m4_define(PA_MICRO, [10])
+m4_define(PA_MICRO, [11])
 
 AC_INIT([pulseaudio], PA_MAJOR.PA_MINOR.PA_MICRO,[mzchyfrnhqvb (at) 0pointer (dot) net])
 AC_CONFIG_SRCDIR([src/daemon/main.c])
@@ -37,7 +37,7 @@ AC_SUBST(PA_MAJORMINOR, "PA_MAJOR.PA_MINOR")
 AC_SUBST(PACKAGE_URL, [http://pulseaudio.org/])
 
 AC_SUBST(PA_API_VERSION, 11)
-AC_SUBST(PA_PROTOCOL_VERSION, 12)
+AC_SUBST(PA_PROTOCOL_VERSION, 13)
 
 # The stable ABI for client applications, for the version info x:y:z
 # always will hold y=z

commit ad18107223e8c4199b86bb3616677a2b57293fad
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Apr 9 01:15:23 2008 +0000

    add new latency argument
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2224 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/utils/pacat.c b/src/utils/pacat.c
index 68e308d..e309213 100644
--- a/src/utils/pacat.c
+++ b/src/utils/pacat.c
@@ -71,6 +71,8 @@ static int channel_map_set = 0;
 
 static pa_stream_flags_t flags = 0;
 
+static size_t latency = 0;
+
 /* A shortcut for terminating the application */
 static void quit(int ret) {
     assert(mainloop_api);
@@ -229,6 +231,7 @@ static void context_state_callback(pa_context *c, void *userdata) {
 
         case PA_CONTEXT_READY: {
             int r;
+            pa_buffer_attr buffer_attr;
 
             assert(c);
             assert(!stream);
@@ -247,15 +250,21 @@ static void context_state_callback(pa_context *c, void *userdata) {
             pa_stream_set_suspended_callback(stream, stream_suspended_callback, NULL);
             pa_stream_set_moved_callback(stream, stream_moved_callback, NULL);
 
+            if (latency > 0) {
+                memset(&buffer_attr, 0, sizeof(buffer_attr));
+                buffer_attr.tlength = latency;
+                flags |= PA_STREAM_ADJUST_LATENCY;
+            }
+
             if (mode == PLAYBACK) {
                 pa_cvolume cv;
-                if ((r = pa_stream_connect_playback(stream, device, NULL, flags, pa_cvolume_set(&cv, sample_spec.channels, volume), NULL)) < 0) {
+                if ((r = pa_stream_connect_playback(stream, device, latency > 0 ? &buffer_attr : NULL, flags, pa_cvolume_set(&cv, sample_spec.channels, volume), NULL)) < 0) {
                     fprintf(stderr, "pa_stream_connect_playback() failed: %s\n", pa_strerror(pa_context_errno(c)));
                     goto fail;
                 }
 
             } else {
-                if ((r = pa_stream_connect_record(stream, device, NULL, flags)) < 0) {
+                if ((r = pa_stream_connect_record(stream, device, latency > 0 ? &buffer_attr : NULL, flags)) < 0) {
                     fprintf(stderr, "pa_stream_connect_record() failed: %s\n", pa_strerror(pa_context_errno(c)));
                     goto fail;
                 }
@@ -478,6 +487,7 @@ static void help(const char *argv0) {
            "                                        from the sink the stream is being connected to.\n"
            "      --no-remix                        Don't upmix or downmix channels.\n"
            "      --no-remap                        Map channels by index instead of name.\n"
+           "      --latency=BYTES                   Request the specified latency in bytes.\n"
            ,
            argv0);
 }
@@ -494,7 +504,8 @@ enum {
     ARG_FIX_RATE,
     ARG_FIX_CHANNELS,
     ARG_NO_REMAP,
-    ARG_NO_REMIX
+    ARG_NO_REMIX,
+    ARG_LATENCY
 };
 
 int main(int argc, char *argv[]) {
@@ -523,6 +534,7 @@ int main(int argc, char *argv[]) {
         {"fix-channels",0, NULL, ARG_FIX_CHANNELS},
         {"no-remap",    0, NULL, ARG_NO_REMAP},
         {"no-remix",    0, NULL, ARG_NO_REMIX},
+        {"latency",     0, NULL, ARG_LATENCY},
         {NULL,          0, NULL, 0}
     };
 
@@ -601,7 +613,7 @@ int main(int argc, char *argv[]) {
 
             case ARG_CHANNELMAP:
                 if (!pa_channel_map_parse(&channel_map, optarg)) {
-                    fprintf(stderr, "Invalid channel map\n");
+                    fprintf(stderr, "Invalid channel map '%s'\n", optarg);
                     goto quit;
                 }
 
@@ -628,6 +640,13 @@ int main(int argc, char *argv[]) {
                 flags |= PA_STREAM_NO_REMAP_CHANNELS;
                 break;
 
+            case ARG_LATENCY:
+                if (((latency = atoi(optarg))) <= 0) {
+                    fprintf(stderr, "Invallid latency specification '%s'\n", optarg);
+                    goto quit;
+                }
+                break;
+
             default:
                 goto quit;
         }

commit da37a7e93db0f17e03f94f7835d7075faa3ac4ba
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Apr 9 01:16:43 2008 +0000

    export both min and max latency that is configured for a sink; add API for querying the requested latency of a sink/source from the main thread
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2225 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c
index 989e2ae..ddd9980 100644
--- a/src/pulsecore/sink-input.c
+++ b/src/pulsecore/sink-input.c
@@ -677,13 +677,21 @@ void pa_sink_input_set_max_rewind(pa_sink_input *i, size_t nbytes  /* in the sin
 pa_usec_t pa_sink_input_set_requested_latency(pa_sink_input *i, pa_usec_t usec) {
     pa_sink_input_assert_ref(i);
 
-    if (usec < i->sink->min_latency)
-        usec = i->sink->min_latency;
+    if (usec > 0) {
+
+        if (i->sink->max_latency > 0 && usec > i->sink->max_latency)
+            usec = i->sink->max_latency;
+
+        if (i->sink->min_latency > 0 && usec < i->sink->min_latency)
+            usec = i->sink->min_latency;
+    }
 
     if (PA_SINK_INPUT_LINKED(i->state))
         pa_asyncmsgq_post(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_SET_REQUESTED_LATENCY, NULL, (int64_t) usec, NULL, NULL);
-    else
+    else {
         i->thread_info.requested_sink_latency = usec;
+        i->sink->thread_info.requested_latency_valid = FALSE;
+    }
 
     return usec;
 }
diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c
index 39ce83f..02f568e 100644
--- a/src/pulsecore/sink.c
+++ b/src/pulsecore/sink.c
@@ -188,6 +188,7 @@ pa_sink* pa_sink_new(
     s->silence = pa_silence_memblock_new(core->mempool, &s->sample_spec, 0);
 
     s->min_latency = DEFAULT_MIN_LATENCY;
+    s->max_latency = s->min_latency;
 
     s->thread_info.inputs = pa_hashmap_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
     s->thread_info.soft_volume = s->volume;
@@ -278,6 +279,8 @@ void pa_sink_put(pa_sink* s) {
     pa_assert(s->asyncmsgq);
     pa_assert(s->rtpoll);
 
+    pa_assert(!s->min_latency || !s->max_latency || s->min_latency <= s->max_latency);
+
     if (s->get_volume && s->set_volume)
         s->flags |= PA_SINK_HW_VOLUME_CTRL;
     else
@@ -1132,13 +1135,20 @@ int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offse
              * asyncmsgq and rtpoll fields can be changed without
              * problems */
             pa_sink_detach_within_thread(s);
-            break;
+            return 0;
 
         case PA_SINK_MESSAGE_ATTACH:
 
             /* Reattach all streams */
             pa_sink_attach_within_thread(s);
-            break;
+            return 0;
+
+        case PA_SINK_MESSAGE_GET_REQUESTED_LATENCY: {
+
+            pa_usec_t *usec = userdata;
+            *usec = pa_sink_get_requested_latency_within_thread(s);
+            return 0;
+        }
 
         case PA_SINK_MESSAGE_GET_LATENCY:
         case PA_SINK_MESSAGE_MAX:
@@ -1223,7 +1233,7 @@ void pa_sink_request_rewind(pa_sink*s, size_t nbytes) {
         s->request_rewind(s);
 }
 
-pa_usec_t pa_sink_get_requested_latency(pa_sink *s) {
+pa_usec_t pa_sink_get_requested_latency_within_thread(pa_sink *s) {
     pa_usec_t result = 0;
     pa_sink_input *i;
     void *state = NULL;
@@ -1239,12 +1249,35 @@ pa_usec_t pa_sink_get_requested_latency(pa_sink *s) {
             (!result || result > i->thread_info.requested_sink_latency))
             result = i->thread_info.requested_sink_latency;
 
+    if (result > 0) {
+        if (s->max_latency > 0 && result > s->max_latency)
+            result = s->max_latency;
+
+        if (s->min_latency > 0 && result < s->min_latency)
+            result = s->min_latency;
+    }
+
     s->thread_info.requested_latency = result;
     s->thread_info.requested_latency_valid = TRUE;
 
     return result;
 }
 
+pa_usec_t pa_sink_get_requested_latency(pa_sink *s) {
+    pa_usec_t usec = 0;
+
+    pa_sink_assert_ref(s);
+    pa_assert(PA_SINK_LINKED(s->state));
+
+    if (!PA_SINK_OPENED(s->state))
+        return 0;
+
+    if (pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_GET_REQUESTED_LATENCY, &usec, 0, NULL) < 0)
+        return 0;
+
+    return usec;
+}
+
 void pa_sink_set_max_rewind(pa_sink *s, size_t max_rewind) {
     pa_sink_input *i;
     void *state = NULL;
diff --git a/src/pulsecore/sink.h b/src/pulsecore/sink.h
index 23f02c4..2dfd845 100644
--- a/src/pulsecore/sink.h
+++ b/src/pulsecore/sink.h
@@ -91,7 +91,8 @@ struct pa_sink {
 
     pa_memblock *silence;
 
-    pa_usec_t min_latency; /* we won't go below this latency setting */
+    pa_usec_t min_latency; /* we won't go below this latency */
+    pa_usec_t max_latency; /* An upper limit for the latencies */
 
     int (*set_state)(pa_sink *s, pa_sink_state_t state); /* may be NULL */
     int (*set_volume)(pa_sink *s);             /* dito */
@@ -135,6 +136,7 @@ typedef enum pa_sink_message {
     PA_SINK_MESSAGE_GET_MUTE,
     PA_SINK_MESSAGE_SET_MUTE,
     PA_SINK_MESSAGE_GET_LATENCY,
+    PA_SINK_MESSAGE_GET_REQUESTED_LATENCY,
     PA_SINK_MESSAGE_SET_STATE,
     PA_SINK_MESSAGE_PING,
     PA_SINK_MESSAGE_REMOVE_INPUT_AND_BUFFER,
@@ -191,6 +193,7 @@ void pa_sink_attach(pa_sink *s);
 
 /* The returned value is supposed to be in the time domain of the sound card! */
 pa_usec_t pa_sink_get_latency(pa_sink *s);
+pa_usec_t pa_sink_get_requested_latency(pa_sink *s);
 
 int pa_sink_update_status(pa_sink*s);
 int pa_sink_suspend(pa_sink *s, pa_bool_t suspend);
@@ -227,7 +230,7 @@ int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offse
 void pa_sink_attach_within_thread(pa_sink *s);
 void pa_sink_detach_within_thread(pa_sink *s);
 
-pa_usec_t pa_sink_get_requested_latency(pa_sink *s);
+pa_usec_t pa_sink_get_requested_latency_within_thread(pa_sink *s);
 
 void pa_sink_set_max_rewind(pa_sink *s, size_t max_rewind);
 
diff --git a/src/pulsecore/source-output.c b/src/pulsecore/source-output.c
index d6c2a2b..cf576ac 100644
--- a/src/pulsecore/source-output.c
+++ b/src/pulsecore/source-output.c
@@ -364,13 +364,22 @@ pa_usec_t pa_source_output_set_requested_latency(pa_source_output *o, pa_usec_t
     pa_source_output_assert_ref(o);
     pa_assert(PA_SOURCE_OUTPUT_LINKED(o->state));
 
-    if (usec < o->source->min_latency)
-        usec = o->source->min_latency;
+    if (usec > 0) {
+
+        if (o->source->max_latency > 0 && usec > o->source->max_latency)
+            usec = o->source->max_latency;
+
+        if (o->source->min_latency > 0 && usec < o->source->min_latency)
+            usec = o->source->min_latency;
+
+    }
 
     if (PA_SOURCE_OUTPUT_LINKED(o->state))
         pa_asyncmsgq_post(o->source->asyncmsgq, PA_MSGOBJECT(o), PA_SOURCE_OUTPUT_MESSAGE_SET_REQUESTED_LATENCY, NULL, (int64_t) usec, NULL, NULL);
-    else
+    else {
         o->thread_info.requested_source_latency = usec;
+        o->source->thread_info.requested_latency_valid = FALSE;
+    }
 
     return usec;
 }
diff --git a/src/pulsecore/source.c b/src/pulsecore/source.c
index b150d8a..5a4b630 100644
--- a/src/pulsecore/source.c
+++ b/src/pulsecore/source.c
@@ -166,6 +166,7 @@ pa_source* pa_source_new(
     s->refresh_volume = s->refresh_muted = FALSE;
 
     s->min_latency = DEFAULT_MIN_LATENCY;
+    s->max_latency = s->min_latency;
 
     s->get_latency = NULL;
     s->set_volume = NULL;
@@ -243,6 +244,8 @@ void pa_source_put(pa_source *s) {
     pa_assert(s->rtpoll);
     pa_assert(s->asyncmsgq);
 
+    pa_assert(!s->min_latency || !s->max_latency || s->min_latency <= s->max_latency);
+
     if (s->get_volume && s->set_volume)
         s->flags |= PA_SOURCE_HW_VOLUME_CTRL;
     else {
@@ -616,13 +619,20 @@ int pa_source_process_msg(pa_msgobject *object, int code, void *userdata, int64_
              * asyncmsgq and rtpoll fields can be changed without
              * problems */
             pa_source_detach_within_thread(s);
-            break;
+            return 0;
 
         case PA_SOURCE_MESSAGE_ATTACH:
 
             /* Reattach all streams */
             pa_source_attach_within_thread(s);
-            break;
+            return 0;
+
+        case PA_SOURCE_MESSAGE_GET_REQUESTED_LATENCY: {
+
+            pa_usec_t *usec = userdata;
+            *usec = pa_source_get_requested_latency_within_thread(s);
+            return 0;
+        }
 
         case PA_SOURCE_MESSAGE_GET_LATENCY:
         case PA_SOURCE_MESSAGE_MAX:
@@ -683,7 +693,7 @@ void pa_source_attach_within_thread(pa_source *s) {
             o->attach(o);
 }
 
-pa_usec_t pa_source_get_requested_latency(pa_source *s) {
+pa_usec_t pa_source_get_requested_latency_within_thread(pa_source *s) {
     pa_usec_t result = 0;
     pa_source_output *o;
     void *state = NULL;
@@ -699,12 +709,35 @@ pa_usec_t pa_source_get_requested_latency(pa_source *s) {
             (!result || result > o->thread_info.requested_source_latency))
             result = o->thread_info.requested_source_latency;
 
+    if (result > 0) {
+        if (s->max_latency > 0 && result > s->max_latency)
+            result = s->max_latency;
+
+        if (s->min_latency > 0 && result < s->min_latency)
+            result = s->min_latency;
+    }
+
     s->thread_info.requested_latency = result;
     s->thread_info.requested_latency_valid = TRUE;
 
     return result;
 }
 
+pa_usec_t pa_source_get_requested_latency(pa_source *s) {
+    pa_usec_t usec;
+
+    pa_source_assert_ref(s);
+    pa_assert(PA_SOURCE_LINKED(s->state));
+
+    if (!PA_SOURCE_OPENED(s->state))
+        return 0;
+
+    if (pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_GET_REQUESTED_LATENCY, &usec, 0, NULL) < 0)
+        return 0;
+
+    return usec;
+}
+
 void pa_source_invalidate_requested_latency(pa_source *s) {
 
     pa_source_assert_ref(s);
diff --git a/src/pulsecore/source.h b/src/pulsecore/source.h
index 3ec8320..ab7236e 100644
--- a/src/pulsecore/source.h
+++ b/src/pulsecore/source.h
@@ -92,6 +92,7 @@ struct pa_source {
     pa_rtpoll *rtpoll;
 
     pa_usec_t min_latency; /* we won't go below this latency setting */
+    pa_usec_t max_latency; /* An upper limit for the latencies */
 
     int (*set_state)(pa_source*source, pa_source_state_t state); /* may be NULL */
     int (*set_volume)(pa_source *s);         /* dito */
@@ -127,6 +128,7 @@ typedef enum pa_source_message {
     PA_SOURCE_MESSAGE_GET_MUTE,
     PA_SOURCE_MESSAGE_SET_MUTE,
     PA_SOURCE_MESSAGE_GET_LATENCY,
+    PA_SOURCE_MESSAGE_GET_REQUESTED_LATENCY,
     PA_SOURCE_MESSAGE_SET_STATE,
     PA_SOURCE_MESSAGE_PING,
     PA_SOURCE_MESSAGE_ATTACH,
@@ -181,6 +183,7 @@ void pa_source_attach(pa_source *s);
 /* May be called by everyone, from main context */
 
 pa_usec_t pa_source_get_latency(pa_source *s);
+pa_usec_t pa_source_get_requested_latency(pa_source *s);
 
 int pa_source_update_status(pa_source*s);
 int pa_source_suspend(pa_source *s, pa_bool_t suspend);
@@ -206,7 +209,7 @@ int pa_source_process_msg(pa_msgobject *o, int code, void *userdata, int64_t, pa
 void pa_source_attach_within_thread(pa_source *s);
 void pa_source_detach_within_thread(pa_source *s);
 
-pa_usec_t pa_source_get_requested_latency(pa_source *s);
+pa_usec_t pa_source_get_requested_latency_within_thread(pa_source *s);
 
 /* To be called exclusively by source output drivers, from IO context */
 

commit f3109be9e1df3f7ef723e7122c80e58cc3944951
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Apr 9 01:17:16 2008 +0000

    show configured latency and its ranges
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2226 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/cli-text.c b/src/pulsecore/cli-text.c
index 8bb567b..5bf27ee 100644
--- a/src/pulsecore/cli-text.c
+++ b/src/pulsecore/cli-text.c
@@ -128,6 +128,7 @@ char *pa_sink_list_to_string(pa_core *c) {
             "\tvolume: <%s>\n"
             "\tmute: <%i>\n"
             "\tlatency: <%0.0f usec>\n"
+            "\tconfigured latency: <%0.0f usec> from range <%0.0f usec> .. <%0.0f usec>\n"
             "\tmonitor source: <%u>\n"
             "\tsample spec: <%s>\n"
             "\tchannel map: <%s>\n"
@@ -147,6 +148,7 @@ char *pa_sink_list_to_string(pa_core *c) {
             pa_cvolume_snprint(cv, sizeof(cv), pa_sink_get_volume(sink)),
             !!pa_sink_get_mute(sink),
             (double) pa_sink_get_latency(sink),
+            (double) pa_sink_get_requested_latency(sink), (double) sink->min_latency, (double) sink->max_latency,
             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),
@@ -194,6 +196,7 @@ char *pa_source_list_to_string(pa_core *c) {
             "\tvolume: <%s>\n"
             "\tmute: <%u>\n"
             "\tlatency: <%0.0f usec>\n"
+            "\tconfigured latency: <%0.0f usec> from range <%0.0f usec> .. <%0.0f usec>\n"
             "\tsample spec: <%s>\n"
             "\tchannel map: <%s>\n"
             "\tused by: <%u>\n"
@@ -212,6 +215,7 @@ char *pa_source_list_to_string(pa_core *c) {
             pa_cvolume_snprint(cv, sizeof(cv), pa_source_get_volume(source)),
             !!pa_source_get_mute(source),
             (double) pa_source_get_latency(source),
+            (double) pa_source_get_requested_latency(source), (double) source->min_latency, (double) source->max_latency,
             pa_sample_spec_snprint(ss, sizeof(ss), &source->sample_spec),
             pa_channel_map_snprint(cm, sizeof(cm), &source->channel_map),
             pa_source_used_by(source),

commit cc1e2654d30ee7547aebd3c1d5b26802e8bea5ff
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Apr 9 01:18:05 2008 +0000

    init min/max latency properly; fix avail_min updating
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2227 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-alsa-sink.c b/src/modules/module-alsa-sink.c
index 70a94ee..513350f 100644
--- a/src/modules/module-alsa-sink.c
+++ b/src/modules/module-alsa-sink.c
@@ -436,7 +436,7 @@ static pa_usec_t hw_sleep_time(struct userdata *u) {
 
     pa_assert(u);
 
-    usec = pa_sink_get_requested_latency(u->sink);
+    usec = pa_sink_get_requested_latency_within_thread(u->sink);
 
     if (usec <= 0)
         usec = pa_bytes_to_usec(u->hwbuf_size, &u->sink->sample_spec);
@@ -461,7 +461,7 @@ static void update_hwbuf_unused_frames(struct userdata *u) {
 
     pa_assert(u);
 
-    if ((usec = pa_sink_get_requested_latency(u->sink)) <= 0) {
+    if ((usec = pa_sink_get_requested_latency_within_thread(u->sink)) <= 0) {
         /* Use the full buffer if noone asked us for anything
          * specific */
         u->hwbuf_unused_frames = 0;
@@ -499,8 +499,6 @@ static int update_sw_params(struct userdata *u) {
     } else
         avail_min = 1;
 
-    avail_min = (snd_pcm_uframes_t) -1;
-
     pa_log("setting avail_min=%lu", (unsigned long) avail_min);
 
     if ((err = pa_alsa_set_sw_params(u->pcm_handle, avail_min)) < 0) {
@@ -1222,8 +1220,10 @@ int pa__init(pa_module*m) {
 
     u->sink->thread_info.max_rewind = use_tsched ? u->hwbuf_size : 0;
 
+    u->sink->max_latency = pa_bytes_to_usec(u->hwbuf_size, &ss);
+
     if (!use_tsched)
-        u->sink->min_latency = pa_bytes_to_usec(u->hwbuf_size, &ss);
+        u->sink->min_latency = u->sink->max_latency;
 
     pa_log_info("Using %u fragments of size %lu bytes, buffer time is %0.2fms",
                 nfrags, (long unsigned) u->fragment_size,
diff --git a/src/modules/module-alsa-source.c b/src/modules/module-alsa-source.c
index a074bc6..caaa545 100644
--- a/src/modules/module-alsa-source.c
+++ b/src/modules/module-alsa-source.c
@@ -411,7 +411,7 @@ static pa_usec_t hw_sleep_time(struct userdata *u) {
 
     pa_assert(u);
 
-    usec = pa_source_get_requested_latency(u->source);
+    usec = pa_source_get_requested_latency_within_thread(u->source);
 
     if (usec <= 0)
         usec = pa_bytes_to_usec(u->hwbuf_size, &u->source->sample_spec);
@@ -1093,8 +1093,10 @@ int pa__init(pa_module*m) {
     u->hw_dB_min = u->hw_dB_max = 0;
     u->hw_volume_min = u->hw_volume_max = 0;
 
+    u->source->max_latency = pa_bytes_to_usec(u->hwbuf_size, &ss);
+
     if (!use_tsched)
-        u->source->min_latency = pa_bytes_to_usec(u->hwbuf_size, &ss);
+        u->source->min_latency = u->source->max_latency;
 
     pa_log_info("Using %u fragments of size %lu bytes, buffer time is %0.2fms",
                 nfrags, (long unsigned) u->fragment_size,
diff --git a/src/modules/module-ladspa-sink.c b/src/modules/module-ladspa-sink.c
index 1ba2b48..2342cde 100644
--- a/src/modules/module-ladspa-sink.c
+++ b/src/modules/module-ladspa-sink.c
@@ -145,7 +145,7 @@ static void sink_update_requested_latency(pa_sink *s) {
     pa_assert_se(u = s->userdata);
 
     /* Just hand this one over to the master sink */
-    u->sink_input->thread_info.requested_sink_latency = pa_sink_get_requested_latency(s);
+    u->sink_input->thread_info.requested_sink_latency = pa_sink_get_requested_latency_within_thread(s);
     pa_sink_invalidate_requested_latency(u->master);
 }
 
diff --git a/src/modules/module-remap-sink.c b/src/modules/module-remap-sink.c
index 1c97a82..2dc4f2a 100644
--- a/src/modules/module-remap-sink.c
+++ b/src/modules/module-remap-sink.c
@@ -123,7 +123,7 @@ static void sink_update_requested_latency(pa_sink *s) {
     pa_assert_se(u = s->userdata);
 
     /* Just hand this one over to the master sink */
-    u->sink_input->thread_info.requested_sink_latency = pa_sink_get_requested_latency(s);
+    u->sink_input->thread_info.requested_sink_latency = pa_sink_get_requested_latency_within_thread(s);
     pa_sink_invalidate_requested_latency(u->master);
 }
 

commit fc9d8276dbc1472c8eb726adfd8aa8203a6393fb
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Apr 9 01:19:01 2008 +0000

    remove doxygen \since tag for API changes older than 0.9; properly implement new latency query APIs
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2228 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulse/channelmap.h b/src/pulse/channelmap.h
index a05e191..4122a31 100644
--- a/src/pulse/channelmap.h
+++ b/src/pulse/channelmap.h
@@ -183,7 +183,7 @@ const char* pa_channel_position_to_pretty_string(pa_channel_position_t pos);
 /** Make a humand readable string from the specified channel map */
 char* pa_channel_map_snprint(char *s, size_t l, const pa_channel_map *map);
 
-/** Parse a channel position list into a channel map structure. \since 0.8.1 */
+/** Parse a channel position list into a channel map structure. */
 pa_channel_map *pa_channel_map_parse(pa_channel_map *map, const char *s);
 
 /** Compare two channel maps. Return 1 if both match. */
diff --git a/src/pulse/context.h b/src/pulse/context.h
index cb2a531..143508f 100644
--- a/src/pulse/context.h
+++ b/src/pulse/context.h
@@ -173,7 +173,7 @@ pa_context *pa_context_new(pa_mainloop_api *mainloop, const char *name);
 
 /** Instantiate a new connection context with an abstract mainloop API
  * and an application name, and specify the the initial client property
- * list. \since 0.9.10 */
+ * list. \since 0.9.11 */
 pa_context *pa_context_new_with_proplist(pa_mainloop_api *mainloop, const char *name, pa_proplist *proplist);
 
 /** Decrease the reference counter of the context by one */
@@ -214,40 +214,40 @@ pa_operation* pa_context_drain(pa_context *c, pa_context_notify_cb_t cb, void *u
  * returning a success notification */
 pa_operation* pa_context_exit_daemon(pa_context *c, pa_context_success_cb_t cb, void *userdata);
 
-/** Set the name of the default sink. \since 0.4 */
+/** Set the name of the default sink. */
 pa_operation* pa_context_set_default_sink(pa_context *c, const char *name, pa_context_success_cb_t cb, void *userdata);
 
-/** Set the name of the default source. \since 0.4 */
+/** Set the name of the default source. */
 pa_operation* pa_context_set_default_source(pa_context *c, const char *name, pa_context_success_cb_t cb, void *userdata);
 
-/** Returns 1 when the connection is to a local daemon. Returns negative when no connection has been made yet. \since 0.5 */
+/** Returns 1 when the connection is to a local daemon. Returns negative when no connection has been made yet. */
 int pa_context_is_local(pa_context *c);
 
-/** Set a different application name for context on the server. \since 0.5 */
+/** Set a different application name for context on the server. */
 pa_operation* pa_context_set_name(pa_context *c, const char *name, pa_context_success_cb_t cb, void *userdata);
 
-/** Return the server name this context is connected to. \since 0.7 */
+/** Return the server name this context is connected to. */
 const char* pa_context_get_server(pa_context *c);
 
-/** Return the protocol version of the library. \since 0.8 */
+/** Return the protocol version of the library. */
 uint32_t pa_context_get_protocol_version(pa_context *c);
 
-/** Return the protocol version of the connected server. \since 0.8 */
+/** Return the protocol version of the connected server. */
 uint32_t pa_context_get_server_protocol_version(pa_context *c);
 
 /* Update the property list of the client, adding new entries. Please
  * note that it is highly recommended to set as much properties
  * initially via pa_context_new_with_proplist() as possible instead a
  * posteriori with this function, since that information may then be
- * used to route streams of the client to the right device. \since 0.9.10 */
+ * used to route streams of the client to the right device. \since 0.9.11 */
 pa_operation *pa_context_proplist_update(pa_context *c, pa_update_mode_t mode, pa_proplist *p, pa_context_success_cb_t cb, void *userdata);
 
-/* Update the property list of the client, remove entries. \since 0.9.10 */
+/* Update the property list of the client, remove entries. \since 0.9.11 */
 pa_operation *pa_context_proplist_remove(pa_context *c, const char *const keys[], pa_context_success_cb_t cb, void *userdata);
 
 /** Return the client index this context is
  * identified in the server with. This is useful for usage with the
- * introspection functions, such as pa_context_get_client_info(). \since 0.9.10 */
+ * introspection functions, such as pa_context_get_client_info(). \since 0.9.11 */
 uint32_t pa_context_get_index(pa_context *s);
 
 PA_C_DECL_END
diff --git a/src/pulse/def.h b/src/pulse/def.h
index ae76660..8a83d7a 100644
--- a/src/pulse/def.h
+++ b/src/pulse/def.h
@@ -67,7 +67,7 @@ typedef enum pa_operation_state {
 /** An invalid index */
 #define PA_INVALID_INDEX ((uint32_t) -1)
 
-/** Some special flags for contexts. \since 0.8 */
+/** Some special flags for contexts. */
 typedef enum pa_context_flags {
     PA_CONTEXT_NOAUTOSPAWN = 1 /**< Disabled autospawning of the PulseAudio daemon if required */
 } pa_context_flags_t;
@@ -80,7 +80,7 @@ typedef enum pa_stream_direction {
     PA_STREAM_UPLOAD         /**< Sample upload stream */
 } pa_stream_direction_t;
 
-/** Some special flags for stream connections. \since 0.6 */
+/** Some special flags for stream connections. */
 typedef enum pa_stream_flags {
     PA_STREAM_START_CORKED = 1,       /**< Create the stream corked, requiring an explicit pa_stream_cork() call to uncork it. */
     PA_STREAM_INTERPOLATE_TIMING = 2, /**< Interpolate the latency for
@@ -293,8 +293,8 @@ enum {
     PA_ERR_MODINITFAILED,          /**< Module initialization failed */
     PA_ERR_BADSTATE,               /**< Bad state */
     PA_ERR_NODATA,                 /**< No data */
-    PA_ERR_VERSION,                /**< Incompatible protocol version \since 0.8 */
-    PA_ERR_TOOLARGE,               /**< Data too large \since 0.8.1 */
+    PA_ERR_VERSION,                /**< Incompatible protocol version */
+    PA_ERR_TOOLARGE,               /**< Data too large */
     PA_ERR_NOTSUPPORTED,           /**< Operation not supported \since 0.9.5 */
     PA_ERR_MAX                     /**< Not really an error but the first invalid error code */
 };
@@ -309,9 +309,9 @@ typedef enum pa_subscription_mask {
     PA_SUBSCRIPTION_MASK_MODULE = 16,            /**< Module events */
     PA_SUBSCRIPTION_MASK_CLIENT = 32,            /**< Client events */
     PA_SUBSCRIPTION_MASK_SAMPLE_CACHE = 64,      /**< Sample cache events */
-    PA_SUBSCRIPTION_MASK_SERVER = 128,           /**< Other global server changes. \since 0.4 */
-    PA_SUBSCRIPTION_MASK_AUTOLOAD = 256,         /**< Autoload table events. \since 0.5 */
-    PA_SUBSCRIPTION_MASK_ALL = 511               /**< Catch all events \since 0.8 */
+    PA_SUBSCRIPTION_MASK_SERVER = 128,           /**< Other global server changes. */
+    PA_SUBSCRIPTION_MASK_AUTOLOAD = 256,         /**< Autoload table events. */
+    PA_SUBSCRIPTION_MASK_ALL = 511               /**< Catch all events */
 } pa_subscription_mask_t;
 
 /** Subscription event types, as used by pa_context_subscribe() */
@@ -323,8 +323,8 @@ typedef enum pa_subscription_event_type {
     PA_SUBSCRIPTION_EVENT_MODULE = 4,         /**< Event type: Module */
     PA_SUBSCRIPTION_EVENT_CLIENT = 5,         /**< Event type: Client */
     PA_SUBSCRIPTION_EVENT_SAMPLE_CACHE = 6,   /**< Event type: Sample cache item */
-    PA_SUBSCRIPTION_EVENT_SERVER = 7,         /**< Event type: Global server change, only occuring with PA_SUBSCRIPTION_EVENT_CHANGE. \since 0.4  */
-    PA_SUBSCRIPTION_EVENT_AUTOLOAD = 8,       /**< Event type: Autoload table changes. \since 0.5 */
+    PA_SUBSCRIPTION_EVENT_SERVER = 7,         /**< Event type: Global server change, only occuring with PA_SUBSCRIPTION_EVENT_CHANGE. */
+    PA_SUBSCRIPTION_EVENT_AUTOLOAD = 8,       /**< Event type: Autoload table changes. */
     PA_SUBSCRIPTION_EVENT_FACILITY_MASK = 15, /**< A mask to extract the event type from an event value */
 
     PA_SUBSCRIPTION_EVENT_NEW = 0,            /**< A new object was created */
@@ -362,12 +362,11 @@ typedef struct pa_timing_info {
                                * detected transport_usec becomes much
                                * more reliable. However, the code that
                                * detects synchronized clocks is very
-                               * limited und unreliable itself. \since
-                               * 0.5 */
+                               * limited und unreliable itself. */
 
     pa_usec_t sink_usec;      /**< Time in usecs a sample takes to be played on the sink. For playback streams and record streams connected to a monitor source. */
-    pa_usec_t source_usec;    /**< Time in usecs a sample takes from being recorded to being delivered to the application. Only for record streams. \since 0.5*/
-    pa_usec_t transport_usec; /**< Estimated time in usecs a sample takes to be transferred to/from the daemon. For both playback and record streams. \since 0.5 */
+    pa_usec_t source_usec;    /**< Time in usecs a sample takes from being recorded to being delivered to the application. Only for record streams. */
+    pa_usec_t transport_usec; /**< Estimated time in usecs a sample takes to be transferred to/from the daemon. For both playback and record streams. */
 
     int playing;              /**< Non-zero when the stream is currently playing. Only for playback streams. */
 
@@ -378,20 +377,19 @@ typedef struct pa_timing_info {
                                * info was current . Only write
                                * commands with SEEK_RELATIVE_ON_READ
                                * and SEEK_RELATIVE_END can corrupt
-                               * write_index. \since 0.8 */
+                               * write_index. */
     int64_t write_index;      /**< Current write index into the
                                * playback buffer in bytes. Think twice before
                                * using this for seeking purposes: it
                                * might be out of date a the time you
                                * want to use it. Consider using
-                               * PA_SEEK_RELATIVE instead. \since
-                               * 0.8 */
+                               * PA_SEEK_RELATIVE instead.  */
 
     int read_index_corrupt;   /**< Non-zero if read_index is not
                                * up-to-date because a local pause or
                                * flush request that corrupted it has
                                * been issued in the time since this
-                               * latency info was current. \since 0.8  */
+                               * latency info was current. */
 
     int64_t read_index;       /**< Current read index into the
                                * playback buffer in bytes. Think twice before
@@ -399,12 +397,12 @@ typedef struct pa_timing_info {
                                * might be out of date a the time you
                                * want to use it. Consider using
                                * PA_SEEK_RELATIVE_ON_READ
-                               * instead. \since 0.8 */
+                               * instead. */
 
-    pa_usec_t max_sink_usec;   /**< The static configure latency for
-                                * the sink. \since 0.9.10 */
-    pa_usec_t max_source_usec; /**< The static configure latency for
-                                * the source. \since 0.9.10 */
+    pa_usec_t configured_sink_usec;   /**< The static configured latency for
+                                * the sink. \since 0.9.11 */
+    pa_usec_t configured_source_usec; /**< The static configured latency for
+                                * the source. \since 0.9.11 */
 } pa_timing_info;
 
 /** A structure for the spawn api. This may be used to integrate auto
@@ -413,7 +411,7 @@ typedef struct pa_timing_info {
  * waitpid() is used on the child's PID. The spawn routine will not
  * block or ignore SIGCHLD signals, since this cannot be done in a
  * thread compatible way. You might have to do this in
- * prefork/postfork. \since 0.4 */
+ * prefork/postfork. */
 typedef struct pa_spawn_api {
     void (*prefork)(void);     /**< Is called just before the fork in the parent process. May be NULL. */
     void (*postfork)(void);    /**< Is called immediately after the fork in the parent process. May be NULL.*/
@@ -426,7 +424,7 @@ typedef struct pa_spawn_api {
                                 * passed to the new process. */
 } pa_spawn_api;
 
-/** Seek type for pa_stream_write(). \since 0.8*/
+/** Seek type for pa_stream_write(). */
 typedef enum pa_seek_mode {
     PA_SEEK_RELATIVE = 0,           /**< Seek relatively to the write index */
     PA_SEEK_ABSOLUTE = 1,           /**< Seek relatively to the start of the buffer queue */
@@ -434,24 +432,24 @@ typedef enum pa_seek_mode {
     PA_SEEK_RELATIVE_END = 3        /**< Seek relatively to the current end of the buffer queue. */
 } pa_seek_mode_t;
 
-/** Special sink flags. \since 0.8  */
+/** Special sink flags. */
 typedef enum pa_sink_flags {
     PA_SINK_HW_VOLUME_CTRL = 1,   /**< Supports hardware volume control */
     PA_SINK_LATENCY = 2,          /**< Supports latency querying */
     PA_SINK_HARDWARE = 4,         /**< Is a hardware sink of some kind, in contrast to "virtual"/software sinks \since 0.9.3 */
     PA_SINK_NETWORK = 8,          /**< Is a networked sink of some kind. \since 0.9.7 */
-    PA_SINK_HW_MUTE_CTRL = 16,    /**< Supports hardware mute control \since 0.9.10 */
-    PA_SINK_DECIBEL_VOLUME = 32   /**< Volume can be translated to dB with pa_sw_volume_to_dB() \since 0.9.10 */
+    PA_SINK_HW_MUTE_CTRL = 16,    /**< Supports hardware mute control \since 0.9.11 */
+    PA_SINK_DECIBEL_VOLUME = 32   /**< Volume can be translated to dB with pa_sw_volume_to_dB() \since 0.9.11 */
 } pa_sink_flags_t;
 
-/** Special source flags. \since 0.8  */
+/** Special source flags.  */
 typedef enum pa_source_flags {
     PA_SOURCE_HW_VOLUME_CTRL = 1,  /**< Supports hardware volume control */
     PA_SOURCE_LATENCY = 2,         /**< Supports latency querying */
     PA_SOURCE_HARDWARE = 4,        /**< Is a hardware source of some kind, in contrast to "virtual"/software source \since 0.9.3 */
     PA_SOURCE_NETWORK = 8,         /**< Is a networked sink of some kind. \since 0.9.7 */
-    PA_SOURCE_HW_MUTE_CTRL = 16,   /**< Supports hardware mute control \since 0.9.10 */
-    PA_SOURCE_DECIBEL_VOLUME = 32  /**< Volume can be translated to dB with pa_sw_volume_to_dB() \since 0.9.10 */
+    PA_SOURCE_HW_MUTE_CTRL = 16,   /**< Supports hardware mute control \since 0.9.11 */
+    PA_SOURCE_DECIBEL_VOLUME = 32  /**< Volume can be translated to dB with pa_sw_volume_to_dB() \since 0.9.11 */
 } pa_source_flags_t;
 
 /** A generic free() like callback prototype */
diff --git a/src/pulse/introspect.c b/src/pulse/introspect.c
index 633ee55..9c50b57 100644
--- a/src/pulse/introspect.c
+++ b/src/pulse/introspect.c
@@ -167,7 +167,9 @@ static void context_get_sink_info_callback(pa_pdispatch *pd, uint32_t command, P
                 pa_tagstruct_get_usec(t, &i.latency) < 0 ||
                 pa_tagstruct_gets(t, &i.driver) < 0 ||
                 pa_tagstruct_getu32(t, &flags) < 0 ||
-                (o->context->version >= 13 && pa_tagstruct_get_proplist(t, i.proplist) < 0)) {
+                (o->context->version >= 13 &&
+                 (pa_tagstruct_get_proplist(t, i.proplist) < 0 ||
+                  pa_tagstruct_get_usec(t, &i.configured_latency) < 0))) {
 
                 pa_context_fail(o->context, PA_ERR_PROTOCOL);
                 pa_proplist_free(i.proplist);
@@ -286,7 +288,9 @@ static void context_get_source_info_callback(pa_pdispatch *pd, uint32_t command,
                 pa_tagstruct_get_usec(t, &i.latency) < 0 ||
                 pa_tagstruct_gets(t, &i.driver) < 0 ||
                 pa_tagstruct_getu32(t, &flags) < 0 ||
-                (o->context->version >= 13 && pa_tagstruct_get_proplist(t, i.proplist) < 0)) {
+                (o->context->version >= 13 &&
+                 (pa_tagstruct_get_proplist(t, i.proplist) < 0 ||
+                  pa_tagstruct_get_usec(t, &i.configured_latency) < 0))) {
 
                 pa_context_fail(o->context, PA_ERR_PROTOCOL);
                 pa_proplist_free(i.proplist);
diff --git a/src/pulse/introspect.h b/src/pulse/introspect.h
index bc78996..09cee60 100644
--- a/src/pulse/introspect.h
+++ b/src/pulse/introspect.h
@@ -207,7 +207,7 @@
 
 PA_C_DECL_BEGIN
 
-#define PA_PORT_SPDIF "spdif"
+#define PA_PORT_DIGITAL "spdif"
 #define PA_PORT_ANALOG_STEREO "analog-stereo"
 #define PA_PORT_ANALOG_5_1 "analog-5-1"
 #define PA_PORT_ANALOG_4_0 "analog-4-0"
@@ -222,17 +222,17 @@ typedef struct pa_sink_info {
     uint32_t index;                    /**< Index of the sink */
     const char *description;           /**< Description of this sink */
     pa_sample_spec sample_spec;        /**< Sample spec of this sink */
-    pa_channel_map channel_map;        /**< Channel map \since 0.8 */
+    pa_channel_map channel_map;        /**< Channel map */
     uint32_t owner_module;             /**< Index of the owning module of this sink, or PA_INVALID_INDEX */
     pa_cvolume volume;                 /**< Volume of the sink */
-    int mute;                          /**< Mute switch of the sink \since 0.8 */
+    int mute;                          /**< Mute switch of the sink */
     uint32_t monitor_source;           /**< Index of the monitor source connected to this sink */
     const char *monitor_source_name;   /**< The name of the monitor source */
     pa_usec_t latency;                 /**< Length of queued audio in the output buffer. */
-    const char *driver;                /**< Driver name. \since 0.8 */
-    pa_sink_flags_t flags;             /**< Flags \since 0.8 */
+    const char *driver;                /**< Driver name. */
+    pa_sink_flags_t flags;             /**< Flags */
     pa_proplist *proplist;             /**< Property list \since 0.9.11 */
-    pa_usec_t max_latency;             /**< The static latency this device has been configured to. \since 0.9.11 */
+    pa_usec_t configured_latency;      /**< The latency this device has been configured to. \since 0.9.11 */
 } pa_sink_info;
 
 /** Callback prototype for pa_context_get_sink_info_by_name() and friends */
@@ -253,10 +253,10 @@ pa_operation* pa_context_set_sink_volume_by_index(pa_context *c, uint32_t idx, c
 /** Set the volume of a sink device specified by its name */
 pa_operation* pa_context_set_sink_volume_by_name(pa_context *c, const char *name, const pa_cvolume *volume, pa_context_success_cb_t cb, void *userdata);
 
-/** Set the mute switch of a sink device specified by its index \since 0.8 */
+/** Set the mute switch of a sink device specified by its index */
 pa_operation* pa_context_set_sink_mute_by_index(pa_context *c, uint32_t idx, int mute, pa_context_success_cb_t cb, void *userdata);
 
-/** Set the mute switch of a sink device specified by its name \since 0.8 */
+/** Set the mute switch of a sink device specified by its name */
 pa_operation* pa_context_set_sink_mute_by_name(pa_context *c, const char *name, int mute, pa_context_success_cb_t cb, void *userdata);
 
 /** Suspend/Resume a sink. \since 0.9.7 */
@@ -277,17 +277,17 @@ typedef struct pa_source_info {
     uint32_t index;                     /**< Index of the source */
     const char *description;            /**< Description of this source */
     pa_sample_spec sample_spec;         /**< Sample spec of this source */
-    pa_channel_map channel_map;         /**< Channel map \since 0.8 */
+    pa_channel_map channel_map;         /**< Channel map */
     uint32_t owner_module;              /**< Owning module index, or PA_INVALID_INDEX */
-    pa_cvolume volume;                  /**< Volume of the source \since 0.8 */
-    int mute;                           /**< Mute switch of the sink \since 0.8 */
+    pa_cvolume volume;                  /**< Volume of the source */
+    int mute;                           /**< Mute switch of the sink */
     uint32_t monitor_of_sink;           /**< If this is a monitor source the index of the owning sink, otherwise PA_INVALID_INDEX */
     const char *monitor_of_sink_name;   /**< Name of the owning sink, or PA_INVALID_INDEX */
-    pa_usec_t latency;                  /**< Length of filled record buffer of this source. \since 0.5 */
-    const char *driver;                 /**< Driver name \since 0.8 */
-    pa_source_flags_t flags;            /**< Flags \since 0.8 */
-    pa_proplist *proplist;              /**< Property list \since 0.9.10 */
-    pa_usec_t max_latency;              /**< The static latency this device has been configured to. \since 0.9.11 */
+    pa_usec_t latency;                  /**< Length of filled record buffer of this source. */
+    const char *driver;                 /**< Driver name */
+    pa_source_flags_t flags;            /**< Flags */
+    pa_proplist *proplist;              /**< Property list \since 0.9.11 */
+    pa_usec_t configured_latency;       /**< The latency this device has been configured to. \since 0.9.11 */
 } pa_source_info;
 
 /** Callback prototype for pa_context_get_source_info_by_name() and friends */
@@ -302,16 +302,16 @@ pa_operation* pa_context_get_source_info_by_index(pa_context *c, uint32_t id, pa
 /** Get the complete source list */
 pa_operation* pa_context_get_source_info_list(pa_context *c, pa_source_info_cb_t cb, void *userdata);
 
-/** Set the volume of a source device specified by its index \since 0.8 */
+/** Set the volume of a source device specified by its index */
 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);
 
-/** Set the volume of a source device specified by its name \since 0.8 */
+/** Set the volume of a source device specified by its name */
 pa_operation* pa_context_set_source_volume_by_name(pa_context *c, const char *name, const pa_cvolume *volume, pa_context_success_cb_t cb, void *userdata);
 
-/** Set the mute switch of a source device specified by its index \since 0.8 */
+/** Set the mute switch of a source device specified by its index */
 pa_operation* pa_context_set_source_mute_by_index(pa_context *c, uint32_t idx, int mute, pa_context_success_cb_t cb, void *userdata);
 
-/** Set the mute switch of a source device specified by its name \since 0.8 */
+/** Set the mute switch of a source device specified by its name */
 pa_operation* pa_context_set_source_mute_by_name(pa_context *c, const char *name, int mute, pa_context_success_cb_t cb, void *userdata);
 
 /** @} */
@@ -327,9 +327,9 @@ typedef struct pa_server_info {
     const char *server_version;         /**< Version string of the daemon */
     const char *server_name;            /**< Server package name (usually "pulseaudio") */
     pa_sample_spec sample_spec;         /**< Default sample specification */
-    const char *default_sink_name;      /**< Name of default sink. \since 0.4 */
-    const char *default_source_name;    /**< Name of default sink. \since 0.4*/
-    uint32_t cookie;                    /**< A random cookie for identifying this instance of PulseAudio. \since 0.8 */
+    const char *default_sink_name;      /**< Name of default sink. */
+    const char *default_source_name;    /**< Name of default sink. */
+    uint32_t cookie;                    /**< A random cookie for identifying this instance of PulseAudio. */
 } pa_server_info;
 
 /** Callback prototype for pa_context_get_server_info() */
@@ -365,10 +365,10 @@ pa_operation* pa_context_get_module_info_list(pa_context *c, pa_module_info_cb_t
 /** Callback prototype for pa_context_load_module() */
 typedef void (*pa_context_index_cb_t)(pa_context *c, uint32_t idx, void *userdata);
 
-/** Load a module. \since 0.5 */
+/** Load a module. */
 pa_operation* pa_context_load_module(pa_context *c, const char*name, const char *argument, pa_context_index_cb_t cb, void *userdata);
 
-/** Unload a module. \since 0.5 */
+/** Unload a module. */
 pa_operation* pa_context_unload_module(pa_context *c, uint32_t idx, pa_context_success_cb_t cb, void *userdata);
 
 /** @} */
@@ -382,8 +382,8 @@ typedef struct pa_client_info {
     uint32_t index;                      /**< Index of this client */
     const char *name;                    /**< Name of this client */
     uint32_t owner_module;               /**< Index of the owning module, or PA_INVALID_INDEX */
-    const char *driver;                  /**< Driver name \since 0.8 */
-    pa_proplist *proplist;               /**< Property list \since 0.9.10 */
+    const char *driver;                  /**< Driver name */
+    pa_proplist *proplist;               /**< Property list \since 0.9.11 */
 } pa_client_info;
 
 /** Callback prototype for pa_context_get_client_info() and firends*/
@@ -395,7 +395,7 @@ pa_operation* pa_context_get_client_info(pa_context *c, uint32_t idx, pa_client_
 /** Get the complete client list */
 pa_operation* pa_context_get_client_info_list(pa_context *c, pa_client_info_cb_t cb, void *userdata);
 
-/** Kill a client. \since 0.5 */
+/** Kill a client. */
 pa_operation* pa_context_kill_client(pa_context *c, uint32_t idx, pa_context_success_cb_t cb, void *userdata);
 
 /** @} */
@@ -416,10 +416,10 @@ typedef struct pa_sink_input_info {
     pa_cvolume volume;                   /**< The volume of this sink input */
     pa_usec_t buffer_usec;               /**< Latency due to buffering in sink input, see pa_latency_info for details */
     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 */
+    const char *resample_method;         /**< Thre resampling method used by this sink input. */
+    const char *driver;                  /**< Driver name */
     int mute;                            /**< Stream muted \since 0.9.7 */
-    pa_proplist *proplist;               /**< Property list \since 0.9.10 */
+    pa_proplist *proplist;               /**< Property list \since 0.9.11 */
 } pa_sink_input_info;
 
 /** Callback prototype for pa_context_get_sink_input_info() and firends*/
@@ -443,7 +443,7 @@ pa_operation* pa_context_set_sink_input_volume(pa_context *c, uint32_t idx, cons
 /** 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);
 
-/** Kill a sink input. \since 0.5 */
+/** Kill a sink input. */
 pa_operation* pa_context_kill_sink_input(pa_context *c, uint32_t idx, pa_context_success_cb_t cb, void *userdata);
 
 /** @} */
@@ -461,11 +461,11 @@ typedef struct pa_source_output_info {
     uint32_t source;                     /**< Index of the connected source */
     pa_sample_spec sample_spec;          /**< The sample specification of the source output */
     pa_channel_map channel_map;          /**< Channel map */
-    pa_usec_t buffer_usec;               /**< Latency due to buffering in the source output, see pa_latency_info for details. \since 0.5 */
-    pa_usec_t source_usec;               /**< Latency of the source device, see pa_latency_info for details. \since 0.5 */
-    const char *resample_method;         /**< Thre resampling method used by this source output. \since 0.7 */
-    const char *driver;                  /**< Driver name \since 0.8 */
-    pa_proplist *proplist;               /**< Property list \since 0.9.10 */
+    pa_usec_t buffer_usec;               /**< Latency due to buffering in the source output, see pa_latency_info for details. */
+    pa_usec_t source_usec;               /**< Latency of the source device, see pa_latency_info for details. */
+    const char *resample_method;         /**< Thre resampling method used by this source output. */
+    const char *driver;                  /**< Driver name */
+    pa_proplist *proplist;               /**< Property list \since 0.9.11 */
 } pa_source_output_info;
 
 /** Callback prototype for pa_context_get_source_output_info() and firends*/
@@ -489,7 +489,7 @@ pa_operation* pa_context_suspend_source_by_name(pa_context *c, char *source_name
 /** 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);
 
-/** Kill a source output. \since 0.5 */
+/** Kill a source output. */
 pa_operation* pa_context_kill_source_output(pa_context *c, uint32_t idx, pa_context_success_cb_t cb, void *userdata);
 
 /** @} */
@@ -504,7 +504,7 @@ typedef struct pa_stat_info {
     uint32_t memblock_total_size;      /**< Currentl total size of allocated memory blocks */
     uint32_t memblock_allocated;       /**< Allocated memory blocks during the whole lifetime of the daemon */
     uint32_t memblock_allocated_size;  /**< Total size of all memory blocks allocated during the whole lifetime of the daemon */
-    uint32_t scache_size;              /**< Total size of all sample cache entries. \since 0.4 */
+    uint32_t scache_size;              /**< Total size of all sample cache entries. */
 } pa_stat_info;
 
 /** Callback prototype for pa_context_stat() */
@@ -527,10 +527,10 @@ typedef struct pa_sample_info {
     pa_sample_spec sample_spec;           /**< Sample specification of the sample */
     pa_channel_map channel_map;           /**< The channel map */
     pa_usec_t duration;                   /**< Duration of this entry */
-    uint32_t bytes;                       /**< Length of this sample in bytes. \since 0.4 */
-    int lazy;                             /**< Non-zero when this is a lazy cache entry. \since 0.5 */
-    const char *filename;                 /**< In case this is a lazy cache entry, the filename for the sound file to be loaded on demand. \since 0.5 */
-    pa_proplist *proplist;                /**< Property list for this sample. \since 0.9.10 */
+    uint32_t bytes;                       /**< Length of this sample in bytes. */
+    int lazy;                             /**< Non-zero when this is a lazy cache entry. */
+    const char *filename;                 /**< In case this is a lazy cache entry, the filename for the sound file to be loaded on demand. */
+    pa_proplist *proplist;                /**< Property list for this sample. \since 0.9.11 */
 } pa_sample_info;
 
 /** Callback prototype for pa_context_get_sample_info_by_name() and firends */
@@ -551,7 +551,7 @@ pa_operation* pa_context_get_sample_info_list(pa_context *c, pa_sample_info_cb_t
 
 /** @{ \name Autoload Entries */
 
-/** Type of an autoload entry. \since 0.5 */
+/** Type of an autoload entry. */
 typedef enum pa_autoload_type {
     PA_AUTOLOAD_SINK = 0,
     PA_AUTOLOAD_SOURCE = 1
@@ -559,7 +559,7 @@ typedef enum pa_autoload_type {
 
 /** Stores information about autoload entries. Please note that this structure
  * can be extended as part of evolutionary API updates at any time in
- * any new release. \since 0.5 */
+ * any new release. */
 typedef struct pa_autoload_info {
     uint32_t index;               /**< Index of this autoload entry */
     const char *name;             /**< Name of the sink or source */
@@ -571,22 +571,22 @@ typedef struct pa_autoload_info {
 /** Callback prototype for pa_context_get_autoload_info_by_name() and firends */
 typedef void (*pa_autoload_info_cb_t)(pa_context *c, const pa_autoload_info *i, int eol, void *userdata);
 
-/** Get info about a specific autoload entry. \since 0.6 */
+/** Get info about a specific autoload entry. */
 pa_operation* pa_context_get_autoload_info_by_name(pa_context *c, const char *name, pa_autoload_type_t type, pa_autoload_info_cb_t cb, void *userdata);
 
-/** Get info about a specific autoload entry. \since 0.6 */
+/** Get info about a specific autoload entry. */
 pa_operation* pa_context_get_autoload_info_by_index(pa_context *c, uint32_t idx, pa_autoload_info_cb_t cb, void *userdata);
 
-/** Get the complete list of autoload entries. \since 0.5 */
+/** Get the complete list of autoload entries. */
 pa_operation* pa_context_get_autoload_info_list(pa_context *c, pa_autoload_info_cb_t cb, void *userdata);
 
-/** Add a new autoload entry. \since 0.5 */
+/** Add a new autoload entry. */
 pa_operation* pa_context_add_autoload(pa_context *c, const char *name, pa_autoload_type_t type, const char *module, const char*argument, pa_context_index_cb_t, void* userdata);
 
-/** Remove an autoload entry. \since 0.6 */
+/** Remove an autoload entry. */
 pa_operation* pa_context_remove_autoload_by_name(pa_context *c, const char *name, pa_autoload_type_t type, pa_context_success_cb_t cb, void* userdata);
 
-/** Remove an autoload entry. \since 0.6 */
+/** Remove an autoload entry. */
 pa_operation* pa_context_remove_autoload_by_index(pa_context *c, uint32_t idx, pa_context_success_cb_t cb, void* userdata);
 
 /** @} */
diff --git a/src/pulse/proplist.h b/src/pulse/proplist.h
index 4fea23d..2137916 100644
--- a/src/pulse/proplist.h
+++ b/src/pulse/proplist.h
@@ -102,39 +102,40 @@
 #define PA_PROP_DEVICE_MASTER_DEVICE        "device.master_device"
 
 /** A property list object. Basically a dictionary with UTF-8 strings
- * as keys and arbitrary data as values. \since 0.9.10 */
+ * as keys and arbitrary data as values. \since 0.9.11 */
 typedef struct pa_proplist pa_proplist;
 
-/** Allocate a property list. \since 0.9.10 */
+/** Allocate a property list. \since 0.9.11 */
 pa_proplist* pa_proplist_new(void);
 
-/** Free the property list. \since 0.9.10 */
+/** Free the property list. \since 0.9.11 */
 void pa_proplist_free(pa_proplist* p);
 
 /** Append a new string entry to the property list, possibly
  * overwriting an already existing entry with the same key. An
  * internal copy of the data passed is made. Will accept only valid
- * UTF-8. \since 0.9.10 */
+ * UTF-8. \since 0.9.11 */
 int pa_proplist_sets(pa_proplist *p, const char *key, const char *value);
 
 /** Append a new arbitrary data entry to the property list, possibly
  * overwriting an already existing entry with the same key. An
- * internal copy of the data passed is made. \since 0.9.10 */
+ * internal copy of the data passed is made. \since 0.9.11 */
 int pa_proplist_set(pa_proplist *p, const char *key, const void *data, size_t nbytes);
 
 /* Return a string entry for the specified key. Will return NULL if
  * the data is not valid UTF-8. Will return a NUL-terminated string in
  * an internally allocated buffer. The caller should make a copy of
- * the data before accessing the property list again. \since 0.9.10*/
+ * the data before accessing the property list again. \since 0.9.11 */
 const char *pa_proplist_gets(pa_proplist *p, const char *key);
 
 /** Return the the value for the specified key. Will return a
  * NUL-terminated string for string entries. The pointer returned will
  * point to an internally allocated buffer. The caller should make a
- * copy of the data before the property list is accessed again. \since 0.9.10 */
+ * copy of the data before the property list is accessed again. \since
+ * 0.9.11 */
 int pa_proplist_get(pa_proplist *p, const char *key, const void **data, size_t *nbytes);
 
-/** Update mode enum for pa_proplist_update(). \since 0.9.10 */
+/** Update mode enum for pa_proplist_update(). \since 0.9.11 */
 typedef enum pa_update_mode {
     PA_UPDATE_SET,  /*< Replace the entirey property list with the new one. Don't keep any of the old data around */
     PA_UPDATE_MERGE, /*< Merge new property list into the existing one, not replacing any old entries if they share a common key with the new property list. */
@@ -142,18 +143,18 @@ typedef enum pa_update_mode {
 } pa_update_mode_t;
 
 /** Merge property list "other" into "p", adhering the merge mode as
- * specified in "mode". \since 0.9.10 */
+ * specified in "mode". \since 0.9.11 */
 void pa_proplist_update(pa_proplist *p, pa_update_mode_t mode, pa_proplist *other);
 
 /** Removes a single entry from the property list, identified be the
- * specified key name. \since 0.9.10 */
+ * specified key name. \since 0.9.11 */
 int pa_proplist_unset(pa_proplist *p, const char *key);
 
 /** Similar to pa_proplist_remove() but takes an array of keys to
  * remove. The array should be terminated by a NULL pointer. Return -1
  * on failure, otherwise the number of entries actually removed (which
  * might even be 0, if there where no matching entries to
- * remove). \since 0.9.10 */
+ * remove). \since 0.9.11 */
 int pa_proplist_unset_many(pa_proplist *p, const char * const keys[]);
 
 /** Iterate through the property list. The user should allocate a
@@ -163,19 +164,22 @@ int pa_proplist_unset_many(pa_proplist *p, const char * const keys[]);
  * signifies EOL. The property list should not be modified during
  * iteration through the list. On each invication this function will
  * return the key string for the next entry. The keys in the property
- * list do not have any particular order. \since 0.9.10 */
+ * list do not have any particular order. \since 0.9.11 */
 const char *pa_proplist_iterate(pa_proplist *p, void **state);
 
-/** Format the property list nicely as a human readable string. \since 0.9.10 */
+/** Format the property list nicely as a human readable string. \since
+ * 0.9.11 */
 char *pa_proplist_to_string(pa_proplist *p);
 
-/** Returns 1 if an entry for the specified key is existant in the property list. \since 0.9.10 */
+/** Returns 1 if an entry for the specified key is existant in the
+ * property list. \since 0.9.11 */
 int pa_proplist_contains(pa_proplist *p, const char *key);
 
-/** Remove all entries from the property list object. \since 0.9.10 */
+/** Remove all entries from the property list object. \since 0.9.11 */
 void pa_proplist_clear(pa_proplist *p);
 
-/** Allocate a new property list and copy over every single entry from the specific list. \since 0.9.10 */
+/** Allocate a new property list and copy over every single entry from
+ * the specific list. \since 0.9.11 */
 pa_proplist* pa_proplist_copy(pa_proplist *template);
 
 #endif
diff --git a/src/pulse/scache.h b/src/pulse/scache.h
index a9e0ce8..46d86a1 100644
--- a/src/pulse/scache.h
+++ b/src/pulse/scache.h
@@ -81,7 +81,7 @@ PA_C_DECL_BEGIN
 
 /** Callback prototype for pa_context_play_sample_with_proplist(). The
  * idx value is the index of the sink input object, or
- * PA_INVALID_INDEX on failure. \since 0.9.10*/
+ * PA_INVALID_INDEX on failure. \since 0.9.11 */
 typedef void (*pa_context_play_sample_cb_t)(pa_context *c, uint32_t idx, void *userdata);
 
 /** Make this stream a sample upload stream */
@@ -109,7 +109,7 @@ pa_operation* pa_context_play_sample(
 /** Play a sample from the sample cache to the specified device,
  * allowing specification of a property list for the playback
  * stream. If the latter is NULL use the default sink. Returns an
- * operation object. \since 0.9.10 */
+ * operation object. \since 0.9.11 */
 pa_operation* pa_context_play_sample_with_proplist(
         pa_context *c                   /**< Context */,
         const char *name                /**< Name of the sample to play */,
diff --git a/src/pulse/simple.h b/src/pulse/simple.h
index 0ddd57e..7fca6ac 100644
--- a/src/pulse/simple.h
+++ b/src/pulse/simple.h
@@ -138,10 +138,10 @@ int pa_simple_drain(pa_simple *s, int *error);
 /** Read some data from the server */
 int pa_simple_read(pa_simple *s, void*data, size_t bytes, int *error);
 
-/** Return the playback latency. \since 0.5 */
+/** Return the playback latency. */
 pa_usec_t pa_simple_get_latency(pa_simple *s, int *error);
 
-/** Flush the playback buffer. \since 0.5 */
+/** Flush the playback buffer. */
 int pa_simple_flush(pa_simple *s, int *error);
 
 PA_C_DECL_END
diff --git a/src/pulse/stream.c b/src/pulse/stream.c
index fb96523..3d79487 100644
--- a/src/pulse/stream.c
+++ b/src/pulse/stream.c
@@ -119,7 +119,8 @@ pa_stream *pa_stream_new_with_proplist(pa_context *c, const char *name, const pa
     s->record_memblockq = NULL;
 
     s->previous_time = 0;
-    s->timing_info_valid = 0;
+    memset(&s->timing_info, 0, sizeof(s->timing_info));
+    s->timing_info_valid = FALSE;
     s->read_index_not_before = 0;
     s->write_index_not_before = 0;
 
@@ -462,7 +463,7 @@ static void request_auto_timing_update(pa_stream *s, int force) {
 
         if ((o = pa_stream_update_timing_info(s, NULL, NULL))) {
             pa_operation_unref(o);
-            s->auto_timing_update_requested = 1;
+            s->auto_timing_update_requested = TRUE;
         }
     }
 
@@ -666,6 +667,20 @@ void pa_create_stream_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED
         s->sample_spec = ss;
     }
 
+    if (s->context->version >= 13 && s->direction != PA_STREAM_UPLOAD) {
+        pa_usec_t usec;
+
+        if (pa_tagstruct_get_usec(t, &usec) < 0) {
+            pa_context_fail(s->context, PA_ERR_PROTOCOL);
+            goto finish;
+        }
+
+        if (s->direction == PA_STREAM_RECORD)
+            s->timing_info.configured_source_usec = usec;
+        else
+            s->timing_info.configured_sink_usec = usec;
+    }
+
     if (!pa_tagstruct_eof(t)) {
         pa_context_fail(s->context, PA_ERR_PROTOCOL);
         goto finish;
@@ -1059,7 +1074,7 @@ static void stream_get_timing_info_callback(pa_pdispatch *pd, uint32_t command,
 
 /*     pa_log("pre corrupt w:%u r:%u\n", !o->stream->timing_info_valid || i->write_index_corrupt,!o->stream->timing_info_valid || i->read_index_corrupt); */
 
-    o->stream->timing_info_valid = 0;
+    o->stream->timing_info_valid = FALSE;
     i->write_index_corrupt = 0;
     i->read_index_corrupt = 0;
 
diff --git a/src/pulse/stream.h b/src/pulse/stream.h
index de7c967..69943a7 100644
--- a/src/pulse/stream.h
+++ b/src/pulse/stream.h
@@ -287,7 +287,7 @@ pa_stream* pa_stream_new(
 
 /** Create a new, unconnected stream with the specified name and
  * sample type, and specify the the initial stream property
- * list. \since 0.9.10 */
+ * list. \since 0.9.11 */
 pa_stream* pa_stream_new_with_proplist(
         pa_context *c                     /**< The context to create this stream in */,
         const char *name                  /**< A name for this stream */,
@@ -377,20 +377,20 @@ int pa_stream_write(
  * data will point to the actual data and length will contain the size
  * of the data in bytes (which can be less than a complete framgnet).
  * Use pa_stream_drop() to actually remove the data from the
- * buffer. If no data is available will return a NULL pointer  \since 0.8 */
+ * buffer. If no data is available will return a NULL pointer */
 int pa_stream_peek(
         pa_stream *p                 /**< The stream to use */,
         const void **data            /**< Pointer to pointer that will point to data */,
         size_t *bytes                /**< The length of the data read in bytes */);
 
 /** Remove the current fragment on record streams. It is invalid to do this without first
- * calling pa_stream_peek(). \since 0.8 */
+ * calling pa_stream_peek(). */
 int pa_stream_drop(pa_stream *p);
 
 /** Return the number of bytes that may be written using pa_stream_write() */
 size_t pa_stream_writable_size(pa_stream *p);
 
-/** Return the number of bytes that may be read using pa_stream_read() \since 0.8 */
+/** Return the number of bytes that may be read using pa_stream_read()*/
 size_t pa_stream_readable_size(pa_stream *p);
 
 /** Drain a playback stream. Use this for notification when the buffer is empty */
@@ -410,18 +410,18 @@ void pa_stream_set_state_callback(pa_stream *s, pa_stream_notify_cb_t cb, void *
 void pa_stream_set_write_callback(pa_stream *p, pa_stream_request_cb_t cb, void *userdata);
 
 /** Set the callback function that is called when new data is available from the stream.
- * Return the number of bytes read. \since 0.8 */
+ * Return the number of bytes read.*/
 void pa_stream_set_read_callback(pa_stream *p, pa_stream_request_cb_t cb, void *userdata);
 
-/** Set the callback function that is called when a buffer overflow happens. (Only for playback streams) \since 0.8 */
+/** Set the callback function that is called when a buffer overflow happens. (Only for playback streams) */
 void pa_stream_set_overflow_callback(pa_stream *p, pa_stream_notify_cb_t cb, void *userdata);
 
-/** Set the callback function that is called when a buffer underflow happens. (Only for playback streams) \since 0.8 */
+/** Set the callback function that is called when a buffer underflow happens. (Only for playback streams) */
 void pa_stream_set_underflow_callback(pa_stream *p, pa_stream_notify_cb_t cb, void *userdata);
 
 /** Set the callback function that is called whenever a latency
  * information update happens. Useful on PA_STREAM_AUTO_TIMING_UPDATE
- * streams only. (Only for playback streams) \since 0.8.2 */
+ * streams only. (Only for playback streams) */
 void pa_stream_set_latency_update_callback(pa_stream *p, pa_stream_notify_cb_t cb, void *userdata);
 
 /** Set the callback function that is called whenever the stream is
@@ -441,24 +441,25 @@ void pa_stream_set_moved_callback(pa_stream *p, pa_stream_notify_cb_t cb, void *
  * 0.9.8. \since 0.9.8 */
 void pa_stream_set_suspended_callback(pa_stream *p, pa_stream_notify_cb_t cb, void *userdata);
 
-/** Pause (or resume) playback of this stream temporarily. Available on both playback and recording streams. \since 0.3 */
+/** Pause (or resume) playback of this stream temporarily. Available on both playback and recording streams. */
 pa_operation* pa_stream_cork(pa_stream *s, int b, pa_stream_success_cb_t cb, void *userdata);
 
 /** Flush the playback buffer of this stream. Most of the time you're
- * better off using the parameter delta of pa_stream_write() instead of this
- * function. Available on both playback and recording streams. \since 0.3 */
+ * better off using the parameter delta of pa_stream_write() instead
+ * of this function. Available on both playback and recording
+ * streams. */
 pa_operation* pa_stream_flush(pa_stream *s, pa_stream_success_cb_t cb, void *userdata);
 
 /** Reenable prebuffering as specified in the pa_buffer_attr
- * structure. Available for playback streams only. \since 0.6 */
+ * structure. Available for playback streams only. */
 pa_operation* pa_stream_prebuf(pa_stream *s, pa_stream_success_cb_t cb, void *userdata);
 
 /** Request immediate start of playback on this stream. This disables
- * prebuffering as specified in the pa_buffer_attr
- * structure, temporarily. Available for playback streams only. \since 0.3 */
+ * prebuffering as specified in the pa_buffer_attr structure,
+ * temporarily. Available for playback streams only. */
 pa_operation* pa_stream_trigger(pa_stream *s, pa_stream_success_cb_t cb, void *userdata);
 
-/** Rename the stream. \since 0.5 */
+/** Rename the stream. */
 pa_operation* pa_stream_set_name(pa_stream *s, const char *name, pa_stream_success_cb_t cb, void *userdata);
 
 /** Return the current playback/recording time. This is based on the
@@ -475,13 +476,13 @@ pa_operation* pa_stream_set_name(pa_stream *s, const char *name, pa_stream_succe
  * be disabled by using PA_STREAM_NOT_MONOTONOUS. This may be
  * desirable to deal better with bad estimations of transport
  * latencies, but may have strange effects if the application is not
- * able to deal with time going 'backwards'. \since 0.6 */
+ * able to deal with time going 'backwards'. */
 int pa_stream_get_time(pa_stream *s, pa_usec_t *r_usec);
 
 /** Return the total stream latency. This function is based on
  * pa_stream_get_time(). In case the stream is a monitoring stream the
  * result can be negative, i.e. the captured samples are not yet
- * played. In this case *negative is set to 1. \since 0.6 */
+ * played. In this case *negative is set to 1. */
 int pa_stream_get_latency(pa_stream *s, pa_usec_t *r_usec, int *negative);
 
 /** Return the latest raw timing data structure. The returned pointer
@@ -493,13 +494,13 @@ int pa_stream_get_latency(pa_stream *s, pa_usec_t *r_usec, int *negative);
  * function will fail with PA_ERR_NODATA. Please note that the
  * write_index member field (and only this field) is updated on each
  * pa_stream_write() call, not just when a timing update has been
- * recieved. \since 0.8 */
+ * recieved. */
 const pa_timing_info* pa_stream_get_timing_info(pa_stream *s);
 
-/** Return a pointer to the stream's sample specification. \since 0.6 */
+/** Return a pointer to the stream's sample specification. */
 const pa_sample_spec* pa_stream_get_sample_spec(pa_stream *s);
 
-/** Return a pointer to the stream's channel map. \since 0.8 */
+/** Return a pointer to the stream's channel map. */
 const pa_channel_map* pa_stream_get_channel_map(pa_stream *s);
 
 /** Return the buffer metrics of the stream. Only valid after the
@@ -527,10 +528,11 @@ pa_operation *pa_stream_update_sample_rate(pa_stream *s, uint32_t rate, pa_strea
  * recommended to set as much properties initially via
  * pa_stream_new_with_proplist() as possible instead a posteriori with
  * this function, since that information may then be used to route
- * this stream to the right device. \since 0.9.10 */
+ * this stream to the right device. \since 0.9.11 */
 pa_operation *pa_stream_proplist_update(pa_stream *s, pa_update_mode_t mode, pa_proplist *p, pa_stream_success_cb_t cb, void *userdata);
 
-/* Update the property list of the sink input/source output of this stream, remove entries. \since 0.9.10 */
+/* Update the property list of the sink input/source output of this
+ * stream, remove entries. \since 0.9.11 */
 pa_operation *pa_stream_proplist_remove(pa_stream *s, const char *const keys[], pa_stream_success_cb_t cb, void *userdata);
 
 PA_C_DECL_END
diff --git a/src/pulse/version.h.in b/src/pulse/version.h.in
index 20c7a9c..dc0f8e3 100644
--- a/src/pulse/version.h.in
+++ b/src/pulse/version.h.in
@@ -8,17 +8,17 @@
 
   Copyright 2004-2006 Lennart Poettering
   Copyright 2006 Pierre Ossman <ossman at 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
@@ -39,7 +39,8 @@ a macro and not a function, so it is impossible to get the pointer of
 it. */
 #define pa_get_headers_version() ("@PACKAGE_VERSION@")
 
-/** Return the version of the library the current application is linked to. */
+/** Return the version of the library the current application is
+ * linked to. */
 const char* pa_get_library_version(void);
 
 /** The current API version. Version 6 relates to Polypaudio
@@ -47,8 +48,8 @@ const char* pa_get_library_version(void);
  * PA_API_VERSION undefined.  */
 #define PA_API_VERSION @PA_API_VERSION@
 
-/** The current protocol version. Version 8 relates to Polypaudio 0.8/PulseAudio 0.9.
- * \since 0.8 */
+/** The current protocol version. Version 8 relates to Polypaudio
+ * 0.8/PulseAudio 0.9. */
 #define PA_PROTOCOL_VERSION @PA_PROTOCOL_VERSION@
 
 PA_C_DECL_END
diff --git a/src/pulse/volume.h b/src/pulse/volume.h
index 004e88c..0fbf872 100644
--- a/src/pulse/volume.h
+++ b/src/pulse/volume.h
@@ -151,22 +151,22 @@ 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_GCC_PURE;
 
-/** Convert a decibel value to a volume. This is only valid for software volumes! \since 0.4 */
+/** Convert a decibel value to a volume. This is only valid for software volumes! */
 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 */
+/** Convert a volume to a decibel value. This is only valid for software volumes! */
 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 */
+/** Convert a linear factor to a volume. This is only valid for software volumes! */
 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 */
+/** Convert a volume to a linear factor. This is only valid for software volumes! */
 double pa_sw_volume_to_linear(pa_volume_t v) PA_GCC_CONST;
 
 #ifdef INFINITY
 #define PA_DECIBEL_MININFTY (-INFINITY)
 #else
-/** This value is used as minus infinity when using pa_volume_{to,from}_dB(). \since 0.4 */
+/** This value is used as minus infinity when using pa_volume_{to,from}_dB(). */
 #define PA_DECIBEL_MININFTY (-200)
 #endif
 

commit d69aeebc00d1babd40e2101cd94373f7c8dc4c0d
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Apr 9 01:19:43 2008 +0000

    implement server side of new sink/source reconfiguration commands
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2229 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c
index 59d1612..db52b7f 100644
--- a/src/pulsecore/protocol-native.c
+++ b/src/pulsecore/protocol-native.c
@@ -86,6 +86,7 @@ typedef struct record_stream {
     pa_source_output *source_output;
     pa_memblockq *memblockq;
     size_t fragment_size;
+    pa_usec_t source_latency;
 } record_stream;
 
 typedef struct output_stream {
@@ -107,6 +108,7 @@ typedef struct playback_stream {
 
     pa_atomic_t missing;
     size_t minreq;
+    pa_usec_t sink_latency;
 
     /* Only updated after SINK_INPUT_MESSAGE_UPDATE_LATENCY */
     int64_t read_index, write_index;
@@ -524,7 +526,7 @@ static record_stream* record_stream_new(
         *fragsize = pa_usec_to_bytes(DEFAULT_FRAGSIZE_MSEC*1000, &source_output->sample_spec);
 
     if (adjust_latency) {
-        pa_usec_t fragsize_usec, source_latency;
+        pa_usec_t fragsize_usec;
 
         /* So, the user asked us to adjust the latency according to
          * the what the source can provide. Half the latency will be
@@ -533,12 +535,12 @@ static record_stream* record_stream_new(
 
         fragsize_usec = pa_bytes_to_usec(*fragsize, &source_output->sample_spec);
 
-        source_latency = pa_source_output_set_requested_latency(source_output, fragsize_usec/2);
+        s->source_latency = pa_source_output_set_requested_latency(source_output, fragsize_usec/2);
 
-        if (fragsize_usec >= source_latency*2)
-            fragsize_usec -= source_latency;
+        if (fragsize_usec >= s->source_latency*2)
+            fragsize_usec -= s->source_latency;
         else
-            fragsize_usec = source_latency;
+            fragsize_usec = s->source_latency;
 
         *fragsize = pa_usec_to_bytes(fragsize_usec, &source_output->sample_spec);
     }
@@ -780,7 +782,7 @@ static playback_stream* playback_stream_new(
         *prebuf = *tlength;
 
     if (adjust_latency) {
-        pa_usec_t tlength_usec, minreq_usec, sink_latency;
+        pa_usec_t tlength_usec, minreq_usec;
 
         /* So, the user asked us to adjust the latency according to
          * the what the sink can provide. Half the latency will be
@@ -790,17 +792,17 @@ static playback_stream* playback_stream_new(
         tlength_usec = pa_bytes_to_usec(*tlength, &sink_input->sample_spec);
         minreq_usec = pa_bytes_to_usec(*minreq, &sink_input->sample_spec);
 
-        sink_latency = pa_sink_input_set_requested_latency(sink_input, tlength_usec/2);
+        s->sink_latency = pa_sink_input_set_requested_latency(sink_input, tlength_usec/2);
 
-        if (tlength_usec >= sink_latency*2)
-            tlength_usec -= sink_latency;
+        if (tlength_usec >= s->sink_latency*2)
+            tlength_usec -= s->sink_latency;
         else
-            tlength_usec = sink_latency;
+            tlength_usec = s->sink_latency;
 
-        if (minreq_usec >= sink_latency*2)
-            minreq_usec -= sink_latency;
+        if (minreq_usec >= s->sink_latency*2)
+            minreq_usec -= s->sink_latency;
         else
-            minreq_usec = sink_latency;
+            minreq_usec = s->sink_latency;
 
         *tlength = pa_usec_to_bytes(tlength_usec, &sink_input->sample_spec);
         *minreq = pa_usec_to_bytes(minreq_usec, &sink_input->sample_spec);
@@ -1450,6 +1452,9 @@ static void command_create_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GC
         pa_tagstruct_put_boolean(reply, pa_sink_get_state(s->sink_input->sink) == PA_SINK_SUSPENDED);
     }
 
+    if (c->version >= 13)
+        pa_tagstruct_put_usec(reply, s->sink_latency);
+
     pa_pstream_send_tagstruct(c->pstream, reply);
 }
 
@@ -1651,6 +1656,9 @@ static void command_create_record_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_
         pa_tagstruct_put_boolean(reply, pa_source_get_state(s->source_output->source) == PA_SOURCE_SUSPENDED);
     }
 
+    if (c->version >= 13)
+        pa_tagstruct_put_usec(reply, s->source_latency);
+
     pa_pstream_send_tagstruct(c->pstream, reply);
 }
 
@@ -2258,8 +2266,10 @@ static void sink_input_fill_tagstruct(connection *c, pa_tagstruct *t, pa_sink_in
     pa_tagstruct_puts(t, s->driver);
     if (c->version >= 11)
         pa_tagstruct_put_boolean(t, pa_sink_input_get_mute(s));
-    if (c->version >= 13)
+    if (c->version >= 13) {
         pa_tagstruct_put_proplist(t, s->proplist);
+        pa_tagstruct_put_usec(t, pa_sink_get_requested_latency(s->sink));
+    }
 }
 
 static void source_output_fill_tagstruct(connection *c, pa_tagstruct *t, pa_source_output *s) {
@@ -2282,8 +2292,10 @@ static void source_output_fill_tagstruct(connection *c, pa_tagstruct *t, pa_sour
     pa_tagstruct_puts(t, pa_resample_method_to_string(pa_source_output_get_resample_method(s)));
     pa_tagstruct_puts(t, s->driver);
 
-    if (c->version >= 13)
+    if (c->version >= 13) {
         pa_tagstruct_put_proplist(t, s->proplist);
+        pa_tagstruct_put_usec(t, pa_source_get_requested_latency(s->source));
+    }
 }
 
 static void scache_fill_tagstruct(connection *c, pa_tagstruct *t, pa_scache_entry *e) {

commit 39afb140935ffb9eb47142ddb125bc6488e06fd2
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Apr 9 13:49:04 2008 +0000

    add new pa_proplist_setf() API function
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2230 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulse/proplist.c b/src/pulse/proplist.c
index 31fd10d..33bd274 100644
--- a/src/pulse/proplist.c
+++ b/src/pulse/proplist.c
@@ -102,6 +102,28 @@ int pa_proplist_sets(pa_proplist *p, const char *key, const char *value) {
     return 0;
 }
 
+/** Will accept only valid UTF-8 */
+int pa_proplist_setf(pa_proplist *p, const char *key, const char *format, ...) {
+    va_list ap;
+    int r;
+    char *t;
+
+    pa_assert(p);
+    pa_assert(key);
+
+    if (!property_name_valid(key) || !pa_utf8_valid(format))
+        return -1;
+
+    va_start(ap, format);
+    t = pa_vsprintf_malloc(format, ap);
+    va_end(ap);
+
+    r = pa_proplist_sets(p, key, t);
+
+    pa_xfree(t);
+    return r;
+}
+
 int pa_proplist_set(pa_proplist *p, const char *key, const void *data, size_t nbytes) {
     struct property *prop;
     pa_bool_t add = FALSE;
diff --git a/src/pulse/proplist.h b/src/pulse/proplist.h
index 2137916..7c3423f 100644
--- a/src/pulse/proplist.h
+++ b/src/pulse/proplist.h
@@ -100,6 +100,8 @@
 #define PA_PROP_DEVICE_CONNECTOR            "device.connector"
 #define PA_PROP_DEVICE_ACCESS_MODE          "device.access_mode"
 #define PA_PROP_DEVICE_MASTER_DEVICE        "device.master_device"
+#define PA_PROP_DEVICE_BUFFER_NFRAGMENTS    "device.buffer.nfragments"
+#define PA_PROP_DEVICE_BUFFER_FRAGMENT_SIZE "device.buffer.fragment_size"
 
 /** A property list object. Basically a dictionary with UTF-8 strings
  * as keys and arbitrary data as values. \since 0.9.11 */
@@ -117,6 +119,13 @@ void pa_proplist_free(pa_proplist* p);
  * UTF-8. \since 0.9.11 */
 int pa_proplist_sets(pa_proplist *p, const char *key, const char *value);
 
+/** Append a new string entry to the property list, possibly
+ * overwriting an already existing entry with the same key. An
+ * internal copy of the data passed is made. Will accept only valid
+ * UTF-8. The data can be passed as printf()-style format string with
+ * arguments. \since 0.9.11 */
+int pa_proplist_setf(pa_proplist *p, const char *key, const char *format, ...) PA_GCC_PRINTF_ATTR(3,4);
+
 /** Append a new arbitrary data entry to the property list, possibly
  * overwriting an already existing entry with the same key. An
  * internal copy of the data passed is made. \since 0.9.11 */

commit 5d7128abf992c1b7fb84f0f9e7eea10d7f70aa01
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Apr 9 13:49:37 2008 +0000

    add new describe-module CLI command
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2231 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/cli-command.c b/src/pulsecore/cli-command.c
index ca4be59..ced56c2 100644
--- a/src/pulsecore/cli-command.c
+++ b/src/pulsecore/cli-command.c
@@ -90,6 +90,7 @@ static int pa_cli_command_stat(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_b
 static int pa_cli_command_info(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
 static int pa_cli_command_load(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
 static int pa_cli_command_unload(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
+static int pa_cli_command_describe(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
 static int pa_cli_command_sink_volume(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
 static int pa_cli_command_sink_input_volume(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
 static int pa_cli_command_source_volume(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
@@ -136,6 +137,7 @@ static const struct command commands[] = {
     { "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},
+    { "describe-module",         pa_cli_command_describe,           "Describe a module (arg: name)", 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},
@@ -419,6 +421,45 @@ static int pa_cli_command_unload(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa
     return 0;
 }
 
+static int pa_cli_command_describe(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
+    const char *name;
+    pa_modinfo *i;
+
+    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.\n");
+        return -1;
+    }
+
+    if ((i = pa_modinfo_get_by_name(name))) {
+
+        pa_strbuf_printf(buf, "Name: %s\n", name);
+
+        if (!i->description && !i->version && !i->author && !i->usage)
+            pa_strbuf_printf(buf, "No module information available\n");
+        else {
+            if (i->version)
+                pa_strbuf_printf(buf, "Version: %s\n", i->version);
+            if (i->description)
+                pa_strbuf_printf(buf, "Description: %s\n", i->description);
+            if (i->author)
+                pa_strbuf_printf(buf, "Author: %s\n", i->author);
+            if (i->usage)
+                pa_strbuf_printf(buf, "Usage: %s\n", i->usage);
+            pa_strbuf_printf(buf, "Load Once: %s\n", pa_yes_no(i->load_once));
+        }
+
+        pa_modinfo_free(i);
+    } else
+        pa_strbuf_puts(buf, "Failed to open module.\n");
+
+    return 0;
+}
+
 static int pa_cli_command_sink_volume(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
     const char *n, *v;
     pa_sink *sink;

commit bb9792a616c5e2cae9526974054325854a75b0f2
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Apr 11 16:19:35 2008 +0000

    move gccmacro from pulsecore/ to pulse/
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2232 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulse/gccmacro.h b/src/pulse/gccmacro.h
new file mode 100644
index 0000000..5a2a250
--- /dev/null
+++ b/src/pulse/gccmacro.h
@@ -0,0 +1,89 @@
+#ifndef foopulsegccmacrohfoo
+#define foopulsegccmacrohfoo
+
+/* $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 __GNUC__
+#define PA_GCC_PRINTF_ATTR(a,b) __attribute__ ((format (printf, a, b)))
+#else
+/** If we're in GNU C, use some magic for detecting invalid format strings */
+#define PA_GCC_PRINTF_ATTR(a,b)
+#endif
+
+#if defined(__GNUC__) && (__GNUC__ >= 4)
+#define PA_GCC_SENTINEL __attribute__ ((sentinel))
+#else
+/** Macro for usage of GCC's sentinel compilation warnings */
+#define PA_GCC_SENTINEL
+#endif
+
+#ifdef __GNUC__
+#define PA_GCC_NORETURN __attribute__((noreturn))
+#else
+/** Macro for no-return functions */
+#define PA_GCC_NORETURN
+#endif
+
+#ifdef __GNUC__
+#define PA_GCC_UNUSED __attribute__ ((unused))
+#else
+/** Macro for not used parameter */
+#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 __GNUC__
+#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 __GNUC__
+#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
+
+#ifndef PA_GCC_DEPRECATED
+#ifdef __GNUC__
+#define PA_GCC_DEPRECATED __attribute__ ((deprecated))
+#else
+/** This function is deprecated **/
+#define PA_GCC_DEPRECATED
+#endif
+#endif
+
+#endif
diff --git a/src/pulsecore/gccmacro.h b/src/pulsecore/gccmacro.h
deleted file mode 100644
index f94a8c4..0000000
--- a/src/pulsecore/gccmacro.h
+++ /dev/null
@@ -1,90 +0,0 @@
-#ifndef foopulsegccmacrohfoo
-#define foopulsegccmacrohfoo
-
-/* $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 __GNUC__
-#define PA_GCC_PRINTF_ATTR(a,b) __attribute__ ((format (printf, a, b)))
-#else
-/** If we're in GNU C, use some magic for detecting invalid format strings */
-#define PA_GCC_PRINTF_ATTR(a,b)
-#endif
-
-#if defined(__GNUC__) && (__GNUC__ >= 4)
-#define PA_GCC_SENTINEL __attribute__ ((sentinel))
-#else
-/** Macro for usage of GCC's sentinel compilation warnings */
-#define PA_GCC_SENTINEL
-#endif
-
-#ifdef __GNUC__
-#define PA_GCC_NORETURN __attribute__((noreturn))
-#else
-/** Macro for no-return functions */
-#define PA_GCC_NORETURN
-#endif
-
-#ifdef __GNUC__
-#define PA_GCC_UNUSED __attribute__ ((unused))
-#else
-/** Macro for not used parameter */
-#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 __GNUC__
-#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 __GNUC__
-#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
-
-#ifndef PA_LIKELY
-#ifdef __GNUC__
-#define PA_LIKELY(x) (__builtin_expect(!!(x),1))
-#define PA_UNLIKELY(x) (__builtin_expect((x),0))
-#else
-#define PA_LIKELY(x) (x)
-#define PA_UNLIKELY(x) (x)
-#endif
-#endif
-
-#endif

commit e1c1a782b65e5e207b72e88f3ae04720a743c7e8
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Apr 11 16:20:33 2008 +0000

    fix proplist serialization
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2233 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/tagstruct.c b/src/pulsecore/tagstruct.c
index 92bace2..fb412a4 100644
--- a/src/pulsecore/tagstruct.c
+++ b/src/pulsecore/tagstruct.c
@@ -570,10 +570,11 @@ int pa_tagstruct_get_proplist(pa_tagstruct *t, pa_proplist *p) {
         return -1;
 
     saved_rindex = t->rindex;
+    t->rindex++;
 
     for (;;) {
         const char *k;
-        void *d;
+        const void *d;
         uint32_t length;
 
         if (pa_tagstruct_gets(t, &k) < 0)
@@ -588,17 +589,11 @@ int pa_tagstruct_get_proplist(pa_tagstruct *t, pa_proplist *p) {
         if (length > MAX_TAG_SIZE)
             goto fail;
 
-        d = pa_xmalloc(length);
-
-        if (pa_tagstruct_get_arbitrary(t, d, length) < 0)
+        if (pa_tagstruct_get_arbitrary(t, &d, length) < 0)
             goto fail;
 
-        if (pa_proplist_set(p, k, d, length) < 0) {
-            pa_xfree(d);
+        if (pa_proplist_set(p, k, d, length) < 0)
             goto fail;
-        }
-
-        pa_xfree(d);
     }
 
     return 0;
diff --git a/src/pulsecore/tagstruct.h b/src/pulsecore/tagstruct.h
index 8846b30..8699e6c 100644
--- a/src/pulsecore/tagstruct.h
+++ b/src/pulsecore/tagstruct.h
@@ -33,6 +33,9 @@
 #include <pulse/channelmap.h>
 #include <pulse/volume.h>
 #include <pulse/proplist.h>
+#include <pulse/gccmacro.h>
+
+#include <pulsecore/macro.h>
 
 typedef struct pa_tagstruct pa_tagstruct;
 

commit 6cddf6135cfa86f15a2b43f6e7ae7d16f8711241
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Apr 11 16:21:13 2008 +0000

    add new API pa_rtclock_from_wallclock()
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2234 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/rtclock.c b/src/pulsecore/rtclock.c
index 07d776e..e74e524 100644
--- a/src/pulsecore/rtclock.c
+++ b/src/pulsecore/rtclock.c
@@ -96,3 +96,24 @@ pa_usec_t pa_rtclock_usec(void) {
 
     return pa_timeval_load(pa_rtclock_get(&tv));
 }
+
+struct timeval* pa_rtclock_from_wallclock(struct timeval *tv) {
+
+#ifdef HAVE_CLOCK_GETTIME
+    struct timeval wc_now, rt_now;
+
+    pa_gettimeofday(&wc_now);
+    pa_rtclock_get(&rt_now);
+
+    pa_assert(tv);
+
+    if (pa_timeval_cmp(&wc_now, tv) < 0)
+        pa_timeval_add(&rt_now, pa_timeval_diff(tv, &wc_now));
+    else
+        pa_timeval_sub(&rt_now, pa_timeval_diff(&wc_now, tv));
+
+    *tv = rt_now;
+#endif
+
+    return tv;
+}
diff --git a/src/pulsecore/rtclock.h b/src/pulsecore/rtclock.h
index f0360af..f68ad76 100644
--- a/src/pulsecore/rtclock.h
+++ b/src/pulsecore/rtclock.h
@@ -40,4 +40,6 @@ pa_bool_t pa_rtclock_hrtimer(void);
 /* timer with a resolution better than this are considered high-resolution */
 #define PA_HRTIMER_THRESHOLD_USEC 10
 
+struct timeval* pa_rtclock_from_wallclock(struct timeval *tv);
+
 #endif

commit c61c3b614134a76e167136415d6de52752180886
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Apr 11 16:22:02 2008 +0000

    increase version of required ALSA to 1.0.16. check for gdbm
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2235 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/configure.ac b/configure.ac
index 76ce327..ca7565d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -377,6 +377,9 @@ AC_SEARCH_LIBS([connect], [socket])
 # build, disabling its ability to make dlls.
 AC_CHECK_FUNCS([getopt_long], [], [AC_CHECK_LIB([iberty], [getopt_long])])
 
+AC_CHECK_LIB(gdbm, gdbm_open)
+AC_CHECK_HEADERS(gdbm.h)
+
 #### Check for functions ####
 
 # ISO
@@ -592,7 +595,7 @@ AC_ARG_ENABLE([alsa],
         [alsa=auto])
 
 if test "x${alsa}" != xno ; then
-    PKG_CHECK_MODULES(ASOUNDLIB, [ alsa >= 1.0.0 ],
+    PKG_CHECK_MODULES(ASOUNDLIB, [ alsa >= 1.0.16 ],
         [
             HAVE_ALSA=1
             AC_DEFINE([HAVE_ALSA], 1, [Have ALSA?])

commit e084e4b5de6d763b8827095231a860926e12b120
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Apr 11 16:22:37 2008 +0000

    add new module module-device-restore
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2236 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/Makefile.am b/src/Makefile.am
index e537e97..7139d14 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -999,6 +999,7 @@ modlibexec_LTLIBRARIES += \
 		module-null-sink.la \
 		module-detect.la \
 		module-volume-restore.la \
+		module-device-restore.la \
 		module-default-device-restore.la \
 		module-rescue-streams.la \
 		module-suspend-on-idle.la \
@@ -1169,6 +1170,7 @@ SYMDEF_FILES = \
 		modules/module-jack-sink-symdef.h \
 		modules/module-jack-source-symdef.h \
 		modules/module-volume-restore-symdef.h \
+		modules/module-device-restore-symdef.h \
 		modules/module-default-device-restore-symdef.h \
 		modules/module-rescue-streams-symdef.h \
 		modules/module-suspend-on-idle-symdef.h \
@@ -1409,6 +1411,12 @@ module_volume_restore_la_LDFLAGS = -module -avoid-version
 module_volume_restore_la_LIBADD = $(AM_LIBADD) libpulsecore.la
 module_volume_restore_la_CFLAGS = $(AM_CFLAGS)
 
+# Device volume restore module
+module_device_restore_la_SOURCES = modules/module-device-restore.c
+module_device_restore_la_LDFLAGS = -module -avoid-version
+module_device_restore_la_LIBADD = $(AM_LIBADD) libpulsecore.la -lgdbm
+module_device_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
diff --git a/src/modules/module-device-restore.c b/src/modules/module-device-restore.c
new file mode 100644
index 0000000..27c69f3
--- /dev/null
+++ b/src/modules/module-device-restore.c
@@ -0,0 +1,348 @@
+/* $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 <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <gdbm.h>
+
+#include <pulse/xmalloc.h>
+#include <pulse/volume.h>
+#include <pulse/timeval.h>
+#include <pulse/util.h>
+
+#include <pulsecore/core-error.h>
+#include <pulsecore/module.h>
+#include <pulsecore/core-util.h>
+#include <pulsecore/modargs.h>
+#include <pulsecore/log.h>
+#include <pulsecore/core-subscribe.h>
+#include <pulsecore/sink-input.h>
+#include <pulsecore/source-output.h>
+#include <pulsecore/namereg.h>
+
+#include "module-device-restore-symdef.h"
+
+PA_MODULE_AUTHOR("Lennart Poettering");
+PA_MODULE_DESCRIPTION("Automatically restore the volume/mute state of devices");
+PA_MODULE_VERSION(PACKAGE_VERSION);
+PA_MODULE_LOAD_ONCE(TRUE);
+
+#define SAVE_INTERVAL 10
+
+static const char* const valid_modargs[] = {
+    NULL,
+};
+
+struct userdata {
+    pa_core *core;
+    pa_subscription *subscription;
+    pa_hook_slot *sink_fixate_hook_slot, *source_fixate_hook_slot;
+    pa_time_event *save_time_event;
+    GDBM_FILE gdbm_file;
+};
+
+struct entry {
+    pa_cvolume volume;
+    int muted;
+};
+
+static void save_time_callback(pa_mainloop_api*a, pa_time_event* e, const struct timeval *tv, void *userdata) {
+    struct userdata *u = userdata;
+
+    pa_assert(a);
+    pa_assert(e);
+    pa_assert(tv);
+    pa_assert(u);
+
+    pa_assert(e == u->save_time_event);
+    u->core->mainloop->time_free(u->save_time_event);
+    u->save_time_event = NULL;
+
+    gdbm_sync(u->gdbm_file);
+    pa_log_info("Synced.");
+}
+
+static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint32_t idx, void *userdata) {
+    struct userdata *u = userdata;
+    struct entry entry;
+    char *name;
+    datum key, data;
+
+    pa_assert(c);
+    pa_assert(u);
+
+    if (t != (PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_NEW) &&
+        t != (PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE) &&
+        t != (PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_NEW) &&
+        t != (PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE))
+        return;
+
+    if ((t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_SINK) {
+        pa_sink *sink;
+
+        if (!(sink = pa_idxset_get_by_index(c->sinks, idx)))
+            return;
+
+        name = pa_sprintf_malloc("sink:%s", sink->name);
+        entry.volume = *pa_sink_get_volume(sink);
+        entry.muted = pa_sink_get_mute(sink);
+
+    } else {
+        pa_source *source;
+
+        pa_assert((t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_SOURCE);
+
+        if (!(source = pa_idxset_get_by_index(c->sources, idx)))
+            return;
+
+        name = pa_sprintf_malloc("source:%s", source->name);
+        entry.volume = *pa_source_get_volume(source);
+        entry.muted = pa_source_get_mute(source);
+    }
+
+    key.dptr = name;
+    key.dsize = strlen(name);
+
+    data = gdbm_fetch(u->gdbm_file, key);
+
+    if (data.dptr) {
+
+        if (data.dsize == sizeof(struct entry)) {
+            struct entry *old = (struct entry*) data.dptr;
+
+            if (pa_cvolume_valid(&old->volume)) {
+
+                if (pa_cvolume_equal(&old->volume, &entry.volume) &&
+                    !old->muted == !entry.muted) {
+
+                    pa_xfree(data.dptr);
+                    pa_xfree(name);
+                    return;
+                }
+            } else
+                pa_log_warn("Invalid volume stored in database for device %s", name);
+
+        } else
+            pa_log_warn("Database contains entry for device %s of wrong size %lu != %lu", name, (unsigned long) data.dsize, (unsigned long) sizeof(struct entry));
+
+        pa_xfree(data.dptr);
+    }
+
+    data.dptr = (void*) &entry;
+    data.dsize = sizeof(entry);
+
+    pa_log_info("Storing volume/mute for device %s.", name);
+
+    gdbm_store(u->gdbm_file, key, data, GDBM_REPLACE);
+
+    if (!u->save_time_event) {
+        struct timeval tv;
+        pa_gettimeofday(&tv);
+        tv.tv_sec += SAVE_INTERVAL;
+        u->save_time_event = u->core->mainloop->time_new(u->core->mainloop, &tv, save_time_callback, u);
+    }
+
+    pa_xfree(name);
+}
+
+static struct entry* read_entry(struct userdata *u, char *name) {
+    datum key, data;
+    struct entry *e;
+
+    pa_assert(u);
+    pa_assert(name);
+
+    key.dptr = name;
+    key.dsize = strlen(name);
+
+    data = gdbm_fetch(u->gdbm_file, key);
+
+    if (!data.dptr)
+        goto fail;
+
+    if (data.dsize != sizeof(struct entry)) {
+        pa_log_warn("Database contains entry for device %s of wrong size %lu != %lu", name, (unsigned long) data.dsize, (unsigned long) sizeof(struct entry));
+        goto fail;
+    }
+
+    e = (struct entry*) data.dptr;
+
+    if (!(pa_cvolume_valid(&e->volume))) {
+        pa_log_warn("Invalid volume stored in database for device %s", name);
+        goto fail;
+    }
+
+    return e;
+
+fail:
+
+    pa_xfree(data.dptr);
+    return NULL;
+}
+
+
+static pa_hook_result_t sink_fixate_hook_callback(pa_core *c, pa_sink_new_data *new_data, struct userdata *u) {
+    char *name;
+    struct entry *e;
+
+    pa_assert(new_data);
+
+    name = pa_sprintf_malloc("sink:%s", new_data->name);
+
+    if ((e = read_entry(u, name))) {
+
+        if (e->volume.channels == new_data->sample_spec.channels) {
+            pa_log_info("Restoring volume for sink %s.", new_data->name);
+            pa_sink_new_data_set_volume(new_data, &e->volume);
+        }
+
+        pa_log_info("Restoring mute state for sink %s.", new_data->name);
+        pa_sink_new_data_set_muted(new_data, e->muted);
+        pa_xfree(e);
+    }
+
+    pa_xfree(name);
+
+    return PA_HOOK_OK;
+}
+
+static pa_hook_result_t source_fixate_hook_callback(pa_core *c, pa_source_new_data *new_data, struct userdata *u) {
+    char *name;
+    struct entry *e;
+
+    pa_assert(new_data);
+
+    name = pa_sprintf_malloc("source:%s", new_data->name);
+
+    if ((e = read_entry(u, name))) {
+
+        if (e->volume.channels == new_data->sample_spec.channels) {
+            pa_log_info("Restoring volume for source %s.", new_data->name);
+            pa_source_new_data_set_volume(new_data, &e->volume);
+        }
+
+        pa_log_info("Restoring mute state for source %s.", new_data->name);
+        pa_source_new_data_set_muted(new_data, e->muted);
+        pa_xfree(e);
+    }
+
+    pa_xfree(name);
+
+    return PA_HOOK_OK;
+}
+
+int pa__init(pa_module*m) {
+    pa_modargs *ma = NULL;
+    struct userdata *u;
+    char *fname, *state_dir;
+    char hn[256];
+    pa_sink *sink;
+    pa_source *source;
+    uint32_t idx;
+
+    pa_assert(m);
+
+    if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
+        pa_log("Failed to parse module arguments");
+        goto fail;
+    }
+
+    u = pa_xnew(struct userdata, 1);
+    u->core = m->core;
+    u->save_time_event = NULL;
+
+    u->subscription = pa_subscription_new(m->core, PA_SUBSCRIPTION_MASK_SINK|PA_SUBSCRIPTION_MASK_SOURCE, subscribe_callback, u);
+
+    u->sink_fixate_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_FIXATE], (pa_hook_cb_t) sink_fixate_hook_callback, u);
+    u->source_fixate_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_FIXATE], (pa_hook_cb_t) source_fixate_hook_callback, u);
+
+    m->userdata = u;
+
+    if (!pa_get_host_name(hn, sizeof(hn)))
+        goto fail;
+
+    if (!(state_dir = pa_get_state_dir()))
+        goto fail;
+
+    fname = pa_sprintf_malloc("%s/device-volumes.%s.gdbm", state_dir, hn);
+    pa_xfree(state_dir);
+
+    if (!(u->gdbm_file = gdbm_open(fname, 0, GDBM_WRCREAT, 0600, NULL))) {
+        pa_log("Failed to open volume database '%s': %s", fname, gdbm_strerror(gdbm_errno));
+        pa_xfree(fname);
+        goto fail;
+    }
+
+    pa_log_info("Sucessfully opened database file '%s'.", fname);
+    pa_xfree(fname);
+
+    for (sink = pa_idxset_first(m->core->sinks, &idx); sink; sink = pa_idxset_next(m->core->sinks, &idx))
+        subscribe_callback(m->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_NEW, sink->index, u);
+
+    for (source = pa_idxset_first(m->core->sources, &idx); source; source = pa_idxset_next(m->core->sources, &idx))
+        subscribe_callback(m->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_NEW, source->index, u);
+
+    pa_modargs_free(ma);
+    return 0;
+
+fail:
+    pa__done(m);
+    if (ma)
+        pa_modargs_free(ma);
+
+    return  -1;
+}
+
+void pa__done(pa_module*m) {
+    struct userdata* u;
+
+    pa_assert(m);
+
+    if (!(u = m->userdata))
+        return;
+
+    if (u->subscription)
+        pa_subscription_free(u->subscription);
+
+    if (u->sink_fixate_hook_slot)
+        pa_hook_slot_free(u->sink_fixate_hook_slot);
+    if (u->source_fixate_hook_slot)
+        pa_hook_slot_free(u->source_fixate_hook_slot);
+
+    if (u->save_time_event)
+        u->core->mainloop->time_free(u->save_time_event);
+
+    if (u->gdbm_file)
+        gdbm_close(u->gdbm_file);
+
+    pa_xfree(u);
+}

commit d491adff74640040b2ae3fba0bd864e1178ba461
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Apr 11 16:23:06 2008 +0000

    add gccmacro.h to doxygen docs
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2237 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/doxygen/doxygen.conf.in b/doxygen/doxygen.conf.in
index a45dc2d..7ad5d2f 100644
--- a/doxygen/doxygen.conf.in
+++ b/doxygen/doxygen.conf.in
@@ -417,7 +417,7 @@ WARN_LOGFILE           =
 # directories like "/usr/src/myproject". Separate the files or directories 
 # with spaces.
 
-INPUT                  = ../src/pulse/context.h ../src/pulse/stream.h ../src/pulse/pulseaudio.h ../src/pulse/sample.h ../src/pulse/def.h ../src/pulse/subscribe.h ../src/pulse/introspect.h ../src/pulse/scache.h ../src/pulse/mainloop-api.h ../src/pulse/glib-mainloop.h ../src/pulse/mainloop.h ../src/pulse/mainloop-signal.h ../src/pulse/error.h ../src/pulse/operation.h ../src/pulse/simple.h ../src/pulse/version.h ../src/pulse/volume.h ../src/pulse/channelmap.h ../src/pulse/thread-mainloop.h ../src/pulse/xmalloc.h ../src/pulse/utf8.h ../src/pulse/util.h ../src/pulse/timeval.h ../src/pulse/proplist.h
+INPUT                  = ../src/pulse/context.h ../src/pulse/stream.h ../src/pulse/pulseaudio.h ../src/pulse/sample.h ../src/pulse/def.h ../src/pulse/subscribe.h ../src/pulse/introspect.h ../src/pulse/scache.h ../src/pulse/mainloop-api.h ../src/pulse/glib-mainloop.h ../src/pulse/mainloop.h ../src/pulse/mainloop-signal.h ../src/pulse/error.h ../src/pulse/operation.h ../src/pulse/simple.h ../src/pulse/version.h ../src/pulse/volume.h ../src/pulse/channelmap.h ../src/pulse/thread-mainloop.h ../src/pulse/xmalloc.h ../src/pulse/utf8.h ../src/pulse/util.h ../src/pulse/timeval.h ../src/pulse/proplist.h ../src/pulse/gccmacro.h
 
 # If the value of the INPUT tag contains directories, you can use the 
 # FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp 

commit 007f82d351a1c40bbfce19c5299ea2d541d0b117
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Apr 11 16:27:31 2008 +0000

    fix bad memory access when initializing client proplist
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2238 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulse/context.c b/src/pulse/context.c
index b9d9308..abc6a85 100644
--- a/src/pulse/context.c
+++ b/src/pulse/context.c
@@ -1205,8 +1205,10 @@ void pa_init_proplist(pa_proplist *p) {
         }
     }
 
-    if (!(a = pa_proplist_contains(p, PA_PROP_APPLICATION_PROCESS_BINARY)) ||
-        !(b = pa_proplist_contains(p, PA_PROP_APPLICATION_NAME))) {
+    a = pa_proplist_contains(p, PA_PROP_APPLICATION_PROCESS_BINARY);
+    b = pa_proplist_contains(p, PA_PROP_APPLICATION_NAME);
+
+    if (!a || !b) {
         char t[PATH_MAX];
         if (pa_get_binary_name(t, sizeof(t))) {
             char *c = pa_utf8_filter(t);

commit 566322ad30648317f9fbf2e5bd43f5862e68bc60
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Apr 11 16:28:17 2008 +0000

    remove gcc macros from cdecl.h because we have them in gccmacro.h now
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2239 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulse/cdecl.h b/src/pulse/cdecl.h
index e1f23d2..922ad27 100644
--- a/src/pulse/cdecl.h
+++ b/src/pulse/cdecl.h
@@ -41,22 +41,4 @@
 
 #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

commit 919bd98dff2f4cd357fe89f9e4fbc202ee5dc409
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Apr 11 16:28:49 2008 +0000

    add new API function pa_timeval_add()
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2240 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulse/timeval.c b/src/pulse/timeval.c
index 70ceb71..180e015 100644
--- a/src/pulse/timeval.c
+++ b/src/pulse/timeval.c
@@ -148,6 +148,24 @@ struct timeval* pa_timeval_add(struct timeval *tv, pa_usec_t v) {
     return tv;
 }
 
+struct timeval* pa_timeval_sub(struct timeval *tv, pa_usec_t v) {
+    unsigned long secs;
+    pa_assert(tv);
+
+    secs = (unsigned long) (v/PA_USEC_PER_SEC);
+    tv->tv_sec -= secs;
+    v -= ((pa_usec_t) secs) * PA_USEC_PER_SEC;
+
+    if (tv->tv_usec >= (suseconds_t) v)
+        tv->tv_usec -= (suseconds_t) v;
+    else {
+        tv->tv_sec --;
+        tv->tv_usec = tv->tv_usec + PA_USEC_PER_SEC - v;
+    }
+
+    return tv;
+}
+
 struct timeval* pa_timeval_store(struct timeval *tv, pa_usec_t v) {
     pa_assert(tv);
 
diff --git a/src/pulse/timeval.h b/src/pulse/timeval.h
index 65a0e51..315f419 100644
--- a/src/pulse/timeval.h
+++ b/src/pulse/timeval.h
@@ -26,6 +26,7 @@
 ***/
 
 #include <pulse/cdecl.h>
+#include <pulse/gccmacro.h>
 #include <pulse/sample.h>
 
 /** \file
@@ -54,7 +55,10 @@ int pa_timeval_cmp(const struct timeval *a, const struct timeval *b) PA_GCC_PURE
 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) PA_GCC_PURE;
+struct timeval* pa_timeval_add(struct timeval *tv, pa_usec_t v);
+
+/** Subtract the specified time inmicroseconds to the specified timeval structure. \since 0.9.11 */
+struct timeval* pa_timeval_sub(struct timeval *tv, pa_usec_t v);
 
 /** 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);

commit 7dad6350e3a80e234278261ed41a83ea236b67b5
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Apr 11 16:29:22 2008 +0000

    fix bit depth guarantee for pa_usec_t
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2241 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulse/sample.h b/src/pulse/sample.h
index f0b839f..dedd72d 100644
--- a/src/pulse/sample.h
+++ b/src/pulse/sample.h
@@ -30,6 +30,7 @@
 #include <sys/param.h>
 #include <math.h>
 
+#include <pulse/gccmacro.h>
 #include <pulse/cdecl.h>
 
 /** \page sample Sample Format Specifications
@@ -172,7 +173,7 @@ typedef struct pa_sample_spec {
     uint8_t channels;              /**< Audio channels. (1 for mono, 2 for stereo, ...) */
 } pa_sample_spec;
 
-/** Type for usec specifications (unsigned). May be either 32 or 64 bit, depending on the architecture */
+/** Type for usec specifications (unsigned). Always 64 bit. */
 typedef uint64_t pa_usec_t;
 
 /** Return the amount of bytes playback of a second of audio with the specified sample type takes */

commit e832b0c7fa3ae17adcbbea23183caeca718ac85a
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Apr 11 16:30:14 2008 +0000

    add C++ safety to header file
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2242 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulse/proplist.h b/src/pulse/proplist.h
index 7c3423f..302a59d 100644
--- a/src/pulse/proplist.h
+++ b/src/pulse/proplist.h
@@ -24,7 +24,10 @@
   USA.
 ***/
 
-#include <pulsecore/macro.h>
+#include <pulse/cdecl.h>
+#include <pulse/gccmacro.h>
+
+PA_C_DECL_BEGIN
 
 /* Defined properties:
  *
@@ -65,43 +68,43 @@
  *    device.buffer_size
  */
 
-#define PA_PROP_MEDIA_NAME                  "media.name"
-#define PA_PROP_MEDIA_TITLE                 "media.title"
-#define PA_PROP_MEDIA_ARTIST                "media.artist"
-#define PA_PROP_MEDIA_LANGUAGE              "media.language"
-#define PA_PROP_MEDIA_FILENAME              "media.filename"
-#define PA_PROP_MEDIA_ICON                  "media.icon"
-#define PA_PROP_MEDIA_ICON_NAME             "media.icon_name"
-#define PA_PROP_MEDIA_ROLE                  "media.role"
-#define PA_PROP_EVENT_ID                    "event.id"
-#define PA_PROP_EVENT_X11_DISPLAY           "event.x11.display"
-#define PA_PROP_EVENT_X11_XID               "event.x11.xid"
-#define PA_PROP_EVENT_MOUSE_X               "event.mouse.x"
-#define PA_PROP_EVENT_MOUSE_Y               "event.mouse.y"
-#define PA_PROP_EVENT_MOUSE_BUTTON          "event.mouse.button"
-#define PA_PROP_APPLICATION_NAME            "application.name"
-#define PA_PROP_APPLICATION_ID              "application.id"
-#define PA_PROP_APPLICATION_VERSION         "application.version"
-#define PA_PROP_APPLICATION_ICON            "application.icon"
-#define PA_PROP_APPLICATION_ICON_NAME       "application.icon_name"
-#define PA_PROP_APPLICATION_LANGUAGE        "application.language"
-#define PA_PROP_APPLICATION_PROCESS_ID      "application.process.id"
-#define PA_PROP_APPLICATION_PROCESS_BINARY  "application.process.binary"
-#define PA_PROP_APPLICATION_PROCESS_USER    "application.process.user"
-#define PA_PROP_APPLICATION_PROCESS_HOST    "application.process.host"
-#define PA_PROP_DEVICE_STRING               "device.string"
-#define PA_PROP_DEVICE_API                  "device.api"
-#define PA_PROP_DEVICE_DESCRIPTION          "device.description"
-#define PA_PROP_DEVICE_BUS_PATH             "device.bus_path"
-#define PA_PROP_DEVICE_SERIAL               "device.serial"
-#define PA_PROP_DEVICE_VENDOR_PRODUCT_ID    "device.vendor_product_id"
-#define PA_PROP_DEVICE_CLASS                "device.class"
-#define PA_PROP_DEVICE_FORM_FACTOR          "device.form_factor"
-#define PA_PROP_DEVICE_CONNECTOR            "device.connector"
-#define PA_PROP_DEVICE_ACCESS_MODE          "device.access_mode"
-#define PA_PROP_DEVICE_MASTER_DEVICE        "device.master_device"
-#define PA_PROP_DEVICE_BUFFER_NFRAGMENTS    "device.buffer.nfragments"
-#define PA_PROP_DEVICE_BUFFER_FRAGMENT_SIZE "device.buffer.fragment_size"
+#define PA_PROP_MEDIA_NAME                     "media.name"
+#define PA_PROP_MEDIA_TITLE                    "media.title"
+#define PA_PROP_MEDIA_ARTIST                   "media.artist"
+#define PA_PROP_MEDIA_LANGUAGE                 "media.language"
+#define PA_PROP_MEDIA_FILENAME                 "media.filename"
+#define PA_PROP_MEDIA_ICON                     "media.icon"
+#define PA_PROP_MEDIA_ICON_NAME                "media.icon_name"
+#define PA_PROP_MEDIA_ROLE                     "media.role"
+#define PA_PROP_EVENT_ID                       "event.id"
+#define PA_PROP_EVENT_X11_DISPLAY              "event.x11.display"
+#define PA_PROP_EVENT_X11_XID                  "event.x11.xid"
+#define PA_PROP_EVENT_MOUSE_X                  "event.mouse.x"
+#define PA_PROP_EVENT_MOUSE_Y                  "event.mouse.y"
+#define PA_PROP_EVENT_MOUSE_BUTTON             "event.mouse.button"
+#define PA_PROP_APPLICATION_NAME               "application.name"
+#define PA_PROP_APPLICATION_ID                 "application.id"
+#define PA_PROP_APPLICATION_VERSION            "application.version"
+#define PA_PROP_APPLICATION_ICON               "application.icon"
+#define PA_PROP_APPLICATION_ICON_NAME          "application.icon_name"
+#define PA_PROP_APPLICATION_LANGUAGE           "application.language"
+#define PA_PROP_APPLICATION_PROCESS_ID         "application.process.id"
+#define PA_PROP_APPLICATION_PROCESS_BINARY     "application.process.binary"
+#define PA_PROP_APPLICATION_PROCESS_USER       "application.process.user"
+#define PA_PROP_APPLICATION_PROCESS_HOST       "application.process.host"
+#define PA_PROP_DEVICE_STRING                  "device.string"
+#define PA_PROP_DEVICE_API                     "device.api"
+#define PA_PROP_DEVICE_DESCRIPTION             "device.description"
+#define PA_PROP_DEVICE_BUS_PATH                "device.bus_path"
+#define PA_PROP_DEVICE_SERIAL                  "device.serial"
+#define PA_PROP_DEVICE_VENDOR_PRODUCT_ID       "device.vendor_product_id"
+#define PA_PROP_DEVICE_CLASS                   "device.class"
+#define PA_PROP_DEVICE_FORM_FACTOR             "device.form_factor"
+#define PA_PROP_DEVICE_CONNECTOR               "device.connector"
+#define PA_PROP_DEVICE_ACCESS_MODE             "device.access_mode"
+#define PA_PROP_DEVICE_MASTER_DEVICE           "device.master_device"
+#define PA_PROP_DEVICE_BUFFERING_BUFFER_SIZE   "device.buffering.buffer_size"
+#define PA_PROP_DEVICE_BUFFERING_FRAGMENT_SIZE "device.buffering.fragment_size"
 
 /** A property list object. Basically a dictionary with UTF-8 strings
  * as keys and arbitrary data as values. \since 0.9.11 */
@@ -176,7 +179,7 @@ int pa_proplist_unset_many(pa_proplist *p, const char * const keys[]);
  * list do not have any particular order. \since 0.9.11 */
 const char *pa_proplist_iterate(pa_proplist *p, void **state);
 
-/** Format the property list nicely as a human readable string. \since
+/** Format the property list nicely as a human readable string. Call pa_xfree() on the result. \since
  * 0.9.11 */
 char *pa_proplist_to_string(pa_proplist *p);
 
@@ -191,4 +194,6 @@ void pa_proplist_clear(pa_proplist *p);
  * the specific list. \since 0.9.11 */
 pa_proplist* pa_proplist_copy(pa_proplist *template);
 
+PA_C_DECL_END
+
 #endif

commit d7e260bf6eb53c111c443c8c49d991651f7e7619
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Apr 11 16:30:34 2008 +0000

    remove misplaced PA_GCC_PURE
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2243 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulse/volume.h b/src/pulse/volume.h
index 0fbf872..245cc12 100644
--- a/src/pulse/volume.h
+++ b/src/pulse/volume.h
@@ -26,7 +26,9 @@
 ***/
 
 #include <inttypes.h>
+
 #include <pulse/cdecl.h>
+#include <pulse/gccmacro.h>
 #include <pulse/sample.h>
 
 /** \page volume Volume Control
@@ -149,7 +151,7 @@ int pa_cvolume_channels_equal_to(const pa_cvolume *a, pa_volume_t v) PA_GCC_PURE
 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_GCC_PURE;
+pa_cvolume *pa_sw_cvolume_multiply(pa_cvolume *dest, const pa_cvolume *a, const pa_cvolume *b);
 
 /** Convert a decibel value to a volume. This is only valid for software volumes! */
 pa_volume_t pa_sw_volume_from_dB(double f) PA_GCC_CONST;

commit 0f28de6f17fd9416db21792cf2dbfdb51ef5b5b6
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Apr 11 16:31:01 2008 +0000

    mark autoload functions as deprecated
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2244 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulse/introspect.h b/src/pulse/introspect.h
index 09cee60..d185a3a 100644
--- a/src/pulse/introspect.h
+++ b/src/pulse/introspect.h
@@ -30,6 +30,7 @@
 #include <pulse/operation.h>
 #include <pulse/context.h>
 #include <pulse/cdecl.h>
+#include <pulse/gccmacro.h>
 #include <pulse/channelmap.h>
 #include <pulse/volume.h>
 #include <pulse/proplist.h>
@@ -572,22 +573,22 @@ typedef struct pa_autoload_info {
 typedef void (*pa_autoload_info_cb_t)(pa_context *c, const pa_autoload_info *i, int eol, void *userdata);
 
 /** Get info about a specific autoload entry. */
-pa_operation* pa_context_get_autoload_info_by_name(pa_context *c, const char *name, pa_autoload_type_t type, pa_autoload_info_cb_t cb, void *userdata);
+pa_operation* pa_context_get_autoload_info_by_name(pa_context *c, const char *name, pa_autoload_type_t type, pa_autoload_info_cb_t cb, void *userdata) PA_GCC_DEPRECATED;
 
 /** Get info about a specific autoload entry. */
-pa_operation* pa_context_get_autoload_info_by_index(pa_context *c, uint32_t idx, pa_autoload_info_cb_t cb, void *userdata);
+pa_operation* pa_context_get_autoload_info_by_index(pa_context *c, uint32_t idx, pa_autoload_info_cb_t cb, void *userdata) PA_GCC_DEPRECATED;
 
 /** Get the complete list of autoload entries. */
-pa_operation* pa_context_get_autoload_info_list(pa_context *c, pa_autoload_info_cb_t cb, void *userdata);
+pa_operation* pa_context_get_autoload_info_list(pa_context *c, pa_autoload_info_cb_t cb, void *userdata) PA_GCC_DEPRECATED;
 
 /** Add a new autoload entry. */
-pa_operation* pa_context_add_autoload(pa_context *c, const char *name, pa_autoload_type_t type, const char *module, const char*argument, pa_context_index_cb_t, void* userdata);
+pa_operation* pa_context_add_autoload(pa_context *c, const char *name, pa_autoload_type_t type, const char *module, const char*argument, pa_context_index_cb_t, void* userdata) PA_GCC_DEPRECATED;
 
 /** Remove an autoload entry. */
-pa_operation* pa_context_remove_autoload_by_name(pa_context *c, const char *name, pa_autoload_type_t type, pa_context_success_cb_t cb, void* userdata);
+pa_operation* pa_context_remove_autoload_by_name(pa_context *c, const char *name, pa_autoload_type_t type, pa_context_success_cb_t cb, void* userdata) PA_GCC_DEPRECATED;
 
 /** Remove an autoload entry. */
-pa_operation* pa_context_remove_autoload_by_index(pa_context *c, uint32_t idx, pa_context_success_cb_t cb, void* userdata);
+pa_operation* pa_context_remove_autoload_by_index(pa_context *c, uint32_t idx, pa_context_success_cb_t cb, void* userdata) PA_GCC_DEPRECATED;
 
 /** @} */
 

commit 1c5f66519d06b65099c89e44a40c8ba070c0ca64
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Apr 11 16:32:03 2008 +0000

    make use of new alsa SND_PCM_NO_AUTO_xxx flags; redirect alsa errors to normal PA log system
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2245 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/alsa-util.c b/src/modules/alsa-util.c
index c8f594a..9c9fc72 100644
--- a/src/modules/alsa-util.c
+++ b/src/modules/alsa-util.c
@@ -36,6 +36,7 @@
 #include <pulsecore/log.h>
 #include <pulsecore/macro.h>
 #include <pulsecore/core-util.h>
+#include <pulsecore/atomic.h>
 
 #include "alsa-util.h"
 
@@ -571,7 +572,11 @@ snd_pcm_t *pa_alsa_open_by_device_id(
         d = pa_sprintf_malloc("%s:%s", device_table[i].name, dev_id);
         pa_log_debug("Trying %s...", d);
 
-        if ((err = snd_pcm_open(&pcm_handle, d, mode, SND_PCM_NONBLOCK)) < 0) {
+        if ((err = snd_pcm_open(&pcm_handle, d, mode,
+                                SND_PCM_NONBLOCK|
+                                SND_PCM_NO_AUTO_RESAMPLE|
+                                SND_PCM_NO_AUTO_CHANNELS|
+                                SND_PCM_NO_AUTO_FORMAT)) < 0) {
             pa_log_info("Couldn't open PCM device %s: %s", d, snd_strerror(err));
             pa_xfree(d);
             continue;
@@ -595,9 +600,9 @@ snd_pcm_t *pa_alsa_open_by_device_id(
         return pcm_handle;
     }
 
-    /* OK, we didn't find any good device, so let's try the raw hw: stuff */
+    /* OK, we didn't find any good device, so let's try the raw plughw: stuff */
 
-    d = pa_sprintf_malloc("hw:%s", dev_id);
+    d = pa_sprintf_malloc("plughw:%s", dev_id);
     pa_log_debug("Trying %s as last resort...", d);
     pcm_handle = pa_alsa_open_by_device_string(d, dev, ss, map, mode, nfrags, period_size, tsched_size, use_mmap, use_tsched);
     pa_xfree(d);
@@ -632,7 +637,10 @@ snd_pcm_t *pa_alsa_open_by_device_string(
 
     for (;;) {
 
-        if ((err = snd_pcm_open(&pcm_handle, d, mode, SND_PCM_NONBLOCK)) < 0) {
+        if ((err = snd_pcm_open(&pcm_handle, d, mode, SND_PCM_NONBLOCK|
+                                SND_PCM_NO_AUTO_RESAMPLE|
+                                SND_PCM_NO_AUTO_CHANNELS|
+                                SND_PCM_NO_AUTO_FORMAT)) < 0) {
             pa_log("Error opening PCM device %s: %s", d, snd_strerror(err));
             pa_xfree(d);
             return NULL;
@@ -937,3 +945,31 @@ void pa_alsa_dump_status(snd_pcm_t *pcm) {
 
     pa_assert_se(snd_output_close(out) == 0);
 }
+
+static void alsa_error_handler(const char *file, int line, const char *function, int err, const char *fmt,...) {
+    va_list ap;
+
+    va_start(ap, fmt);
+
+    pa_log_levelv_meta(PA_LOG_WARN, file, line, function, fmt, ap);
+
+    va_end(ap);
+}
+
+static pa_atomic_t n_error_handler_installed = PA_ATOMIC_INIT(0);
+
+void pa_alsa_redirect_errors_inc(void) {
+    /* This is not really thread safe, but we do our best */
+
+    if (pa_atomic_inc(&n_error_handler_installed) == 0)
+        snd_lib_error_set_handler(alsa_error_handler);
+}
+
+void pa_alsa_redirect_errors_dec(void) {
+    int r;
+
+    pa_assert_se((r = pa_atomic_dec(&n_error_handler_installed)) >= 1);
+
+    if (r == 1)
+        snd_lib_error_set_handler(NULL);
+}
diff --git a/src/modules/alsa-util.h b/src/modules/alsa-util.h
index 0e536f1..51222a4 100644
--- a/src/modules/alsa-util.h
+++ b/src/modules/alsa-util.h
@@ -85,4 +85,8 @@ void pa_alsa_0dB_capture(snd_mixer_elem_t *elem);
 void pa_alsa_dump(snd_pcm_t *pcm);
 void pa_alsa_dump_status(snd_pcm_t *pcm);
 
+void pa_alsa_redirect_errors_inc(void);
+void pa_alsa_redirect_errors_dec(void);
+
+
 #endif

commit 78368db54f1e47dd4d7c74142d1a7abebb85f8bb
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Apr 11 16:33:33 2008 +0000

    redirect alsa errors to normal PA log system; export buffer settings in device props
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2246 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-alsa-sink.c b/src/modules/module-alsa-sink.c
index 513350f..f8a2c48 100644
--- a/src/modules/module-alsa-sink.c
+++ b/src/modules/module-alsa-sink.c
@@ -60,7 +60,7 @@ PA_MODULE_LOAD_ONCE(FALSE);
 PA_MODULE_USAGE(
         "sink_name=<name for the sink> "
         "device=<ALSA device> "
-        "device_id=<ALSA device id> "
+        "device_id=<ALSA card index> "
         "format=<sample format> "
         "rate=<sample rate> "
         "channels=<number of channels> "
@@ -74,7 +74,7 @@ PA_MODULE_USAGE(
 
 #define DEFAULT_DEVICE "default"
 #define DEFAULT_TSCHED_BUFFER_USEC (2*PA_USEC_PER_SEC)
-#define DEFAULT_TSCHED_WATERMARK_USEC (10*PA_USEC_PER_MSEC)
+#define DEFAULT_TSCHED_WATERMARK_USEC (20*PA_USEC_PER_MSEC)
 
 struct userdata {
     pa_core *core;
@@ -267,6 +267,7 @@ static int unix_write(struct userdata *u) {
         int err;
 
         snd_pcm_hwsync(u->pcm_handle);
+        snd_pcm_avail_update(u->pcm_handle);
 
         if (PA_UNLIKELY((err = snd_pcm_status(u->pcm_handle, status)) < 0)) {
             pa_log("Failed to query DSP status data: %s", snd_strerror(err));
@@ -343,6 +344,10 @@ static void update_smoother(struct userdata *u) {
     int64_t frames;
     int err;
     pa_usec_t now1, now2;
+/*     struct timeval timestamp; */
+    snd_pcm_status_t *status;
+
+    snd_pcm_status_alloca(&status);
 
     pa_assert(u);
     pa_assert(u->pcm_handle);
@@ -352,15 +357,19 @@ static void update_smoother(struct userdata *u) {
     snd_pcm_hwsync(u->pcm_handle);
     snd_pcm_avail_update(u->pcm_handle);
 
-    if (PA_UNLIKELY((err = snd_pcm_delay(u->pcm_handle, &delay)) < 0)) {
-        pa_log_warn("Failed to get delay: %s", snd_strerror(err));
+    if (PA_UNLIKELY((err = snd_pcm_status(u->pcm_handle, status)) < 0)) {
+        pa_log("Failed to query DSP status data: %s", snd_strerror(err));
         return;
     }
 
+    delay = snd_pcm_status_get_delay(status);
     frames = u->frame_index - delay;
-
     pa_log_debug("frame_index = %llu, delay = %llu, p = %llu", (unsigned long long) u->frame_index, (unsigned long long) delay, (unsigned long long) frames);
 
+/*     snd_pcm_status_get_tstamp(status, &timestamp); */
+/*     pa_rtclock_from_wallclock(&timestamp); */
+/*     now1 = pa_timeval_load(&timestamp); */
+
     now1 = pa_rtclock_usec();
     now2 = pa_bytes_to_usec(frames * u->frame_size, &u->sink->sample_spec);
     pa_smoother_put(u->smoother, now1, now2);
@@ -1008,6 +1017,8 @@ int pa__init(pa_module*m) {
 
     pa_assert(m);
 
+    pa_alsa_redirect_errors_inc();
+
     if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
         pa_log("Failed to parse module arguments");
         goto fail;
@@ -1185,6 +1196,8 @@ int pa__init(pa_module*m) {
     pa_proplist_sets(data.proplist, PA_PROP_DEVICE_STRING, u->device_name);
     pa_proplist_sets(data.proplist, PA_PROP_DEVICE_API, "alsa");
     pa_proplist_sets(data.proplist, PA_PROP_DEVICE_DESCRIPTION, snd_pcm_info_get_name(pcm_info));
+    pa_proplist_setf(data.proplist, PA_PROP_DEVICE_BUFFERING_BUFFER_SIZE, "%lu", (unsigned long) (period_frames * frame_size * nfrags));
+    pa_proplist_setf(data.proplist, PA_PROP_DEVICE_BUFFERING_FRAGMENT_SIZE, "%lu", (unsigned long) (period_frames * frame_size));
 
     if (class_table[snd_pcm_info_get_class(pcm_info)])
         pa_proplist_sets(data.proplist, PA_PROP_DEVICE_CLASS, class_table[snd_pcm_info_get_class(pcm_info)]);
@@ -1366,8 +1379,10 @@ void pa__done(pa_module*m) {
 
     pa_assert(m);
 
-    if (!(u = m->userdata))
+    if (!(u = m->userdata)) {
+        pa_alsa_redirect_errors_dec();
         return;
+    }
 
     if (u->sink)
         pa_sink_unlink(u->sink);
@@ -1409,4 +1424,6 @@ void pa__done(pa_module*m) {
     pa_xfree(u);
 
     snd_config_update_free_global();
+
+    pa_alsa_redirect_errors_dec();
 }
diff --git a/src/modules/module-alsa-source.c b/src/modules/module-alsa-source.c
index caaa545..83b7f53 100644
--- a/src/modules/module-alsa-source.c
+++ b/src/modules/module-alsa-source.c
@@ -61,7 +61,7 @@ PA_MODULE_LOAD_ONCE(FALSE);
 PA_MODULE_USAGE(
         "source_name=<name for the source> "
         "device=<ALSA device> "
-        "device_id=<ALSA device id> "
+        "device_id=<ALSA card index> "
         "format=<sample format> "
         "rate=<sample rate> "
         "channels=<number of channels> "
@@ -889,6 +889,8 @@ int pa__init(pa_module*m) {
 
     pa_assert(m);
 
+    pa_alsa_redirect_errors_inc();
+
     if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
         pa_log("Failed to parse module arguments");
         goto fail;
@@ -1061,6 +1063,8 @@ int pa__init(pa_module*m) {
     pa_proplist_sets(data.proplist, PA_PROP_DEVICE_STRING, u->device_name);
     pa_proplist_sets(data.proplist, PA_PROP_DEVICE_API, "alsa");
     pa_proplist_sets(data.proplist, PA_PROP_DEVICE_DESCRIPTION, snd_pcm_info_get_name(pcm_info));
+    pa_proplist_setf(data.proplist, PA_PROP_DEVICE_BUFFERING_BUFFER_SIZE, "%lu", (unsigned long) (period_frames * frame_size * nfrags));
+    pa_proplist_setf(data.proplist, PA_PROP_DEVICE_BUFFERING_FRAGMENT_SIZE, "%lu", (unsigned long) (period_frames * frame_size));
 
     if (class_table[snd_pcm_info_get_class(pcm_info)])
         pa_proplist_sets(data.proplist, PA_PROP_DEVICE_CLASS, class_table[snd_pcm_info_get_class(pcm_info)]);
@@ -1228,8 +1232,10 @@ void pa__done(pa_module*m) {
 
     pa_assert(m);
 
-    if (!(u = m->userdata))
+    if (!(u = m->userdata)) {
+        pa_alsa_redirect_errors_dec();
         return;
+    }
 
     if (u->source)
         pa_source_unlink(u->source);
@@ -1268,4 +1274,5 @@ void pa__done(pa_module*m) {
     pa_xfree(u);
 
     snd_config_update_free_global();
+    pa_alsa_redirect_errors_dec();
 }

commit d0ebb71eede6c626e61aac27aabbe679638358f5
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Apr 11 16:34:11 2008 +0000

    don't use fqdn if we don't have to
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2247 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/protocol-http.c b/src/pulsecore/protocol-http.c
index d91ae14..589eba4 100644
--- a/src/pulsecore/protocol-http.c
+++ b/src/pulsecore/protocol-http.c
@@ -168,7 +168,7 @@ static void line_callback(pa_ioline *line, const char *s, void *userdata) {
 #define PRINTF_FIELD(a,b) pa_ioline_printf(c->line, "<tr><td><b>%s</b></td><td>%s</td></tr>\n",(a),(b))
 
                 PRINTF_FIELD("User Name:", pa_get_user_name(txt, sizeof(txt)));
-                PRINTF_FIELD("Fully Qualified Domain Name:", pa_get_fqdn(txt, sizeof(txt)));
+                PRINTF_FIELD("Host name:", pa_get_host_name(txt, sizeof(txt)));
                 PRINTF_FIELD("Default Sample Specification:", pa_sample_spec_snprint(txt, sizeof(txt), &c->protocol->core->default_sample_spec));
                 PRINTF_FIELD("Default Sink:", pa_namereg_get_default_sink_name(c->protocol->core));
                 PRINTF_FIELD("Default Source:", pa_namereg_get_default_source_name(c->protocol->core));

commit 50d585e458039bf428d76deb04cd378e61d4b533
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Apr 11 16:35:31 2008 +0000

    fix linker warning macro code, move pa_strnull() to core-util.h, move PA_LIKELY definitions here from gccmacro.h
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2248 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/macro.h b/src/pulsecore/macro.h
index a301bba..1d9eafd 100644
--- a/src/pulsecore/macro.h
+++ b/src/pulsecore/macro.h
@@ -33,12 +33,22 @@
 #include <stdlib.h>
 
 #include <pulsecore/log.h>
-#include <pulsecore/gccmacro.h>
+#include <pulse/gccmacro.h>
 
 #ifndef PACKAGE
 #error "Please include config.h before including this file!"
 #endif
 
+#ifndef PA_LIKELY
+#ifdef __GNUC__
+#define PA_LIKELY(x) (__builtin_expect(!!(x),1))
+#define PA_UNLIKELY(x) (__builtin_expect((x),0))
+#else
+#define PA_LIKELY(x) (x)
+#define PA_UNLIKELY(x) (x)
+#endif
+#endif
+
 #if defined(PAGE_SIZE)
 #define PA_PAGE_SIZE ((size_t) PAGE_SIZE)
 #elif defined(PAGESIZE)
@@ -200,20 +210,16 @@ typedef int pa_bool_t;
 #define PA_PATH_SEP_CHAR '/'
 #endif
 
-static inline const char *pa_strnull(const char *x) {
-    return x ? x : "(null)";
-}
-
 #ifdef __GNUC__
 
-#define PA_WARN_REFERENCE(sym,msg)              \
-    __asm__(".section .gnu.warning.sym");       \
-    __asm__(".asciz \"msg\"");                  \
+#define PA_WARN_REFERENCE(sym, msg)                  \
+    __asm__(".section .gnu.warning." #sym);          \
+    __asm__(".asciz \"" msg "\"");                   \
     __asm__(".previous")
 
 #else
 
-#define PA_WARN_REFERENCE(sym,msg)
+#define PA_WARN_REFERENCE(sym, msg)
 
 #endif
 

commit 28ab2a0c1dc9e4cf86d8b583748796754b607096
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Apr 11 16:36:13 2008 +0000

    don't print 'signal' each time a rtpoll poll() call is canceled
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2249 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/rtpoll.c b/src/pulsecore/rtpoll.c
index 7403508..afcd7e5 100644
--- a/src/pulsecore/rtpoll.c
+++ b/src/pulsecore/rtpoll.c
@@ -98,7 +98,7 @@ struct pa_rtpoll_item {
 
 PA_STATIC_FLIST_DECLARE(items, 0, pa_xfree);
 
-static void signal_handler_noop(int s) { write(2, "signal\n", 7); }
+static void signal_handler_noop(int s) { /* write(2, "signal\n", 7); */ }
 
 pa_rtpoll *pa_rtpoll_new(void) {
     pa_rtpoll *p;

commit 413656bce6ed85e4732412ddf89e93fc7a46683a
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Apr 11 16:36:38 2008 +0000

    update list-xxx commands a bit
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2250 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/cli-text.c b/src/pulsecore/cli-text.c
index 5bf27ee..140334a 100644
--- a/src/pulsecore/cli-text.c
+++ b/src/pulsecore/cli-text.c
@@ -57,12 +57,12 @@ char *pa_module_list_to_string(pa_core *c) {
 
     for (m = pa_idxset_first(c->modules, &idx); m; m = pa_idxset_next(c->modules, &idx)) {
         pa_strbuf_printf(s, "    index: %u\n"
-            "\tname: <%s>\n"
-            "\targument: <%s>\n"
-            "\tused: %i\n"
-            "\tauto unload: %s\n",
-            m->index, m->name, m->argument ? m->argument : "", m->n_used,
-            m->auto_unload ? "yes" : "no");
+                         "\tname: <%s>\n"
+                         "\targument: <%s>\n"
+                         "\tused: %i\n"
+                         "\tauto unload: %s\n",
+                         m->index, m->name, m->argument ? m->argument : "", m->n_used,
+                         pa_yes_no(m->auto_unload));
     }
 
     return pa_strbuf_tostring_free(s);
@@ -138,12 +138,12 @@ char *pa_sink_list_to_string(pa_core *c) {
             sink->index,
             sink->name,
             sink->driver,
+            sink->flags & PA_SINK_HARDWARE ? "HARDWARE " : "",
+            sink->flags & PA_SINK_NETWORK ? "NETWORK " : "",
             sink->flags & PA_SINK_HW_MUTE_CTRL ? "HW_MUTE_CTRL " : "",
             sink->flags & PA_SINK_HW_VOLUME_CTRL ? "HW_VOLUME_CTRL " : "",
             sink->flags & PA_SINK_DECIBEL_VOLUME ? "DECIBEL_VOLUME " : "",
             sink->flags & PA_SINK_LATENCY ? "LATENCY " : "",
-            sink->flags & PA_SINK_HARDWARE ? "HARDWARE " : "",
-            sink->flags & PA_SINK_NETWORK ? "NETWORK " : "",
             state_table[pa_sink_get_state(sink)],
             pa_cvolume_snprint(cv, sizeof(cv), pa_sink_get_volume(sink)),
             !!pa_sink_get_mute(sink),
@@ -205,12 +205,12 @@ char *pa_source_list_to_string(pa_core *c) {
             source->index,
             source->name,
             source->driver,
+            source->flags & PA_SOURCE_HARDWARE ? "HARDWARE " : "",
+            source->flags & PA_SOURCE_NETWORK ? "NETWORK " : "",
             source->flags & PA_SOURCE_HW_MUTE_CTRL ? "HW_MUTE_CTRL " : "",
             source->flags & PA_SOURCE_HW_VOLUME_CTRL ? "HW_VOLUME_CTRL " : "",
             source->flags & PA_SOURCE_DECIBEL_VOLUME ? "DECIBEL_VOLUME " : "",
             source->flags & PA_SOURCE_LATENCY ? "LATENCY " : "",
-            source->flags & PA_SOURCE_HARDWARE ? "HARDWARE " : "",
-            source->flags & PA_SOURCE_NETWORK ? "NETWORK " : "",
             state_table[pa_source_get_state(source)],
             pa_cvolume_snprint(cv, sizeof(cv), pa_source_get_volume(source)),
             !!pa_source_get_mute(source),

commit c9db6d2543fd0be51a6c73ef3afb1462c1924f1b
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Apr 11 16:37:22 2008 +0000

    don't fail if a signalled writability of STDOUT is no longer true when we try it because some other thread already wrote something
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2251 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/ioline.c b/src/pulsecore/ioline.c
index 5fd2189..860a651 100644
--- a/src/pulsecore/ioline.c
+++ b/src/pulsecore/ioline.c
@@ -299,6 +299,10 @@ static int do_read(pa_ioline *l) {
 
         /* Read some data */
         if ((r = pa_iochannel_read(l->io, l->rbuf+l->rbuf_index+l->rbuf_valid_length, len)) <= 0) {
+
+            if (r < 0 && errno == EAGAIN)
+                return 0;
+
             if (r < 0 && errno != ECONNRESET) {
                 pa_log("read(): %s", pa_cstrerror(errno));
                 failure(l, 0);
@@ -328,6 +332,9 @@ static int do_write(pa_ioline *l) {
 
         if ((r = pa_iochannel_write(l->io, l->wbuf+l->wbuf_index, l->wbuf_valid_length)) <= 0) {
 
+            if (r < 0 && errno == EAGAIN)
+                return 0;
+
             if (r < 0 && errno != EPIPE)
                 pa_log("write(): %s", pa_cstrerror(errno));
 

commit 096e7f0f817d5dbf130e623bdae0388019bfbfc6
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Apr 11 16:38:16 2008 +0000

    make shm magic marker compat with multiarch systems where 64bit and 32bit processes might share SHM areas
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2252 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/shm.c b/src/pulsecore/shm.c
index 59341f0..33034e2 100644
--- a/src/pulsecore/shm.c
+++ b/src/pulsecore/shm.c
@@ -73,10 +73,10 @@
 struct shm_marker {
     pa_atomic_t marker; /* 0xbeefcafe */
     pa_atomic_t pid;
-    void *_reserverd1;
-    void *_reserverd2;
-    void *_reserverd3;
-    void *_reserverd4;
+    uint64_t *_reserverd1;
+    uint64_t *_reserverd2;
+    uint64_t *_reserverd3;
+    uint64_t *_reserverd4;
 };
 
 static char *segment_name(char *fn, size_t l, unsigned id) {

commit 29cbd88138291d4344bad166b9943814b943e293
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Apr 11 16:51:21 2008 +0000

    add new PA_GCC_PACKED macro
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2253 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulse/gccmacro.h b/src/pulse/gccmacro.h
index 5a2a250..032c3ba 100644
--- a/src/pulse/gccmacro.h
+++ b/src/pulse/gccmacro.h
@@ -86,4 +86,13 @@
 #endif
 #endif
 
+#ifndef PA_GCC_PACKED
+#ifdef __GNUCC__
+#define PA_GCC_PACKED __attribute__ ((packed))
+#else
+/** Structure shall be packed in memory **/
+#define PA_GCC_PACKED
+#endif
+#endif
+
 #endif

commit 2c6176fdd40ccec36b3788a07289cf57cafd028f
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Apr 11 16:52:45 2008 +0000

    mark shm marker struct as packed, to guarantee identical sizes between archs
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2254 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/shm.c b/src/pulsecore/shm.c
index 33034e2..a1bbf60 100644
--- a/src/pulsecore/shm.c
+++ b/src/pulsecore/shm.c
@@ -42,6 +42,7 @@
 #endif
 
 #include <pulse/xmalloc.h>
+#include <pulse/gccmacro.h>
 
 #include <pulsecore/core-error.h>
 #include <pulsecore/log.h>
@@ -69,8 +70,9 @@
 
 #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 {
+/* 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_GCC_PACKED {
     pa_atomic_t marker; /* 0xbeefcafe */
     pa_atomic_t pid;
     uint64_t *_reserverd1;

commit fe3c42dbfe1a80a4112df61a25dfa285005356c2
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Apr 11 16:53:29 2008 +0000

    fix packet formatting for a few commands
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2255 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c
index db52b7f..fc5aa59 100644
--- a/src/pulsecore/protocol-native.c
+++ b/src/pulsecore/protocol-native.c
@@ -2186,8 +2186,10 @@ static void sink_fill_tagstruct(connection *c, pa_tagstruct *t, pa_sink *sink) {
         PA_TAG_U32, sink->flags,
         PA_TAG_INVALID);
 
-    if (c->version >= 13)
+    if (c->version >= 13) {
         pa_tagstruct_put_proplist(t, sink->proplist);
+        pa_tagstruct_put_usec(t, pa_sink_get_requested_latency(sink));
+    }
 }
 
 static void source_fill_tagstruct(connection *c, pa_tagstruct *t, pa_source *source) {
@@ -2215,10 +2217,13 @@ static void source_fill_tagstruct(connection *c, pa_tagstruct *t, pa_source *sou
         PA_TAG_U32, source->flags,
         PA_TAG_INVALID);
 
-    if (c->version >= 13)
+    if (c->version >= 13) {
         pa_tagstruct_put_proplist(t, source->proplist);
+        pa_tagstruct_put_usec(t, pa_source_get_requested_latency(source));
+    }
 }
 
+
 static void client_fill_tagstruct(connection *c, pa_tagstruct *t, pa_client *client) {
     pa_assert(t);
     pa_assert(client);
@@ -2266,10 +2271,8 @@ static void sink_input_fill_tagstruct(connection *c, pa_tagstruct *t, pa_sink_in
     pa_tagstruct_puts(t, s->driver);
     if (c->version >= 11)
         pa_tagstruct_put_boolean(t, pa_sink_input_get_mute(s));
-    if (c->version >= 13) {
+    if (c->version >= 13)
         pa_tagstruct_put_proplist(t, s->proplist);
-        pa_tagstruct_put_usec(t, pa_sink_get_requested_latency(s->sink));
-    }
 }
 
 static void source_output_fill_tagstruct(connection *c, pa_tagstruct *t, pa_source_output *s) {
@@ -2292,10 +2295,8 @@ static void source_output_fill_tagstruct(connection *c, pa_tagstruct *t, pa_sour
     pa_tagstruct_puts(t, pa_resample_method_to_string(pa_source_output_get_resample_method(s)));
     pa_tagstruct_puts(t, s->driver);
 
-    if (c->version >= 13) {
+    if (c->version >= 13)
         pa_tagstruct_put_proplist(t, s->proplist);
-        pa_tagstruct_put_usec(t, pa_source_get_requested_latency(s->source));
-    }
 }
 
 static void scache_fill_tagstruct(connection *c, pa_tagstruct *t, pa_scache_entry *e) {
@@ -2480,7 +2481,7 @@ static void command_get_server_info(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSE
     pa_tagstruct_puts(reply, PACKAGE_NAME);
     pa_tagstruct_puts(reply, PACKAGE_VERSION);
     pa_tagstruct_puts(reply, pa_get_user_name(txt, sizeof(txt)));
-    pa_tagstruct_puts(reply, pa_get_fqdn(txt, sizeof(txt)));
+    pa_tagstruct_puts(reply, pa_get_host_name(txt, sizeof(txt)));
 
     fixup_sample_spec(c, &fixed_ss, &c->protocol->core->default_sample_spec);
     pa_tagstruct_put_sample_spec(reply, &fixed_ss);

commit dcf71734892ed6f8076a6ae37718fa02c750be7a
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Apr 11 16:57:26 2008 +0000

    fix help string for volume commands
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2256 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/cli-command.c b/src/pulsecore/cli-command.c
index ced56c2..7c85224 100644
--- a/src/pulsecore/cli-command.c
+++ b/src/pulsecore/cli-command.c
@@ -477,7 +477,7 @@ static int pa_cli_command_sink_volume(pa_core *c, pa_tokenizer *t, pa_strbuf *bu
     }
 
     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");
+        pa_strbuf_puts(buf, "You need to specify a volume >= 0. (0 is muted, 0x10000 is normal volume)\n");
         return -1;
     }
 
@@ -519,7 +519,7 @@ static int pa_cli_command_sink_input_volume(pa_core *c, pa_tokenizer *t, pa_strb
     }
 
     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");
+        pa_strbuf_puts(buf, "You need to specify a volume >= 0. (0 is muted, 0x10000 is normal volume)\n");
         return -1;
     }
 
@@ -555,7 +555,7 @@ static int pa_cli_command_source_volume(pa_core *c, pa_tokenizer *t, pa_strbuf *
     }
 
     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");
+        pa_strbuf_puts(buf, "You need to specify a volume >= 0. (0 is muted, 0x10000 is normal volume)\n");
         return -1;
     }
 
@@ -664,7 +664,7 @@ static int pa_cli_command_sink_input_mute(pa_core *c, pa_tokenizer *t, pa_strbuf
     }
 
     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");
+        pa_strbuf_puts(buf, "You need to specify a volume >= 0. (0 is muted, 0x10000 is normal volume)\n");
         return -1;
     }
 

commit cdb273de904a0a66fee2c0dc0c164455f8c035ac
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Apr 11 16:58:07 2008 +0000

    add new pa_get_state_dir() function, move pa_strnull() here
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2257 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/core-util.c b/src/pulsecore/core-util.c
index 61d04c2..28885b2 100644
--- a/src/pulsecore/core-util.c
+++ b/src/pulsecore/core-util.c
@@ -1093,6 +1093,35 @@ int pa_unlock_lockfile(const char *fn, int fd) {
     return r;
 }
 
+char *pa_get_state_dir(void) {
+    const char *e;
+    char *d;
+
+    if ((e = getenv("PULSE_STATE_PATH")))
+        d = pa_xstrdup(e);
+    else {
+        char h[PATH_MAX];
+
+        if (!pa_get_home_dir(h, sizeof(h))) {
+            pa_log_error("Failed to get home directory.");
+            return NULL;
+        }
+
+        d = pa_sprintf_malloc("%s/.pulse", h);
+    }
+
+    mkdir(d, 0755);
+
+    if (access(d, W_OK) == 0)
+        return d;
+
+    pa_log_error("Failed to set up state directory %s", d);
+
+    pa_xfree(d);
+
+    return NULL;
+}
+
 /* Try to open a configuration file. If "env" is specified, open the
  * value of the specified environment variable. Otherwise look for a
  * file "local" in the home directory or a file "global" in global
diff --git a/src/pulsecore/core-util.h b/src/pulsecore/core-util.h
index c8760a1..d5c0a3f 100644
--- a/src/pulsecore/core-util.h
+++ b/src/pulsecore/core-util.h
@@ -30,7 +30,7 @@
 #include <stdarg.h>
 #include <stdio.h>
 
-#include <pulsecore/gccmacro.h>
+#include <pulse/gccmacro.h>
 #include <pulsecore/macro.h>
 
 struct timeval;
@@ -67,6 +67,10 @@ static inline const char *pa_yes_no(pa_bool_t b) {
     return b ? "yes" : "no";
 }
 
+static inline const char *pa_strnull(const char *x) {
+    return x ? x : "(null)";
+}
+
 char *pa_split(const char *c, const char*delimiters, const char **state);
 char *pa_split_spaces(const char *c, const char **state);
 
@@ -129,4 +133,6 @@ void pa_close_pipe(int fds[2]);
 
 char *pa_readlink(const char *p);
 
+char *pa_get_state_dir(void);
+
 #endif

commit dbe36333f37ad76a9ba011211740b79da7e4683c
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Apr 11 17:02:42 2008 +0000

    properly initialize ->memblockq
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2258 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/sound-file-stream.c b/src/pulsecore/sound-file-stream.c
index 60c2560..5c8400d 100644
--- a/src/pulsecore/sound-file-stream.c
+++ b/src/pulsecore/sound-file-stream.c
@@ -247,6 +247,7 @@ int pa_play_file(
     u->sink_input = NULL;
     u->sndfile = NULL;
     u->readf_function = NULL;
+    u->memblockq = NULL;
 
     memset(&sfinfo, 0, sizeof(sfinfo));
 

commit aad9d39838d247e563354e56ccdea280a428d098
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Apr 11 17:03:18 2008 +0000

    dump all info we know about sinks/sources/... in pactl
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2259 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/utils/pactl.c b/src/utils/pactl.c
index 674eaee..1f875a8 100644
--- a/src/utils/pactl.c
+++ b/src/utils/pactl.c
@@ -158,6 +158,7 @@ static void get_server_info_callback(pa_context *c, const pa_server_info *i, voi
 
 static void get_sink_info_callback(pa_context *c, const pa_sink_info *i, int is_last, void *userdata) {
     char s[PA_SAMPLE_SPEC_SNPRINT_MAX], cv[PA_CVOLUME_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX];
+    char *pl;
 
     if (is_last < 0) {
         fprintf(stderr, "Failed to get sink information: %s\n", pa_strerror(pa_context_errno(c)));
@@ -179,32 +180,37 @@ static void get_sink_info_callback(pa_context *c, const pa_sink_info *i, int is_
     printf("*** Sink #%u ***\n"
            "Name: %s\n"
            "Driver: %s\n"
-           "Description: %s\n"
            "Sample Specification: %s\n"
            "Channel Map: %s\n"
            "Owner Module: %u\n"
            "Volume: %s\n"
-           "Monitor Source: %u\n"
-           "Latency: %0.0f usec\n"
-           "Flags: %s%s%s\n",
+           "Monitor Source: %s\n"
+           "Latency: %0.0f usec, configured %0.0f usec\n"
+           "Flags: %s%s%s%s%s%s\n"
+           "Properties:\n%s",
            i->index,
            i->name,
-           i->driver,
-           i->description,
+           pa_strnull(i->driver),
            pa_sample_spec_snprint(s, sizeof(s), &i->sample_spec),
            pa_channel_map_snprint(cm, sizeof(cm), &i->channel_map),
            i->owner_module,
            i->mute ? "muted" : pa_cvolume_snprint(cv, sizeof(cv), &i->volume),
-           i->monitor_source,
-           (double) i->latency,
+           pa_strnull(i->monitor_source_name),
+           (double) i->latency, (double) i->configured_latency,
+           i->flags & PA_SINK_HARDWARE ? "HARDWARE " : "",
+           i->flags & PA_SINK_NETWORK ? "NETWORK " : "",
+           i->flags & PA_SINK_HW_MUTE_CTRL ? "HW_MUTE_CTRL " : "",
            i->flags & PA_SINK_HW_VOLUME_CTRL ? "HW_VOLUME_CTRL " : "",
+           i->flags & PA_SINK_DECIBEL_VOLUME ? "DECIBEL_VOLUME " : "",
            i->flags & PA_SINK_LATENCY ? "LATENCY " : "",
-           i->flags & PA_SINK_HARDWARE ? "HARDWARE" : "");
+           pl = pa_proplist_to_string(i->proplist));
 
+    pa_xfree(pl);
 }
 
 static void get_source_info_callback(pa_context *c, const pa_source_info *i, int is_last, void *userdata) {
-    char s[PA_SAMPLE_SPEC_SNPRINT_MAX], t[32], cv[PA_CVOLUME_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX];
+    char s[PA_SAMPLE_SPEC_SNPRINT_MAX], cv[PA_CVOLUME_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX];
+    char *pl;
 
     if (is_last < 0) {
         fprintf(stderr, "Failed to get source information: %s\n", pa_strerror(pa_context_errno(c)));
@@ -223,33 +229,35 @@ static void get_source_info_callback(pa_context *c, const pa_source_info *i, int
         printf("\n");
     nl = 1;
 
-    snprintf(t, sizeof(t), "%u", i->monitor_of_sink);
-
     printf("*** Source #%u ***\n"
            "Name: %s\n"
            "Driver: %s\n"
-           "Description: %s\n"
            "Sample Specification: %s\n"
            "Channel Map: %s\n"
            "Owner Module: %u\n"
            "Volume: %s\n"
            "Monitor of Sink: %s\n"
-           "Latency: %0.0f usec\n"
-           "Flags: %s%s%s\n",
+           "Latency: %0.0f usec, configured %0.0f usec\n"
+           "Flags: %s%s%s%s%s%s\n"
+           "Properties:\n%s",
            i->index,
            i->name,
-           i->driver,
-           i->description,
+           pa_strnull(i->driver),
            pa_sample_spec_snprint(s, sizeof(s), &i->sample_spec),
            pa_channel_map_snprint(cm, sizeof(cm), &i->channel_map),
            i->owner_module,
            i->mute ? "muted" : pa_cvolume_snprint(cv, sizeof(cv), &i->volume),
-           i->monitor_of_sink != PA_INVALID_INDEX ? t : "no",
-           (double) i->latency,
+           i->monitor_of_sink_name ? i->monitor_of_sink_name : "n/a",
+           (double) i->latency, (double) i->configured_latency,
+           i->flags & PA_SOURCE_HARDWARE ? "HARDWARE " : "",
+           i->flags & PA_SOURCE_NETWORK ? "NETWORK " : "",
+           i->flags & PA_SOURCE_HW_MUTE_CTRL ? "HW_MUTE_CTRL " : "",
            i->flags & PA_SOURCE_HW_VOLUME_CTRL ? "HW_VOLUME_CTRL " : "",
+           i->flags & PA_SOURCE_DECIBEL_VOLUME ? "DECIBEL_VOLUME " : "",
            i->flags & PA_SOURCE_LATENCY ? "LATENCY " : "",
-           i->flags & PA_SOURCE_HARDWARE ? "HARDWARE" : "");
+           pl = pa_proplist_to_string(i->proplist));
 
+    pa_xfree(pl);
 }
 
 static void get_module_info_callback(pa_context *c, const pa_module_info *i, int is_last, void *userdata) {
@@ -283,11 +291,12 @@ static void get_module_info_callback(pa_context *c, const pa_module_info *i, int
            i->name,
            i->argument ? i->argument : "",
            i->n_used != PA_INVALID_INDEX ? t : "n/a",
-           i->auto_unload ? "yes" : "no");
+           pa_yes_no(i->auto_unload));
 }
 
 static void get_client_info_callback(pa_context *c, const pa_client_info *i, int is_last, void *userdata) {
     char t[32];
+    char *pl;
 
     if (is_last < 0) {
         fprintf(stderr, "Failed to get client information: %s\n", pa_strerror(pa_context_errno(c)));
@@ -309,17 +318,20 @@ static void get_client_info_callback(pa_context *c, const pa_client_info *i, int
     snprintf(t, sizeof(t), "%u", i->owner_module);
 
     printf("*** Client #%u ***\n"
-           "Name: %s\n"
            "Driver: %s\n"
-           "Owner Module: %s\n",
+           "Owner Module: %s\n"
+           "Properties:\n%s",
            i->index,
-           i->name,
-           i->driver,
-           i->owner_module != PA_INVALID_INDEX ? t : "n/a");
+           pa_strnull(i->driver),
+           i->owner_module != PA_INVALID_INDEX ? t : "n/a",
+           pl = pa_proplist_to_string(i->proplist));
+
+    pa_xfree(pl);
 }
 
 static void get_sink_input_info_callback(pa_context *c, const pa_sink_input_info *i, int is_last, void *userdata) {
     char t[32], k[32], s[PA_SAMPLE_SPEC_SNPRINT_MAX], cv[PA_CVOLUME_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX];
+    char *pl;
 
     if (is_last < 0) {
         fprintf(stderr, "Failed to get sink input information: %s\n", pa_strerror(pa_context_errno(c)));
@@ -342,7 +354,6 @@ static void get_sink_input_info_callback(pa_context *c, const pa_sink_input_info
     snprintf(k, sizeof(k), "%u", i->client);
 
     printf("*** Sink Input #%u ***\n"
-           "Name: %s\n"
            "Driver: %s\n"
            "Owner Module: %s\n"
            "Client: %s\n"
@@ -352,10 +363,10 @@ static void get_sink_input_info_callback(pa_context *c, const pa_sink_input_info
            "Volume: %s\n"
            "Buffer Latency: %0.0f usec\n"
            "Sink Latency: %0.0f usec\n"
-           "Resample method: %s\n",
+           "Resample method: %s\n"
+           "Properties:\n%s",
            i->index,
-           i->name,
-           i->driver,
+           pa_strnull(i->driver),
            i->owner_module != PA_INVALID_INDEX ? t : "n/a",
            i->client != PA_INVALID_INDEX ? k : "n/a",
            i->sink,
@@ -364,12 +375,15 @@ static void get_sink_input_info_callback(pa_context *c, const pa_sink_input_info
            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");
-}
+           i->resample_method ? i->resample_method : "n/a",
+           pl = pa_proplist_to_string(i->proplist));
 
+    pa_xfree(pl);
+}
 
 static void get_source_output_info_callback(pa_context *c, const pa_source_output_info *i, int is_last, void *userdata) {
     char t[32], k[32], s[PA_SAMPLE_SPEC_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX];
+    char *pl;
 
     if (is_last < 0) {
         fprintf(stderr, "Failed to get source output information: %s\n", pa_strerror(pa_context_errno(c)));
@@ -393,7 +407,6 @@ static void get_source_output_info_callback(pa_context *c, const pa_source_outpu
     snprintf(k, sizeof(k), "%u", i->client);
 
     printf("*** Source Output #%u ***\n"
-           "Name: %s\n"
            "Driver: %s\n"
            "Owner Module: %s\n"
            "Client: %s\n"
@@ -402,10 +415,10 @@ static void get_source_output_info_callback(pa_context *c, const pa_source_outpu
            "Channel Map: %s\n"
            "Buffer Latency: %0.0f usec\n"
            "Source Latency: %0.0f usec\n"
-           "Resample method: %s\n",
+           "Resample method: %s\n"
+           "Properties:\n%s",
            i->index,
-           i->name,
-           i->driver,
+           pa_strnull(i->driver),
            i->owner_module != PA_INVALID_INDEX ? t : "n/a",
            i->client != PA_INVALID_INDEX ? k : "n/a",
            i->source,
@@ -413,11 +426,15 @@ static void get_source_output_info_callback(pa_context *c, const pa_source_outpu
            pa_channel_map_snprint(cm, sizeof(cm), &i->channel_map),
            (double) i->buffer_usec,
            (double) i->source_usec,
-           i->resample_method ? i->resample_method : "n/a");
+           i->resample_method ? i->resample_method : "n/a",
+           pl = pa_proplist_to_string(i->proplist));
+
+    pa_xfree(pl);
 }
 
 static void get_sample_info_callback(pa_context *c, const pa_sample_info *i, int is_last, void *userdata) {
     char t[32], s[PA_SAMPLE_SPEC_SNPRINT_MAX], cv[PA_CVOLUME_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX];
+    char *pl;
 
     if (is_last < 0) {
         fprintf(stderr, "Failed to get sample information: %s\n", pa_strerror(pa_context_errno(c)));
@@ -447,7 +464,8 @@ static void get_sample_info_callback(pa_context *c, const pa_sample_info *i, int
            "Duration: %0.1fs\n"
            "Size: %s\n"
            "Lazy: %s\n"
-           "Filename: %s\n",
+           "Filename: %s\n"
+           "Properties:\n%s",
            i->index,
            i->name,
            pa_cvolume_snprint(cv, sizeof(cv), &i->volume),
@@ -455,8 +473,11 @@ static void get_sample_info_callback(pa_context *c, const pa_sample_info *i, int
            pa_sample_spec_valid(&i->sample_spec) ? pa_channel_map_snprint(cm, sizeof(cm), &i->channel_map) : "n/a",
            (double) i->duration/1000000,
            t,
-           i->lazy ? "yes" : "no",
-           i->filename ? i->filename : "n/a");
+           pa_yes_no(i->lazy),
+           i->filename ? i->filename : "n/a",
+           pl = pa_proplist_to_string(i->proplist));
+
+    pa_xfree(pl);
 }
 
 static void get_autoload_info_callback(pa_context *c, const pa_autoload_info *i, int is_last, void *userdata) {
@@ -868,6 +889,10 @@ int main(int argc, char *argv[]) {
 
             if (argc > optind+2)
                 source_name = pa_xstrdup(argv[optind+1]);
+        } else if (!strcmp(argv[optind], "help")) {
+            help(bn);
+            ret = 0;
+            goto quit;
         }
     }
 

commit 07f5c1d8e433b5feb4f8b7a4307477e071234f1a
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Apr 11 17:05:46 2008 +0000

    register sink/source name as first step when creating a new sink/source so that we can hand the valid name string to the hook functions; se tup props for monitor sources correctly; fix implicit flag setting logic
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2260 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c
index 02f568e..7c1256f 100644
--- a/src/pulsecore/sink.c
+++ b/src/pulsecore/sink.c
@@ -118,9 +118,22 @@ pa_sink* pa_sink_new(
 
     pa_assert(core);
     pa_assert(data);
+    pa_assert(data->name);
 
-    if (pa_hook_fire(&core->hooks[PA_CORE_HOOK_SINK_NEW], data) < 0)
+    s = pa_msgobject_new(pa_sink);
+
+    if (!(name = pa_namereg_register(core, data->name, PA_NAMEREG_SINK, s, data->namereg_fail))) {
+        pa_xfree(s);
+        return NULL;
+    }
+
+    pa_sink_new_data_set_name(data, name);
+
+    if (pa_hook_fire(&core->hooks[PA_CORE_HOOK_SINK_NEW], data) < 0) {
+        pa_xfree(s);
+        pa_namereg_unregister(core, name);
         return NULL;
+    }
 
     pa_return_null_if_fail(!data->driver || pa_utf8_valid(data->driver));
     pa_return_null_if_fail(data->name && pa_utf8_valid(data->name) && data->name[0]);
@@ -142,13 +155,9 @@ pa_sink* pa_sink_new(
     if (!data->muted_is_set)
         data->muted = FALSE;
 
-    if (pa_hook_fire(&core->hooks[PA_CORE_HOOK_SINK_FIXATE], data) < 0)
-        return NULL;
-
-    s = pa_msgobject_new(pa_sink);
-
-    if (!(name = pa_namereg_register(core, data->name, PA_NAMEREG_SINK, s, data->namereg_fail))) {
+    if (pa_hook_fire(&core->hooks[PA_CORE_HOOK_SINK_FIXATE], data) < 0) {
         pa_xfree(s);
+        pa_namereg_unregister(core, name);
         return NULL;
     }
 
@@ -212,11 +221,12 @@ pa_sink* pa_sink_new(
     pa_source_new_data_set_channel_map(&source_data, &s->channel_map);
     source_data.name = pa_sprintf_malloc("%s.monitor", name);
     source_data.driver = data->driver;
+    source_data.module = data->module;
 
     d = pa_sprintf_malloc("Monitor Source of %s", s->name);
-    pa_proplist_sets(data->proplist, PA_PROP_DEVICE_DESCRIPTION, d);
+    pa_proplist_sets(source_data.proplist, PA_PROP_DEVICE_DESCRIPTION, d);
     pa_xfree(d);
-    pa_proplist_sets(data->proplist, PA_PROP_DEVICE_CLASS, "monitor");
+    pa_proplist_sets(source_data.proplist, PA_PROP_DEVICE_CLASS, "monitor");
 
     s->monitor_source = pa_source_new(core, &source_data, 0);
 
@@ -281,15 +291,8 @@ void pa_sink_put(pa_sink* s) {
 
     pa_assert(!s->min_latency || !s->max_latency || s->min_latency <= s->max_latency);
 
-    if (s->get_volume && s->set_volume)
-        s->flags |= PA_SINK_HW_VOLUME_CTRL;
-    else
-        s->flags = (s->flags & ~PA_SINK_HW_VOLUME_CTRL) | PA_SINK_DECIBEL_VOLUME;
-
-    if (s->get_mute && s->set_mute)
-        s->flags |= PA_SINK_HW_MUTE_CTRL;
-    else
-        s->flags &= ~PA_SINK_HW_MUTE_CTRL;
+    if (!(s->flags & PA_SINK_HW_VOLUME_CTRL))
+        s->flags |= PA_SINK_DECIBEL_VOLUME;
 
     pa_assert_se(sink_set_state(s, PA_SINK_IDLE) == 0);
 
diff --git a/src/pulsecore/source.c b/src/pulsecore/source.c
index 5a4b630..4f96332 100644
--- a/src/pulsecore/source.c
+++ b/src/pulsecore/source.c
@@ -110,8 +110,18 @@ pa_source* pa_source_new(
 
     pa_assert(core);
 
-    if (pa_hook_fire(&core->hooks[PA_CORE_HOOK_SOURCE_NEW], data) < 0)
+    s = pa_msgobject_new(pa_source);
+
+    if (!(name = pa_namereg_register(core, data->name, PA_NAMEREG_SOURCE, s, data->namereg_fail))) {
+        pa_xfree(s);
         return NULL;
+    }
+
+    if (pa_hook_fire(&core->hooks[PA_CORE_HOOK_SOURCE_NEW], data) < 0) {
+        pa_xfree(s);
+        pa_namereg_unregister(core, name);
+        return NULL;
+    }
 
     pa_return_null_if_fail(!data->driver || pa_utf8_valid(data->driver));
     pa_return_null_if_fail(data->name && pa_utf8_valid(data->name) && data->name[0]);
@@ -133,13 +143,9 @@ pa_source* pa_source_new(
     if (!data->muted_is_set)
         data->muted = FALSE;
 
-    if (pa_hook_fire(&core->hooks[PA_CORE_HOOK_SOURCE_FIXATE], data) < 0)
-        return NULL;
-
-    s = pa_msgobject_new(pa_source);
-
-    if (!(name = pa_namereg_register(core, data->name, PA_NAMEREG_SOURCE, s, data->namereg_fail))) {
+    if (pa_hook_fire(&core->hooks[PA_CORE_HOOK_SOURCE_FIXATE], data) < 0) {
         pa_xfree(s);
+        pa_namereg_unregister(core, name);
         return NULL;
     }
 
@@ -246,21 +252,8 @@ void pa_source_put(pa_source *s) {
 
     pa_assert(!s->min_latency || !s->max_latency || s->min_latency <= s->max_latency);
 
-    if (s->get_volume && s->set_volume)
-        s->flags |= PA_SOURCE_HW_VOLUME_CTRL;
-    else {
-        s->get_volume = NULL;
-        s->set_volume = NULL;
-        s->flags = (s->flags & ~PA_SOURCE_HW_VOLUME_CTRL) | PA_SOURCE_DECIBEL_VOLUME;
-    }
-
-    if (s->get_mute && s->set_mute)
-        s->flags |= PA_SOURCE_HW_MUTE_CTRL;
-    else {
-        s->get_mute = NULL;
-        s->set_mute = NULL;
-        s->flags &= ~PA_SOURCE_HW_MUTE_CTRL;
-    }
+    if (!(s->flags & PA_SOURCE_HW_VOLUME_CTRL))
+        s->flags |= PA_SOURCE_DECIBEL_VOLUME;
 
     pa_assert_se(source_set_state(s, PA_SOURCE_IDLE) == 0);
 

commit 55f273eb008cac7c2307057aa0ce85cf297b982c
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Apr 11 17:06:41 2008 +0000

    s/pulsecore\/gccmacro.h/pulse\/gccmacro.h/
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2261 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulse/channelmap.h b/src/pulse/channelmap.h
index 4122a31..00d3eb0 100644
--- a/src/pulse/channelmap.h
+++ b/src/pulse/channelmap.h
@@ -27,6 +27,7 @@
 
 #include <pulse/sample.h>
 #include <pulse/cdecl.h>
+#include <pulse/gccmacro.h>
 
 /** \page channelmap Channel Maps
  *
diff --git a/src/pulse/introspect.c b/src/pulse/introspect.c
index 9c50b57..49f9346 100644
--- a/src/pulse/introspect.c
+++ b/src/pulse/introspect.c
@@ -27,8 +27,8 @@
 #endif
 
 #include <pulse/context.h>
+#include <pulse/gccmacro.h>
 
-#include <pulsecore/gccmacro.h>
 #include <pulsecore/macro.h>
 #include <pulsecore/pstream-util.h>
 
diff --git a/src/pulse/mainloop-api.c b/src/pulse/mainloop-api.c
index b2ed343..dda5129 100644
--- a/src/pulse/mainloop-api.c
+++ b/src/pulse/mainloop-api.c
@@ -28,8 +28,8 @@
 #include <stdlib.h>
 
 #include <pulse/xmalloc.h>
+#include <pulse/gccmacro.h>
 
-#include <pulsecore/gccmacro.h>
 #include <pulsecore/macro.h>
 
 #include "mainloop-api.h"
@@ -75,4 +75,3 @@ void pa_mainloop_api_once(pa_mainloop_api* m, void (*callback)(pa_mainloop_api *
     pa_assert_se(e = m->defer_new(m, once_callback, i));
     m->defer_set_destroy(e, free_callback);
 }
-
diff --git a/src/pulse/mainloop-signal.c b/src/pulse/mainloop-signal.c
index e41ed14..8ad465b 100644
--- a/src/pulse/mainloop-signal.c
+++ b/src/pulse/mainloop-signal.c
@@ -39,11 +39,11 @@
 #endif
 
 #include <pulse/xmalloc.h>
+#include <pulse/gccmacro.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"
diff --git a/src/pulse/subscribe.c b/src/pulse/subscribe.c
index 580038c..db25f3c 100644
--- a/src/pulse/subscribe.c
+++ b/src/pulse/subscribe.c
@@ -27,7 +27,8 @@
 
 #include <stdio.h>
 
-#include <pulsecore/gccmacro.h>
+#include <pulse/gccmacro.h>
+
 #include <pulsecore/macro.h>
 #include <pulsecore/pstream-util.h>
 
diff --git a/src/pulse/utf8.h b/src/pulse/utf8.h
index 1e08047..840c74e 100644
--- a/src/pulse/utf8.h
+++ b/src/pulse/utf8.h
@@ -26,6 +26,7 @@
 ***/
 
 #include <pulse/cdecl.h>
+#include <pulse/gccmacro.h>
 
 /** \file
  * UTF8 Validation functions
diff --git a/src/pulse/util.h b/src/pulse/util.h
index 764678e..666ccce 100644
--- a/src/pulse/util.h
+++ b/src/pulse/util.h
@@ -28,6 +28,7 @@
 #include <stddef.h>
 
 #include <pulse/cdecl.h>
+#include <pulse/gccmacro.h>
 
 /** \file
  * Assorted utility functions */
diff --git a/src/pulse/xmalloc.c b/src/pulse/xmalloc.c
index 5348dda..2849097 100644
--- a/src/pulse/xmalloc.c
+++ b/src/pulse/xmalloc.c
@@ -30,8 +30,8 @@
 #include <unistd.h>
 #include <string.h>
 
+#include <pulse/gccmacro.h>
 #include <pulsecore/core-util.h>
-#include <pulsecore/gccmacro.h>
 #include <pulsecore/macro.h>
 
 #include "xmalloc.h"
diff --git a/src/pulsecore/client.c b/src/pulsecore/client.c
index 6a087d4..4eca4e2 100644
--- a/src/pulsecore/client.c
+++ b/src/pulsecore/client.c
@@ -35,6 +35,7 @@
 #include <pulsecore/core-subscribe.h>
 #include <pulsecore/log.h>
 #include <pulsecore/macro.h>
+#include <pulsecore/core-util.h>
 
 #include "client.h"
 
diff --git a/src/pulsecore/flist.h b/src/pulsecore/flist.h
index daf0fec..3d9a89a 100644
--- a/src/pulsecore/flist.h
+++ b/src/pulsecore/flist.h
@@ -25,9 +25,9 @@
 ***/
 
 #include <pulse/def.h>
+#include <pulse/gccmacro.h>
 
 #include <pulsecore/once.h>
-#include <pulsecore/gccmacro.h>
 
 /* A multiple-reader multipler-write lock-free free list implementation */
 
diff --git a/src/pulsecore/hook-list.h b/src/pulsecore/hook-list.h
index b3bd600..c288980 100644
--- a/src/pulsecore/hook-list.h
+++ b/src/pulsecore/hook-list.h
@@ -24,9 +24,10 @@
   USA.
 ***/
 
-#include <pulsecore/llist.h>
 #include <pulse/xmalloc.h>
-#include <pulsecore/gccmacro.h>
+#include <pulse/gccmacro.h>
+
+#include <pulsecore/llist.h>
 
 typedef struct pa_hook_slot pa_hook_slot;
 typedef struct pa_hook pa_hook;
diff --git a/src/pulsecore/log.h b/src/pulsecore/log.h
index b0711dc..765dd2e 100644
--- a/src/pulsecore/log.h
+++ b/src/pulsecore/log.h
@@ -27,7 +27,7 @@
 
 #include <stdarg.h>
 #include <stdlib.h>
-#include <pulsecore/gccmacro.h>
+#include <pulse/gccmacro.h>
 
 /* A simple logging subsystem */
 
diff --git a/src/pulsecore/play-memblockq.c b/src/pulsecore/play-memblockq.c
index bad60ae..3d435c8 100644
--- a/src/pulsecore/play-memblockq.c
+++ b/src/pulsecore/play-memblockq.c
@@ -30,9 +30,9 @@
 #include <string.h>
 
 #include <pulse/xmalloc.h>
+#include <pulse/gccmacro.h>
 
 #include <pulsecore/sink-input.h>
-#include <pulsecore/gccmacro.h>
 #include <pulsecore/thread-mq.h>
 #include <pulsecore/sample-util.h>
 
diff --git a/src/pulsecore/play-memchunk.c b/src/pulsecore/play-memchunk.c
index c528b1d..e4d24a9 100644
--- a/src/pulsecore/play-memchunk.c
+++ b/src/pulsecore/play-memchunk.c
@@ -30,9 +30,9 @@
 #include <string.h>
 
 #include <pulse/xmalloc.h>
+#include <pulse/gccmacro.h>
 
 #include <pulsecore/sink-input.h>
-#include <pulsecore/gccmacro.h>
 #include <pulsecore/thread-mq.h>
 #include <pulsecore/play-memblockq.h>
 
diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c
index ddd9980..2d0ba44 100644
--- a/src/pulsecore/sink-input.c
+++ b/src/pulsecore/sink-input.c
@@ -38,6 +38,7 @@
 #include <pulsecore/log.h>
 #include <pulsecore/play-memblockq.h>
 #include <pulsecore/namereg.h>
+#include <pulsecore/core-util.h>
 
 #include "sink-input.h"
 
diff --git a/src/pulsecore/source-output.c b/src/pulsecore/source-output.c
index cf576ac..c0cbb42 100644
--- a/src/pulsecore/source-output.c
+++ b/src/pulsecore/source-output.c
@@ -36,6 +36,7 @@
 #include <pulsecore/core-subscribe.h>
 #include <pulsecore/log.h>
 #include <pulsecore/namereg.h>
+#include <pulsecore/core-util.h>
 
 #include "source-output.h"
 
diff --git a/src/pulsecore/strbuf.h b/src/pulsecore/strbuf.h
index 1c0850b..d3555a2 100644
--- a/src/pulsecore/strbuf.h
+++ b/src/pulsecore/strbuf.h
@@ -24,7 +24,7 @@
   USA.
 ***/
 
-#include <pulsecore/gccmacro.h>
+#include <pulse/gccmacro.h>
 
 typedef struct pa_strbuf pa_strbuf;
 
diff --git a/src/pulsecore/tokenizer.c b/src/pulsecore/tokenizer.c
index f79c19c..cf5da64 100644
--- a/src/pulsecore/tokenizer.c
+++ b/src/pulsecore/tokenizer.c
@@ -29,9 +29,9 @@
 #include <stdlib.h>
 
 #include <pulse/xmalloc.h>
+#include <pulse/gccmacro.h>
 
 #include <pulsecore/dynarray.h>
-#include <pulsecore/gccmacro.h>
 #include <pulsecore/macro.h>
 
 #include "tokenizer.h"
diff --git a/src/utils/padsp.c b/src/utils/padsp.c
index d3f034d..6ab022e 100644
--- a/src/utils/padsp.c
+++ b/src/utils/padsp.c
@@ -53,8 +53,8 @@
 #endif
 
 #include <pulse/pulseaudio.h>
+#include <pulse/gccmacro.h>
 #include <pulsecore/llist.h>
-#include <pulsecore/gccmacro.h>
 
 /* On some systems SIOCINQ isn't defined, but FIONREAD is just an alias */
 #if !defined(SIOCINQ) && defined(FIONREAD)

commit 14fd32ee4b20d9c3e50896f52c7e7b22e72db868
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Apr 11 17:39:38 2008 +0000

    add missing 'break's in switch
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2262 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/tagstruct.c b/src/pulsecore/tagstruct.c
index fb412a4..7616cd1 100644
--- a/src/pulsecore/tagstruct.c
+++ b/src/pulsecore/tagstruct.c
@@ -667,6 +667,7 @@ void pa_tagstruct_put(pa_tagstruct *t, ...) {
 
             case PA_TAG_PROPLIST:
                 pa_tagstruct_put_proplist(t, va_arg(va, pa_proplist *));
+                break;
 
             default:
                 pa_assert_not_reached();
@@ -741,6 +742,7 @@ int pa_tagstruct_get(pa_tagstruct *t, ...) {
 
             case PA_TAG_PROPLIST:
                 ret = pa_tagstruct_get_proplist(t, va_arg(va, pa_proplist *));
+                break;
 
             default:
                 pa_assert_not_reached();

commit 04178d428e5f687849e00d8a38ba206003fdcfed
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Apr 14 18:43:11 2008 +0000

    add _cb suffix to _max_rewind function like with all other functions, too
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2264 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/sound-file-stream.c b/src/pulsecore/sound-file-stream.c
index 5c8400d..7e0f8ef 100644
--- a/src/pulsecore/sound-file-stream.c
+++ b/src/pulsecore/sound-file-stream.c
@@ -212,7 +212,7 @@ static void sink_input_rewind_cb(pa_sink_input *i, size_t nbytes) {
     pa_memblockq_rewind(u->memblockq, nbytes);
 }
 
-static void sink_input_set_max_rewind(pa_sink_input *i, size_t nbytes) {
+static void sink_input_set_max_rewind_cb(pa_sink_input *i, size_t nbytes) {
     file_stream *u;
 
     pa_sink_input_assert_ref(i);
@@ -332,7 +332,7 @@ int pa_play_file(
 
     u->sink_input->pop = sink_input_pop_cb;
     u->sink_input->rewind = sink_input_rewind_cb;
-    u->sink_input->set_max_rewind = sink_input_set_max_rewind;
+    u->sink_input->set_max_rewind = sink_input_set_max_rewind_cb;
     u->sink_input->kill = sink_input_kill_cb;
     u->sink_input->userdata = u;
 

commit 6946d2ad2d905870bcbf98defc22c34ab6f21bd6
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Apr 14 18:43:59 2008 +0000

    make sure to clear all queued RT signals before arm a new timer
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2265 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/rtpoll.c b/src/pulsecore/rtpoll.c
index afcd7e5..bd1c43a 100644
--- a/src/pulsecore/rtpoll.c
+++ b/src/pulsecore/rtpoll.c
@@ -462,9 +462,22 @@ static void update_timer(pa_rtpoll *p) {
 
         if (p->timer != (timer_t) -1) {
             struct itimerspec its;
+            struct timespec ts = { .tv_sec = 0, .tv_nsec = 0 };
+            sigset_t ss;
+
+            /* First disarm timer */
             memset(&its, 0, sizeof(its));
+            pa_assert_se(timer_settime(p->timer, TIMER_ABSTIME, &its, NULL) == 0);
+
+            /* Remove a signal that might be waiting in the signal q */
+            pa_assert_se(sigemptyset(&ss) == 0);
+            pa_assert_se(sigaddset(&ss, p->rtsig) == 0);
+            sigtimedwait(&ss, NULL, &ts);
 
+            /* And install the new timer */
             if (p->timer_enabled) {
+                memset(&its, 0, sizeof(its));
+
                 its.it_value.tv_sec = p->next_elapse.tv_sec;
                 its.it_value.tv_nsec = p->next_elapse.tv_usec*1000;
 
@@ -472,9 +485,8 @@ static void update_timer(pa_rtpoll *p) {
                  * "disarming" */
                 if (its.it_value.tv_sec == 0 && its.it_value.tv_nsec == 0)
                     its.it_value.tv_nsec = 1;
+                pa_assert_se(timer_settime(p->timer, TIMER_ABSTIME, &its, NULL) == 0);
             }
-
-            pa_assert_se(timer_settime(p->timer, TIMER_ABSTIME, &its, NULL) == 0);
         }
 
 #ifdef __linux__

commit 68e4a93705117e14e28fa919873a239e907c73d8
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Apr 14 18:45:08 2008 +0000

    properly ask the sink to rewind on new sink inputs and when they disappear
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2266 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c
index 7c1256f..6dcc7ab 100644
--- a/src/pulsecore/sink.c
+++ b/src/pulsecore/sink.c
@@ -973,8 +973,8 @@ int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offse
 
             pa_sink_invalidate_requested_latency(s);
 
-/*             i->thread_info.ignore_rewind = TRUE; */
-/*             pa_sink_request_rewind(s, 0); */
+            i->thread_info.ignore_rewind = TRUE;
+            pa_sink_request_rewind(s, 0);
 
             return 0;
         }
@@ -1014,7 +1014,7 @@ int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offse
 
             pa_sink_invalidate_requested_latency(s);
 
-/*             pa_sink_request_rewind(s, 0); */
+            pa_sink_request_rewind(s, 0);
 
             return 0;
         }

commit 1f0a52dad1515e4aa7c9f45541faaa03a88aa13a
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Apr 14 18:46:24 2008 +0000

    the pointer to rewind() may actually be NULL
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2267 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c
index 2d0ba44..01e3bd9 100644
--- a/src/pulsecore/sink-input.c
+++ b/src/pulsecore/sink-input.c
@@ -399,7 +399,6 @@ void pa_sink_input_put(pa_sink_input *i) {
 
     pa_assert(i->state == PA_SINK_INPUT_INIT);
     pa_assert(i->pop);
-    pa_assert(i->rewind);
 
     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;
@@ -611,7 +610,7 @@ void pa_sink_input_rewind(pa_sink_input *i, size_t nbytes /* in sink sample spec
     pa_assert(PA_SINK_INPUT_LINKED(i->thread_info.state));
     pa_assert(pa_frame_aligned(nbytes, &i->sink->sample_spec));
 
-    pa_log_debug("rewind(%u, %u)", nbytes, i->thread_info.rewrite_nbytes);
+    pa_log_debug("rewind(%lu, %lu)", (unsigned long) nbytes, (unsigned long) i->thread_info.rewrite_nbytes);
 
     if (i->thread_info.state == PA_SINK_INPUT_CORKED)
         return;
@@ -623,7 +622,7 @@ void pa_sink_input_rewind(pa_sink_input *i, size_t nbytes /* in sink sample spec
     }
 
     if (nbytes > 0)
-        pa_log_debug("Have to rewind %u bytes.", nbytes);
+        pa_log_debug("Have to rewind %lu bytes.", (unsigned long) nbytes);
 
     if (i->thread_info.rewrite_nbytes > 0) {
         size_t max_rewrite;
diff --git a/src/pulsecore/sink-input.h b/src/pulsecore/sink-input.h
index 62464ca..8545dea 100644
--- a/src/pulsecore/sink-input.h
+++ b/src/pulsecore/sink-input.h
@@ -103,7 +103,7 @@ struct pa_sink_input {
      * before peek() if it is called at all. Only called if the sink
      * input driver ever plans to call
      * pa_sink_input_request_rewrite(). Called from IO context. */
-    void (*rewind) (pa_sink_input *i, size_t nbytes);
+    void (*rewind) (pa_sink_input *i, size_t nbytes);     /* may be NULL */
 
     /* Called whenever the maximum rewindable size of the sink
      * changes. Called from UI context. */

commit c9d01592d4aa57f955456a675ebb2281ac5850e1
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Apr 17 16:24:26 2008 +0000

    define PA_xxxSEC_PER_yyySEC for usec, too
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2268 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulse/timeval.h b/src/pulse/timeval.h
index 315f419..09d5397 100644
--- a/src/pulse/timeval.h
+++ b/src/pulse/timeval.h
@@ -38,6 +38,8 @@ PA_C_DECL_BEGIN
 #define PA_USEC_PER_SEC 1000000
 #define PA_NSEC_PER_SEC 1000000000
 #define PA_USEC_PER_MSEC 1000
+#define PA_NSEC_PER_MSEC 1000000
+#define PA_NSEC_PER_USEC 1000
 
 struct timeval;
 

commit 22ceb15bae3251b95fb89c7f2451f3004f62c02f
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Apr 17 16:28:23 2008 +0000

    add new rtstutter tool which can be used generate artifical scheduling latencies in the OS to trigger buffer underrun events in your software. it's an awesome debug tool for glitch-free; also move test programs from automake's check_ back to noinst_ to make sure it is built everytime Lennart presses F9 in his emacs
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2269 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/Makefile.am b/src/Makefile.am
index 7139d14..45e3de7 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -226,7 +226,7 @@ pabrowse_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS)
 #         Test programs           #
 ###################################
 
-check_PROGRAMS = \
+noinst_PROGRAMS = \
 		mainloop-test \
 		mcalign-test \
 		pacat-simple \
@@ -255,16 +255,17 @@ check_PROGRAMS = \
 		mix-test \
 		remix-test \
 		envelope-test \
-		proplist-test
+		proplist-test \
+		rtstutter
 
 if HAVE_SIGXCPU
-check_PROGRAMS += \
+noinst_PROGRAMS += \
 		cpulimit-test \
 		cpulimit-test2
 endif
 
 if HAVE_GLIB20
-check_PROGRAMS += \
+noinst_PROGRAMS += \
 		mainloop-test-glib
 endif
 
@@ -426,10 +427,15 @@ envelope_test_CFLAGS = $(AM_CFLAGS) $(LIBOIL_CFLAGS)
 envelope_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) $(LIBOIL_LIBS)
 
 proplist_test_SOURCES = tests/proplist-test.c
-proplist_test_LDADD = $(AM_LDADD) libpulse.la
+proplist_test_LDADD = $(AM_LDADD) libpulsecore.la
 proplist_test_CFLAGS = $(AM_CFLAGS) $(LIBOIL_CFLAGS)
 proplist_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) $(LIBOIL_LIBS)
 
+rtstutter_SOURCES = tests/rtstutter.c
+rtstutter_LDADD = $(AM_LDADD) libpulsecore.la
+rtstutter_CFLAGS = $(AM_CFLAGS) $(LIBOIL_CFLAGS)
+rtstutter_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) $(LIBOIL_LIBS)
+
 ###################################
 #         Client library          #
 ###################################
diff --git a/src/tests/rtstutter.c b/src/tests/rtstutter.c
new file mode 100644
index 0000000..a7d1b04
--- /dev/null
+++ b/src/tests/rtstutter.c
@@ -0,0 +1,107 @@
+/* $Id$ */
+
+/***
+  This file is part of PulseAudio.
+
+  Copyright 2008 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 <stdlib.h>
+#include <unistd.h>
+#include <time.h>
+#include <sched.h>
+#include <inttypes.h>
+#include <string.h>
+#include <pthread.h>
+
+#include <pulse/timeval.h>
+#include <pulse/gccmacro.h>
+
+#include <pulsecore/log.h>
+#include <pulsecore/macro.h>
+
+static int msec;
+
+static void* work(void *p) PA_GCC_NORETURN;
+
+static void* work(void *p) {
+    cpu_set_t mask;
+    struct sched_param param;
+
+    pa_log_notice("CPU%i: Created thread.", PA_PTR_TO_INT(p));
+
+    memset(&param, 0, sizeof(param));
+    param.sched_priority = 12;
+    pa_assert_se(pthread_setschedparam(pthread_self(), SCHED_FIFO, &param) == 0);
+
+    CPU_ZERO(&mask);
+    CPU_SET(PA_PTR_TO_INT(p), &mask);
+    pa_assert_se(pthread_setaffinity_np(pthread_self(), sizeof(mask), &mask) == 0);
+
+    for (;;) {
+        struct timespec now, end;
+        uint64_t nsec;
+
+        pa_log_notice("CPU%i: Sleeping for 1s", PA_PTR_TO_INT(p));
+        sleep(1);
+
+        pa_assert_se(clock_gettime(CLOCK_REALTIME, &end) == 0);
+
+        nsec = (uint64_t) ((((double) rand())*msec*PA_NSEC_PER_MSEC)/RAND_MAX);
+
+        pa_log_notice("CPU%i: Freezing for %ims", PA_PTR_TO_INT(p), (int) (nsec/PA_NSEC_PER_MSEC));
+
+        end.tv_sec += nsec / PA_NSEC_PER_SEC;
+        end.tv_nsec += nsec % PA_NSEC_PER_SEC;
+
+        while (end.tv_nsec > PA_NSEC_PER_SEC) {
+            end.tv_sec++;
+            end.tv_nsec -= PA_NSEC_PER_SEC;
+        }
+
+        do {
+            pa_assert_se(clock_gettime(CLOCK_REALTIME, &now) == 0);
+        } while (now.tv_sec < end.tv_sec ||
+                 (now.tv_sec == end.tv_sec && now.tv_nsec < end.tv_nsec));
+    }
+}
+
+int main(int argc, char*argv[]) {
+    int n;
+
+    srand(time(NULL));
+
+    msec = argc > 1 ? atoi(argv[1]) : 1000;
+
+    pa_assert(msec > 0);
+
+    pa_log_notice("Creating random latencies of up to %ims.", msec);
+
+    for (n = 1; n < sysconf(_SC_NPROCESSORS_CONF); n++) {
+        pthread_t t;
+        pa_assert_se(pthread_create(&t, NULL, work, PA_INT_TO_PTR(n)) == 0);
+    }
+
+    work(PA_INT_TO_PTR(0));
+
+    return 0;
+}

commit 144b237d863030819bd9309148a1a264e31a4628
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sun Apr 20 19:38:33 2008 +0000

    print a message on xrun
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2270 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/utils/pacat.c b/src/utils/pacat.c
index e309213..c05bff7 100644
--- a/src/utils/pacat.c
+++ b/src/utils/pacat.c
@@ -212,6 +212,18 @@ static void stream_suspended_callback(pa_stream *s, void *userdata) {
     }
 }
 
+static void stream_underflow_callback(pa_stream *s, void *userdata) {
+    assert(s);
+
+    fprintf(stderr, "Underrun.\n");
+}
+
+static void stream_overflow_callback(pa_stream *s, void *userdata) {
+    assert(s);
+
+    fprintf(stderr, "Overrun.\n");
+}
+
 static void stream_moved_callback(pa_stream *s, void *userdata) {
     assert(s);
 
@@ -249,6 +261,8 @@ static void context_state_callback(pa_context *c, void *userdata) {
             pa_stream_set_read_callback(stream, stream_read_callback, NULL);
             pa_stream_set_suspended_callback(stream, stream_suspended_callback, NULL);
             pa_stream_set_moved_callback(stream, stream_moved_callback, NULL);
+            pa_stream_set_underflow_callback(stream, stream_underflow_callback, NULL);
+            pa_stream_set_overflow_callback(stream, stream_overflow_callback, NULL);
 
             if (latency > 0) {
                 memset(&buffer_attr, 0, sizeof(buffer_attr));
@@ -416,14 +430,14 @@ static void exit_signal_callback(pa_mainloop_api*m, pa_signal_event *e, int sig,
 
 /* Show the current latency */
 static void stream_update_timing_callback(pa_stream *s, int success, void *userdata) {
-    pa_usec_t latency, usec;
+    pa_usec_t l, usec;
     int negative = 0;
 
     assert(s);
 
     if (!success ||
         pa_stream_get_time(s, &usec) < 0 ||
-        pa_stream_get_latency(s, &latency, &negative) < 0) {
+        pa_stream_get_latency(s, &l, &negative) < 0) {
         fprintf(stderr, "Failed to get latency: %s\n", pa_strerror(pa_context_errno(context)));
         quit(1);
         return;
@@ -431,7 +445,7 @@ static void stream_update_timing_callback(pa_stream *s, int success, void *userd
 
     fprintf(stderr, "Time: %0.3f sec; Latency: %0.0f usec.  \r",
             (float) usec / 1000000,
-            (float) latency * (negative?-1:1));
+            (float) l * (negative?-1:1));
 }
 
 /* Someone requested that the latency is shown */

commit 4b1d684d261c52ad6ed83f1d8efdaff7105ba324
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sun Apr 20 19:40:30 2008 +0000

    add new API function pa_memchunk_memcpy()
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2271 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/memchunk.c b/src/pulsecore/memchunk.c
index 4e73b63..16a9c14 100644
--- a/src/pulsecore/memchunk.c
+++ b/src/pulsecore/memchunk.c
@@ -90,3 +90,23 @@ pa_memchunk *pa_memchunk_will_need(const pa_memchunk *c) {
 
     return (pa_memchunk*) c;
 }
+
+pa_memchunk* pa_memchunk_memcpy(pa_memchunk *dst, pa_memchunk *src) {
+    void *p, *q;
+
+    pa_assert(dst);
+    pa_assert(src);
+    pa_assert(dst->length == src->length);
+
+    p = pa_memblock_acquire(dst->memblock);
+    q = pa_memblock_acquire(src->memblock);
+
+    memmove((uint8_t*) p + dst->index,
+            (uint8_t*) q + src->index,
+            dst->length);
+
+    pa_memblock_release(dst->memblock);
+    pa_memblock_release(src->memblock);
+
+    return dst;
+}
diff --git a/src/pulsecore/memchunk.h b/src/pulsecore/memchunk.h
index e6105ac..46a8240 100644
--- a/src/pulsecore/memchunk.h
+++ b/src/pulsecore/memchunk.h
@@ -49,4 +49,7 @@ 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);
 
+/* Copy the data in the src memchunk to the dst memchunk */
+pa_memchunk* pa_memchunk_memcpy(pa_memchunk *dst, pa_memchunk *src);
+
 #endif

commit 1ddb95a4ce337d6fbe113655437b64c293318d5f
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sun Apr 20 19:41:26 2008 +0000

    add new silence memblock caching subsystem
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2272 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/sample-util.c b/src/pulsecore/sample-util.c
index 4a532f2..bf1f7c2 100644
--- a/src/pulsecore/sample-util.c
+++ b/src/pulsecore/sample-util.c
@@ -42,28 +42,6 @@
 
 #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) {
-    pa_memblock *b;
-
-    pa_assert(pool);
-    pa_assert(spec);
-
-    if (length <= 0)
-        length = PA_MIN(pa_bytes_per_second(spec)/20, /* 50 ms */
-                        pa_mempool_block_size_max(pool));
-
-    if (length > PA_SILENCE_MAX)
-        length = PA_SILENCE_MAX;
-
-    length = pa_frame_align(length, spec);
-
-    b = pa_silence_memblock(pa_memblock_new(pool, length), spec);
-
-    pa_memblock_set_is_silence(b, TRUE);
-
-    return b;
-}
-
 pa_memblock *pa_silence_memblock(pa_memblock* b, const pa_sample_spec *spec) {
     void *data;
 
@@ -77,7 +55,7 @@ pa_memblock *pa_silence_memblock(pa_memblock* b, const pa_sample_spec *spec) {
     return b;
 }
 
-void pa_silence_memchunk(pa_memchunk *c, const pa_sample_spec *spec) {
+pa_memchunk* pa_silence_memchunk(pa_memchunk *c, const pa_sample_spec *spec) {
     void *data;
 
     pa_assert(c);
@@ -87,37 +65,38 @@ void pa_silence_memchunk(pa_memchunk *c, const pa_sample_spec *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;
-    pa_assert(p);
-    pa_assert(length > 0);
-    pa_assert(spec);
+    return c;
+}
 
-    switch (spec->format) {
+static uint8_t silence_byte(pa_sample_format_t format) {
+    switch (format) {
         case PA_SAMPLE_U8:
-            c = 0x80;
-            break;
+            return 0x80;
         case PA_SAMPLE_S16LE:
         case PA_SAMPLE_S16BE:
         case PA_SAMPLE_S32LE:
         case PA_SAMPLE_S32BE:
-        case PA_SAMPLE_FLOAT32:
-        case PA_SAMPLE_FLOAT32RE:
-            c = 0;
-            break;
+        case PA_SAMPLE_FLOAT32LE:
+        case PA_SAMPLE_FLOAT32BE:
+            return 0;
         case PA_SAMPLE_ALAW:
-            c = 0xd5;
-            break;
+            return 0xd5;
         case PA_SAMPLE_ULAW:
-            c = 0xff;
-            break;
+            return 0xff;
         default:
             pa_assert_not_reached();
     }
+    return 0;
+}
 
-    memset(p, c, length);
+void* pa_silence_memory(void *p, size_t length, const pa_sample_spec *spec) {
+    pa_assert(p);
+    pa_assert(length > 0);
+    pa_assert(spec);
+
+    memset(p, silence_byte(spec->format), length);
+    return p;
 }
 
 static void calc_linear_integer_stream_volumes(pa_mix_info streams[], unsigned nstreams, const pa_sample_spec *spec) {
@@ -934,3 +913,90 @@ void pa_deinterleave(const void *src, void *dst[], unsigned channels, size_t ss,
         }
     }
 }
+
+static pa_memblock *silence_memblock_new(pa_mempool *pool, uint8_t c) {
+    pa_memblock *b;
+    size_t length;
+    void *data;
+
+    pa_assert(pool);
+
+    length = PA_MIN(pa_mempool_block_size_max(pool), PA_SILENCE_MAX);
+
+    b = pa_memblock_new(pool, length);
+
+    data = pa_memblock_acquire(b);
+    memset(data, c, length);
+    pa_memblock_release(b);
+
+    pa_memblock_set_is_silence(b, TRUE);
+
+    return b;
+}
+
+void pa_silence_cache_init(pa_silence_cache *cache) {
+    pa_assert(cache);
+
+    memset(cache, 0, sizeof(pa_silence_cache));
+}
+
+void pa_silence_cache_done(pa_silence_cache *cache) {
+    pa_sample_format_t f;
+    pa_assert(cache);
+
+    for (f = 0; f < PA_SAMPLE_MAX; f++)
+        if (cache->blocks[f])
+            pa_memblock_unref(cache->blocks[f]);
+
+    memset(cache, 0, sizeof(pa_silence_cache));
+}
+
+pa_memchunk* pa_silence_memchunk_get(pa_silence_cache *cache, pa_mempool *pool, pa_memchunk* ret, const pa_sample_spec *spec, size_t length) {
+    pa_memblock *b;
+    size_t l;
+
+    pa_assert(cache);
+    pa_assert(pa_sample_spec_valid(spec));
+
+    if (!(b = cache->blocks[spec->format]))
+
+        switch (spec->format) {
+            case PA_SAMPLE_U8:
+                cache->blocks[PA_SAMPLE_U8] = b = silence_memblock_new(pool, 0x80);
+                break;
+            case PA_SAMPLE_S16LE:
+            case PA_SAMPLE_S16BE:
+            case PA_SAMPLE_S32LE:
+            case PA_SAMPLE_S32BE:
+            case PA_SAMPLE_FLOAT32LE:
+            case PA_SAMPLE_FLOAT32BE:
+                cache->blocks[PA_SAMPLE_S16LE] = b = silence_memblock_new(pool, 0);
+                cache->blocks[PA_SAMPLE_S16BE] = pa_memblock_ref(b);
+                cache->blocks[PA_SAMPLE_S32LE] = pa_memblock_ref(b);
+                cache->blocks[PA_SAMPLE_S32BE] = pa_memblock_ref(b);
+                cache->blocks[PA_SAMPLE_FLOAT32LE] = pa_memblock_ref(b);
+                cache->blocks[PA_SAMPLE_FLOAT32BE] = pa_memblock_ref(b);
+                break;
+            case PA_SAMPLE_ALAW:
+                cache->blocks[PA_SAMPLE_ALAW] = b = silence_memblock_new(pool, 0xd5);
+                break;
+            case PA_SAMPLE_ULAW:
+                cache->blocks[PA_SAMPLE_ULAW] = b = silence_memblock_new(pool, 0xff);
+                break;
+            default:
+                pa_assert_not_reached();
+    }
+
+    pa_assert(b);
+
+    ret->memblock = pa_memblock_ref(b);
+
+    l = pa_memblock_get_length(b);
+    if (length > l || length == 0)
+        length = l;
+
+    ret->length = pa_frame_align(length, spec);
+    ret->index = 0;
+
+    return ret;
+}
diff --git a/src/pulsecore/sample-util.h b/src/pulsecore/sample-util.h
index 2ef8f92..45f0088 100644
--- a/src/pulsecore/sample-util.h
+++ b/src/pulsecore/sample-util.h
@@ -30,10 +30,18 @@
 #include <pulsecore/memblock.h>
 #include <pulsecore/memchunk.h>
 
-pa_memblock *pa_silence_memblock(pa_memblock* b, const pa_sample_spec *spec);
-pa_memblock *pa_silence_memblock_new(pa_mempool *pool, const pa_sample_spec *spec, size_t length);
-void pa_silence_memchunk(pa_memchunk *c, const pa_sample_spec *spec);
-void pa_silence_memory(void *p, size_t length, const pa_sample_spec *spec);
+typedef struct pa_silence_cache {
+    pa_memblock* blocks[PA_SAMPLE_MAX];
+} pa_silence_cache;
+
+void pa_silence_cache_init(pa_silence_cache *cache);
+void pa_silence_cache_done(pa_silence_cache *cache);
+
+void *pa_silence_memory(void *p, size_t length, const pa_sample_spec *spec);
+pa_memchunk* pa_silence_memchunk(pa_memchunk *c, const pa_sample_spec *spec);
+pa_memblock* pa_silence_memblock(pa_memblock *b, const pa_sample_spec *spec);
+
+pa_memchunk* pa_silence_memchunk_get(pa_silence_cache *cache, pa_mempool *pool, pa_memchunk* ret, const pa_sample_spec *spec, size_t length);
 
 typedef struct pa_mix_info {
     pa_memchunk chunk;

commit bee409acbe575b78559c82d6904ebcf63ddc885f
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sun Apr 20 19:41:53 2008 +0000

    remove debug messages
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2273 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/time-smoother.c b/src/pulsecore/time-smoother.c
index b44aaa5..b3f8edc 100644
--- a/src/pulsecore/time-smoother.c
+++ b/src/pulsecore/time-smoother.c
@@ -333,7 +333,7 @@ void pa_smoother_put(pa_smoother *s, pa_usec_t x, pa_usec_t y) {
 
     s->abc_valid = FALSE;
 
-    pa_log_debug("put(%llu | %llu) = %llu", x + s->time_offset, x, y);
+/*     pa_log_debug("put(%llu | %llu) = %llu", (unsigned long long)  (x + s->time_offset), (unsigned long long) x, (unsigned long long) y); */
 }
 
 pa_usec_t pa_smoother_get(pa_smoother *s, pa_usec_t x) {
@@ -353,7 +353,7 @@ pa_usec_t pa_smoother_get(pa_smoother *s, pa_usec_t x) {
 
     estimate(s, x, &y, NULL);
 
-    pa_log_debug("get(%llu | %llu) = %llu", x + s->time_offset, x, y);
+/*     pa_log_debug("get(%llu | %llu) = %llu", (unsigned long long) (x + s->time_offset), (unsigned long long) x, (unsigned long long) y); */
 
     return y;
 }
@@ -363,7 +363,7 @@ void pa_smoother_set_time_offset(pa_smoother *s, pa_usec_t offset) {
 
     s->time_offset = offset;
 
-    pa_log_debug("offset(%llu)", offset);
+/*     pa_log_debug("offset(%llu)", (unsigned long long) offset); */
 }
 
 void pa_smoother_pause(pa_smoother *s, pa_usec_t x) {
@@ -372,7 +372,7 @@ void pa_smoother_pause(pa_smoother *s, pa_usec_t x) {
     if (s->paused)
         return;
 
-    pa_log_debug("pause(%llu)", x);
+/*     pa_log_debug("pause(%llu)", (unsigned long long)  x); */
 
     s->paused = TRUE;
     s->pause_time = x;
@@ -386,7 +386,7 @@ void pa_smoother_resume(pa_smoother *s, pa_usec_t x) {
 
     pa_assert(x >= s->pause_time);
 
-    pa_log_debug("resume(%llu)", x);
+/*     pa_log_debug("resume(%llu)", (unsigned long long) x); */
 
     s->paused = FALSE;
     s->time_offset += x - s->pause_time;
@@ -410,7 +410,7 @@ pa_usec_t pa_smoother_translate(pa_smoother *s, pa_usec_t x, pa_usec_t y_delay)
 
     estimate(s, x, &ney, &nde);
 
-    pa_log_debug("translate(%llu) = %llu (%0.2f)", (unsigned long long) y_delay, (unsigned long long) ((double) y_delay / s->dp), s->dp);
+/*     pa_log_debug("translate(%llu) = %llu (%0.2f)", (unsigned long long) y_delay, (unsigned long long) ((double) y_delay / s->dp), s->dp); */
 
     return (pa_usec_t) ((double) y_delay / s->dp);
 }

commit 687aa295a78187069ec7b44eb3ec2e6ed12106f6
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sun Apr 20 19:43:20 2008 +0000

    add new pa_pstream_get_shm() API, rename pa_pstream_use_shm() to pa_pstream_enable_shm(); pa_bool_t-ization
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2274 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/pstream.c b/src/pulsecore/pstream.c
index 97ac2b0..5004d67 100644
--- a/src/pulsecore/pstream.c
+++ b/src/pulsecore/pstream.c
@@ -98,7 +98,7 @@ struct item_info {
     /* packet info */
     pa_packet *packet;
 #ifdef HAVE_CREDS
-    int with_creds;
+    pa_bool_t with_creds;
     pa_creds creds;
 #endif
 
@@ -121,7 +121,7 @@ struct pa_pstream {
 
     pa_queue *send_queue;
 
-    int dead;
+    pa_bool_t dead;
 
     struct {
         pa_pstream_descriptor descriptor;
@@ -141,7 +141,7 @@ struct pa_pstream {
         size_t index;
     } read;
 
-    int use_shm;
+    pa_bool_t use_shm;
     pa_memimport *import;
     pa_memexport *export;
 
@@ -167,7 +167,7 @@ struct pa_pstream {
 
 #ifdef HAVE_CREDS
     pa_creds read_creds, write_creds;
-    int read_creds_valid, send_creds_now;
+    pa_bool_t read_creds_valid, send_creds_now;
 #endif
 };
 
@@ -239,7 +239,7 @@ pa_pstream *pa_pstream_new(pa_mainloop_api *m, pa_iochannel *io, pa_mempool *poo
     PA_REFCNT_INIT(p);
     p->io = io;
     pa_iochannel_set_callback(io, io_callback, p);
-    p->dead = 0;
+    p->dead = FALSE;
 
     p->mainloop = m;
     p->defer_event = m->defer_new(m, defer_callback, p);
@@ -269,18 +269,18 @@ pa_pstream *pa_pstream_new(pa_mainloop_api *m, pa_iochannel *io, pa_mempool *poo
 
     p->mempool = pool;
 
-    p->use_shm = 0;
+    p->use_shm = FALSE;
     p->export = NULL;
 
     /* We do importing unconditionally */
     p->import = pa_memimport_new(p->mempool, memimport_release_cb, p);
 
-    pa_iochannel_socket_set_rcvbuf(io, 1024*8);
-    pa_iochannel_socket_set_sndbuf(io, 1024*8);
+    pa_iochannel_socket_set_rcvbuf(io, pa_mempool_block_size_max(p->mempool));
+    pa_iochannel_socket_set_sndbuf(io, pa_mempool_block_size_max(p->mempool));
 
 #ifdef HAVE_CREDS
-    p->send_creds_now = 0;
-    p->read_creds_valid = 0;
+    p->send_creds_now = FALSE;
+    p->read_creds_valid = FALSE;
 #endif
     return p;
 }
@@ -383,7 +383,7 @@ void pa_pstream_send_memblock(pa_pstream*p, uint32_t channel, int64_t offset, pa
         i->offset = offset;
         i->seek_mode = seek_mode;
 #ifdef HAVE_CREDS
-        i->with_creds = 0;
+        i->with_creds = FALSE;
 #endif
 
         pa_queue_push(p->send_queue, i);
@@ -410,7 +410,7 @@ void pa_pstream_send_release(pa_pstream *p, uint32_t block_id) {
     item->type = PA_PSTREAM_ITEM_SHMRELEASE;
     item->block_id = block_id;
 #ifdef HAVE_CREDS
-    item->with_creds = 0;
+    item->with_creds = FALSE;
 #endif
 
     pa_queue_push(p->send_queue, item);
@@ -447,7 +447,7 @@ void pa_pstream_send_revoke(pa_pstream *p, uint32_t block_id) {
     item->type = PA_PSTREAM_ITEM_SHMREVOKE;
     item->block_id = block_id;
 #ifdef HAVE_CREDS
-    item->with_creds = 0;
+    item->with_creds = FALSE;
 #endif
 
     pa_queue_push(p->send_queue, item);
@@ -504,7 +504,7 @@ static void prepare_next_write_item(pa_pstream *p) {
 
     } else {
         uint32_t flags;
-        int send_payload = 1;
+        pa_bool_t send_payload = TRUE;
 
         pa_assert(p->write.current->type == PA_PSTREAM_ITEM_MEMBLOCK);
         pa_assert(p->write.current->chunk.memblock);
@@ -529,7 +529,7 @@ static void prepare_next_write_item(pa_pstream *p) {
                                  &length) >= 0) {
 
                 flags |= PA_FLAG_SHMDATA;
-                send_payload = 0;
+                send_payload = FALSE;
 
                 p->write.shm_info[PA_PSTREAM_SHM_BLOCKID] = htonl(block_id);
                 p->write.shm_info[PA_PSTREAM_SHM_SHMID] = htonl(shm_id);
@@ -599,7 +599,7 @@ static int do_write(pa_pstream *p) {
         if ((r = pa_iochannel_write_with_creds(p->io, d, l, &p->write_creds)) < 0)
             goto fail;
 
-        p->send_creds_now = 0;
+        p->send_creds_now = FALSE;
     } else
 #endif
 
@@ -875,7 +875,7 @@ frame_done:
     p->read.data = NULL;
 
 #ifdef HAVE_CREDS
-    p->read_creds_valid = 0;
+    p->read_creds_valid = FALSE;
 #endif
 
     return 0;
@@ -935,14 +935,14 @@ void pa_pstream_set_revoke_callback(pa_pstream *p, pa_pstream_block_id_cb_t cb,
     p->release_callback_userdata = userdata;
 }
 
-int pa_pstream_is_pending(pa_pstream *p) {
-    int b;
+pa_bool_t pa_pstream_is_pending(pa_pstream *p) {
+    pa_bool_t b;
 
     pa_assert(p);
     pa_assert(PA_REFCNT_VALUE(p) > 0);
 
     if (p->dead)
-        b = 0;
+        b = FALSE;
     else
         b = p->write.current || !pa_queue_is_empty(p->send_queue);
 
@@ -971,7 +971,7 @@ void pa_pstream_unlink(pa_pstream *p) {
     if (p->dead)
         return;
 
-    p->dead = 1;
+    p->dead = TRUE;
 
     if (p->import) {
         pa_memimport_free(p->import);
@@ -999,7 +999,7 @@ void pa_pstream_unlink(pa_pstream *p) {
     p->recieve_memblock_callback = NULL;
 }
 
-void pa_pstream_use_shm(pa_pstream *p, int enable) {
+void pa_pstream_enable_shm(pa_pstream *p, pa_bool_t enable) {
     pa_assert(p);
     pa_assert(PA_REFCNT_VALUE(p) > 0);
 
@@ -1018,3 +1018,10 @@ void pa_pstream_use_shm(pa_pstream *p, int enable) {
         }
     }
 }
+
+pa_bool_t pa_pstream_get_shm(pa_pstream *p) {
+    pa_assert(p);
+    pa_assert(PA_REFCNT_VALUE(p) > 0);
+
+    return p->use_shm;
+}
diff --git a/src/pulsecore/pstream.h b/src/pulsecore/pstream.h
index 72babea..00b37b7 100644
--- a/src/pulsecore/pstream.h
+++ b/src/pulsecore/pstream.h
@@ -35,6 +35,7 @@
 #include <pulsecore/iochannel.h>
 #include <pulsecore/memchunk.h>
 #include <pulsecore/creds.h>
+#include <pulsecore/macro.h>
 
 typedef struct pa_pstream pa_pstream;
 
@@ -44,8 +45,11 @@ 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);
+
 pa_pstream* pa_pstream_ref(pa_pstream*p);
+void pa_pstream_unref(pa_pstream*p);
+
+void pa_pstream_unlink(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);
@@ -59,10 +63,9 @@ void pa_pstream_set_die_callback(pa_pstream *p, pa_pstream_notify_cb_t cb, void
 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);
+pa_bool_t pa_pstream_is_pending(pa_pstream *p);
 
-void pa_pstream_unlink(pa_pstream *p);
+void pa_pstream_enable_shm(pa_pstream *p, pa_bool_t enable);
+pa_bool_t pa_pstream_get_shm(pa_pstream *p);
 
 #endif

commit af256978debba3f1149eb314eba51c2ca5716379
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sun Apr 20 19:43:59 2008 +0000

    follow pa_pstream_use_shm->pa_pstream_enable_shm rename
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2275 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulse/context.c b/src/pulse/context.c
index abc6a85..7806e88 100644
--- a/src/pulse/context.c
+++ b/src/pulse/context.c
@@ -427,7 +427,7 @@ static void setup_complete_callback(pa_pdispatch *pd, uint32_t command, uint32_t
                 const pa_creds *creds;
                 if ((creds = pa_pdispatch_creds(pd)))
                     if (getuid() == creds->uid)
-                        pa_pstream_use_shm(c->pstream, 1);
+                        pa_pstream_enable_shm(c->pstream, TRUE);
 #endif
             }
 

commit 03df08872df4bd6b1266b1928bb74d8595dcc2c8
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sun Apr 20 19:44:33 2008 +0000

    add lower boundary for artifical latencies
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2276 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/tests/rtstutter.c b/src/tests/rtstutter.c
index a7d1b04..39dfc5d 100644
--- a/src/tests/rtstutter.c
+++ b/src/tests/rtstutter.c
@@ -39,7 +39,7 @@
 #include <pulsecore/log.h>
 #include <pulsecore/macro.h>
 
-static int msec;
+static int msec_lower, msec_upper;
 
 static void* work(void *p) PA_GCC_NORETURN;
 
@@ -66,7 +66,9 @@ static void* work(void *p) {
 
         pa_assert_se(clock_gettime(CLOCK_REALTIME, &end) == 0);
 
-        nsec = (uint64_t) ((((double) rand())*msec*PA_NSEC_PER_MSEC)/RAND_MAX);
+        nsec =
+            (uint64_t) ((((double) rand())*(msec_upper-msec_lower)*PA_NSEC_PER_MSEC)/RAND_MAX) +
+            (uint64_t) (msec_lower*PA_NSEC_PER_MSEC);
 
         pa_log_notice("CPU%i: Freezing for %ims", PA_PTR_TO_INT(p), (int) (nsec/PA_NSEC_PER_MSEC));
 
@@ -90,11 +92,21 @@ int main(int argc, char*argv[]) {
 
     srand(time(NULL));
 
-    msec = argc > 1 ? atoi(argv[1]) : 1000;
+    if (argc >= 3) {
+        msec_lower = atoi(argv[1]);
+        msec_upper = atoi(argv[2]);
+    } else if (argc >= 2) {
+        msec_lower = 0;
+        msec_upper = atoi(argv[1]);
+    } else {
+        msec_lower = 0;
+        msec_upper = 1000;
+    }
 
-    pa_assert(msec > 0);
+    pa_assert(msec_upper > 0);
+    pa_assert(msec_upper >= msec_lower);
 
-    pa_log_notice("Creating random latencies of up to %ims.", msec);
+    pa_log_notice("Creating random latencies in the range of %ims to  %ims.", msec_lower, msec_upper);
 
     for (n = 1; n < sysconf(_SC_NPROCESSORS_CONF); n++) {
         pthread_t t;

commit ed36f3129cf4ff88cd99c39ac9708b639e172c9f
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sun Apr 20 19:46:43 2008 +0000

    increase the default pool size to 16MB because we now need to keep a lot more memory around due to glitch-free.
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2277 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/memblock.c b/src/pulsecore/memblock.c
index b76980f..c452ae0 100644
--- a/src/pulsecore/memblock.c
+++ b/src/pulsecore/memblock.c
@@ -46,8 +46,8 @@
 
 #include "memblock.h"
 
-#define PA_MEMPOOL_SLOTS_MAX 128
-#define PA_MEMPOOL_SLOT_SIZE (16*1024)
+#define PA_MEMPOOL_SLOTS_MAX 512
+#define PA_MEMPOOL_SLOT_SIZE (32*1024)
 
 #define PA_MEMEXPORT_SLOTS_MAX 128
 
@@ -253,7 +253,7 @@ static struct mempool_slot* mempool_allocate_slot(pa_mempool *p) {
             slot = (struct mempool_slot*) ((uint8_t*) p->memory.ptr + (p->block_size * idx));
 
         if (!slot) {
-            pa_log_debug("Pool full");
+            pa_log_info("Pool full");
             pa_atomic_inc(&p->stat.n_pool_full);
             return NULL;
         }

commit 33cb5897e17e42e07512452cea587c2b1ffbeaba
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sun Apr 20 19:49:55 2008 +0000

    split user supplied data in multiple memory blocks if necessary to fit in one mempool tile. If the caller supplied a free_cb and we use shm it's better to copy the data immediately to the shm region instead of keeping it around as user memblock
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2278 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulse/stream.c b/src/pulse/stream.c
index 3d79487..f047acf 100644
--- a/src/pulse/stream.c
+++ b/src/pulse/stream.c
@@ -896,6 +896,10 @@ int pa_stream_write(
         pa_seek_mode_t seek) {
 
     pa_memchunk chunk;
+    pa_seek_mode_t t_seek;
+    int64_t t_offset;
+    size_t t_length;
+    const void *t_data;
 
     pa_assert(s);
     pa_assert(PA_REFCNT_VALUE(s) >= 1);
@@ -909,21 +913,42 @@ int pa_stream_write(
     if (length <= 0)
         return 0;
 
-    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);
-        tdata = pa_memblock_acquire(chunk.memblock);
-        memcpy(tdata, data, length);
-        pa_memblock_release(chunk.memblock);
-    }
+    t_seek = seek;
+    t_offset = offset;
+    t_length = length;
+    t_data = data;
+
+    while (t_length > 0) {
+
+        chunk.index = 0;
+
+        if (free_cb && !pa_pstream_get_shm(s->context->pstream)) {
+            chunk.memblock = pa_memblock_new_user(s->context->mempool, (void*) t_data, t_length, free_cb, 1);
+            chunk.length = t_length;
+        } else {
+            void *d;
+
+            chunk.length = PA_MIN(t_length, pa_mempool_block_size_max(s->context->mempool));
+            chunk.memblock = pa_memblock_new(s->context->mempool, chunk.length);
 
-    chunk.index = 0;
-    chunk.length = length;
+            d = pa_memblock_acquire(chunk.memblock);
+            memcpy(d, t_data, chunk.length);
+            pa_memblock_release(chunk.memblock);
+        }
+
+        pa_pstream_send_memblock(s->context->pstream, s->channel, t_offset, t_seek, &chunk);
+
+        t_offset = 0;
+        t_seek = PA_SEEK_RELATIVE;
+
+        t_data = (const uint8_t*) t_data + chunk.length;
+        t_length -= chunk.length;
+
+        pa_memblock_unref(chunk.memblock);
+    }
 
-    pa_pstream_send_memblock(s->context->pstream, s->channel, offset, seek, &chunk);
-    pa_memblock_unref(chunk.memblock);
+    if (free_cb && pa_pstream_get_shm(s->context->pstream))
+        free_cb((void*) data);
 
     if (length < s->requested_bytes)
         s->requested_bytes -= length;

commit 33a35b6f2ef6edbf0e2b680c7883616bcfeb2728
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sun Apr 20 19:50:42 2008 +0000

    update to recent changes of proplist api
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2279 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/tests/proplist-test.c b/src/tests/proplist-test.c
index b88f4e5..5f7a78f 100644
--- a/src/tests/proplist-test.c
+++ b/src/tests/proplist-test.c
@@ -28,25 +28,26 @@
 #include <pulse/proplist.h>
 #include <pulse/xmalloc.h>
 #include <pulsecore/macro.h>
+#include <pulsecore/core-util.h>
 
 int main(int argc, char*argv[]) {
     pa_proplist *a, *b;
     char *s, *t;
 
     a = pa_proplist_new();
-    pa_assert_se(pa_proplist_puts(a, PA_PROP_MEDIA_TITLE, "Brandenburgische Konzerte") == 0);
-    pa_assert_se(pa_proplist_puts(a, PA_PROP_MEDIA_ARTIST, "Johann Sebastian Bach") == 0);
+    pa_assert_se(pa_proplist_sets(a, PA_PROP_MEDIA_TITLE, "Brandenburgische Konzerte") == 0);
+    pa_assert_se(pa_proplist_sets(a, PA_PROP_MEDIA_ARTIST, "Johann Sebastian Bach") == 0);
 
     b = pa_proplist_new();
-    pa_assert_se(pa_proplist_puts(b, PA_PROP_MEDIA_TITLE, "Goldbergvariationen") == 0);
-    pa_assert_se(pa_proplist_put(b, PA_PROP_MEDIA_ICON, "\0\1\2\3\4\5\6\7", 8) == 0);
+    pa_assert_se(pa_proplist_sets(b, PA_PROP_MEDIA_TITLE, "Goldbergvariationen") == 0);
+    pa_assert_se(pa_proplist_set(b, PA_PROP_MEDIA_ICON, "\0\1\2\3\4\5\6\7", 8) == 0);
 
-    pa_proplist_merge(a, b);
+    pa_proplist_update(a, PA_UPDATE_MERGE, b);
 
     pa_assert_se(!pa_proplist_gets(a, PA_PROP_MEDIA_ICON));
 
     printf("%s\n", pa_strnull(pa_proplist_gets(a, PA_PROP_MEDIA_TITLE)));
-    pa_assert_se(pa_proplist_remove(b, PA_PROP_MEDIA_TITLE) == 0);
+    pa_assert_se(pa_proplist_unset(b, PA_PROP_MEDIA_TITLE) == 0);
 
     s = pa_proplist_to_string(a);
     t = pa_proplist_to_string(b);

commit d1d7a0749d95701aac226895319b8dee044c3da7
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sun Apr 20 19:51:08 2008 +0000

    we have not periodic timers anymore
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2280 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/tests/rtpoll-test.c b/src/tests/rtpoll-test.c
index e649377..af94210 100644
--- a/src/tests/rtpoll-test.c
+++ b/src/tests/rtpoll-test.c
@@ -67,7 +67,7 @@ int main(int argc, char *argv[]) {
     pa_rtpoll_item_set_before_callback(w, worker);
 
     pa_rtpoll_install(p);
-    pa_rtpoll_set_timer_periodic(p, 10000000); /* 10 s */
+    pa_rtpoll_set_timer_relative(p, 10000000); /* 10 s */
 
     pa_rtpoll_run(p, 1);
 

commit a0671aa8db8d92ae33dc0e8003cd793635098201
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sun Apr 20 19:52:05 2008 +0000

    fix for new location of gccmacro.h
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2281 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/tests/channelmap-test.c b/src/tests/channelmap-test.c
index 98f36b6..d26d2cf 100644
--- a/src/tests/channelmap-test.c
+++ b/src/tests/channelmap-test.c
@@ -4,7 +4,7 @@
 #include <assert.h>
 
 #include <pulse/channelmap.h>
-#include <pulsecore/gccmacro.h>
+#include <pulse/gccmacro.h>
 
 int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char *argv[]) {
     char cm[PA_CHANNEL_MAP_SNPRINT_MAX];
diff --git a/src/tests/cpulimit-test.c b/src/tests/cpulimit-test.c
index d582e9c..4563c0f 100644
--- a/src/tests/cpulimit-test.c
+++ b/src/tests/cpulimit-test.c
@@ -30,7 +30,7 @@
 #include <signal.h>
 
 #include <pulse/mainloop.h>
-#include <pulsecore/gccmacro.h>
+#include <pulse/gccmacro.h>
 
 #ifdef TEST2
 #include <pulse/mainloop-signal.h>
diff --git a/src/tests/mainloop-test.c b/src/tests/mainloop-test.c
index c386251..79a4aaa 100644
--- a/src/tests/mainloop-test.c
+++ b/src/tests/mainloop-test.c
@@ -29,9 +29,9 @@
 #include <assert.h>
 
 #include <pulse/timeval.h>
+#include <pulse/gccmacro.h>
 
 #include <pulsecore/core-util.h>
-#include <pulsecore/gccmacro.h>
 
 #ifdef GLIB_MAIN_LOOP
 
diff --git a/src/tests/mcalign-test.c b/src/tests/mcalign-test.c
index d101311..79dd579 100644
--- a/src/tests/mcalign-test.c
+++ b/src/tests/mcalign-test.c
@@ -31,9 +31,10 @@
 #include <stdlib.h>
 #include <time.h>
 
+#include <pulse/gccmacro.h>
+
 #include <pulsecore/core-util.h>
 #include <pulsecore/mcalign.h>
-#include <pulsecore/gccmacro.h>
 
 /* A simple program for testing pa_mcalign */
 
diff --git a/src/tests/pacat-simple.c b/src/tests/pacat-simple.c
index 2da67c1..c2123b7 100644
--- a/src/tests/pacat-simple.c
+++ b/src/tests/pacat-simple.c
@@ -31,7 +31,7 @@
 
 #include <pulse/simple.h>
 #include <pulse/error.h>
-#include <pulsecore/gccmacro.h>
+#include <pulse/gccmacro.h>
 
 #define BUFSIZE 1024
 
diff --git a/src/tests/parec-simple.c b/src/tests/parec-simple.c
index d7d8836..9c66cc2 100644
--- a/src/tests/parec-simple.c
+++ b/src/tests/parec-simple.c
@@ -30,7 +30,7 @@
 
 #include <pulse/simple.h>
 #include <pulse/error.h>
-#include <pulsecore/gccmacro.h>
+#include <pulse/gccmacro.h>
 
 #define BUFSIZE 1024
 
diff --git a/src/tests/strlist-test.c b/src/tests/strlist-test.c
index 47770b5..2bd1645 100644
--- a/src/tests/strlist-test.c
+++ b/src/tests/strlist-test.c
@@ -1,8 +1,9 @@
 #include <stdio.h>
 
 #include <pulse/xmalloc.h>
+#include <pulse/gccmacro.h>
+
 #include <pulsecore/strlist.h>
-#include <pulsecore/gccmacro.h>
 
 int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char* argv[]) {
     char *t, *u;
diff --git a/src/tests/thread-mainloop-test.c b/src/tests/thread-mainloop-test.c
index 558e53a..ac6d504 100644
--- a/src/tests/thread-mainloop-test.c
+++ b/src/tests/thread-mainloop-test.c
@@ -30,8 +30,8 @@
 #include <pulse/timeval.h>
 #include <pulse/util.h>
 #include <pulse/thread-mainloop.h>
+#include <pulse/gccmacro.h>
 
-#include <pulsecore/gccmacro.h>
 #include <pulsecore/macro.h>
 
 static void tcb(pa_mainloop_api*a, pa_time_event *e, const struct timeval *tv, void *userdata) {
diff --git a/src/tests/voltest.c b/src/tests/voltest.c
index dcc1ec5..91752ad 100644
--- a/src/tests/voltest.c
+++ b/src/tests/voltest.c
@@ -3,7 +3,7 @@
 #include <stdio.h>
 
 #include <pulse/volume.h>
-#include <pulsecore/gccmacro.h>
+#include <pulse/gccmacro.h>
 
 int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char *argv[]) {
     pa_volume_t v;

commit 7556ef5bfc37c99064d95857626bcf9f20423c70
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sun Apr 20 19:53:07 2008 +0000

    maintain a global silence memblock cache
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2282 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/core.c b/src/pulsecore/core.c
index cf01850..3b758a3 100644
--- a/src/pulsecore/core.c
+++ b/src/pulsecore/core.c
@@ -125,6 +125,7 @@ pa_core* pa_core_new(pa_mainloop_api *m, int shared) {
     c->subscription_event_last = NULL;
 
     c->mempool = pool;
+    pa_silence_cache_init(&c->silence_cache);
 
     c->quit_event = NULL;
 
@@ -188,6 +189,7 @@ static void core_free(pa_object *o) {
     pa_xfree(c->default_source_name);
     pa_xfree(c->default_sink_name);
 
+    pa_silence_cache_done(&c->silence_cache);
     pa_mempool_free(c->mempool);
 
     pa_property_cleanup(c);
diff --git a/src/pulsecore/core.h b/src/pulsecore/core.h
index 6be1a0c..50c05b4 100644
--- a/src/pulsecore/core.h
+++ b/src/pulsecore/core.h
@@ -35,6 +35,7 @@
 #include <pulsecore/llist.h>
 #include <pulsecore/hook-list.h>
 #include <pulsecore/asyncmsgq.h>
+#include <pulsecore/sample-util.h>
 
 typedef struct pa_core pa_core;
 
@@ -112,6 +113,7 @@ struct pa_core {
     pa_subscription_event *subscription_event_last;
 
     pa_mempool *mempool;
+    pa_silence_cache silence_cache;
 
     int exit_idle_time, module_idle_time, scache_idle_time;
 

commit 62e7bc17c41c5542779a3c395a9d47d2bd306de2
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sun Apr 20 20:16:55 2008 +0000

    Big pile of dependant changes:
    * Change pa_memblockq to carry silence memchunk instead of memblock and adapt all users
    * Add new call pa_sink_input_get_silence() to get the suitable silence block for a sink input
    * Implement monitoring sources properly by adding a delay queue to even out rewinds
    * Remove pa_{sink|source}_ping() becaused unnecessary these days and not used
    * Fix naming of various rewind related functions. Downstream is now _request_rewind(), upstream is _process_rewind()
    * Fix volume adjustments for a single stream in pa_sink_render()
    * Properly handle prebuf-style buffer underruns in pa_sink_input
    * Don't allow rewinding to more than the last underrun
    * Rework default buffering metrics selection for native protocol
    * New functions pa_memblockq_prebuf_active(), pa_memblockq_silence()
    * add option "mixer_reset=" to module-alsa-sink
    * Other cleanups
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2283 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-alsa-sink.c b/src/modules/module-alsa-sink.c
index f8a2c48..32bfc30 100644
--- a/src/modules/module-alsa-sink.c
+++ b/src/modules/module-alsa-sink.c
@@ -70,11 +70,30 @@ PA_MODULE_USAGE(
         "mmap=<enable memory mapping?> "
         "tsched=<enable system timer based scheduling mode?> "
         "tsched_buffer_size=<buffer size when using timer based scheduling> "
-        "tsched_buffer_watermark=<lower fill watermark>");
+        "tsched_buffer_watermark=<lower fill watermark> "
+        "mixer_reset=<reset hw volume and mute settings to sane defaults when falling back to software?>");
+
+static const char* const valid_modargs[] = {
+    "sink_name",
+    "device",
+    "device_id",
+    "format",
+    "rate",
+    "channels",
+    "channel_map",
+    "fragments",
+    "fragment_size",
+    "mmap",
+    "tsched",
+    "tsched_buffer_size",
+    "tsched_buffer_watermark",
+    "mixer_reset",
+    NULL
+};
 
 #define DEFAULT_DEVICE "default"
-#define DEFAULT_TSCHED_BUFFER_USEC (2*PA_USEC_PER_SEC)
-#define DEFAULT_TSCHED_WATERMARK_USEC (20*PA_USEC_PER_MSEC)
+#define DEFAULT_TSCHED_BUFFER_USEC (10*PA_USEC_PER_SEC)           /* 10s */
+#define DEFAULT_TSCHED_WATERMARK_USEC (200*PA_USEC_PER_MSEC)       /* 20ms */
 
 struct userdata {
     pa_core *core;
@@ -112,23 +131,7 @@ struct userdata {
     int64_t frame_index;
 
     snd_pcm_sframes_t hwbuf_unused_frames;
-};
-
-static const char* const valid_modargs[] = {
-    "sink_name",
-    "device",
-    "device_id",
-    "format",
-    "rate",
-    "channels",
-    "channel_map",
-    "fragments",
-    "fragment_size",
-    "mmap",
-    "tsched",
-    "tsched_buffer_size",
-    "tsched_buffer_watermark",
-    NULL
+    snd_pcm_sframes_t avail_min_frames;
 };
 
 static int mmap_write(struct userdata *u) {
@@ -144,6 +147,7 @@ static int mmap_write(struct userdata *u) {
         int err;
         const snd_pcm_channel_area_t *areas;
         snd_pcm_uframes_t offset, frames;
+        size_t left_to_play;
 
         snd_pcm_hwsync(u->pcm_handle);
 
@@ -177,8 +181,26 @@ static int mmap_write(struct userdata *u) {
         if (PA_UNLIKELY(n <= u->hwbuf_unused_frames))
             return work_done;
 
+        if (n*u->frame_size < u->hwbuf_size)
+            left_to_play = u->hwbuf_size - (n*u->frame_size);
+        else
+            left_to_play = 0;
+
+        pa_log_debug("%0.2f ms left to play", (double) pa_bytes_to_usec(left_to_play, &u->sink->sample_spec) / PA_USEC_PER_MSEC);
+
+        if (left_to_play <= 0 && !u->first) {
+            u->tsched_watermark *=2;
+
+            if (u->tsched_watermark >= u->hwbuf_size)
+                u->tsched_watermark = u->hwbuf_size-u->frame_size;
+
+            pa_log_notice("Underrun! Increasing wakeup watermark to %0.2f", (double) pa_bytes_to_usec(u->tsched_watermark, &u->sink->sample_spec) / PA_USEC_PER_MSEC);
+        }
+
         frames = n = n - u->hwbuf_unused_frames;
 
+        pa_log_debug("%llu frames to write", (unsigned long long) frames);
+
         if (PA_UNLIKELY((err = snd_pcm_mmap_begin(u->pcm_handle, &areas, &offset, &frames)) < 0)) {
 
             pa_log_debug("snd_pcm_mmap_begin: %s", snd_strerror(err));
@@ -357,14 +379,21 @@ static void update_smoother(struct userdata *u) {
     snd_pcm_hwsync(u->pcm_handle);
     snd_pcm_avail_update(u->pcm_handle);
 
-    if (PA_UNLIKELY((err = snd_pcm_status(u->pcm_handle, status)) < 0)) {
+/*     if (PA_UNLIKELY((err = snd_pcm_status(u->pcm_handle, status)) < 0)) { */
+/*         pa_log("Failed to query DSP status data: %s", snd_strerror(err)); */
+/*         return; */
+/*     } */
+
+/*     delay = snd_pcm_status_get_delay(status); */
+
+    if (PA_UNLIKELY((err = snd_pcm_delay(u->pcm_handle, &delay)) < 0)) {
         pa_log("Failed to query DSP status data: %s", snd_strerror(err));
         return;
     }
 
-    delay = snd_pcm_status_get_delay(status);
+
     frames = u->frame_index - delay;
-    pa_log_debug("frame_index = %llu, delay = %llu, p = %llu", (unsigned long long) u->frame_index, (unsigned long long) delay, (unsigned long long) frames);
+/*     pa_log_debug("frame_index = %llu, delay = %llu, p = %llu", (unsigned long long) u->frame_index, (unsigned long long) delay, (unsigned long long) frames); */
 
 /*     snd_pcm_status_get_tstamp(status, &timestamp); */
 /*     pa_rtclock_from_wallclock(&timestamp); */
@@ -450,7 +479,7 @@ static pa_usec_t hw_sleep_time(struct userdata *u) {
     if (usec <= 0)
         usec = pa_bytes_to_usec(u->hwbuf_size, &u->sink->sample_spec);
 
-    pa_log_debug("hw buffer time: %u ms", (unsigned) (usec / PA_USEC_PER_MSEC));
+/*     pa_log_debug("hw buffer time: %u ms", (unsigned) (usec / PA_USEC_PER_MSEC)); */
 
     wm = pa_bytes_to_usec(u->tsched_watermark, &u->sink->sample_spec);
 
@@ -459,66 +488,58 @@ static pa_usec_t hw_sleep_time(struct userdata *u) {
     else
         usec /= 2;
 
-    pa_log_debug("after watermark: %u ms", (unsigned) (usec / PA_USEC_PER_MSEC));
+/*     pa_log_debug("after watermark: %u ms", (unsigned) (usec / PA_USEC_PER_MSEC)); */
 
     return usec;
 }
 
-static void update_hwbuf_unused_frames(struct userdata *u) {
-    pa_usec_t usec;
-    size_t b;
+static int update_sw_params(struct userdata *u) {
+    int err;
+    pa_usec_t latency;
 
     pa_assert(u);
 
-    if ((usec = pa_sink_get_requested_latency_within_thread(u->sink)) <= 0) {
-        /* Use the full buffer if noone asked us for anything
-         * specific */
-        u->hwbuf_unused_frames = 0;
-        return;
-    }
+    /* Use the full buffer if noone asked us for anything specific */
+    u->hwbuf_unused_frames = 0;
 
-    b = pa_usec_to_bytes(usec, &u->sink->sample_spec);
+    if (u->use_tsched)
+        if ((latency = pa_sink_get_requested_latency_within_thread(u->sink)) > 0) {
+            size_t b;
 
-    /* We need at least one sample in our buffer */
+            pa_log("latency set to %llu", (unsigned long long) latency);
 
-    if (PA_UNLIKELY(b < u->frame_size))
-        b = u->frame_size;
+            b = pa_usec_to_bytes(latency, &u->sink->sample_spec);
 
-    u->hwbuf_unused_frames =
-        PA_LIKELY(b < u->hwbuf_size) ?
-        ((u->hwbuf_size - b) / u->frame_size) : 0;
-}
+            /* We need at least one sample in our buffer */
 
-static int update_sw_params(struct userdata *u) {
-    snd_pcm_uframes_t avail_min;
-    int err;
+            if (PA_UNLIKELY(b < u->frame_size))
+                b = u->frame_size;
 
-    pa_assert(u);
+            u->hwbuf_unused_frames =
+                PA_LIKELY(b < u->hwbuf_size) ?
+                ((u->hwbuf_size - b) / u->frame_size) : 0;
+        }
+
+    pa_log("hwbuf_unused_frames=%lu", (unsigned long) u->hwbuf_unused_frames);
+
+    /* We need at last one frame in the used part of the buffer */
+    u->avail_min_frames = u->hwbuf_unused_frames + 1;
 
     if (u->use_tsched) {
         pa_usec_t usec;
 
         usec = hw_sleep_time(u);
 
-        avail_min = pa_usec_to_bytes(usec, &u->sink->sample_spec) / u->frame_size;
-
-        if (avail_min <= 0)
-            avail_min = 1;
-
-    } else
-        avail_min = 1;
+        u->avail_min_frames += (pa_usec_to_bytes(usec, &u->sink->sample_spec) / u->frame_size);
+    }
 
-    pa_log("setting avail_min=%lu", (unsigned long) avail_min);
+    pa_log("setting avail_min=%lu", (unsigned long) u->avail_min_frames);
 
-    if ((err = pa_alsa_set_sw_params(u->pcm_handle, avail_min)) < 0) {
+    if ((err = pa_alsa_set_sw_params(u->pcm_handle, u->avail_min_frames)) < 0) {
         pa_log("Failed to set software parameters: %s", snd_strerror(err));
         return err;
     }
 
-    update_hwbuf_unused_frames(u);
-
-    pa_log("hwbuf_unused_frames=%lu", (unsigned long) u->hwbuf_unused_frames);
-
     return 0;
 }
 
@@ -808,23 +829,23 @@ static void thread_func(void *userdata) {
     pa_thread_mq_install(&u->thread_mq);
     pa_rtpoll_install(u->rtpoll);
 
-/*     update_hwbuf_unused_frames(u); */
-
     for (;;) {
         int ret;
 
-        pa_log_debug("loop");
+/*         pa_log_debug("loop"); */
 
         /* Render some data and write it to the dsp */
         if (PA_SINK_OPENED(u->sink->thread_info.state)) {
             int work_done = 0;
 
-            if (u->sink->thread_info.rewind_nbytes > 0 && u->use_tsched) {
-                snd_pcm_sframes_t frames, limit, unused;
+            if (u->sink->thread_info.rewind_nbytes > 0) {
+                snd_pcm_sframes_t unused;
+                size_t rewind_nbytes, unused_nbytes, limit_nbytes;
 
-                pa_log_debug("Requested to rewind %lu bytes.", (unsigned long) u->sink->thread_info.rewind_nbytes);
+                rewind_nbytes = u->sink->thread_info.rewind_nbytes;
+                u->sink->thread_info.rewind_nbytes = 0;
 
-                frames = u->sink->thread_info.rewind_nbytes / u->frame_size;
+                pa_log_debug("Requested to rewind %lu bytes.", (unsigned long) rewind_nbytes);
 
                 snd_pcm_hwsync(u->pcm_handle);
                 if ((unused = snd_pcm_avail_update(u->pcm_handle)) < 0) {
@@ -832,32 +853,54 @@ static void thread_func(void *userdata) {
                     goto fail;
                 }
 
-                limit = (u->hwbuf_size / u->frame_size) - unused;
+                unused_nbytes = u->tsched_watermark + (size_t) unused * u->frame_size;
 
-                if (frames > limit)
-                    frames = limit;
+                if (u->hwbuf_size > unused_nbytes)
+                    limit_nbytes = u->hwbuf_size - unused_nbytes;
+                else
+                    limit_nbytes = 0;
 
-                frames = 0;
+                if (rewind_nbytes > limit_nbytes)
+                    rewind_nbytes = limit_nbytes;
 
-                if (frames > 0) {
+                if (rewind_nbytes > 0) {
+                    snd_pcm_sframes_t in_frames, out_frames;
 
-                    pa_log_debug("Limited to %lu bytes.", (unsigned long) frames * u->frame_size);
+                    pa_log_debug("Limited to %lu bytes.", (unsigned long) rewind_nbytes);
 
-                    if ((frames = snd_pcm_rewind(u->pcm_handle, frames)) < 0) {
-                        pa_log("snd_pcm_rewind() failed: %s", snd_strerror(frames));
+                    in_frames = (snd_pcm_sframes_t) rewind_nbytes / u->frame_size;
+                    pa_log_debug("before: %lu", (unsigned long) in_frames);
+                    if ((out_frames = snd_pcm_rewind(u->pcm_handle, in_frames)) < 0) {
+                        pa_log("snd_pcm_rewind() failed: %s", snd_strerror(out_frames));
                         goto fail;
                     }
+                    pa_log_debug("after: %lu", (unsigned long) out_frames);
+
+                    if (out_frames > in_frames) {
+                        snd_pcm_sframes_t sfix;
+                        pa_log("FUCK, device rewound %lu frames more than we wanted. What a mess!", (unsigned long) (out_frames-in_frames));
+
+                        if ((sfix = snd_pcm_forward(u->pcm_handle, out_frames-in_frames)) < 0) {
+                            pa_log("snd_pcm_forward() failed: %s", snd_strerror(sfix));
+                            goto fail;
+                        }
+
+                        pa_log("Could fix by %lu", (unsigned long) sfix);
+                        out_frames -= sfix;
+                    }
 
-                    if ((u->sink->thread_info.rewind_nbytes = frames * u->frame_size) <= 0)
+                    rewind_nbytes = out_frames * u->frame_size;
+
+                    if (rewind_nbytes <= 0)
                         pa_log_info("Tried rewind, but was apparently not possible.");
                     else {
-                        u->frame_index -= frames;
-                        pa_log_debug("Rewound %lu bytes.", (unsigned long) u->sink->thread_info.rewind_nbytes);
-                        pa_sink_process_rewind(u->sink);
+                        u->frame_index -= out_frames;
+                        pa_log_debug("Rewound %lu bytes.", (unsigned long) rewind_nbytes);
+                        pa_sink_process_rewind(u->sink, rewind_nbytes);
                     }
-                } else {
+                } else
                     pa_log_debug("Mhmm, actually there is nothing to rewind.");
-                }
+
             }
 
             if (u->use_mmap) {
@@ -868,7 +911,7 @@ static void thread_func(void *userdata) {
                     goto fail;
             }
 
-            pa_log_debug("work_done = %i", work_done);
+/*             pa_log_debug("work_done = %i", work_done); */
 
             if (work_done) {
 
@@ -891,13 +934,13 @@ static void thread_func(void *userdata) {
 
                 usec = hw_sleep_time(u);
 
-                pa_log_debug("Waking up in %0.2fms (sound card clock).", (double) usec / PA_USEC_PER_MSEC);
+/*                 pa_log_debug("Waking up in %0.2fms (sound card clock).", (double) usec / PA_USEC_PER_MSEC); */
 
                 /* Convert from the sound card time domain to the
                  * system time domain */
                 cusec = pa_smoother_translate(u->smoother, pa_rtclock_usec(), usec);
 
-                pa_log_debug("Waking up in %0.2fms (system clock).", (double) cusec / PA_USEC_PER_MSEC);
+/*                 pa_log_debug("Waking up in %0.2fms (system clock).", (double) cusec / PA_USEC_PER_MSEC); */
 
                 /* We don't trust the conversion, so we wake up whatever comes first */
                 pa_rtpoll_set_timer_relative(u->rtpoll, PA_MIN(usec, cusec));
@@ -974,7 +1017,8 @@ static void thread_func(void *userdata) {
                 u->first = TRUE;
             }
 
-            pa_log_debug("alsa revents = %i", revents);
+            if (revents)
+                pa_log_info("Wakeup from ALSA! (%i)", revents);
         }
     }
 
@@ -1003,7 +1047,7 @@ int pa__init(pa_module*m) {
     const char *name;
     char *name_buf = NULL;
     pa_bool_t namereg_fail;
-    pa_bool_t use_mmap = TRUE, b, use_tsched = TRUE, d;
+    pa_bool_t use_mmap = TRUE, b, use_tsched = TRUE, d, mixer_reset = TRUE;
     pa_usec_t usec;
     pa_sink_new_data data;
     static const char * const class_table[SND_PCM_CLASS_LAST+1] = {
@@ -1066,6 +1110,11 @@ int pa__init(pa_module*m) {
         use_tsched = FALSE;
     }
 
+    if (pa_modargs_get_value_boolean(ma, "mixer_reset", &mixer_reset) < 0) {
+        pa_log("Failed to parse mixer_reset argument.");
+        goto fail;
+    }
+
     u = pa_xnew0(struct userdata, 1);
     u->core = m->core;
     u->module = m;
@@ -1202,7 +1251,7 @@ int pa__init(pa_module*m) {
     if (class_table[snd_pcm_info_get_class(pcm_info)])
         pa_proplist_sets(data.proplist, PA_PROP_DEVICE_CLASS, class_table[snd_pcm_info_get_class(pcm_info)]);
 
-    pa_proplist_sets(data.proplist, PA_PROP_DEVICE_ACCESS_MODE, u->use_tsched ? "mmap_rewrite" : (u->use_mmap ? "mmap" : "serial"));
+    pa_proplist_sets(data.proplist, PA_PROP_DEVICE_ACCESS_MODE, u->use_tsched ? "mmap+timer" : (u->use_mmap ? "mmap" : "serial"));
 
     u->sink = pa_sink_new(m->core, &data, PA_SINK_HARDWARE|PA_SINK_LATENCY);
     pa_sink_new_data_done(&data);
@@ -1225,14 +1274,18 @@ int pa__init(pa_module*m) {
     u->nfragments = nfrags;
     u->hwbuf_size = u->fragment_size * nfrags;
     u->hwbuf_unused_frames = 0;
+    u->avail_min_frames = 0;
     u->tsched_watermark = tsched_watermark;
     u->frame_index = 0;
     u->hw_dB_supported = FALSE;
     u->hw_dB_min = u->hw_dB_max = 0;
     u->hw_volume_min = u->hw_volume_max = 0;
 
-    u->sink->thread_info.max_rewind = use_tsched ? u->hwbuf_size : 0;
+    if (use_tsched)
+        if (u->tsched_watermark >= u->hwbuf_size/2)
+            u->tsched_watermark = pa_frame_align(u->hwbuf_size/2, &ss);
 
+    u->sink->thread_info.max_rewind = use_tsched ? u->hwbuf_size : 0;
     u->sink->max_latency = pa_bytes_to_usec(u->hwbuf_size, &ss);
 
     if (!use_tsched)
@@ -1310,10 +1363,11 @@ int pa__init(pa_module*m) {
                     u->sink->flags |= PA_SINK_HW_VOLUME_CTRL | (u->hw_dB_supported ? PA_SINK_DECIBEL_VOLUME : 0);
                     pa_log_info("Using hardware volume control. %s dB scale.", u->hw_dB_supported ? "Using" : "Not using");
 
-                } else {
+                } else if (mixer_reset) {
                     pa_log_info("Using software volume control. Trying to reset sound card to 0 dB.");
                     pa_alsa_0dB_playback(u->mixer_elem);
-                }
+                } else
+                    pa_log_info("Using software volume control. Leaving hw mixer controls untouched.");
             }
 
         if (snd_mixer_selem_has_playback_switch(u->mixer_elem)) {
diff --git a/src/modules/module-alsa-source.c b/src/modules/module-alsa-source.c
index 83b7f53..185acc0 100644
--- a/src/modules/module-alsa-source.c
+++ b/src/modules/module-alsa-source.c
@@ -71,7 +71,26 @@ PA_MODULE_USAGE(
         "mmap=<enable memory mapping?> "
         "tsched=<enable system timer based scheduling mode?> "
         "tsched_buffer_size=<buffer size when using timer based scheduling> "
-        "tsched_buffer_watermark=<upper fill watermark>");
+        "tsched_buffer_watermark=<upper fill watermark> "
+        "mixer_reset=<reset hw volume and mute settings to sane defaults when falling back to software?>");
+
+static const char* const valid_modargs[] = {
+    "source_name",
+    "device",
+    "device_id",
+    "format",
+    "rate",
+    "channels",
+    "channel_map",
+    "fragments",
+    "fragment_size",
+    "mmap",
+    "tsched",
+    "tsched_buffer_size",
+    "tsched_buffer_watermark",
+    "mixer_reset",
+    NULL
+};
 
 #define DEFAULT_DEVICE "default"
 #define DEFAULT_TSCHED_BUFFER_USEC (2*PA_USEC_PER_SEC)
@@ -110,23 +129,6 @@ struct userdata {
     int64_t frame_index;
 };
 
-static const char* const valid_modargs[] = {
-    "source_name",
-    "device",
-    "device_id",
-    "format",
-    "rate",
-    "channels",
-    "channel_map",
-    "fragments",
-    "fragment_size",
-    "mmap",
-    "tsched",
-    "tsched_buffer_size",
-    "tsched_buffer_watermark",
-    NULL
-};
-
 static int mmap_read(struct userdata *u) {
     int work_done = 0;
 
@@ -876,7 +878,7 @@ int pa__init(pa_module*m) {
     const char *name;
     char *name_buf = NULL;
     pa_bool_t namereg_fail;
-    pa_bool_t use_mmap = TRUE, b, use_tsched = TRUE, d;
+    pa_bool_t use_mmap = TRUE, b, use_tsched = TRUE, d, mixer_reset = TRUE;
     pa_source_new_data data;
     static const char * const class_table[SND_PCM_CLASS_LAST+1] = {
         [SND_PCM_CLASS_GENERIC] = "sound",
@@ -938,6 +940,11 @@ int pa__init(pa_module*m) {
         use_tsched = FALSE;
     }
 
+    if (pa_modargs_get_value_boolean(ma, "mixer_reset", &mixer_reset) < 0) {
+        pa_log("Failed to parse mixer_reset argument.");
+        goto fail;
+    }
+
     u = pa_xnew0(struct userdata, 1);
     u->core = m->core;
     u->module = m;
@@ -1163,10 +1170,12 @@ int pa__init(pa_module*m) {
                     u->source->flags |= PA_SOURCE_HW_VOLUME_CTRL | (u->hw_dB_supported ? PA_SOURCE_DECIBEL_VOLUME : 0);
                     pa_log_info("Using hardware volume control. %s dB scale.", u->hw_dB_supported ? "Using" : "Not using");
 
-                } else {
+                } else if (mixer_reset) {
                     pa_log_info("Using software volume control. Trying to reset sound card to 0 dB.");
                     pa_alsa_0dB_capture(u->mixer_elem);
-                }
+                } else
+                    pa_log_info("Using software volume control. Leaving hw mixer controls untouched.");
+
             }
 
 
diff --git a/src/modules/module-combine.c b/src/modules/module-combine.c
index 0b17bc5..6f99ae4 100644
--- a/src/modules/module-combine.c
+++ b/src/modules/module-combine.c
@@ -252,7 +252,8 @@ static void thread_func(void *userdata) {
 
             /* Just rewind if necessary, since we are in NULL mode, we
              * don't have to pass this on */
-            pa_sink_process_rewind(u->sink);
+            pa_sink_process_rewind(u->sink, u->sink->thread_info.rewind_nbytes);
+            u->sink->thread_info.rewind_nbytes = 0;
 
             pa_rtclock_get(&now);
 
diff --git a/src/modules/module-ladspa-sink.c b/src/modules/module-ladspa-sink.c
index 2342cde..14f14b1 100644
--- a/src/modules/module-ladspa-sink.c
+++ b/src/modules/module-ladspa-sink.c
@@ -134,7 +134,7 @@ static void sink_request_rewind(pa_sink *s) {
     pa_assert_se(u = s->userdata);
 
     /* Just hand this one over to the master sink */
-    pa_sink_input_request_rewrite(u->sink_input, s->thread_info.rewind_nbytes);
+    pa_sink_input_request_rewind(u->sink_input, s->thread_info.rewind_nbytes, FALSE);
 }
 
 /* Called from I/O thread context */
@@ -224,8 +224,7 @@ static void sink_input_rewind_cb(pa_sink_input *i, size_t nbytes) {
     pa_assert_se(u = i->userdata);
     pa_assert(nbytes > 0);
 
-    u->sink->thread_info.rewind_nbytes = nbytes;
-    pa_sink_process_rewind(u->sink);
+    pa_sink_process_rewind(u->sink, nbytes);
 }
 
 /* Called from I/O thread context */
diff --git a/src/modules/module-remap-sink.c b/src/modules/module-remap-sink.c
index 2dc4f2a..3f70ee1 100644
--- a/src/modules/module-remap-sink.c
+++ b/src/modules/module-remap-sink.c
@@ -112,7 +112,7 @@ static void sink_request_rewind(pa_sink *s) {
     pa_sink_assert_ref(s);
     pa_assert_se(u = s->userdata);
 
-    pa_sink_input_request_rewrite(u->sink_input, s->thread_info.rewind_nbytes);
+    pa_sink_input_request_rewind(u->sink_input, s->thread_info.rewind_nbytes, FALSE);
 }
 
 /* Called from I/O thread context */
@@ -166,8 +166,7 @@ static void sink_input_rewind_cb(pa_sink_input *i, size_t nbytes) {
     pa_assert_se(u = i->userdata);
     pa_assert(nbytes > 0);
 
-    u->sink->thread_info.rewind_nbytes = nbytes;
-    pa_sink_process_rewind(u->sink);
+    pa_sink_process_rewind(u->sink, nbytes);
 }
 
 /* Called from I/O thread context */
diff --git a/src/modules/rtp/module-rtp-recv.c b/src/modules/rtp/module-rtp-recv.c
index be54c38..92b43dd 100644
--- a/src/modules/rtp/module-rtp-recv.c
+++ b/src/modules/rtp/module-rtp-recv.c
@@ -313,7 +313,7 @@ static struct session *session_new(struct userdata *u, const pa_sdp_info *sdp_in
     char *c;
     pa_sink *sink;
     int fd = -1;
-    pa_memblock *silence;
+    pa_memchunk silence;
     pa_sink_input_new_data data;
     struct timeval now;
 
@@ -371,10 +371,7 @@ static struct session *session_new(struct userdata *u, const pa_sdp_info *sdp_in
     s->sink_input->attach = sink_input_attach;
     s->sink_input->detach = sink_input_detach;
 
-    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));
+    pa_sink_input_get_silence(s->sink_input, &silence);
 
     s->memblockq = pa_memblockq_new(
             0,
@@ -384,9 +381,9 @@ static struct session *session_new(struct userdata *u, const pa_sdp_info *sdp_in
             pa_bytes_per_second(&s->sink_input->sample_spec)/10+1,
             0,
             0,
-            silence);
+            &silence);
 
-    pa_memblock_unref(silence);
+    pa_memblock_unref(silence.memblock);
 
     pa_rtp_context_init_recv(&s->rtp_context, fd, pa_frame_size(&s->sdp_info.sample_spec));
 
diff --git a/src/pulsecore/memblockq.c b/src/pulsecore/memblockq.c
index 1d9583e..947c69a 100644
--- a/src/pulsecore/memblockq.c
+++ b/src/pulsecore/memblockq.c
@@ -55,7 +55,7 @@ struct pa_memblockq {
     size_t maxlength, tlength, base, prebuf, minreq, maxrewind;
     int64_t read_index, write_index;
     pa_bool_t in_prebuf;
-    pa_memblock *silence;
+    pa_memchunk silence;
     pa_mcalign *mcalign;
     int64_t missing;
     size_t requested;
@@ -69,7 +69,7 @@ pa_memblockq* pa_memblockq_new(
         size_t prebuf,
         size_t minreq,
         size_t maxrewind,
-        pa_memblock *silence) {
+        pa_memchunk *silence) {
 
     pa_memblockq* bq;
 
@@ -98,7 +98,12 @@ pa_memblockq* pa_memblockq_new(
     pa_log_debug("memblockq sanitized: maxlength=%lu, tlength=%lu, base=%lu, prebuf=%lu, minreq=%lu maxrewind=%lu",
                  (unsigned long) bq->maxlength, (unsigned long) bq->tlength, (unsigned long) bq->base, (unsigned long) bq->prebuf, (unsigned long) bq->minreq, (unsigned long) bq->maxrewind);
 
-    bq->silence = silence ? pa_memblock_ref(silence) : NULL;
+    if (silence) {
+        bq->silence = *silence;
+        pa_memblock_ref(bq->silence.memblock);
+    } else
+        pa_memchunk_reset(&bq->silence);
+
     bq->mcalign = pa_mcalign_new(bq->base);
 
     return bq;
@@ -109,8 +114,8 @@ void pa_memblockq_free(pa_memblockq* bq) {
 
     pa_memblockq_flush(bq);
 
-    if (bq->silence)
-        pa_memblock_unref(bq->silence);
+    if (bq->silence.memblock)
+        pa_memblock_unref(bq->silence.memblock);
 
     if (bq->mcalign)
         pa_mcalign_free(bq->mcalign);
@@ -420,7 +425,7 @@ finish:
     return 0;
 }
 
-static pa_bool_t memblockq_check_prebuf(pa_memblockq *bq) {
+pa_bool_t pa_memblockq_prebuf_active(pa_memblockq *bq) {
     pa_assert(bq);
 
     if (bq->in_prebuf) {
@@ -447,7 +452,7 @@ int pa_memblockq_peek(pa_memblockq* bq, pa_memchunk *chunk) {
     pa_assert(chunk);
 
     /* We need to pre-buffer */
-    if (memblockq_check_prebuf(bq))
+    if (pa_memblockq_prebuf_active(bq))
         return -1;
 
     fix_current_read(bq);
@@ -466,13 +471,12 @@ int pa_memblockq_peek(pa_memblockq* bq, pa_memchunk *chunk) {
             length = 0;
 
         /* We need to return silence, since no data is yet available */
-        if (bq->silence) {
-            size_t l;
-
-            chunk->memblock = pa_memblock_ref(bq->silence);
+        if (bq->silence.memblock) {
+            *chunk = bq->silence;
+            pa_memblock_ref(chunk->memblock);
 
-            l = pa_memblock_get_length(chunk->memblock);
-            chunk->length = (length <= 0 || length > l) ? l : length;
+            if (length > 0 && length < chunk->length)
+                chunk->length = length;
 
         } else {
 
@@ -511,7 +515,7 @@ void pa_memblockq_drop(pa_memblockq *bq, size_t length) {
     while (length > 0) {
 
         /* Do not drop any data when we are in prebuffering mode */
-        if (memblockq_check_prebuf(bq))
+        if (pa_memblockq_prebuf_active(bq))
             break;
 
         fix_current_read(bq);
@@ -546,10 +550,20 @@ void pa_memblockq_drop(pa_memblockq *bq, size_t length) {
     bq->missing += delta;
 }
 
+void pa_memblockq_rewind(pa_memblockq *bq, size_t length) {
+    pa_assert(bq);
+    pa_assert(length % bq->base == 0);
+
+    /* This is kind of the inverse of pa_memblockq_drop() */
+
+    bq->read_index -= length;
+    bq->missing -= length;
+}
+
 pa_bool_t pa_memblockq_is_readable(pa_memblockq *bq) {
     pa_assert(bq);
 
-    if (memblockq_check_prebuf(bq))
+    if (pa_memblockq_prebuf_active(bq))
         return FALSE;
 
     if (pa_memblockq_get_length(bq) <= 0)
@@ -621,10 +635,7 @@ void pa_memblockq_flush(pa_memblockq *bq) {
     int64_t old, delta;
     pa_assert(bq);
 
-    while (bq->blocks)
-        drop_block(bq, bq->blocks);
-
-    pa_assert(bq->n_blocks == 0);
+    pa_memblockq_silence(bq);
 
     old = bq->write_index;
     bq->write_index = bq->read_index;
@@ -757,18 +768,17 @@ void pa_memblockq_set_tlength(pa_memblockq *bq, size_t tlength) {
     size_t old_tlength;
     pa_assert(bq);
 
-    old_tlength = bq->tlength;
-
     if (tlength <= 0)
         tlength = bq->maxlength;
 
+    old_tlength = bq->tlength;
     bq->tlength = ((tlength+bq->base-1)/bq->base)*bq->base;
 
     if (bq->tlength > bq->maxlength)
         bq->tlength = bq->maxlength;
 
-    if (bq->minreq > bq->tlength - bq->prebuf)
-        pa_memblockq_set_minreq(bq, bq->tlength - bq->prebuf);
+    if (bq->minreq > bq->tlength)
+        pa_memblockq_set_minreq(bq, bq->tlength);
 
     bq->missing += (int64_t) bq->tlength - (int64_t) old_tlength;
 }
@@ -776,8 +786,10 @@ void pa_memblockq_set_tlength(pa_memblockq *bq, size_t tlength) {
 void pa_memblockq_set_prebuf(pa_memblockq *bq, size_t prebuf) {
     pa_assert(bq);
 
-    bq->prebuf = (prebuf == (size_t) -1) ? bq->tlength : prebuf;
-    bq->prebuf = ((bq->prebuf+bq->base-1)/bq->base)*bq->base;
+    if (prebuf == (size_t) -1)
+        prebuf = bq->tlength;
+
+    bq->prebuf = ((prebuf+bq->base-1)/bq->base)*bq->base;
 
     if (prebuf > 0 && bq->prebuf < bq->base)
         bq->prebuf = bq->base;
@@ -788,8 +800,8 @@ void pa_memblockq_set_prebuf(pa_memblockq *bq, size_t prebuf) {
     if (bq->prebuf <= 0 || pa_memblockq_get_length(bq) >= bq->prebuf)
         bq->in_prebuf = FALSE;
 
-    if (bq->minreq > bq->tlength - bq->prebuf)
-        pa_memblockq_set_minreq(bq, bq->tlength - bq->prebuf);
+    if (bq->minreq > bq->prebuf)
+        pa_memblockq_set_minreq(bq, bq->prebuf);
 }
 
 void pa_memblockq_set_minreq(pa_memblockq *bq, size_t minreq) {
@@ -797,8 +809,11 @@ void pa_memblockq_set_minreq(pa_memblockq *bq, size_t minreq) {
 
     bq->minreq = (minreq/bq->base)*bq->base;
 
-    if (bq->minreq > bq->tlength - bq->prebuf)
-        bq->minreq = bq->tlength - bq->prebuf;
+    if (bq->minreq > bq->tlength)
+        bq->minreq = bq->tlength;
+
+    if (bq->minreq > bq->prebuf)
+        bq->minreq = bq->prebuf;
 
     if (bq->minreq < bq->base)
         bq->minreq = bq->base;
@@ -810,14 +825,6 @@ void pa_memblockq_set_maxrewind(pa_memblockq *bq, size_t maxrewind) {
     bq->maxrewind = (maxrewind/bq->base)*bq->base;
 }
 
-void pa_memblockq_rewind(pa_memblockq *bq, size_t length) {
-    pa_assert(bq);
-    pa_assert(length % bq->base == 0);
-
-    bq->read_index -= length;
-    bq->missing -= length;
-}
-
 int pa_memblockq_splice(pa_memblockq *bq, pa_memblockq *source) {
 
     pa_assert(bq);
@@ -859,13 +866,17 @@ void pa_memblockq_willneed(pa_memblockq *bq) {
         pa_memchunk_will_need(&q->chunk);
 }
 
-void pa_memblockq_set_silence(pa_memblockq *bq, pa_memblock *silence) {
+void pa_memblockq_set_silence(pa_memblockq *bq, pa_memchunk *silence) {
     pa_assert(bq);
 
-    if (bq->silence)
-        pa_memblock_unref(bq->silence);
+    if (bq->silence.memblock)
+        pa_memblock_unref(bq->silence.memblock);
 
-    bq->silence = silence ? pa_memblock_ref(silence) : NULL;
+    if (silence) {
+        bq->silence = *silence;
+        pa_memblock_ref(bq->silence.memblock);
+    } else
+        pa_memchunk_reset(&bq->silence);
 }
 
 pa_bool_t pa_memblockq_is_empty(pa_memblockq *bq) {
@@ -873,3 +884,12 @@ pa_bool_t pa_memblockq_is_empty(pa_memblockq *bq) {
 
     return !bq->blocks;
 }
+
+void pa_memblockq_silence(pa_memblockq *bq) {
+    pa_assert(bq);
+
+    while (bq->blocks)
+        drop_block(bq, bq->blocks);
+
+    pa_assert(bq->n_blocks == 0);
+}
diff --git a/src/pulsecore/memblockq.h b/src/pulsecore/memblockq.h
index 8610a1a..a6065de 100644
--- a/src/pulsecore/memblockq.h
+++ b/src/pulsecore/memblockq.h
@@ -64,7 +64,7 @@ typedef struct pa_memblockq pa_memblockq;
 
    - maxrewind: how many bytes of history to keep in the queue
 
-   - silence:   return this memblock when reading unitialized data
+   - silence:   return this memchunk when reading unitialized data
 */
 pa_memblockq* pa_memblockq_new(
         int64_t idx,
@@ -74,7 +74,7 @@ pa_memblockq* pa_memblockq_new(
         size_t prebuf,
         size_t minreq,
         size_t maxrewind,
-        pa_memblock *silence);
+        pa_memchunk *silence);
 
 void pa_memblockq_free(pa_memblockq*bq);
 
@@ -152,7 +152,7 @@ void pa_memblockq_set_tlength(pa_memblockq *memblockq, size_t tlength); /* might
 void pa_memblockq_set_prebuf(pa_memblockq *memblockq, size_t prebuf); /* might modify minreq, too */
 void pa_memblockq_set_minreq(pa_memblockq *memblockq, size_t minreq);
 void pa_memblockq_set_maxrewind(pa_memblockq *memblockq, size_t rewind); /* Set the maximum history size */
-void pa_memblockq_set_silence(pa_memblockq *memblockq, pa_memblock *silence);
+void pa_memblockq_set_silence(pa_memblockq *memblockq, pa_memchunk *silence);
 
 /* Call pa_memchunk_willneed() for every chunk in the queue from the current read pointer to the end */
 void pa_memblockq_willneed(pa_memblockq *bq);
@@ -162,4 +162,9 @@ void pa_memblockq_willneed(pa_memblockq *bq);
  * data for the future nor data in the backlog. */
 pa_bool_t pa_memblockq_is_empty(pa_memblockq *bq);
 
+void pa_memblockq_silence(pa_memblockq *bq);
+
+/* Check whether we currently are in prebuf state */
+pa_bool_t pa_memblockq_prebuf_active(pa_memblockq *bq);
+
 #endif
diff --git a/src/pulsecore/play-memblockq.c b/src/pulsecore/play-memblockq.c
index 3d435c8..7b9b8fb 100644
--- a/src/pulsecore/play-memblockq.c
+++ b/src/pulsecore/play-memblockq.c
@@ -255,17 +255,13 @@ void pa_memblockq_sink_input_set_queue(pa_sink_input *i, pa_memblockq *q) {
         pa_memblockq_free(u->memblockq);
 
     if ((u->memblockq = q)) {
-        pa_memblock *silence;
+        pa_memchunk silence;
 
         pa_memblockq_set_prebuf(q, 0);
 
-        silence = pa_silence_memblock_new(
-                i->sink->core->mempool,
-                &i->sample_spec,
-                i->thread_info.resampler ? pa_resampler_max_block_size(i->thread_info.resampler) : 0);
-
-        pa_memblockq_set_silence(q, silence);
-        pa_memblock_unref(silence);
+        pa_sink_input_get_silence(i, &silence);
+        pa_memblockq_set_silence(q, &silence);
+        pa_memblock_unref(silence.memblock);
 
         pa_memblockq_willneed(q);
     }
diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c
index fc5aa59..37200db 100644
--- a/src/pulsecore/protocol-native.c
+++ b/src/pulsecore/protocol-native.c
@@ -72,6 +72,7 @@
 
 #define MAX_MEMBLOCKQ_LENGTH (4*1024*1024) /* 4MB */
 #define DEFAULT_TLENGTH_MSEC 2000 /* 2s */
+#define DEFAULT_PROCESS_MSEC 20   /* 20ms */
 #define DEFAULT_FRAGSIZE_MSEC DEFAULT_TLENGTH_MSEC
 
 typedef struct connection connection;
@@ -104,7 +105,7 @@ typedef struct playback_stream {
     pa_bool_t drain_request;
     uint32_t drain_tag;
     uint32_t syncid;
-    pa_bool_t underrun;
+    uint64_t underrun; /* length of underrun */
 
     pa_atomic_t missing;
     size_t minreq;
@@ -208,6 +209,9 @@ static int sink_input_pop_cb(pa_sink_input *i, size_t length, pa_memchunk *chunk
 static void sink_input_kill_cb(pa_sink_input *i);
 static void sink_input_suspend_cb(pa_sink_input *i, pa_bool_t suspend);
 static void sink_input_moved_cb(pa_sink_input *i);
+static void sink_input_rewind_cb(pa_sink_input *i, size_t nbytes);
+static void sink_input_set_max_rewind_cb(pa_sink_input *i, size_t nbytes);
+
 
 static void send_memblock(connection *c);
 static void request_bytes(struct playback_stream*s);
@@ -471,7 +475,6 @@ static record_stream* record_stream_new(
         pa_source *source,
         pa_sample_spec *ss,
         pa_channel_map *map,
-        const char *name,
         uint32_t *maxlength,
         uint32_t *fragsize,
         pa_source_output_flags_t flags,
@@ -485,7 +488,6 @@ static record_stream* record_stream_new(
 
     pa_assert(c);
     pa_assert(ss);
-    pa_assert(name);
     pa_assert(maxlength);
     pa_assert(p);
 
@@ -523,7 +525,7 @@ static record_stream* record_stream_new(
     if (*maxlength <= 0 || *maxlength > MAX_MEMBLOCKQ_LENGTH)
         *maxlength = MAX_MEMBLOCKQ_LENGTH;
     if (*fragsize <= 0)
-        *fragsize = pa_usec_to_bytes(DEFAULT_FRAGSIZE_MSEC*1000, &source_output->sample_spec);
+        *fragsize = pa_usec_to_bytes(DEFAULT_FRAGSIZE_MSEC*PA_USEC_PER_MSEC, &source_output->sample_spec);
 
     if (adjust_latency) {
         pa_usec_t fragsize_usec;
@@ -618,21 +620,14 @@ static int playback_stream_process_msg(pa_msgobject *o, int code, void*userdata,
             uint32_t l = 0;
 
             for (;;) {
-                int32_t k;
-
-                if ((k = pa_atomic_load(&s->missing)) <= 0)
-                    break;
-
-                l += k;
-
-                if (l < s->minreq)
+                if ((l = pa_atomic_load(&s->missing)) <= 0)
                     break;
 
-                if (pa_atomic_sub(&s->missing, k) <= k)
+                if (pa_atomic_cmpxchg(&s->missing, l, 0))
                     break;
             }
 
-            if (l < s->minreq)
+            if (l <= 0)
                 break;
 
             t = pa_tagstruct_new(NULL, 0);
@@ -642,7 +637,7 @@ static int playback_stream_process_msg(pa_msgobject *o, int code, void*userdata,
             pa_tagstruct_putu32(t, l);
             pa_pstream_send_tagstruct(s->connection->pstream, t);
 
-/*             pa_log("Requesting %u bytes", l);     */
+/*             pa_log("Requesting %lu bytes", (unsigned long) l); */
             break;
         }
 
@@ -684,7 +679,6 @@ static playback_stream* playback_stream_new(
         pa_sink *sink,
         pa_sample_spec *ss,
         pa_channel_map *map,
-        const char *name,
         uint32_t *maxlength,
         uint32_t *tlength,
         uint32_t *prebuf,
@@ -699,14 +693,15 @@ static playback_stream* playback_stream_new(
 
     playback_stream *s, *ssync;
     pa_sink_input *sink_input;
-    pa_memblock *silence;
+    pa_memchunk silence;
     uint32_t idx;
     int64_t start_index;
     pa_sink_input_new_data data;
+    pa_usec_t tlength_usec, minreq_usec, sink_usec;
+    size_t frame_size;
 
     pa_assert(c);
     pa_assert(ss);
-    pa_assert(name);
     pa_assert(maxlength);
     pa_assert(tlength);
     pa_assert(prebuf);
@@ -761,10 +756,12 @@ static playback_stream* playback_stream_new(
     s->connection = c;
     s->syncid = syncid;
     s->sink_input = sink_input;
-    s->underrun = TRUE;
+    s->underrun = (uint64_t) -1;
 
     s->sink_input->parent.process_msg = sink_input_process_msg;
     s->sink_input->pop = sink_input_pop_cb;
+    s->sink_input->rewind = sink_input_rewind_cb;
+    s->sink_input->set_max_rewind = sink_input_set_max_rewind_cb;
     s->sink_input->kill = sink_input_kill_cb;
     s->sink_input->moved = sink_input_moved_cb;
     s->sink_input->suspend = sink_input_suspend_cb;
@@ -775,40 +772,69 @@ static playback_stream* playback_stream_new(
     if (*maxlength <= 0 || *maxlength > MAX_MEMBLOCKQ_LENGTH)
         *maxlength = MAX_MEMBLOCKQ_LENGTH;
     if (*tlength <= 0)
-        *tlength = pa_usec_to_bytes(DEFAULT_TLENGTH_MSEC*1000, &sink_input->sample_spec);
+        *tlength = pa_usec_to_bytes(DEFAULT_TLENGTH_MSEC*PA_USEC_PER_MSEC, &sink_input->sample_spec);
     if (*minreq <= 0)
-        *minreq = (*tlength*9)/10;
-    if (*prebuf <= 0)
-        *prebuf = *tlength;
+        *minreq = pa_usec_to_bytes(DEFAULT_PROCESS_MSEC*PA_USEC_PER_MSEC, &sink_input->sample_spec);
+
+    frame_size = pa_frame_size(&sink_input->sample_spec);
+    if (*minreq <= 0)
+        *minreq = frame_size;
+    if (*tlength < *minreq+frame_size)
+        *tlength = *minreq+frame_size;
+
+    tlength_usec = pa_bytes_to_usec(*tlength, &sink_input->sample_spec);
+    minreq_usec = pa_bytes_to_usec(*minreq, &sink_input->sample_spec);
 
     if (adjust_latency) {
-        pa_usec_t tlength_usec, minreq_usec;
 
-        /* So, the user asked us to adjust the latency according to
-         * the what the sink can provide. Half the latency will be
-         * spent on the hw buffer, half of it in the async buffer
-         * queue we maintain for each client. */
+        /* So, the user asked us to adjust the latency of the stream
+         * buffer according to the what the sink can provide. The
+         * tlength passed in shall be the overall latency. Roughly
+         * half the latency will be spent on the hw buffer, the other
+         * half of it in the async buffer queue we maintain for each
+         * client. In between we'll have a safety space of size
+         * minreq.*/
+
+        sink_usec = (tlength_usec-minreq_usec)/2;
+
+    } else {
+
+        /* Ok, the user didn't ask us to adjust the latency, but we
+         * still need to make sure that the parameters from the user
+         * do make sense. */
+
+        sink_usec = tlength_usec - minreq_usec;
+    }
 
-        tlength_usec = pa_bytes_to_usec(*tlength, &sink_input->sample_spec);
-        minreq_usec = pa_bytes_to_usec(*minreq, &sink_input->sample_spec);
+    s->sink_latency = pa_sink_input_set_requested_latency(sink_input, sink_usec);
 
-        s->sink_latency = pa_sink_input_set_requested_latency(sink_input, tlength_usec/2);
+    if (adjust_latency) {
+        /* Ok, we didn't necessarily get what we were asking for, so
+         * let's subtract from what we asked for for the remaining
+         * buffer space */
 
-        if (tlength_usec >= s->sink_latency*2)
+        if (tlength_usec >= s->sink_latency)
             tlength_usec -= s->sink_latency;
-        else
-            tlength_usec = s->sink_latency;
+    }
 
-        if (minreq_usec >= s->sink_latency*2)
-            minreq_usec -= s->sink_latency;
-        else
-            minreq_usec = s->sink_latency;
+    if (tlength_usec < s->sink_latency + minreq_usec)
+        tlength_usec = s->sink_latency + minreq_usec;
 
-        *tlength = pa_usec_to_bytes(tlength_usec, &sink_input->sample_spec);
-        *minreq = pa_usec_to_bytes(minreq_usec, &sink_input->sample_spec);
+    *tlength = pa_usec_to_bytes(tlength_usec, &sink_input->sample_spec);
+    *minreq = pa_usec_to_bytes(minreq_usec, &sink_input->sample_spec);
+
+    if (*minreq <= 0) {
+        *minreq = frame_size;
+        *tlength += frame_size;
     }
 
-    silence = pa_silence_memblock_new(c->protocol->core->mempool, &sink_input->sample_spec, 0);
+    if (*tlength <= *minreq)
+        *tlength = *minreq + frame_size;
+
+    if (*prebuf <= 0)
+        *prebuf = *tlength;
+
+    pa_sink_input_get_silence(sink_input, &silence);
 
     s->memblockq = pa_memblockq_new(
             start_index,
@@ -818,9 +844,9 @@ static playback_stream* playback_stream_new(
             *prebuf,
             *minreq,
             0,
-            silence);
+            &silence);
 
-    pa_memblock_unref(silence);
+    pa_memblock_unref(silence.memblock);
 
     *maxlength = (uint32_t) pa_memblockq_get_maxlength(s->memblockq);
     *tlength = (uint32_t) pa_memblockq_get_tlength(s->memblockq);
@@ -924,10 +950,12 @@ static void request_bytes(playback_stream *s) {
     if (m <= 0)
         return;
 
-/*     pa_log("request_bytes(%u)", m); */
+/*     pa_log("request_bytes(%lu)", (unsigned long) m); */
 
     previous_missing = pa_atomic_add(&s->missing, m);
-    if (previous_missing < s->minreq && previous_missing+m >= s->minreq) {
+
+    if (pa_memblockq_prebuf_active(s->memblockq) ||
+        (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);
     }
@@ -989,6 +1017,45 @@ static void send_record_stream_killed(record_stream *r) {
 
 /*** sink input callbacks ***/
 
+static void handle_seek(playback_stream *s, int64_t indexw) {
+    playback_stream_assert_ref(s);
+
+/*     pa_log("handle_seek: %llu -- %i", (unsigned long long) s->underrun, pa_memblockq_is_readable(s->memblockq)); */
+
+    if (s->underrun != 0) {
+
+/*         pa_log("%lu vs. %lu", (unsigned long) pa_memblockq_get_length(s->memblockq), (unsigned long) pa_memblockq_get_prebuf(s->memblockq)); */
+
+        if (pa_memblockq_is_readable(s->memblockq)) {
+
+            size_t u = pa_memblockq_get_length(s->memblockq);
+
+            if (u >= s->underrun)
+                u = s->underrun;
+
+            pa_log("yeah! ready to rock");
+
+            /* We just ended an underrun, let's ask the sink
+             * to rewrite */
+            s->sink_input->thread_info.ignore_rewind = TRUE;
+            pa_sink_input_request_rewind(s->sink_input, u, TRUE);
+        }
+
+    } else {
+        int64_t indexr;
+
+        indexr = pa_memblockq_get_read_index(s->memblockq);
+
+        if (indexw < indexr)
+            /* OK, the sink already asked for this data, so
+             * let's have it usk us again */
+
+            pa_sink_input_request_rewind(s->sink_input, indexr - indexw, FALSE);
+    }
+
+    request_bytes(s);
+}
+
 /* 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);
@@ -1000,48 +1067,42 @@ static int sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int
 
     switch (code) {
 
-        case SINK_INPUT_MESSAGE_SEEK:
+        case SINK_INPUT_MESSAGE_SEEK: {
+            int64_t windex;
+
+            windex = pa_memblockq_get_write_index(s->memblockq);
             pa_memblockq_seek(s->memblockq, offset, PA_PTR_TO_UINT(userdata));
-            request_bytes(s);
+
+            handle_seek(s, windex);
             return 0;
+        }
 
         case SINK_INPUT_MESSAGE_POST_DATA: {
+            int64_t windex;
+
             pa_assert(chunk);
 
-/*             pa_log("sink input post: %u", chunk->length); */
+/*             pa_log("sink input post: %lu", (unsigned long) chunk->length); */
 
-            if (pa_memblockq_push_align(s->memblockq, chunk) < 0) {
+            windex = pa_memblockq_get_write_index(s->memblockq);
 
+            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);
             }
 
-            request_bytes(s);
-
-            s->underrun = FALSE;
-            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 = TRUE;
-            }
-            request_bytes(s);
+            handle_seek(s, windex);
 
             return 0;
         }
 
+        case SINK_INPUT_MESSAGE_DRAIN:
         case SINK_INPUT_MESSAGE_FLUSH:
         case SINK_INPUT_MESSAGE_PREBUF_FORCE:
         case SINK_INPUT_MESSAGE_TRIGGER: {
 
+            int64_t windex;
             pa_sink_input *isync;
             void (*func)(pa_memblockq *bq);
 
@@ -1054,6 +1115,7 @@ static int sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int
                     func = pa_memblockq_prebuf_force;
                     break;
 
+                case SINK_INPUT_MESSAGE_DRAIN:
                 case SINK_INPUT_MESSAGE_TRIGGER:
                     func = pa_memblockq_prebuf_disable;
                     break;
@@ -1062,23 +1124,32 @@ static int sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int
                     pa_assert_not_reached();
             }
 
+            windex = pa_memblockq_get_write_index(s->memblockq);
             func(s->memblockq);
-            s->underrun = FALSE;
-            request_bytes(s);
+            handle_seek(s, windex);
 
             /* 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);
+                windex = pa_memblockq_get_write_index(ssync->memblockq);
                 func(ssync->memblockq);
-                ssync->underrun = FALSE;
-                request_bytes(ssync);
+                handle_seek(ssync, windex);
             }
 
             for (isync = i->sync_next; isync; isync = isync->sync_next) {
                 playback_stream *ssync = PLAYBACK_STREAM(isync->userdata);
+                windex = pa_memblockq_get_write_index(ssync->memblockq);
                 func(ssync->memblockq);
-                ssync->underrun = FALSE;
-                request_bytes(ssync);
+                handle_seek(ssync, windex);
+            }
+
+            if (code == SINK_INPUT_MESSAGE_DRAIN) {
+                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 = TRUE;
+                }
             }
 
             return 0;
@@ -1091,11 +1162,18 @@ static int sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int
             s->render_memblockq_length = pa_memblockq_get_length(s->sink_input->thread_info.render_memblockq);
             return 0;
 
-        case PA_SINK_INPUT_MESSAGE_SET_STATE:
+        case PA_SINK_INPUT_MESSAGE_SET_STATE: {
+            int64_t windex;
+
+            windex = pa_memblockq_get_write_index(s->memblockq);
 
             pa_memblockq_prebuf_force(s->memblockq);
-            request_bytes(s);
+
+            handle_seek(s, windex);
+
+            /* Fall through to the default handler */
             break;
+        }
 
         case PA_SINK_INPUT_MESSAGE_GET_LATENCY: {
             pa_usec_t *r = userdata;
@@ -1112,7 +1190,7 @@ static int sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int
 }
 
 /* Called from thread context */
-static int sink_input_pop_cb(pa_sink_input *i, size_t length, pa_memchunk *chunk) {
+static int sink_input_pop_cb(pa_sink_input *i, size_t nbytes, pa_memchunk *chunk) {
     playback_stream *s;
 
     pa_sink_input_assert_ref(i);
@@ -1122,23 +1200,58 @@ static int sink_input_pop_cb(pa_sink_input *i, size_t length, pa_memchunk *chunk
 
     if (pa_memblockq_peek(s->memblockq, chunk) < 0) {
 
+/*         pa_log("UNDERRUN"); */
+
         if (s->drain_request && pa_sink_input_safe_to_remove(i)) {
             s->drain_request = FALSE;
             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);
-        } else if (!s->underrun) {
-            s->underrun = TRUE;
+        } else if (s->underrun == 0)
             pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(s), PLAYBACK_STREAM_MESSAGE_UNDERFLOW, NULL, 0, NULL, NULL);
-        }
+
+        if (s->underrun != (size_t) -1)
+            s->underrun += nbytes;
+
+/*         pa_log("added %llu bytes, total is %llu", (unsigned long long) nbytes, (unsigned long long) s->underrun); */
+
+        request_bytes(s);
 
         return -1;
     }
 
+/*     pa_log("NOTUNDERRUN"); */
+
+    s->underrun = 0;
+
     pa_memblockq_drop(s->memblockq, chunk->length);
     request_bytes(s);
 
     return 0;
 }
 
+static void sink_input_rewind_cb(pa_sink_input *i, size_t nbytes) {
+    playback_stream *s;
+
+    pa_sink_input_assert_ref(i);
+    s = PLAYBACK_STREAM(i->userdata);
+    playback_stream_assert_ref(s);
+
+    /* If we are in an underrun, then we don't rewind */
+    if (s->underrun != 0)
+        return;
+
+    pa_memblockq_rewind(s->memblockq, nbytes);
+}
+
+static void sink_input_set_max_rewind_cb(pa_sink_input *i, size_t nbytes) {
+    playback_stream *s;
+
+    pa_sink_input_assert_ref(i);
+    s = PLAYBACK_STREAM(i->userdata);
+    playback_stream_assert_ref(s);
+
+    pa_memblockq_set_maxrewind(s->memblockq, nbytes);
+}
+
 /* Called from main context */
 static void sink_input_kill_cb(pa_sink_input *i) {
     playback_stream *s;
@@ -1416,7 +1529,7 @@ static void command_create_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GC
         (no_move ?  PA_SINK_INPUT_DONT_MOVE : 0) |
         (variable_rate ?  PA_SINK_INPUT_VARIABLE_RATE : 0);
 
-    s = playback_stream_new(c, sink, &ss, &map, name, &maxlength, &tlength, &prebuf, &minreq, &volume, muted, syncid, &missing, flags, p, adjust_latency);
+    s = playback_stream_new(c, sink, &ss, &map, &maxlength, &tlength, &prebuf, &minreq, &volume, muted, syncid, &missing, flags, p, adjust_latency);
     pa_proplist_free(p);
 
     CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_INVALID);
@@ -1625,7 +1738,7 @@ static void command_create_record_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_
         (no_move ?  PA_SOURCE_OUTPUT_DONT_MOVE : 0) |
         (variable_rate ?  PA_SOURCE_OUTPUT_VARIABLE_RATE : 0);
 
-    s = record_stream_new(c, source, &ss, &map, name, &maxlength, &fragment_size, flags, p, adjust_latency);
+    s = record_stream_new(c, source, &ss, &map, &maxlength, &fragment_size, flags, p, adjust_latency);
     pa_proplist_free(p);
 
     CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_INVALID);
@@ -1721,7 +1834,6 @@ static void command_auth(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t
                     pa_log_warn("failed to get GID of group '%s'", c->protocol->auth_group);
                 else if (gid == creds->gid)
                     success = 1;
-
                 if (!success) {
                     if ((r = pa_uid_in_group(creds->uid, c->protocol->auth_group)) < 0)
                         pa_log_warn("failed to check group membership.");
@@ -1739,7 +1851,7 @@ static void command_auth(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t
                 pa_mempool_is_shared(c->protocol->core->mempool) &&
                 creds->uid == getuid()) {
 
-                pa_pstream_use_shm(c->pstream, 1);
+                pa_pstream_enable_shm(c->pstream, TRUE);
                 pa_log_info("Enabled SHM for new connection");
             }
 
diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c
index 01e3bd9..7e6c5de 100644
--- a/src/pulsecore/sink-input.c
+++ b/src/pulsecore/sink-input.c
@@ -42,7 +42,7 @@
 
 #include "sink-input.h"
 
-#define MEMBLOCKQ_MAXLENGTH (16*1024*1024)
+#define MEMBLOCKQ_MAXLENGTH (32*1024*1024)
 #define CONVERT_BUFFER_LENGTH (PA_PAGE_SIZE)
 #define MOVE_BUFFER_LENGTH (PA_PAGE_SIZE*256)
 
@@ -94,6 +94,20 @@ void pa_sink_input_new_data_done(pa_sink_input_new_data *data) {
     pa_proplist_free(data->proplist);
 }
 
+static void reset_callbacks(pa_sink_input *i) {
+    pa_assert(i);
+
+    i->pop = NULL;
+    i->rewind = NULL;
+    i->set_max_rewind = NULL;
+    i->attach = NULL;
+    i->detach = NULL;
+    i->suspend = NULL;
+    i->moved = NULL;
+    i->kill = NULL;
+    i->get_latency = NULL;
+}
+
 pa_sink_input* pa_sink_input_new(
         pa_core *core,
         pa_sink_input_new_data *data,
@@ -102,7 +116,6 @@ pa_sink_input* pa_sink_input_new(
     pa_sink_input *i;
     pa_resampler *resampler = NULL;
     char st[PA_SAMPLE_SPEC_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX];
-    pa_memblock *silence;
 
     pa_assert(core);
     pa_assert(data);
@@ -223,15 +236,7 @@ pa_sink_input* pa_sink_input_new(
     } else
         i->sync_next = i->sync_prev = NULL;
 
-    i->pop = NULL;
-    i->rewind = NULL;
-    i->set_max_rewind = NULL;
-    i->kill = NULL;
-    i->get_latency = NULL;
-    i->attach = NULL;
-    i->detach = NULL;
-    i->suspend = NULL;
-    i->moved = NULL;
+    reset_callbacks(i);
     i->userdata = NULL;
 
     i->thread_info.state = i->state;
@@ -244,10 +249,9 @@ pa_sink_input* pa_sink_input_new(
     i->thread_info.muted = i->muted;
     i->thread_info.requested_sink_latency = 0;
     i->thread_info.rewrite_nbytes = 0;
+    i->thread_info.since_underrun = 0;
     i->thread_info.ignore_rewind = FALSE;
 
-    silence = pa_silence_memblock_new(i->sink->core->mempool, &i->sink->sample_spec, 0);
-
     i->thread_info.render_memblockq = pa_memblockq_new(
             0,
             MEMBLOCKQ_MAXLENGTH,
@@ -256,9 +260,7 @@ pa_sink_input* pa_sink_input_new(
             0,
             1,
             0,
-            silence);
-
-    pa_memblock_unref(silence);
+            &i->sink->silence);
 
     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);
@@ -349,15 +351,7 @@ void pa_sink_input_unlink(pa_sink_input *i) {
     } else
         i->state = PA_SINK_INPUT_UNLINKED;
 
-    i->pop = NULL;
-    i->rewind = NULL;
-    i->set_max_rewind = NULL;
-    i->kill = NULL;
-    i->get_latency = NULL;
-    i->attach = NULL;
-    i->detach = NULL;
-    i->suspend = NULL;
-    i->moved = NULL;
+    reset_callbacks(i);
 
     if (linked) {
         pa_subscription_post(i->sink->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_REMOVE, i->index);
@@ -395,19 +389,21 @@ static void sink_input_free(pa_object *o) {
 }
 
 void pa_sink_input_put(pa_sink_input *i) {
+    pa_sink_input_state_t state;
     pa_sink_input_assert_ref(i);
 
     pa_assert(i->state == PA_SINK_INPUT_INIT);
     pa_assert(i->pop);
+    pa_assert(i->rewind);
 
-    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;
 
-    if (i->state == PA_SINK_INPUT_CORKED)
-        i->sink->n_corked++;
+    state = i->flags & PA_SINK_INPUT_START_CORKED ? PA_SINK_INPUT_CORKED : PA_SINK_INPUT_RUNNING;
+
+    update_n_corked(i, state);
+    i->thread_info.state = i->state = state;
 
-    pa_sink_update_status(i->sink);
     pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i->sink), PA_SINK_MESSAGE_ADD_INPUT, i, 0, NULL);
 
     pa_subscription_post(i->sink->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_NEW, i->index);
@@ -454,18 +450,20 @@ int pa_sink_input_peek(pa_sink_input *i, size_t slength /* in sink frames */, pa
     pa_assert(chunk);
     pa_assert(volume);
 
-    pa_log_debug("peek");
+/*     pa_log_debug("peek"); */
 
-    if (!i->pop || i->thread_info.state == PA_SINK_INPUT_CORKED)
+    if (!i->pop)
         return -1;
 
-    pa_assert(i->thread_info.state == PA_SINK_INPUT_RUNNING || i->thread_info.state == PA_SINK_INPUT_DRAINED);
+    pa_assert(i->thread_info.state == PA_SINK_INPUT_RUNNING ||
+              i->thread_info.state == PA_SINK_INPUT_CORKED ||
+              i->thread_info.state == PA_SINK_INPUT_DRAINED);
 
     /* If there's still some rewrite request the handle, but the sink
     didn't do this for us, we do it here. However, since the sink
     apparently doesn't support rewinding, we pass 0 here. This still
     allows rewinding through the render buffer. */
-    pa_sink_input_rewind(i, 0);
+    pa_sink_input_process_rewind(i, 0);
 
     block_size_max_sink_input = i->thread_info.resampler ?
         pa_resampler_max_block_size(i->thread_info.resampler) :
@@ -504,11 +502,15 @@ int pa_sink_input_peek(pa_sink_input *i, size_t slength /* in sink frames */, pa
         /* There's nothing in our render queue. We need to fill it up
          * with data from the implementor. */
 
-        if (i->pop(i, ilength, &tchunk) < 0) {
+        if (i->thread_info.state == PA_SINK_INPUT_CORKED ||
+            i->pop(i, ilength, &tchunk) < 0) {
+
+            /* OK, we're corked or the implementor didn't give us any
+             * data, so let's just hand out silence */
             pa_atomic_store(&i->thread_info.drained, 1);
 
-            /* OK, we got no data from the implementor, so let's just skip ahead */
             pa_memblockq_seek(i->thread_info.render_memblockq, slength, PA_SEEK_RELATIVE_ON_READ);
+            i->thread_info.since_underrun = 0;
             break;
         }
 
@@ -517,10 +519,13 @@ int pa_sink_input_peek(pa_sink_input *i, size_t slength /* in sink frames */, pa
         pa_assert(tchunk.length > 0);
         pa_assert(tchunk.memblock);
 
+        i->thread_info.since_underrun += tchunk.length;
+
         while (tchunk.length > 0) {
             pa_memchunk wchunk;
 
             wchunk = tchunk;
+            pa_memblock_ref(wchunk.memblock);
 
             if (wchunk.length > block_size_max_sink_input)
                 wchunk.length = block_size_max_sink_input;
@@ -529,6 +534,8 @@ int pa_sink_input_peek(pa_sink_input *i, size_t slength /* in sink frames */, pa
             if (do_volume_adj_here && !volume_is_norm) {
                 pa_memchunk_make_writable(&wchunk, 0);
 
+                pa_log_debug("adjusting volume!");
+
                 if (i->thread_info.muted)
                     pa_silence_memchunk(&wchunk, &i->thread_info.sample_spec);
                 else
@@ -547,6 +554,8 @@ int pa_sink_input_peek(pa_sink_input *i, size_t slength /* in sink frames */, pa
                 }
             }
 
+            pa_memblock_unref(wchunk.memblock);
+
             tchunk.index += wchunk.length;
             tchunk.length -= wchunk.length;
         }
@@ -581,22 +590,18 @@ int pa_sink_input_peek(pa_sink_input *i, size_t slength /* in sink frames */, pa
 
 /* Called from thread context */
 void pa_sink_input_drop(pa_sink_input *i, size_t nbytes /* in sink sample spec */) {
-
     pa_sink_input_assert_ref(i);
 
     pa_assert(PA_SINK_INPUT_LINKED(i->thread_info.state));
     pa_assert(pa_frame_aligned(nbytes, &i->sink->sample_spec));
     pa_assert(nbytes > 0);
 
-    if (i->thread_info.state == PA_SINK_INPUT_CORKED)
-        return;
-
     /* If there's still some rewrite request the handle, but the sink
     didn't do this for us, we do it here. However, since the sink
     apparently doesn't support rewinding, we pass 0 here. This still
     allows rewinding through the render buffer. */
     if (i->thread_info.rewrite_nbytes > 0)
-        pa_sink_input_rewind(i, 0);
+        pa_sink_input_process_rewind(i, 0);
 
     pa_memblockq_drop(i->thread_info.render_memblockq, nbytes);
 
@@ -604,25 +609,22 @@ void pa_sink_input_drop(pa_sink_input *i, size_t nbytes /* in sink sample spec *
 }
 
 /* Called from thread context */
-void pa_sink_input_rewind(pa_sink_input *i, size_t nbytes /* in sink sample spec */) {
+void pa_sink_input_process_rewind(pa_sink_input *i, size_t nbytes /* in sink sample spec */) {
     pa_sink_input_assert_ref(i);
 
     pa_assert(PA_SINK_INPUT_LINKED(i->thread_info.state));
     pa_assert(pa_frame_aligned(nbytes, &i->sink->sample_spec));
 
-    pa_log_debug("rewind(%lu, %lu)", (unsigned long) nbytes, (unsigned long) i->thread_info.rewrite_nbytes);
-
-    if (i->thread_info.state == PA_SINK_INPUT_CORKED)
-        return;
+/*     pa_log_debug("rewind(%lu, %lu)", (unsigned long) nbytes, (unsigned long) i->thread_info.rewrite_nbytes); */
 
     if (i->thread_info.ignore_rewind) {
-        i->thread_info.rewrite_nbytes = 0;
         i->thread_info.ignore_rewind = FALSE;
+        i->thread_info.rewrite_nbytes = 0;
         return;
     }
 
     if (nbytes > 0)
-        pa_log_debug("Have to rewind %lu bytes.", (unsigned long) nbytes);
+        pa_log_debug("Have to rewind %lu bytes on render memblockq.", (unsigned long) nbytes);
 
     if (i->thread_info.rewrite_nbytes > 0) {
         size_t max_rewrite;
@@ -641,19 +643,23 @@ void pa_sink_input_rewind(pa_sink_input *i, size_t nbytes /* in sink sample spec
             /* Convert back to to sink domain */
             r = i->thread_info.resampler ? pa_resampler_result(i->thread_info.resampler, amount) : amount;
 
-            /* Ok, now update the write pointer */
-            pa_memblockq_seek(i->thread_info.render_memblockq, -r, PA_SEEK_RELATIVE);
+            if (r > 0)
+                /* Ok, now update the write pointer */
+                pa_memblockq_seek(i->thread_info.render_memblockq, -r, PA_SEEK_RELATIVE);
+
+            if (amount) {
+                pa_log_debug("Have to rewind %lu bytes on implementor.", (unsigned long) amount);
 
-            /* Tell the implementor */
-            if (i->rewind)
-                i->rewind(i, amount);
+                /* Tell the implementor */
+                if (i->rewind)
+                    i->rewind(i, amount);
+            }
 
             /* And reset the resampler */
             if (i->thread_info.resampler)
                 pa_resampler_reset(i->thread_info.resampler);
         }
 
-
         i->thread_info.rewrite_nbytes = 0;
     }
 
@@ -664,7 +670,6 @@ void pa_sink_input_rewind(pa_sink_input *i, size_t nbytes /* in sink sample spec
 /* Called from thread context */
 void pa_sink_input_set_max_rewind(pa_sink_input *i, size_t nbytes  /* in the sink's sample spec */) {
     pa_sink_input_assert_ref(i);
-
     pa_assert(PA_SINK_INPUT_LINKED(i->thread_info.state));
     pa_assert(pa_frame_aligned(nbytes, &i->sink->sample_spec));
 
@@ -935,7 +940,7 @@ int pa_sink_input_move_to(pa_sink_input *i, pa_sink *dest, int immediately) {
 
     /* Replace resampler */
     if (new_resampler != i->thread_info.resampler) {
-        pa_memblock *silence;
+        pa_memchunk silence;
 
         if (i->thread_info.resampler)
             pa_resampler_free(i->thread_info.resampler);
@@ -944,9 +949,15 @@ int pa_sink_input_move_to(pa_sink_input *i, pa_sink *dest, int immediately) {
         /* if the resampler changed, the silence memblock is
          * probably invalid now, too */
 
-        silence = pa_silence_memblock_new(i->sink->core->mempool, &dest->sample_spec, new_resampler ? pa_resampler_max_block_size(new_resampler) : 0);
-        pa_memblockq_set_silence(i->thread_info.render_memblockq, silence);
-        pa_memblock_unref(silence);
+        pa_silence_memchunk_get(
+                &i->sink->core->silence_cache,
+                i->sink->core->mempool,
+                &silence,
+                &dest->sample_spec,
+                0);
+
+        pa_memblockq_set_silence(i->thread_info.render_memblockq, &silence);
+        pa_memblock_unref(silence.memblock);
 
     }
 
@@ -974,6 +985,35 @@ int pa_sink_input_move_to(pa_sink_input *i, pa_sink *dest, int immediately) {
     return 0;
 }
 
+static void set_state(pa_sink_input *i, pa_sink_input_state_t state) {
+    pa_sink_input_assert_ref(i);
+
+    if ((state == PA_SINK_INPUT_DRAINED || state == 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);
+
+    if (state == PA_SINK_INPUT_CORKED && i->thread_info.state != PA_SINK_INPUT_CORKED) {
+
+        /* OK, we're corked, so let's make sure we have total silence
+         * from now on on this stream */
+        pa_memblockq_silence(i->thread_info.render_memblockq);
+
+        /* This will tell the implementing sink input driver to rewind
+         * so that the unplayed already mixed data is not lost */
+        pa_sink_input_request_rewind(i, 0, FALSE);
+
+    } else if (i->thread_info.state == PA_SINK_INPUT_CORKED && state != PA_SINK_INPUT_CORKED) {
+
+        /* OK, we're being uncorked. Make sure we're not rewound when
+         * the hw buffer is remixed and request a remix. */
+        i->thread_info.ignore_rewind = TRUE;
+        i->thread_info.since_underrun = 0;
+        pa_sink_request_rewind(i->sink, 0);
+    }
+
+    i->thread_info.state = state;
+}
+
 /* 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);
@@ -984,12 +1024,12 @@ int pa_sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int64_t
     switch (code) {
         case PA_SINK_INPUT_MESSAGE_SET_VOLUME:
             i->thread_info.volume = *((pa_cvolume*) userdata);
-            pa_sink_input_request_rewrite(i, 0);
+            pa_sink_input_request_rewind(i, 0, FALSE);
             return 0;
 
         case PA_SINK_INPUT_MESSAGE_SET_MUTE:
             i->thread_info.muted = PA_PTR_TO_UINT(userdata);
-            pa_sink_input_request_rewrite(i, 0);
+            pa_sink_input_request_rewind(i, 0, FALSE);
             return 0;
 
         case PA_SINK_INPUT_MESSAGE_GET_LATENCY: {
@@ -1010,25 +1050,13 @@ int pa_sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int64_t
         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);
+            set_state(i, PA_PTR_TO_UINT(userdata));
 
-            i->thread_info.state = PA_PTR_TO_UINT(userdata);
+            for (ssync = i->thread_info.sync_prev; ssync; ssync = ssync->thread_info.sync_prev)
+                set_state(ssync, 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);
-            }
+            for (ssync = i->thread_info.sync_next; ssync; ssync = ssync->thread_info.sync_next)
+                set_state(ssync, PA_PTR_TO_UINT(userdata));
 
             return 0;
         }
@@ -1062,24 +1090,42 @@ pa_bool_t pa_sink_input_safe_to_remove(pa_sink_input *i) {
     return TRUE;
 }
 
-void pa_sink_input_request_rewrite(pa_sink_input *i, size_t nbytes  /* in our sample spec */) {
+void pa_sink_input_request_rewind(pa_sink_input *i, size_t nbytes  /* in our sample spec */, pa_bool_t ignore_underruns) {
     size_t l, lbq;
 
     pa_sink_input_assert_ref(i);
 
+    /* We don't take rewind requests while we are corked */
+    if (i->state == PA_SINK_INPUT_CORKED)
+        return;
+
     lbq = pa_memblockq_get_length(i->thread_info.render_memblockq);
 
     if (nbytes <= 0) {
+        /* Calulate maximum number of bytes that could be rewound in theory */
+        nbytes = i->sink->thread_info.max_rewind + lbq;
+
+        /* Transform from sink domain */
         nbytes =
             i->thread_info.resampler ?
-            pa_resampler_request(i->thread_info.resampler, i->sink->thread_info.max_rewind + lbq) :
-            (i->sink->thread_info.max_rewind + lbq);
+            pa_resampler_request(i->thread_info.resampler, nbytes) :
+            nbytes;
     }
 
-    i->thread_info.rewrite_nbytes = PA_MAX(nbytes, i->thread_info.rewrite_nbytes);
+    /* Increase the number of bytes to rewrite, never decrease */
+    if (nbytes > i->thread_info.rewrite_nbytes)
+        i->thread_info.rewrite_nbytes = nbytes;
+
+    if (!ignore_underruns) {
+        /* Make sure to not overwrite over underruns */
+        if ((int64_t) i->thread_info.rewrite_nbytes > i->thread_info.since_underrun)
+            i->thread_info.rewrite_nbytes = (size_t) i->thread_info.since_underrun;
+    }
 
     /* Transform to sink domain */
-    l = i->thread_info.resampler ? pa_resampler_result(i->thread_info.resampler, nbytes) : nbytes;
+    l = i->thread_info.resampler ?
+        pa_resampler_result(i->thread_info.resampler, i->thread_info.rewrite_nbytes) :
+        i->thread_info.rewrite_nbytes;
 
     if (l <= 0)
         return;
@@ -1087,3 +1133,17 @@ void pa_sink_input_request_rewrite(pa_sink_input *i, size_t nbytes  /* in our sa
     if (l > lbq)
         pa_sink_request_rewind(i->sink, l - lbq);
 }
+
+pa_memchunk* pa_sink_input_get_silence(pa_sink_input *i, pa_memchunk *ret) {
+    pa_sink_input_assert_ref(i);
+    pa_assert(ret);
+
+    pa_silence_memchunk_get(
+                &i->sink->core->silence_cache,
+                i->sink->core->mempool,
+                ret,
+                &i->sample_spec,
+                i->thread_info.resampler ? pa_resampler_max_block_size(i->thread_info.resampler) : 0);
+
+    return ret;
+}
diff --git a/src/pulsecore/sink-input.h b/src/pulsecore/sink-input.h
index 8545dea..184a2c4 100644
--- a/src/pulsecore/sink-input.h
+++ b/src/pulsecore/sink-input.h
@@ -97,16 +97,16 @@ struct pa_sink_input {
      * 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 (*pop) (pa_sink_input *i, size_t request_nbytes, pa_memchunk *chunk);
+    int (*pop) (pa_sink_input *i, size_t request_nbytes, pa_memchunk *chunk); /* may NOT be NULL */
 
     /* Rewind the queue by the specified number of bytes. Called just
      * before peek() if it is called at all. Only called if the sink
      * input driver ever plans to call
-     * pa_sink_input_request_rewrite(). Called from IO context. */
-    void (*rewind) (pa_sink_input *i, size_t nbytes);     /* may be NULL */
+     * pa_sink_input_request_rewind(). Called from IO context. */
+    void (*rewind) (pa_sink_input *i, size_t nbytes);     /* may NOT be NULL */
 
     /* Called whenever the maximum rewindable size of the sink
-     * changes. Called from UI context. */
+     * changes. Called from RT context. */
     void (*set_max_rewind) (pa_sink_input *i, size_t nbytes); /* may be NULL */
 
     /* If non-NULL this function is called when the input is first
@@ -150,7 +150,9 @@ struct pa_sink_input {
 
         /* We maintain a history of resampled audio data here. */
         pa_memblockq *render_memblockq;
+
         size_t rewrite_nbytes;
+        int64_t since_underrun;
         pa_bool_t ignore_rewind;
 
         pa_sink_input *sync_prev, *sync_next;
@@ -229,14 +231,13 @@ void pa_sink_input_set_name(pa_sink_input *i, const char *name);
 pa_usec_t pa_sink_input_set_requested_latency(pa_sink_input *i, pa_usec_t usec);
 
 /* Request that the specified number of bytes already written out to
-the hw device is rewritten, if possible. If this function is used you
-need to supply the ->rewind() function pointer. Please note that this
-is only a kind request. The sink driver may not be able to fulfill it
+the hw device is rewritten, if possible.  Please note that this is
+only a kind request. The sink driver may not be able to fulfill it
 fully -- or at all. If the request for a rewrite was successful, the
 sink driver will call ->rewind() and pass the number of bytes that
 could be rewound in the HW device. This functionality is required for
 implementing the "zero latency" write-through functionality. */
-void pa_sink_input_request_rewrite(pa_sink_input *i, size_t nbytes);
+void pa_sink_input_request_rewind(pa_sink_input *i, size_t nbytes, pa_bool_t ignore_rewind);
 
 /* Callable by everyone from main thread*/
 
@@ -265,7 +266,7 @@ pa_bool_t pa_sink_input_safe_to_remove(pa_sink_input *i);
 
 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);
-void pa_sink_input_rewind(pa_sink_input *i, size_t nbytes /* in the sink's sample spec */);
+void pa_sink_input_process_rewind(pa_sink_input *i, size_t nbytes /* in the sink's sample spec */);
 void pa_sink_input_set_max_rewind(pa_sink_input *i, size_t nbytes  /* in the sink's sample spec */);
 
 int pa_sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offset, pa_memchunk *chunk);
@@ -277,5 +278,6 @@ typedef struct pa_sink_input_move_info {
     size_t buffer_bytes;
 } pa_sink_input_move_info;
 
+pa_memchunk* pa_sink_input_get_silence(pa_sink_input *i, pa_memchunk *ret);
 
 #endif
diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c
index 6dcc7ab..f631de3 100644
--- a/src/pulsecore/sink.c
+++ b/src/pulsecore/sink.c
@@ -105,6 +105,19 @@ void pa_sink_new_data_done(pa_sink_new_data *data) {
     pa_proplist_free(data->proplist);
 }
 
+static void reset_callbacks(pa_sink *s) {
+    pa_assert(s);
+
+    s->set_state = NULL;
+    s->get_volume = NULL;
+    s->set_volume = NULL;
+    s->get_mute = NULL;
+    s->set_mute = NULL;
+    s->get_latency = NULL;
+    s->request_rewind = NULL;
+    s->update_requested_latency = NULL;
+}
+
 pa_sink* pa_sink_new(
         pa_core *core,
         pa_sink_new_data *data,
@@ -182,19 +195,18 @@ pa_sink* pa_sink_new(
     s->muted = data->muted;
     s->refresh_volume = s->refresh_mute = FALSE;
 
-    s->get_latency = NULL;
-    s->set_volume = NULL;
-    s->get_volume = NULL;
-    s->set_mute = NULL;
-    s->get_mute = NULL;
-    s->set_state = NULL;
-    s->request_rewind = NULL;
-    s->update_requested_latency = NULL;
+    reset_callbacks(s);
     s->userdata = NULL;
 
     s->asyncmsgq = NULL;
     s->rtpoll = NULL;
-    s->silence = pa_silence_memblock_new(core->mempool, &s->sample_spec, 0);
+
+    pa_silence_memchunk_get(
+            &core->silence_cache,
+            core->mempool,
+            &s->silence,
+            &s->sample_spec,
+            0);
 
     s->min_latency = DEFAULT_MIN_LATENCY;
     s->max_latency = s->min_latency;
@@ -239,6 +251,7 @@ pa_sink* pa_sink_new(
     }
 
     s->monitor_source->monitor_of = s;
+    pa_source_set_max_rewind(s->monitor_source, s->thread_info.max_rewind);
 
     return s;
 }
@@ -336,14 +349,7 @@ void pa_sink_unlink(pa_sink* s) {
     else
         s->state = PA_SINK_UNLINKED;
 
-    s->get_latency = NULL;
-    s->get_volume = NULL;
-    s->set_volume = NULL;
-    s->set_mute = NULL;
-    s->get_mute = NULL;
-    s->set_state = NULL;
-    s->request_rewind = NULL;
-    s->update_requested_latency = NULL;
+    reset_callbacks(s);
 
     if (s->monitor_source)
         pa_source_unlink(s->monitor_source);
@@ -378,8 +384,8 @@ static void sink_free(pa_object *o) {
 
     pa_hashmap_free(s->thread_info.inputs, NULL, NULL);
 
-    if (s->silence)
-        pa_memblock_unref(s->silence);
+    if (s->silence.memblock)
+        pa_memblock_unref(s->silence.memblock);
 
     pa_xfree(s->name);
     pa_xfree(s->driver);
@@ -429,37 +435,31 @@ int pa_sink_suspend(pa_sink *s, pa_bool_t suspend) {
         return sink_set_state(s, pa_sink_used_by(s) ? PA_SINK_RUNNING : PA_SINK_IDLE);
 }
 
-void pa_sink_ping(pa_sink *s) {
-    pa_sink_assert_ref(s);
-    pa_assert(PA_SINK_LINKED(s->state));
-
-    pa_asyncmsgq_post(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_PING, NULL, 0, NULL, NULL);
-}
-
-void pa_sink_process_rewind(pa_sink *s) {
+void pa_sink_process_rewind(pa_sink *s, size_t nbytes) {
     pa_sink_input *i;
     void *state = NULL;
     pa_sink_assert_ref(s);
     pa_assert(PA_SINK_LINKED(s->state));
 
-    if (s->thread_info.rewind_nbytes <= 0)
+    if (nbytes <= 0)
         return;
 
     pa_log_debug("Processing rewind...");
 
     while ((i = pa_hashmap_iterate(s->thread_info.inputs, &state, NULL))) {
         pa_sink_input_assert_ref(i);
-
-        pa_sink_input_rewind(i, s->thread_info.rewind_nbytes);
+        pa_sink_input_process_rewind(i, nbytes);
     }
 
-    s->thread_info.rewind_nbytes = 0;
+    if (s->monitor_source && PA_SOURCE_OPENED(pa_source_get_state(s->monitor_source)))
+        pa_source_process_rewind(s->monitor_source, nbytes);
 }
 
-static unsigned fill_mix_info(pa_sink *s, size_t length, pa_mix_info *info, unsigned maxinfo) {
+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;
+    size_t mixlength = *length;
 
     pa_sink_assert_ref(s);
     pa_assert(info);
@@ -467,9 +467,12 @@ static unsigned fill_mix_info(pa_sink *s, size_t length, pa_mix_info *info, unsi
     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, length, &info->chunk, &info->volume) < 0)
+        if (pa_sink_input_peek(i, *length, &info->chunk, &info->volume) < 0)
             continue;
 
+        if (mixlength == 0 || info->chunk.length < mixlength)
+            mixlength = info->chunk.length;
+
         if (pa_memblock_is_silence(info->chunk.memblock)) {
             pa_memblock_unref(info->chunk.memblock);
             continue;
@@ -485,6 +488,9 @@ static unsigned fill_mix_info(pa_sink *s, size_t length, pa_mix_info *info, unsi
         maxinfo--;
     }
 
+    if (mixlength > 0)
+        *length = mixlength;
+
     return n;
 }
 
@@ -569,13 +575,15 @@ void pa_sink_render(pa_sink*s, size_t length, pa_memchunk *result) {
 
     pa_assert(length > 0);
 
-    n = s->thread_info.state == PA_SINK_RUNNING ? fill_mix_info(s, length, info, MAX_MIX_CHANNELS) : 0;
+    n = s->thread_info.state == PA_SINK_RUNNING ? fill_mix_info(s, &length, info, MAX_MIX_CHANNELS) : 0;
 
     if (n == 0) {
 
-        result->memblock = pa_memblock_ref(s->silence);
-        result->length = PA_MIN(pa_memblock_get_length(s->silence), length);
-        result->index = 0;
+        *result = s->silence;
+        pa_memblock_ref(result->memblock);
+
+        if (result->length > length)
+            result->length = length;
 
     } else if (n == 1) {
         pa_cvolume volume;
@@ -589,6 +597,7 @@ void pa_sink_render(pa_sink*s, size_t length, pa_memchunk *result) {
         pa_sw_cvolume_multiply(&volume, &s->thread_info.soft_volume, &info[0].volume);
 
         if (s->thread_info.soft_muted || !pa_cvolume_is_norm(&volume)) {
+            pa_log("adjusting volume ");
             pa_memchunk_make_writable(result, 0);
             if (s->thread_info.soft_muted || pa_cvolume_is_muted(&volume))
                 pa_silence_memchunk(result, &s->sample_spec);
@@ -600,7 +609,11 @@ void pa_sink_render(pa_sink*s, size_t length, pa_memchunk *result) {
         result->memblock = pa_memblock_new(s->core->mempool, length);
 
         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);
+        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->index = 0;
@@ -618,6 +631,7 @@ void pa_sink_render(pa_sink*s, size_t length, pa_memchunk *result) {
 void pa_sink_render_into(pa_sink*s, pa_memchunk *target) {
     pa_mix_info info[MAX_MIX_CHANNELS];
     unsigned n;
+    size_t length, block_size_max;
 
     pa_sink_assert_ref(s);
     pa_assert(PA_SINK_OPENED(s->thread_info.state));
@@ -630,34 +644,44 @@ void pa_sink_render_into(pa_sink*s, pa_memchunk *target) {
 
     s->thread_info.rewind_nbytes = 0;
 
-    n = s->thread_info.state == PA_SINK_RUNNING ? fill_mix_info(s, target->length, info, MAX_MIX_CHANNELS) : 0;
+    length = target->length;
+    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);
+
+    n = s->thread_info.state == PA_SINK_RUNNING ? fill_mix_info(s, &length, info, MAX_MIX_CHANNELS) : 0;
+
+    if (n == 0) {
+        if (target->length > length)
+            target->length = length;
 
-    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;
+    } else if (n == 1) {
+        pa_cvolume volume;
+
+        if (target->length > length)
+            target->length = length;
+
+        pa_sw_cvolume_multiply(&volume, &s->thread_info.soft_volume, &info[0].volume);
 
-        if (s->thread_info.soft_muted)
+        if (s->thread_info.soft_muted || pa_cvolume_is_muted(&volume))
             pa_silence_memchunk(target, &s->sample_spec);
         else {
-            void *src, *ptr;
-            pa_cvolume volume;
+            pa_memchunk vchunk;
 
-            ptr = pa_memblock_acquire(target->memblock);
-            src = pa_memblock_acquire(info[0].chunk.memblock);
+            vchunk = info[0].chunk;
+            pa_memblock_ref(vchunk.memblock);
 
-            memcpy((uint8_t*) ptr + target->index,
-                   (uint8_t*) src + info[0].chunk.index,
-                   target->length);
+            if (vchunk.length > target->length)
+                vchunk.length = 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_memchunk_make_writable(&vchunk, 0);
+                pa_volume_memchunk(&vchunk, &s->sample_spec, &volume);
+            }
 
-            if (!pa_cvolume_is_norm(&volume))
-                pa_volume_memchunk(target, &s->sample_spec, &volume);
+            pa_memchunk_memcpy(target, &vchunk);
+            pa_memblock_unref(vchunk.memblock);
         }
 
     } else {
@@ -666,8 +690,7 @@ void pa_sink_render_into(pa_sink*s, pa_memchunk *target) {
         ptr = pa_memblock_acquire(target->memblock);
 
         target->length = pa_mix(info, n,
-                                (uint8_t*) ptr + target->index,
-                                target->length,
+                                (uint8_t*) ptr + target->index, length,
                                 &s->sample_spec,
                                 &s->thread_info.soft_volume,
                                 s->thread_info.soft_muted);
@@ -923,12 +946,11 @@ unsigned pa_sink_used_by(pa_sink *s) {
 
     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;
+    return ret - s->n_corked;
 }
 
 int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offset, pa_memchunk *chunk) {
@@ -973,7 +995,9 @@ int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offse
 
             pa_sink_invalidate_requested_latency(s);
 
+            /* Make sure we're not rewound when the hw buffer is remixed and request a remix*/
             i->thread_info.ignore_rewind = TRUE;
+            i->thread_info.since_underrun = 0;
             pa_sink_request_rewind(s, 0);
 
             return 0;
@@ -1124,9 +1148,6 @@ int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offse
             *((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);
@@ -1286,7 +1307,6 @@ void pa_sink_set_max_rewind(pa_sink *s, size_t max_rewind) {
     void *state = NULL;
 
     pa_sink_assert_ref(s);
-    pa_assert(PA_SINK_LINKED(s->thread_info.state));
 
     if (max_rewind == s->thread_info.max_rewind)
         return;
@@ -1295,6 +1315,9 @@ void pa_sink_set_max_rewind(pa_sink *s, size_t max_rewind) {
 
     while ((i = pa_hashmap_iterate(s->thread_info.inputs, &state, NULL)))
         pa_sink_input_set_max_rewind(i, s->thread_info.max_rewind);
+
+    if (s->monitor_source)
+        pa_source_set_max_rewind(s->monitor_source, s->thread_info.max_rewind);
 }
 
 void pa_sink_invalidate_requested_latency(pa_sink *s) {
diff --git a/src/pulsecore/sink.h b/src/pulsecore/sink.h
index 2dfd845..97491f4 100644
--- a/src/pulsecore/sink.h
+++ b/src/pulsecore/sink.h
@@ -89,14 +89,14 @@ struct pa_sink {
     pa_asyncmsgq *asyncmsgq;
     pa_rtpoll *rtpoll;
 
-    pa_memblock *silence;
+    pa_memchunk silence;
 
     pa_usec_t min_latency; /* we won't go below this latency */
     pa_usec_t max_latency; /* An upper limit for the latencies */
 
     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 (*set_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 */
@@ -138,7 +138,6 @@ typedef enum pa_sink_message {
     PA_SINK_MESSAGE_GET_LATENCY,
     PA_SINK_MESSAGE_GET_REQUESTED_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,
@@ -199,13 +198,6 @@ 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_rewind(pa_sink *s, size_t length);
-
-/* 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, 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);
@@ -217,14 +209,14 @@ unsigned pa_sink_used_by(pa_sink *s); /* Number of connected streams which are n
 
 /* To be called exclusively by the sink driver, from IO context */
 
-void pa_sink_process_rewind(pa_sink *s);
-
 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);
 
+void pa_sink_process_rewind(pa_sink *s, size_t nbytes);
+
 int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offset, pa_memchunk *chunk);
 
 void pa_sink_attach_within_thread(pa_sink *s);
diff --git a/src/pulsecore/sound-file-stream.c b/src/pulsecore/sound-file-stream.c
index 7e0f8ef..9030d6d 100644
--- a/src/pulsecore/sound-file-stream.c
+++ b/src/pulsecore/sound-file-stream.c
@@ -235,7 +235,7 @@ int pa_play_file(
     pa_sample_spec ss;
     pa_sink_input_new_data data;
     int fd;
-    pa_memblock *silence;
+    pa_memchunk silence;
 
     pa_assert(sink);
     pa_assert(fname);
@@ -336,13 +336,9 @@ int pa_play_file(
     u->sink_input->kill = sink_input_kill_cb;
     u->sink_input->userdata = u;
 
-    silence = pa_silence_memblock_new(
-            u->core->mempool,
-            &u->sink_input->sample_spec,
-            u->sink_input->thread_info.resampler ? pa_resampler_max_block_size(u->sink_input->thread_info.resampler) : 0);
-
-    u->memblockq = pa_memblockq_new(0, MEMBLOCKQ_MAXLENGTH, 0, pa_frame_size(&u->sink_input->sample_spec), 1, 1, 0, silence);
-    pa_memblock_unref(silence);
+    pa_sink_input_get_silence(u->sink_input, &silence);
+    u->memblockq = pa_memblockq_new(0, MEMBLOCKQ_MAXLENGTH, 0, pa_frame_size(&u->sink_input->sample_spec), 1, 1, 0, &silence);
+    pa_memblock_unref(silence.memblock);
 
     pa_sink_input_put(u->sink_input);
 
diff --git a/src/pulsecore/source-output.c b/src/pulsecore/source-output.c
index c0cbb42..318f6f8 100644
--- a/src/pulsecore/source-output.c
+++ b/src/pulsecore/source-output.c
@@ -40,6 +40,8 @@
 
 #include "source-output.h"
 
+#define MEMBLOCKQ_MAXLENGTH (32*1024*1024)
+
 static PA_DEFINE_CHECK_TYPE(pa_source_output, pa_msgobject);
 
 static void source_output_free(pa_object* mo);
@@ -74,6 +76,20 @@ void pa_source_output_new_data_done(pa_source_output_new_data *data) {
     pa_proplist_free(data->proplist);
 }
 
+static void reset_callbacks(pa_source_output *o) {
+    pa_assert(o);
+
+    o->push = NULL;
+    o->rewind = NULL;
+    o->set_max_rewind = NULL;
+    o->attach = NULL;
+    o->detach = NULL;
+    o->suspend = NULL;
+    o->moved = NULL;
+    o->kill = NULL;
+    o->get_latency = NULL;
+}
+
 pa_source_output* pa_source_output_new(
         pa_core *core,
         pa_source_output_new_data *data,
@@ -175,13 +191,7 @@ pa_source_output* pa_source_output_new(
     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->moved = NULL;
+    reset_callbacks(o);
     o->userdata = NULL;
 
     o->thread_info.state = o->state;
@@ -190,6 +200,16 @@ pa_source_output* pa_source_output_new(
     o->thread_info.resampler = resampler;
     o->thread_info.requested_source_latency = 0;
 
+    o->thread_info.delay_memblockq = pa_memblockq_new(
+            0,
+            MEMBLOCKQ_MAXLENGTH,
+            0,
+            pa_frame_size(&o->source->sample_spec),
+            0,
+            1,
+            0,
+            &o->source->silence);
+
     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);
 
@@ -205,6 +225,17 @@ pa_source_output* pa_source_output_new(
     return o;
 }
 
+static void update_n_corked(pa_source_output *o, pa_source_output_state_t state) {
+    pa_assert(o);
+
+    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);
+}
+
 static int source_output_set_state(pa_source_output *o, pa_source_output_state_t state) {
     pa_assert(o);
 
@@ -214,12 +245,7 @@ static int source_output_set_state(pa_source_output *o, pa_source_output_state_t
     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);
+    update_n_corked(o, state);
     o->state = state;
 
     if (state != PA_SOURCE_OUTPUT_UNLINKED)
@@ -253,13 +279,7 @@ void pa_source_output_unlink(pa_source_output*o) {
     } 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;
-    o->moved = NULL;
+    reset_callbacks(o);
 
     if (linked) {
         pa_subscription_post(o->source->core, PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_REMOVE, o->index);
@@ -282,6 +302,9 @@ static void source_output_free(pa_object* mo) {
 
     pa_assert(!o->thread_info.attached);
 
+    if (o->thread_info.delay_memblockq)
+        pa_memblockq_free(o->thread_info.delay_memblockq);
+
     if (o->thread_info.resampler)
         pa_resampler_free(o->thread_info.resampler);
 
@@ -293,17 +316,17 @@ static void source_output_free(pa_object* mo) {
 }
 
 void pa_source_output_put(pa_source_output *o) {
+    pa_source_output_state_t state;
     pa_source_output_assert_ref(o);
 
     pa_assert(o->state == PA_SOURCE_OUTPUT_INIT);
     pa_assert(o->push);
 
-    o->thread_info.state = o->state = o->flags & PA_SOURCE_OUTPUT_START_CORKED ? PA_SOURCE_OUTPUT_CORKED : PA_SOURCE_OUTPUT_RUNNING;
+    state = o->flags & PA_SOURCE_OUTPUT_START_CORKED ? PA_SOURCE_OUTPUT_CORKED : PA_SOURCE_OUTPUT_RUNNING;
 
-    if (o->state == PA_SOURCE_OUTPUT_CORKED)
-        o->source->n_corked++;
+    update_n_corked(o, state);
+    o->thread_info.state = o->state = state;
 
-    pa_source_update_status(o->source);
     pa_asyncmsgq_send(o->source->asyncmsgq, PA_MSGOBJECT(o->source), PA_SOURCE_MESSAGE_ADD_OUTPUT, o, 0, NULL);
 
     pa_subscription_post(o->source->core, PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_NEW, o->index);
@@ -335,7 +358,8 @@ pa_usec_t pa_source_output_get_latency(pa_source_output *o) {
 
 /* Called from thread context */
 void pa_source_output_push(pa_source_output *o, const pa_memchunk *chunk) {
-    pa_memchunk rchunk;
+    size_t length;
+    size_t limit;
 
     pa_source_output_assert_ref(o);
     pa_assert(PA_SOURCE_OUTPUT_LINKED(o->thread_info.state));
@@ -347,23 +371,83 @@ void pa_source_output_push(pa_source_output *o, const pa_memchunk *chunk) {
 
     pa_assert(o->state == PA_SOURCE_OUTPUT_RUNNING);
 
-    if (!o->thread_info.resampler) {
-        o->push(o, chunk);
-        return;
+    if (pa_memblockq_push(o->thread_info.delay_memblockq, chunk) < 0) {
+        pa_log_debug("Delay queue overflow!");
+        pa_memblockq_seek(o->thread_info.delay_memblockq, chunk->length, PA_SEEK_RELATIVE);
+    }
+
+    limit = o->rewind ? 0 : o->source->thread_info.max_rewind;
+
+    /* Implement the delay queue */
+    while ((length = pa_memblockq_get_length(o->thread_info.delay_memblockq)) > limit) {
+        pa_memchunk qchunk;
+
+        length -= limit;
+
+        pa_assert_se(pa_memblockq_peek(o->thread_info.delay_memblockq, &qchunk) >= 0);
+
+        if (qchunk.length > length)
+            qchunk.length = length;
+
+        pa_assert(qchunk.length > 0);
+
+        if (!o->thread_info.resampler)
+            o->push(o, &qchunk);
+        else {
+            pa_memchunk rchunk;
+
+            pa_resampler_run(o->thread_info.resampler, &qchunk, &rchunk);
+
+            if (rchunk.length > 0)
+                o->push(o, &rchunk);
+
+            pa_memblock_unref(rchunk.memblock);
+        }
+
+        pa_memblock_unref(qchunk.memblock);
     }
+}
+
+/* Called from thread context */
+void pa_source_output_process_rewind(pa_source_output *o, size_t nbytes /* in sink sample spec */) {
+    pa_source_output_assert_ref(o);
+
+    pa_assert(PA_SOURCE_OUTPUT_LINKED(o->state));
+    pa_assert(pa_frame_aligned(nbytes, &o->source->sample_spec));
 
-    pa_resampler_run(o->thread_info.resampler, chunk, &rchunk);
-    if (!rchunk.length)
+    if (nbytes <= 0)
         return;
 
-    pa_assert(rchunk.memblock);
-    o->push(o, &rchunk);
-    pa_memblock_unref(rchunk.memblock);
+    if (o->rewind) {
+        pa_assert(pa_memblockq_get_length(o->thread_info.delay_memblockq) == 0);
+
+        if (o->thread_info.resampler)
+            nbytes = pa_resampler_result(o->thread_info.resampler, nbytes);
+
+        pa_log_debug("Have to rewind %lu bytes on implementor.", (unsigned long) nbytes);
+
+        if (nbytes > 0)
+            o->rewind(o, nbytes);
+
+        if (o->thread_info.resampler)
+            pa_resampler_reset(o->thread_info.resampler);
+
+    } else
+        pa_memblockq_rewind(o->thread_info.delay_memblockq, nbytes);
+}
+
+/* Called from thread context */
+void pa_source_output_set_max_rewind(pa_source_output *o, size_t nbytes  /* in the source's sample spec */) {
+    pa_source_output_assert_ref(o);
+    pa_assert(PA_SOURCE_OUTPUT_LINKED(o->thread_info.state));
+    pa_assert(pa_frame_aligned(nbytes, &o->source->sample_spec));
+
+    if (o->set_max_rewind)
+        o->set_max_rewind(o, o->thread_info.resampler ? pa_resampler_result(o->thread_info.resampler, nbytes) : nbytes);
 }
 
 pa_usec_t pa_source_output_set_requested_latency(pa_source_output *o, pa_usec_t usec) {
     pa_source_output_assert_ref(o);
-    pa_assert(PA_SOURCE_OUTPUT_LINKED(o->state));
 
     if (usec > 0) {
 
@@ -372,7 +456,6 @@ pa_usec_t pa_source_output_set_requested_latency(pa_source_output *o, pa_usec_t
 
         if (o->source->min_latency > 0 && usec < o->source->min_latency)
             usec = o->source->min_latency;
-
     }
 
     if (PA_SOURCE_OUTPUT_LINKED(o->state))
@@ -535,6 +618,14 @@ int pa_source_output_process_msg(pa_msgobject *mo, int code, void *userdata, int
 
     switch (code) {
 
+        case PA_SOURCE_OUTPUT_MESSAGE_GET_LATENCY: {
+            pa_usec_t *r = userdata;
+
+            *r += pa_bytes_to_usec(pa_memblockq_get_length(o->thread_info.delay_memblockq), &o->source->sample_spec);
+
+            return 0;
+        }
+
         case PA_SOURCE_OUTPUT_MESSAGE_SET_RATE: {
 
             o->thread_info.sample_spec.rate = PA_PTR_TO_UINT(userdata);
diff --git a/src/pulsecore/source-output.h b/src/pulsecore/source-output.h
index 0a2286b..f79761a 100644
--- a/src/pulsecore/source-output.h
+++ b/src/pulsecore/source-output.h
@@ -82,6 +82,14 @@ struct pa_source_output {
      * context. */
     void (*push)(pa_source_output *o, const pa_memchunk *chunk);
 
+    /* Only relevant for monitor sources right now: called when the
+     * recorded stream is rewound. */
+    void (*rewind)(pa_source_output *o, size_t nbytes);
+
+    /* Called whenever the maximum rewindable size of the source
+     * changes. Called from RT context. */
+    void (*set_max_rewind) (pa_source_output *o, size_t nbytes); /* may be NULL */
+
     /* 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 */
@@ -117,6 +125,10 @@ struct pa_source_output {
 
         pa_resampler* resampler;              /* may be NULL */
 
+        /* We maintain a delay memblockq here for source outputs that
+         * don't implement rewind() */
+        pa_memblockq *delay_memblockq;
+
         /* The requested latency for the source */
         pa_usec_t requested_source_latency;
     } thread_info;
@@ -196,6 +208,8 @@ int pa_source_output_move_to(pa_source_output *o, pa_source *dest);
 /* To be used exclusively by the source driver thread */
 
 void pa_source_output_push(pa_source_output *o, const pa_memchunk *chunk);
+void pa_source_output_process_rewind(pa_source_output *o, size_t nbytes);
+void pa_source_output_set_max_rewind(pa_source_output *o, size_t nbytes);
 
 int pa_source_output_process_msg(pa_msgobject *mo, int code, void *userdata, int64_t offset, pa_memchunk *chunk);
 
diff --git a/src/pulsecore/source.c b/src/pulsecore/source.c
index 4f96332..0de78f4 100644
--- a/src/pulsecore/source.c
+++ b/src/pulsecore/source.c
@@ -99,6 +99,18 @@ void pa_source_new_data_done(pa_source_new_data *data) {
     pa_proplist_free(data->proplist);
 }
 
+static void reset_callbacks(pa_source *s) {
+    pa_assert(s);
+
+    s->set_state = NULL;
+    s->get_volume = NULL;
+    s->set_volume = NULL;
+    s->get_mute = NULL;
+    s->set_mute = NULL;
+    s->get_latency = NULL;
+    s->update_requested_latency = NULL;
+}
+
 pa_source* pa_source_new(
         pa_core *core,
         pa_source_new_data *data,
@@ -171,25 +183,27 @@ pa_source* pa_source_new(
     s->muted = data->muted;
     s->refresh_volume = s->refresh_muted = FALSE;
 
-    s->min_latency = DEFAULT_MIN_LATENCY;
-    s->max_latency = s->min_latency;
-
-    s->get_latency = NULL;
-    s->set_volume = NULL;
-    s->get_volume = NULL;
-    s->set_mute = NULL;
-    s->get_mute = NULL;
-    s->set_state = NULL;
-    s->update_requested_latency = NULL;
+    reset_callbacks(s);
     s->userdata = NULL;
 
     s->asyncmsgq = NULL;
     s->rtpoll = NULL;
 
+    pa_silence_memchunk_get(
+            &core->silence_cache,
+            core->mempool,
+            &s->silence,
+            &s->sample_spec,
+            0);
+
+    s->min_latency = DEFAULT_MIN_LATENCY;
+    s->max_latency = s->min_latency;
+
     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;
+    s->thread_info.max_rewind = 0;
     s->thread_info.requested_latency_valid = TRUE;
     s->thread_info.requested_latency = 0;
 
@@ -247,8 +261,8 @@ 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(s->rtpoll);
 
     pa_assert(!s->min_latency || !s->max_latency || s->min_latency <= s->max_latency);
 
@@ -290,13 +304,7 @@ void pa_source_unlink(pa_source *s) {
     else
         s->state = PA_SOURCE_UNLINKED;
 
-    s->get_latency = NULL;
-    s->get_volume = NULL;
-    s->set_volume = NULL;
-    s->set_mute = NULL;
-    s->get_mute = NULL;
-    s->set_state = NULL;
-    s->update_requested_latency = NULL;
+    reset_callbacks(s);
 
     if (linked) {
         pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE | PA_SUBSCRIPTION_EVENT_REMOVE, s->index);
@@ -323,6 +331,9 @@ static void source_free(pa_object *o) {
 
     pa_hashmap_free(s->thread_info.outputs, NULL, NULL);
 
+    if (s->silence.memblock)
+        pa_memblock_unref(s->silence.memblock);
+
     pa_xfree(s->name);
     pa_xfree(s->driver);
 
@@ -332,6 +343,20 @@ static void source_free(pa_object *o) {
     pa_xfree(s);
 }
 
+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;
+}
+
 int pa_source_update_status(pa_source*s) {
     pa_source_assert_ref(s);
     pa_assert(PA_SOURCE_LINKED(s->state));
@@ -352,11 +377,22 @@ int pa_source_suspend(pa_source *s, pa_bool_t suspend) {
         return source_set_state(s, pa_source_used_by(s) ? PA_SOURCE_RUNNING : PA_SOURCE_IDLE);
 }
 
-void pa_source_ping(pa_source *s) {
+void pa_source_process_rewind(pa_source *s, size_t nbytes) {
+    pa_source_output *o;
+    void *state = NULL;
+
     pa_source_assert_ref(s);
-    pa_assert(PA_SOURCE_LINKED(s->state));
+    pa_assert(PA_SOURCE_OPENED(s->thread_info.state));
+
+    if (nbytes <= 0)
+        return;
 
-    pa_asyncmsgq_post(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_PING, NULL, 0, NULL, NULL);
+    pa_log_debug("Processing rewind...");
+
+    while ((o = pa_hashmap_iterate(s->thread_info.outputs, &state, NULL))) {
+        pa_source_output_assert_ref(o);
+        pa_source_output_process_rewind(o, nbytes);
+    }
 }
 
 void pa_source_post(pa_source*s, const pa_memchunk *chunk) {
@@ -381,14 +417,18 @@ void pa_source_post(pa_source*s, const pa_memchunk *chunk) {
         else
             pa_volume_memchunk(&vchunk, &s->sample_spec, &s->thread_info.soft_volume);
 
-        while ((o = pa_hashmap_iterate(s->thread_info.outputs, &state, NULL)))
+        while ((o = pa_hashmap_iterate(s->thread_info.outputs, &state, NULL))) {
+            pa_source_output_assert_ref(o);
             pa_source_output_push(o, &vchunk);
+        }
 
         pa_memblock_unref(vchunk.memblock);
     } else {
 
-        while ((o = pa_hashmap_iterate(s->thread_info.outputs, &state, NULL)))
+        while ((o = pa_hashmap_iterate(s->thread_info.outputs, &state, NULL))) {
+            pa_source_output_assert_ref(o);
             pa_source_output_push(o, chunk);
+        }
     }
 }
 
@@ -497,6 +537,7 @@ void pa_source_set_description(pa_source *s, const char *description) {
         return;
 
     old = pa_proplist_gets(s->proplist, PA_PROP_DEVICE_DESCRIPTION);
+
     if (old && description && !strcmp(old, description))
         return;
 
@@ -511,20 +552,6 @@ void pa_source_set_description(pa_source *s, const char *description) {
     }
 }
 
-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));
@@ -555,6 +582,8 @@ int pa_source_process_msg(pa_msgobject *object, int code, void *userdata, int64_
 
             pa_hashmap_put(s->thread_info.outputs, PA_UINT32_TO_PTR(o->index), pa_source_output_ref(o));
 
+            pa_source_output_set_max_rewind(o, s->thread_info.max_rewind);
+
             pa_assert(!o->thread_info.attached);
             o->thread_info.attached = TRUE;
 
@@ -599,9 +628,6 @@ int pa_source_process_msg(pa_msgobject *object, int code, void *userdata, int64_
             *((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;
@@ -731,6 +757,21 @@ pa_usec_t pa_source_get_requested_latency(pa_source *s) {
     return usec;
 }
 
+void pa_source_set_max_rewind(pa_source *s, size_t max_rewind) {
+    pa_source_output *o;
+    void *state = NULL;
+
+    pa_source_assert_ref(s);
+
+    if (max_rewind == s->thread_info.max_rewind)
+        return;
+
+    s->thread_info.max_rewind = max_rewind;
+
+    while ((o = pa_hashmap_iterate(s->thread_info.outputs, &state, NULL)))
+        pa_source_output_set_max_rewind(o, s->thread_info.max_rewind);
+}
+
 void pa_source_invalidate_requested_latency(pa_source *s) {
 
     pa_source_assert_ref(s);
diff --git a/src/pulsecore/source.h b/src/pulsecore/source.h
index ab7236e..b8859c8 100644
--- a/src/pulsecore/source.h
+++ b/src/pulsecore/source.h
@@ -91,6 +91,8 @@ struct pa_source {
     pa_asyncmsgq *asyncmsgq;
     pa_rtpoll *rtpoll;
 
+    pa_memchunk silence;
+
     pa_usec_t min_latency; /* we won't go below this latency setting */
     pa_usec_t max_latency; /* An upper limit for the latencies */
 
@@ -112,6 +114,10 @@ struct pa_source {
 
         pa_bool_t requested_latency_valid;
         size_t requested_latency;
+
+        /* Then number of bytes this source will be rewound for at
+         * max */
+        size_t max_rewind;
     } thread_info;
 
     void *userdata;
@@ -130,7 +136,6 @@ typedef enum pa_source_message {
     PA_SOURCE_MESSAGE_GET_LATENCY,
     PA_SOURCE_MESSAGE_GET_REQUESTED_LATENCY,
     PA_SOURCE_MESSAGE_SET_STATE,
-    PA_SOURCE_MESSAGE_PING,
     PA_SOURCE_MESSAGE_ATTACH,
     PA_SOURCE_MESSAGE_DETACH,
     PA_SOURCE_MESSAGE_MAX
@@ -189,8 +194,6 @@ 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_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);
@@ -203,6 +206,7 @@ unsigned pa_source_used_by(pa_source *s); /* Number of connected streams that ar
 /* To be called exclusively by the source driver, from IO context */
 
 void pa_source_post(pa_source*s, const pa_memchunk *b);
+void pa_source_process_rewind(pa_source *s, size_t nbytes);
 
 int pa_source_process_msg(pa_msgobject *o, int code, void *userdata, int64_t, pa_memchunk *chunk);
 
@@ -211,6 +215,8 @@ void pa_source_detach_within_thread(pa_source *s);
 
 pa_usec_t pa_source_get_requested_latency_within_thread(pa_source *s);
 
+void pa_source_set_max_rewind(pa_source *s, size_t max_rewind);
+
 /* To be called exclusively by source output drivers, from IO context */
 
 void pa_source_invalidate_requested_latency(pa_source *s);
diff --git a/src/tests/memblockq-test.c b/src/tests/memblockq-test.c
index 402c857..3fa8d79 100644
--- a/src/tests/memblockq-test.c
+++ b/src/tests/memblockq-test.c
@@ -61,16 +61,18 @@ int main(int argc, char *argv[]) {
     pa_mempool *p;
     pa_memblockq *bq;
     pa_memchunk chunk1, chunk2, chunk3, chunk4;
-    pa_memblock *silence;
+    pa_memchunk silence;
 
     pa_log_set_maximal_level(PA_LOG_DEBUG);
 
     p = pa_mempool_new(0);
 
-    silence = pa_memblock_new_fixed(p, (char*)  "__", 2, 1);
-    assert(silence);
+    silence.memblock = pa_memblock_new_fixed(p, (char*)  "__", 2, 1);
+    assert(silence.memblock);
+    silence.index = 0;
+    silence.length = pa_memblock_get_length(silence.memblock);
 
-    bq = pa_memblockq_new(0, 40, 10, 2, 4, 4, 40, silence);
+    bq = pa_memblockq_new(0, 40, 10, 2, 4, 4, 40, &silence);
     assert(bq);
 
     chunk1.memblock = pa_memblock_new_fixed(p, (char*) "11", 2, 1);
@@ -152,7 +154,7 @@ int main(int argc, char *argv[]) {
     dump(bq);
 
     pa_memblockq_free(bq);
-    pa_memblock_unref(silence);
+    pa_memblock_unref(silence.memblock);
     pa_memblock_unref(chunk1.memblock);
     pa_memblock_unref(chunk2.memblock);
     pa_memblock_unref(chunk3.memblock);

commit 5971345e9951762ec27af3d824b2909c034b1c48
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sun Apr 20 20:35:44 2008 +0000

    rename sink_input->rewind to process_rewind() and set_max_rewind to update_max_rewind()
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2284 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/play-memblockq.c b/src/pulsecore/play-memblockq.c
index 7b9b8fb..99b5913 100644
--- a/src/pulsecore/play-memblockq.c
+++ b/src/pulsecore/play-memblockq.c
@@ -127,7 +127,7 @@ static int sink_input_pop_cb(pa_sink_input *i, size_t nbytes, pa_memchunk *chunk
     return 0;
 }
 
-static void sink_input_rewind_cb(pa_sink_input *i, size_t nbytes) {
+static void sink_input_process_rewind_cb(pa_sink_input *i, size_t nbytes) {
     memblockq_stream *u;
 
     pa_sink_input_assert_ref(i);
@@ -141,7 +141,7 @@ static void sink_input_rewind_cb(pa_sink_input *i, size_t nbytes) {
     pa_memblockq_rewind(u->memblockq, nbytes);
 }
 
-static void sink_input_set_max_rewind(pa_sink_input *i, size_t nbytes) {
+static void sink_input_update_max_rewind(pa_sink_input *i, size_t nbytes) {
     memblockq_stream *u;
 
     pa_sink_input_assert_ref(i);
@@ -193,8 +193,8 @@ pa_sink_input* pa_memblockq_sink_input_new(
         goto fail;
 
     u->sink_input->pop = sink_input_pop_cb;
-    u->sink_input->rewind = sink_input_rewind_cb;
-    u->sink_input->set_max_rewind = sink_input_set_max_rewind;
+    u->sink_input->process_rewind = sink_input_process_rewind_cb;
+    u->sink_input->update_max_rewind = sink_input_update_max_rewind;
     u->sink_input->kill = sink_input_kill_cb;
     u->sink_input->userdata = u;
 
diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c
index 37200db..42baf8d 100644
--- a/src/pulsecore/protocol-native.c
+++ b/src/pulsecore/protocol-native.c
@@ -209,8 +209,8 @@ static int sink_input_pop_cb(pa_sink_input *i, size_t length, pa_memchunk *chunk
 static void sink_input_kill_cb(pa_sink_input *i);
 static void sink_input_suspend_cb(pa_sink_input *i, pa_bool_t suspend);
 static void sink_input_moved_cb(pa_sink_input *i);
-static void sink_input_rewind_cb(pa_sink_input *i, size_t nbytes);
-static void sink_input_set_max_rewind_cb(pa_sink_input *i, size_t nbytes);
+static void sink_input_process_rewind_cb(pa_sink_input *i, size_t nbytes);
+static void sink_input_update_max_rewind_cb(pa_sink_input *i, size_t nbytes);
 
 
 static void send_memblock(connection *c);
@@ -760,8 +760,8 @@ static playback_stream* playback_stream_new(
 
     s->sink_input->parent.process_msg = sink_input_process_msg;
     s->sink_input->pop = sink_input_pop_cb;
-    s->sink_input->rewind = sink_input_rewind_cb;
-    s->sink_input->set_max_rewind = sink_input_set_max_rewind_cb;
+    s->sink_input->process_rewind = sink_input_process_rewind_cb;
+    s->sink_input->update_max_rewind = sink_input_update_max_rewind_cb;
     s->sink_input->kill = sink_input_kill_cb;
     s->sink_input->moved = sink_input_moved_cb;
     s->sink_input->suspend = sink_input_suspend_cb;
@@ -1228,7 +1228,7 @@ static int sink_input_pop_cb(pa_sink_input *i, size_t nbytes, pa_memchunk *chunk
     return 0;
 }
 
-static void sink_input_rewind_cb(pa_sink_input *i, size_t nbytes) {
+static void sink_input_process_rewind_cb(pa_sink_input *i, size_t nbytes) {
     playback_stream *s;
 
     pa_sink_input_assert_ref(i);
@@ -1242,7 +1242,7 @@ static void sink_input_rewind_cb(pa_sink_input *i, size_t nbytes) {
     pa_memblockq_rewind(s->memblockq, nbytes);
 }
 
-static void sink_input_set_max_rewind_cb(pa_sink_input *i, size_t nbytes) {
+static void sink_input_update_max_rewind_cb(pa_sink_input *i, size_t nbytes) {
     playback_stream *s;
 
     pa_sink_input_assert_ref(i);
diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c
index 7e6c5de..ccb1ff1 100644
--- a/src/pulsecore/sink-input.c
+++ b/src/pulsecore/sink-input.c
@@ -98,8 +98,8 @@ static void reset_callbacks(pa_sink_input *i) {
     pa_assert(i);
 
     i->pop = NULL;
-    i->rewind = NULL;
-    i->set_max_rewind = NULL;
+    i->process_rewind = NULL;
+    i->update_max_rewind = NULL;
     i->attach = NULL;
     i->detach = NULL;
     i->suspend = NULL;
@@ -394,7 +394,7 @@ void pa_sink_input_put(pa_sink_input *i) {
 
     pa_assert(i->state == PA_SINK_INPUT_INIT);
     pa_assert(i->pop);
-    pa_assert(i->rewind);
+    pa_assert(i->process_rewind);
 
     i->thread_info.volume = i->volume;
     i->thread_info.muted = i->muted;
@@ -651,8 +651,8 @@ void pa_sink_input_process_rewind(pa_sink_input *i, size_t nbytes /* in sink sam
                 pa_log_debug("Have to rewind %lu bytes on implementor.", (unsigned long) amount);
 
                 /* Tell the implementor */
-                if (i->rewind)
-                    i->rewind(i, amount);
+                if (i->process_rewind)
+                    i->process_rewind(i, amount);
             }
 
             /* And reset the resampler */
@@ -668,15 +668,15 @@ void pa_sink_input_process_rewind(pa_sink_input *i, size_t nbytes /* in sink sam
 }
 
 /* Called from thread context */
-void pa_sink_input_set_max_rewind(pa_sink_input *i, size_t nbytes  /* in the sink's sample spec */) {
+void pa_sink_input_update_max_rewind(pa_sink_input *i, size_t nbytes  /* in the sink's sample spec */) {
     pa_sink_input_assert_ref(i);
     pa_assert(PA_SINK_INPUT_LINKED(i->thread_info.state));
     pa_assert(pa_frame_aligned(nbytes, &i->sink->sample_spec));
 
     pa_memblockq_set_maxrewind(i->thread_info.render_memblockq, nbytes);
 
-    if (i->set_max_rewind)
-        i->set_max_rewind(i, i->thread_info.resampler ? pa_resampler_request(i->thread_info.resampler, nbytes) : nbytes);
+    if (i->update_max_rewind)
+        i->update_max_rewind(i, i->thread_info.resampler ? pa_resampler_request(i->thread_info.resampler, nbytes) : nbytes);
 }
 
 pa_usec_t pa_sink_input_set_requested_latency(pa_sink_input *i, pa_usec_t usec) {
diff --git a/src/pulsecore/sink-input.h b/src/pulsecore/sink-input.h
index 184a2c4..b433edc 100644
--- a/src/pulsecore/sink-input.h
+++ b/src/pulsecore/sink-input.h
@@ -103,11 +103,11 @@ struct pa_sink_input {
      * before peek() if it is called at all. Only called if the sink
      * input driver ever plans to call
      * pa_sink_input_request_rewind(). Called from IO context. */
-    void (*rewind) (pa_sink_input *i, size_t nbytes);     /* may NOT be NULL */
+    void (*process_rewind) (pa_sink_input *i, size_t nbytes);     /* may NOT be NULL */
 
     /* Called whenever the maximum rewindable size of the sink
      * changes. Called from RT context. */
-    void (*set_max_rewind) (pa_sink_input *i, size_t nbytes); /* may be NULL */
+    void (*update_max_rewind) (pa_sink_input *i, size_t nbytes); /* may be NULL */
 
     /* If non-NULL this function is called when the input is first
      * connected to a sink or when the rtpoll/asyncmsgq fields
@@ -267,7 +267,7 @@ pa_bool_t pa_sink_input_safe_to_remove(pa_sink_input *i);
 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);
 void pa_sink_input_process_rewind(pa_sink_input *i, size_t nbytes /* in the sink's sample spec */);
-void pa_sink_input_set_max_rewind(pa_sink_input *i, size_t nbytes  /* in the sink's sample spec */);
+void pa_sink_input_update_max_rewind(pa_sink_input *i, size_t nbytes  /* in the sink's sample spec */);
 
 int pa_sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offset, pa_memchunk *chunk);
 
diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c
index f631de3..39468f1 100644
--- a/src/pulsecore/sink.c
+++ b/src/pulsecore/sink.c
@@ -981,7 +981,7 @@ int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offse
                 i->thread_info.sync_next->thread_info.sync_prev = i;
             }
 
-            pa_sink_input_set_max_rewind(i, s->thread_info.max_rewind);
+            pa_sink_input_update_max_rewind(i, s->thread_info.max_rewind);
 
             pa_assert(!i->thread_info.attached);
             i->thread_info.attached = TRUE;
@@ -1111,7 +1111,7 @@ int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offse
                 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_sink_input_set_max_rewind(info->ghost_sink_input, s->thread_info.max_rewind);
+                pa_sink_input_update_max_rewind(info->ghost_sink_input, s->thread_info.max_rewind);
 
                 pa_assert(!info->ghost_sink_input->thread_info.attached);
                 info->ghost_sink_input->thread_info.attached = TRUE;
@@ -1314,7 +1314,7 @@ void pa_sink_set_max_rewind(pa_sink *s, size_t max_rewind) {
     s->thread_info.max_rewind = max_rewind;
 
     while ((i = pa_hashmap_iterate(s->thread_info.inputs, &state, NULL)))
-        pa_sink_input_set_max_rewind(i, s->thread_info.max_rewind);
+        pa_sink_input_update_max_rewind(i, s->thread_info.max_rewind);
 
     if (s->monitor_source)
         pa_source_set_max_rewind(s->monitor_source, s->thread_info.max_rewind);
diff --git a/src/pulsecore/sound-file-stream.c b/src/pulsecore/sound-file-stream.c
index 9030d6d..604723f 100644
--- a/src/pulsecore/sound-file-stream.c
+++ b/src/pulsecore/sound-file-stream.c
@@ -198,7 +198,7 @@ static int sink_input_pop_cb(pa_sink_input *i, size_t length, pa_memchunk *chunk
     return -1;
 }
 
-static void sink_input_rewind_cb(pa_sink_input *i, size_t nbytes) {
+static void sink_input_process_rewind_cb(pa_sink_input *i, size_t nbytes) {
     file_stream *u;
 
     pa_sink_input_assert_ref(i);
@@ -212,7 +212,7 @@ static void sink_input_rewind_cb(pa_sink_input *i, size_t nbytes) {
     pa_memblockq_rewind(u->memblockq, nbytes);
 }
 
-static void sink_input_set_max_rewind_cb(pa_sink_input *i, size_t nbytes) {
+static void sink_input_update_max_rewind_cb(pa_sink_input *i, size_t nbytes) {
     file_stream *u;
 
     pa_sink_input_assert_ref(i);
@@ -331,8 +331,8 @@ int pa_play_file(
         goto fail;
 
     u->sink_input->pop = sink_input_pop_cb;
-    u->sink_input->rewind = sink_input_rewind_cb;
-    u->sink_input->set_max_rewind = sink_input_set_max_rewind_cb;
+    u->sink_input->process_rewind = sink_input_process_rewind_cb;
+    u->sink_input->update_max_rewind = sink_input_update_max_rewind_cb;
     u->sink_input->kill = sink_input_kill_cb;
     u->sink_input->userdata = u;
 
diff --git a/src/pulsecore/source-output.c b/src/pulsecore/source-output.c
index 318f6f8..c6dc9e8 100644
--- a/src/pulsecore/source-output.c
+++ b/src/pulsecore/source-output.c
@@ -80,8 +80,8 @@ static void reset_callbacks(pa_source_output *o) {
     pa_assert(o);
 
     o->push = NULL;
-    o->rewind = NULL;
-    o->set_max_rewind = NULL;
+    o->process_rewind = NULL;
+    o->update_max_rewind = NULL;
     o->attach = NULL;
     o->detach = NULL;
     o->suspend = NULL;
@@ -376,7 +376,7 @@ void pa_source_output_push(pa_source_output *o, const pa_memchunk *chunk) {
         pa_memblockq_seek(o->thread_info.delay_memblockq, chunk->length, PA_SEEK_RELATIVE);
     }
 
-    limit = o->rewind ? 0 : o->source->thread_info.max_rewind;
+    limit = o->process_rewind ? 0 : o->source->thread_info.max_rewind;
 
     /* Implement the delay queue */
     while ((length = pa_memblockq_get_length(o->thread_info.delay_memblockq)) > limit) {
@@ -418,7 +418,7 @@ void pa_source_output_process_rewind(pa_source_output *o, size_t nbytes /* in si
     if (nbytes <= 0)
         return;
 
-    if (o->rewind) {
+    if (o->process_rewind) {
         pa_assert(pa_memblockq_get_length(o->thread_info.delay_memblockq) == 0);
 
         if (o->thread_info.resampler)
@@ -427,7 +427,7 @@ void pa_source_output_process_rewind(pa_source_output *o, size_t nbytes /* in si
         pa_log_debug("Have to rewind %lu bytes on implementor.", (unsigned long) nbytes);
 
         if (nbytes > 0)
-            o->rewind(o, nbytes);
+            o->process_rewind(o, nbytes);
 
         if (o->thread_info.resampler)
             pa_resampler_reset(o->thread_info.resampler);
@@ -437,13 +437,13 @@ void pa_source_output_process_rewind(pa_source_output *o, size_t nbytes /* in si
 }
 
 /* Called from thread context */
-void pa_source_output_set_max_rewind(pa_source_output *o, size_t nbytes  /* in the source's sample spec */) {
+void pa_source_output_update_max_rewind(pa_source_output *o, size_t nbytes  /* in the source's sample spec */) {
     pa_source_output_assert_ref(o);
     pa_assert(PA_SOURCE_OUTPUT_LINKED(o->thread_info.state));
     pa_assert(pa_frame_aligned(nbytes, &o->source->sample_spec));
 
-    if (o->set_max_rewind)
-        o->set_max_rewind(o, o->thread_info.resampler ? pa_resampler_result(o->thread_info.resampler, nbytes) : nbytes);
+    if (o->update_max_rewind)
+        o->update_max_rewind(o, o->thread_info.resampler ? pa_resampler_result(o->thread_info.resampler, nbytes) : nbytes);
 }
 
 pa_usec_t pa_source_output_set_requested_latency(pa_source_output *o, pa_usec_t usec) {
diff --git a/src/pulsecore/source-output.h b/src/pulsecore/source-output.h
index f79761a..e7d8963 100644
--- a/src/pulsecore/source-output.h
+++ b/src/pulsecore/source-output.h
@@ -84,11 +84,11 @@ struct pa_source_output {
 
     /* Only relevant for monitor sources right now: called when the
      * recorded stream is rewound. */
-    void (*rewind)(pa_source_output *o, size_t nbytes);
+    void (*process_rewind)(pa_source_output *o, size_t nbytes);
 
     /* Called whenever the maximum rewindable size of the source
      * changes. Called from RT context. */
-    void (*set_max_rewind) (pa_source_output *o, size_t nbytes); /* may be NULL */
+    void (*update_max_rewind) (pa_source_output *o, size_t nbytes); /* may be NULL */
 
     /* If non-NULL this function is called when the output is first
      * connected to a source. Called from IO thread context */
@@ -209,7 +209,7 @@ int pa_source_output_move_to(pa_source_output *o, pa_source *dest);
 
 void pa_source_output_push(pa_source_output *o, const pa_memchunk *chunk);
 void pa_source_output_process_rewind(pa_source_output *o, size_t nbytes);
-void pa_source_output_set_max_rewind(pa_source_output *o, size_t nbytes);
+void pa_source_output_update_max_rewind(pa_source_output *o, size_t nbytes);
 
 int pa_source_output_process_msg(pa_msgobject *mo, int code, void *userdata, int64_t offset, pa_memchunk *chunk);
 
diff --git a/src/pulsecore/source.c b/src/pulsecore/source.c
index 0de78f4..8138a43 100644
--- a/src/pulsecore/source.c
+++ b/src/pulsecore/source.c
@@ -582,7 +582,7 @@ int pa_source_process_msg(pa_msgobject *object, int code, void *userdata, int64_
 
             pa_hashmap_put(s->thread_info.outputs, PA_UINT32_TO_PTR(o->index), pa_source_output_ref(o));
 
-            pa_source_output_set_max_rewind(o, s->thread_info.max_rewind);
+            pa_source_output_update_max_rewind(o, s->thread_info.max_rewind);
 
             pa_assert(!o->thread_info.attached);
             o->thread_info.attached = TRUE;
@@ -769,7 +769,7 @@ void pa_source_set_max_rewind(pa_source *s, size_t max_rewind) {
     s->thread_info.max_rewind = max_rewind;
 
     while ((o = pa_hashmap_iterate(s->thread_info.outputs, &state, NULL)))
-        pa_source_output_set_max_rewind(o, s->thread_info.max_rewind);
+        pa_source_output_update_max_rewind(o, s->thread_info.max_rewind);
 }
 
 void pa_source_invalidate_requested_latency(pa_source *s) {

commit 64e048cb1b170636e72b6a15afa3b6b8b90bb366
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sun Apr 20 20:53:46 2008 +0000

    drop a redundant pa_init_proplist(), properly set MEDIA_NAME property on stream, not on context
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2285 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulse/stream.c b/src/pulse/stream.c
index f047acf..e67f24c 100644
--- a/src/pulse/stream.c
+++ b/src/pulse/stream.c
@@ -95,7 +95,7 @@ pa_stream *pa_stream_new_with_proplist(pa_context *c, const char *name, const pa
     s->proplist = p ? pa_proplist_copy(p) : pa_proplist_new();
 
     if (name)
-        pa_proplist_sets(c->proplist, PA_PROP_MEDIA_NAME, name);
+        pa_proplist_sets(s->proplist, PA_PROP_MEDIA_NAME, name);
 
     s->channel = 0;
     s->channel_valid = 0;
@@ -843,8 +843,6 @@ static int create_stream(
         else
             pa_tagstruct_put_boolean(t, flags & PA_STREAM_PEAK_DETECT);
 
-        pa_init_proplist(s->proplist);
-
         pa_tagstruct_put(
                 t,
                 PA_TAG_BOOLEAN, flags & PA_STREAM_ADJUST_LATENCY,

commit c2c833c068a38ab2d5bea1cd9515cda8ad93b28d
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sun Apr 20 21:49:05 2008 +0000

    use the sink description instead of the name to choose the description for the monitor source
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2286 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c
index 39468f1..34fb7ae 100644
--- a/src/pulsecore/sink.c
+++ b/src/pulsecore/sink.c
@@ -124,10 +124,10 @@ pa_sink* pa_sink_new(
         pa_sink_flags_t flags) {
 
     pa_sink *s;
-    char *d;
     const char *name;
     char st[PA_SAMPLE_SPEC_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX];
     pa_source_new_data source_data;
+    const char *dn;
 
     pa_assert(core);
     pa_assert(data);
@@ -235,9 +235,8 @@ pa_sink* pa_sink_new(
     source_data.driver = data->driver;
     source_data.module = data->module;
 
-    d = pa_sprintf_malloc("Monitor Source of %s", s->name);
-    pa_proplist_sets(source_data.proplist, PA_PROP_DEVICE_DESCRIPTION, d);
-    pa_xfree(d);
+    dn = pa_proplist_gets(s->proplist, PA_PROP_DEVICE_DESCRIPTION);
+    pa_proplist_setf(source_data.proplist, PA_PROP_DEVICE_DESCRIPTION, "Monitor Source of %s", dn ? dn : s->name);
     pa_proplist_sets(source_data.proplist, PA_PROP_DEVICE_CLASS, "monitor");
 
     s->monitor_source = pa_source_new(core, &source_data, 0);

commit 8181db182b1612df48dec07b6904fa9ce32b6bd8
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sun Apr 20 21:50:57 2008 +0000

    initialize properties for ALSA sinks/sources more elaborately, re #277
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2287 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/alsa-util.c b/src/modules/alsa-util.c
index 9c9fc72..d056555 100644
--- a/src/modules/alsa-util.c
+++ b/src/modules/alsa-util.c
@@ -973,3 +973,76 @@ void pa_alsa_redirect_errors_dec(void) {
     if (r == 1)
         snd_lib_error_set_handler(NULL);
 }
+
+
+void pa_alsa_init_proplist(pa_proplist *p, snd_pcm_info_t *pcm_info) {
+
+    static const char * const alsa_class_table[SND_PCM_CLASS_LAST+1] = {
+        [SND_PCM_CLASS_GENERIC] = "generic",
+        [SND_PCM_CLASS_MULTI] = "multi",
+        [SND_PCM_CLASS_MODEM] = "modem",
+        [SND_PCM_CLASS_DIGITIZER] = "digitizer"
+    };
+    static const char * const class_table[SND_PCM_CLASS_LAST+1] = {
+        [SND_PCM_CLASS_GENERIC] = "sound",
+        [SND_PCM_CLASS_MULTI] = NULL,
+        [SND_PCM_CLASS_MODEM] = "modem",
+        [SND_PCM_CLASS_DIGITIZER] = NULL
+    };
+    static const char * const alsa_subclass_table[SND_PCM_SUBCLASS_LAST+1] = {
+        [SND_PCM_SUBCLASS_GENERIC_MIX] = "generic-mix",
+        [SND_PCM_SUBCLASS_MULTI_MIX] = "multi-mix"
+    };
+
+    snd_pcm_class_t class;
+    snd_pcm_subclass_t subclass;
+    const char *n, *id, *sdn;
+    char *cn = NULL, *lcn = NULL;
+    int card;
+
+    pa_assert(p);
+    pa_assert(pcm_info);
+
+    pa_proplist_sets(p, PA_PROP_DEVICE_API, "alsa");
+
+    class = snd_pcm_info_get_class(pcm_info);
+    if (class <= SND_PCM_CLASS_LAST) {
+        if (class_table[class])
+            pa_proplist_sets(p, PA_PROP_DEVICE_CLASS, class_table[class]);
+        if (alsa_class_table[class])
+            pa_proplist_sets(p, "alsa.class", alsa_class_table[class]);
+    }
+    subclass = snd_pcm_info_get_subclass(pcm_info);
+    if (subclass <= SND_PCM_SUBCLASS_LAST)
+        if (alsa_subclass_table[subclass])
+            pa_proplist_sets(p, "alsa.subclass", alsa_subclass_table[subclass]);
+
+    if ((n = snd_pcm_info_get_name(pcm_info)))
+        pa_proplist_sets(p, "alsa.name", n);
+
+    if ((id = snd_pcm_info_get_id(pcm_info)))
+        pa_proplist_sets(p, "alsa.id", id);
+
+    pa_proplist_setf(p, "alsa.subdevice", "%u", snd_pcm_info_get_subdevice(pcm_info));
+    if ((sdn = snd_pcm_info_get_subdevice_name(pcm_info)))
+        pa_proplist_sets(p, "alsa.subdevice_name", sdn);
+
+    pa_proplist_setf(p, "alsa.device", "%u", snd_pcm_info_get_device(pcm_info));
+
+    if ((card = snd_pcm_info_get_card(pcm_info)) >= 0) {
+        pa_proplist_setf(p, "card", "%i", card);
+
+        if (snd_card_get_name(card, &cn) >= 0)
+            pa_proplist_sets(p, "alsa.card_name", cn);
+
+        if (snd_card_get_longname(card, &lcn) >= 0)
+            pa_proplist_sets(p, "alsa.long_card_name", lcn);
+    }
+
+    if (cn && n)
+        pa_proplist_setf(p, PA_PROP_DEVICE_DESCRIPTION, "%s - %s", cn, n);
+    else if (cn)
+        pa_proplist_sets(p, PA_PROP_DEVICE_DESCRIPTION, cn);
+    else if (n)
+        pa_proplist_sets(p, PA_PROP_DEVICE_DESCRIPTION, n);
+}
diff --git a/src/modules/alsa-util.h b/src/modules/alsa-util.h
index 51222a4..03de61e 100644
--- a/src/modules/alsa-util.h
+++ b/src/modules/alsa-util.h
@@ -29,8 +29,8 @@
 
 #include <pulse/sample.h>
 #include <pulse/mainloop-api.h>
-
 #include <pulse/channelmap.h>
+#include <pulse/proplist.h>
 
 typedef struct pa_alsa_fdlist pa_alsa_fdlist;
 
@@ -88,5 +88,6 @@ void pa_alsa_dump_status(snd_pcm_t *pcm);
 void pa_alsa_redirect_errors_inc(void);
 void pa_alsa_redirect_errors_dec(void);
 
+void pa_alsa_init_proplist(pa_proplist *p, snd_pcm_info_t *pcm_info);
 
 #endif
diff --git a/src/modules/module-alsa-sink.c b/src/modules/module-alsa-sink.c
index 32bfc30..2c993d6 100644
--- a/src/modules/module-alsa-sink.c
+++ b/src/modules/module-alsa-sink.c
@@ -93,7 +93,7 @@ static const char* const valid_modargs[] = {
 
 #define DEFAULT_DEVICE "default"
 #define DEFAULT_TSCHED_BUFFER_USEC (10*PA_USEC_PER_SEC)           /* 10s */
-#define DEFAULT_TSCHED_WATERMARK_USEC (200*PA_USEC_PER_MSEC)       /* 20ms */
+#define DEFAULT_TSCHED_WATERMARK_USEC (10*PA_USEC_PER_MSEC)       /* 20ms */
 
 struct userdata {
     pa_core *core;
@@ -1050,12 +1050,6 @@ int pa__init(pa_module*m) {
     pa_bool_t use_mmap = TRUE, b, use_tsched = TRUE, d, mixer_reset = TRUE;
     pa_usec_t usec;
     pa_sink_new_data data;
-    static const char * const class_table[SND_PCM_CLASS_LAST+1] = {
-        [SND_PCM_CLASS_GENERIC] = "sound",
-        [SND_PCM_CLASS_MULTI] = NULL,
-        [SND_PCM_CLASS_MODEM] = "modem",
-        [SND_PCM_CLASS_DIGITIZER] = NULL
-    };
 
     snd_pcm_info_alloca(&pcm_info);
 
@@ -1242,15 +1236,10 @@ int pa__init(pa_module*m) {
     pa_sink_new_data_set_sample_spec(&data, &ss);
     pa_sink_new_data_set_channel_map(&data, &map);
 
+    pa_alsa_init_proplist(data.proplist, pcm_info);
     pa_proplist_sets(data.proplist, PA_PROP_DEVICE_STRING, u->device_name);
-    pa_proplist_sets(data.proplist, PA_PROP_DEVICE_API, "alsa");
-    pa_proplist_sets(data.proplist, PA_PROP_DEVICE_DESCRIPTION, snd_pcm_info_get_name(pcm_info));
     pa_proplist_setf(data.proplist, PA_PROP_DEVICE_BUFFERING_BUFFER_SIZE, "%lu", (unsigned long) (period_frames * frame_size * nfrags));
     pa_proplist_setf(data.proplist, PA_PROP_DEVICE_BUFFERING_FRAGMENT_SIZE, "%lu", (unsigned long) (period_frames * frame_size));
-
-    if (class_table[snd_pcm_info_get_class(pcm_info)])
-        pa_proplist_sets(data.proplist, PA_PROP_DEVICE_CLASS, class_table[snd_pcm_info_get_class(pcm_info)]);
-
     pa_proplist_sets(data.proplist, PA_PROP_DEVICE_ACCESS_MODE, u->use_tsched ? "mmap+timer" : (u->use_mmap ? "mmap" : "serial"));
 
     u->sink = pa_sink_new(m->core, &data, PA_SINK_HARDWARE|PA_SINK_LATENCY);
diff --git a/src/modules/module-alsa-source.c b/src/modules/module-alsa-source.c
index 185acc0..e6ea2d7 100644
--- a/src/modules/module-alsa-source.c
+++ b/src/modules/module-alsa-source.c
@@ -880,12 +880,6 @@ int pa__init(pa_module*m) {
     pa_bool_t namereg_fail;
     pa_bool_t use_mmap = TRUE, b, use_tsched = TRUE, d, mixer_reset = TRUE;
     pa_source_new_data data;
-    static const char * const class_table[SND_PCM_CLASS_LAST+1] = {
-        [SND_PCM_CLASS_GENERIC] = "sound",
-        [SND_PCM_CLASS_MULTI] = NULL,
-        [SND_PCM_CLASS_MODEM] = "modem",
-        [SND_PCM_CLASS_DIGITIZER] = NULL
-    };
 
     snd_pcm_info_alloca(&pcm_info);
 
@@ -1067,15 +1061,10 @@ int pa__init(pa_module*m) {
     pa_source_new_data_set_sample_spec(&data, &ss);
     pa_source_new_data_set_channel_map(&data, &map);
 
+    pa_alsa_init_proplist(data.proplist, pcm_info);
     pa_proplist_sets(data.proplist, PA_PROP_DEVICE_STRING, u->device_name);
-    pa_proplist_sets(data.proplist, PA_PROP_DEVICE_API, "alsa");
-    pa_proplist_sets(data.proplist, PA_PROP_DEVICE_DESCRIPTION, snd_pcm_info_get_name(pcm_info));
     pa_proplist_setf(data.proplist, PA_PROP_DEVICE_BUFFERING_BUFFER_SIZE, "%lu", (unsigned long) (period_frames * frame_size * nfrags));
     pa_proplist_setf(data.proplist, PA_PROP_DEVICE_BUFFERING_FRAGMENT_SIZE, "%lu", (unsigned long) (period_frames * frame_size));
-
-    if (class_table[snd_pcm_info_get_class(pcm_info)])
-        pa_proplist_sets(data.proplist, PA_PROP_DEVICE_CLASS, class_table[snd_pcm_info_get_class(pcm_info)]);
-
     pa_proplist_sets(data.proplist, PA_PROP_DEVICE_ACCESS_MODE, u->use_tsched ? "mmap_rewrite" : (u->use_mmap ? "mmap" : "serial"));
 
     u->source = pa_source_new(m->core, &data, PA_SOURCE_HARDWARE|PA_SOURCE_LATENCY);

commit ba6c0e17cf91b8a93179e9e9f05c492836015f4d
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sun Apr 20 23:56:55 2008 +0000

    fix C++ compat
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2288 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulse/proplist.h b/src/pulse/proplist.h
index 302a59d..40c4775 100644
--- a/src/pulse/proplist.h
+++ b/src/pulse/proplist.h
@@ -192,7 +192,7 @@ void pa_proplist_clear(pa_proplist *p);
 
 /** Allocate a new property list and copy over every single entry from
  * the specific list. \since 0.9.11 */
-pa_proplist* pa_proplist_copy(pa_proplist *template);
+pa_proplist* pa_proplist_copy(pa_proplist *t);
 
 PA_C_DECL_END
 

commit 5e7e827be5988db0262830886c7c9213fe45b554
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sun Apr 20 23:57:44 2008 +0000

    improve dB volume calculation
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2289 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulse/volume.c b/src/pulse/volume.c
index 3688b84..33ab1c5 100644
--- a/src/pulse/volume.c
+++ b/src/pulse/volume.c
@@ -80,10 +80,10 @@ pa_volume_t pa_sw_volume_multiply(pa_volume_t a, pa_volume_t b) {
     return pa_sw_volume_from_linear(pa_sw_volume_to_linear(a)* pa_sw_volume_to_linear(b));
 }
 
-#define USER_DECIBEL_RANGE 30
+#define USER_DECIBEL_RANGE 60
 
 pa_volume_t pa_sw_volume_from_dB(double dB) {
-    if (dB <= -USER_DECIBEL_RANGE)
+    if (isinf(dB) < 0 || dB <= -USER_DECIBEL_RANGE)
         return PA_VOLUME_MUTED;
 
     return (pa_volume_t) ((dB/USER_DECIBEL_RANGE+1)*PA_VOLUME_NORM);
diff --git a/src/pulse/volume.h b/src/pulse/volume.h
index 245cc12..e7ceb0d 100644
--- a/src/pulse/volume.h
+++ b/src/pulse/volume.h
@@ -166,10 +166,10 @@ pa_volume_t pa_sw_volume_from_linear(double v) PA_GCC_CONST;
 double pa_sw_volume_to_linear(pa_volume_t v) PA_GCC_CONST;
 
 #ifdef INFINITY
-#define PA_DECIBEL_MININFTY (-INFINITY)
+#define PA_DECIBEL_MININFTY ((double) -INFINITY)
 #else
 /** This value is used as minus infinity when using pa_volume_{to,from}_dB(). */
-#define PA_DECIBEL_MININFTY (-200)
+#define PA_DECIBEL_MININFTY ((double) -200)
 #endif
 
 PA_C_DECL_END

commit 88227c41c1dc9505b043b6a37ca86eaafe5b549f
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Apr 22 00:52:31 2008 +0000

    properly initialize memblock->is_silence for imported memory blocks; make is_silence and read_only a bit field
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2290 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/memblock.c b/src/pulsecore/memblock.c
index c452ae0..4653779 100644
--- a/src/pulsecore/memblock.c
+++ b/src/pulsecore/memblock.c
@@ -59,7 +59,7 @@ struct pa_memblock {
     pa_mempool *pool;
 
     pa_memblock_type_t type;
-    pa_bool_t read_only, is_silence;
+    pa_bool_t read_only:1, is_silence:1;
 
     pa_atomic_ptr_t data;
     size_t length;
@@ -226,8 +226,7 @@ static pa_memblock *memblock_new_appended(pa_mempool *p, size_t length) {
     PA_REFCNT_INIT(b);
     b->pool = p;
     b->type = PA_MEMBLOCK_APPENDED;
-    b->read_only = FALSE;
-    b->is_silence = FALSE;
+    b->read_only = b->is_silence = FALSE;
     pa_atomic_ptr_store(&b->data, (uint8_t*) b + PA_ALIGN(sizeof(pa_memblock)));
     b->length = length;
     pa_atomic_store(&b->n_acquired, 0);
@@ -331,8 +330,7 @@ pa_memblock *pa_memblock_new_pool(pa_mempool *p, size_t length) {
 
     PA_REFCNT_INIT(b);
     b->pool = p;
-    b->read_only = FALSE;
-    b->is_silence = FALSE;
+    b->read_only = b->is_silence = FALSE;
     b->length = length;
     pa_atomic_store(&b->n_acquired, 0);
     pa_atomic_store(&b->please_signal, 0);
@@ -598,7 +596,7 @@ static void memblock_make_local(pa_memblock *b) {
             pa_atomic_ptr_store(&b->data, new_data);
 
             b->type = PA_MEMBLOCK_POOL_EXTERNAL;
-            b->read_only = 0;
+            b->read_only = FALSE;
 
             goto finish;
         }
@@ -609,7 +607,7 @@ static void memblock_make_local(pa_memblock *b) {
     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->read_only = FALSE;
 
 finish:
     pa_atomic_inc(&b->pool->stat.n_allocated_by_type[b->type]);
@@ -905,7 +903,8 @@ pa_memblock* pa_memimport_get(pa_memimport *i, uint32_t block_id, uint32_t shm_i
     PA_REFCNT_INIT(b);
     b->pool = i->pool;
     b->type = PA_MEMBLOCK_IMPORTED;
-    b->read_only = 1;
+    b->read_only = TRUE;
+    b->is_silence = FALSE;
     pa_atomic_ptr_store(&b->data, (uint8_t*) seg->memory.ptr + offset);
     b->length = size;
     pa_atomic_store(&b->n_acquired, 0);

commit e16a1987a3ffa33b4a04a4c3a02320d79fd14195
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Apr 22 01:04:27 2008 +0000

    - Change meaning of special values of latency request: 0 -> "minimal latency, please"; (pa_usec_t)-1 -> "don't care"
    - Remove "source" word from monitor source description
    - Increase default tsched watermark to 20ms again
    - For the first iteration after snd_pcm_start() halve the sleep time as workaround for USB devices with quick starts
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2291 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-alsa-sink.c b/src/modules/module-alsa-sink.c
index 2c993d6..c3ae6e6 100644
--- a/src/modules/module-alsa-sink.c
+++ b/src/modules/module-alsa-sink.c
@@ -93,7 +93,7 @@ static const char* const valid_modargs[] = {
 
 #define DEFAULT_DEVICE "default"
 #define DEFAULT_TSCHED_BUFFER_USEC (10*PA_USEC_PER_SEC)           /* 10s */
-#define DEFAULT_TSCHED_WATERMARK_USEC (10*PA_USEC_PER_MSEC)       /* 20ms */
+#define DEFAULT_TSCHED_WATERMARK_USEC (20*PA_USEC_PER_MSEC)       /* 20ms */
 
 struct userdata {
     pa_core *core;
@@ -476,7 +476,7 @@ static pa_usec_t hw_sleep_time(struct userdata *u) {
 
     usec = pa_sink_get_requested_latency_within_thread(u->sink);
 
-    if (usec <= 0)
+    if (usec == (pa_usec_t) -1)
         usec = pa_bytes_to_usec(u->hwbuf_size, &u->sink->sample_spec);
 
 /*     pa_log_debug("hw buffer time: %u ms", (unsigned) (usec / PA_USEC_PER_MSEC)); */
@@ -488,6 +488,11 @@ static pa_usec_t hw_sleep_time(struct userdata *u) {
     else
         usec /= 2;
 
+    if (u->first) {
+        pa_log_debug("Decreasing wakeup time for the first iteration by half.");
+        usec /= 2;
+    }
+
 /*     pa_log_debug("after watermark: %u ms", (unsigned) (usec / PA_USEC_PER_MSEC)); */
 
     return usec;
@@ -503,10 +508,10 @@ static int update_sw_params(struct userdata *u) {
     u->hwbuf_unused_frames = 0;
 
     if (u->use_tsched)
-        if ((latency = pa_sink_get_requested_latency_within_thread(u->sink)) > 0) {
+        if ((latency = pa_sink_get_requested_latency_within_thread(u->sink)) != (pa_usec_t) -1) {
             size_t b;
 
-            pa_log("latency set to %llu", (unsigned long long) latency);
+            pa_log_debug("latency set to %llu", (unsigned long long) latency);
 
             b = pa_usec_to_bytes(latency, &u->sink->sample_spec);
 
@@ -520,7 +525,7 @@ static int update_sw_params(struct userdata *u) {
                 ((u->hwbuf_size - b) / u->frame_size) : 0;
         }
 
-    pa_log("hwbuf_unused_frames=%lu", (unsigned long) u->hwbuf_unused_frames);
+    pa_log_debug("hwbuf_unused_frames=%lu", (unsigned long) u->hwbuf_unused_frames);
 
     /* We need at last one frame in the used part of the buffer */
     u->avail_min_frames = u->hwbuf_unused_frames + 1;
@@ -533,7 +538,7 @@ static int update_sw_params(struct userdata *u) {
         u->avail_min_frames += (pa_usec_to_bytes(usec, &u->sink->sample_spec) / u->frame_size);
     }
 
-    pa_log("setting avail_min=%lu", (unsigned long) u->avail_min_frames);
+    pa_log_debug("setting avail_min=%lu", (unsigned long) u->avail_min_frames);
 
     if ((err = pa_alsa_set_sw_params(u->pcm_handle, u->avail_min_frames)) < 0) {
         pa_log("Failed to set software parameters: %s", snd_strerror(err));
@@ -918,7 +923,6 @@ static void thread_func(void *userdata) {
                 if (u->first) {
                     pa_log_info("Starting playback.");
                     snd_pcm_start(u->pcm_handle);
-                    u->first = FALSE;
 
                     pa_smoother_resume(u->smoother, pa_rtclock_usec());
                 }
@@ -946,6 +950,8 @@ static void thread_func(void *userdata) {
                 pa_rtpoll_set_timer_relative(u->rtpoll, PA_MIN(usec, cusec));
             }
 
+            u->first = FALSE;
+
         } else if (u->use_tsched)
 
             /* OK, we're in an invalid state, let's disable our timers */
@@ -1018,7 +1024,7 @@ static void thread_func(void *userdata) {
             }
 
             if (revents)
-                pa_log_info("Wakeup from ALSA! (%i)", revents);
+                pa_log_debug("Wakeup from ALSA! (%i)", revents);
         }
     }
 
diff --git a/src/modules/module-alsa-source.c b/src/modules/module-alsa-source.c
index e6ea2d7..a0677f8 100644
--- a/src/modules/module-alsa-source.c
+++ b/src/modules/module-alsa-source.c
@@ -415,7 +415,7 @@ static pa_usec_t hw_sleep_time(struct userdata *u) {
 
     usec = pa_source_get_requested_latency_within_thread(u->source);
 
-    if (usec <= 0)
+    if (usec == (pa_usec_t) -1)
         usec = pa_bytes_to_usec(u->hwbuf_size, &u->source->sample_spec);
 
     pa_log_debug("hw buffer time: %u ms", (unsigned) (usec / PA_USEC_PER_MSEC));
@@ -850,6 +850,9 @@ static void thread_func(void *userdata) {
 
                 snd_pcm_start(u->pcm_handle);
             }
+
+            if (revents)
+                pa_log_debug("Wakeup from ALSA! (%i)", revents);
         }
     }
 
diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c
index ccb1ff1..8df3687 100644
--- a/src/pulsecore/sink-input.c
+++ b/src/pulsecore/sink-input.c
@@ -247,7 +247,7 @@ pa_sink_input* pa_sink_input_new(
     i->thread_info.resampler = resampler;
     i->thread_info.volume = i->volume;
     i->thread_info.muted = i->muted;
-    i->thread_info.requested_sink_latency = 0;
+    i->thread_info.requested_sink_latency = (pa_usec_t) -1;
     i->thread_info.rewrite_nbytes = 0;
     i->thread_info.since_underrun = 0;
     i->thread_info.ignore_rewind = FALSE;
@@ -534,8 +534,6 @@ int pa_sink_input_peek(pa_sink_input *i, size_t slength /* in sink frames */, pa
             if (do_volume_adj_here && !volume_is_norm) {
                 pa_memchunk_make_writable(&wchunk, 0);
 
-                pa_log_debug("adjusting volume!");
-
                 if (i->thread_info.muted)
                     pa_silence_memchunk(&wchunk, &i->thread_info.sample_spec);
                 else
@@ -682,7 +680,7 @@ void pa_sink_input_update_max_rewind(pa_sink_input *i, size_t nbytes  /* in the
 pa_usec_t pa_sink_input_set_requested_latency(pa_sink_input *i, pa_usec_t usec) {
     pa_sink_input_assert_ref(i);
 
-    if (usec > 0) {
+    if (usec != (pa_usec_t) -1) {
 
         if (i->sink->max_latency > 0 && usec > i->sink->max_latency)
             usec = i->sink->max_latency;
diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c
index 34fb7ae..e88e7d2 100644
--- a/src/pulsecore/sink.c
+++ b/src/pulsecore/sink.c
@@ -217,7 +217,7 @@ pa_sink* pa_sink_new(
     s->thread_info.state = s->state;
     s->thread_info.rewind_nbytes = 0;
     s->thread_info.max_rewind = 0;
-    s->thread_info.requested_latency_valid = TRUE;
+    s->thread_info.requested_latency_valid = FALSE;
     s->thread_info.requested_latency = 0;
 
     pa_assert_se(pa_idxset_put(core->sinks, s, &s->index) >= 0);
@@ -236,7 +236,7 @@ pa_sink* pa_sink_new(
     source_data.module = data->module;
 
     dn = pa_proplist_gets(s->proplist, PA_PROP_DEVICE_DESCRIPTION);
-    pa_proplist_setf(source_data.proplist, PA_PROP_DEVICE_DESCRIPTION, "Monitor Source of %s", dn ? dn : s->name);
+    pa_proplist_setf(source_data.proplist, PA_PROP_DEVICE_DESCRIPTION, "Monitor of %s", dn ? dn : s->name);
     pa_proplist_sets(source_data.proplist, PA_PROP_DEVICE_CLASS, "monitor");
 
     s->monitor_source = pa_source_new(core, &source_data, 0);
@@ -1257,7 +1257,7 @@ void pa_sink_request_rewind(pa_sink*s, size_t nbytes) {
 }
 
 pa_usec_t pa_sink_get_requested_latency_within_thread(pa_sink *s) {
-    pa_usec_t result = 0;
+    pa_usec_t result = (pa_usec_t) -1;
     pa_sink_input *i;
     void *state = NULL;
 
@@ -1268,11 +1268,11 @@ pa_usec_t pa_sink_get_requested_latency_within_thread(pa_sink *s) {
 
     while ((i = pa_hashmap_iterate(s->thread_info.inputs, &state, NULL)))
 
-        if (i->thread_info.requested_sink_latency > 0 &&
-            (!result || result > i->thread_info.requested_sink_latency))
+        if (i->thread_info.requested_sink_latency != (pa_usec_t) -1 &&
+            (result == (pa_usec_t) -1 || result > i->thread_info.requested_sink_latency))
             result = i->thread_info.requested_sink_latency;
 
-    if (result > 0) {
+    if (result != (pa_usec_t) -1) {
         if (s->max_latency > 0 && result > s->max_latency)
             result = s->max_latency;
 
diff --git a/src/pulsecore/source-output.c b/src/pulsecore/source-output.c
index c6dc9e8..9c75b39 100644
--- a/src/pulsecore/source-output.c
+++ b/src/pulsecore/source-output.c
@@ -198,7 +198,7 @@ pa_source_output* pa_source_output_new(
     o->thread_info.attached = FALSE;
     o->thread_info.sample_spec = o->sample_spec;
     o->thread_info.resampler = resampler;
-    o->thread_info.requested_source_latency = 0;
+    o->thread_info.requested_source_latency = (pa_usec_t) -1;
 
     o->thread_info.delay_memblockq = pa_memblockq_new(
             0,
@@ -449,7 +449,7 @@ void pa_source_output_update_max_rewind(pa_source_output *o, size_t nbytes  /* i
 pa_usec_t pa_source_output_set_requested_latency(pa_source_output *o, pa_usec_t usec) {
     pa_source_output_assert_ref(o);
 
-    if (usec > 0) {
+    if (usec != (pa_usec_t) -1) {
 
         if (o->source->max_latency > 0 && usec > o->source->max_latency)
             usec = o->source->max_latency;
diff --git a/src/pulsecore/source.c b/src/pulsecore/source.c
index 8138a43..2727971 100644
--- a/src/pulsecore/source.c
+++ b/src/pulsecore/source.c
@@ -204,7 +204,7 @@ pa_source* pa_source_new(
     s->thread_info.soft_muted = s->muted;
     s->thread_info.state = s->state;
     s->thread_info.max_rewind = 0;
-    s->thread_info.requested_latency_valid = TRUE;
+    s->thread_info.requested_latency_valid = FALSE;
     s->thread_info.requested_latency = 0;
 
     pa_assert_se(pa_idxset_put(core->sources, s, &s->index) >= 0);
@@ -713,7 +713,7 @@ void pa_source_attach_within_thread(pa_source *s) {
 }
 
 pa_usec_t pa_source_get_requested_latency_within_thread(pa_source *s) {
-    pa_usec_t result = 0;
+    pa_usec_t result = (pa_usec_t) -1;
     pa_source_output *o;
     void *state = NULL;
 
@@ -724,11 +724,11 @@ pa_usec_t pa_source_get_requested_latency_within_thread(pa_source *s) {
 
     while ((o = pa_hashmap_iterate(s->thread_info.outputs, &state, NULL)))
 
-        if (o->thread_info.requested_source_latency > 0 &&
-            (!result || result > o->thread_info.requested_source_latency))
+        if (o->thread_info.requested_source_latency != (pa_usec_t) -1 &&
+            (result == (pa_usec_t) -1 || result > o->thread_info.requested_source_latency))
             result = o->thread_info.requested_source_latency;
 
-    if (result > 0) {
+    if (result != (pa_usec_t) -1) {
         if (s->max_latency > 0 && result > s->max_latency)
             result = s->max_latency;
 

commit 0d01c4350b9b0a504e47141e89383d03c59c5e7f
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Apr 22 01:11:16 2008 +0000

    make sure the client buffer has space for 2*minreq+tlength. Explain why
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2292 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c
index 42baf8d..7e86f11 100644
--- a/src/pulsecore/protocol-native.c
+++ b/src/pulsecore/protocol-native.c
@@ -793,9 +793,21 @@ static playback_stream* playback_stream_new(
          * half the latency will be spent on the hw buffer, the other
          * half of it in the async buffer queue we maintain for each
          * client. In between we'll have a safety space of size
-         * minreq.*/
-
-        sink_usec = (tlength_usec-minreq_usec)/2;
+         * 2*minreq. Why the 2*minreq? When the hw buffer is completey
+         * empty and needs to be filled, then our buffer must have
+         * enough data to fulfill this request immediatly and thus
+         * have at least the same tlength as the size of the hw
+         * buffer. It additionally needs space for 2 times minreq
+         * because if the buffer ran empty and a partial fillup
+         * happens immediately on the next iteration we need to be
+         * able to fulfill it and give the application also minreq
+         * time to fill it up again for the next request Makes 2 times
+         * minreq in plus.. */
+
+        if (tlength_usec > minreq_usec*2)
+            sink_usec = (tlength_usec - minreq_usec*2)/2;
+        else
+            sink_usec = 0;
 
     } else {
 
@@ -803,7 +815,10 @@ static playback_stream* playback_stream_new(
          * still need to make sure that the parameters from the user
          * do make sense. */
 
-        sink_usec = tlength_usec - minreq_usec;
+        if (tlength_usec > minreq_usec*2)
+            sink_usec = (tlength_usec - minreq_usec*2);
+        else
+            sink_usec = 0;
     }
 
     s->sink_latency = pa_sink_input_set_requested_latency(sink_input, sink_usec);
@@ -817,19 +832,19 @@ static playback_stream* playback_stream_new(
             tlength_usec -= s->sink_latency;
     }
 
-    if (tlength_usec < s->sink_latency + minreq_usec)
-        tlength_usec = s->sink_latency + minreq_usec;
+    if (tlength_usec < s->sink_latency + 2*minreq_usec)
+        tlength_usec = s->sink_latency + 2*minreq_usec;
 
     *tlength = pa_usec_to_bytes(tlength_usec, &sink_input->sample_spec);
     *minreq = pa_usec_to_bytes(minreq_usec, &sink_input->sample_spec);
 
     if (*minreq <= 0) {
-        *minreq = frame_size;
-        *tlength += frame_size;
+        *minreq += frame_size;
+        *tlength += frame_size*2;
     }
 
     if (*tlength <= *minreq)
-        *tlength = *minreq + frame_size;
+        *tlength =  *minreq*2 + frame_size;
 
     if (*prebuf <= 0)
         *prebuf = *tlength;

commit 9a486efa5f85b83a1b9d006c8b4eac04092501ed
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Apr 22 02:38:51 2008 +0000

    implement --process-time
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2293 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/utils/pacat.c b/src/utils/pacat.c
index c05bff7..e802015 100644
--- a/src/utils/pacat.c
+++ b/src/utils/pacat.c
@@ -71,7 +71,7 @@ static int channel_map_set = 0;
 
 static pa_stream_flags_t flags = 0;
 
-static size_t latency = 0;
+static size_t latency = 0, process_time=0;
 
 /* A shortcut for terminating the application */
 static void quit(int ret) {
@@ -267,6 +267,7 @@ static void context_state_callback(pa_context *c, void *userdata) {
             if (latency > 0) {
                 memset(&buffer_attr, 0, sizeof(buffer_attr));
                 buffer_attr.tlength = latency;
+                buffer_attr.minreq = process_time;
                 flags |= PA_STREAM_ADJUST_LATENCY;
             }
 
@@ -502,6 +503,7 @@ static void help(const char *argv0) {
            "      --no-remix                        Don't upmix or downmix channels.\n"
            "      --no-remap                        Map channels by index instead of name.\n"
            "      --latency=BYTES                   Request the specified latency in bytes.\n"
+           "      --process-time=BYTES              Request the specified process time per request in bytes.\n"
            ,
            argv0);
 }
@@ -519,7 +521,8 @@ enum {
     ARG_FIX_CHANNELS,
     ARG_NO_REMAP,
     ARG_NO_REMIX,
-    ARG_LATENCY
+    ARG_LATENCY,
+    ARG_PROCESS_TIME
 };
 
 int main(int argc, char *argv[]) {
@@ -529,27 +532,28 @@ int main(int argc, char *argv[]) {
     pa_time_event *time_event = NULL;
 
     static const struct option long_options[] = {
-        {"record",      0, NULL, 'r'},
-        {"playback",    0, NULL, 'p'},
-        {"device",      1, NULL, 'd'},
-        {"server",      1, NULL, 's'},
-        {"client-name", 1, NULL, 'n'},
-        {"stream-name", 1, NULL, ARG_STREAM_NAME},
-        {"version",     0, NULL, ARG_VERSION},
-        {"help",        0, NULL, 'h'},
-        {"verbose",     0, NULL, 'v'},
-        {"volume",      1, NULL, ARG_VOLUME},
-        {"rate",        1, NULL, ARG_SAMPLERATE},
-        {"format",      1, NULL, ARG_SAMPLEFORMAT},
-        {"channels",    1, NULL, ARG_CHANNELS},
-        {"channel-map", 1, NULL, ARG_CHANNELMAP},
-        {"fix-format",  0, NULL, ARG_FIX_FORMAT},
-        {"fix-rate",    0, NULL, ARG_FIX_RATE},
-        {"fix-channels",0, NULL, ARG_FIX_CHANNELS},
-        {"no-remap",    0, NULL, ARG_NO_REMAP},
-        {"no-remix",    0, NULL, ARG_NO_REMIX},
-        {"latency",     0, NULL, ARG_LATENCY},
-        {NULL,          0, NULL, 0}
+        {"record",       0, NULL, 'r'},
+        {"playback",     0, NULL, 'p'},
+        {"device",       1, NULL, 'd'},
+        {"server",       1, NULL, 's'},
+        {"client-name",  1, NULL, 'n'},
+        {"stream-name",  1, NULL, ARG_STREAM_NAME},
+        {"version",      0, NULL, ARG_VERSION},
+        {"help",         0, NULL, 'h'},
+        {"verbose",      0, NULL, 'v'},
+        {"volume",       1, NULL, ARG_VOLUME},
+        {"rate",         1, NULL, ARG_SAMPLERATE},
+        {"format",       1, NULL, ARG_SAMPLEFORMAT},
+        {"channels",     1, NULL, ARG_CHANNELS},
+        {"channel-map",  1, NULL, ARG_CHANNELMAP},
+        {"fix-format",   0, NULL, ARG_FIX_FORMAT},
+        {"fix-rate",     0, NULL, ARG_FIX_RATE},
+        {"fix-channels", 0, NULL, ARG_FIX_CHANNELS},
+        {"no-remap",     0, NULL, ARG_NO_REMAP},
+        {"no-remix",     0, NULL, ARG_NO_REMIX},
+        {"latency",      1, NULL, ARG_LATENCY},
+        {"process-time", 1, NULL, ARG_PROCESS_TIME},
+        {NULL,           0, NULL, 0}
     };
 
     if (!(bn = strrchr(argv[0], '/')))
@@ -656,7 +660,14 @@ int main(int argc, char *argv[]) {
 
             case ARG_LATENCY:
                 if (((latency = atoi(optarg))) <= 0) {
-                    fprintf(stderr, "Invallid latency specification '%s'\n", optarg);
+                    fprintf(stderr, "Invalid latency specification '%s'\n", optarg);
+                    goto quit;
+                }
+                break;
+
+            case ARG_PROCESS_TIME:
+                if (((process_time = atoi(optarg))) <= 0) {
+                    fprintf(stderr, "Invalid process time specification '%s'\n", optarg);
                     goto quit;
                 }
                 break;

commit 69f6bdf1557fa9d8edd590222c17b5c2450ec8bd
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Apr 22 02:44:25 2008 +0000

    add new function pa_alsa_recover_from_poll() to merge common core from module-alsa-sink and module-alsa-source
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2294 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/alsa-util.c b/src/modules/alsa-util.c
index d056555..11367d9 100644
--- a/src/modules/alsa-util.c
+++ b/src/modules/alsa-util.c
@@ -974,7 +974,6 @@ void pa_alsa_redirect_errors_dec(void) {
         snd_lib_error_set_handler(NULL);
 }
 
-
 void pa_alsa_init_proplist(pa_proplist *p, snd_pcm_info_t *pcm_info) {
 
     static const char * const alsa_class_table[SND_PCM_CLASS_LAST+1] = {
@@ -1030,7 +1029,7 @@ void pa_alsa_init_proplist(pa_proplist *p, snd_pcm_info_t *pcm_info) {
     pa_proplist_setf(p, "alsa.device", "%u", snd_pcm_info_get_device(pcm_info));
 
     if ((card = snd_pcm_info_get_card(pcm_info)) >= 0) {
-        pa_proplist_setf(p, "card", "%i", card);
+        pa_proplist_setf(p, "alsa.card", "%i", card);
 
         if (snd_card_get_name(card, &cn) >= 0)
             pa_proplist_sets(p, "alsa.card_name", cn);
@@ -1046,3 +1045,51 @@ void pa_alsa_init_proplist(pa_proplist *p, snd_pcm_info_t *pcm_info) {
     else if (n)
         pa_proplist_sets(p, PA_PROP_DEVICE_DESCRIPTION, n);
 }
+
+int pa_alsa_recover_from_poll(snd_pcm_t *pcm, int revents) {
+    snd_pcm_state_t state;
+    int err;
+
+    pa_assert(pcm);
+
+    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");
+
+    state = snd_pcm_state(pcm);
+    pa_log_warn("PCM state is %s", snd_pcm_state_name(state));
+
+    /* Try to recover from this error */
+
+    switch (state) {
+
+        case SND_PCM_STATE_XRUN:
+            if ((err = snd_pcm_recover(pcm, -EPIPE, 1)) != 0) {
+                pa_log_warn("Could not recover from POLLERR|POLLNVAL|POLLHUP and XRUN: %s", snd_strerror(err));
+                return -1;
+            }
+            break;
+
+        case SND_PCM_STATE_SUSPENDED:
+            if ((err = snd_pcm_recover(pcm, -ESTRPIPE, 1)) != 0) {
+                pa_log_warn("Could not recover from POLLERR|POLLNVAL|POLLHUP and SUSPENDED: %s", snd_strerror(err));
+                return -1;
+            }
+            break;
+
+        default:
+
+            snd_pcm_drop(pcm);
+
+            if ((err = snd_pcm_prepare(pcm)) < 0) {
+                pa_log_warn("Could not recover from POLLERR|POLLNVAL|POLLHUP with snd_pcm_prepare(): %s", snd_strerror(err));
+                return -1;
+            }
+            break;
+    }
+
+    return 0;
+}
diff --git a/src/modules/alsa-util.h b/src/modules/alsa-util.h
index 03de61e..5494b40 100644
--- a/src/modules/alsa-util.h
+++ b/src/modules/alsa-util.h
@@ -90,4 +90,6 @@ void pa_alsa_redirect_errors_dec(void);
 
 void pa_alsa_init_proplist(pa_proplist *p, snd_pcm_info_t *pcm_info);
 
+int pa_alsa_recover_from_poll(snd_pcm_t *pcm, int revents);
+
 #endif

commit 4a1971a5351d49d3ff7fa33f386b579f558c2fd0
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Apr 22 02:46:19 2008 +0000

    if no latency was configure for a sink/source, fill in the max latency automatically
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2295 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c
index e88e7d2..452dab7 100644
--- a/src/pulsecore/sink.c
+++ b/src/pulsecore/sink.c
@@ -1298,6 +1298,9 @@ pa_usec_t pa_sink_get_requested_latency(pa_sink *s) {
     if (pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_GET_REQUESTED_LATENCY, &usec, 0, NULL) < 0)
         return 0;
 
+    if (usec == (pa_usec_t) -1)
+        usec = s->max_latency;
+
     return usec;
 }
 
diff --git a/src/pulsecore/source.c b/src/pulsecore/source.c
index 2727971..dab307e 100644
--- a/src/pulsecore/source.c
+++ b/src/pulsecore/source.c
@@ -754,6 +754,9 @@ pa_usec_t pa_source_get_requested_latency(pa_source *s) {
     if (pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_GET_REQUESTED_LATENCY, &usec, 0, NULL) < 0)
         return 0;
 
+    if (usec == (pa_usec_t) -1)
+        usec = s->max_latency;
+
     return usec;
 }
 

commit cdb077b6c040314ece12fd52fb41fb7b3f368909
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Apr 22 02:47:05 2008 +0000

    if no timer was armed, we don't need to disarm it
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2296 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/rtpoll.c b/src/pulsecore/rtpoll.c
index bd1c43a..734f344 100644
--- a/src/pulsecore/rtpoll.c
+++ b/src/pulsecore/rtpoll.c
@@ -71,6 +71,7 @@ struct pa_rtpoll {
     int rtsig;
     sigset_t sigset_unblocked;
     timer_t timer;
+    pa_bool_t timer_armed;
 #ifdef __linux__
     pa_bool_t dont_use_ppoll;
 #endif
@@ -130,6 +131,7 @@ pa_rtpoll *pa_rtpoll_new(void) {
     p->rtsig = -1;
     sigemptyset(&p->sigset_unblocked);
     p->timer = (timer_t) -1;
+    p->timer_armed = FALSE;
 
 #endif
 
@@ -465,14 +467,16 @@ static void update_timer(pa_rtpoll *p) {
             struct timespec ts = { .tv_sec = 0, .tv_nsec = 0 };
             sigset_t ss;
 
-            /* First disarm timer */
-            memset(&its, 0, sizeof(its));
-            pa_assert_se(timer_settime(p->timer, TIMER_ABSTIME, &its, NULL) == 0);
+            if (p->timer_armed) {
+                /* First disarm timer */
+                memset(&its, 0, sizeof(its));
+                pa_assert_se(timer_settime(p->timer, TIMER_ABSTIME, &its, NULL) == 0);
 
-            /* Remove a signal that might be waiting in the signal q */
-            pa_assert_se(sigemptyset(&ss) == 0);
-            pa_assert_se(sigaddset(&ss, p->rtsig) == 0);
-            sigtimedwait(&ss, NULL, &ts);
+                /* Remove a signal that might be waiting in the signal q */
+                pa_assert_se(sigemptyset(&ss) == 0);
+                pa_assert_se(sigaddset(&ss, p->rtsig) == 0);
+                sigtimedwait(&ss, NULL, &ts);
+            }
 
             /* And install the new timer */
             if (p->timer_enabled) {
@@ -487,6 +491,8 @@ static void update_timer(pa_rtpoll *p) {
                     its.it_value.tv_nsec = 1;
                 pa_assert_se(timer_settime(p->timer, TIMER_ABSTIME, &its, NULL) == 0);
             }
+
+            p->timer_armed = p->timer_enabled;
         }
 
 #ifdef __linux__

commit 1adbe822b8e21542e0193e91376e73bbf7002fbe
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Apr 22 02:47:47 2008 +0000

    some beautification updates, show msec instead of usec everywhere
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2297 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/cli-text.c b/src/pulsecore/cli-text.c
index 140334a..f251a14 100644
--- a/src/pulsecore/cli-text.c
+++ b/src/pulsecore/cli-text.c
@@ -29,6 +29,7 @@
 
 #include <pulse/volume.h>
 #include <pulse/xmalloc.h>
+#include <pulse/timeval.h>
 
 #include <pulsecore/module.h>
 #include <pulsecore/client.h>
@@ -88,7 +89,7 @@ char *pa_client_list_to_string(pa_core *c) {
                 client->driver);
 
         if (client->module)
-            pa_strbuf_printf(s, "\towner module: <%u>\n", client->module->index);
+            pa_strbuf_printf(s, "\towner module: %u\n", client->module->index);
 
         t = pa_proplist_to_string(client->proplist);
         pa_strbuf_printf(s, "\tproperties:\n%s", t);
@@ -125,15 +126,15 @@ char *pa_sink_list_to_string(pa_core *c) {
             "\tdriver: <%s>\n"
             "\tflags: %s%s%s%s%s%s\n"
             "\tstate: %s\n"
-            "\tvolume: <%s>\n"
-            "\tmute: <%i>\n"
-            "\tlatency: <%0.0f usec>\n"
-            "\tconfigured latency: <%0.0f usec> from range <%0.0f usec> .. <%0.0f usec>\n"
-            "\tmonitor source: <%u>\n"
-            "\tsample spec: <%s>\n"
-            "\tchannel map: <%s>\n"
-            "\tused by: <%u>\n"
-            "\tlinked by: <%u>\n",
+            "\tvolume: %s\n"
+            "\tmuted: %s\n"
+            "\tcurrent latency: %0.2f ms\n"
+            "\tconfigured latency: %0.2f ms; range is %0.2f .. %0.2f ms\n"
+            "\tmonitor source: %u\n"
+            "\tsample spec: %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,
@@ -146,9 +147,9 @@ char *pa_sink_list_to_string(pa_core *c) {
             sink->flags & PA_SINK_LATENCY ? "LATENCY " : "",
             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),
-            (double) pa_sink_get_requested_latency(sink), (double) sink->min_latency, (double) sink->max_latency,
+            pa_yes_no(pa_sink_get_mute(sink)),
+            (double) pa_sink_get_latency(sink) / PA_USEC_PER_MSEC,
+            (double) pa_sink_get_requested_latency(sink) / PA_USEC_PER_MSEC, (double) sink->min_latency / PA_USEC_PER_MSEC, (double) sink->max_latency / PA_USEC_PER_MSEC,
             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),
@@ -156,7 +157,7 @@ char *pa_sink_list_to_string(pa_core *c) {
             pa_sink_linked_by(sink));
 
         if (sink->module)
-            pa_strbuf_printf(s, "\tmodule: <%u>\n", sink->module->index);
+            pa_strbuf_printf(s, "\tmodule: %u\n", sink->module->index);
 
         t = pa_proplist_to_string(sink->proplist);
         pa_strbuf_printf(s, "\tproperties:\n%s", t);
@@ -193,14 +194,14 @@ char *pa_source_list_to_string(pa_core *c) {
             "\tdriver: <%s>\n"
             "\tflags: %s%s%s%s%s%s\n"
             "\tstate: %s\n"
-            "\tvolume: <%s>\n"
-            "\tmute: <%u>\n"
-            "\tlatency: <%0.0f usec>\n"
-            "\tconfigured latency: <%0.0f usec> from range <%0.0f usec> .. <%0.0f usec>\n"
-            "\tsample spec: <%s>\n"
-            "\tchannel map: <%s>\n"
-            "\tused by: <%u>\n"
-            "\tlinked by: <%u>\n",
+            "\tvolume: %s\n"
+            "\tmuted: %s\n"
+            "\tcurrent latency: %0.2f ms\n"
+            "\tconfigured latency: %0.2f ms; range is %0.2f .. %0.2f ms\n"
+            "\tsample spec: %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,
@@ -213,18 +214,18 @@ char *pa_source_list_to_string(pa_core *c) {
             source->flags & PA_SOURCE_LATENCY ? "LATENCY " : "",
             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),
-            (double) pa_source_get_requested_latency(source), (double) source->min_latency, (double) source->max_latency,
+            pa_yes_no(pa_source_get_mute(source)),
+            (double) pa_source_get_latency(source) / PA_USEC_PER_MSEC,
+            (double) pa_source_get_requested_latency(source) / PA_USEC_PER_MSEC, (double) source->min_latency / PA_USEC_PER_MSEC, (double) source->max_latency / PA_USEC_PER_MSEC,
             pa_sample_spec_snprint(ss, sizeof(ss), &source->sample_spec),
             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);
+            pa_strbuf_printf(s, "\tmonitor_of: %u\n", source->monitor_of->index);
         if (source->module)
-            pa_strbuf_printf(s, "\tmodule: <%u>\n", source->module->index);
+            pa_strbuf_printf(s, "\tmodule: %u\n", source->module->index);
 
         t = pa_proplist_to_string(source->proplist);
         pa_strbuf_printf(s, "\tproperties:\n%s", t);
@@ -262,10 +263,10 @@ char *pa_source_output_list_to_string(pa_core *c) {
             "\tdriver: <%s>\n"
             "\tflags: %s%s%s%s%s%s%s%s\n"
             "\tstate: %s\n"
-            "\tsource: <%u> '%s'\n"
-            "\tlatency: <%0.0f usec>\n"
-            "\tsample spec: <%s>\n"
-            "\tchannel map: <%s>\n"
+            "\tsource: %u <%s>\n"
+            "\tlatency: %0.2f ms\n"
+            "\tsample spec: %s\n"
+            "\tchannel map: %s\n"
             "\tresample method: %s\n",
             o->index,
             o->driver,
@@ -279,14 +280,14 @@ char *pa_source_output_list_to_string(pa_core *c) {
             o->flags & PA_SOURCE_OUTPUT_FIX_CHANNELS ? "FIX_CHANNELS " : "",
             state_table[pa_source_output_get_state(o)],
             o->source->index, o->source->name,
-            (double) pa_source_output_get_latency(o),
+            (double) pa_source_output_get_latency(o) / PA_USEC_PER_MSEC,
             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)));
         if (o->module)
-            pa_strbuf_printf(s, "\towner module: <%u>\n", o->module->index);
+            pa_strbuf_printf(s, "\towner module: %u\n", o->module->index);
         if (o->client)
-            pa_strbuf_printf(s, "\tclient: <%u> '%s'\n", o->client->index, pa_strnull(pa_proplist_gets(o->client->proplist, PA_PROP_APPLICATION_NAME)));
+            pa_strbuf_printf(s, "\tclient: %u <%s>\n", o->client->index, pa_strnull(pa_proplist_gets(o->client->proplist, PA_PROP_APPLICATION_NAME)));
 
         t = pa_proplist_to_string(o->proplist);
         pa_strbuf_printf(s, "\tproperties:\n%s", t);
@@ -324,12 +325,12 @@ char *pa_sink_input_list_to_string(pa_core *c) {
             "\tdriver: <%s>\n"
             "\tflags: %s%s%s%s%s%s%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"
+            "\tsink: %u <%s>\n"
+            "\tvolume: %s\n"
+            "\tmuted: %s\n"
+            "\tlatency: %0.2f ms\n"
+            "\tsample spec: %s\n"
+            "\tchannel map: %s\n"
             "\tresample method: %s\n",
             i->index,
             i->driver,
@@ -344,16 +345,16 @@ char *pa_sink_input_list_to_string(pa_core *c) {
             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_yes_no(pa_sink_input_get_mute(i)),
+            (double) pa_sink_input_get_latency(i) / PA_USEC_PER_MSEC,
             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, "\tmodule: <%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, pa_strnull(pa_proplist_gets(i->client->proplist, PA_PROP_APPLICATION_NAME)));
+            pa_strbuf_printf(s, "\tclient: %u <%s>\n", i->client->index, pa_strnull(pa_proplist_gets(i->client->proplist, PA_PROP_APPLICATION_NAME)));
 
         t = pa_proplist_to_string(i->proplist);
         pa_strbuf_printf(s, "\tproperties:\n%s", t);
@@ -388,14 +389,14 @@ char *pa_scache_list_to_string(pa_core *c) {
             pa_strbuf_printf(
                 s,
                 "    name: <%s>\n"
-                "\tindex: <%u>\n"
-                "\tsample spec: <%s>\n"
-                "\tchannel map: <%s>\n"
-                "\tlength: <%lu>\n"
-                "\tduration: <%0.1fs>\n"
-                "\tvolume: <%s>\n"
+                "\tindex: %u\n"
+                "\tsample spec: %s\n"
+                "\tchannel map: %s\n"
+                "\tlength: %lu\n"
+                "\tduration: %0.1f s\n"
+                "\tvolume: %s\n"
                 "\tlazy: %s\n"
-                "\tfilename: %s\n",
+                "\tfilename: <%s>\n",
                 e->name,
                 e->index,
                 ss,
@@ -429,7 +430,12 @@ char *pa_autoload_list_to_string(pa_core *c) {
 
         while ((e = pa_hashmap_iterate(c->autoload_hashmap, &state, NULL))) {
             pa_strbuf_printf(
-                s, "    name: <%s>\n\ttype: <%s>\n\tindex: <%u>\n\tmodule_name: <%s>\n\targuments: <%s>\n",
+                s,
+                "    name: <%s>\n"
+                "\ttype: %s\n"
+                "\tindex: %u\n"
+                "\tmodule_name: <%s>\n"
+                "\targuments: <%s>\n",
                 e->name,
                 e->type == PA_NAMEREG_SOURCE ? "source" : "sink",
                 e->index,

commit 6b4b95beedf08089ec0dc48dd152210e3bc75046
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Apr 22 02:48:24 2008 +0000

    show configure latency metrics
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2298 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c
index 7e86f11..cde113d 100644
--- a/src/pulsecore/protocol-native.c
+++ b/src/pulsecore/protocol-native.c
@@ -785,6 +785,10 @@ static playback_stream* playback_stream_new(
     tlength_usec = pa_bytes_to_usec(*tlength, &sink_input->sample_spec);
     minreq_usec = pa_bytes_to_usec(*minreq, &sink_input->sample_spec);
 
+    pa_log_info("Requested tlength=%0.2f ms, minreq=%0.2f ms",
+                (double) tlength_usec / PA_USEC_PER_MSEC,
+                (double) minreq_usec / PA_USEC_PER_MSEC);
+
     if (adjust_latency) {
 
         /* So, the user asked us to adjust the latency of the stream
@@ -878,6 +882,12 @@ static playback_stream* playback_stream_new(
 
     pa_idxset_put(c->output_streams, s, &s->index);
 
+    pa_log_info("Final latency %0.2f ms = %0.2f ms + 2*%0.2f ms + %0.2f ms",
+                ((double) pa_bytes_to_usec(*tlength, &sink_input->sample_spec) + (double) s->sink_latency) / PA_USEC_PER_MSEC,
+                (double) pa_bytes_to_usec(*tlength-*minreq*2, &sink_input->sample_spec) / PA_USEC_PER_MSEC,
+                (double) pa_bytes_to_usec(*minreq, &sink_input->sample_spec) / PA_USEC_PER_MSEC,
+                (double) s->sink_latency / PA_USEC_PER_MSEC);
+
     pa_sink_input_put(s->sink_input);
     return s;
 }
@@ -1048,8 +1058,6 @@ static void handle_seek(playback_stream *s, int64_t indexw) {
             if (u >= s->underrun)
                 u = s->underrun;
 
-            pa_log("yeah! ready to rock");
-
             /* We just ended an underrun, let's ask the sink
              * to rewrite */
             s->sink_input->thread_info.ignore_rewind = TRUE;

commit 5e6aacdbe2df444ab9708ce3b007bece32d2cb93
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Apr 22 02:50:55 2008 +0000

    * don't increase tsched_watermark on underrun without limits
    * fix the watermark when we change the latency
    * fix latency measurement
    * move rewinding code into its own function
    * make use of new function pa_alsa_recover_from_poll() were applicable
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2299 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-alsa-sink.c b/src/modules/module-alsa-sink.c
index c3ae6e6..665dbde 100644
--- a/src/modules/module-alsa-sink.c
+++ b/src/modules/module-alsa-sink.c
@@ -92,7 +92,7 @@ static const char* const valid_modargs[] = {
 };
 
 #define DEFAULT_DEVICE "default"
-#define DEFAULT_TSCHED_BUFFER_USEC (10*PA_USEC_PER_SEC)           /* 10s */
+#define DEFAULT_TSCHED_BUFFER_USEC (5*PA_USEC_PER_SEC)           /* 5s */
 #define DEFAULT_TSCHED_WATERMARK_USEC (20*PA_USEC_PER_MSEC)       /* 20ms */
 
 struct userdata {
@@ -134,6 +134,16 @@ struct userdata {
     snd_pcm_sframes_t avail_min_frames;
 };
 
+static void fix_tsched_watermark(struct userdata *u) {
+    size_t max_use;
+    pa_assert(u);
+
+    max_use = u->hwbuf_size - u->hwbuf_unused_frames * u->frame_size;
+
+    if (u->tsched_watermark >= max_use/2)
+        u->tsched_watermark = max_use/2;
+}
+
 static int mmap_write(struct userdata *u) {
     int work_done = 0;
 
@@ -189,12 +199,10 @@ static int mmap_write(struct userdata *u) {
         pa_log_debug("%0.2f ms left to play", (double) pa_bytes_to_usec(left_to_play, &u->sink->sample_spec) / PA_USEC_PER_MSEC);
 
         if (left_to_play <= 0 && !u->first) {
-            u->tsched_watermark *=2;
-
-            if (u->tsched_watermark >= u->hwbuf_size)
-                u->tsched_watermark = u->hwbuf_size-u->frame_size;
-
-            pa_log_notice("Underrun! Increasing wakeup watermark to %0.2f", (double) pa_bytes_to_usec(u->tsched_watermark, &u->sink->sample_spec) / PA_USEC_PER_MSEC);
+            u->tsched_watermark *= 2;
+            fix_tsched_watermark(u);
+            pa_log_notice("Underrun! Increasing wakeup watermark to %0.2f ms",
+                          (double) pa_bytes_to_usec(u->tsched_watermark, &u->sink->sample_spec) / PA_USEC_PER_MSEC);
         }
 
         frames = n = n - u->hwbuf_unused_frames;
@@ -407,13 +415,17 @@ static void update_smoother(struct userdata *u) {
 static pa_usec_t sink_get_latency(struct userdata *u) {
     pa_usec_t r = 0;
     int64_t delay;
+    pa_usec_t now1, now2;
 
     pa_assert(u);
 
-    delay = u->frame_index - pa_smoother_get(u->smoother, pa_rtclock_usec());
+    now1 = pa_rtclock_usec();
+    now2 = pa_smoother_get(u->smoother, now1);
+
+    delay = (int64_t) pa_bytes_to_usec(u->frame_index * u->frame_size, &u->sink->sample_spec) - now2;
 
     if (delay > 0)
-        r = pa_bytes_to_usec(delay * u->frame_size, &u->sink->sample_spec);
+        r = (pa_usec_t) delay;
 
     if (u->memchunk.memblock)
         r += pa_bytes_to_usec(u->memchunk.length, &u->sink->sample_spec);
@@ -523,6 +535,8 @@ static int update_sw_params(struct userdata *u) {
             u->hwbuf_unused_frames =
                 PA_LIKELY(b < u->hwbuf_size) ?
                 ((u->hwbuf_size - b) / u->frame_size) : 0;
+
+            fix_tsched_watermark(u);
         }
 
     pa_log_debug("hwbuf_unused_frames=%lu", (unsigned long) u->hwbuf_unused_frames);
@@ -815,12 +829,66 @@ static int sink_set_mute_cb(pa_sink *s) {
 
 static void sink_update_requested_latency_cb(pa_sink *s) {
     struct userdata *u = s->userdata;
-
     pa_assert(u);
 
     update_sw_params(u);
 }
 
+static int process_rewind(struct userdata *u) {
+    snd_pcm_sframes_t unused;
+    size_t rewind_nbytes, unused_nbytes, limit_nbytes;
+    pa_assert(u);
+
+    rewind_nbytes = u->sink->thread_info.rewind_nbytes;
+    u->sink->thread_info.rewind_nbytes = 0;
+
+    pa_assert(rewind_nbytes > 0);
+    pa_log_debug("Requested to rewind %lu bytes.", (unsigned long) rewind_nbytes);
+
+    snd_pcm_hwsync(u->pcm_handle);
+    if ((unused = snd_pcm_avail_update(u->pcm_handle)) < 0) {
+        pa_log("snd_pcm_avail_update() failed: %s", snd_strerror(unused));
+        return -1;
+    }
+
+    unused_nbytes = u->tsched_watermark + (size_t) unused * u->frame_size;
+
+    if (u->hwbuf_size > unused_nbytes)
+        limit_nbytes = u->hwbuf_size - unused_nbytes;
+    else
+        limit_nbytes = 0;
+
+    if (rewind_nbytes > limit_nbytes)
+        rewind_nbytes = limit_nbytes;
+
+    if (rewind_nbytes > 0) {
+        snd_pcm_sframes_t in_frames, out_frames;
+
+        pa_log_debug("Limited to %lu bytes.", (unsigned long) rewind_nbytes);
+
+        in_frames = (snd_pcm_sframes_t) rewind_nbytes / u->frame_size;
+        pa_log_debug("before: %lu", (unsigned long) in_frames);
+        if ((out_frames = snd_pcm_rewind(u->pcm_handle, in_frames)) < 0) {
+            pa_log("snd_pcm_rewind() failed: %s", snd_strerror(out_frames));
+            return -1;
+        }
+        pa_log_debug("after: %lu", (unsigned long) out_frames);
+
+        rewind_nbytes = out_frames * u->frame_size;
+
+        if (rewind_nbytes <= 0)
+            pa_log_info("Tried rewind, but was apparently not possible.");
+        else {
+            u->frame_index -= out_frames;
+            pa_log_debug("Rewound %lu bytes.", (unsigned long) rewind_nbytes);
+            pa_sink_process_rewind(u->sink, rewind_nbytes);
+        }
+    } else
+        pa_log_debug("Mhmm, actually there is nothing to rewind.");
+
+    return 0;
+}
+
 static void thread_func(void *userdata) {
     struct userdata *u = userdata;
 
@@ -843,78 +911,17 @@ static void thread_func(void *userdata) {
         if (PA_SINK_OPENED(u->sink->thread_info.state)) {
             int work_done = 0;
 
-            if (u->sink->thread_info.rewind_nbytes > 0) {
-                snd_pcm_sframes_t unused;
-                size_t rewind_nbytes, unused_nbytes, limit_nbytes;
-
-                rewind_nbytes = u->sink->thread_info.rewind_nbytes;
-                u->sink->thread_info.rewind_nbytes = 0;
-
-                pa_log_debug("Requested to rewind %lu bytes.", (unsigned long) rewind_nbytes);
-
-                snd_pcm_hwsync(u->pcm_handle);
-                if ((unused = snd_pcm_avail_update(u->pcm_handle)) < 0) {
-                    pa_log("snd_pcm_avail_update() failed: %s", snd_strerror(unused));
+            if (u->sink->thread_info.rewind_nbytes > 0)
+                if (process_rewind(u) < 0)
                     goto fail;
-                }
-
-                unused_nbytes = u->tsched_watermark + (size_t) unused * u->frame_size;
-
-                if (u->hwbuf_size > unused_nbytes)
-                    limit_nbytes = u->hwbuf_size - unused_nbytes;
-                else
-                    limit_nbytes = 0;
-
-                if (rewind_nbytes > limit_nbytes)
-                    rewind_nbytes = limit_nbytes;
-
-                if (rewind_nbytes > 0) {
-                    snd_pcm_sframes_t in_frames, out_frames;
-
-                    pa_log_debug("Limited to %lu bytes.", (unsigned long) rewind_nbytes);
-
-                    in_frames = (snd_pcm_sframes_t) rewind_nbytes / u->frame_size;
-                    pa_log_debug("before: %lu", (unsigned long) in_frames);
-                    if ((out_frames = snd_pcm_rewind(u->pcm_handle, in_frames)) < 0) {
-                        pa_log("snd_pcm_rewind() failed: %s", snd_strerror(out_frames));
-                        goto fail;
-                    }
-                    pa_log_debug("after: %lu", (unsigned long) out_frames);
-
-                    if (out_frames > in_frames) {
-                        snd_pcm_sframes_t sfix;
-                        pa_log("FUCK, device rewound %lu frames more than we wanted. What a mess!", (unsigned long) (out_frames-in_frames));
-
-                        if ((sfix = snd_pcm_forward(u->pcm_handle, out_frames-in_frames)) < 0) {
-                            pa_log("snd_pcm_forward() failed: %s", snd_strerror(sfix));
-                            goto fail;
-                        }
-
-                        pa_log("Could fix by %lu", (unsigned long) sfix);
-                        out_frames -= sfix;
-                    }
-
-                    rewind_nbytes = out_frames * u->frame_size;
-
-                    if (rewind_nbytes <= 0)
-                        pa_log_info("Tried rewind, but was apparently not possible.");
-                    else {
-                        u->frame_index -= out_frames;
-                        pa_log_debug("Rewound %lu bytes.", (unsigned long) rewind_nbytes);
-                        pa_sink_process_rewind(u->sink, rewind_nbytes);
-                    }
-                } else
-                    pa_log_debug("Mhmm, actually there is nothing to rewind.");
 
-            }
+            if (u->use_mmap)
+                work_done = mmap_write(u);
+            else
+                work_done = unix_write(u);
 
-            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 < 0)
+                goto fail;
 
 /*             pa_log_debug("work_done = %i", work_done); */
 
@@ -979,46 +986,8 @@ static void thread_func(void *userdata) {
             }
 
             if (revents & (POLLERR|POLLNVAL|POLLHUP)) {
-                snd_pcm_state_t state;
-
-                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");
-
-                state = snd_pcm_state(u->pcm_handle);
-                pa_log_warn("PCM state is %s", snd_pcm_state_name(state));
-
-                /* Try to recover from this error */
-
-                switch (state) {
-
-                    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;
-                }
+                if (pa_alsa_recover_from_poll(u->pcm_handle, revents) < 0)
+                    goto fail;
 
                 u->first = TRUE;
             }
diff --git a/src/modules/module-alsa-source.c b/src/modules/module-alsa-source.c
index a0677f8..bcb3c2d 100644
--- a/src/modules/module-alsa-source.c
+++ b/src/modules/module-alsa-source.c
@@ -93,8 +93,8 @@ static const char* const valid_modargs[] = {
 };
 
 #define DEFAULT_DEVICE "default"
-#define DEFAULT_TSCHED_BUFFER_USEC (2*PA_USEC_PER_SEC)
-#define DEFAULT_TSCHED_WATERMARK_USEC (10*PA_USEC_PER_MSEC)
+#define DEFAULT_TSCHED_BUFFER_USEC (5*PA_USEC_PER_SEC)
+#define DEFAULT_TSCHED_WATERMARK_USEC (20*PA_USEC_PER_MSEC)
 
 struct userdata {
     pa_core *core;
@@ -749,14 +749,13 @@ static void thread_func(void *userdata) {
         if (PA_SOURCE_OPENED(u->source->thread_info.state)) {
             int work_done = 0;
 
-            if (u->use_mmap) {
-                if ((work_done = mmap_read(u)) < 0)
-                    goto fail;
+            if (u->use_mmap)
+                work_done = mmap_read(u);
+            else
+                work_done = unix_read(u);
 
-            } else {
-                if ((work_done = unix_read(u) < 0))
-                    goto fail;
-            }
+            if (work_done < 0)
+                goto fail;
 
             if (work_done)
                 update_smoother(u);
@@ -807,46 +806,9 @@ static void thread_func(void *userdata) {
             }
 
             if (revents & (POLLERR|POLLNVAL|POLLHUP)) {
-                snd_pcm_state_t state;
-
-                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");
-
-                state = snd_pcm_state(u->pcm_handle);
-                pa_log_warn("PCM state is %s", snd_pcm_state_name(state));
-
-                /* Try to recover from this error */
 
-                switch (state) {
-
-                    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;
-                }
+                if (pa_alsa_recover_from_poll(u->pcm_handle, revents))
+                    goto fail;
 
                 snd_pcm_start(u->pcm_handle);
             }

commit 3c8e83fb3ebd4e1e6496e047cbf4c357550631b4
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Apr 23 18:10:34 2008 +0000

    do not fix automatic buffer attrs anymore, the new protocol version doesn't need this anymore and it creates more problems than it solves. Also drop the initial timing info query. Correct programs shouldn't depend on it anyway
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2300 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulse/internal.h b/src/pulse/internal.h
index d988e1a..f15c69c 100644
--- a/src/pulse/internal.h
+++ b/src/pulse/internal.h
@@ -116,7 +116,6 @@ struct pa_stream {
     uint32_t stream_index;
     pa_stream_direction_t direction;
     pa_stream_state_t state;
-    pa_bool_t buffer_attr_not_ready, timing_info_not_ready;
 
     uint32_t requested_bytes;
 
diff --git a/src/pulse/stream.c b/src/pulse/stream.c
index e67f24c..ccbabb5 100644
--- a/src/pulse/stream.c
+++ b/src/pulse/stream.c
@@ -68,8 +68,6 @@ pa_stream *pa_stream_new_with_proplist(pa_context *c, const char *name, const pa
     s->context = c;
     s->mainloop = c->mainloop;
 
-    s->buffer_attr_not_ready = s->timing_info_not_ready = FALSE;
-
     s->read_callback = NULL;
     s->read_userdata = NULL;
     s->write_callback = NULL;
@@ -527,9 +525,6 @@ static void create_stream_complete(pa_stream *s) {
     pa_assert(PA_REFCNT_VALUE(s) >= 1);
     pa_assert(s->state == PA_STREAM_CREATING);
 
-    if (s->buffer_attr_not_ready || s->timing_info_not_ready)
-        return;
-
     pa_stream_set_state(s, PA_STREAM_READY);
 
     if (s->requested_bytes > 0 && s->write_callback)
@@ -562,7 +557,7 @@ static void automatic_buffer_attr(pa_stream *s, pa_buffer_attr *attr, const pa_s
         attr->tlength = pa_bytes_per_second(ss)*2; /* 2s of buffering */
 
     if (!attr->minreq <= 0)
-        attr->minreq = (9*attr->tlength)/10; /* Ask for more data when there are only 200ms left in the playback buffer */
+        attr->minreq = (2*attr->tlength)/10; /* Ask for more data when there are only 200ms left in the playback buffer */
 
     if (!attr->prebuf)
         attr->prebuf = attr->tlength; /* Start to play only when the playback is fully filled up once */
@@ -644,25 +639,6 @@ void pa_create_stream_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED
         s->device_name = pa_xstrdup(dn);
         s->suspended = suspended;
 
-        if (!s->manual_buffer_attr && pa_bytes_per_second(&ss) != pa_bytes_per_second(&s->sample_spec)) {
-            pa_buffer_attr attr;
-            pa_operation *o;
-
-            memset(&attr, 0, sizeof(attr));
-            automatic_buffer_attr(s, &attr, &ss);
-
-            /* If we need to update the buffer metrics, we wait for
-             * the the OK for that call before we go to
-             * PA_STREAM_READY */
-
-            s->state = PA_STREAM_READY;
-            pa_assert_se(o = pa_stream_set_buffer_attr(s, &attr, NULL, NULL));
-            pa_operation_unref(o);
-            s->state = PA_STREAM_CREATING;
-
-            s->buffer_attr_not_ready = TRUE;
-        }
-
         s->channel_map = cm;
         s->sample_spec = ss;
     }
@@ -703,19 +679,6 @@ 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);
 
-    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;
-
-        s->timing_info_not_ready = TRUE;
-    }
-
     create_stream_complete(s);
 
 finish:
@@ -1212,12 +1175,6 @@ 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) {
-        o->stream->timing_info_not_ready = FALSE;
-        create_stream_complete(o->stream);
-    }
-
     if (o->stream->latency_update_callback)
         o->stream->latency_update_callback(o->stream, o->stream->latency_update_userdata);
 
@@ -1777,11 +1734,6 @@ static void stream_set_buffer_attr_callback(pa_pdispatch *pd, uint32_t command,
         o->stream->manual_buffer_attr = TRUE;
     }
 
-    if (o->stream->state == PA_STREAM_CREATING) {
-        o->stream->buffer_attr_not_ready = FALSE;
-        create_stream_complete(o->stream);
-    }
-
     if (o->callback) {
         pa_stream_success_cb_t cb = (pa_stream_success_cb_t) o->callback;
         cb(o->stream, success, o->userdata);
@@ -1826,6 +1778,9 @@ pa_operation* pa_stream_set_buffer_attr(pa_stream *s, const pa_buffer_attr *attr
     else
         pa_tagstruct_putu32(t, attr->fragsize);
 
+    if (s->context->version >= 13)
+        pa_tagstruct_put_boolean(t, !!(s->flags & PA_STREAM_ADJUST_LATENCY));
+
     pa_pstream_send_tagstruct(s->context->pstream, t);
     pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, stream_set_buffer_attr_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
 

commit af03dd4e4fe668c988e1d9e781212763d3e9d56e
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Apr 23 18:11:14 2008 +0000

    drop a misplaced newline
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2301 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/resampler.c b/src/pulsecore/resampler.c
index 3d7e536..d645639 100644
--- a/src/pulsecore/resampler.c
+++ b/src/pulsecore/resampler.c
@@ -1442,7 +1442,6 @@ static void peaks_resample(pa_resampler *r, const pa_memchunk *input, unsigned i
 
         pa_assert(o_index * fz < pa_memblock_get_length(output->memblock));
 
-
         if (r->work_format == PA_SAMPLE_S16NE) {
             unsigned i, c;
             int16_t *s = (int16_t*) ((uint8_t*) src + fz * j);

commit ed0af46e69a207249bfbade2babfbc93b3f89fc9
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Apr 23 18:11:57 2008 +0000

    unify code that fixes up buffering metrics
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2302 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c
index cde113d..ca14b95 100644
--- a/src/pulsecore/protocol-native.c
+++ b/src/pulsecore/protocol-native.c
@@ -470,11 +470,65 @@ static int record_stream_process_msg(pa_msgobject *o, int code, void*userdata, i
     return 0;
 }
 
+static void fix_record_buffer_attr_pre(record_stream *s, pa_bool_t adjust_latency, uint32_t *maxlength, uint32_t *fragsize) {
+    pa_assert(s);
+    pa_assert(maxlength);
+    pa_assert(fragsize);
+
+    if (*maxlength <= 0 || *maxlength > MAX_MEMBLOCKQ_LENGTH)
+        *maxlength = MAX_MEMBLOCKQ_LENGTH;
+
+    if (*fragsize <= 0)
+        *fragsize = pa_usec_to_bytes(DEFAULT_FRAGSIZE_MSEC*PA_USEC_PER_MSEC, &s->source_output->sample_spec);
+
+    if (adjust_latency) {
+        pa_usec_t fragsize_usec;
+
+        /* So, the user asked us to adjust the latency according to
+         * the what the source can provide. Half the latency will be
+         * spent on the hw buffer, half of it in the async buffer
+         * queue we maintain for each client. */
+
+        fragsize_usec = pa_bytes_to_usec(*fragsize, &s->source_output->sample_spec);
+
+        s->source_latency = pa_source_output_set_requested_latency(s->source_output, fragsize_usec/2);
+
+        if (fragsize_usec >= s->source_latency*2)
+            fragsize_usec -= s->source_latency;
+        else
+            fragsize_usec = s->source_latency;
+
+        *fragsize = pa_usec_to_bytes(fragsize_usec, &s->source_output->sample_spec);
+    }
+}
+
+static void fix_record_buffer_attr_post(record_stream *s, uint32_t *maxlength, uint32_t *fragsize) {
+    size_t base;
+
+    pa_assert(s);
+    pa_assert(maxlength);
+    pa_assert(fragsize);
+
+    *maxlength = pa_memblockq_get_maxlength(s->memblockq);
+
+    base = pa_frame_size(&s->source_output->sample_spec);
+
+    s->fragment_size = (*fragsize/base)*base;
+    if (s->fragment_size <= 0)
+        s->fragment_size = base;
+
+    if (s->fragment_size > *maxlength)
+        s->fragment_size = *maxlength;
+
+    *fragsize = s->fragment_size;
+}
+
 static record_stream* record_stream_new(
         connection *c,
         pa_source *source,
         pa_sample_spec *ss,
         pa_channel_map *map,
+        pa_bool_t peak_detect,
         uint32_t *maxlength,
         uint32_t *fragsize,
         pa_source_output_flags_t flags,
@@ -501,6 +555,8 @@ static record_stream* record_stream_new(
     data.source = source;
     pa_source_output_new_data_set_sample_spec(&data, ss);
     pa_source_output_new_data_set_channel_map(&data, map);
+    if (peak_detect)
+        data.resample_method = PA_RESAMPLER_PEAKS;
 
     source_output = pa_source_output_new(c->protocol->core, &data, flags);
 
@@ -522,30 +578,7 @@ static record_stream* record_stream_new(
     s->source_output->suspend = source_output_suspend_cb;
     s->source_output->userdata = s;
 
-    if (*maxlength <= 0 || *maxlength > MAX_MEMBLOCKQ_LENGTH)
-        *maxlength = MAX_MEMBLOCKQ_LENGTH;
-    if (*fragsize <= 0)
-        *fragsize = pa_usec_to_bytes(DEFAULT_FRAGSIZE_MSEC*PA_USEC_PER_MSEC, &source_output->sample_spec);
-
-    if (adjust_latency) {
-        pa_usec_t fragsize_usec;
-
-        /* So, the user asked us to adjust the latency according to
-         * the what the source can provide. Half the latency will be
-         * spent on the hw buffer, half of it in the async buffer
-         * queue we maintain for each client. */
-
-        fragsize_usec = pa_bytes_to_usec(*fragsize, &source_output->sample_spec);
-
-        s->source_latency = pa_source_output_set_requested_latency(source_output, fragsize_usec/2);
-
-        if (fragsize_usec >= s->source_latency*2)
-            fragsize_usec -= s->source_latency;
-        else
-            fragsize_usec = s->source_latency;
-
-        *fragsize = pa_usec_to_bytes(fragsize_usec, &source_output->sample_spec);
-    }
+    fix_record_buffer_attr_pre(s, adjust_latency, maxlength, fragsize);
 
     s->memblockq = pa_memblockq_new(
             0,
@@ -557,16 +590,7 @@ static record_stream* record_stream_new(
             0,
             NULL);
 
-    *maxlength = pa_memblockq_get_maxlength(s->memblockq);
-
-    s->fragment_size = (*fragsize/base)*base;
-    if (s->fragment_size <= 0)
-        s->fragment_size = base;
-
-    if (s->fragment_size > *maxlength)
-        s->fragment_size = *maxlength;
-
-    *fragsize = s->fragment_size;
+    fix_record_buffer_attr_post(s, maxlength, fragsize);
 
     *ss = s->source_output->sample_spec;
     *map = s->source_output->channel_map;
@@ -674,6 +698,114 @@ static int playback_stream_process_msg(pa_msgobject *o, int code, void*userdata,
     return 0;
 }
 
+static void fix_playback_buffer_attr_pre(playback_stream *s, pa_bool_t adjust_latency, uint32_t *maxlength, uint32_t *tlength, uint32_t* prebuf, uint32_t* minreq) {
+    size_t frame_size;
+    pa_usec_t tlength_usec, minreq_usec, sink_usec;
+
+    pa_assert(s);
+    pa_assert(maxlength);
+    pa_assert(tlength);
+    pa_assert(prebuf);
+    pa_assert(minreq);
+
+    if (*maxlength <= 0 || *maxlength > MAX_MEMBLOCKQ_LENGTH)
+        *maxlength = MAX_MEMBLOCKQ_LENGTH;
+    if (*tlength <= 0)
+        *tlength = pa_usec_to_bytes(DEFAULT_TLENGTH_MSEC*PA_USEC_PER_MSEC, &s->sink_input->sample_spec);
+    if (*minreq <= 0)
+        *minreq = pa_usec_to_bytes(DEFAULT_PROCESS_MSEC*PA_USEC_PER_MSEC, &s->sink_input->sample_spec);
+
+    frame_size = pa_frame_size(&s->sink_input->sample_spec);
+    if (*minreq <= 0)
+        *minreq = frame_size;
+    if (*tlength < *minreq+frame_size)
+        *tlength = *minreq+frame_size;
+
+    tlength_usec = pa_bytes_to_usec(*tlength, &s->sink_input->sample_spec);
+    minreq_usec = pa_bytes_to_usec(*minreq, &s->sink_input->sample_spec);
+
+    pa_log_info("Requested tlength=%0.2f ms, minreq=%0.2f ms",
+                (double) tlength_usec / PA_USEC_PER_MSEC,
+                (double) minreq_usec / PA_USEC_PER_MSEC);
+
+    if (adjust_latency) {
+
+        /* So, the user asked us to adjust the latency of the stream
+         * buffer according to the what the sink can provide. The
+         * tlength passed in shall be the overall latency. Roughly
+         * half the latency will be spent on the hw buffer, the other
+         * half of it in the async buffer queue we maintain for each
+         * client. In between we'll have a safety space of size
+         * 2*minreq. Why the 2*minreq? When the hw buffer is completey
+         * empty and needs to be filled, then our buffer must have
+         * enough data to fulfill this request immediatly and thus
+         * have at least the same tlength as the size of the hw
+         * buffer. It additionally needs space for 2 times minreq
+         * because if the buffer ran empty and a partial fillup
+         * happens immediately on the next iteration we need to be
+         * able to fulfill it and give the application also minreq
+         * time to fill it up again for the next request Makes 2 times
+         * minreq in plus.. */
+
+        if (tlength_usec > minreq_usec*2)
+            sink_usec = (tlength_usec - minreq_usec*2)/2;
+        else
+            sink_usec = 0;
+
+    } else {
+
+        /* Ok, the user didn't ask us to adjust the latency, but we
+         * still need to make sure that the parameters from the user
+         * do make sense. */
+
+        if (tlength_usec > minreq_usec*2)
+            sink_usec = (tlength_usec - minreq_usec*2);
+        else
+            sink_usec = 0;
+    }
+
+    s->sink_latency = pa_sink_input_set_requested_latency(s->sink_input, sink_usec);
+
+    if (adjust_latency) {
+        /* Ok, we didn't necessarily get what we were asking for, so
+         * let's subtract from what we asked for for the remaining
+         * buffer space */
+
+        if (tlength_usec >= s->sink_latency)
+            tlength_usec -= s->sink_latency;
+    }
+
+    if (tlength_usec < s->sink_latency + 2*minreq_usec)
+        tlength_usec = s->sink_latency + 2*minreq_usec;
+
+    *tlength = pa_usec_to_bytes(tlength_usec, &s->sink_input->sample_spec);
+    *minreq = pa_usec_to_bytes(minreq_usec, &s->sink_input->sample_spec);
+
+    if (*minreq <= 0) {
+        *minreq += frame_size;
+        *tlength += frame_size*2;
+    }
+
+    if (*tlength <= *minreq)
+        *tlength =  *minreq*2 + frame_size;
+
+    if (*prebuf <= 0)
+        *prebuf = *tlength;
+}
+
+static void fix_playback_buffer_attr_post(playback_stream *s, uint32_t *maxlength, uint32_t *tlength, uint32_t* prebuf, uint32_t* minreq) {
+    pa_assert(s);
+    pa_assert(maxlength);
+    pa_assert(tlength);
+    pa_assert(prebuf);
+    pa_assert(minreq);
+
+    *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);
+}
+
 static playback_stream* playback_stream_new(
         connection *c,
         pa_sink *sink,
@@ -697,8 +829,6 @@ static playback_stream* playback_stream_new(
     uint32_t idx;
     int64_t start_index;
     pa_sink_input_new_data data;
-    pa_usec_t tlength_usec, minreq_usec, sink_usec;
-    size_t frame_size;
 
     pa_assert(c);
     pa_assert(ss);
@@ -769,90 +899,7 @@ static playback_stream* playback_stream_new(
 
     start_index = ssync ? pa_memblockq_get_read_index(ssync->memblockq) : 0;
 
-    if (*maxlength <= 0 || *maxlength > MAX_MEMBLOCKQ_LENGTH)
-        *maxlength = MAX_MEMBLOCKQ_LENGTH;
-    if (*tlength <= 0)
-        *tlength = pa_usec_to_bytes(DEFAULT_TLENGTH_MSEC*PA_USEC_PER_MSEC, &sink_input->sample_spec);
-    if (*minreq <= 0)
-        *minreq = pa_usec_to_bytes(DEFAULT_PROCESS_MSEC*PA_USEC_PER_MSEC, &sink_input->sample_spec);
-
-    frame_size = pa_frame_size(&sink_input->sample_spec);
-    if (*minreq <= 0)
-        *minreq = frame_size;
-    if (*tlength < *minreq+frame_size)
-        *tlength = *minreq+frame_size;
-
-    tlength_usec = pa_bytes_to_usec(*tlength, &sink_input->sample_spec);
-    minreq_usec = pa_bytes_to_usec(*minreq, &sink_input->sample_spec);
-
-    pa_log_info("Requested tlength=%0.2f ms, minreq=%0.2f ms",
-                (double) tlength_usec / PA_USEC_PER_MSEC,
-                (double) minreq_usec / PA_USEC_PER_MSEC);
-
-    if (adjust_latency) {
-
-        /* So, the user asked us to adjust the latency of the stream
-         * buffer according to the what the sink can provide. The
-         * tlength passed in shall be the overall latency. Roughly
-         * half the latency will be spent on the hw buffer, the other
-         * half of it in the async buffer queue we maintain for each
-         * client. In between we'll have a safety space of size
-         * 2*minreq. Why the 2*minreq? When the hw buffer is completey
-         * empty and needs to be filled, then our buffer must have
-         * enough data to fulfill this request immediatly and thus
-         * have at least the same tlength as the size of the hw
-         * buffer. It additionally needs space for 2 times minreq
-         * because if the buffer ran empty and a partial fillup
-         * happens immediately on the next iteration we need to be
-         * able to fulfill it and give the application also minreq
-         * time to fill it up again for the next request Makes 2 times
-         * minreq in plus.. */
-
-        if (tlength_usec > minreq_usec*2)
-            sink_usec = (tlength_usec - minreq_usec*2)/2;
-        else
-            sink_usec = 0;
-
-    } else {
-
-        /* Ok, the user didn't ask us to adjust the latency, but we
-         * still need to make sure that the parameters from the user
-         * do make sense. */
-
-        if (tlength_usec > minreq_usec*2)
-            sink_usec = (tlength_usec - minreq_usec*2);
-        else
-            sink_usec = 0;
-    }
-
-    s->sink_latency = pa_sink_input_set_requested_latency(sink_input, sink_usec);
-
-    if (adjust_latency) {
-        /* Ok, we didn't necessarily get what we were asking for, so
-         * let's subtract from what we asked for for the remaining
-         * buffer space */
-
-        if (tlength_usec >= s->sink_latency)
-            tlength_usec -= s->sink_latency;
-    }
-
-    if (tlength_usec < s->sink_latency + 2*minreq_usec)
-        tlength_usec = s->sink_latency + 2*minreq_usec;
-
-    *tlength = pa_usec_to_bytes(tlength_usec, &sink_input->sample_spec);
-    *minreq = pa_usec_to_bytes(minreq_usec, &sink_input->sample_spec);
-
-    if (*minreq <= 0) {
-        *minreq += frame_size;
-        *tlength += frame_size*2;
-    }
-
-    if (*tlength <= *minreq)
-        *tlength =  *minreq*2 + frame_size;
-
-    if (*prebuf <= 0)
-        *prebuf = *tlength;
-
+    fix_playback_buffer_attr_pre(s, adjust_latency, maxlength, tlength, prebuf, minreq);
     pa_sink_input_get_silence(sink_input, &silence);
 
     s->memblockq = pa_memblockq_new(
@@ -866,17 +913,14 @@ static playback_stream* playback_stream_new(
             &silence);
 
     pa_memblock_unref(silence.memblock);
+    fix_playback_buffer_attr_post(s, maxlength, tlength, prebuf, minreq);
 
-    *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);
 
     *ss = s->sink_input->sample_spec;
     *map = s->sink_input->channel_map;
 
-    s->minreq = pa_memblockq_get_minreq(s->memblockq);
+    s->minreq = *minreq;
     pa_atomic_store(&s->missing, 0);
     s->drain_request = FALSE;
 
@@ -1671,7 +1715,8 @@ static void command_create_record_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_
         fix_channels = FALSE,
         no_move = FALSE,
         variable_rate = FALSE,
-        adjust_latency = FALSE;
+        adjust_latency = FALSE,
+        peak_detect = FALSE;
     pa_source_output_flags_t flags = 0;
     pa_proplist *p;
 
@@ -1720,7 +1765,8 @@ static void command_create_record_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_
 
     if (c->version >= 13) {
 
-        if (pa_tagstruct_get_boolean(t, &adjust_latency) < 0 ||
+        if (pa_tagstruct_get_boolean(t, &peak_detect) < 0 ||
+            pa_tagstruct_get_boolean(t, &adjust_latency) < 0 ||
             pa_tagstruct_get_proplist(t, p) < 0) {
             protocol_error(c);
             pa_proplist_free(p);
@@ -1761,7 +1807,7 @@ static void command_create_record_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_
         (no_move ?  PA_SOURCE_OUTPUT_DONT_MOVE : 0) |
         (variable_rate ?  PA_SOURCE_OUTPUT_VARIABLE_RATE : 0);
 
-    s = record_stream_new(c, source, &ss, &map, &maxlength, &fragment_size, flags, p, adjust_latency);
+    s = record_stream_new(c, source, &ss, &map, peak_detect, &maxlength, &fragment_size, flags, p, adjust_latency);
     pa_proplist_free(p);
 
     CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_INVALID);
@@ -2940,6 +2986,7 @@ static void command_set_stream_buffer_attr(pa_pdispatch *pd, uint32_t command, u
 
     if (command == PA_COMMAND_SET_PLAYBACK_STREAM_BUFFER_ATTR) {
         playback_stream *s;
+        pa_bool_t adjust_latency = FALSE;
 
         s = pa_idxset_get_by_index(c->output_streams, idx);
         CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
@@ -2952,34 +2999,28 @@ static void command_set_stream_buffer_attr(pa_pdispatch *pd, uint32_t command, u
                     PA_TAG_U32, &prebuf,
                     PA_TAG_U32, &minreq,
                     PA_TAG_INVALID) < 0 ||
+            (c->version >= 13 && pa_tagstruct_get_boolean(t, &adjust_latency) < 0) ||
             !pa_tagstruct_eof(t)) {
             protocol_error(c);
             return;
         }
 
-        if (maxlength <= 0 || maxlength > MAX_MEMBLOCKQ_LENGTH)
-            maxlength = MAX_MEMBLOCKQ_LENGTH;
-        if (tlength <= 0)
-            tlength = pa_usec_to_bytes(DEFAULT_TLENGTH_MSEC*1000, &s->sink_input->sample_spec);
-        if (minreq <= 0)
-            minreq = (tlength*9)/10;
-        if (prebuf <= 0)
-            prebuf = tlength;
-
+        fix_playback_buffer_attr_pre(s, adjust_latency, &maxlength, &tlength, &prebuf, &minreq);
         pa_memblockq_set_maxlength(s->memblockq, maxlength);
         pa_memblockq_set_tlength(s->memblockq, tlength);
         pa_memblockq_set_prebuf(s->memblockq, prebuf);
         pa_memblockq_set_minreq(s->memblockq, minreq);
+        fix_playback_buffer_attr_post(s, &maxlength, &tlength, &prebuf, &minreq);
 
         reply = reply_new(tag);
-        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, maxlength);
+        pa_tagstruct_putu32(reply, tlength);
+        pa_tagstruct_putu32(reply, prebuf);
+        pa_tagstruct_putu32(reply, minreq);
 
     } else {
         record_stream *s;
-        size_t base;
+        pa_bool_t adjust_latency = FALSE;
         pa_assert(command == PA_COMMAND_SET_RECORD_STREAM_BUFFER_ATTR);
 
         s = pa_idxset_get_by_index(c->record_streams, idx);
@@ -2990,29 +3031,19 @@ static void command_set_stream_buffer_attr(pa_pdispatch *pd, uint32_t command, u
                     PA_TAG_U32, &maxlength,
                     PA_TAG_U32, &fragsize,
                     PA_TAG_INVALID) < 0 ||
+            (c->version >= 13 && pa_tagstruct_get_boolean(t, &adjust_latency) < 0) ||
             !pa_tagstruct_eof(t)) {
             protocol_error(c);
             return;
         }
 
-        if (maxlength <= 0 || maxlength > MAX_MEMBLOCKQ_LENGTH)
-            maxlength = MAX_MEMBLOCKQ_LENGTH;
-        if (fragsize <= 0)
-            fragsize = pa_usec_to_bytes(DEFAULT_FRAGSIZE_MSEC*1000, &s->source_output->sample_spec);
-
+        fix_record_buffer_attr_pre(s, adjust_latency, &maxlength, &fragsize);
         pa_memblockq_set_maxlength(s->memblockq, maxlength);
-
-        base = pa_frame_size(&s->source_output->sample_spec);
-        s->fragment_size = (fragsize/base)*base;
-        if (s->fragment_size <= 0)
-            s->fragment_size = base;
-
-        if (s->fragment_size > pa_memblockq_get_maxlength(s->memblockq))
-            s->fragment_size = pa_memblockq_get_maxlength(s->memblockq);
+        fix_record_buffer_attr_post(s, &maxlength, &fragsize);
 
         reply = reply_new(tag);
-        pa_tagstruct_putu32(reply, (uint32_t) pa_memblockq_get_maxlength(s->memblockq));
-        pa_tagstruct_putu32(reply, s->fragment_size);
+        pa_tagstruct_putu32(reply, maxlength);
+        pa_tagstruct_putu32(reply, fragsize);
     }
 
     pa_pstream_send_tagstruct(c->pstream, reply);

commit 3f57d3aab2ded1c730ac8625e8ca6242d4445954
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Apr 23 18:12:46 2008 +0000

    add new function pa_alsa_build_pollfd() to alsa-util to unify a bit more common code from the sink and the source
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2303 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/alsa-util.c b/src/modules/alsa-util.c
index 11367d9..0c4c020 100644
--- a/src/modules/alsa-util.c
+++ b/src/modules/alsa-util.c
@@ -1093,3 +1093,27 @@ int pa_alsa_recover_from_poll(snd_pcm_t *pcm, int revents) {
 
     return 0;
 }
+
+pa_rtpoll_item* pa_alsa_build_pollfd(snd_pcm_t *pcm, pa_rtpoll *rtpoll) {
+    int n, err;
+    struct pollfd *pollfd;
+    pa_rtpoll_item *item;
+
+    pa_assert(pcm);
+
+    if ((n = snd_pcm_poll_descriptors_count(pcm)) < 0) {
+        pa_log("snd_pcm_poll_descriptors_count() failed: %s", snd_strerror(n));
+        return NULL;
+    }
+
+    item = pa_rtpoll_item_new(rtpoll, PA_RTPOLL_NEVER, n);
+    pollfd = pa_rtpoll_item_get_pollfd(item, NULL);
+
+    if ((err = snd_pcm_poll_descriptors(pcm, pollfd, n)) < 0) {
+        pa_log("snd_pcm_poll_descriptors() failed: %s", snd_strerror(err));
+        pa_rtpoll_item_free(item);
+        return NULL;
+    }
+
+    return item;
+}

commit 998ed8ede1f4ff700b36864e58e3ed3ae284e486
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Apr 23 18:13:11 2008 +0000

    add missing header definitions for last commit
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2304 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/alsa-util.h b/src/modules/alsa-util.h
index 5494b40..442c264 100644
--- a/src/modules/alsa-util.h
+++ b/src/modules/alsa-util.h
@@ -32,6 +32,8 @@
 #include <pulse/channelmap.h>
 #include <pulse/proplist.h>
 
+#include <pulsecore/rtpoll.h>
+
 typedef struct pa_alsa_fdlist pa_alsa_fdlist;
 
 struct pa_alsa_fdlist *pa_alsa_fdlist_new(void);
@@ -92,4 +94,6 @@ void pa_alsa_init_proplist(pa_proplist *p, snd_pcm_info_t *pcm_info);
 
 int pa_alsa_recover_from_poll(snd_pcm_t *pcm, int revents);
 
+pa_rtpoll_item* pa_alsa_build_pollfd(snd_pcm_t *pcm, pa_rtpoll *rtpoll);
+
 #endif

commit 0b183fbdc6c83a0fe0f19343c72a524f0bb2ca9f
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Apr 23 18:14:25 2008 +0000

    respect the resampler's maximum block size to avoid that we get kicked out of the memory pool due to resampling. actually drop data from the delay queue after we used it
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2305 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/source-output.c b/src/pulsecore/source-output.c
index 9c75b39..de543a5 100644
--- a/src/pulsecore/source-output.c
+++ b/src/pulsecore/source-output.c
@@ -359,7 +359,7 @@ pa_usec_t pa_source_output_get_latency(pa_source_output *o) {
 /* Called from thread context */
 void pa_source_output_push(pa_source_output *o, const pa_memchunk *chunk) {
     size_t length;
-    size_t limit;
+    size_t limit, mbs = 0;
 
     pa_source_output_assert_ref(o);
     pa_assert(PA_SOURCE_OUTPUT_LINKED(o->thread_info.state));
@@ -396,6 +396,12 @@ void pa_source_output_push(pa_source_output *o, const pa_memchunk *chunk) {
         else {
             pa_memchunk rchunk;
 
+            if (mbs == 0)
+                mbs = pa_resampler_max_block_size(o->thread_info.resampler);
+
+            if (qchunk.length > mbs)
+                qchunk.length = mbs;
+
             pa_resampler_run(o->thread_info.resampler, &qchunk, &rchunk);
 
             if (rchunk.length > 0)
@@ -405,6 +411,7 @@ void pa_source_output_push(pa_source_output *o, const pa_memchunk *chunk) {
         }
 
         pa_memblock_unref(qchunk.memblock);
+        pa_memblockq_drop(o->thread_info.delay_memblockq, qchunk.length);
     }
 }
 

commit f2dffb717d592fb02f009f235e8a05763c500684
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Apr 23 18:17:17 2008 +0000

    pa_bool_t'ization
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2306 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/tests/asyncq-test.c b/src/tests/asyncq-test.c
index 09b2004..0e10ed8 100644
--- a/src/tests/asyncq-test.c
+++ b/src/tests/asyncq-test.c
@@ -44,7 +44,7 @@ static void producer(void *_q) {
         pa_asyncq_push(q, PA_UINT_TO_PTR(i+1), 1);
     }
 
-    pa_asyncq_push(q, PA_UINT_TO_PTR(-1), 1);
+    pa_asyncq_push(q, PA_UINT_TO_PTR(-1), TRUE);
     printf("pushed end\n");
 }
 
@@ -56,7 +56,7 @@ static void consumer(void *_q) {
     sleep(1);
 
     for (i = 0;; i++) {
-        p = pa_asyncq_pop(q, 1);
+        p = pa_asyncq_pop(q, TRUE);
 
         if (p == PA_UINT_TO_PTR(-1))
             break;

commit a197644ea2cac5e35f2ca6d3d2af149ebedc13ba
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Apr 23 18:19:45 2008 +0000

    add new tool 'stripnul' which can be used to drop leading zeros from a file which is useful to do byte-by-byte comparison of what goes in and comes out of PA
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2307 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/tests/stripnul.c b/src/tests/stripnul.c
new file mode 100644
index 0000000..2f87e87
--- /dev/null
+++ b/src/tests/stripnul.c
@@ -0,0 +1,72 @@
+/* $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 <string.h>
+#include <inttypes.h>
+
+#include <pulse/xmalloc.h>
+#include <pulsecore/macro.h>
+
+int main(int argc, char *argv[]) {
+    FILE *i, *o;
+    size_t granularity;
+    pa_bool_t found;
+    uint8_t *zero;
+
+    pa_assert_se(argc >= 2);
+    pa_assert_se((granularity = atoi(argv[1])) >= 1);
+    pa_assert_se((i = (argc >= 3) ? fopen(argv[2], "r") : stdin));
+    pa_assert_se((o = (argc >= 4) ? fopen(argv[3], "w") : stdout));
+
+    zero = pa_xmalloc0(granularity);
+
+    for (;;) {
+        uint8_t buffer[16*1024], *p;
+        size_t k;
+
+        k = fread(buffer, granularity, sizeof(buffer)/granularity, i);
+
+        if (k <= 0)
+            break;
+
+        if (found)
+            pa_assert_se(fwrite(buffer, granularity, k, o) == k);
+        else {
+            for (p = buffer; (p-buffer)/granularity < k; p += granularity)
+                if (memcmp(p, zero, granularity)) {
+                    size_t left;
+                    found = TRUE;
+                    left = k - (p-buffer)/granularity;
+                    pa_assert_se(fwrite(p, granularity, left, o) == left);
+                    break;
+                }
+        }
+    }
+
+    fflush(o);
+
+    return 0;
+}

commit 76031df4a4a156b7a6a9723b108bfdb37521ef7c
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Apr 23 18:26:48 2008 +0000

    Big pile of interdependant changes:
    * Fix a deadlock when an asyncq overflows and an RT thread needed to wait until space became available again while the main thread was waiting for a operation to complete and thus didn't free any new items. Now, if the asyncq overflows, queue those items temporarily, and return immediately. Then, when the queue becomes writable again, flush it.
    * Modify pa_thread_mq_init() to also set up pa_rtpoll events properly for the MQ
    * Some more pa_bool_t'ization
    * Unify more common code between alsa-sink and alsa-source
    * The upper limit for the tsched watermark is max_use minus one frame
    * make module-alsa-source work
    * make the alsa modules use pa_alsa_build_pollfd() now
    * fix detection of dB scale for alsa-source
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2308 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-alsa-sink.c b/src/modules/module-alsa-sink.c
index 665dbde..bc95e6c 100644
--- a/src/modules/module-alsa-sink.c
+++ b/src/modules/module-alsa-sink.c
@@ -131,7 +131,6 @@ struct userdata {
     int64_t frame_index;
 
     snd_pcm_sframes_t hwbuf_unused_frames;
-    snd_pcm_sframes_t avail_min_frames;
 };
 
 static void fix_tsched_watermark(struct userdata *u) {
@@ -140,8 +139,61 @@ static void fix_tsched_watermark(struct userdata *u) {
 
     max_use = u->hwbuf_size - u->hwbuf_unused_frames * u->frame_size;
 
-    if (u->tsched_watermark >= max_use/2)
-        u->tsched_watermark = max_use/2;
+    if (u->tsched_watermark >= max_use-u->frame_size)
+        u->tsched_watermark = max_use-u->frame_size;
+}
+
+static int try_recover(struct userdata *u, const char *call, int err) {
+    pa_assert(u);
+    pa_assert(call);
+    pa_assert(err < 0);
+
+    pa_log_debug("%s: %s", call, snd_strerror(err));
+
+    if (err == -EAGAIN) {
+        pa_log_debug("%s: EAGAIN", call);
+        return 1;
+    }
+
+    if (err == -EPIPE)
+        pa_log_debug("%s: Buffer underrun!", call);
+
+    if ((err = snd_pcm_recover(u->pcm_handle, err, 1)) == 0) {
+        u->first = TRUE;
+        return 0;
+    }
+
+    pa_log("%s: %s", call, snd_strerror(err));
+    return -1;
+}
+
+static void check_left_to_play(struct userdata *u, snd_pcm_sframes_t n) {
+    size_t left_to_play;
+
+    if (u->first)
+        return;
+
+    if (n*u->frame_size < u->hwbuf_size)
+        left_to_play = u->hwbuf_size - (n*u->frame_size);
+    else
+        left_to_play = 0;
+
+    if (left_to_play > 0)
+        pa_log_debug("%0.2f ms left to play", (double) pa_bytes_to_usec(left_to_play, &u->sink->sample_spec) / PA_USEC_PER_MSEC);
+    else {
+        pa_log_info("Underrun!");
+
+        if (u->use_tsched) {
+            size_t old_watermark = u->tsched_watermark;
+
+            u->tsched_watermark *= 2;
+            fix_tsched_watermark(u);
+
+            if (old_watermark != u->tsched_watermark)
+                pa_log_notice("Increasing wakeup watermark to %0.2f ms",
+                              (double) pa_bytes_to_usec(u->tsched_watermark, &u->sink->sample_spec) / PA_USEC_PER_MSEC);
+        }
+    }
 }
 
 static int mmap_write(struct userdata *u) {
@@ -154,10 +206,9 @@ static int mmap_write(struct userdata *u) {
         pa_memchunk chunk;
         void *p;
         snd_pcm_sframes_t n;
-        int err;
+        int err, r;
         const snd_pcm_channel_area_t *areas;
         snd_pcm_uframes_t offset, frames;
-        size_t left_to_play;
 
         snd_pcm_hwsync(u->pcm_handle);
 
@@ -166,70 +217,40 @@ static int mmap_write(struct userdata *u) {
 
         if (PA_UNLIKELY((n = snd_pcm_avail_update(u->pcm_handle)) < 0)) {
 
-            pa_log_debug("snd_pcm_avail_update: %s", snd_strerror(n));
-
-            if (err == -EAGAIN) {
-                pa_log_debug("EAGAIN");
-                return work_done;
-            }
-
-            if (n == -EPIPE)
-                pa_log_debug("snd_pcm_avail_update: Buffer underrun!");
-
-            if ((err = snd_pcm_recover(u->pcm_handle, n, 1)) == 0) {
-                u->first = TRUE;
+            if ((r = try_recover(u, "snd_pcm_avail_update", n)) == 0)
                 continue;
-            }
+            else if (r > 0)
+                return work_done;
 
-            pa_log("snd_pcm_recover: %s", snd_strerror(err));
-            return -1;
+            return r;
         }
 
+        check_left_to_play(u, n);
+
         /* We only use part of the buffer that matches our
          * dynamically requested latency */
 
         if (PA_UNLIKELY(n <= u->hwbuf_unused_frames))
             return work_done;
 
-        if (n*u->frame_size < u->hwbuf_size)
-            left_to_play = u->hwbuf_size - (n*u->frame_size);
-        else
-            left_to_play = 0;
-
-        pa_log_debug("%0.2f ms left to play", (double) pa_bytes_to_usec(left_to_play, &u->sink->sample_spec) / PA_USEC_PER_MSEC);
-
-        if (left_to_play <= 0 && !u->first) {
-            u->tsched_watermark *= 2;
-            fix_tsched_watermark(u);
-            pa_log_notice("Underrun! Increasing wakeup watermark to %0.2f ms",
-                          (double) pa_bytes_to_usec(u->tsched_watermark, &u->sink->sample_spec) / PA_USEC_PER_MSEC);
-        }
-
         frames = n = n - u->hwbuf_unused_frames;
 
-        pa_log_debug("%llu frames to write", (unsigned long long) frames);
+        pa_log_debug("%lu frames to write", (unsigned long) frames);
 
         if (PA_UNLIKELY((err = snd_pcm_mmap_begin(u->pcm_handle, &areas, &offset, &frames)) < 0)) {
 
-            pa_log_debug("snd_pcm_mmap_begin: %s", snd_strerror(err));
-
-            if (err == -EAGAIN) {
-                pa_log_debug("EAGAIN");
-                return work_done;
-            }
-
-            if (err == -EPIPE)
-                pa_log_debug("snd_pcm_mmap_begin: Buffer underrun!");
-
-            if ((err = snd_pcm_recover(u->pcm_handle, err, 1)) == 0) {
-                u->first = TRUE;
+            if ((r = try_recover(u, "snd_pcm_mmap_begin", err)) == 0)
                 continue;
-            }
+            else if (r > 0)
+                return work_done;
 
-            pa_log("Failed to write data to DSP: %s", snd_strerror(err));
-            return -1;
+            return r;
         }
 
+        /* Make sure that if these memblocks need to be copied they will fit into one slot */
+        if (frames > pa_mempool_block_size_max(u->sink->core->mempool)/u->frame_size)
+            frames = pa_mempool_block_size_max(u->sink->core->mempool)/u->frame_size;
+
         /* Check these are multiples of 8 bit */
         pa_assert((areas[0].first & 7) == 0);
         pa_assert((areas[0].step & 7)== 0);
@@ -240,7 +261,7 @@ static int mmap_write(struct userdata *u) {
 
         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.memblock = pa_memblock_new_fixed(u->core->mempool, p, frames * u->frame_size, TRUE);
         chunk.length = pa_memblock_get_length(chunk.memblock);
         chunk.index = 0;
 
@@ -252,30 +273,19 @@ static int mmap_write(struct userdata *u) {
 
         if (PA_UNLIKELY((err = snd_pcm_mmap_commit(u->pcm_handle, offset, frames)) < 0)) {
 
-            pa_log_debug("snd_pcm_mmap_commit: %s", snd_strerror(err));
-
-            if (err == -EAGAIN) {
-                pa_log_debug("EAGAIN");
-                return work_done;
-            }
-
-            if (err == -EPIPE)
-                pa_log_debug("snd_pcm_mmap_commit: Buffer underrun!");
-
-            if ((err = snd_pcm_recover(u->pcm_handle, err, 1)) == 0) {
-                u->first = TRUE;
+            if ((r = try_recover(u, "snd_pcm_mmap_commit", err)) == 0)
                 continue;
-            }
+            else if (r > 0)
+                return work_done;
 
-            pa_log("Failed to write data to DSP: %s", snd_strerror(err));
-            return -1;
+            return r;
         }
 
         work_done = 1;
 
         u->frame_index += frames;
 
-        pa_log_debug("wrote %llu frames", (unsigned long long) frames);
+        pa_log_debug("wrote %lu frames", (unsigned long) frames);
 
         if (PA_LIKELY(frames >= (snd_pcm_uframes_t) n))
             return work_done;
@@ -283,40 +293,37 @@ static int mmap_write(struct userdata *u) {
 }
 
 static int unix_write(struct userdata *u) {
-    snd_pcm_status_t *status;
     int work_done = 0;
 
-    snd_pcm_status_alloca(&status);
-
     pa_assert(u);
     pa_sink_assert_ref(u->sink);
 
     for (;;) {
         void *p;
         snd_pcm_sframes_t n, frames;
-        int err;
+        int r;
 
         snd_pcm_hwsync(u->pcm_handle);
-        snd_pcm_avail_update(u->pcm_handle);
 
-        if (PA_UNLIKELY((err = snd_pcm_status(u->pcm_handle, status)) < 0)) {
-            pa_log("Failed to query DSP status data: %s", snd_strerror(err));
-            return -1;
-        }
+        if (PA_UNLIKELY((n = snd_pcm_avail_update(u->pcm_handle)) < 0)) {
 
-        if (PA_UNLIKELY(snd_pcm_status_get_avail_max(status)*u->frame_size >= u->hwbuf_size))
-            pa_log_debug("Buffer underrun!");
+            if ((r = try_recover(u, "snd_pcm_avail_update", n)) == 0)
+                continue;
+            else if (r > 0)
+                return work_done;
 
-        n = snd_pcm_status_get_avail(status);
+            return r;
+        }
 
-        /* We only use part of the buffer that matches our
-         * dynamically requested latency */
+        check_left_to_play(u, n);
 
         if (PA_UNLIKELY(n <= u->hwbuf_unused_frames))
             return work_done;
 
         n -= u->hwbuf_unused_frames;
 
+        pa_log_debug("%lu frames to write", (unsigned long) frames);
+
         if (u->memchunk.length <= 0)
             pa_sink_render(u->sink, n * u->frame_size, &u->memchunk);
 
@@ -335,21 +342,12 @@ static int unix_write(struct userdata *u) {
 
         if (PA_UNLIKELY(frames < 0)) {
 
-            if (frames == -EAGAIN) {
-                pa_log_debug("EAGAIN");
-                return work_done;
-            }
-
-            if (frames == -EPIPE)
-                pa_log_debug("snd_pcm_avail_update: Buffer underrun!");
-
-            if ((frames = snd_pcm_recover(u->pcm_handle, frames, 1)) == 0) {
-                u->first = TRUE;
+            if ((r = try_recover(u, "snd_pcm_writei", n)) == 0)
                 continue;
-            }
+            else if (r > 0)
+                return work_done;
 
-            pa_log("Failed to write data to DSP: %s", snd_strerror(frames));
-            return -1;
+            return r;
         }
 
         u->memchunk.index += frames * u->frame_size;
@@ -364,6 +362,8 @@ static int unix_write(struct userdata *u) {
 
         u->frame_index += frames;
 
+        pa_log_debug("wrote %lu frames", (unsigned long) frames);
+
         if (PA_LIKELY(frames >= n))
             return work_done;
     }
@@ -399,8 +399,8 @@ static void update_smoother(struct userdata *u) {
         return;
     }
 
-
     frames = u->frame_index - delay;
+
 /*     pa_log_debug("frame_index = %llu, delay = %llu, p = %llu", (unsigned long long) u->frame_index, (unsigned long long) delay, (unsigned long long) frames); */
 
 /*     snd_pcm_status_get_tstamp(status, &timestamp); */
@@ -422,7 +422,7 @@ static pa_usec_t sink_get_latency(struct userdata *u) {
     now1 = pa_rtclock_usec();
     now2 = pa_smoother_get(u->smoother, now1);
 
-    delay = (int64_t) pa_bytes_to_usec(u->frame_index * u->frame_size, &u->sink->sample_spec) - now2;
+    delay = (int64_t) pa_bytes_to_usec(u->frame_index * u->frame_size, &u->sink->sample_spec) - (int64_t) now2;
 
     if (delay > 0)
         r = (pa_usec_t) delay;
@@ -434,28 +434,14 @@ static pa_usec_t sink_get_latency(struct userdata *u) {
 }
 
 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));
+    if (!(u->alsa_rtpoll_item = pa_alsa_build_pollfd(u->pcm_handle, u->rtpoll)))
         return -1;
-    }
 
     return 0;
 }
@@ -491,7 +477,7 @@ static pa_usec_t hw_sleep_time(struct userdata *u) {
     if (usec == (pa_usec_t) -1)
         usec = pa_bytes_to_usec(u->hwbuf_size, &u->sink->sample_spec);
 
-/*     pa_log_debug("hw buffer time: %u ms", (unsigned) (usec / PA_USEC_PER_MSEC)); */
+    pa_log_debug("hw buffer time: %u ms", (unsigned) (usec / PA_USEC_PER_MSEC));
 
     wm = pa_bytes_to_usec(u->tsched_watermark, &u->sink->sample_spec);
 
@@ -505,25 +491,27 @@ static pa_usec_t hw_sleep_time(struct userdata *u) {
         usec /= 2;
     }
 
-/*     pa_log_debug("after watermark: %u ms", (unsigned) (usec / PA_USEC_PER_MSEC)); */
+    pa_log_debug("after watermark: %u ms", (unsigned) (usec / PA_USEC_PER_MSEC));
 
     return usec;
 }
 
 static int update_sw_params(struct userdata *u) {
+    snd_pcm_uframes_t avail_min;
     int err;
-    pa_usec_t latency;
 
     pa_assert(u);
 
     /* Use the full buffer if noone asked us for anything specific */
     u->hwbuf_unused_frames = 0;
 
-    if (u->use_tsched)
+    if (u->use_tsched) {
+        pa_usec_t latency;
+
         if ((latency = pa_sink_get_requested_latency_within_thread(u->sink)) != (pa_usec_t) -1) {
             size_t b;
 
-            pa_log_debug("latency set to %llu", (unsigned long long) latency);
+            pa_log_debug("latency set to %0.2f", (double) latency / PA_USEC_PER_MSEC);
 
             b = pa_usec_to_bytes(latency, &u->sink->sample_spec);
 
@@ -538,23 +526,23 @@ static int update_sw_params(struct userdata *u) {
 
             fix_tsched_watermark(u);
         }
+    }
 
     pa_log_debug("hwbuf_unused_frames=%lu", (unsigned long) u->hwbuf_unused_frames);
 
     /* We need at last one frame in the used part of the buffer */
-    u->avail_min_frames = u->hwbuf_unused_frames + 1;
+    avail_min = u->hwbuf_unused_frames + 1;
 
     if (u->use_tsched) {
         pa_usec_t usec;
 
         usec = hw_sleep_time(u);
-
-        u->avail_min_frames += (pa_usec_to_bytes(usec, &u->sink->sample_spec) / u->frame_size);
+        avail_min += pa_usec_to_bytes(usec, &u->sink->sample_spec);
     }
 
-    pa_log_debug("setting avail_min=%lu", (unsigned long) u->avail_min_frames);
+    pa_log_debug("setting avail_min=%lu", (unsigned long) avail_min);
 
-    if ((err = pa_alsa_set_sw_params(u->pcm_handle, u->avail_min_frames)) < 0) {
+    if ((err = pa_alsa_set_sw_params(u->pcm_handle, avail_min)) < 0) {
         pa_log("Failed to set software parameters: %s", snd_strerror(err));
         return err;
     }
@@ -678,14 +666,6 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
             }
 
             break;
-
-/*         case PA_SINK_MESSAGE_ADD_INPUT: */
-/*         case PA_SINK_MESSAGE_REMOVE_INPUT: */
-/*         case PA_SINK_MESSAGE_REMOVE_INPUT_AND_BUFFER: { */
-/*             int r = pa_sink_process_msg(o, code, data, offset, chunk); */
-/*             update_hwbuf_unused_frames(u); */
-/*             return r; */
-/*         } */
     }
 
     return pa_sink_process_msg(o, code, data, offset, chunk);
@@ -1091,10 +1071,9 @@ int pa__init(pa_module*m) {
     u->use_mmap = use_mmap;
     u->use_tsched = use_tsched;
     u->first = TRUE;
-    pa_thread_mq_init(&u->thread_mq, m->core->mainloop);
     u->rtpoll = pa_rtpoll_new();
+    pa_thread_mq_init(&u->thread_mq, m->core->mainloop, u->rtpoll);
     u->alsa_rtpoll_item = NULL;
-    pa_rtpoll_item_new_asyncmsgq(u->rtpoll, PA_RTPOLL_EARLY, u->thread_mq.inq);
 
     u->smoother = pa_smoother_new(DEFAULT_TSCHED_BUFFER_USEC*2, DEFAULT_TSCHED_BUFFER_USEC*2, TRUE);
     usec = pa_rtclock_usec();
@@ -1238,7 +1217,6 @@ int pa__init(pa_module*m) {
     u->nfragments = nfrags;
     u->hwbuf_size = u->fragment_size * nfrags;
     u->hwbuf_unused_frames = 0;
-    u->avail_min_frames = 0;
     u->tsched_watermark = tsched_watermark;
     u->frame_index = 0;
     u->hw_dB_supported = FALSE;
@@ -1246,12 +1224,10 @@ int pa__init(pa_module*m) {
     u->hw_volume_min = u->hw_volume_max = 0;
 
     if (use_tsched)
-        if (u->tsched_watermark >= u->hwbuf_size/2)
-            u->tsched_watermark = pa_frame_align(u->hwbuf_size/2, &ss);
+        fix_tsched_watermark(u);
 
     u->sink->thread_info.max_rewind = use_tsched ? u->hwbuf_size : 0;
     u->sink->max_latency = pa_bytes_to_usec(u->hwbuf_size, &ss);
-
     if (!use_tsched)
         u->sink->min_latency = u->sink->max_latency;
 
@@ -1325,7 +1301,7 @@ int pa__init(pa_module*m) {
                     u->sink->get_volume = sink_get_volume_cb;
                     u->sink->set_volume = sink_set_volume_cb;
                     u->sink->flags |= PA_SINK_HW_VOLUME_CTRL | (u->hw_dB_supported ? PA_SINK_DECIBEL_VOLUME : 0);
-                    pa_log_info("Using hardware volume control. %s dB scale.", u->hw_dB_supported ? "Using" : "Not using");
+                    pa_log_info("Using hardware volume control. Hardware dB scale %s.", u->hw_dB_supported ? "supported" : "not supported");
 
                 } else if (mixer_reset) {
                     pa_log_info("Using software volume control. Trying to reset sound card to 0 dB.");
diff --git a/src/modules/module-alsa-source.c b/src/modules/module-alsa-source.c
index bcb3c2d..3999ada 100644
--- a/src/modules/module-alsa-source.c
+++ b/src/modules/module-alsa-source.c
@@ -127,8 +127,70 @@ struct userdata {
 
     pa_smoother *smoother;
     int64_t frame_index;
+
+    snd_pcm_sframes_t hwbuf_unused_frames;
 };
 
+static void fix_tsched_watermark(struct userdata *u) {
+    size_t max_use;
+    pa_assert(u);
+
+    max_use = u->hwbuf_size - u->hwbuf_unused_frames * u->frame_size;
+
+    if (u->tsched_watermark >= max_use-u->frame_size)
+        u->tsched_watermark = max_use-u->frame_size;
+}
+
+static int try_recover(struct userdata *u, const char *call, int err) {
+    pa_assert(u);
+    pa_assert(call);
+    pa_assert(err < 0);
+
+    pa_log_debug("%s: %s", call, snd_strerror(err));
+
+    if (err == -EAGAIN) {
+        pa_log_debug("%s: EAGAIN", call);
+        return 1;
+    }
+
+    if (err == -EPIPE)
+        pa_log_debug("%s: Buffer overrun!", call);
+
+    if ((err = snd_pcm_recover(u->pcm_handle, err, 1)) == 0) {
+        snd_pcm_start(u->pcm_handle);
+        return 0;
+    }
+
+    pa_log("%s: %s", call, snd_strerror(err));
+    return -1;
+}
+
+static void check_left_to_record(struct userdata *u, snd_pcm_sframes_t n) {
+    size_t left_to_record;
+
+    if (n*u->frame_size < u->hwbuf_size)
+        left_to_record = u->hwbuf_size - (n*u->frame_size);
+    else
+        left_to_record = 0;
+
+    if (left_to_record > 0)
+        pa_log_debug("%0.2f ms left to record", (double) pa_bytes_to_usec(left_to_record, &u->source->sample_spec) / PA_USEC_PER_MSEC);
+    else {
+        pa_log_info("Overrun!");
+
+        if (u->use_tsched) {
+            size_t old_watermark = u->tsched_watermark;
+
+            u->tsched_watermark *= 2;
+            fix_tsched_watermark(u);
+
+            if (old_watermark != u->tsched_watermark)
+                pa_log_notice("Increasing wakeup watermark to %0.2f ms",
+                              (double) pa_bytes_to_usec(u->tsched_watermark, &u->source->sample_spec) / PA_USEC_PER_MSEC);
+        }
+    }
+}
+
 static int mmap_read(struct userdata *u) {
     int work_done = 0;
 
@@ -137,7 +199,7 @@ static int mmap_read(struct userdata *u) {
 
     for (;;) {
         snd_pcm_sframes_t n;
-        int err;
+        int err, r;
         const snd_pcm_channel_area_t *areas;
         snd_pcm_uframes_t offset, frames;
         pa_memchunk chunk;
@@ -147,51 +209,37 @@ static int mmap_read(struct userdata *u) {
 
         if (PA_UNLIKELY((n = snd_pcm_avail_update(u->pcm_handle)) < 0)) {
 
-            pa_log_debug("snd_pcm_avail_update: %s", snd_strerror(n));
-
-            if (err == -EAGAIN) {
-                pa_log_debug("EAGAIN");
-                return work_done;
-            }
-
-            if (n == -EPIPE)
-                pa_log_debug("snd_pcm_avail_update: Buffer underrun!");
-
-            if ((err = snd_pcm_recover(u->pcm_handle, n, 1)) == 0) {
-                snd_pcm_start(u->pcm_handle);
+            if ((r = try_recover(u, "snd_pcm_avail_update", err)) == 0)
                 continue;
-            }
+            else if (r > 0)
+                return work_done;
 
-            pa_log("snd_pcm_recover: %s", snd_strerror(err));
-            return -1;
+            return r;
         }
 
+        check_left_to_record(u, n);
+
         if (PA_UNLIKELY(n <= 0))
             return work_done;
 
         frames = n;
 
-        if (PA_UNLIKELY((err = snd_pcm_mmap_begin(u->pcm_handle, &areas, &offset, &frames)) < 0)) {
+        pa_log_debug("%lu frames to read", (unsigned long) frames);
 
-            pa_log_debug("snd_pcm_mmap_begin: %s", snd_strerror(err));
-
-            if (err == -EAGAIN) {
-                pa_log_debug("EAGAIN");
-                return work_done;
-            }
-
-            if (err == -EPIPE)
-                pa_log_debug("snd_pcm_mmap_begin: Buffer underrun!");
+        if (PA_UNLIKELY((err = snd_pcm_mmap_begin(u->pcm_handle, &areas, &offset, &frames)) < 0)) {
 
-            if ((err = snd_pcm_recover(u->pcm_handle, err, 1)) == 0) {
-                snd_pcm_start(u->pcm_handle);
+            if ((r = try_recover(u, "snd_pcm_mmap_begin", err)) == 0)
                 continue;
-            }
+            else if (r > 0)
+                return work_done;
 
-            pa_log("Failed to write data to DSP: %s", snd_strerror(err));
-            return -1;
+            return r;
         }
 
+        /* Make sure that if these memblocks need to be copied they will fit into one slot */
+        if (frames > pa_mempool_block_size_max(u->source->core->mempool)/u->frame_size)
+            frames = pa_mempool_block_size_max(u->source->core->mempool)/u->frame_size;
+
         /* Check these are multiples of 8 bit */
         pa_assert((areas[0].first & 7) == 0);
         pa_assert((areas[0].step & 7)== 0);
@@ -202,42 +250,28 @@ static int mmap_read(struct userdata *u) {
 
         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.memblock = pa_memblock_new_fixed(u->core->mempool, p, frames * u->frame_size, TRUE);
         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 (PA_UNLIKELY((err = snd_pcm_mmap_commit(u->pcm_handle, offset, frames)) < 0)) {
 
-            pa_log_debug("snd_pcm_mmap_commit: %s", snd_strerror(err));
-
-            if (err == -EAGAIN) {
-                pa_log_debug("EAGAIN");
-                return work_done;
-            }
-
-            if (err == -EPIPE)
-                pa_log_debug("snd_pcm_mmap_commit: Buffer underrun!");
-
-            if ((err = snd_pcm_recover(u->pcm_handle, err, 1)) == 0) {
-                snd_pcm_start(u->pcm_handle);
+            if ((r = try_recover(u, "snd_pcm_mmap_commit", err)) == 0)
                 continue;
-            }
+            else if (r > 0)
+                return work_done;
 
-            pa_log("Failed to write data to DSP: %s", snd_strerror(err));
-            return -1;
+            return r;
         }
 
         work_done = 1;
 
         u->frame_index += frames;
 
-        pa_log_debug("read %llu frames", (unsigned long long) frames);
+        pa_log_debug("read %lu frames", (unsigned long) frames);
 
         if (PA_LIKELY(frames >= (snd_pcm_uframes_t) n))
             return work_done;
@@ -245,31 +279,30 @@ static int mmap_read(struct userdata *u) {
 }
 
 static int unix_read(struct userdata *u) {
-    snd_pcm_status_t *status;
     int work_done = 0;
 
-    snd_pcm_status_alloca(&status);
-
     pa_assert(u);
     pa_source_assert_ref(u->source);
 
     for (;;) {
         void *p;
         snd_pcm_sframes_t n, frames;
-        int err;
+        int r;
         pa_memchunk chunk;
 
         snd_pcm_hwsync(u->pcm_handle);
 
-        if (PA_UNLIKELY((err = snd_pcm_status(u->pcm_handle, status)) < 0)) {
-            pa_log("Failed to query DSP status data: %s", snd_strerror(err));
-            return -1;
-        }
+        if (PA_UNLIKELY((n = snd_pcm_avail_update(u->pcm_handle)) < 0)) {
+
+            if ((r = try_recover(u, "snd_pcm_avail_update", n)) == 0)
+                continue;
+            else if (r > 0)
+                return work_done;
 
-        if (PA_UNLIKELY(snd_pcm_status_get_avail_max(status)*u->frame_size >= u->hwbuf_size))
-            pa_log_debug("Buffer overrun!");
+            return r;
+        }
 
-        n = snd_pcm_status_get_avail(status);
+        check_left_to_record(u, n);
 
         if (PA_UNLIKELY(n <= 0))
             return work_done;
@@ -281,6 +314,8 @@ static int unix_read(struct userdata *u) {
         if (frames > n)
             frames = n;
 
+        pa_log_debug("%lu frames to read", (unsigned long) n);
+
         p = pa_memblock_acquire(chunk.memblock);
         frames = snd_pcm_readi(u->pcm_handle, (uint8_t*) p, frames);
         pa_memblock_release(chunk.memblock);
@@ -290,20 +325,12 @@ static int unix_read(struct userdata *u) {
         if (PA_UNLIKELY(frames < 0)) {
             pa_memblock_unref(chunk.memblock);
 
-            if (frames == -EAGAIN) {
-                pa_log_debug("EAGAIN");
-                return work_done;
-            }
-
-            if (frames == -EPIPE)
-                pa_log_debug("snd_pcm_avail_update: Buffer overrun!");
-
-            if ((frames = snd_pcm_recover(u->pcm_handle, frames, 1)) == 0)
-                snd_pcm_start(u->pcm_handle);
+            if ((r = try_recover(u, "snd_pcm_readi", n)) == 0)
                 continue;
+            else if (r > 0)
+                return work_done;
 
-            pa_log("Failed to read data from DSP: %s", snd_strerror(frames));
-            return -1;
+            return r;
         }
 
         chunk.index = 0;
@@ -316,6 +343,8 @@ static int unix_read(struct userdata *u) {
 
         u->frame_index += frames;
 
+        pa_log_debug("read %lu frames", (unsigned long) frames);
+
         if (PA_LIKELY(frames >= n))
             return work_done;
     }
@@ -344,46 +373,37 @@ static void update_smoother(struct userdata *u) {
 
     now1 = pa_rtclock_usec();
     now2 = pa_bytes_to_usec(frames * u->frame_size, &u->source->sample_spec);
+
     pa_smoother_put(u->smoother, now1, now2);
 }
 
 static pa_usec_t source_get_latency(struct userdata *u) {
     pa_usec_t r = 0;
     int64_t delay;
+    pa_usec_t now1, now2;
 
     pa_assert(u);
 
-    delay = pa_smoother_get(u->smoother, pa_rtclock_usec()) - u->frame_index;
+    now1 = pa_rtclock_usec();
+    now2 = pa_smoother_get(u->smoother, now1);
+
+    delay = (int64_t) now2 - pa_bytes_to_usec(u->frame_index * u->frame_size, &u->source->sample_spec);
 
     if (delay > 0)
-        r = pa_bytes_to_usec(delay * u->frame_size, &u->source->sample_spec);
+        r = (pa_usec_t) delay;
 
     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));
+    if (!(u->alsa_rtpoll_item = pa_alsa_build_pollfd(u->pcm_handle, u->rtpoll)))
         return -1;
-    }
 
     return 0;
 }
@@ -418,7 +438,7 @@ static pa_usec_t hw_sleep_time(struct userdata *u) {
     if (usec == (pa_usec_t) -1)
         usec = pa_bytes_to_usec(u->hwbuf_size, &u->source->sample_spec);
 
-    pa_log_debug("hw buffer time: %u ms", (unsigned) (usec / PA_USEC_PER_MSEC));
+/*     pa_log_debug("hw buffer time: %u ms", (unsigned) (usec / PA_USEC_PER_MSEC)); */
 
     wm = pa_bytes_to_usec(u->tsched_watermark, &u->source->sample_spec);
 
@@ -427,29 +447,55 @@ static pa_usec_t hw_sleep_time(struct userdata *u) {
     else
         usec /= 2;
 
-    pa_log_debug("after watermark: %u ms", (unsigned) (usec / PA_USEC_PER_MSEC));
+/*     pa_log_debug("after watermark: %u ms", (unsigned) (usec / PA_USEC_PER_MSEC)); */
 
     return usec;
 }
 
 static int update_sw_params(struct userdata *u) {
-    size_t avail_min;
+    snd_pcm_uframes_t avail_min;
     int err;
 
     pa_assert(u);
 
+    /* Use the full buffer if noone asked us for anything specific */
+    u->hwbuf_unused_frames = 0;
+
     if (u->use_tsched) {
-        pa_usec_t usec;
+        pa_usec_t latency;
 
-        usec = hw_sleep_time(u);
+        if ((latency = pa_source_get_requested_latency_within_thread(u->source)) != (pa_usec_t) -1) {
+            size_t b;
 
-        avail_min = pa_usec_to_bytes(usec, &u->source->sample_spec);
+            pa_log_debug("latency set to %0.2f", (double) latency / PA_USEC_PER_MSEC);
 
-        if (avail_min <= 0)
-            avail_min = 1;
+            b = pa_usec_to_bytes(latency, &u->source->sample_spec);
 
-    } else
-        avail_min = 1;
+            /* We need at least one sample in our buffer */
+
+            if (PA_UNLIKELY(b < u->frame_size))
+                b = u->frame_size;
+
+            u->hwbuf_unused_frames =
+                PA_LIKELY(b < u->hwbuf_size) ?
+                ((u->hwbuf_size - b) / u->frame_size) : 0;
+
+            fix_tsched_watermark(u);
+        }
+    }
+
+    pa_log_debug("hwbuf_unused_frames=%lu", (unsigned long) u->hwbuf_unused_frames);
+
+    avail_min = 1;
+
+    if (u->use_tsched) {
+        pa_usec_t usec;
+
+        usec = hw_sleep_time(u);
+        avail_min += pa_usec_to_bytes(usec, &u->source->sample_spec);
+    }
+
+    pa_log_debug("setting avail_min=%lu", (unsigned long) avail_min);
 
     if ((err = pa_alsa_set_sw_params(u->pcm_handle, avail_min)) < 0) {
         pa_log("Failed to set software parameters: %s", snd_strerror(err));
@@ -649,7 +695,6 @@ static int source_set_volume_cb(pa_source *s) {
         long alsa_vol;
         pa_volume_t vol;
 
-
         pa_assert(snd_mixer_selem_has_capture_channel(u->mixer_elem, u->mixer_map[i]));
 
         vol = PA_MIN(s->volume.values[i], PA_VOLUME_NORM);
@@ -670,7 +715,6 @@ static int source_set_volume_cb(pa_source *s) {
             u->hw_dB_supported = FALSE;
         }
 
-
         alsa_vol = (long) roundf(((float) vol * (u->hw_volume_max - u->hw_volume_min)) / PA_VOLUME_NORM) + u->hw_volume_min;
         alsa_vol = PA_CLAMP_UNLIKELY(alsa_vol, u->hw_volume_min, u->hw_volume_max);
 
@@ -745,6 +789,8 @@ static void thread_func(void *userdata) {
     for (;;) {
         int ret;
 
+        pa_log_debug("loop");
+
         /* Read some data and pass it to the sources */
         if (PA_SOURCE_OPENED(u->source->thread_info.state)) {
             int work_done = 0;
@@ -757,6 +803,8 @@ static void thread_func(void *userdata) {
             if (work_done < 0)
                 goto fail;
 
+            pa_log_debug("work_done = %i", work_done);
+
             if (work_done)
                 update_smoother(u);
 
@@ -806,8 +854,7 @@ static void thread_func(void *userdata) {
             }
 
             if (revents & (POLLERR|POLLNVAL|POLLHUP)) {
-
-                if (pa_alsa_recover_from_poll(u->pcm_handle, revents))
+                if (pa_alsa_recover_from_poll(u->pcm_handle, revents) < 0)
                     goto fail;
 
                 snd_pcm_start(u->pcm_handle);
@@ -910,10 +957,9 @@ int pa__init(pa_module*m) {
     m->userdata = u;
     u->use_mmap = use_mmap;
     u->use_tsched = use_tsched;
-    pa_thread_mq_init(&u->thread_mq, m->core->mainloop);
     u->rtpoll = pa_rtpoll_new();
+    pa_thread_mq_init(&u->thread_mq, m->core->mainloop, u->rtpoll);
     u->alsa_rtpoll_item = NULL;
-    pa_rtpoll_item_new_asyncmsgq(u->rtpoll, PA_RTPOLL_EARLY, u->thread_mq.inq);
 
     u->smoother = pa_smoother_new(DEFAULT_TSCHED_WATERMARK_USEC, DEFAULT_TSCHED_WATERMARK_USEC, TRUE);
     pa_smoother_set_time_offset(u->smoother, pa_rtclock_usec());
@@ -951,7 +997,7 @@ int pa__init(pa_module*m) {
 
     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;
+        u->use_mmap = use_mmap = FALSE;
     }
 
     if (use_tsched && (!b || !d)) {
@@ -1030,7 +1076,7 @@ int pa__init(pa_module*m) {
     pa_proplist_sets(data.proplist, PA_PROP_DEVICE_STRING, u->device_name);
     pa_proplist_setf(data.proplist, PA_PROP_DEVICE_BUFFERING_BUFFER_SIZE, "%lu", (unsigned long) (period_frames * frame_size * nfrags));
     pa_proplist_setf(data.proplist, PA_PROP_DEVICE_BUFFERING_FRAGMENT_SIZE, "%lu", (unsigned long) (period_frames * frame_size));
-    pa_proplist_sets(data.proplist, PA_PROP_DEVICE_ACCESS_MODE, u->use_tsched ? "mmap_rewrite" : (u->use_mmap ? "mmap" : "serial"));
+    pa_proplist_sets(data.proplist, PA_PROP_DEVICE_ACCESS_MODE, u->use_tsched ? "mmap+timer" : (u->use_mmap ? "mmap" : "serial"));
 
     u->source = pa_source_new(m->core, &data, PA_SOURCE_HARDWARE|PA_SOURCE_LATENCY);
     pa_source_new_data_done(&data);
@@ -1052,14 +1098,17 @@ int pa__init(pa_module*m) {
     u->fragment_size = frag_size = period_frames * frame_size;
     u->nfragments = nfrags;
     u->hwbuf_size = u->fragment_size * nfrags;
+    u->hwbuf_unused_frames = 0;
     u->tsched_watermark = tsched_watermark;
     u->frame_index = 0;
     u->hw_dB_supported = FALSE;
     u->hw_dB_min = u->hw_dB_max = 0;
     u->hw_volume_min = u->hw_volume_max = 0;
 
-    u->source->max_latency = pa_bytes_to_usec(u->hwbuf_size, &ss);
+    if (use_tsched)
+        fix_tsched_watermark(u);
 
+    u->source->max_latency = pa_bytes_to_usec(u->hwbuf_size, &ss);
     if (!use_tsched)
         u->source->min_latency = u->source->max_latency;
 
@@ -1095,7 +1144,7 @@ int pa__init(pa_module*m) {
                     pa_log_info("Device has less than 4 volume levels. Falling back to software volume control.");
                     suitable = FALSE;
 
-                } else if (snd_mixer_selem_get_playback_dB_range(u->mixer_elem, &u->hw_dB_min, &u->hw_dB_max) >= 0) {
+                } else if (snd_mixer_selem_get_capture_dB_range(u->mixer_elem, &u->hw_dB_min, &u->hw_dB_max) >= 0) {
 
                     pa_log_info("Volume ranges from %0.2f dB to %0.2f dB.", u->hw_dB_min/100.0, u->hw_dB_max/100.0);
 
@@ -1122,7 +1171,7 @@ int pa__init(pa_module*m) {
                     u->source->get_volume = source_get_volume_cb;
                     u->source->set_volume = source_set_volume_cb;
                     u->source->flags |= PA_SOURCE_HW_VOLUME_CTRL | (u->hw_dB_supported ? PA_SOURCE_DECIBEL_VOLUME : 0);
-                    pa_log_info("Using hardware volume control. %s dB scale.", u->hw_dB_supported ? "Using" : "Not using");
+                    pa_log_info("Using hardware volume control. Hardware dB scale %s.", u->hw_dB_supported ? "supported" : "not supported");
 
                 } else if (mixer_reset) {
                     pa_log_info("Using software volume control. Trying to reset sound card to 0 dB.");
diff --git a/src/modules/module-null-sink.c b/src/modules/module-null-sink.c
index 6e59c62..2301f08 100644
--- a/src/modules/module-null-sink.c
+++ b/src/modules/module-null-sink.c
@@ -188,9 +188,8 @@ int pa__init(pa_module*m) {
     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);
+    pa_thread_mq_init(&u->thread_mq, m->core->mainloop, u->rtpoll);
 
     pa_sink_new_data_init(&data);
     data.driver = __FILE__;
diff --git a/src/modules/module-pipe-sink.c b/src/modules/module-pipe-sink.c
index 73a5211..870b32f 100644
--- a/src/modules/module-pipe-sink.c
+++ b/src/modules/module-pipe-sink.c
@@ -227,9 +227,8 @@ int pa__init(pa_module*m) {
     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);
+    pa_thread_mq_init(&u->thread_mq, m->core->mainloop, u->rtpoll);
 
     u->filename = pa_xstrdup(pa_modargs_get_value(ma, "file", DEFAULT_FILE_NAME));
 
diff --git a/src/modules/module-pipe-source.c b/src/modules/module-pipe-source.c
index cf88c82..5bf4da1 100644
--- a/src/modules/module-pipe-source.c
+++ b/src/modules/module-pipe-source.c
@@ -204,9 +204,8 @@ int pa__init(pa_module*m) {
     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);
+    pa_thread_mq_init(&u->thread_mq, m->core->mainloop, u->rtpoll);
 
     u->filename = pa_xstrdup(pa_modargs_get_value(ma, "file", DEFAULT_FILE_NAME));
 
diff --git a/src/pulsecore/asyncmsgq.c b/src/pulsecore/asyncmsgq.c
index 96b43a7..eba1c2c 100644
--- a/src/pulsecore/asyncmsgq.c
+++ b/src/pulsecore/asyncmsgq.c
@@ -136,7 +136,7 @@ void pa_asyncmsgq_post(pa_asyncmsgq *a, pa_msgobject *object, int code, const vo
 
     /* 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_asyncq_post(a->asyncq, i);
     pa_mutex_unlock(a->mutex);
 }
 
@@ -163,7 +163,7 @@ int pa_asyncmsgq_send(pa_asyncmsgq *a, pa_msgobject *object, int code, const voi
 
     /* 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_assert_se(pa_asyncq_push(a->asyncq, &i, TRUE) == 0);
     pa_mutex_unlock(a->mutex);
 
     pa_semaphore_wait(i.semaphore);
@@ -174,7 +174,7 @@ int pa_asyncmsgq_send(pa_asyncmsgq *a, pa_msgobject *object, int code, const voi
     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) {
+int pa_asyncmsgq_get(pa_asyncmsgq *a, pa_msgobject **object, int *code, void **userdata, int64_t *offset, pa_memchunk *chunk, pa_bool_t wait) {
     pa_assert(PA_REFCNT_VALUE(a) > 0);
     pa_assert(!a->current);
 
@@ -276,22 +276,40 @@ int pa_asyncmsgq_process_one(pa_asyncmsgq *a) {
     return 1;
 }
 
-int pa_asyncmsgq_get_fd(pa_asyncmsgq *a) {
+int pa_asyncmsgq_read_fd(pa_asyncmsgq *a) {
     pa_assert(PA_REFCNT_VALUE(a) > 0);
 
-    return pa_asyncq_get_fd(a->asyncq);
+    return pa_asyncq_read_fd(a->asyncq);
 }
 
-int pa_asyncmsgq_before_poll(pa_asyncmsgq *a) {
+int pa_asyncmsgq_read_before_poll(pa_asyncmsgq *a) {
     pa_assert(PA_REFCNT_VALUE(a) > 0);
 
-    return pa_asyncq_before_poll(a->asyncq);
+    return pa_asyncq_read_before_poll(a->asyncq);
 }
 
-void pa_asyncmsgq_after_poll(pa_asyncmsgq *a) {
+void pa_asyncmsgq_read_after_poll(pa_asyncmsgq *a) {
     pa_assert(PA_REFCNT_VALUE(a) > 0);
 
-    pa_asyncq_after_poll(a->asyncq);
+    pa_asyncq_read_after_poll(a->asyncq);
+}
+
+int pa_asyncmsgq_write_fd(pa_asyncmsgq *a) {
+    pa_assert(PA_REFCNT_VALUE(a) > 0);
+
+    return pa_asyncq_write_fd(a->asyncq);
+}
+
+void pa_asyncmsgq_write_before_poll(pa_asyncmsgq *a) {
+    pa_assert(PA_REFCNT_VALUE(a) > 0);
+
+    pa_asyncq_write_before_poll(a->asyncq);
+}
+
+void pa_asyncmsgq_write_after_poll(pa_asyncmsgq *a) {
+    pa_assert(PA_REFCNT_VALUE(a) > 0);
+
+    pa_asyncq_write_after_poll(a->asyncq);
 }
 
 int pa_asyncmsgq_dispatch(pa_msgobject *object, int code, void *userdata, int64_t offset, pa_memchunk *memchunk) {
diff --git a/src/pulsecore/asyncmsgq.h b/src/pulsecore/asyncmsgq.h
index 575f760..93f1ce8 100644
--- a/src/pulsecore/asyncmsgq.h
+++ b/src/pulsecore/asyncmsgq.h
@@ -62,15 +62,20 @@ 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_get(pa_asyncmsgq *q, pa_msgobject **object, int *code, void **userdata, int64_t *offset, pa_memchunk *memchunk, pa_bool_t 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);
+/* For the reading side */
+int pa_asyncmsgq_read_fd(pa_asyncmsgq *q);
+int pa_asyncmsgq_read_before_poll(pa_asyncmsgq *a);
+void pa_asyncmsgq_read_after_poll(pa_asyncmsgq *a);
+
+/* For the write side */
+int pa_asyncmsgq_write_fd(pa_asyncmsgq *q);
+void pa_asyncmsgq_write_before_poll(pa_asyncmsgq *a);
+void pa_asyncmsgq_write_after_poll(pa_asyncmsgq *a);
 
 #endif
diff --git a/src/pulsecore/asyncq.c b/src/pulsecore/asyncq.c
index 75b15c0..34506e4 100644
--- a/src/pulsecore/asyncq.c
+++ b/src/pulsecore/asyncq.c
@@ -33,6 +33,8 @@
 #include <pulsecore/thread.h>
 #include <pulsecore/macro.h>
 #include <pulsecore/core-util.h>
+#include <pulsecore/llist.h>
+#include <pulsecore/flist.h>
 #include <pulse/xmalloc.h>
 
 #include "asyncq.h"
@@ -51,13 +53,24 @@
 #define _Y do { } while(0)
 #endif
 
+struct localq {
+    void *data;
+    PA_LLIST_FIELDS(struct localq);
+};
+
 struct pa_asyncq {
     unsigned size;
     unsigned read_idx;
     unsigned write_idx;
     pa_fdsem *read_fdsem, *write_fdsem;
+
+    PA_LLIST_HEAD(struct localq, localq);
+    struct localq *last_localq;
+    pa_bool_t waiting_for_post;
 };
 
+PA_STATIC_FLIST_DECLARE(localq, 0, pa_xfree);
+
 #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) {
@@ -80,6 +93,10 @@ pa_asyncq *pa_asyncq_new(unsigned size) {
 
     l->size = size;
 
+    PA_LLIST_HEAD_INIT(struct localq, l->localq);
+    l->last_localq = NULL;
+    l->waiting_for_post = FALSE;
+
     if (!(l->read_fdsem = pa_fdsem_new())) {
         pa_xfree(l);
         return NULL;
@@ -95,6 +112,7 @@ pa_asyncq *pa_asyncq_new(unsigned size) {
 }
 
 void pa_asyncq_free(pa_asyncq *l, pa_free_cb_t free_cb) {
+    struct localq *q;
     pa_assert(l);
 
     if (free_cb) {
@@ -104,12 +122,22 @@ void pa_asyncq_free(pa_asyncq *l, pa_free_cb_t free_cb) {
             free_cb(p);
     }
 
+    while ((q = l->localq)) {
+        if (free_cb)
+            free_cb(q->data);
+
+        PA_LLIST_REMOVE(struct localq, l->localq, q);
+
+        if (pa_flist_push(PA_STATIC_FLIST_GET(localq), q) < 0)
+            pa_xfree(q);
+    }
+
     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) {
+static int push(pa_asyncq*l, void *p, pa_bool_t wait) {
     int idx;
     pa_atomic_ptr_t *cells;
 
@@ -141,7 +169,63 @@ int pa_asyncq_push(pa_asyncq*l, void *p, int wait) {
     return 0;
 }
 
-void* pa_asyncq_pop(pa_asyncq*l, int wait) {
+static pa_bool_t flush_postq(pa_asyncq *l) {
+    struct localq *q;
+
+    pa_assert(l);
+
+    while ((q = l->last_localq)) {
+
+        if (push(l, q->data, FALSE) < 0)
+            return FALSE;
+
+        l->last_localq = q->prev;
+
+        PA_LLIST_REMOVE(struct localq, l->localq, q);
+
+        if (pa_flist_push(PA_STATIC_FLIST_GET(localq), q) < 0)
+            pa_xfree(q);
+    }
+
+    return TRUE;
+}
+
+int pa_asyncq_push(pa_asyncq*l, void *p, pa_bool_t wait) {
+    pa_assert(l);
+
+    if (!flush_postq(l))
+        return -1;
+
+    return push(l, p, wait);
+}
+
+void pa_asyncq_post(pa_asyncq*l, void *p) {
+    struct localq *q;
+
+    pa_assert(l);
+    pa_assert(p);
+
+    if (pa_asyncq_push(l, p, FALSE) >= 0)
+        return;
+
+    /* OK, we couldn't push anything in the queue. So let's queue it
+     * locally and push it later */
+
+    pa_log("q overrun, queuing locally");
+
+    if (!(q = pa_flist_pop(PA_STATIC_FLIST_GET(localq))))
+        q = pa_xnew(struct localq, 1);
+
+    q->data = p;
+    PA_LLIST_PREPEND(struct localq, l->localq, q);
+
+    if (!l->last_localq)
+        l->last_localq = q;
+
+    return;
+}
+
+void* pa_asyncq_pop(pa_asyncq*l, pa_bool_t wait) {
     int idx;
     void *ret;
     pa_atomic_ptr_t *cells;
@@ -178,13 +262,13 @@ void* pa_asyncq_pop(pa_asyncq*l, int wait) {
     return ret;
 }
 
-int pa_asyncq_get_fd(pa_asyncq *q) {
+int pa_asyncq_read_fd(pa_asyncq *q) {
     pa_assert(q);
 
     return pa_fdsem_get(q->write_fdsem);
 }
 
-int pa_asyncq_before_poll(pa_asyncq *l) {
+int pa_asyncq_read_before_poll(pa_asyncq *l) {
     int idx;
     pa_atomic_ptr_t *cells;
 
@@ -206,8 +290,38 @@ int pa_asyncq_before_poll(pa_asyncq *l) {
     return 0;
 }
 
-void pa_asyncq_after_poll(pa_asyncq *l) {
+void pa_asyncq_read_after_poll(pa_asyncq *l) {
     pa_assert(l);
 
     pa_fdsem_after_poll(l->write_fdsem);
 }
+
+int pa_asyncq_write_fd(pa_asyncq *q) {
+    pa_assert(q);
+
+    return pa_fdsem_get(q->read_fdsem);
+}
+
+void pa_asyncq_write_before_poll(pa_asyncq *l) {
+    pa_assert(l);
+
+    for (;;) {
+
+        if (flush_postq(l))
+            break;
+
+        if (pa_fdsem_before_poll(l->read_fdsem) >= 0) {
+            l->waiting_for_post = TRUE;
+            break;
+        }
+    }
+}
+
+void pa_asyncq_write_after_poll(pa_asyncq *l) {
+    pa_assert(l);
+
+    if (l->waiting_for_post) {
+        pa_fdsem_after_poll(l->read_fdsem);
+        l->waiting_for_post = FALSE;
+    }
+}
diff --git a/src/pulsecore/asyncq.h b/src/pulsecore/asyncq.h
index 53d4586..4cdf8cd 100644
--- a/src/pulsecore/asyncq.h
+++ b/src/pulsecore/asyncq.h
@@ -26,6 +26,7 @@
 
 #include <sys/types.h>
 #include <pulse/def.h>
+#include <pulsecore/macro.h>
 
 /* A simple, asynchronous, lock-free (if requested also wait-free)
  * queue. Not multiple-reader/multiple-writer safe. If that is
@@ -46,11 +47,21 @@ 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);
+void* pa_asyncq_pop(pa_asyncq *q, pa_bool_t wait);
+int pa_asyncq_push(pa_asyncq *q, void *p, pa_bool_t 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);
+/* Similar to pa_asyncq_push(), but if the queue is full, postpone it
+ * locally and delay until pa_asyncq_before_poll_post() */
+void pa_asyncq_post(pa_asyncq*l, void *p);
+
+/* For the reading side */
+int pa_asyncq_read_fd(pa_asyncq *q);
+int pa_asyncq_read_before_poll(pa_asyncq *a);
+void pa_asyncq_read_after_poll(pa_asyncq *a);
+
+/* For the writing side */
+int pa_asyncq_write_fd(pa_asyncq *q);
+void pa_asyncq_write_before_poll(pa_asyncq *a);
+void pa_asyncq_write_after_poll(pa_asyncq *a);
 
 #endif
diff --git a/src/pulsecore/rtpoll.c b/src/pulsecore/rtpoll.c
index 734f344..c3e76ca 100644
--- a/src/pulsecore/rtpoll.c
+++ b/src/pulsecore/rtpoll.c
@@ -661,23 +661,23 @@ pa_rtpoll_item *pa_rtpoll_item_new_fdsem(pa_rtpoll *p, pa_rtpoll_priority_t prio
     return i;
 }
 
-static int asyncmsgq_before(pa_rtpoll_item *i) {
+static int asyncmsgq_read_before(pa_rtpoll_item *i) {
     pa_assert(i);
 
-    if (pa_asyncmsgq_before_poll(i->userdata) < 0)
+    if (pa_asyncmsgq_read_before_poll(i->userdata) < 0)
         return 1; /* 1 means immediate restart of the loop */
 
     return 0;
 }
 
-static void asyncmsgq_after(pa_rtpoll_item *i) {
+static void asyncmsgq_read_after(pa_rtpoll_item *i) {
     pa_assert(i);
 
     pa_assert((i->pollfd[0].revents & ~POLLIN) == 0);
-    pa_asyncmsgq_after_poll(i->userdata);
+    pa_asyncmsgq_read_after_poll(i->userdata);
 }
 
-static int asyncmsgq_work(pa_rtpoll_item *i) {
+static int asyncmsgq_read_work(pa_rtpoll_item *i) {
     pa_msgobject *object;
     int code;
     void *data;
@@ -703,7 +703,7 @@ static int asyncmsgq_work(pa_rtpoll_item *i) {
     return 0;
 }
 
-pa_rtpoll_item *pa_rtpoll_item_new_asyncmsgq(pa_rtpoll *p, pa_rtpoll_priority_t prio, pa_asyncmsgq *q) {
+pa_rtpoll_item *pa_rtpoll_item_new_asyncmsgq_read(pa_rtpoll *p, pa_rtpoll_priority_t prio, pa_asyncmsgq *q) {
     pa_rtpoll_item *i;
     struct pollfd *pollfd;
 
@@ -713,12 +713,47 @@ pa_rtpoll_item *pa_rtpoll_item_new_asyncmsgq(pa_rtpoll *p, pa_rtpoll_priority_t
     i = pa_rtpoll_item_new(p, prio, 1);
 
     pollfd = pa_rtpoll_item_get_pollfd(i, NULL);
-    pollfd->fd = pa_asyncmsgq_get_fd(q);
+    pollfd->fd = pa_asyncmsgq_read_fd(q);
     pollfd->events = POLLIN;
 
-    i->before_cb = asyncmsgq_before;
-    i->after_cb = asyncmsgq_after;
-    i->work_cb = asyncmsgq_work;
+    i->before_cb = asyncmsgq_read_before;
+    i->after_cb = asyncmsgq_read_after;
+    i->work_cb = asyncmsgq_read_work;
+    i->userdata = q;
+
+    return i;
+}
+
+static int asyncmsgq_write_before(pa_rtpoll_item *i) {
+    pa_assert(i);
+
+    pa_asyncmsgq_write_before_poll(i->userdata);
+    return 0;
+}
+
+static void asyncmsgq_write_after(pa_rtpoll_item *i) {
+    pa_assert(i);
+
+    pa_assert((i->pollfd[0].revents & ~POLLIN) == 0);
+    pa_asyncmsgq_write_after_poll(i->userdata);
+}
+
+pa_rtpoll_item *pa_rtpoll_item_new_asyncmsgq_write(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_write_fd(q);
+    pollfd->events = POLLIN;
+
+    i->before_cb = asyncmsgq_write_before;
+    i->after_cb = asyncmsgq_write_after;
+    i->work_cb = NULL;
     i->userdata = q;
 
     return i;
diff --git a/src/pulsecore/rtpoll.h b/src/pulsecore/rtpoll.h
index f7f96e6..6d72eb5 100644
--- a/src/pulsecore/rtpoll.h
+++ b/src/pulsecore/rtpoll.h
@@ -106,7 +106,8 @@ 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);
+pa_rtpoll_item *pa_rtpoll_item_new_asyncmsgq_read(pa_rtpoll *p, pa_rtpoll_priority_t prio, pa_asyncmsgq *q);
+pa_rtpoll_item *pa_rtpoll_item_new_asyncmsgq_write(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 */
diff --git a/src/pulsecore/thread-mq.c b/src/pulsecore/thread-mq.c
index 9b87942..7e39c57 100644
--- a/src/pulsecore/thread-mq.c
+++ b/src/pulsecore/thread-mq.c
@@ -43,15 +43,15 @@
 
 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) {
+static void asyncmsgq_read_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(pa_asyncmsgq_read_fd(q->outq) == fd);
     pa_assert(events == PA_IO_EVENT_INPUT);
 
     pa_asyncmsgq_ref(aq = q->outq);
-    pa_asyncmsgq_after_poll(aq);
+    pa_asyncmsgq_write_after_poll(aq);
 
     for (;;) {
         pa_msgobject *object;
@@ -68,14 +68,24 @@ static void asyncmsgq_cb(pa_mainloop_api*api, pa_io_event* e, int fd, pa_io_even
             pa_asyncmsgq_done(aq, ret);
         }
 
-        if (pa_asyncmsgq_before_poll(aq) == 0)
+        if (pa_asyncmsgq_read_before_poll(aq) == 0)
             break;
     }
 
     pa_asyncmsgq_unref(aq);
 }
 
-void pa_thread_mq_init(pa_thread_mq *q, pa_mainloop_api *mainloop) {
+static void asyncmsgq_write_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_assert(pa_asyncmsgq_write_fd(q->inq) == fd);
+    pa_assert(events == PA_IO_EVENT_INPUT);
+
+    pa_asyncmsgq_write_after_poll(q->inq);
+    pa_asyncmsgq_write_before_poll(q->inq);
+}
+
+void pa_thread_mq_init(pa_thread_mq *q, pa_mainloop_api *mainloop, pa_rtpoll *rtpoll) {
     pa_assert(q);
     pa_assert(mainloop);
 
@@ -83,15 +93,22 @@ void pa_thread_mq_init(pa_thread_mq *q, pa_mainloop_api *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));
+    pa_assert_se(pa_asyncmsgq_read_before_poll(q->outq) == 0);
+    pa_assert_se(q->read_event = mainloop->io_new(mainloop, pa_asyncmsgq_read_fd(q->outq), PA_IO_EVENT_INPUT, asyncmsgq_read_cb, q));
+
+    pa_asyncmsgq_write_before_poll(q->inq);
+    pa_assert_se(q->write_event = mainloop->io_new(mainloop, pa_asyncmsgq_write_fd(q->inq), PA_IO_EVENT_INPUT, asyncmsgq_write_cb, q));
+
+    pa_rtpoll_item_new_asyncmsgq_read(rtpoll, PA_RTPOLL_EARLY, q->inq);
+    pa_rtpoll_item_new_asyncmsgq_write(rtpoll, PA_RTPOLL_LATE, q->outq);
 }
 
 void pa_thread_mq_done(pa_thread_mq *q) {
     pa_assert(q);
 
-    q->mainloop->io_free(q->io_event);
-    q->io_event = NULL;
+    q->mainloop->io_free(q->read_event);
+    q->mainloop->io_free(q->write_event);
+    q->read_event = q->write_event = NULL;
 
     pa_asyncmsgq_unref(q->inq);
     pa_asyncmsgq_unref(q->outq);
diff --git a/src/pulsecore/thread-mq.h b/src/pulsecore/thread-mq.h
index 13b6e01..0ae49f8 100644
--- a/src/pulsecore/thread-mq.h
+++ b/src/pulsecore/thread-mq.h
@@ -26,6 +26,7 @@
 
 #include <pulse/mainloop-api.h>
 #include <pulsecore/asyncmsgq.h>
+#include <pulsecore/rtpoll.h>
 
 /* Two way communication between a thread and a mainloop. Before the
  * thread is started a pa_pthread_mq should be initialized and than
@@ -34,10 +35,10 @@
 typedef struct pa_thread_mq {
     pa_mainloop_api *mainloop;
     pa_asyncmsgq *inq, *outq;
-    pa_io_event *io_event;
+    pa_io_event *read_event, *write_event;
 } pa_thread_mq;
 
-void pa_thread_mq_init(pa_thread_mq *q, pa_mainloop_api *mainloop);
+void pa_thread_mq_init(pa_thread_mq *q, pa_mainloop_api *mainloop, pa_rtpoll *rtpoll);
 void pa_thread_mq_done(pa_thread_mq *q);
 
 /* Install the specified pa_thread_mq object for the current thread */

commit c8fc223fe902e66e99c402a4854bfb4e76c7a0c0
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Apr 23 18:56:19 2008 +0000

    add stripnul to build
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2309 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/Makefile.am b/src/Makefile.am
index 45e3de7..2888208 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -256,7 +256,8 @@ noinst_PROGRAMS = \
 		remix-test \
 		envelope-test \
 		proplist-test \
-		rtstutter
+		rtstutter \
+		stripnul
 
 if HAVE_SIGXCPU
 noinst_PROGRAMS += \
@@ -436,6 +437,11 @@ rtstutter_LDADD = $(AM_LDADD) libpulsecore.la
 rtstutter_CFLAGS = $(AM_CFLAGS) $(LIBOIL_CFLAGS)
 rtstutter_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) $(LIBOIL_LIBS)
 
+stripnul_SOURCES = tests/stripnul.c
+stripnul_LDADD = $(AM_LDADD) libpulsecore.la
+stripnul_CFLAGS = $(AM_CFLAGS) $(LIBOIL_CFLAGS)
+stripnul_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) $(LIBOIL_LIBS)
+
 ###################################
 #         Client library          #
 ###################################

commit 067a68abf9563e18c837a6b824f096ce9e7f1914
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Apr 23 19:22:56 2008 +0000

    fix build for auxiliary modules
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2310 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-combine.c b/src/modules/module-combine.c
index 6f99ae4..e15654f 100644
--- a/src/modules/module-combine.c
+++ b/src/modules/module-combine.c
@@ -384,7 +384,7 @@ static void sink_input_attach_cb(pa_sink_input *i) {
 
     /* 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(
+    o->inq_rtpoll_item = pa_rtpoll_item_new_asyncmsgq_read(
             i->sink->rtpoll,
             PA_RTPOLL_LATE,  /* This one is not that important, since we check for data in _peek() anyway. */
             o->inq);
@@ -584,7 +584,7 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
 
             /* Create pa_asyncmsgq to the sink thread */
 
-            op->outq_rtpoll_item = pa_rtpoll_item_new_asyncmsgq(
+            op->outq_rtpoll_item = pa_rtpoll_item_new_asyncmsgq_read(
                     u->rtpoll,
                     PA_RTPOLL_EARLY-1,  /* This item is very important */
                     op->outq);
@@ -786,7 +786,7 @@ static struct output *output_new(struct userdata *u, pa_sink *sink) {
         /* 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);
 
-        o->outq_rtpoll_item = pa_rtpoll_item_new_asyncmsgq(
+        o->outq_rtpoll_item = pa_rtpoll_item_new_asyncmsgq_read(
                 u->rtpoll,
                 PA_RTPOLL_EARLY-1,  /* This item is very important */
                 o->outq);
@@ -945,8 +945,8 @@ int pa__init(pa_module*m) {
     u->master = NULL;
     u->time_event = NULL;
     u->adjust_time = DEFAULT_ADJUST_TIME;
-    pa_thread_mq_init(&u->thread_mq, m->core->mainloop);
     u->rtpoll = pa_rtpoll_new();
+    pa_thread_mq_init(&u->thread_mq, m->core->mainloop, u->rtpoll);
     u->thread = NULL;
     u->resample_method = resample_method;
     u->outputs = pa_idxset_new(NULL, NULL);
@@ -955,7 +955,6 @@ int pa__init(pa_module*m) {
     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");
diff --git a/src/modules/module-esound-sink.c b/src/modules/module-esound-sink.c
index 51c76dc..9a4ba58 100644
--- a/src/modules/module-esound-sink.c
+++ b/src/modules/module-esound-sink.c
@@ -538,9 +538,8 @@ int pa__init(pa_module*m) {
     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);
+    pa_thread_mq_init(&u->thread_mq, m->core->mainloop, u->rtpoll);
     u->rtpoll_item = NULL;
 
     u->format =
diff --git a/src/modules/module-jack-sink.c b/src/modules/module-jack-sink.c
index 80a14a6..f97041a 100644
--- a/src/modules/module-jack-sink.c
+++ b/src/modules/module-jack-sink.c
@@ -301,9 +301,8 @@ int pa__init(pa_module*m) {
     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);
+    pa_thread_mq_init(&u->thread_mq, m->core->mainloop, u->rtpoll);
 
     /* The queue linking the JACK thread and our RT thread */
     u->jack_msgq = pa_asyncmsgq_new(0);
@@ -313,7 +312,7 @@ int pa__init(pa_module*m) {
      * 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);
+    u->rtpoll_item = pa_rtpoll_item_new_asyncmsgq_read(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.");
diff --git a/src/modules/module-jack-source.c b/src/modules/module-jack-source.c
index a687563..18ffa55 100644
--- a/src/modules/module-jack-source.c
+++ b/src/modules/module-jack-source.c
@@ -279,12 +279,11 @@ int pa__init(pa_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);
+    pa_thread_mq_init(&u->thread_mq, m->core->mainloop, u->rtpoll);
 
     u->jack_msgq = pa_asyncmsgq_new(0);
-    u->rtpoll_item = pa_rtpoll_item_new_asyncmsgq(u->rtpoll, PA_RTPOLL_EARLY-1, u->jack_msgq);
+    u->rtpoll_item = pa_rtpoll_item_new_asyncmsgq_read(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.");
diff --git a/src/modules/module-ladspa-sink.c b/src/modules/module-ladspa-sink.c
index 14f14b1..aa398a2 100644
--- a/src/modules/module-ladspa-sink.c
+++ b/src/modules/module-ladspa-sink.c
@@ -217,7 +217,7 @@ static int sink_input_pop_cb(pa_sink_input *i, size_t nbytes, pa_memchunk *chunk
 }
 
 /* Called from I/O thread context */
-static void sink_input_rewind_cb(pa_sink_input *i, size_t nbytes) {
+static void sink_input_process_rewind_cb(pa_sink_input *i, size_t nbytes) {
     struct userdata *u;
 
     pa_sink_input_assert_ref(i);
@@ -228,7 +228,7 @@ static void sink_input_rewind_cb(pa_sink_input *i, size_t nbytes) {
 }
 
 /* Called from I/O thread context */
-static void sink_input_set_max_rewind_cb(pa_sink_input *i, size_t nbytes) {
+static void sink_input_update_max_rewind_cb(pa_sink_input *i, size_t nbytes) {
     struct userdata *u;
 
     pa_sink_input_assert_ref(i);
@@ -650,8 +650,8 @@ int pa__init(pa_module*m) {
 
     u->sink_input->parent.process_msg = sink_input_process_msg;
     u->sink_input->pop = sink_input_pop_cb;
-    u->sink_input->rewind = sink_input_rewind_cb;
-    u->sink_input->set_max_rewind = sink_input_set_max_rewind_cb;
+    u->sink_input->process_rewind = sink_input_process_rewind_cb;
+    u->sink_input->update_max_rewind = sink_input_update_max_rewind_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;
diff --git a/src/modules/module-oss.c b/src/modules/module-oss.c
index 149c70d..f07d82a 100644
--- a/src/modules/module-oss.c
+++ b/src/modules/module-oss.c
@@ -1234,9 +1234,8 @@ int pa__init(pa_module*m) {
     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);
+    pa_thread_mq_init(&u->thread_mq, m->core->mainloop, u->rtpoll);
     u->rtpoll_item = NULL;
     build_pollfd(u);
 
diff --git a/src/modules/module-remap-sink.c b/src/modules/module-remap-sink.c
index 3f70ee1..6a16321 100644
--- a/src/modules/module-remap-sink.c
+++ b/src/modules/module-remap-sink.c
@@ -143,8 +143,6 @@ static int sink_input_process_msg(pa_msgobject *o, int code, void *data, int64_t
     return pa_sink_input_process_msg(o, code, data, offset, chunk);
 }
 
-static void sink_input_rewind_cb(pa_sink_input *i, size_t nbytes);
-
 /* Called from I/O thread context */
 static int sink_input_pop_cb(pa_sink_input *i, size_t nbytes, pa_memchunk *chunk) {
     struct userdata *u;
@@ -159,7 +157,7 @@ static int sink_input_pop_cb(pa_sink_input *i, size_t nbytes, pa_memchunk *chunk
 }
 
 /* Called from I/O thread context */
-static void sink_input_rewind_cb(pa_sink_input *i, size_t nbytes) {
+static void sink_input_process_rewind_cb(pa_sink_input *i, size_t nbytes) {
     struct userdata *u;
 
     pa_sink_input_assert_ref(i);
@@ -170,7 +168,7 @@ static void sink_input_rewind_cb(pa_sink_input *i, size_t nbytes) {
 }
 
 /* Called from I/O thread context */
-static void sink_input_set_max_rewind_cb(pa_sink_input *i, size_t nbytes) {
+static void sink_input_update_max_rewind_cb(pa_sink_input *i, size_t nbytes) {
     struct userdata *u;
 
     pa_sink_input_assert_ref(i);
@@ -321,8 +319,8 @@ int pa__init(pa_module*m) {
 
     u->sink_input->parent.process_msg = sink_input_process_msg;
     u->sink_input->pop = sink_input_pop_cb;
-    u->sink_input->rewind = sink_input_rewind_cb;
-    u->sink_input->set_max_rewind = sink_input_set_max_rewind_cb;
+    u->sink_input->process_rewind = sink_input_process_rewind_cb;
+    u->sink_input->update_max_rewind = sink_input_update_max_rewind_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;
diff --git a/src/modules/module-tunnel.c b/src/modules/module-tunnel.c
index 5483be3..74d5a82 100644
--- a/src/modules/module-tunnel.c
+++ b/src/modules/module-tunnel.c
@@ -1329,9 +1329,8 @@ int pa__init(pa_module*m) {
     u->auth_cookie_in_property = FALSE;
     u->time_event = NULL;
 
-    pa_thread_mq_init(&u->thread_mq, m->core->mainloop);
     u->rtpoll = pa_rtpoll_new();
-    pa_rtpoll_item_new_asyncmsgq(u->rtpoll, PA_RTPOLL_EARLY, u->thread_mq.inq);
+    pa_thread_mq_init(&u->thread_mq, m->core->mainloop, u->rtpoll);
 
     if (load_key(u, pa_modargs_get_value(ma, "cookie", NULL)) < 0)
         goto fail;

commit 5353cf45f5a35b33076cc440cc8a8ba587418315
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Apr 23 19:55:04 2008 +0000

    fix size of requested_latency
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2311 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/sink.h b/src/pulsecore/sink.h
index 97491f4..7bc4a70 100644
--- a/src/pulsecore/sink.h
+++ b/src/pulsecore/sink.h
@@ -112,7 +112,7 @@ struct pa_sink {
         pa_bool_t soft_muted;
 
         pa_bool_t requested_latency_valid;
-        size_t requested_latency;
+        pa_usec_t requested_latency;
 
         /* The number of bytes we need keep around to be able to satisfy
          * every DMA buffer rewrite */

commit caf742a0764589cd77bf3b28e4b80c761d83e3bb
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Apr 23 23:22:51 2008 +0000

    define minimal and maximal wakeup/sleep times; check for underrun condition only once during buffer fillup
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2312 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-alsa-sink.c b/src/modules/module-alsa-sink.c
index bc95e6c..5cc27f1 100644
--- a/src/modules/module-alsa-sink.c
+++ b/src/modules/module-alsa-sink.c
@@ -94,6 +94,8 @@ static const char* const valid_modargs[] = {
 #define DEFAULT_DEVICE "default"
 #define DEFAULT_TSCHED_BUFFER_USEC (5*PA_USEC_PER_SEC)           /* 5s */
 #define DEFAULT_TSCHED_WATERMARK_USEC (20*PA_USEC_PER_MSEC)       /* 20ms */
+#define TSCHED_MIN_SLEEP_USEC (3*PA_USEC_PER_MSEC)        /* 3ms */
+#define TSCHED_MIN_WAKEUP_USEC (3*PA_USEC_PER_MSEC)        /* 3ms */
 
 struct userdata {
     pa_core *core;
@@ -121,7 +123,7 @@ struct userdata {
 
     pa_bool_t use_mmap, use_tsched;
 
-    pa_bool_t first;
+    pa_bool_t first, after_rewind;
 
     pa_rtpoll_item *alsa_rtpoll_item;
 
@@ -135,12 +137,29 @@ struct userdata {
 
 static void fix_tsched_watermark(struct userdata *u) {
     size_t max_use;
+    size_t min_sleep, min_wakeup;
     pa_assert(u);
 
     max_use = u->hwbuf_size - u->hwbuf_unused_frames * u->frame_size;
 
-    if (u->tsched_watermark >= max_use-u->frame_size)
-        u->tsched_watermark = max_use-u->frame_size;
+    min_sleep = pa_usec_to_bytes(TSCHED_MIN_SLEEP_USEC, &u->sink->sample_spec);
+    min_wakeup = pa_usec_to_bytes(TSCHED_MIN_WAKEUP_USEC, &u->sink->sample_spec);
+
+    if (min_sleep > max_use/2)
+        min_sleep = pa_frame_align(max_use/2, &u->sink->sample_spec);
+    if (min_sleep < u->frame_size)
+        min_sleep = u->frame_size;
+
+    if (min_wakeup > max_use/2)
+        min_wakeup = pa_frame_align(max_use/2, &u->sink->sample_spec);
+    if (min_wakeup < u->frame_size)
+        min_wakeup = u->frame_size;
+
+    if (u->tsched_watermark > max_use-min_sleep)
+        u->tsched_watermark = max_use-min_sleep;
+
+    if (u->tsched_watermark < min_wakeup)
+        u->tsched_watermark = min_wakeup;
 }
 
 static int try_recover(struct userdata *u, const char *call, int err) {
@@ -170,7 +189,7 @@ static int try_recover(struct userdata *u, const char *call, int err) {
 static void check_left_to_play(struct userdata *u, snd_pcm_sframes_t n) {
     size_t left_to_play;
 
-    if (u->first)
+    if (u->first || u->after_rewind)
         return;
 
     if (n*u->frame_size < u->hwbuf_size)
@@ -198,6 +217,7 @@ static void check_left_to_play(struct userdata *u, snd_pcm_sframes_t n) {
 
 static int mmap_write(struct userdata *u) {
     int work_done = 0;
+    pa_bool_t checked_left_to_play = FALSE;
 
     pa_assert(u);
     pa_sink_assert_ref(u->sink);
@@ -225,7 +245,10 @@ static int mmap_write(struct userdata *u) {
             return r;
         }
 
-        check_left_to_play(u, n);
+        if (!checked_left_to_play) {
+            check_left_to_play(u, n);
+            checked_left_to_play = TRUE;
+        }
 
         /* We only use part of the buffer that matches our
          * dynamically requested latency */
@@ -294,6 +317,7 @@ static int mmap_write(struct userdata *u) {
 
 static int unix_write(struct userdata *u) {
     int work_done = 0;
+    pa_bool_t checked_left_to_play = FALSE;
 
     pa_assert(u);
     pa_sink_assert_ref(u->sink);
@@ -315,7 +339,10 @@ static int unix_write(struct userdata *u) {
             return r;
         }
 
-        check_left_to_play(u, n);
+        if (!checked_left_to_play) {
+            check_left_to_play(u, n);
+            checked_left_to_play = TRUE;
+        }
 
         if (PA_UNLIKELY(n <= u->hwbuf_unused_frames))
             return work_done;
@@ -862,6 +889,8 @@ static int process_rewind(struct userdata *u) {
             u->frame_index -= out_frames;
             pa_log_debug("Rewound %lu bytes.", (unsigned long) rewind_nbytes);
             pa_sink_process_rewind(u->sink, rewind_nbytes);
+
+            u->after_rewind = TRUE;
         }
     } else
         pa_log_debug("Mhmm, actually there is nothing to rewind.");
@@ -938,6 +967,7 @@ static void thread_func(void *userdata) {
             }
 
             u->first = FALSE;
+            u->after_rewind = FALSE;
 
         } else if (u->use_tsched)
 
@@ -1071,6 +1101,7 @@ int pa__init(pa_module*m) {
     u->use_mmap = use_mmap;
     u->use_tsched = use_tsched;
     u->first = TRUE;
+    u->after_rewind = FALSE;
     u->rtpoll = pa_rtpoll_new();
     pa_thread_mq_init(&u->thread_mq, m->core->mainloop, u->rtpoll);
     u->alsa_rtpoll_item = NULL;
diff --git a/src/modules/module-alsa-source.c b/src/modules/module-alsa-source.c
index 3999ada..3c6b8db 100644
--- a/src/modules/module-alsa-source.c
+++ b/src/modules/module-alsa-source.c
@@ -95,6 +95,8 @@ static const char* const valid_modargs[] = {
 #define DEFAULT_DEVICE "default"
 #define DEFAULT_TSCHED_BUFFER_USEC (5*PA_USEC_PER_SEC)
 #define DEFAULT_TSCHED_WATERMARK_USEC (20*PA_USEC_PER_MSEC)
+#define TSCHED_MIN_SLEEP_USEC (3*PA_USEC_PER_MSEC)        /* 3ms */
+#define TSCHED_MIN_WAKEUP_USEC (3*PA_USEC_PER_MSEC)        /* 3ms */
 
 struct userdata {
     pa_core *core;
@@ -133,12 +135,29 @@ struct userdata {
 
 static void fix_tsched_watermark(struct userdata *u) {
     size_t max_use;
+    size_t min_sleep, min_wakeup;
     pa_assert(u);
 
     max_use = u->hwbuf_size - u->hwbuf_unused_frames * u->frame_size;
 
-    if (u->tsched_watermark >= max_use-u->frame_size)
-        u->tsched_watermark = max_use-u->frame_size;
+    min_sleep = pa_usec_to_bytes(TSCHED_MIN_SLEEP_USEC, &u->source->sample_spec);
+    min_wakeup = pa_usec_to_bytes(TSCHED_MIN_WAKEUP_USEC, &u->source->sample_spec);
+
+    if (min_sleep > max_use/2)
+        min_sleep = pa_frame_align(max_use/2, &u->source->sample_spec);
+    if (min_sleep < u->frame_size)
+        min_sleep = u->frame_size;
+
+    if (min_wakeup > max_use/2)
+        min_wakeup = pa_frame_align(max_use/2, &u->source->sample_spec);
+    if (min_wakeup < u->frame_size)
+        min_wakeup = u->frame_size;
+
+    if (u->tsched_watermark > max_use-min_sleep)
+        u->tsched_watermark = max_use-min_sleep;
+
+    if (u->tsched_watermark < min_wakeup)
+        u->tsched_watermark = min_wakeup;
 }
 
 static int try_recover(struct userdata *u, const char *call, int err) {
@@ -193,6 +212,7 @@ static void check_left_to_record(struct userdata *u, snd_pcm_sframes_t n) {
 
 static int mmap_read(struct userdata *u) {
     int work_done = 0;
+    pa_bool_t checked_left_to_record = FALSE;
 
     pa_assert(u);
     pa_source_assert_ref(u->source);
@@ -217,7 +237,10 @@ static int mmap_read(struct userdata *u) {
             return r;
         }
 
-        check_left_to_record(u, n);
+        if (checked_left_to_record) {
+            check_left_to_record(u, n);
+            checked_left_to_record = TRUE;
+        }
 
         if (PA_UNLIKELY(n <= 0))
             return work_done;
@@ -280,6 +303,7 @@ static int mmap_read(struct userdata *u) {
 
 static int unix_read(struct userdata *u) {
     int work_done = 0;
+    pa_bool_t checked_left_to_record = FALSE;
 
     pa_assert(u);
     pa_source_assert_ref(u->source);
@@ -302,7 +326,10 @@ static int unix_read(struct userdata *u) {
             return r;
         }
 
-        check_left_to_record(u, n);
+        if (checked_left_to_record) {
+            check_left_to_record(u, n);
+            checked_left_to_record = TRUE;
+        }
 
         if (PA_UNLIKELY(n <= 0))
             return work_done;

commit b12b8ee16071305cc0686a0d8130f958742a5078
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu May 1 18:56:14 2008 +0000

    save errno before calling free()
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2313 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulse/xmalloc.c b/src/pulse/xmalloc.c
index 2849097..a64761b 100644
--- a/src/pulse/xmalloc.c
+++ b/src/pulse/xmalloc.c
@@ -29,6 +29,7 @@
 #include <signal.h>
 #include <unistd.h>
 #include <string.h>
+#include <errno.h>
 
 #include <pulse/gccmacro.h>
 #include <pulsecore/core-util.h>
@@ -123,8 +124,12 @@ char *pa_xstrndup(const char *s, size_t l) {
 }
 
 void pa_xfree(void *p) {
+    int saved_errno;
+
     if (!p)
         return;
 
+    saved_errno = errno;
     free(p);
+    errno = saved_errno;
 }

commit 06a05bc66c46550dd550a8960e421b5e9cb1b2bb
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu May 1 18:57:18 2008 +0000

    a bit of pa_bool_t'ization
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2314 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/daemon/cpulimit.c b/src/daemon/cpulimit.c
index 620a93a..579b91e 100644
--- a/src/daemon/cpulimit.c
+++ b/src/daemon/cpulimit.c
@@ -82,7 +82,7 @@ static pa_io_event *io_event = NULL;
 static struct sigaction sigaction_prev;
 
 /* Nonzero after pa_cpu_limit_init() */
-static int installed = 0;
+static pa_bool_t installed = FALSE;
 
 /* The current state of operation */
 static enum  {
@@ -210,7 +210,7 @@ int pa_cpu_limit_init(pa_mainloop_api *m) {
         return -1;
     }
 
-    installed = 1;
+    installed = TRUE;
 
     reset_cpu_time(CPUTIME_INTERVAL_SOFT);
 
@@ -231,7 +231,7 @@ void pa_cpu_limit_done(void) {
 
     if (installed) {
         pa_assert_se(sigaction(SIGXCPU, &sigaction_prev, NULL) >= 0);
-        installed = 0;
+        installed = FALSE;
     }
 }
 

commit 563f4b63cd37794b72af4601796edb5b6f5f2455
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu May 1 18:59:25 2008 +0000

    make check for $DISPLAY=="" more readable, pa_bool_tization
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2315 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulse/client-conf-x11.c b/src/pulse/client-conf-x11.c
index e240ba8..49df4b6 100644
--- a/src/pulse/client-conf-x11.c
+++ b/src/pulse/client-conf-x11.c
@@ -46,7 +46,10 @@ int pa_client_conf_from_x11(pa_client_conf *c, const char *dname) {
 
     pa_assert(c);
 
-    if (!dname && (!(dname = getenv("DISPLAY")) || *dname == '\0'))
+    if (!dname && !(dname = getenv("DISPLAY")))
+        goto finish;
+
+    if (*dname == 0)
         goto finish;
 
     if (!(d = XOpenDisplay(dname))) {
@@ -80,7 +83,7 @@ int pa_client_conf_from_x11(pa_client_conf *c, const char *dname) {
         pa_assert(sizeof(cookie) == sizeof(c->cookie));
         memcpy(c->cookie, cookie, sizeof(cookie));
 
-        c->cookie_valid = 1;
+        c->cookie_valid = TRUE;
 
         pa_xfree(c->cookie_file);
         c->cookie_file = NULL;

commit f49df7a3b09957585d4227390d4ba0929e7e29f2
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu May 1 19:04:42 2008 +0000

    * Increase history set to 64 to simplify reduction of indexes
    * Decrease memory consumption a bit by using bitfields for some bools
    * Rework reduction code
    * Drop an unnessacary counter
    * Before adding a new entry to the history, try to figure out if we already have an existing entry with the same x value and replace that. This fixes a division by zero
    * Fix up input x for all functions, according to the time offset
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2316 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/time-smoother.c b/src/pulsecore/time-smoother.c
index b3f8edc..97e32b7 100644
--- a/src/pulsecore/time-smoother.c
+++ b/src/pulsecore/time-smoother.c
@@ -34,7 +34,7 @@
 
 #include "time-smoother.h"
 
-#define HISTORY_MAX 50
+#define HISTORY_MAX 64
 
 /*
  * Implementation of a time smoothing algorithm to synchronize remote
@@ -61,7 +61,6 @@
 
 struct pa_smoother {
     pa_usec_t adjust_time, history_time;
-    pa_bool_t monotonic;
 
     pa_usec_t time_offset;
 
@@ -82,7 +81,9 @@ struct pa_smoother {
     double a, b, c;
     pa_bool_t abc_valid;
 
-    pa_bool_t paused;
+    pa_bool_t monotonic:1;
+    pa_bool_t paused:1;
+
     pa_usec_t pause_time;
 };
 
@@ -122,39 +123,58 @@ void pa_smoother_free(pa_smoother* s) {
     pa_xfree(s);
 }
 
+#define REDUCE(x)                               \
+    do {                                        \
+        x = (x) % HISTORY_MAX;                  \
+    } while(FALSE)
+
+#define REDUCE_INC(x)                           \
+    do {                                        \
+        x = ((x)+1) % HISTORY_MAX;              \
+    } while(FALSE)
+
+
 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 */
+    /* 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--) {
+    while (s->n_history > 2) {
 
-        if (s->history_x[s->history_idx] + s->history_time >= x) {
+        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;
+        REDUCE_INC(s->history_idx);
 
         s->n_history --;
     }
 }
 
 static void add_to_history(pa_smoother *s, pa_usec_t x, pa_usec_t y) {
-    unsigned j;
+    unsigned j, i;
     pa_assert(s);
 
+    /* First try to update an existing history entry */
+    i = s->history_idx;
+    for (j = s->n_history; j > 0; j--) {
+
+        if (s->history_x[i] == x) {
+            s->history_y[i] = y;
+            return;
+        }
+
+        REDUCE_INC(i);
+    }
+
+    /* Drop old entries */
     drop_old(s, x);
 
     /* Calculate position for new entry */
     j = s->history_idx + s->n_history;
-    while (j >= HISTORY_MAX)
-        j -= HISTORY_MAX;
+    REDUCE(j);
 
     /* Fill in entry */
     s->history_x[j] = x;
@@ -166,6 +186,7 @@ static void add_to_history(pa_smoother *s, pa_usec_t x, pa_usec_t y) {
     /* 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;
+        REDUCE(s->history_idx);
         s->n_history = HISTORY_MAX;
     }
 }
@@ -185,9 +206,7 @@ static double avg_gradient(pa_smoother *s, pa_usec_t x) {
         ay += s->history_y[i];
         c++;
 
-        i++;
-        while (i >= HISTORY_MAX)
-            i -= HISTORY_MAX;
+        REDUCE_INC(i);
     }
 
     /* Too few measurements, assume gradient of 1 */
@@ -210,14 +229,12 @@ static double avg_gradient(pa_smoother *s, pa_usec_t x) {
         k += dx*dy;
         t += dx*dx;
 
-        i++;
-        while (i >= HISTORY_MAX)
-            i -= HISTORY_MAX;
+        REDUCE_INC(i);
     }
 
     r = (double) k / t;
 
-    return s->monotonic && r < 0 ? 0 : r;
+    return (s->monotonic && r < 0) ? 0 : r;
 }
 
 static void estimate(pa_smoother *s, pa_usec_t x, pa_usec_t *y, double *deriv) {
@@ -305,14 +322,12 @@ void pa_smoother_put(pa_smoother *s, pa_usec_t x, pa_usec_t y) {
     double nde;
 
     pa_assert(s);
-    pa_assert(x >= s->time_offset);
 
     /* Fix up x value */
     if (s->paused)
         x = s->pause_time;
 
-    pa_assert(x >= s->time_offset);
-    x -= s->time_offset;
+    x = PA_LIKELY(x >= s->time_offset) ? x - s->time_offset : 0;
 
     pa_assert(x >= s->ex);
 
@@ -340,15 +355,12 @@ 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;
 
-    pa_assert(x >= s->time_offset);
-    x -= s->time_offset;
-
+    x = PA_LIKELY(x >= s->time_offset) ? x - s->time_offset : 0;
     pa_assert(x >= s->ex);
 
     estimate(s, x, &y, NULL);
@@ -397,14 +409,12 @@ pa_usec_t pa_smoother_translate(pa_smoother *s, pa_usec_t x, pa_usec_t y_delay)
     double nde;
 
     pa_assert(s);
-    pa_assert(x >= s->time_offset);
 
     /* Fix up x value */
     if (s->paused)
         x = s->pause_time;
 
-    pa_assert(x >= s->time_offset);
-    x -= s->time_offset;
+    x = PA_LIKELY(x >= s->time_offset) ? x - s->time_offset : 0;
 
     pa_assert(x >= s->ex);
 

commit 264385aae4683a47b15aa37a3949796be72870d1
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu May 1 19:06:15 2008 +0000

    strip CRLF line breaks from read CLI commands. This should fix the cli interface for people accessing it via telnet.
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2317 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/ioline.c b/src/pulsecore/ioline.c
index 860a651..6d11e4f 100644
--- a/src/pulsecore/ioline.c
+++ b/src/pulsecore/ioline.c
@@ -247,7 +247,7 @@ static void scan_for_lines(pa_ioline *l, size_t skip) {
             l->rbuf_index = 0;
 
         if (l->callback)
-            l->callback(l, p, l->userdata);
+            l->callback(l, pa_strip_nl(p), l->userdata);
 
         skip = 0;
     }

commit 9dd8f6ceb7cce6576eef2f3278cea16ef76344b9
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu May 1 19:09:03 2008 +0000

    add new function pa_sample_clamp()
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2318 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/sample-util.c b/src/pulsecore/sample-util.c
index bf1f7c2..654c3b9 100644
--- a/src/pulsecore/sample-util.c
+++ b/src/pulsecore/sample-util.c
@@ -1000,3 +1000,34 @@ pa_memchunk* pa_silence_memchunk_get(pa_silence_cache *cache, pa_mempool *pool,
 
     return ret;
 }
+
+void pa_sample_clamp(pa_sample_format_t format, void *dst, size_t dstr, const void *src, size_t sstr, unsigned n) {
+
+    const float *s;
+    float *d;
+
+    if (format != PA_SAMPLE_FLOAT32BE && format != PA_SAMPLE_FLOAT32LE)
+        return;
+
+    s = src;
+    d = dst;
+
+    if (format == PA_SAMPLE_FLOAT32NE) {
+        for (; n > 0; n--) {
+            *d = PA_CLAMP_UNLIKELY(*s, -1.0, 1.0);
+
+            s = (const float*) ((const uint8_t*) s + sstr);
+            d = (float*) ((uint8_t*) d + dstr);
+        }
+    } else
+        for (; n > 0; n--) {
+            float f;
+
+            f = PA_FLOAT32_SWAP(*s);
+            f = PA_CLAMP_UNLIKELY(f, -1.0, 1.0);
+            *d = PA_FLOAT32_SWAP(f);
+
+            s = (const float*) ((const uint8_t*) s + sstr);
+            d = (float*) ((uint8_t*) d + dstr);
+        }
+}
diff --git a/src/pulsecore/sample-util.h b/src/pulsecore/sample-util.h
index 45f0088..59b4c63 100644
--- a/src/pulsecore/sample-util.h
+++ b/src/pulsecore/sample-util.h
@@ -78,4 +78,6 @@ 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);
 
+void pa_sample_clamp(pa_sample_format_t format, void *dst, size_t dstr, const void *src, size_t sstr, unsigned n);
+
 #endif

commit b70edf77dad853ebed66e3c07d16bc2c2548e294
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu May 1 19:13:53 2008 +0000

    port pa_sample_clamp() to liboil
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2319 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/sample-util.c b/src/pulsecore/sample-util.c
index 654c3b9..d295742 100644
--- a/src/pulsecore/sample-util.c
+++ b/src/pulsecore/sample-util.c
@@ -1013,12 +1013,8 @@ void pa_sample_clamp(pa_sample_format_t format, void *dst, size_t dstr, const vo
     d = dst;
 
     if (format == PA_SAMPLE_FLOAT32NE) {
-        for (; n > 0; n--) {
-            *d = PA_CLAMP_UNLIKELY(*s, -1.0, 1.0);
-
-            s = (const float*) ((const uint8_t*) s + sstr);
-            d = (float*) ((uint8_t*) d + dstr);
-        }
+        const static float minus_one = -1.0, plus_one = 1.0;
+        oil_clip_f32(dst, dstr, src, sstr, n, &minus_one, &plus_one);
     } else
         for (; n > 0; n--) {
             float f;

commit 18ad6f845eee212f38053ee0ff0f066f20da3a97
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu May 1 19:15:08 2008 +0000

    don't allow overwriting of callback pointers when we're already dead
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2320 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulse/subscribe.c b/src/pulse/subscribe.c
index db25f3c..0c5686b 100644
--- a/src/pulse/subscribe.c
+++ b/src/pulse/subscribe.c
@@ -88,6 +88,9 @@ void pa_context_set_subscribe_callback(pa_context *c, pa_context_subscribe_cb_t
     pa_assert(c);
     pa_assert(PA_REFCNT_VALUE(c) >= 1);
 
+    if (c->state == PA_CONTEXT_TERMINATED || c->state == PA_CONTEXT_FAILED)
+        return;
+
     c->subscribe_callback = cb;
     c->subscribe_userdata = userdata;
 }

commit 4f99c431d0122ba1256b5f8793adfa86d21e17ce
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu May 1 19:15:49 2008 +0000

    check for $PULSE_INTERNAL before enabling padsp
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2321 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/utils/padsp.c b/src/utils/padsp.c
index 6ab022e..e43a0de 100644
--- a/src/utils/padsp.c
+++ b/src/utils/padsp.c
@@ -302,7 +302,6 @@ static int padsp_disabled(void) {
     if (!sym_resolved) {
         sym = (int*) dlsym(RTLD_DEFAULT, "__padsp_disabled__");
         sym_resolved = 1;
-
     }
     pthread_mutex_unlock(&func_mutex);
 
@@ -316,7 +315,7 @@ static int dsp_cloak_enable(void) {
     if (padsp_disabled() & 1)
         return 0;
 
-    if (getenv("PADSP_NO_DSP"))
+    if (getenv("PADSP_NO_DSP") || getenv("PULSE_INTERNAL"))
         return 0;
 
     return 1;
@@ -326,7 +325,7 @@ static int sndstat_cloak_enable(void) {
     if (padsp_disabled() & 2)
         return 0;
 
-    if (getenv("PADSP_NO_SNDSTAT"))
+    if (getenv("PADSP_NO_SNDSTAT") || getenv("PULSE_INTERNAL"))
         return 0;
 
     return 1;
@@ -336,7 +335,7 @@ static int mixer_cloak_enable(void) {
     if (padsp_disabled() & 4)
         return 0;
 
-    if (getenv("PADSP_NO_MIXER"))
+    if (getenv("PADSP_NO_MIXER") || getenv("PULSE_INTERNAL"))
         return 0;
 
     return 1;

commit b93ea1840ccb49f1ee020186cef6f8a147343b34
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu May 1 19:16:25 2008 +0000

    minor reformat
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2322 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/memblock.c b/src/pulsecore/memblock.c
index 4653779..33b3874 100644
--- a/src/pulsecore/memblock.c
+++ b/src/pulsecore/memblock.c
@@ -59,7 +59,9 @@ struct pa_memblock {
     pa_mempool *pool;
 
     pa_memblock_type_t type;
-    pa_bool_t read_only:1, is_silence:1;
+
+    pa_bool_t read_only:1;
+    pa_bool_t is_silence:1;
 
     pa_atomic_ptr_t data;
     size_t length;

commit 58168711171d823833a8d699090a8238e24ebea1
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu May 1 19:16:55 2008 +0000

    save and restore errno in log functions
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2323 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/log.c b/src/pulsecore/log.c
index c824e84..a898578 100644
--- a/src/pulsecore/log.c
+++ b/src/pulsecore/log.c
@@ -30,6 +30,7 @@
 #include <stdio.h>
 #include <unistd.h>
 #include <string.h>
+#include <errno.h>
 
 #ifdef HAVE_SYSLOG_H
 #include <syslog.h>
@@ -109,6 +110,7 @@ void pa_log_levelv_meta(
 
     const char *e;
     char *text, *t, *n, *location;
+    int saved_errno = errno;
 
     pa_assert(level < PA_LOG_LEVEL_MAX);
     pa_assert(format);
@@ -116,8 +118,10 @@ void pa_log_levelv_meta(
     if ((e = getenv(ENV_LOGLEVEL)))
         maximal_level = atoi(e);
 
-    if (level > maximal_level)
+    if (level > maximal_level) {
+        errno = saved_errno;
         return;
+    }
 
     text = pa_vsprintf_malloc(format, ap);
 
@@ -206,6 +210,8 @@ void pa_log_levelv_meta(
 
     pa_xfree(text);
     pa_xfree(location);
+
+    errno = saved_errno;
 }
 
 void pa_log_level_meta(

commit d7cc1f5a12cb1cf29879443fe1d151c3747aea04
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu May 1 19:17:52 2008 +0000

    change pa_rtpoll_set_timer_absolute() to take a pa_usec_t instead of struct timeval
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2324 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/rtpoll.c b/src/pulsecore/rtpoll.c
index c3e76ca..64fa42a 100644
--- a/src/pulsecore/rtpoll.c
+++ b/src/pulsecore/rtpoll.c
@@ -502,11 +502,10 @@ static void update_timer(pa_rtpoll *p) {
 #endif
 }
 
-void pa_rtpoll_set_timer_absolute(pa_rtpoll *p, const struct timeval *ts) {
+void pa_rtpoll_set_timer_absolute(pa_rtpoll *p, pa_usec_t usec) {
     pa_assert(p);
-    pa_assert(ts);
 
-    p->next_elapse = *ts;
+    pa_timeval_store(&p->next_elapse, usec);
     p->timer_enabled = TRUE;
 
     update_timer(p);
diff --git a/src/pulsecore/rtpoll.h b/src/pulsecore/rtpoll.h
index 6d72eb5..16dadbc 100644
--- a/src/pulsecore/rtpoll.h
+++ b/src/pulsecore/rtpoll.h
@@ -74,7 +74,7 @@ void pa_rtpoll_install(pa_rtpoll *p);
  * 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_absolute(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);
 

commit 414f1d956f98e1921a88061dc118795519168d66
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu May 1 19:22:35 2008 +0000

    install gccmacro.h properly, drop  unused core-def.h file
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2325 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/Makefile.am b/src/Makefile.am
index 2888208..5cc9546 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -131,8 +131,7 @@ pulseaudio_SOURCES = \
 		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
+		daemon/main.c
 
 pulseaudio_CFLAGS = $(AM_CFLAGS) $(LIBOIL_CFLAGS) $(LIBSAMPLERATE_CFLAGS) $(LIBSNDFILE_CFLAGS) $(CAP_CFLAGS) $(LIBOIL_CFLAGS) $(DBUS_CFLAGS)
 pulseaudio_CPPFLAGS = $(AM_CPPFLAGS)
@@ -470,7 +469,8 @@ pulseinclude_HEADERS = \
 		pulse/version.h \
 		pulse/volume.h \
 		pulse/xmalloc.h \
-		pulse/proplist.h
+		pulse/proplist.h \
+		pulse/gccmacro.h
 
 if HAVE_AVAHI
 pulseinclude_HEADERS += \
@@ -529,7 +529,6 @@ libpulse_la_SOURCES += \
 		pulsecore/conf-parser.c pulsecore/conf-parser.h \
 		pulsecore/core-util.c pulsecore/core-util.h \
 		pulsecore/dynarray.c pulsecore/dynarray.h \
-		pulsecore/gccmacro.h \
 		pulsecore/hashmap.c pulsecore/hashmap.h \
 		pulsecore/idxset.c pulsecore/idxset.h \
 		pulsecore/inet_ntop.c pulsecore/inet_ntop.h \
@@ -562,6 +561,8 @@ libpulse_la_SOURCES += \
 		pulsecore/object.c pulsecore/object.h \
 		pulsecore/msgobject.c pulsecore/msgobject.h \
 		pulsecore/once.c pulsecore/once.h \
+		pulsecore/rtclock.c pulsecore/rtclock.h \
+		pulsecore/time-smoother.c pulsecore/time-smoother.h \
 		$(PA_THREAD_OBJS)
 
 if OS_IS_WIN32
@@ -661,7 +662,6 @@ noinst_HEADERS = \
 		pulsecore/cli-text.h \
 		pulsecore/client.h \
 		pulsecore/core.h \
-		pulsecore/core-def.h \
 		pulsecore/core-scache.h \
 		pulsecore/core-subscribe.h \
 		pulsecore/conf-parser.h \
diff --git a/src/pulsecore/core-def.h b/src/pulsecore/core-def.h
deleted file mode 100644
index 4bc0513..0000000
--- a/src/pulsecore/core-def.h
+++ /dev/null
@@ -1,29 +0,0 @@
-#ifndef foocoredefhfoo
-#define foocoredefhfoo
-
-/* $Id$ */
-
-/***
-  This file is part of PulseAudio.
-
-  Copyright 2006 Pierre Ossman <ossman at 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.
-***/
-
-/* FIXME: Remove this shit */
-
-#endif

commit 11559a63863fcbbd8a87b8dd8a790aa0ed6f35d1
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu May 1 19:24:09 2008 +0000

    parse boolean parameters as boolean instead of int wherever applicable. add new function pa_cli_command_execute_file_stream()
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2326 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/cli-command.c b/src/pulsecore/cli-command.c
index 7c85224..b6194f8 100644
--- a/src/pulsecore/cli-command.c
+++ b/src/pulsecore/cli-command.c
@@ -594,7 +594,7 @@ static int pa_cli_command_sink_mute(pa_core *c, pa_tokenizer *t, pa_strbuf *buf,
         return -1;
     }
 
-    if (pa_atoi(m, &mute) < 0) {
+    if ((mute = pa_parse_boolean(m)) < 0) {
         pa_strbuf_puts(buf, "Failed to parse mute switch.\n");
         return -1;
     }
@@ -628,7 +628,7 @@ static int pa_cli_command_source_mute(pa_core *c, pa_tokenizer *t, pa_strbuf *bu
         return -1;
     }
 
-    if (pa_atoi(m, &mute) < 0) {
+    if ((mute = pa_parse_boolean(m)) < 0) {
         pa_strbuf_puts(buf, "Failed to parse mute switch.\n");
         return -1;
     }
@@ -664,11 +664,11 @@ static int pa_cli_command_sink_input_mute(pa_core *c, pa_tokenizer *t, pa_strbuf
     }
 
     if (!(v = pa_tokenizer_get(t, 2))) {
-        pa_strbuf_puts(buf, "You need to specify a volume >= 0. (0 is muted, 0x10000 is normal volume)\n");
+        pa_strbuf_puts(buf, "You need to specify a mute switch setting (0/1).\n");
         return -1;
     }
 
-    if (pa_atoi(v, &mute) < 0) {
+    if ((mute = pa_parse_boolean(v)) < 0) {
         pa_strbuf_puts(buf, "Failed to parse mute switch.\n");
         return -1;
     }
@@ -1125,7 +1125,7 @@ static int pa_cli_command_suspend_sink(pa_core *c, pa_tokenizer *t, pa_strbuf *b
         return -1;
     }
 
-    if (pa_atoi(m, &suspend) < 0) {
+    if ((suspend = pa_parse_boolean(m)) < 0) {
         pa_strbuf_puts(buf, "Failed to parse suspend switch.\n");
         return -1;
     }
@@ -1159,7 +1159,7 @@ static int pa_cli_command_suspend_source(pa_core *c, pa_tokenizer *t, pa_strbuf
         return -1;
     }
 
-    if (pa_atoi(m, &suspend) < 0) {
+    if ((suspend = pa_parse_boolean(m)) < 0) {
         pa_strbuf_puts(buf, "Failed to parse suspend switch.\n");
         return -1;
     }
@@ -1188,7 +1188,7 @@ static int pa_cli_command_suspend(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, p
         return -1;
     }
 
-    if (pa_atoi(m, &suspend) < 0) {
+    if ((suspend = pa_parse_boolean(m)) < 0) {
         pa_strbuf_puts(buf, "Failed to parse suspend switch.\n");
         return -1;
     }
@@ -1252,7 +1252,8 @@ static int pa_cli_command_dump(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_b
         }
 
         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));
+        pa_strbuf_printf(buf, "set-sink-mute %s %s\n", sink->name, pa_yes_no(pa_sink_get_mute(sink)));
+        pa_strbuf_printf(buf, "suspend-sink %s %s\n", sink->name, pa_yes_no(pa_sink_get_state(sink) == PA_SINK_SUSPENDED));
     }
 
     for (source = pa_idxset_first(c->sources, &idx); source; source = pa_idxset_next(c->sources, &idx)) {
@@ -1265,7 +1266,8 @@ static int pa_cli_command_dump(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_b
         }
 
         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));
+        pa_strbuf_printf(buf, "set-source-mute %s %s\n", source->name, pa_yes_no(pa_source_get_mute(source)));
+        pa_strbuf_printf(buf, "suspend-source %s %s\n", source->name, pa_yes_no(pa_source_get_state(source) == PA_SOURCE_SUSPENDED));
     }
 
 
@@ -1440,16 +1442,45 @@ int pa_cli_command_execute_line(pa_core *c, const char *s, pa_strbuf *buf, pa_bo
     return pa_cli_command_execute_line_stateful(c, s, buf, fail, NULL);
 }
 
-int pa_cli_command_execute_file(pa_core *c, const char *fn, pa_strbuf *buf, pa_bool_t *fail) {
+int pa_cli_command_execute_file_stream(pa_core *c, FILE *f, pa_strbuf *buf, pa_bool_t *fail) {
     char line[1024];
-    FILE *f = NULL;
     int ifstate = IFSTATE_NONE;
     int ret = -1;
+    pa_bool_t _fail = TRUE;
+
+    pa_assert(c);
+    pa_assert(f);
+    pa_assert(buf);
+
+    if (!fail)
+        fail = &_fail;
+
+    while (fgets(line, sizeof(line), f)) {
+        pa_strip_nl(line);
+
+        if (pa_cli_command_execute_line_stateful(c, line, buf, fail, &ifstate) < 0 && *fail)
+            goto fail;
+    }
+
+    ret = 0;
+
+fail:
+
+    return ret;
+}
+
+int pa_cli_command_execute_file(pa_core *c, const char *fn, pa_strbuf *buf, pa_bool_t *fail) {
+    FILE *f = NULL;
+    int ret = -1;
+    pa_bool_t _fail = TRUE;
 
     pa_assert(c);
     pa_assert(fn);
     pa_assert(buf);
 
+    if (!fail)
+        fail = &_fail;
+
     if (!(f = fopen(fn, "r"))) {
         pa_strbuf_printf(buf, "open('%s') failed: %s\n", fn, pa_cstrerror(errno));
         if (!*fail)
@@ -1457,13 +1488,7 @@ int pa_cli_command_execute_file(pa_core *c, const char *fn, pa_strbuf *buf, pa_b
         goto fail;
     }
 
-    while (fgets(line, sizeof(line), f)) {
-        char *e = line + strcspn(line, linebreak);
-        *e = 0;
-
-        if (pa_cli_command_execute_line_stateful(c, line, buf, fail, &ifstate) < 0 && *fail)
-            goto fail;
-    }
+    ret = pa_cli_command_execute_file_stream(c, f, buf, fail);
 
     ret = 0;
 
@@ -1477,11 +1502,15 @@ fail:
 int pa_cli_command_execute(pa_core *c, const char *s, pa_strbuf *buf, pa_bool_t *fail) {
     const char *p;
     int ifstate = IFSTATE_NONE;
+    pa_bool_t _fail = TRUE;
 
     pa_assert(c);
     pa_assert(s);
     pa_assert(buf);
 
+    if (!fail)
+        fail = &_fail;
+
     p = s;
     while (*p) {
         size_t l = strcspn(p, linebreak);
diff --git a/src/pulsecore/cli-command.h b/src/pulsecore/cli-command.h
index c90c8e0..2a92344 100644
--- a/src/pulsecore/cli-command.h
+++ b/src/pulsecore/cli-command.h
@@ -36,6 +36,9 @@ int pa_cli_command_execute_line(pa_core *c, const char *s, pa_strbuf *buf, pa_bo
 /* Execute a whole file of CLI commands */
 int pa_cli_command_execute_file(pa_core *c, const char *fn, pa_strbuf *buf, pa_bool_t *fail);
 
+/* Execute a whole file of CLI commands */
+int pa_cli_command_execute_file_stream(pa_core *c, FILE *f, pa_strbuf *buf, pa_bool_t *fail);
+
 /* Split the specified string into lines and run pa_cli_command_execute_line() for each. */
 int pa_cli_command_execute(pa_core *c, const char *s, pa_strbuf *buf, pa_bool_t *fail);
 

commit f3cc178b9233dba9b33210bd35e11e20b6b80f1a
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu May 1 19:25:24 2008 +0000

    some minor updates
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2327 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/tests/interpol-test.c b/src/tests/interpol-test.c
index 85a509d..f894d2f 100644
--- a/src/tests/interpol-test.c
+++ b/src/tests/interpol-test.c
@@ -42,10 +42,9 @@ static pa_context *context = NULL;
 static pa_stream *stream = NULL;
 static pa_mainloop_api *mainloop_api = NULL;
 
-static void stream_write_cb(pa_stream *p, size_t length, void *userdata) {
-
+static void stream_write_cb(pa_stream *p, size_t nbytes, void *userdata) {
     /* Just some silence */
-    pa_stream_write(p, pa_xmalloc0(length), length, pa_xfree, 0, PA_SEEK_RELATIVE);
+    pa_stream_write(p, pa_xmalloc0(nbytes), nbytes, pa_xfree, 0, PA_SEEK_RELATIVE);
 }
 
 /* This is called whenever the context status changes */
@@ -63,7 +62,7 @@ static void context_state_callback(pa_context *c, void *userdata) {
             static const pa_sample_spec ss = {
                 .format = PA_SAMPLE_S16LE,
                 .rate = 44100,
-                .channels = 1
+                .channels = 2
             };
 
             fprintf(stderr, "Connection established.\n");
@@ -112,9 +111,10 @@ int main(int argc, char *argv[]) {
     pa_threaded_mainloop_start(m);
 
     for (k = 0; k < 5000; k++) {
-        int success = 0, changed = 0;
+        pa_bool_t success = FALSE, changed = FALSE;
         pa_usec_t t, rtc;
         struct timeval now, tv;
+        pa_bool_t playing = FALSE;
 
         pa_threaded_mainloop_lock(m);
 
@@ -122,22 +122,26 @@ int main(int argc, char *argv[]) {
             const pa_timing_info *info;
 
             if (pa_stream_get_time(stream, &t) >= 0)
-                success = 1;
+                success = TRUE;
 
-            if ((info = pa_stream_get_timing_info(stream)))
-                if (last_info.tv_usec != info->timestamp.tv_usec || last_info.tv_sec != info->timestamp.tv_sec) {
-                    changed = 1;
+            if ((info = pa_stream_get_timing_info(stream))) {
+                if (memcmp(&last_info, &info->timestamp, sizeof(struct timeval))) {
+                    changed = TRUE;
                     last_info = info->timestamp;
                 }
+                if (info->playing)
+                    playing = TRUE;
+            }
         }
 
         pa_threaded_mainloop_unlock(m);
 
-        if (success) {
-            pa_gettimeofday(&now);
+        pa_gettimeofday(&now);
 
+        if (success) {
             rtc = pa_timeval_diff(&now, &start);
-            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);
+            printf("%i\t%llu\t%llu\t%llu\t%llu\t%u\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, playing);
+            fflush(stdout);
             old_t = t;
             old_rtc = rtc;
         }

commit f94fae3da3e3201afc060d3ae24c96fd9bba56ab
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu May 1 19:26:41 2008 +0000

    move unlinking code to operation_unlink()
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2328 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulse/operation.c b/src/pulse/operation.c
index 5d2da5b..6b5c142 100644
--- a/src/pulse/operation.c
+++ b/src/pulse/operation.c
@@ -77,6 +77,23 @@ void pa_operation_unref(pa_operation *o) {
     }
 }
 
+static void operation_unlink(pa_operation *o) {
+    pa_assert(o);
+
+    if (o->context) {
+        pa_assert(PA_REFCNT_VALUE(o) >= 2);
+
+        PA_LLIST_REMOVE(pa_operation, o->context->operations, o);
+        pa_operation_unref(o);
+
+        o->context = NULL;
+    }
+
+    o->stream = NULL;
+    o->callback = NULL;
+    o->userdata = NULL;
+}
+
 static void operation_set_state(pa_operation *o, pa_operation_state_t st) {
     pa_assert(o);
     pa_assert(PA_REFCNT_VALUE(o) >= 1);
@@ -88,20 +105,8 @@ static void operation_set_state(pa_operation *o, pa_operation_state_t st) {
 
     o->state = st;
 
-    if ((o->state == PA_OPERATION_DONE) || (o->state == PA_OPERATION_CANCELED)) {
-
-        if (o->context) {
-            pa_assert(PA_REFCNT_VALUE(o) >= 2);
-
-            PA_LLIST_REMOVE(pa_operation, o->context->operations, o);
-            pa_operation_unref(o);
-        }
-
-        o->context = NULL;
-        o->stream = NULL;
-        o->callback = NULL;
-        o->userdata = NULL;
-    }
+    if ((o->state == PA_OPERATION_DONE) || (o->state == PA_OPERATION_CANCELED))
+        operation_unlink(o);
 
     pa_operation_unref(o);
 }

commit 52e3628c3edd98ae3402605e7f44a0fc4545dd0a
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu May 1 19:51:05 2008 +0000

    Yes, yet another evil all-in-one commit of intervowen changes. I suck.
    * Drop "state" directory, fold that into "runtime directory"
    * No longer automatically rewind when a new stream connects
    * Rework sound file stream, to cause a rewind on initialisation, shorten _pop() code a bit
    * Fix reference counting of pa_socket_server in the protocol implementations
    * Rework daemon initialization code to be compatible with non-SUID-root setups where RLIMIT_RTPRIO is non-zero
    * Print warning if RT/HP is enabled in the config, but due to missing caps, rlimits, policy we cannot enable it.
    * Fix potential memory leak in pa_open_config_file()
    * Add pa_find_config_file() which works much like pa_open_config_file() but doesn't actually open the config file in question. Just searches for it.
    * Add portable pa_is_path_absolute()
    * Add pa_close_all() and use it on daemon startup to close leaking file descriptors (inspired from what I did for libdaemon)
    * Add pa_unblock_sigs() and use it on daemon startup to unblock all signals (inspired from libdaemon, too)
    * Add pa_reset_sigs() and use it on daemon startup to reset all signal handlers (inspired from libdaemon as well)
    * Implement pa_set_env()
    * Define RLIMIT_RTTIME and friends if not defined by glibc
    * Add pa_strempty()
    * rename state testing macros to include _IS_, to make clearer that they are no states, but testing macros
    * Implement pa_source_output_set_requested_latency_within_thread() to be able to forward latency info to sources from within the IO thread
    * Similar for sink inputs
    * generelize since_underrun counter in sink inputs to "playing_for" and "underrun_for". Use only this for ignore potential rewind requests over underruns
    * Add new native protocol message PLAYBACK_STREAM_MESSAGE_STARTED for notification about the end of an underrun
    * Port native protocol to use underrun_for/playing_for which is maintained by the sink input anyway
    * Pass underrun_for/playing_for in timing info to client
    * Drop pa_sink_skip() since it breaks underrun detection code
    * Move PID file and unix sockets to the runtime dir (i.e. ~/.pulse). This fixes a potention DoS attack from other users stealing dirs in /tmp from us so that we cannot take them anymore)
    * Allow setting of more resource limits from the config file. Set RTTIME by default
    * Streamline daemon startup code
    * Rework algorithm to find default configuration files
    * If run in system mode use "system.pa" instead of "default.pa" as default script file
    * Change ladspa sink to use pa_clamp_samples() for clamping samples
    * Teach module-null-sink how to deal with rewinding
    * Try to support ALSA devices with no implicit channel map. Synthesize one by padding with PA_CHANNEL_POSITION_AUX channels. This is not tested since I lack hardware with these problems.
    * Make use of time smoother in the client libraries.
    * Add new pa_stream_is_corked() and pa_stream_set_started_callback() functions to public API
    * Since our native socket moved, add some code for finding sockets created by old versions of PA. This should ease upgrades
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2329 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/daemon/cmdline.c b/src/daemon/cmdline.c
index f1e1282..97c75f3 100644
--- a/src/daemon/cmdline.c
+++ b/src/daemon/cmdline.c
@@ -293,8 +293,7 @@ int pa_cmdline_parse(pa_daemon_conf *conf, int argc, char *const argv [], int *d
                 break;
 
             case 'n':
-                pa_xfree(conf->default_script_file);
-                conf->default_script_file = NULL;
+                conf->load_default_script_file = FALSE;
                 break;
 
             case ARG_LOG_TARGET:
diff --git a/src/daemon/daemon-conf.c b/src/daemon/daemon-conf.c
index c98c021..f9ad7ec 100644
--- a/src/daemon/daemon-conf.c
+++ b/src/daemon/daemon-conf.c
@@ -33,6 +33,7 @@
 #include <sched.h>
 
 #include <pulse/xmalloc.h>
+#include <pulse/timeval.h>
 
 #include <pulsecore/core-error.h>
 #include <pulsecore/core-util.h>
@@ -45,6 +46,8 @@
 
 #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_SYSTEM_SCRIPT_FILE PA_DEFAULT_CONFIG_DIR PA_PATH_SEP "system.pa"
+
 #define DEFAULT_CONFIG_FILE PA_DEFAULT_CONFIG_DIR PA_PATH_SEP "daemon.conf"
 #define DEFAULT_CONFIG_FILE_USER PA_PATH_SEP "daemon.conf"
 
@@ -67,6 +70,7 @@ static const pa_daemon_conf default_conf = {
     .auto_log_target = 1,
     .script_commands = NULL,
     .dl_search_path = NULL,
+    .load_default_script_file = TRUE,
     .default_script_file = NULL,
     .log_target = PA_LOG_SYSLOG,
     .log_level = PA_LOG_NOTICE,
@@ -81,34 +85,43 @@ static const pa_daemon_conf default_conf = {
     .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 = FALSE },
-    .rlimit_core = { .value = 0, .is_set = FALSE },
+   ,.rlimit_fsize = { .value = 0, .is_set = FALSE },
     .rlimit_data = { .value = 0, .is_set = FALSE },
-    .rlimit_fsize = { .value = 0, .is_set = FALSE },
-    .rlimit_nofile = { .value = 256, .is_set = TRUE },
-    .rlimit_stack = { .value = 0, .is_set = FALSE }
+    .rlimit_stack = { .value = 0, .is_set = FALSE },
+    .rlimit_core = { .value = 0, .is_set = FALSE },
+    .rlimit_rss = { .value = 0, .is_set = FALSE }
 #ifdef RLIMIT_NPROC
-    , .rlimit_nproc = { .value = 0, .is_set = FALSE }
+   ,.rlimit_nproc = { .value = 0, .is_set = FALSE }
 #endif
+   ,.rlimit_nofile = { .value = 256, .is_set = TRUE }
 #ifdef RLIMIT_MEMLOCK
-    , .rlimit_memlock = { .value = 0, .is_set = FALSE }
+   ,.rlimit_memlock = { .value = 0, .is_set = FALSE }
+#endif
+   ,.rlimit_as = { .value = 0, .is_set = FALSE }
+#ifdef RLIMIT_LOCKS
+   ,.rlimit_locks = { .value = 0, .is_set = FALSE }
+#endif
+#ifdef RLIMIT_SIGPENDING
+   ,.rlimit_sigpending = { .value = 0, .is_set = FALSE }
+#endif
+#ifdef RLIMIT_MSGQUEUE
+   ,.rlimit_msgqueue = { .value = 0, .is_set = FALSE }
 #endif
 #ifdef RLIMIT_NICE
-    , .rlimit_nice = { .value = 31, .is_set = TRUE }     /* nice level of -11 */
+   ,.rlimit_nice = { .value = 31, .is_set = TRUE }     /* nice level of -11 */
 #endif
 #ifdef RLIMIT_RTPRIO
-    , .rlimit_rtprio = { .value = 9, .is_set = TRUE }      /* One below JACK's default for the server */
+   ,.rlimit_rtprio = { .value = 9, .is_set = TRUE }    /* One below JACK's default for the server */
+#endif
+#ifdef RLIMIT_RTTIME
+   ,.rlimit_rttime = { .value = PA_USEC_PER_SEC, .is_set = TRUE }
 #endif
 #endif
 };
 
 pa_daemon_conf* pa_daemon_conf_new(void) {
-    FILE *f;
     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);
-
     c->dl_search_path = pa_xstrdup(PA_DLSEARCHPATH);
     return c;
 }
@@ -412,25 +425,39 @@ int pa_daemon_conf_load(pa_daemon_conf *c, const char *filename) {
         { "default-fragment-size-msec", parse_fragment_size_msec, NULL },
         { "nice-level",                 parse_nice_level,         NULL },
         { "disable-remixing",           pa_config_parse_bool,     NULL },
+        { "load-default-script-file",   pa_config_parse_bool,     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-data",                parse_rlimit,             NULL },
         { "rlimit-stack",               parse_rlimit,             NULL },
+        { "rlimit-core",                parse_rlimit,             NULL },
+        { "rlimit-rss",                 parse_rlimit,             NULL },
+        { "rlimit-nofile",              parse_rlimit,             NULL },
+        { "rlimit-as",                  parse_rlimit,             NULL },
 #ifdef RLIMIT_NPROC
         { "rlimit-nproc",               parse_rlimit,             NULL },
 #endif
 #ifdef RLIMIT_MEMLOCK
         { "rlimit-memlock",             parse_rlimit,             NULL },
 #endif
+#ifdef RLIMIT_LOCKS
+        { "rlimit-locks",               parse_rlimit,             NULL },
+#endif
+#ifdef RLIMIT_SIGPENDING
+        { "rlimit-sigpending",          parse_rlimit,             NULL },
+#endif
+#ifdef RLIMIT_MSGQUEUE
+        { "rlimit-msgqueue",            parse_rlimit,             NULL },
+#endif
 #ifdef RLIMIT_NICE
         { "rlimit-nice",                parse_rlimit,             NULL },
 #endif
 #ifdef RLIMIT_RTPRIO
         { "rlimit-rtprio",              parse_rlimit,             NULL },
 #endif
+#ifdef RLIMIT_RTTIME
+        { "rlimit-rttime",              parse_rlimit,             NULL },
+#endif
 #endif
         { NULL,                         NULL,                     NULL },
     };
@@ -461,33 +488,66 @@ int pa_daemon_conf_load(pa_daemon_conf *c, const char *filename) {
     table[23].data = c;
     table[24].data = c;
     table[25].data = &c->disable_remixing;
+    table[26].data = &c->load_default_script_file;
 #ifdef HAVE_SYS_RESOURCE_H
-    table[26].data = &c->rlimit_as;
-    table[27].data = &c->rlimit_core;
+    table[27].data = &c->rlimit_fsize;
     table[28].data = &c->rlimit_data;
-    table[29].data = &c->rlimit_fsize;
-    table[30].data = &c->rlimit_nofile;
-    table[31].data = &c->rlimit_stack;
+    table[29].data = &c->rlimit_stack;
+    table[30].data = &c->rlimit_as;
+    table[31].data = &c->rlimit_core;
+    table[32].data = &c->rlimit_nofile;
+    table[33].data = &c->rlimit_as;
 #ifdef RLIMIT_NPROC
-    table[32].data = &c->rlimit_nproc;
+    table[34].data = &c->rlimit_nproc;
 #endif
+
 #ifdef RLIMIT_MEMLOCK
 #ifndef RLIMIT_NPROC
 #error "Houston, we have a numbering problem!"
 #endif
-    table[33].data = &c->rlimit_memlock;
+    table[35].data = &c->rlimit_memlock;
 #endif
-#ifdef RLIMIT_NICE
+
+#ifdef RLIMIT_LOCKS
 #ifndef RLIMIT_MEMLOCK
 #error "Houston, we have a numbering problem!"
 #endif
-    table[34].data = &c->rlimit_nice;
+    table[36].data = &c->rlimit_locks;
+#endif
+
+#ifdef RLIMIT_SIGPENDING
+#ifndef RLIMIT_LOCKS
+#error "Houston, we have a numbering problem!"
+#endif
+    table[37].data = &c->rlimit_sigpending;
+#endif
+
+#ifdef RLIMIT_MSGQUEUE
+#ifndef RLIMIT_SIGPENDING
+#error "Houston, we have a numbering problem!"
+#endif
+    table[38].data = &c->rlimit_msgqueue;
+#endif
+
+#ifdef RLIMIT_NICE
+#ifndef RLIMIT_MSGQUEUE
+#error "Houston, we have a numbering problem!"
+#endif
+    table[39].data = &c->rlimit_nice;
 #endif
+
 #ifdef RLIMIT_RTPRIO
 #ifndef RLIMIT_NICE
 #error "Houston, we have a numbering problem!"
 #endif
-    table[35].data = &c->rlimit_rtprio;
+    table[40].data = &c->rlimit_rtprio;
+#endif
+
+#ifdef RLIMIT_RTTIME
+#ifndef RLIMIT_RTTIME
+#error "Houston, we have a numbering problem!"
+#endif
+    table[41].data = &c->rlimit_rttime;
 #endif
 #endif
 
@@ -496,10 +556,10 @@ int pa_daemon_conf_load(pa_daemon_conf *c, const char *filename) {
 
     f = filename ?
         fopen(c->config_file = pa_xstrdup(filename), "r") :
-        pa_open_config_file(DEFAULT_CONFIG_FILE, DEFAULT_CONFIG_FILE_USER, ENV_CONFIG_FILE, &c->config_file, "r");
+        pa_open_config_file(DEFAULT_CONFIG_FILE, DEFAULT_CONFIG_FILE_USER, ENV_CONFIG_FILE, &c->config_file);
 
     if (!f && errno != ENOENT) {
-        pa_log_warn("Failed to open configuration file '%s': %s", c->config_file, pa_cstrerror(errno));
+        pa_log_warn("Failed to open configuration file: %s", pa_cstrerror(errno));
         goto finish;
     }
 
@@ -514,6 +574,7 @@ finish:
 
 int pa_daemon_conf_env(pa_daemon_conf *c) {
     char *e;
+    pa_assert(c);
 
     if ((e = getenv(ENV_DL_SEARCH_PATH))) {
         pa_xfree(c->dl_search_path);
@@ -527,6 +588,35 @@ int pa_daemon_conf_env(pa_daemon_conf *c) {
     return 0;
 }
 
+const char *pa_daemon_conf_get_default_script_file(pa_daemon_conf *c) {
+    pa_assert(c);
+
+    if (!c->default_script_file) {
+        if (c->system_instance)
+            c->default_script_file = pa_find_config_file(DEFAULT_SYSTEM_SCRIPT_FILE, NULL, ENV_SCRIPT_FILE);
+        else
+            c->default_script_file = pa_find_config_file(DEFAULT_SCRIPT_FILE, DEFAULT_SCRIPT_FILE_USER, ENV_SCRIPT_FILE);
+    }
+
+    return c->default_script_file;
+}
+
+FILE *pa_daemon_conf_open_default_script_file(pa_daemon_conf *c) {
+    FILE *f;
+    pa_assert(c);
+
+    if (!c->default_script_file) {
+        if (c->system_instance)
+            f = pa_open_config_file(DEFAULT_SYSTEM_SCRIPT_FILE, NULL, ENV_SCRIPT_FILE, &c->default_script_file);
+        else
+            f = pa_open_config_file(DEFAULT_SCRIPT_FILE, DEFAULT_SCRIPT_FILE_USER, ENV_SCRIPT_FILE, &c->default_script_file);
+    } else
+        f = fopen(c->default_script_file, "r");
+
+    return f;
+}
+
+
 static const char* const log_level_to_string[] = {
     [PA_LOG_DEBUG] = "debug",
     [PA_LOG_INFO] = "info",
@@ -561,8 +651,9 @@ char *pa_daemon_conf_dump(pa_daemon_conf *c) {
     pa_strbuf_printf(s, "exit-idle-time = %i\n", c->exit_idle_time);
     pa_strbuf_printf(s, "module-idle-time = %i\n", c->module_idle_time);
     pa_strbuf_printf(s, "scache-idle-time = %i\n", c->scache_idle_time);
-    pa_strbuf_printf(s, "dl-search-path = %s\n", c->dl_search_path ? c->dl_search_path : "");
-    pa_strbuf_printf(s, "default-script-file = %s\n", c->default_script_file);
+    pa_strbuf_printf(s, "dl-search-path = %s\n", pa_strempty(c->dl_search_path));
+    pa_strbuf_printf(s, "default-script-file = %s\n", pa_strempty(pa_daemon_conf_get_default_script_file(c)));
+    pa_strbuf_printf(s, "load-default-script-file = %s\n", pa_yes_no(c->load_default_script_file));
     pa_strbuf_printf(s, "log-target = %s\n", c->auto_log_target ? "auto" : (c->log_target == PA_LOG_SYSLOG ? "syslog" : "stderr"));
     pa_strbuf_printf(s, "log-level = %s\n", log_level_to_string[c->log_level]);
     pa_strbuf_printf(s, "resample-method = %s\n", pa_resample_method_to_string(c->resample_method));
@@ -573,23 +664,36 @@ char *pa_daemon_conf_dump(pa_daemon_conf *c) {
     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);
-    pa_strbuf_printf(s, "rlimit-data = %li\n", c->rlimit_data.is_set ? (long int) c->rlimit_data.value : -1);
     pa_strbuf_printf(s, "rlimit-fsize = %li\n", c->rlimit_fsize.is_set ? (long int) c->rlimit_fsize.value : -1);
-    pa_strbuf_printf(s, "rlimit-nofile = %li\n", c->rlimit_nofile.is_set ? (long int) c->rlimit_nofile.value : -1);
+    pa_strbuf_printf(s, "rlimit-data = %li\n", c->rlimit_data.is_set ? (long int) c->rlimit_data.value : -1);
     pa_strbuf_printf(s, "rlimit-stack = %li\n", c->rlimit_stack.is_set ? (long int) c->rlimit_stack.value : -1);
+    pa_strbuf_printf(s, "rlimit-core = %li\n", c->rlimit_core.is_set ? (long int) c->rlimit_core.value : -1);
+    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-rss = %li\n", c->rlimit_rss.is_set ? (long int) c->rlimit_rss.value : -1);
 #ifdef RLIMIT_NPROC
     pa_strbuf_printf(s, "rlimit-nproc = %li\n", c->rlimit_nproc.is_set ? (long int) c->rlimit_nproc.value : -1);
 #endif
+    pa_strbuf_printf(s, "rlimit-nofile = %li\n", c->rlimit_nofile.is_set ? (long int) c->rlimit_nofile.value : -1);
 #ifdef RLIMIT_MEMLOCK
     pa_strbuf_printf(s, "rlimit-memlock = %li\n", c->rlimit_memlock.is_set ? (long int) c->rlimit_memlock.value : -1);
 #endif
+#ifdef RLIMIT_LOCKS
+    pa_strbuf_printf(s, "rlimit-locks = %li\n", c->rlimit_locks.is_set ? (long int) c->rlimit_locks.value : -1);
+#endif
+#ifdef RLIMIT_SIGPENDING
+    pa_strbuf_printf(s, "rlimit-sigpending = %li\n", c->rlimit_sigpending.is_set ? (long int) c->rlimit_sigpending.value : -1);
+#endif
+#ifdef RLIMIT_MSGQUEUE
+    pa_strbuf_printf(s, "rlimit-msgqueue = %li\n", c->rlimit_msgqueue.is_set ? (long int) c->rlimit_msgqueue.value : -1);
+#endif
 #ifdef RLIMIT_NICE
-    pa_strbuf_printf(s, "rlimit-nice = %li\n", c->rlimit_memlock.is_set ? (long int) c->rlimit_nice.value : -1);
+    pa_strbuf_printf(s, "rlimit-nice = %li\n", c->rlimit_nice.is_set ? (long int) c->rlimit_nice.value : -1);
 #endif
 #ifdef RLIMIT_RTPRIO
-    pa_strbuf_printf(s, "rlimit-rtprio = %li\n", c->rlimit_memlock.is_set ? (long int) c->rlimit_rtprio.value : -1);
+    pa_strbuf_printf(s, "rlimit-rtprio = %li\n", c->rlimit_rtprio.is_set ? (long int) c->rlimit_rtprio.value : -1);
+#endif
+#ifdef RLIMIT_RTTIME
+    pa_strbuf_printf(s, "rlimit-rttime = %li\n", c->rlimit_rttime.is_set ? (long int) c->rlimit_rttime.value : -1);
 #endif
 #endif
 
diff --git a/src/daemon/daemon-conf.h b/src/daemon/daemon-conf.h
index 3dcafbf..03a7566 100644
--- a/src/daemon/daemon-conf.h
+++ b/src/daemon/daemon-conf.h
@@ -27,6 +27,7 @@
 
 #include <pulsecore/log.h>
 #include <pulsecore/macro.h>
+#include <pulsecore/core-util.h>
 #include <pulse/sample.h>
 
 #ifdef HAVE_SYS_RESOURCE_H
@@ -65,7 +66,8 @@ typedef struct pa_daemon_conf {
         system_instance,
         no_cpu_limit,
         disable_shm,
-        disable_remixing;
+        disable_remixing,
+        load_default_script_file;
     int exit_idle_time,
         module_idle_time,
         scache_idle_time,
@@ -79,19 +81,31 @@ typedef struct pa_daemon_conf {
     char *config_file;
 
 #ifdef HAVE_SYS_RESOURCE_H
-    pa_rlimit rlimit_as, rlimit_core, rlimit_data, rlimit_fsize, rlimit_nofile, rlimit_stack;
+    pa_rlimit rlimit_fsize, rlimit_data, rlimit_stack, rlimit_core, rlimit_rss, rlimit_nofile, rlimit_as;
 #ifdef RLIMIT_NPROC
     pa_rlimit rlimit_nproc;
 #endif
 #ifdef RLIMIT_MEMLOCK
     pa_rlimit rlimit_memlock;
 #endif
+#ifdef RLIMIT_LOCKS
+    pa_rlimit rlimit_locks;
+#endif
+#ifdef RLIMIT_SIGPENDING
+    pa_rlimit rlimit_sigpending;
+#endif
+#ifdef RLIMIT_MSGQUEUE
+    pa_rlimit rlimit_msgqueue;
+#endif
 #ifdef RLIMIT_NICE
     pa_rlimit rlimit_nice;
 #endif
 #ifdef RLIMIT_RTPRIO
     pa_rlimit rlimit_rtprio;
 #endif
+#ifdef RLIMIT_RTTIME
+    pa_rlimit rlimit_rttime;
+#endif
 #endif
 
     unsigned default_n_fragments, default_fragment_size_msec;
@@ -121,4 +135,7 @@ 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);
 int pa_daemon_conf_set_resample_method(pa_daemon_conf *c, const char *string);
 
+const char *pa_daemon_conf_get_default_script_file(pa_daemon_conf *c);
+FILE *pa_daemon_conf_open_default_script_file(pa_daemon_conf *c);
+
 #endif
diff --git a/src/daemon/daemon.conf.in b/src/daemon/daemon.conf.in
index e4cfb82..fd35c0f 100644
--- a/src/daemon/daemon.conf.in
+++ b/src/daemon/daemon.conf.in
@@ -40,6 +40,7 @@
 
 ; dl-search-path = (depends on architecture)
 
+; load-defaul-script-file = yes
 ; default-script-file = @PA_DEFAULT_CONFIG_FILE@
 
 ; log-target = auto
@@ -50,16 +51,21 @@
 
 ; no-cpu-limit = no
 
-; rlimit-as = -1
-; rlimit-core = -1
-; rlimit-data = -1
 ; rlimit-fsize = -1
-; rlimit-nofile = 256
+; rlimit-data = -1
 ; rlimit-stack = -1
+; rlimit-core = -1
+; rlimit-as = -1
+; rlimit-rss = -1
 ; rlimit-nproc = -1
+; rlimit-nofile = 256
 ; rlimit-memlock = -1
+; rlimit-locks = -1
+; rlimit-sigpending = -1
+; rlimit-msgqueue = -1
 ; rlimit-nice = 31
 ; rlimit-rtprio = 9
+; rlimit-rtttime = 1000000
 
 ; default-sample-format = s16le
 ; default-sample-rate = 44100
diff --git a/src/daemon/main.c b/src/daemon/main.c
index 6b0c81d..b1ba5a3 100644
--- a/src/daemon/main.c
+++ b/src/daemon/main.c
@@ -115,7 +115,7 @@ static void message_cb(pa_mainloop_api*a, pa_time_event*e, PA_GCC_UNUSED const s
     MSG msg;
     struct timeval tvnext;
 
-    while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
+    while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
         if (msg.message == WM_QUIT)
             raise(SIGTERM);
         else {
@@ -164,8 +164,6 @@ static void signal_callback(pa_mainloop_api*m, PA_GCC_UNUSED pa_signal_event *e,
     }
 }
 
-#define set_env(key, value) putenv(pa_sprintf_malloc("%s=%s", (key), (value)))
-
 #if defined(HAVE_PWD_H) && defined(HAVE_GRP_H)
 
 static int change_user(void) {
@@ -241,14 +239,14 @@ static int change_user(void) {
         return -1;
     }
 
-    set_env("USER", PA_SYSTEM_USER);
-    set_env("USERNAME", PA_SYSTEM_USER);
-    set_env("LOGNAME", PA_SYSTEM_USER);
-    set_env("HOME", PA_SYSTEM_RUNTIME_PATH);
+    pa_set_env("USER", PA_SYSTEM_USER);
+    pa_set_env("USERNAME", PA_SYSTEM_USER);
+    pa_set_env("LOGNAME", PA_SYSTEM_USER);
+    pa_set_env("HOME", PA_SYSTEM_RUNTIME_PATH);
 
     /* Relevant for pa_runtime_path() */
-    set_env("PULSE_RUNTIME_PATH", PA_SYSTEM_RUNTIME_PATH);
-    set_env("PULSE_CONFIG_PATH", PA_SYSTEM_RUNTIME_PATH);
+    pa_set_env("PULSE_RUNTIME_PATH", PA_SYSTEM_RUNTIME_PATH);
+    pa_set_env("PULSE_CONFIG_PATH", PA_SYSTEM_RUNTIME_PATH);
 
     pa_log_info("Successfully dropped root privileges.");
 
@@ -264,23 +262,6 @@ static int change_user(void) {
 
 #endif /* HAVE_PWD_H && HAVE_GRP_H */
 
-static int create_runtime_dir(void) {
-    char fn[PATH_MAX];
-
-    pa_runtime_path(NULL, fn, sizeof(fn));
-
-    /* This function is called only when the daemon is started in
-     * per-user mode. We create the runtime directory somewhere in
-     * /tmp/ with the current UID/GID */
-
-    if (pa_make_secure_dir(fn, 0700, (uid_t)-1, (gid_t)-1) < 0) {
-        pa_log("Failed to create '%s': %s", fn, pa_cstrerror(errno));
-        return -1;
-    }
-
-    return 0;
-}
-
 #ifdef HAVE_SYS_RESOURCE_H
 
 static int set_one_rlimit(const pa_rlimit *r, int resource, const char *name) {
@@ -293,7 +274,7 @@ static int set_one_rlimit(const pa_rlimit *r, int resource, const char *name) {
     rl.rlim_cur = rl.rlim_max = r->value;
 
     if (setrlimit(resource, &rl) < 0) {
-        pa_log_warn("setrlimit(%s, (%u, %u)) failed: %s", name, (unsigned) r->value, (unsigned) r->value, pa_cstrerror(errno));
+        pa_log_info("setrlimit(%s, (%u, %u)) failed: %s", name, (unsigned) r->value, (unsigned) r->value, pa_cstrerror(errno));
         return -1;
     }
 
@@ -301,24 +282,37 @@ static int set_one_rlimit(const pa_rlimit *r, int resource, const char *name) {
 }
 
 static void set_all_rlimits(const pa_daemon_conf *conf) {
-    set_one_rlimit(&conf->rlimit_as, RLIMIT_AS, "RLIMIT_AS");
-    set_one_rlimit(&conf->rlimit_core, RLIMIT_CORE, "RLIMIT_CORE");
-    set_one_rlimit(&conf->rlimit_data, RLIMIT_DATA, "RLIMIT_DATA");
     set_one_rlimit(&conf->rlimit_fsize, RLIMIT_FSIZE, "RLIMIT_FSIZE");
-    set_one_rlimit(&conf->rlimit_nofile, RLIMIT_NOFILE, "RLIMIT_NOFILE");
+    set_one_rlimit(&conf->rlimit_data, RLIMIT_DATA, "RLIMIT_DATA");
     set_one_rlimit(&conf->rlimit_stack, RLIMIT_STACK, "RLIMIT_STACK");
+    set_one_rlimit(&conf->rlimit_core, RLIMIT_CORE, "RLIMIT_CORE");
+    set_one_rlimit(&conf->rlimit_rss, RLIMIT_RSS, "RLIMIT_RSS");
 #ifdef RLIMIT_NPROC
     set_one_rlimit(&conf->rlimit_nproc, RLIMIT_NPROC, "RLIMIT_NPROC");
 #endif
+    set_one_rlimit(&conf->rlimit_nofile, RLIMIT_NOFILE, "RLIMIT_NOFILE");
 #ifdef RLIMIT_MEMLOCK
     set_one_rlimit(&conf->rlimit_memlock, RLIMIT_MEMLOCK, "RLIMIT_MEMLOCK");
 #endif
+    set_one_rlimit(&conf->rlimit_as, RLIMIT_AS, "RLIMIT_AS");
+#ifdef RLIMIT_LOCKS
+    set_one_rlimit(&conf->rlimit_locks, RLIMIT_LOCKS, "RLIMIT_LOCKS");
+#endif
+#ifdef RLIMIT_SIGPENDING
+    set_one_rlimit(&conf->rlimit_sigpending, RLIMIT_SIGPENDING, "RLIMIT_SIGPENDING");
+#endif
+#ifdef RLIMIT_MSGQUEUE
+    set_one_rlimit(&conf->rlimit_msgqueue, RLIMIT_MSGQUEUE, "RLIMIT_MSGQUEUE");
+#endif
 #ifdef RLIMIT_NICE
     set_one_rlimit(&conf->rlimit_nice, RLIMIT_NICE, "RLIMIT_NICE");
 #endif
 #ifdef RLIMIT_RTPRIO
     set_one_rlimit(&conf->rlimit_rtprio, RLIMIT_RTPRIO, "RLIMIT_RTPRIO");
 #endif
+#ifdef RLIMIT_RTTIME
+    set_one_rlimit(&conf->rlimit_rttime, RLIMIT_RTTIME, "RLIMIT_RTTIME");
+#endif
 }
 #endif
 
@@ -329,19 +323,20 @@ int main(int argc, char *argv[]) {
     pa_mainloop *mainloop = NULL;
     char *s;
     int r = 0, retval = 1, d = 0;
-    int daemon_pipe[2] = { -1, -1 };
     pa_bool_t suid_root, real_root;
-    int valid_pid_file = 0;
+    pa_bool_t valid_pid_file = FALSE;
     gid_t gid = (gid_t) -1;
-    pa_bool_t allow_realtime, allow_high_priority;
     pa_bool_t ltdl_init = FALSE;
-
+    int passed_fd = -1;
+    const char *e;
+#ifdef HAVE_FORK
+    int daemon_pipe[2] = { -1, -1 };
+#endif
 #ifdef OS_IS_WIN32
-    pa_time_event *timer;
-    struct timeval tv;
+    pa_time_event *win32_timer;
+    struct timeval win32_tv;
 #endif
 
-
 #if defined(__linux__) && defined(__OPTIMIZE__)
     /*
        Disable lazy relocations to make usage of external libraries
@@ -355,7 +350,7 @@ int main(int argc, char *argv[]) {
         /* We have to execute ourselves, because the libc caches the
          * value of $LD_BIND_NOW on initialization. */
 
-        putenv(pa_xstrdup("LD_BIND_NOW=1"));
+        pa_set_env("LD_BIND_NOW", "1");
         pa_assert_se(rp = pa_readlink("/proc/self/exe"));
         pa_assert_se(execv(rp, argv) == 0);
     }
@@ -385,6 +380,18 @@ int main(int argc, char *argv[]) {
          * is just too risky tun let PA run as root all the time. */
     }
 
+    if ((e = getenv("PULSE_PASSED_FD"))) {
+        passed_fd = atoi(e);
+
+        if (passed_fd <= 2)
+            passed_fd = -1;
+    }
+
+    pa_close_all(passed_fd, -1);
+
+    pa_reset_sigs(-1);
+    pa_unblock_sigs(-1);
+
     /* At this point, we are a normal user, possibly with CAP_NICE if
      * we were started SUID. If we are started as normal root, than we
      * still are normal root. */
@@ -410,67 +417,59 @@ int main(int argc, char *argv[]) {
     pa_log_set_target(conf->auto_log_target ? PA_LOG_STDERR : conf->log_target, NULL);
 
     if (suid_root) {
+        pa_bool_t allow_realtime, allow_high_priority;
+
         /* Ok, we're suid root, so let's better not enable high prio
          * or RT by default */
 
         allow_high_priority = allow_realtime = FALSE;
 
+        if (conf->high_priority || conf->realtime_scheduling)
+            if (pa_own_uid_in_group(PA_REALTIME_GROUP, &gid) > 0) {
+                pa_log_info("We're in the group '"PA_REALTIME_GROUP"', allowing real-time and high-priority scheduling.");
+                allow_realtime = conf->realtime_scheduling;
+                allow_high_priority = conf->high_priority;
+            }
+
 #ifdef HAVE_POLKIT
-        if (conf->high_priority) {
+        if (conf->high_priority && !allow_high_priority) {
             if (pa_polkit_check("org.pulseaudio.acquire-high-priority") > 0) {
-                pa_log_info("PolicyKit grants us acquire-high-priority privilige.");
+                pa_log_info("PolicyKit grants us acquire-high-priority privilege.");
                 allow_high_priority = TRUE;
             } else
-                pa_log_info("PolicyKit refuses acquire-high-priority privilige.");
+                pa_log_info("PolicyKit refuses acquire-high-priority privilege.");
         }
 
-        if (conf->realtime_scheduling) {
+        if (conf->realtime_scheduling && !allow_realtime) {
             if (pa_polkit_check("org.pulseaudio.acquire-real-time") > 0) {
-                pa_log_info("PolicyKit grants us acquire-real-time privilige.");
+                pa_log_info("PolicyKit grants us acquire-real-time privilege.");
                 allow_realtime = TRUE;
             } else
-                pa_log_info("PolicyKit refuses acquire-real-time privilige.");
+                pa_log_info("PolicyKit refuses acquire-real-time privilege.");
         }
 #endif
 
-        if ((conf->high_priority || conf->realtime_scheduling) && pa_own_uid_in_group(PA_REALTIME_GROUP, &gid) > 0) {
-            pa_log_info("We're in the group '"PA_REALTIME_GROUP"', allowing real-time and high-priority scheduling.");
-            allow_realtime = conf->realtime_scheduling;
-            allow_high_priority = conf->high_priority;
-        }
-
         if (!allow_high_priority && !allow_realtime) {
 
             /* OK, there's no further need to keep CAP_NICE. Hence
              * let's give it up early */
 
             pa_drop_caps();
-            pa_drop_root();
-            suid_root = real_root = FALSE;
+            suid_root = FALSE;
 
             if (conf->high_priority || conf->realtime_scheduling)
                 pa_log_notice("Called SUID root and real-time/high-priority scheduling was requested in the configuration. However, we lack the necessary priviliges:\n"
                               "We are not in group '"PA_REALTIME_GROUP"' and PolicyKit refuse to grant us priviliges. Dropping SUID again.\n"
                               "For enabling real-time scheduling please acquire the appropriate PolicyKit priviliges, or become a member of '"PA_REALTIME_GROUP"', or increase the RLIMIT_NICE/RLIMIT_RTPRIO resource limits for this user.");
         }
-
-    } else {
-
-        /* OK, we're a normal user, so let's allow the user evrything
-         * he asks for, it's now the kernel's job to enforce limits,
-         * not ours anymore */
-        allow_high_priority = allow_realtime = TRUE;
     }
 
-    if (conf->high_priority && !allow_high_priority) {
-        pa_log_info("High-priority scheduling enabled in configuration but now allowed by policy. Disabling forcibly.");
-        conf->high_priority = FALSE;
-    }
+#ifdef HAVE_SYS_RESOURCE_H
+    set_all_rlimits(conf);
+#endif
 
-    if (conf->realtime_scheduling && !allow_realtime) {
-        pa_log_info("Real-time scheduling enabled in configuration but now allowed by policy. Disabling forcibly.");
-        conf->realtime_scheduling = FALSE;
-    }
+    if (conf->high_priority && !pa_can_high_priority())
+        pa_log_warn("High-priority scheduling enabled in configuration but now allowed by policy.");
 
     if (conf->high_priority && conf->cmd == PA_CMD_DAEMON)
         pa_raise_priority(conf->nice_level);
@@ -482,28 +481,38 @@ int main(int argc, char *argv[]) {
 
 #ifdef RLIMIT_RTPRIO
         if (!drop) {
-
+            struct rlimit rl;
             /* At this point we still have CAP_NICE if we were loaded
              * SUID root. If possible let's acquire RLIMIT_RTPRIO
              * instead and give CAP_NICE up. */
 
-            const pa_rlimit rl = { 9, TRUE };
+            if (getrlimit(RLIMIT_RTPRIO, &rl) >= 0) {
 
-            if (set_one_rlimit(&rl, RLIMIT_RTPRIO, "RLIMIT_RTPRIO") >= 0) {
-                pa_log_info("Successfully increased RLIMIT_RTPRIO, giving up CAP_NICE.");
-                drop = TRUE;
-            } else
-                pa_log_warn("RLIMIT_RTPRIO failed: %s", pa_cstrerror(errno));
+                if (rl.rlim_cur >= 9)
+                    drop = TRUE;
+                else {
+                    rl.rlim_max = rl.rlim_cur = 9;
+
+                    if (setrlimit(RLIMIT_RTPRIO, &rl) < 0) {
+                        pa_log_info("Successfully increased RLIMIT_RTPRIO");
+                        drop = TRUE;
+                    } else
+                        pa_log_warn("RLIMIT_RTPRIO failed: %s", pa_cstrerror(errno));
+                }
+            }
         }
 #endif
 
         if (drop)  {
+            pa_log_info("Giving up CAP_NICE");
             pa_drop_caps();
-            pa_drop_root();
-            suid_root = real_root = FALSE;
+            suid_root = FALSE;
         }
     }
 
+    if (conf->realtime_scheduling && !pa_can_realtime())
+        pa_log_warn("Real-time scheduling enabled in configuration but now allowed by policy.");
+
     LTDL_SET_PRELOADED_SYMBOLS();
     pa_ltdl_init();
     ltdl_init = TRUE;
@@ -605,7 +614,7 @@ int main(int argc, char *argv[]) {
 
 #ifdef HAVE_FORK
         if (pipe(daemon_pipe) < 0) {
-            pa_log("Failed to create pipe.");
+            pa_log("pipe failed: %s", pa_cstrerror(errno));
             goto finish;
         }
 
@@ -615,20 +624,24 @@ int main(int argc, char *argv[]) {
         }
 
         if (child != 0) {
+            ssize_t n;
             /* Father */
 
             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)) {
-                pa_log("read() failed: %s", pa_cstrerror(errno));
+            if ((n = pa_loop_read(daemon_pipe[0], &retval, sizeof(retval), NULL)) != sizeof(retval)) {
+
+                if (n < 0)
+                    pa_log("read() failed: %s", pa_cstrerror(errno));
+
                 retval = 1;
             }
 
             if (retval)
-                pa_log("daemon startup failed.");
+                pa_log("Daemon startup failed.");
             else
-                pa_log_info("daemon startup successful.");
+                pa_log_info("Daemon startup successful.");
 
             goto finish;
         }
@@ -652,9 +665,9 @@ int main(int argc, char *argv[]) {
         pa_close(1);
         pa_close(2);
 
-        open("/dev/null", O_RDONLY);
-        open("/dev/null", O_WRONLY);
-        open("/dev/null", O_WRONLY);
+        pa_assert_se(open("/dev/null", O_RDONLY) == 0);
+        pa_assert_se(open("/dev/null", O_WRONLY) == 1);
+        pa_assert_se(open("/dev/null", O_WRONLY) == 2);
 #else
         FreeConsole();
 #endif
@@ -677,39 +690,32 @@ int main(int argc, char *argv[]) {
 #endif
     }
 
+    pa_set_env("PULSE_INTERNAL", "1");
     pa_assert_se(chdir("/") == 0);
     umask(0022);
 
-    if (conf->system_instance) {
+    if (conf->system_instance)
         if (change_user() < 0)
             goto finish;
-    } else if (create_runtime_dir() < 0)
-        goto finish;
+
+    pa_log_info("This is PulseAudio " PACKAGE_VERSION);
+    pa_log_info("Page size is %lu bytes", (unsigned long) PA_PAGE_SIZE);
+    pa_log_info("Using runtime directory %s.", s = pa_get_runtime_dir());
+    pa_xfree(s);
 
     if (conf->use_pid_file) {
         if (pa_pid_file_create() < 0) {
             pa_log("pa_pid_file_create() failed.");
-#ifdef HAVE_FORK
-            if (conf->daemonize)
-                pa_loop_write(daemon_pipe[1], &retval, sizeof(retval), NULL);
-#endif
             goto finish;
         }
 
-        valid_pid_file = 1;
+        valid_pid_file = TRUE;
     }
 
-#ifdef HAVE_SYS_RESOURCE_H
-    set_all_rlimits(conf);
-#endif
-
 #ifdef SIGPIPE
     signal(SIGPIPE, SIG_IGN);
 #endif
 
-    pa_log_info("This is PulseAudio " PACKAGE_VERSION);
-    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
@@ -738,11 +744,11 @@ int main(int argc, char *argv[]) {
     c->realtime_priority = conf->realtime_priority;
     c->realtime_scheduling = !!conf->realtime_scheduling;
     c->disable_remixing = !!conf->disable_remixing;
+    c->running_as_daemon = !!conf->daemonize;
 
     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);
-
 #ifdef SIGUSR1
     pa_signal_new(SIGUSR1, signal_callback, c);
 #endif
@@ -754,23 +760,27 @@ int main(int argc, char *argv[]) {
 #endif
 
 #ifdef OS_IS_WIN32
-    pa_assert_se(timer = pa_mainloop_get_api(mainloop)->time_new(pa_mainloop_get_api(mainloop), pa_gettimeofday(&tv), message_cb, NULL));
+    win32_timer = pa_mainloop_get_api(mainloop)->time_new(pa_mainloop_get_api(mainloop), pa_gettimeofday(&win32_tv), message_cb, NULL);
 #endif
 
-    if (conf->daemonize)
-        c->running_as_daemon = TRUE;
-
     oil_init();
 
     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)
-        r = pa_cli_command_execute_file(c, conf->default_script_file, buf, &conf->fail);
+    if (conf->load_default_script_file) {
+        FILE *f;
+
+        if ((f = pa_daemon_conf_open_default_script_file(conf))) {
+            r = pa_cli_command_execute_file_stream(c, f, buf, &conf->fail);
+            fclose(f);
+        }
+    }
 
     if (r >= 0)
         r = pa_cli_command_execute(c, conf->script_commands, buf, &conf->fail);
+
     pa_log_error("%s", s = pa_strbuf_tostring_free(buf));
     pa_xfree(s);
 
@@ -780,53 +790,55 @@ int main(int argc, char *argv[]) {
 
     if (r < 0 && conf->fail) {
         pa_log("Failed to initialize daemon.");
-#ifdef HAVE_FORK
-        if (conf->daemonize)
-            pa_loop_write(daemon_pipe[1], &retval, sizeof(retval), NULL);
-#endif
-    } else if (!c->modules || pa_idxset_size(c->modules) == 0) {
-        pa_log("daemon startup without any loaded modules, refusing to work.");
-#ifdef HAVE_FORK
-        if (conf->daemonize)
-            pa_loop_write(daemon_pipe[1], &retval, sizeof(retval), NULL);
-#endif
-    } else {
+        goto finish;
+    }
 
-        retval = 0;
+    if (!c->modules || pa_idxset_size(c->modules) == 0) {
+        pa_log("Daemon startup without any loaded modules, refusing to work.");
+        goto finish;
+    }
+
+    if (c->default_sink_name && !pa_namereg_get(c, c->default_sink_name, PA_NAMEREG_SINK, TRUE) && conf->fail) {
+        pa_log_error("Default sink name (%s) does not exist in name register.", c->default_sink_name);
+        goto finish;
+    }
 
-        if (c->default_sink_name &&
-            pa_namereg_get(c, c->default_sink_name, PA_NAMEREG_SINK, 1) == NULL) {
-            pa_log_error("%s : Default sink name (%s) does not exist in name register.", __FILE__, c->default_sink_name);
-            retval = !!conf->fail;
-        }
 
 #ifdef HAVE_FORK
-        if (conf->daemonize)
-            pa_loop_write(daemon_pipe[1], &retval, sizeof(retval), NULL);
+    if (conf->daemonize) {
+        int ok = 0;
+        pa_loop_write(daemon_pipe[1], &ok, sizeof(ok), NULL);
+    }
 #endif
 
-        if (!retval) {
-            pa_log_info("Daemon startup complete.");
-            if (pa_mainloop_run(mainloop, &retval) < 0)
-                retval = 1;
-            pa_log_info("Daemon shutdown initiated.");
-        }
-    }
+    pa_log_info("Daemon startup complete.");
+
+    retval = 0;
+    if (pa_mainloop_run(mainloop, &retval) < 0)
+        goto finish;
+
+    pa_log_info("Daemon shutdown initiated.");
+
+finish:
 
 #ifdef OS_IS_WIN32
-    pa_mainloop_get_api(mainloop)->time_free(timer);
+    if (win32_timer)
+        pa_mainloop_get_api(mainloop)->time_free(win32_timer);
 #endif
 
-    pa_core_unref(c);
+    if (c) {
+        pa_core_unref(c);
+        pa_log_info("Daemon terminated.");
+    }
 
     if (!conf->no_cpu_limit)
         pa_cpu_limit_done();
 
     pa_signal_done();
 
-    pa_log_info("Daemon terminated.");
-
-finish:
+#ifdef HAVE_FORK
+    pa_close_pipe(daemon_pipe);
+#endif
 
     if (mainloop)
         pa_mainloop_free(mainloop);
@@ -837,8 +849,6 @@ finish:
     if (valid_pid_file)
         pa_pid_file_remove();
 
-    pa_close_pipe(daemon_pipe);
-
 #ifdef OS_IS_WIN32
     WSACleanup();
 #endif
diff --git a/src/modules/alsa-util.c b/src/modules/alsa-util.c
index 0c4c020..47ed9ac 100644
--- a/src/modules/alsa-util.c
+++ b/src/modules/alsa-util.c
@@ -671,8 +671,24 @@ snd_pcm_t *pa_alsa_open_by_device_string(
         *dev = d;
 
         if (ss->channels != map->channels) {
-            pa_assert_se(pa_channel_map_init_auto(map, ss->channels, PA_CHANNEL_MAP_AUX));
-            pa_channel_map_init_auto(map, ss->channels, PA_CHANNEL_MAP_ALSA);
+            if (!pa_channel_map_init_auto(map, ss->channels, PA_CHANNEL_MAP_ALSA)) {
+                unsigned c;
+                pa_channel_position_t pos;
+
+                pa_log_warn("Device has an unknown channel mapping. This is a limitation of ALSA. Synthesizing channel map.");
+
+                for (c = ss->channels; c > 0; c--)
+                    if (pa_channel_map_init_auto(map, c, PA_CHANNEL_MAP_ALSA))
+                        break;
+
+                pa_assert(c > 0);
+
+                pos = PA_CHANNEL_POSITION_AUX0;
+                for (; c < map->channels; c ++)
+                    map->map[c] = pos++;
+
+                map->channels = ss->channels;
+            }
         }
 
         return pcm_handle;
diff --git a/src/modules/module-alsa-sink.c b/src/modules/module-alsa-sink.c
index 5cc27f1..efb0fd8 100644
--- a/src/modules/module-alsa-sink.c
+++ b/src/modules/module-alsa-sink.c
@@ -665,7 +665,7 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
             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_assert(PA_SINK_IS_OPENED(u->sink->thread_info.state));
 
                     if (suspend(u) < 0)
                         return -1;
@@ -836,9 +836,20 @@ static int sink_set_mute_cb(pa_sink *s) {
 
 static void sink_update_requested_latency_cb(pa_sink *s) {
     struct userdata *u = s->userdata;
+    snd_pcm_sframes_t before;
     pa_assert(u);
 
+    before = u->hwbuf_unused_frames;
     update_sw_params(u);
+
+    /* Let's check whether we now use only a smaller part of the
+    buffer then before. If so, we need to make sure that subsequent
+    rewinds are relative to the new maxium fill level and not to the
+    current fill level. Thus, let's do a full rewind once, to clear
+    things up. */
+
+    if (u->hwbuf_unused_frames > before)
+        pa_sink_request_rewind(s, 0);
 }
 
 static int process_rewind(struct userdata *u) {
@@ -846,6 +857,7 @@ static int process_rewind(struct userdata *u) {
     size_t rewind_nbytes, unused_nbytes, limit_nbytes;
     pa_assert(u);
 
+    /* Figure out how much we shall rewind and reset the counter */
     rewind_nbytes = u->sink->thread_info.rewind_nbytes;
     u->sink->thread_info.rewind_nbytes = 0;
 
@@ -917,7 +929,7 @@ static void thread_func(void *userdata) {
 /*         pa_log_debug("loop"); */
 
         /* Render some data and write it to the dsp */
-        if (PA_SINK_OPENED(u->sink->thread_info.state)) {
+        if (PA_SINK_IS_OPENED(u->sink->thread_info.state)) {
             int work_done = 0;
 
             if (u->sink->thread_info.rewind_nbytes > 0)
@@ -982,7 +994,7 @@ static void thread_func(void *userdata) {
             goto finish;
 
         /* Tell ALSA about this and process its response */
-        if (PA_SINK_OPENED(u->sink->thread_info.state)) {
+        if (PA_SINK_IS_OPENED(u->sink->thread_info.state)) {
             struct pollfd *pollfd;
             unsigned short revents = 0;
             int err;
diff --git a/src/modules/module-alsa-source.c b/src/modules/module-alsa-source.c
index 3c6b8db..9eb6f06 100644
--- a/src/modules/module-alsa-source.c
+++ b/src/modules/module-alsa-source.c
@@ -621,7 +621,7 @@ static int source_process_msg(pa_msgobject *o, int code, void *data, int64_t off
             switch ((pa_source_state_t) PA_PTR_TO_UINT(data)) {
 
                 case PA_SOURCE_SUSPENDED:
-                    pa_assert(PA_SOURCE_OPENED(u->source->thread_info.state));
+                    pa_assert(PA_SOURCE_IS_OPENED(u->source->thread_info.state));
 
                     if (suspend(u) < 0)
                         return -1;
@@ -819,7 +819,7 @@ static void thread_func(void *userdata) {
         pa_log_debug("loop");
 
         /* Read some data and pass it to the sources */
-        if (PA_SOURCE_OPENED(u->source->thread_info.state)) {
+        if (PA_SOURCE_IS_OPENED(u->source->thread_info.state)) {
             int work_done = 0;
 
             if (u->use_mmap)
@@ -867,7 +867,7 @@ static void thread_func(void *userdata) {
             goto finish;
 
         /* Tell ALSA about this and process its response */
-        if (PA_SOURCE_OPENED(u->source->thread_info.state)) {
+        if (PA_SOURCE_IS_OPENED(u->source->thread_info.state)) {
             struct pollfd *pollfd;
             unsigned short revents = 0;
             int err;
diff --git a/src/modules/module-combine.c b/src/modules/module-combine.c
index e15654f..2409ef8 100644
--- a/src/modules/module-combine.c
+++ b/src/modules/module-combine.c
@@ -162,13 +162,13 @@ static void adjust_rates(struct userdata *u) {
     if (!u->master)
         return;
 
-    if (!PA_SINK_OPENED(pa_sink_get_state(u->sink)))
+    if (!PA_SINK_IS_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)))
+        if (!o->sink_input || !PA_SINK_IS_OPENED(pa_sink_get_state(o->sink)))
             continue;
 
         sink_latency = pa_sink_get_latency(o->sink);
@@ -194,7 +194,7 @@ static void adjust_rates(struct userdata *u) {
     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)))
+        if (!o->sink_input || !PA_SINK_IS_OPENED(pa_sink_get_state(o->sink)))
             continue;
 
         if (o->total_latency < target_latency)
@@ -258,7 +258,10 @@ static void thread_func(void *userdata) {
             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);
+                pa_memchunk chunk;
+
+                pa_sink_render_full(u->sink, u->block_size, &chunk);
+                pa_memblock_unref(chunk.memblock);
 
                 if (!u->thread_info.in_null_mode)
                     u->thread_info.timestamp = now;
@@ -432,7 +435,7 @@ static int sink_input_process_msg(pa_msgobject *obj, int code, void *data, int64
 
         case SINK_INPUT_MESSAGE_POST:
 
-            if (PA_SINK_OPENED(o->sink_input->sink->thread_info.state))
+            if (PA_SINK_IS_OPENED(o->sink_input->sink->thread_info.state))
                 pa_memblockq_push_align(o->memblockq, chunk);
             else
                 pa_memblockq_flush(o->memblockq);
@@ -471,7 +474,7 @@ static void enable_output(struct output *o) {
 
         pa_sink_input_put(o->sink_input);
 
-        if (o->userdata->sink && PA_SINK_LINKED(pa_sink_get_state(o->userdata->sink)))
+        if (o->userdata->sink && PA_SINK_IS_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);
     }
 }
@@ -504,7 +507,7 @@ static void unsuspend(struct userdata *u) {
 
         pa_sink_suspend(o->sink, FALSE);
 
-        if (PA_SINK_OPENED(pa_sink_get_state(o->sink)))
+        if (PA_SINK_IS_OPENED(pa_sink_get_state(o->sink)))
             enable_output(o);
     }
 
@@ -525,7 +528,7 @@ static int sink_set_state(pa_sink *sink, pa_sink_state_t state) {
 
     switch (state) {
         case PA_SINK_SUSPENDED:
-            pa_assert(PA_SINK_OPENED(pa_sink_get_state(u->sink)));
+            pa_assert(PA_SINK_IS_OPENED(pa_sink_get_state(u->sink)));
 
             suspend(u);
             break;
@@ -697,7 +700,7 @@ static void pick_master(struct userdata *u, struct output *except) {
     if (u->master &&
         u->master != except &&
         u->master->sink_input &&
-        PA_SINK_OPENED(pa_sink_get_state(u->master->sink))) {
+        PA_SINK_IS_OPENED(pa_sink_get_state(u->master->sink))) {
         update_master(u, u->master);
         return;
     }
@@ -705,7 +708,7 @@ static void pick_master(struct userdata *u, struct output *except) {
     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))) {
+            PA_SINK_IS_OPENED(pa_sink_get_state(o->sink))) {
             update_master(u, o);
             return;
         }
@@ -780,7 +783,7 @@ static struct output *output_new(struct userdata *u, pa_sink *sink) {
 
     pa_assert_se(pa_idxset_put(u->outputs, o, NULL) == 0);
 
-    if (u->sink && PA_SINK_LINKED(pa_sink_get_state(u->sink)))
+    if (u->sink && PA_SINK_IS_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 */
@@ -792,10 +795,10 @@ static struct output *output_new(struct userdata *u, pa_sink *sink) {
                 o->outq);
     }
 
-    if (PA_SINK_OPENED(pa_sink_get_state(u->sink)) || pa_sink_get_state(u->sink) == PA_SINK_INIT) {
+    if (PA_SINK_IS_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 (PA_SINK_IS_OPENED(pa_sink_get_state(sink)))
             if (output_create_sink_input(o) < 0)
                 goto fail;
     }
@@ -898,7 +901,7 @@ static pa_hook_result_t sink_state_changed_hook_cb(pa_core *c, pa_sink *s, struc
 
     state = pa_sink_get_state(s);
 
-    if (PA_SINK_OPENED(state) && PA_SINK_OPENED(pa_sink_get_state(u->sink)) && !o->sink_input) {
+    if (PA_SINK_IS_OPENED(state) && PA_SINK_IS_OPENED(pa_sink_get_state(u->sink)) && !o->sink_input) {
         enable_output(o);
         pick_master(u, NULL);
     }
diff --git a/src/modules/module-default-device-restore.c b/src/modules/module-default-device-restore.c
index b550ae7..a7fc3a3 100644
--- a/src/modules/module-default-device-restore.c
+++ b/src/modules/module-default-device-restore.c
@@ -3,7 +3,7 @@
 /***
   This file is part of PulseAudio.
 
-  Copyright 2006 Lennart Poettering
+  Copyright 2006-2008 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
@@ -25,10 +25,16 @@
 #include <config.h>
 #endif
 
+#include <errno.h>
+#include <stdio.h>
+
+#include <pulse/timeval.h>
+
 #include <pulsecore/core-util.h>
 #include <pulsecore/module.h>
 #include <pulsecore/log.h>
 #include <pulsecore/namereg.h>
+#include <pulsecore/core-error.h>
 
 #include "module-default-device-restore-symdef.h"
 
@@ -39,15 +45,24 @@ PA_MODULE_LOAD_ONCE(TRUE);
 
 #define DEFAULT_SINK_FILE "default-sink"
 #define DEFAULT_SOURCE_FILE "default-source"
+#define DEFAULT_SAVE_INTERVAL 5
 
-int pa__init(pa_module *m) {
+struct userdata {
+    pa_core *core;
+    pa_subscription *subscription;
+    pa_time_event *time_event;
+    char *sink_filename, *source_filename;
+    pa_bool_t modified;
+};
+
+static void load(struct userdata *u) {
     FILE *f;
 
     /* We never overwrite manually configured settings */
 
-    if (m->core->default_sink_name)
+    if (u->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"))) {
+    else if ((f = fopen(u->sink_filename, "r"))) {
         char ln[256] = "";
 
         fgets(ln, sizeof(ln)-1, f);
@@ -55,17 +70,19 @@ int pa__init(pa_module *m) {
         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);
+            pa_log_info("No previous default sink setting, ignoring.");
+        else if (pa_namereg_get(u->core, ln, PA_NAMEREG_SINK, TRUE)) {
+            pa_namereg_set_default(u->core, ln, PA_NAMEREG_SINK);
+            pa_log_info("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)
+    } else if (errno != ENOENT)
+        pa_log("Failed to load default sink: %s", pa_cstrerror(errno));
+
+    if (u->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"))) {
+    else if ((f = fopen(u->source_filename, "r"))) {
         char ln[256] = "";
 
         fgets(ln, sizeof(ln)-1, f);
@@ -73,29 +90,114 @@ int pa__init(pa_module *m) {
         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);
+            pa_log_info("No previous default source setting, ignoring.");
+        else if (pa_namereg_get(u->core, ln, PA_NAMEREG_SOURCE, TRUE)) {
+            pa_namereg_set_default(u->core, ln, PA_NAMEREG_SOURCE);
+            pa_log_info("Restored default source '%s'.", ln);
         } else
             pa_log_info("Saved default source '%s' not existant, not restoring default source setting.", ln);
-    }
 
-    return 0;
+    } else if (errno != ENOENT)
+            pa_log("Failed to load default sink: %s", pa_cstrerror(errno));
 }
 
-void pa__done(pa_module*m) {
+static void save(struct userdata *u) {
     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 (!u->modified)
+        return;
+
+    if (u->sink_filename) {
+        if ((f = fopen(u->sink_filename, "w"))) {
+            const char *n = pa_namereg_get_default_sink_name(u->core);
+            fprintf(f, "%s\n", pa_strempty(n));
+            fclose(f);
+        } else
+            pa_log("Failed to save default sink: %s", pa_cstrerror(errno));
     }
 
-    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);
+    if (u->source_filename) {
+        if ((f = fopen(u->source_filename, "w"))) {
+            const char *n = pa_namereg_get_default_source_name(u->core);
+            fprintf(f, "%s\n", pa_strempty(n));
+            fclose(f);
+        } else
+            pa_log("Failed to save default source: %s", pa_cstrerror(errno));
+    }
+
+    u->modified = FALSE;
+}
+
+static void time_cb(pa_mainloop_api *a, pa_time_event *e, const struct timeval *tv, void *userdata) {
+    struct userdata *u = userdata;
+
+    pa_assert(u);
+    save(u);
+
+    if (u->time_event) {
+        u->core->mainloop->time_free(u->time_event);
+        u->time_event = NULL;
+    }
+}
+
+static void subscribe_cb(pa_core *c, pa_subscription_event_type_t t, uint32_t idx, void *userdata) {
+    struct userdata *u = userdata;
+
+    pa_assert(u);
+
+    u->modified = TRUE;
+
+    if (!u->time_event) {
+        struct timeval tv;
+        pa_gettimeofday(&tv);
+        pa_timeval_add(&tv, DEFAULT_SAVE_INTERVAL*PA_USEC_PER_SEC);
+        u->time_event = u->core->mainloop->time_new(u->core->mainloop, &tv, time_cb, u);
     }
 }
+
+int pa__init(pa_module *m) {
+    struct userdata *u;
+
+    pa_assert(u);
+
+    u = pa_xnew0(struct userdata, 1);
+    u->core = m->core;
+
+    if (!(u->sink_filename = pa_runtime_path(DEFAULT_SINK_FILE)))
+        goto fail;
+
+    if (!(u->source_filename = pa_runtime_path(DEFAULT_SOURCE_FILE)))
+        goto fail;
+
+    load(u);
+
+    u->subscription = pa_subscription_new(u->core, PA_SUBSCRIPTION_MASK_SERVER, subscribe_cb, u);
+
+    return 0;
+
+fail:
+    pa__done(m);
+
+    return -1;
+}
+
+void pa__done(pa_module*m) {
+    struct userdata *u;
+
+    pa_assert(m);
+
+    if (!(u = m->userdata))
+        return;
+
+    save(u);
+
+    if (u->subscription)
+        pa_subscription_free(u->subscription);
+
+    if (u->time_event)
+        m->core->mainloop->time_free(u->time_event);
+
+    pa_xfree(u->sink_filename);
+    pa_xfree(u->source_filename);
+    pa_xfree(u);
+}
diff --git a/src/modules/module-device-restore.c b/src/modules/module-device-restore.c
index 27c69f3..0a41b84 100644
--- a/src/modules/module-device-restore.c
+++ b/src/modules/module-device-restore.c
@@ -263,7 +263,7 @@ static pa_hook_result_t source_fixate_hook_callback(pa_core *c, pa_source_new_da
 int pa__init(pa_module*m) {
     pa_modargs *ma = NULL;
     struct userdata *u;
-    char *fname, *state_dir;
+    char *fname, *runtime_dir;
     char hn[256];
     pa_sink *sink;
     pa_source *source;
@@ -290,11 +290,11 @@ int pa__init(pa_module*m) {
     if (!pa_get_host_name(hn, sizeof(hn)))
         goto fail;
 
-    if (!(state_dir = pa_get_state_dir()))
+    if (!(runtime_dir = pa_get_runtime_dir()))
         goto fail;
 
-    fname = pa_sprintf_malloc("%s/device-volumes.%s.gdbm", state_dir, hn);
-    pa_xfree(state_dir);
+    fname = pa_sprintf_malloc("%s/device-volumes.%s.gdbm", runtime_dir, hn);
+    pa_xfree(runtime_dir);
 
     if (!(u->gdbm_file = gdbm_open(fname, 0, GDBM_WRCREAT, 0600, NULL))) {
         pa_log("Failed to open volume database '%s': %s", fname, gdbm_strerror(gdbm_errno));
@@ -316,6 +316,7 @@ int pa__init(pa_module*m) {
 
 fail:
     pa__done(m);
+
     if (ma)
         pa_modargs_free(ma);
 
diff --git a/src/modules/module-esound-sink.c b/src/modules/module-esound-sink.c
index 9a4ba58..2206e2b 100644
--- a/src/modules/module-esound-sink.c
+++ b/src/modules/module-esound-sink.c
@@ -143,7 +143,7 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
             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_assert(PA_SINK_IS_OPENED(u->sink->thread_info.state));
 
                     pa_smoother_pause(u->smoother, pa_rtclock_usec());
                     break;
@@ -211,7 +211,7 @@ static void thread_func(void *userdata) {
             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) {
+            if (PA_SINK_IS_OPENED(u->sink->thread_info.state) && pollfd->revents) {
                 pa_usec_t usec;
                 int64_t n;
 
@@ -294,7 +294,7 @@ static void thread_func(void *userdata) {
             }
 
             /* Hmm, nothing to do. Let's sleep */
-            pollfd->events = PA_SINK_OPENED(u->sink->thread_info.state)  ? POLLOUT : 0;
+            pollfd->events = PA_SINK_IS_OPENED(u->sink->thread_info.state)  ? POLLOUT : 0;
         }
 
         if ((ret = pa_rtpoll_run(u->rtpoll, TRUE)) < 0)
diff --git a/src/modules/module-ladspa-sink.c b/src/modules/module-ladspa-sink.c
index aa398a2..6e0faac 100644
--- a/src/modules/module-ladspa-sink.c
+++ b/src/modules/module-ladspa-sink.c
@@ -102,10 +102,14 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
         case PA_SINK_MESSAGE_GET_LATENCY: {
             pa_usec_t usec = 0;
 
+            /* Get the latency of the master sink */
             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) */;
+            /* Add the latency internal to our sink input on top */
+            usec += pa_bytes_to_usec(pa_memblockq_get_length(u->sink_input->thread_info.render_memblockq), &u->master->sample_spec);
+
+            *((pa_usec_t*) data) = usec;
             return 0;
         }
     }
@@ -120,7 +124,10 @@ static int sink_set_state(pa_sink *s, pa_sink_state_t state) {
     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)))
+    if (PA_SINK_IS_LINKED(state) &&
+        u->sink_input &&
+        PA_SINK_INPUT_IS_LINKED(pa_sink_input_get_state(u->sink_input)))
+
         pa_sink_input_cork(u->sink_input, state == PA_SINK_SUSPENDED);
 
     return 0;
@@ -134,7 +141,7 @@ static void sink_request_rewind(pa_sink *s) {
     pa_assert_se(u = s->userdata);
 
     /* Just hand this one over to the master sink */
-    pa_sink_input_request_rewind(u->sink_input, s->thread_info.rewind_nbytes, FALSE);
+    pa_sink_input_request_rewind(u->sink_input, s->thread_info.rewind_nbytes, FALSE, FALSE);
 }
 
 /* Called from I/O thread context */
@@ -145,24 +152,9 @@ static void sink_update_requested_latency(pa_sink *s) {
     pa_assert_se(u = s->userdata);
 
     /* Just hand this one over to the master sink */
-    u->sink_input->thread_info.requested_sink_latency = pa_sink_get_requested_latency_within_thread(s);
-    pa_sink_invalidate_requested_latency(u->master);
-}
-
-/* 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) = 0 /*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);
+    pa_sink_input_set_requested_latency_within_thread(
+            u->sink_input,
+            pa_sink_get_requested_latency_within_thread(s));
 }
 
 /* Called from I/O thread context */
@@ -192,20 +184,9 @@ static int sink_input_pop_cb(pa_sink_input *i, size_t nbytes, pa_memchunk *chunk
     dst = (float*) pa_memblock_acquire(chunk->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 = PA_CLAMP_UNLIKELY(*p, -1.0, 1.0);
-
+        pa_sample_clamp(PA_SAMPLE_FLOAT32NE, u->input, sizeof(float), src+c, u->channels*sizeof(float), n);
         u->descriptor->run(u->handle[c], n);
-
-        q = u->output;
-        p = dst + c;
-        for (j = 0; j < n; j++, q++, p += u->channels)
-            *p = PA_CLAMP_UNLIKELY(*q, -1.0, 1.0);
+        pa_sample_clamp(PA_SAMPLE_FLOAT32NE, dst+c, u->channels*sizeof(float), u->output, sizeof(float), n);
     }
 
     pa_memblock_release(tchunk.memblock);
@@ -245,6 +226,9 @@ static void sink_input_detach_cb(pa_sink_input *i) {
     pa_assert_se(u = i->userdata);
 
     pa_sink_detach_within_thread(u->sink);
+
+    pa_sink_set_asyncmsgq(u->sink, NULL);
+    pa_sink_set_rtpoll(u->sink, NULL);
 }
 
 /* Called from I/O thread context */
@@ -648,7 +632,6 @@ int pa__init(pa_module*m) {
     if (!u->sink_input)
         goto fail;
 
-    u->sink_input->parent.process_msg = sink_input_process_msg;
     u->sink_input->pop = sink_input_pop_cb;
     u->sink_input->process_rewind = sink_input_process_rewind_cb;
     u->sink_input->update_max_rewind = sink_input_update_max_rewind_cb;
diff --git a/src/modules/module-match.c b/src/modules/module-match.c
index 0411dcd..d026545 100644
--- a/src/modules/module-match.c
+++ b/src/modules/module-match.c
@@ -82,12 +82,14 @@ static int load_rules(struct userdata *u, const char *filename) {
 
     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");
+    if (filename)
+        f = fopen(fn = pa_xstrdup(filename), "r");
+    else
+        f = pa_open_config_file(DEFAULT_MATCH_TABLE_FILE, DEFAULT_MATCH_TABLE_FILE_USER, NULL, &fn);
 
     if (!f) {
-        pa_log("failed to open file '%s': %s", fn, pa_cstrerror(errno));
+        pa_xfree(fn);
+        pa_log("Failed to open file config file: %s", pa_cstrerror(errno));
         goto finish;
     }
 
diff --git a/src/modules/module-null-sink.c b/src/modules/module-null-sink.c
index 2301f08..606b87d 100644
--- a/src/modules/module-null-sink.c
+++ b/src/modules/module-null-sink.c
@@ -3,7 +3,7 @@
 /***
   This file is part of PulseAudio.
 
-  Copyright 2004-2006 Lennart Poettering
+  Copyright 2004-2008 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
@@ -64,6 +64,7 @@ PA_MODULE_USAGE(
         "description=<description for the sink>");
 
 #define DEFAULT_SINK_NAME "null"
+#define MAX_LATENCY_USEC (PA_USEC_PER_SEC * 2)
 
 struct userdata {
     pa_core *core;
@@ -76,7 +77,8 @@ struct userdata {
 
     size_t block_size;
 
-    struct timeval timestamp;
+    pa_usec_t block_usec;
+    pa_usec_t timestamp;
 };
 
 static const char* const valid_modargs[] = {
@@ -96,26 +98,93 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
         case PA_SINK_MESSAGE_SET_STATE:
 
             if (PA_PTR_TO_UINT(data) == PA_SINK_RUNNING)
-                pa_rtclock_get(&u->timestamp);
+                u->timestamp = pa_rtclock_usec();
 
             break;
 
         case PA_SINK_MESSAGE_GET_LATENCY: {
-            struct timeval now;
+            pa_usec_t now;
 
-            pa_rtclock_get(&now);
+            now = pa_rtclock_usec();
+            *((pa_usec_t*) data) = u->timestamp > now ? u->timestamp - now : 0;
 
-            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 0;
         }
     }
 
     return pa_sink_process_msg(o, code, data, offset, chunk);
 }
 
+static void sink_update_requested_latency_cb(pa_sink *s) {
+    struct userdata *u;
+
+    pa_sink_assert_ref(s);
+    u = s->userdata;
+    pa_assert(u);
+
+    u->block_usec = pa_sink_get_requested_latency_within_thread(s);
+}
+
+static void process_rewind(struct userdata *u, pa_usec_t now) {
+    size_t rewind_nbytes, in_buffer;
+    pa_usec_t delay;
+
+    pa_assert(u);
+
+    /* Figure out how much we shall rewind and reset the counter */
+    rewind_nbytes = u->sink->thread_info.rewind_nbytes;
+    u->sink->thread_info.rewind_nbytes = 0;
+
+    pa_assert(rewind_nbytes > 0);
+    pa_log_debug("Requested to rewind %lu bytes.", (unsigned long) rewind_nbytes);
+
+    if (u->timestamp <= now)
+        return;
+
+    delay = u->timestamp - now;
+    in_buffer = pa_usec_to_bytes(delay, &u->sink->sample_spec);
+
+    if (in_buffer <= 0)
+        return;
+
+    if (rewind_nbytes > in_buffer)
+        rewind_nbytes = in_buffer;
+
+    pa_sink_process_rewind(u->sink, rewind_nbytes);
+    u->timestamp -= pa_bytes_to_usec(rewind_nbytes, &u->sink->sample_spec);
+
+    pa_log_debug("Rewound %lu bytes.", (unsigned long) rewind_nbytes);
+}
+
+static void process_render(struct userdata *u, pa_usec_t now) {
+    size_t nbytes;
+    size_t ate = 0;
+
+    /* This is the configured latency. Sink inputs connected to us
+    might not have a single frame more than this value queued. Hence:
+    at maximum read this many bytes from the sink inputs. */
+
+    nbytes = pa_usec_to_bytes(u->block_usec, &u->sink->sample_spec);
+
+    /* Fill the buffer up the the latency size */
+    while (u->timestamp < now + u->block_usec) {
+        pa_memchunk chunk;
+
+        pa_sink_render(u->sink, nbytes, &chunk);
+        pa_memblock_unref(chunk.memblock);
+
+        pa_log_debug("Ate %lu bytes.", (unsigned long) chunk.length);
+        u->timestamp += pa_bytes_to_usec(chunk.length, &u->sink->sample_spec);
+
+        ate += chunk.length;
+
+        if (ate >= nbytes)
+            break;
+    }
+
+    pa_log_debug("Ate in sum %lu bytes (of %lu)", (unsigned long) ate, (unsigned long) nbytes);
+}
+
 static void thread_func(void *userdata) {
     struct userdata *u = userdata;
 
@@ -126,23 +195,24 @@ static void thread_func(void *userdata) {
     pa_thread_mq_install(&u->thread_mq);
     pa_rtpoll_install(u->rtpoll);
 
-    pa_rtclock_get(&u->timestamp);
+    u->timestamp = pa_rtclock_usec();
 
     for (;;) {
         int ret;
 
         /* Render some data and drop it immediately */
         if (u->sink->thread_info.state == PA_SINK_RUNNING) {
-            struct timeval now;
+            pa_usec_t now;
 
-            pa_rtclock_get(&now);
+            now = pa_rtclock_usec();
 
-            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));
-            }
+            if (u->sink->thread_info.rewind_nbytes > 0)
+                process_rewind(u, now);
 
-            pa_rtpoll_set_timer_absolute(u->rtpoll, &u->timestamp);
+            if (u->timestamp <= now)
+                process_render(u, now);
+
+            pa_rtpoll_set_timer_absolute(u->rtpoll, u->timestamp);
         } else
             pa_rtpoll_set_timer_disabled(u->rtpoll);
 
@@ -197,26 +267,26 @@ int pa__init(pa_module*m) {
     pa_sink_new_data_set_name(&data, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME));
     pa_sink_new_data_set_sample_spec(&data, &ss);
     pa_sink_new_data_set_channel_map(&data, &map);
-    pa_proplist_sets(data.proplist, PA_PROP_DEVICE_DESCRIPTION, pa_modargs_get_value(ma, "description", "NULL sink"));
+    pa_proplist_sets(data.proplist, PA_PROP_DEVICE_DESCRIPTION, pa_modargs_get_value(ma, "description", "Null Output"));
 
-    u->sink = pa_sink_new(m->core, &data, 0);
+    u->sink = pa_sink_new(m->core, &data, PA_SINK_LATENCY);
     pa_sink_new_data_done(&data);
 
     if (!u->sink) {
-        pa_log("Failed to create sink.");
+        pa_log("Failed to create sink object.");
         goto fail;
     }
 
     u->sink->parent.process_msg = sink_process_msg;
+    u->sink->update_requested_latency = sink_update_requested_latency_cb;
     u->sink->userdata = u;
-    u->sink->flags = PA_SINK_LATENCY;
 
     pa_sink_set_asyncmsgq(u->sink, u->thread_mq.inq);
     pa_sink_set_rtpoll(u->sink, u->rtpoll);
 
-    u->block_size = pa_bytes_per_second(&ss) / 20; /* 50 ms */
-    if (u->block_size <= 0)
-        u->block_size = pa_frame_size(&ss);
+    u->block_usec = u->sink->max_latency = MAX_LATENCY_USEC;
+
+    u->sink->thread_info.max_rewind = pa_usec_to_bytes(u->block_usec, &u->sink->sample_spec);
 
     if (!(u->thread = pa_thread_new(thread_func, u))) {
         pa_log("Failed to create thread.");
diff --git a/src/modules/module-oss.c b/src/modules/module-oss.c
index f07d82a..3dd4508 100644
--- a/src/modules/module-oss.c
+++ b/src/modules/module-oss.c
@@ -161,10 +161,10 @@ static void trigger(struct userdata *u, pa_bool_t quick) {
 
      pa_log_debug("trigger");
 
-    if (u->source && PA_SOURCE_OPENED(u->source->thread_info.state))
+    if (u->source && PA_SOURCE_IS_OPENED(u->source->thread_info.state))
         enable_bits |= PCM_ENABLE_INPUT;
 
-    if (u->sink && PA_SINK_OPENED(u->sink->thread_info.state))
+    if (u->sink && PA_SINK_IS_OPENED(u->sink->thread_info.state))
         enable_bits |= PCM_ENABLE_OUTPUT;
 
     pa_log_debug("trigger: %i", enable_bits);
@@ -202,7 +202,7 @@ static void trigger(struct userdata *u, pa_bool_t quick) {
              * register the fd as ready.
              */
 
-            if (u->source && PA_SOURCE_OPENED(u->source->thread_info.state)) {
+            if (u->source && PA_SOURCE_IS_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);
@@ -641,7 +641,7 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
             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_assert(PA_SINK_IS_OPENED(u->sink->thread_info.state));
 
                     if (!u->source || u->source_suspended) {
                         if (suspend(u) < 0)
@@ -658,7 +658,7 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
 
                     if (u->sink->thread_info.state == PA_SINK_INIT) {
                         do_trigger = TRUE;
-                        quick = u->source && PA_SOURCE_OPENED(u->source->thread_info.state);
+                        quick = u->source && PA_SOURCE_IS_OPENED(u->source->thread_info.state);
                     }
 
                     if (u->sink->thread_info.state == PA_SINK_SUSPENDED) {
@@ -721,7 +721,7 @@ static int source_process_msg(pa_msgobject *o, int code, void *data, int64_t off
 
             switch ((pa_source_state_t) PA_PTR_TO_UINT(data)) {
                 case PA_SOURCE_SUSPENDED:
-                    pa_assert(PA_SOURCE_OPENED(u->source->thread_info.state));
+                    pa_assert(PA_SOURCE_IS_OPENED(u->source->thread_info.state));
 
                     if (!u->sink || u->sink_suspended) {
                         if (suspend(u) < 0)
@@ -738,7 +738,7 @@ static int source_process_msg(pa_msgobject *o, int code, void *data, int64_t off
 
                     if (u->source->thread_info.state == PA_SOURCE_INIT) {
                         do_trigger = TRUE;
-                        quick = u->sink && PA_SINK_OPENED(u->sink->thread_info.state);
+                        quick = u->sink && PA_SINK_IS_OPENED(u->sink->thread_info.state);
                     }
 
                     if (u->source->thread_info.state == PA_SOURCE_SUSPENDED) {
@@ -877,7 +877,7 @@ static void thread_func(void *userdata) {
 
         /* 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->sink && PA_SINK_IS_OPENED(u->sink->thread_info.state) && ((revents & POLLOUT) || u->use_mmap || u->use_getospace)) {
 
             if (u->use_mmap) {
 
@@ -985,7 +985,7 @@ static void thread_func(void *userdata) {
 
         /* 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->source && PA_SOURCE_IS_OPENED(u->source->thread_info.state) && ((revents & POLLIN) || u->use_mmap || u->use_getispace)) {
 
             if (u->use_mmap) {
 
@@ -1095,8 +1095,8 @@ static void thread_func(void *userdata) {
 
             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);
+                ((u->source && PA_SOURCE_IS_OPENED(u->source->thread_info.state)) ? POLLIN : 0) |
+                ((u->sink && PA_SINK_IS_OPENED(u->sink->thread_info.state)) ? POLLOUT : 0);
         }
 
         /* Hmm, nothing to do. Let's sleep */
diff --git a/src/modules/module-protocol-stub.c b/src/modules/module-protocol-stub.c
index 600201b..8bcc19b 100644
--- a/src/modules/module-protocol-stub.c
+++ b/src/modules/module-protocol-stub.c
@@ -215,15 +215,6 @@ int pa__init(pa_module*m) {
 #else
     pa_socket_server *s;
     int r;
-    char tmp[PATH_MAX];
-
-#if defined(USE_PROTOCOL_ESOUND)
-#if defined(USE_PER_USER_ESOUND_SOCKET)
-    char esdsocketpath[PATH_MAX];
-#else
-    const char esdsocketpath[] = "/tmp/.esd/socket";
-#endif
-#endif
 #endif
 
     pa_assert(m);
@@ -255,27 +246,28 @@ int pa__init(pa_module*m) {
         goto fail;
 
     if (s_ipv4)
-        if (!(u->protocol_ipv4 = protocol_new(m->core, s_ipv4, m, ma)))
-            pa_socket_server_unref(s_ipv4);
-
+        u->protocol_ipv4 = protocol_new(m->core, s_ipv4, m, ma);
     if (s_ipv6)
-        if (!(u->protocol_ipv6 = protocol_new(m->core, s_ipv6, m, ma)))
-            pa_socket_server_unref(s_ipv6);
+        u->protocol_ipv6 = protocol_new(m->core, s_ipv6, m, ma);
 
     if (!u->protocol_ipv4 && !u->protocol_ipv6)
         goto fail;
 
+    if (s_ipv6)
+        pa_socket_server_unref(s_ipv6);
+    if (s_ipv6)
+        pa_socket_server_unref(s_ipv4);
+
 #else
 
 #if defined(USE_PROTOCOL_ESOUND)
 
 #if defined(USE_PER_USER_ESOUND_SOCKET)
-    snprintf(esdsocketpath, sizeof(esdsocketpath), "/tmp/.esd-%lu/socket", (unsigned long) getuid());
+    u->socket_path = pa_sprintf_malloc("/tmp/.esd-%lu/socket", (unsigned long) getuid());
+#else
+    u->socket_path = pa_xstrdup("/tmp/.esd/socket");
 #endif
 
-    pa_runtime_path(pa_modargs_get_value(ma, "socket", esdsocketpath), 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 */
 
@@ -285,24 +277,26 @@ int pa__init(pa_module*m) {
     }
 
 #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) {
-        pa_log("Failed to remove stale UNIX socket '%s': %s", tmp, pa_cstrerror(errno));
+    if (!(u->socket_path = pa_runtime_path(pa_modargs_get_value(ma, "socket", UNIX_SOCKET)))) {
+        pa_log("Failed to generate socket path.");
         goto fail;
     }
+#endif
 
-    if (r)
-        pa_log("Removed stale UNIX socket '%s'.", tmp);
+    if ((r = pa_unix_socket_remove_stale(u->socket_path)) < 0) {
+        pa_log("Failed to remove stale UNIX socket '%s': %s", u->socket_path, pa_cstrerror(errno));
+        goto fail;
+    } else if (r > 0)
+        pa_log_info("Removed stale UNIX socket '%s'.", u->socket_path);
 
-    if (!(s = pa_socket_server_new_unix(m->core->mainloop, tmp)))
+    if (!(s = pa_socket_server_new_unix(m->core->mainloop, u->socket_path)))
         goto fail;
 
     if (!(u->protocol_unix = protocol_new(m->core, s, m, ma)))
         goto fail;
 
+    pa_socket_server_unref(s);
+
 #endif
 
     m->userdata = u;
@@ -325,23 +319,21 @@ fail:
 #else
         if (u->protocol_unix)
             protocol_free(u->protocol_unix);
-
-        if (u->socket_path)
-            pa_xfree(u->socket_path);
+        pa_xfree(u->socket_path);
 #endif
 
         pa_xfree(u);
-    } else {
+    }
+
 #if defined(USE_TCP_SOCKETS)
-        if (s_ipv4)
-            pa_socket_server_unref(s_ipv4);
-        if (s_ipv6)
-            pa_socket_server_unref(s_ipv6);
+    if (s_ipv4)
+        pa_socket_server_unref(s_ipv4);
+    if (s_ipv6)
+        pa_socket_server_unref(s_ipv6);
 #else
-        if (s)
-            pa_socket_server_unref(s);
+    if (s)
+        pa_socket_server_unref(s);
 #endif
-    }
 
     goto finish;
 }
@@ -362,7 +354,7 @@ void pa__done(pa_module*m) {
     if (u->protocol_unix)
         protocol_free(u->protocol_unix);
 
-#if defined(USE_PROTOCOL_ESOUND)
+#if defined(USE_PROTOCOL_ESOUND) && !defined(USE_PER_USER_ESOUND_SOCKET)
     if (u->socket_path) {
         char *p = pa_parent_dir(u->socket_path);
         rmdir(p);
diff --git a/src/modules/module-remap-sink.c b/src/modules/module-remap-sink.c
index 6a16321..f68b719 100644
--- a/src/modules/module-remap-sink.c
+++ b/src/modules/module-remap-sink.c
@@ -81,10 +81,14 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
         case PA_SINK_MESSAGE_GET_LATENCY: {
             pa_usec_t usec = 0;
 
+            /* Get the latency of the master sink */
             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)*/;
+            /* Add the latency internal to our sink input on top */
+            usec += pa_bytes_to_usec(pa_memblockq_get_length(u->sink_input->thread_info.render_memblockq), &u->master->sample_spec);
+
+            *((pa_usec_t*) data) = usec;
             return 0;
         }
     }
@@ -99,7 +103,10 @@ static int sink_set_state(pa_sink *s, pa_sink_state_t state) {
     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)))
+    if (PA_SINK_IS_LINKED(state) &&
+        u->sink_input &&
+        PA_SINK_INPUT_IS_LINKED(pa_sink_input_get_state(u->sink_input)))
+
         pa_sink_input_cork(u->sink_input, state == PA_SINK_SUSPENDED);
 
     return 0;
@@ -112,7 +119,7 @@ static void sink_request_rewind(pa_sink *s) {
     pa_sink_assert_ref(s);
     pa_assert_se(u = s->userdata);
 
-    pa_sink_input_request_rewind(u->sink_input, s->thread_info.rewind_nbytes, FALSE);
+    pa_sink_input_request_rewind(u->sink_input, s->thread_info.rewind_nbytes, FALSE, FALSE);
 }
 
 /* Called from I/O thread context */
@@ -123,24 +130,9 @@ static void sink_update_requested_latency(pa_sink *s) {
     pa_assert_se(u = s->userdata);
 
     /* Just hand this one over to the master sink */
-    u->sink_input->thread_info.requested_sink_latency = pa_sink_get_requested_latency_within_thread(s);
-    pa_sink_invalidate_requested_latency(u->master);
-}
-
-/* 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) = 0; /*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);
+    pa_sink_input_set_requested_latency_within_thread(
+            u->sink_input,
+            pa_sink_get_requested_latency_within_thread(s));
 }
 
 /* Called from I/O thread context */
@@ -152,7 +144,6 @@ static int sink_input_pop_cb(pa_sink_input *i, size_t nbytes, pa_memchunk *chunk
     pa_assert_se(u = i->userdata);
 
     pa_sink_render(u->sink, nbytes, chunk);
-
     return 0;
 }
 
@@ -185,6 +176,9 @@ static void sink_input_detach_cb(pa_sink_input *i) {
     pa_assert_se(u = i->userdata);
 
     pa_sink_detach_within_thread(u->sink);
+
+    pa_sink_set_asyncmsgq(u->sink, NULL);
+    pa_sink_set_rtpoll(u->sink, NULL);
 }
 
 /* Called from I/O thread context */
@@ -317,7 +311,6 @@ int pa__init(pa_module*m) {
     if (!u->sink_input)
         goto fail;
 
-    u->sink_input->parent.process_msg = sink_input_process_msg;
     u->sink_input->pop = sink_input_pop_cb;
     u->sink_input->process_rewind = sink_input_process_rewind_cb;
     u->sink_input->update_max_rewind = sink_input_update_max_rewind_cb;
diff --git a/src/modules/module-suspend-on-idle.c b/src/modules/module-suspend-on-idle.c
index ef8239d..a398597 100644
--- a/src/modules/module-suspend-on-idle.c
+++ b/src/modules/module-suspend-on-idle.c
@@ -317,7 +317,7 @@ static pa_hook_result_t device_state_changed_hook_cb(pa_core *c, pa_object *o, s
 
         if (pa_sink_used_by(s) <= 0) {
 
-            if (PA_SINK_OPENED(state))
+            if (PA_SINK_IS_OPENED(state))
                 restart(d);
 
         }
@@ -328,7 +328,7 @@ static pa_hook_result_t device_state_changed_hook_cb(pa_core *c, pa_object *o, s
 
         if (pa_source_used_by(s) <= 0) {
 
-            if (PA_SOURCE_OPENED(state))
+            if (PA_SOURCE_IS_OPENED(state))
                 restart(d);
         }
     }
diff --git a/src/modules/module-tunnel.c b/src/modules/module-tunnel.c
index 74d5a82..e3ae5e1 100644
--- a/src/modules/module-tunnel.c
+++ b/src/modules/module-tunnel.c
@@ -303,7 +303,7 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
 
             /* First, change the state, because otherwide pa_sink_render() would fail */
             if ((r = pa_sink_process_msg(o, code, data, offset, chunk)) >= 0)
-                if (PA_SINK_OPENED((pa_sink_state_t) PA_PTR_TO_UINT(data)))
+                if (PA_SINK_IS_OPENED((pa_sink_state_t) PA_PTR_TO_UINT(data)))
                     send_data(u);
 
             return r;
@@ -314,7 +314,7 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
             pa_assert(offset > 0);
             u->requested_bytes += (size_t) offset;
 
-            if (PA_SINK_OPENED(u->sink->thread_info.state))
+            if (PA_SINK_IS_OPENED(u->sink->thread_info.state))
                 send_data(u);
 
             return 0;
@@ -343,7 +343,7 @@ static int sink_set_state(pa_sink *s, pa_sink_state_t state) {
     switch ((pa_sink_state_t) state) {
 
         case PA_SINK_SUSPENDED:
-            pa_assert(PA_SINK_OPENED(s->state));
+            pa_assert(PA_SINK_IS_OPENED(s->state));
             stream_cork(u, TRUE);
             break;
 
@@ -369,7 +369,7 @@ static int source_process_msg(pa_msgobject *o, int code, void *data, int64_t off
     switch (code) {
         case SOURCE_MESSAGE_POST:
 
-            if (PA_SOURCE_OPENED(u->source->thread_info.state))
+            if (PA_SOURCE_IS_OPENED(u->source->thread_info.state))
                 pa_source_post(u->source, chunk);
             return 0;
     }
@@ -385,7 +385,7 @@ static int source_set_state(pa_source *s, pa_source_state_t state) {
     switch ((pa_source_state_t) state) {
 
         case PA_SOURCE_SUSPENDED:
-            pa_assert(PA_SOURCE_OPENED(s->state));
+            pa_assert(PA_SOURCE_IS_OPENED(s->state));
             stream_cork(u, TRUE);
             break;
 
@@ -1066,7 +1066,7 @@ static void setup_complete_callback(pa_pdispatch *pd, uint32_t command, uint32_t
     pa_tagstruct_putu32(reply, PA_INVALID_INDEX);
     pa_tagstruct_puts(reply, u->sink_name);
     pa_tagstruct_putu32(reply, u->maxlength);
-    pa_tagstruct_put_boolean(reply, !PA_SINK_OPENED(pa_sink_get_state(u->sink)));
+    pa_tagstruct_put_boolean(reply, !PA_SINK_IS_OPENED(pa_sink_get_state(u->sink)));
     pa_tagstruct_putu32(reply, u->tlength);
     pa_tagstruct_putu32(reply, u->prebuf);
     pa_tagstruct_putu32(reply, u->minreq);
@@ -1082,7 +1082,7 @@ static void setup_complete_callback(pa_pdispatch *pd, uint32_t command, uint32_t
     pa_tagstruct_putu32(reply, PA_INVALID_INDEX);
     pa_tagstruct_puts(reply, u->source_name);
     pa_tagstruct_putu32(reply, u->maxlength);
-    pa_tagstruct_put_boolean(reply, !PA_SOURCE_OPENED(pa_source_get_state(u->source)));
+    pa_tagstruct_put_boolean(reply, !PA_SOURCE_IS_OPENED(pa_source_get_state(u->source)));
     pa_tagstruct_putu32(reply, u->fragsize);
 #endif
 
diff --git a/src/modules/module-volume-restore.c b/src/modules/module-volume-restore.c
index 0dc8dcf..336bcac 100644
--- a/src/modules/module-volume-restore.c
+++ b/src/modules/module-volume-restore.c
@@ -134,16 +134,12 @@ static int load_rules(struct userdata *u) {
     char buf_name[256], buf_volume[256], buf_sink[256], buf_source[256];
     char *ln = buf_name;
 
-    f = u->table_file ?
-        fopen(u->table_file, "r") :
-        pa_open_config_file(NULL, DEFAULT_VOLUME_TABLE_FILE, NULL, &u->table_file, "r");
-
-    if (!f) {
+    if (!(f = fopen(u->table_file, "r"))) {
         if (errno == ENOENT) {
-            pa_log_info("starting with empty ruleset.");
+            pa_log_info("Starting with empty ruleset.");
             ret = 0;
         } else
-            pa_log("failed to open file '%s': %s", u->table_file, pa_cstrerror(errno));
+            pa_log("Failed to open file '%s': %s", u->table_file, pa_cstrerror(errno));
 
         goto finish;
     }
@@ -236,11 +232,7 @@ static int save_rules(struct userdata *u) {
 
     pa_log_info("Saving rules...");
 
-    f = u->table_file ?
-        fopen(u->table_file, "w") :
-        pa_open_config_file(NULL, DEFAULT_VOLUME_TABLE_FILE, NULL, &u->table_file, "w");
-
-    if (!f) {
+    if (!(f = fopen(u->table_file, "w"))) {
         pa_log("Failed to open file '%s': %s", u->table_file, pa_cstrerror(errno));
         goto finish;
     }
@@ -496,7 +488,7 @@ int pa__init(pa_module*m) {
     u = pa_xnew(struct userdata, 1);
     u->core = m->core;
     u->hashmap = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func);
-    u->table_file = pa_xstrdup(pa_modargs_get_value(ma, "table", NULL));
+    u->table_file = pa_runtime_path(pa_modargs_get_value(ma, "table", DEFAULT_VOLUME_TABLE_FILE));
     u->modified = FALSE;
     u->subscription = NULL;
     u->sink_input_new_hook_slot = u->sink_input_fixate_hook_slot = u->source_output_new_hook_slot = NULL;
diff --git a/src/pulse/client-conf.c b/src/pulse/client-conf.c
index c054f66..75f4418 100644
--- a/src/pulse/client-conf.c
+++ b/src/pulse/client-conf.c
@@ -112,13 +112,20 @@ int pa_client_conf_load(pa_client_conf *c, const char *filename) {
     table[6].data = &c->cookie_file;
     table[7].data = &c->disable_shm;
 
-    f = filename ?
-        fopen((fn = pa_xstrdup(filename)), "r") :
-        pa_open_config_file(DEFAULT_CLIENT_CONFIG_FILE, DEFAULT_CLIENT_CONFIG_FILE_USER, ENV_CLIENT_CONFIG_FILE, &fn, "r");
+    if (filename) {
 
-    if (!f && errno != EINTR) {
-        pa_log_warn("Failed to open configuration file '%s': %s", fn, pa_cstrerror(errno));
-        goto finish;
+        if (!(f = fopen(filename, "r"))) {
+            pa_log("Failed to open configuration file '%s': %s", fn, pa_cstrerror(errno));
+            goto finish;
+        }
+
+        fn = pa_xstrdup(fn);
+
+    } else {
+
+        if (!(f = pa_open_config_file(DEFAULT_CLIENT_CONFIG_FILE, DEFAULT_CLIENT_CONFIG_FILE_USER, ENV_CLIENT_CONFIG_FILE, &fn)))
+            if (errno != ENOENT)
+                goto finish;
     }
 
     r = f ? pa_config_parse(fn, f, table, NULL) : 0;
@@ -126,7 +133,6 @@ int pa_client_conf_load(pa_client_conf *c, const char *filename) {
     if (!r)
         r = pa_client_conf_load_cookie(c);
 
-
 finish:
     pa_xfree(fn);
 
diff --git a/src/pulse/context.c b/src/pulse/context.c
index 7806e88..f9f021a 100644
--- a/src/pulse/context.c
+++ b/src/pulse/context.c
@@ -3,7 +3,7 @@
 /***
   This file is part of PulseAudio.
 
-  Copyright 2004-2006 Lennart Poettering
+  Copyright 2004-2008 Lennart Poettering
   Copyright 2006 Pierre Ossman <ossman at cendio.se> for Cendio AB
 
   PulseAudio is free software; you can redistribute it and/or modify
@@ -93,6 +93,7 @@ static const pa_pdispatch_cb_t command_table[PA_COMMAND_MAX] = {
     [PA_COMMAND_RECORD_STREAM_MOVED] = pa_command_stream_moved,
     [PA_COMMAND_PLAYBACK_STREAM_SUSPENDED] = pa_command_stream_suspended,
     [PA_COMMAND_RECORD_STREAM_SUSPENDED] = pa_command_stream_suspended,
+    [PA_COMMAND_STARTED] = pa_command_stream_started,
     [PA_COMMAND_SUBSCRIBE_EVENT] = pa_command_subscribe_event
 };
 
@@ -100,10 +101,12 @@ static void unlock_autospawn_lock_file(pa_context *c) {
     pa_assert(c);
 
     if (c->autospawn_lock_fd >= 0) {
-        char lf[PATH_MAX];
-        pa_runtime_path(AUTOSPAWN_LOCK, lf, sizeof(lf));
+        char *lf;
 
+        lf = pa_runtime_path(AUTOSPAWN_LOCK);
         pa_unlock_lockfile(lf, c->autospawn_lock_fd);
+        pa_xfree(lf);
+
         c->autospawn_lock_fd = -1;
     }
 }
@@ -114,6 +117,16 @@ pa_context *pa_context_new(pa_mainloop_api *mainloop, const char *name) {
     return pa_context_new_with_proplist(mainloop, name, NULL);
 }
 
+static void reset_callbacks(pa_context *c) {
+    pa_assert(c);
+
+    c->state_callback = NULL;
+    c->state_userdata = NULL;
+
+    c->subscribe_callback = NULL;
+    c->subscribe_userdata = NULL;
+}
+
 pa_context *pa_context_new_with_proplist(pa_mainloop_api *mainloop, const char *name, pa_proplist *p) {
     pa_context *c;
 
@@ -146,18 +159,14 @@ pa_context *pa_context_new_with_proplist(pa_mainloop_api *mainloop, const char *
     c->ctag = 0;
     c->csyncid = 0;
 
-    c->state_callback = NULL;
-    c->state_userdata = NULL;
-
-    c->subscribe_callback = NULL;
-    c->subscribe_userdata = NULL;
+    reset_callbacks(c);
 
-    c->is_local = -1;
+    c->is_local = FALSE;
     c->server_list = NULL;
     c->server = NULL;
     c->autospawn_lock_fd = -1;
     memset(&c->spawn_api, 0, sizeof(c->spawn_api));
-    c->do_autospawn = 0;
+    c->do_autospawn = FALSE;
 
 #ifndef MSG_NOSIGNAL
 #ifdef SIGPIPE
@@ -186,26 +195,48 @@ pa_context *pa_context_new_with_proplist(pa_mainloop_api *mainloop, const char *
     return c;
 }
 
-static void context_free(pa_context *c) {
+static void context_unlink(pa_context *c) {
+    pa_stream *s;
+
     pa_assert(c);
 
-    unlock_autospawn_lock_file(c);
+    s = c->streams ? pa_stream_ref(c->streams) : NULL;
+    while (s) {
+        pa_stream *n = s->next ? pa_stream_ref(s->next) : NULL;
+        pa_stream_set_state(s, c->state == PA_CONTEXT_FAILED ? PA_STREAM_FAILED : PA_STREAM_TERMINATED);
+        pa_stream_unref(s);
+        s = n;
+    }
 
     while (c->operations)
         pa_operation_cancel(c->operations);
 
-    while (c->streams)
-        pa_stream_set_state(c->streams, PA_STREAM_TERMINATED);
-
-    if (c->client)
-        pa_socket_client_unref(c->client);
-    if (c->pdispatch)
+    if (c->pdispatch) {
         pa_pdispatch_unref(c->pdispatch);
+        c->pdispatch = NULL;
+    }
+
     if (c->pstream) {
         pa_pstream_unlink(c->pstream);
         pa_pstream_unref(c->pstream);
+        c->pstream = NULL;
     }
 
+    if (c->client) {
+        pa_socket_client_unref(c->client);
+        c->client = NULL;
+    }
+
+    reset_callbacks(c);
+}
+
+static void context_free(pa_context *c) {
+    pa_assert(c);
+
+    context_unlink(c);
+
+    unlock_autospawn_lock_file(c);
+
     if (c->record_streams)
         pa_dynarray_free(c->record_streams, NULL, NULL);
     if (c->playback_streams)
@@ -252,46 +283,16 @@ void pa_context_set_state(pa_context *c, pa_context_state_t st) {
     pa_context_ref(c);
 
     c->state = st;
+
     if (c->state_callback)
         c->state_callback(c, c->state_userdata);
 
-    if (st == PA_CONTEXT_FAILED || st == PA_CONTEXT_TERMINATED) {
-        pa_stream *s;
-
-        s = c->streams ? pa_stream_ref(c->streams) : NULL;
-        while (s) {
-            pa_stream *n = s->next ? pa_stream_ref(s->next) : NULL;
-            pa_stream_set_state(s, st == PA_CONTEXT_FAILED ? PA_STREAM_FAILED : PA_STREAM_TERMINATED);
-            pa_stream_unref(s);
-            s = n;
-        }
-
-        if (c->pdispatch)
-            pa_pdispatch_unref(c->pdispatch);
-        c->pdispatch = NULL;
-
-        if (c->pstream) {
-            pa_pstream_unlink(c->pstream);
-            pa_pstream_unref(c->pstream);
-        }
-        c->pstream = NULL;
-
-        if (c->client)
-            pa_socket_client_unref(c->client);
-        c->client = NULL;
-    }
+    if (st == PA_CONTEXT_FAILED || st == PA_CONTEXT_TERMINATED)
+        context_unlink(c);
 
     pa_context_unref(c);
 }
 
-void pa_context_fail(pa_context *c, int error) {
-    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) {
     pa_assert(error >= 0);
     pa_assert(error < PA_ERR_MAX);
@@ -302,6 +303,14 @@ int pa_context_set_error(pa_context *c, int error) {
     return error;
 }
 
+void pa_context_fail(pa_context *c, int error) {
+    pa_assert(c);
+    pa_assert(PA_REFCNT_VALUE(c) >= 1);
+
+    pa_context_set_error(c, error);
+    pa_context_set_state(c, PA_CONTEXT_FAILED);
+}
+
 static void pstream_die_callback(pa_pstream *p, void *userdata) {
     pa_context *c = userdata;
 
@@ -358,25 +367,41 @@ static void pstream_memblock_callback(pa_pstream *p, uint32_t channel, int64_t o
     pa_context_unref(c);
 }
 
-int pa_context_handle_error(pa_context *c, uint32_t command, pa_tagstruct *t) {
+int pa_context_handle_error(pa_context *c, uint32_t command, pa_tagstruct *t, pa_bool_t fail) {
+    uint32_t err;
     pa_assert(c);
     pa_assert(PA_REFCNT_VALUE(c) >= 1);
 
     if (command == PA_COMMAND_ERROR) {
         pa_assert(t);
 
-        if (pa_tagstruct_getu32(t, &c->error) < 0) {
+        if (pa_tagstruct_getu32(t, &err) < 0) {
             pa_context_fail(c, PA_ERR_PROTOCOL);
             return -1;
-
         }
+
     } else if (command == PA_COMMAND_TIMEOUT)
-        c->error = PA_ERR_TIMEOUT;
+        err = PA_ERR_TIMEOUT;
     else {
         pa_context_fail(c, PA_ERR_PROTOCOL);
         return -1;
     }
 
+    if (err == PA_OK) {
+        pa_context_fail(c, PA_ERR_PROTOCOL);
+        return -1;
+    }
+
+    if (err >= PA_ERR_MAX)
+        err = PA_ERR_UNKNOWN;
+
+    if (fail) {
+        pa_context_fail(c, err);
+        return -1;
+    }
+
+    pa_context_set_error(c, err);
+
     return 0;
 }
 
@@ -390,11 +415,7 @@ static void setup_complete_callback(pa_pdispatch *pd, uint32_t command, uint32_t
     pa_context_ref(c);
 
     if (command != PA_COMMAND_REPLY) {
-
-        if (pa_context_handle_error(c, command, t) < 0)
-            pa_context_fail(c, PA_ERR_PROTOCOL);
-
-        pa_context_fail(c, c->error);
+        pa_context_handle_error(c, command, t, TRUE);
         goto finish;
     }
 
@@ -417,7 +438,7 @@ static void setup_complete_callback(pa_pdispatch *pd, uint32_t command, uint32_t
             /* Enable shared memory support if possible */
             if (c->version >= 10 &&
                 pa_mempool_is_shared(c->mempool) &&
-                c->is_local > 0) {
+                c->is_local) {
 
                 /* Only enable SHM if both sides are owned by the same
                  * user. This is a security measure because otherwise
@@ -486,7 +507,7 @@ static void setup_context(pa_context *c, pa_iochannel *io) {
     c->pdispatch = pa_pdispatch_new(c->mainloop, command_table, PA_COMMAND_MAX);
 
     if (!c->conf->cookie_valid)
-        pa_log_warn("No cookie loaded. Attempting to connect without.");
+        pa_log_info("No cookie loaded. Attempting to connect without.");
 
     t = pa_tagstruct_command(c, PA_COMMAND_AUTH, &tag);
     pa_tagstruct_putu32(t, PA_PROTOCOL_VERSION);
@@ -525,10 +546,13 @@ static int context_connect_spawn(pa_context *c) {
     int fds[2] = { -1, -1} ;
     pa_iochannel *io;
 
+    if (getuid() == 0)
+        return -1;
+
     pa_context_ref(c);
 
     if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds) < 0) {
-        pa_log("socketpair(): %s", pa_cstrerror(errno));
+        pa_log_error("socketpair(): %s", pa_cstrerror(errno));
         pa_context_fail(c, PA_ERR_INTERNAL);
         goto fail;
     }
@@ -542,7 +566,7 @@ static int context_connect_spawn(pa_context *c) {
         c->spawn_api.prefork();
 
     if ((pid = fork()) < 0) {
-        pa_log("fork(): %s", pa_cstrerror(errno));
+        pa_log_error("fork(): %s", pa_cstrerror(errno));
         pa_context_fail(c, PA_ERR_INTERNAL);
 
         if (c->spawn_api.postfork)
@@ -557,9 +581,13 @@ static int context_connect_spawn(pa_context *c) {
 #define MAX_ARGS 64
         const char * argv[MAX_ARGS+1];
         int n;
+        char *f;
+
+        pa_close_all(fds[1], -1);
 
-        /* Not required, since fds[0] has CLOEXEC enabled anyway */
-        pa_assert_se(pa_close(fds[0]) == 0);
+        f = pa_sprintf_malloc("%i", fds[1]);
+        pa_set_env("PULSE_PASSED_FD", f);
+        pa_xfree(f);
 
         if (c->spawn_api.atfork)
             c->spawn_api.atfork();
@@ -592,6 +620,8 @@ static int context_connect_spawn(pa_context *c) {
 
     /* Parent */
 
+    pa_assert_se(pa_close(fds[1]) == 0);
+
     r = waitpid(pid, &status, 0);
 
     if (c->spawn_api.postfork)
@@ -606,14 +636,12 @@ static int context_connect_spawn(pa_context *c) {
         goto fail;
     }
 
-    pa_assert_se(pa_close(fds[1]) == 0);
+    c->is_local = TRUE;
 
-    c->is_local = 1;
+    unlock_autospawn_lock_file(c);
 
     io = pa_iochannel_new(c->mainloop, fds[0], fds[0]);
-
     setup_context(c, io);
-    unlock_autospawn_lock_file(c);
 
     pa_context_unref(c);
 
@@ -665,7 +693,7 @@ static int try_next_connection(pa_context *c) {
         if (!(c->client = pa_socket_client_new_string(c->mainloop, u, PA_NATIVE_DEFAULT_PORT)))
             continue;
 
-        c->is_local = pa_socket_client_is_local(c->client);
+        c->is_local = !!pa_socket_client_is_local(c->client);
         pa_socket_client_set_callback(c->client, on_connection, c);
         break;
     }
@@ -680,6 +708,7 @@ finish:
 
 static void on_connection(pa_socket_client *client, pa_iochannel*io, void *userdata) {
     pa_context *c = userdata;
+    int saved_errno = errno;
 
     pa_assert(client);
     pa_assert(c);
@@ -692,7 +721,9 @@ static void on_connection(pa_socket_client *client, pa_iochannel*io, void *userd
 
     if (!io) {
         /* Try the item in the list */
-        if (errno == ECONNREFUSED || errno == ETIMEDOUT || errno == EHOSTUNREACH) {
+        if (saved_errno == ECONNREFUSED ||
+            saved_errno == ETIMEDOUT ||
+            saved_errno == EHOSTUNREACH) {
             try_next_connection(c);
             goto finish;
         }
@@ -708,6 +739,25 @@ finish:
     pa_context_unref(c);
 }
 
+
+static char *get_legacy_runtime_dir(void) {
+    char *p, u[128];
+    struct stat st;
+
+    if (!pa_get_user_name(u, sizeof(u)))
+        return NULL;
+
+    p = pa_sprintf_malloc("/tmp/pulse-%s", u);
+
+    if (stat(p, &st) < 0)
+        return NULL;
+
+    if (st.st_uid != getuid())
+        return NULL;
+
+    return p;
+}
+
 int pa_context_connect(
         pa_context *c,
         const char *server,
@@ -736,8 +786,8 @@ int pa_context_connect(
             goto finish;
         }
     } else {
-        char *d;
-        char ufn[PATH_MAX];
+        char *d, *ufn;
+        static char *legacy_dir;
 
         /* Prepend in reverse order */
 
@@ -757,25 +807,34 @@ int pa_context_connect(
         c->server_list = pa_strlist_prepend(c->server_list, "tcp4:localhost");
 
         /* The system wide instance */
-        c->server_list = pa_strlist_prepend(c->server_list, PA_SYSTEM_RUNTIME_PATH "/" PA_NATIVE_DEFAULT_UNIX_SOCKET);
+        c->server_list = pa_strlist_prepend(c->server_list, PA_SYSTEM_RUNTIME_PATH PA_PATH_SEP PA_NATIVE_DEFAULT_UNIX_SOCKET);
+
+        /* The old per-user instance path. This is supported only to easy upgrades */
+        if ((legacy_dir = get_legacy_runtime_dir())) {
+            char *p = pa_sprintf_malloc("%s" PA_PATH_SEP PA_NATIVE_DEFAULT_UNIX_SOCKET, legacy_dir);
+            c->server_list = pa_strlist_prepend(c->server_list, p);
+            pa_xfree(p);
+            pa_xfree(legacy_dir);
+        }
 
         /* The per-user instance */
-        c->server_list = pa_strlist_prepend(c->server_list, pa_runtime_path(PA_NATIVE_DEFAULT_UNIX_SOCKET, ufn, sizeof(ufn)));
+        c->server_list = pa_strlist_prepend(c->server_list, ufn = pa_runtime_path(PA_NATIVE_DEFAULT_UNIX_SOCKET));
+        pa_xfree(ufn);
 
         /* Wrap the connection attempts in a single transaction for sane autospawn locking */
         if (!(flags & PA_CONTEXT_NOAUTOSPAWN) && c->conf->autospawn) {
-            char lf[PATH_MAX];
+            char *lf;
 
-            pa_runtime_path(AUTOSPAWN_LOCK, lf, sizeof(lf));
-            pa_make_secure_parent_dir(lf, 0700, (uid_t)-1, (gid_t)-1);
+            lf = pa_runtime_path(AUTOSPAWN_LOCK);
             pa_assert(c->autospawn_lock_fd <= 0);
             c->autospawn_lock_fd = pa_lock_lockfile(lf);
+            pa_xfree(lf);
 
             if (api)
                 c->spawn_api = *api;
-            c->do_autospawn = 1;
-        }
 
+            c->do_autospawn = TRUE;
+        }
     }
 
     pa_context_set_state(c, PA_CONTEXT_CONNECTING);
@@ -791,7 +850,8 @@ void pa_context_disconnect(pa_context *c) {
     pa_assert(c);
     pa_assert(PA_REFCNT_VALUE(c) >= 1);
 
-    pa_context_set_state(c, PA_CONTEXT_TERMINATED);
+    if (PA_CONTEXT_IS_GOOD(c->state))
+        pa_context_set_state(c, PA_CONTEXT_TERMINATED);
 }
 
 pa_context_state_t pa_context_get_state(pa_context *c) {
@@ -812,6 +872,9 @@ void pa_context_set_state_callback(pa_context *c, pa_context_notify_cb_t cb, voi
     pa_assert(c);
     pa_assert(PA_REFCNT_VALUE(c) >= 1);
 
+    if (c->state == PA_CONTEXT_TERMINATED || c->state == PA_CONTEXT_FAILED)
+        return;
+
     c->state_callback = cb;
     c->state_userdata = userdata;
 }
@@ -820,11 +883,7 @@ int pa_context_is_pending(pa_context *c) {
     pa_assert(c);
     pa_assert(PA_REFCNT_VALUE(c) >= 1);
 
-    PA_CHECK_VALIDITY(c,
-                      c->state == PA_CONTEXT_CONNECTING ||
-                      c->state == PA_CONTEXT_AUTHORIZING ||
-                      c->state == PA_CONTEXT_SETTING_NAME ||
-                      c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
+    PA_CHECK_VALIDITY(c, PA_CONTEXT_IS_GOOD(c->state), PA_ERR_BADSTATE);
 
     return (c->pstream && pa_pstream_is_pending(c->pstream)) ||
         (c->pdispatch && pa_pdispatch_is_pending(c->pdispatch)) ||
@@ -901,7 +960,7 @@ void pa_context_simple_ack_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_U
         goto finish;
 
     if (command != PA_COMMAND_REPLY) {
-        if (pa_context_handle_error(o->context, command, t) < 0)
+        if (pa_context_handle_error(o->context, command, t, FALSE) < 0)
             goto finish;
 
         success = 0;
@@ -920,7 +979,7 @@ finish:
     pa_operation_unref(o);
 }
 
-pa_operation* pa_context_exit_daemon(pa_context *c, pa_context_success_cb_t cb, void *userdata) {
+pa_operation* pa_context_send_simple_command(pa_context *c, uint32_t command, pa_pdispatch_cb_t internal_cb, pa_operation_cb_t cb, void *userdata) {
     pa_tagstruct *t;
     pa_operation *o;
     uint32_t tag;
@@ -930,32 +989,20 @@ pa_operation* pa_context_exit_daemon(pa_context *c, pa_context_success_cb_t cb,
 
     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
 
-    o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
+    o = pa_operation_new(c, NULL, cb, userdata);
 
-    t = pa_tagstruct_command(c, PA_COMMAND_EXIT, &tag);
+    t = pa_tagstruct_command(c, command, &tag);
     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);
+    pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, internal_cb, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
 
     return o;
 }
 
-pa_operation* pa_context_send_simple_command(pa_context *c, uint32_t command, pa_pdispatch_cb_t internal_cb, pa_operation_cb_t cb, void *userdata) {
-    pa_tagstruct *t;
-    pa_operation *o;
-    uint32_t tag;
-
+pa_operation* pa_context_exit_daemon(pa_context *c, pa_context_success_cb_t cb, void *userdata) {
     pa_assert(c);
     pa_assert(PA_REFCNT_VALUE(c) >= 1);
 
-    PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
-
-    o = pa_operation_new(c, NULL, cb, userdata);
-
-    t = pa_tagstruct_command(c, command, &tag);
-    pa_pstream_send_tagstruct(c->pstream, t);
-    pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, internal_cb, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
-
-    return o;
+    return pa_context_send_simple_command(c, PA_COMMAND_EXIT, pa_context_simple_ack_callback, (pa_operation_cb_t) cb, userdata);
 }
 
 pa_operation* pa_context_set_default_sink(pa_context *c, const char *name, pa_context_success_cb_t cb, void *userdata) {
@@ -969,7 +1016,6 @@ pa_operation* pa_context_set_default_sink(pa_context *c, const char *name, pa_co
     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
 
     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
-
     t = pa_tagstruct_command(c, PA_COMMAND_SET_DEFAULT_SINK, &tag);
     pa_tagstruct_puts(t, name);
     pa_pstream_send_tagstruct(c->pstream, t);
@@ -989,7 +1035,6 @@ pa_operation* pa_context_set_default_source(pa_context *c, const char *name, pa_
     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
 
     o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
-
     t = pa_tagstruct_command(c, PA_COMMAND_SET_DEFAULT_SOURCE, &tag);
     pa_tagstruct_puts(t, name);
     pa_pstream_send_tagstruct(c->pstream, t);
@@ -1002,15 +1047,13 @@ int pa_context_is_local(pa_context *c) {
     pa_assert(c);
     pa_assert(PA_REFCNT_VALUE(c) >= 1);
 
-    PA_CHECK_VALIDITY(c, c->is_local >= 0, PA_ERR_BADSTATE);
+    PA_CHECK_VALIDITY_RETURN_ANY(c, PA_CONTEXT_IS_GOOD(c->state), PA_ERR_BADSTATE, -1);
 
-    return c->is_local;
+    return !!c->is_local;
 }
 
 pa_operation* pa_context_set_name(pa_context *c, const char *name, pa_context_success_cb_t cb, void *userdata) {
-    pa_tagstruct *t;
     pa_operation *o;
-    uint32_t tag;
 
     pa_assert(c);
     pa_assert(PA_REFCNT_VALUE(c) >= 1);
@@ -1020,11 +1063,14 @@ pa_operation* pa_context_set_name(pa_context *c, const char *name, pa_context_su
 
     if (c->version >= 13) {
         pa_proplist *p = pa_proplist_new();
+
         pa_proplist_sets(p, PA_PROP_APPLICATION_NAME, name);
         o = pa_context_proplist_update(c, PA_UPDATE_REPLACE, p, cb, userdata);
         pa_proplist_free(p);
-
     } else {
+        pa_tagstruct *t;
+        uint32_t tag;
+
         o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
         t = pa_tagstruct_command(c, PA_COMMAND_SET_CLIENT_NAME, &tag);
         pa_tagstruct_puts(t, name);
@@ -1062,7 +1108,7 @@ uint32_t pa_context_get_server_protocol_version(pa_context *c) {
     pa_assert(c);
     pa_assert(PA_REFCNT_VALUE(c) >= 1);
 
-    PA_CHECK_VALIDITY_RETURN_ANY(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE, PA_INVALID_INDEX);
+    PA_CHECK_VALIDITY_RETURN_ANY(c, PA_CONTEXT_IS_GOOD(c->state), PA_ERR_BADSTATE, PA_INVALID_INDEX);
 
     return c->version;
 }
diff --git a/src/pulse/def.h b/src/pulse/def.h
index 8a83d7a..1a0b9cb 100644
--- a/src/pulse/def.h
+++ b/src/pulse/def.h
@@ -48,6 +48,15 @@ typedef enum pa_context_state {
     PA_CONTEXT_TERMINATED      /**< The connection was terminated cleanly */
 } pa_context_state_t;
 
+/** Return non-zero if the passed state is one of the connected states */
+static inline int PA_CONTEXT_IS_GOOD(pa_context_state_t x) {
+    return
+        x == PA_CONTEXT_CONNECTING ||
+        x == PA_CONTEXT_AUTHORIZING ||
+        x == PA_CONTEXT_SETTING_NAME ||
+        x == PA_CONTEXT_READY;
+}
+
 /** The state of a stream */
 typedef enum pa_stream_state {
     PA_STREAM_UNCONNECTED, /**< The stream is not yet connected to any sink or source */
@@ -57,6 +66,13 @@ typedef enum pa_stream_state {
     PA_STREAM_TERMINATED    /**< The stream has been terminated cleanly */
 } pa_stream_state_t;
 
+/** Return non-zero if the passed state is one of the connected states */
+static inline int PA_STREAM_IS_GOOD(pa_stream_state_t x) {
+    return
+        x == PA_STREAM_CREATING ||
+        x == PA_STREAM_READY;
+}
+
 /** The state of an operation */
 typedef enum pa_operation_state {
     PA_OPERATION_RUNNING,      /**< The operation is still running */
@@ -296,6 +312,7 @@ enum {
     PA_ERR_VERSION,                /**< Incompatible protocol version */
     PA_ERR_TOOLARGE,               /**< Data too large */
     PA_ERR_NOTSUPPORTED,           /**< Operation not supported \since 0.9.5 */
+    PA_ERR_UNKNOWN,                /**< The error code was unknown to the client */
     PA_ERR_MAX                     /**< Not really an error but the first invalid error code */
 };
 
@@ -368,7 +385,15 @@ typedef struct pa_timing_info {
     pa_usec_t source_usec;    /**< Time in usecs a sample takes from being recorded to being delivered to the application. Only for record streams. */
     pa_usec_t transport_usec; /**< Estimated time in usecs a sample takes to be transferred to/from the daemon. For both playback and record streams. */
 
-    int playing;              /**< Non-zero when the stream is currently playing. Only for playback streams. */
+    int playing;              /**< Non-zero when the stream is
+                               * currently not underrun and data is
+                               * being passed on to the device. Only
+                               * for playback streams. This field does
+                               * not say whether the data is actually
+                               * already being played. To determine
+                               * this check whether since_underrun
+                               * (converted to usec) is larger than
+                               * sink_usec.*/
 
     int write_index_corrupt;  /**< Non-zero if write_index is not
                                * up-to-date because a local write
@@ -403,6 +428,14 @@ typedef struct pa_timing_info {
                                 * the sink. \since 0.9.11 */
     pa_usec_t configured_source_usec; /**< The static configured latency for
                                 * the source. \since 0.9.11 */
+
+    int64_t since_underrun;    /**< Bytes that were handed to the sink
+                                  since the last underrun happened, or
+                                  since playback started again after
+                                  the last underrun. playing will tell
+                                  you which case it is. \since
+                                  0.9.11 */
+
 } pa_timing_info;
 
 /** A structure for the spawn api. This may be used to integrate auto
diff --git a/src/pulse/internal.h b/src/pulse/internal.h
index f15c69c..d346e94 100644
--- a/src/pulse/internal.h
+++ b/src/pulse/internal.h
@@ -42,6 +42,7 @@
 #include <pulsecore/memblockq.h>
 #include <pulsecore/hashmap.h>
 #include <pulsecore/refcnt.h>
+#include <pulsecore/time-smoother.h>
 
 #include "client-conf.h"
 
@@ -69,14 +70,13 @@ struct pa_context {
 
     pa_context_notify_cb_t state_callback;
     void *state_userdata;
-
     pa_context_subscribe_cb_t subscribe_callback;
     void *subscribe_userdata;
 
     pa_mempool *mempool;
 
-    int is_local;
-    int do_autospawn;
+    pa_bool_t is_local;
+    pa_bool_t do_autospawn;
     int autospawn_lock_fd;
     pa_spawn_api spawn_api;
 
@@ -89,35 +89,39 @@ struct pa_context {
     uint32_t client_index;
 };
 
-#define PA_MAX_WRITE_INDEX_CORRECTIONS 10
+#define PA_MAX_WRITE_INDEX_CORRECTIONS 32
 
 typedef struct pa_index_correction {
     uint32_t tag;
-    int valid;
     int64_t value;
-    int absolute, corrupt;
+    pa_bool_t valid:1;
+    pa_bool_t absolute:1;
+    pa_bool_t corrupt:1;
 } pa_index_correction;
 
 struct pa_stream {
     PA_REFCNT_DECLARE;
+    PA_LLIST_FIELDS(pa_stream);
+
     pa_context *context;
     pa_mainloop_api *mainloop;
-    PA_LLIST_FIELDS(pa_stream);
 
-    pa_proplist *proplist;
-    pa_bool_t manual_buffer_attr;
-    pa_buffer_attr buffer_attr;
+    pa_stream_direction_t direction;
+    pa_stream_state_t state;
+    pa_stream_flags_t flags;
+
     pa_sample_spec sample_spec;
     pa_channel_map channel_map;
-    pa_stream_flags_t flags;
+
+    pa_proplist *proplist;
+
     uint32_t channel;
+    pa_bool_t channel_valid;
     uint32_t syncid;
-    int channel_valid;
     uint32_t stream_index;
-    pa_stream_direction_t direction;
-    pa_stream_state_t state;
 
     uint32_t requested_bytes;
+    pa_buffer_attr buffer_attr;
 
     uint32_t device_index;
     char *device_name;
@@ -127,11 +131,11 @@ struct pa_stream {
     void *peek_data;
     pa_memblockq *record_memblockq;
 
-    int corked;
+    pa_bool_t corked;
 
     /* Store latest latency info */
     pa_timing_info timing_info;
-    int timing_info_valid;
+    pa_bool_t timing_info_valid;
 
     /* Use to make sure that time advances monotonically */
     pa_usec_t previous_time;
@@ -146,10 +150,9 @@ struct pa_stream {
 
     /* Latency interpolation stuff */
     pa_time_event *auto_timing_update_event;
-    int auto_timing_update_requested;
+    pa_bool_t auto_timing_update_requested;
 
-    pa_usec_t cached_time;
-    int cached_time_valid;
+    pa_smoother *smoother;
 
     /* Callbacks */
     pa_stream_notify_cb_t state_callback;
@@ -168,6 +171,8 @@ struct pa_stream {
     void *moved_userdata;
     pa_stream_notify_cb_t suspended_callback;
     void *suspended_userdata;
+    pa_stream_notify_cb_t started_callback;
+    void *started_userdata;
 };
 
 typedef void (*pa_operation_cb_t)(void);
@@ -193,7 +198,7 @@ void pa_command_subscribe_event(pa_pdispatch *pd, uint32_t command, uint32_t tag
 void pa_command_overflow_or_underflow(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
 void pa_command_stream_suspended(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
 void pa_command_stream_moved(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
-
+void pa_command_stream_started(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
 pa_operation *pa_operation_new(pa_context *c, pa_stream *s, pa_operation_cb_t callback, void *userdata);
 void pa_operation_done(pa_operation *o);
 
@@ -205,7 +210,7 @@ void pa_stream_simple_ack_callback(pa_pdispatch *pd, uint32_t command, uint32_t
 void pa_context_fail(pa_context *c, int error);
 int pa_context_set_error(pa_context *c, int error);
 void pa_context_set_state(pa_context *c, pa_context_state_t st);
-int pa_context_handle_error(pa_context *c, uint32_t command, pa_tagstruct *t);
+int pa_context_handle_error(pa_context *c, uint32_t command, pa_tagstruct *t, pa_bool_t fail);
 pa_operation* pa_context_send_simple_command(pa_context *c, uint32_t command, void (*internal_callback)(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata), void (*cb)(void), void *userdata);
 
 void pa_stream_set_state(pa_stream *s, pa_stream_state_t st);
diff --git a/src/pulse/introspect.c b/src/pulse/introspect.c
index 49f9346..857e82b 100644
--- a/src/pulse/introspect.c
+++ b/src/pulse/introspect.c
@@ -52,7 +52,7 @@ static void context_stat_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNU
         goto finish;
 
     if (command != PA_COMMAND_REPLY) {
-        if (pa_context_handle_error(o->context, command, t) < 0)
+        if (pa_context_handle_error(o->context, command, t, FALSE) < 0)
             goto finish;
 
         p = NULL;
@@ -95,7 +95,7 @@ static void context_get_server_info_callback(pa_pdispatch *pd, uint32_t command,
         goto finish;
 
     if (command != PA_COMMAND_REPLY) {
-        if (pa_context_handle_error(o->context, command, t) < 0)
+        if (pa_context_handle_error(o->context, command, t, FALSE) < 0)
             goto finish;
 
         p = NULL;
@@ -140,7 +140,7 @@ static void context_get_sink_info_callback(pa_pdispatch *pd, uint32_t command, P
         goto finish;
 
     if (command != PA_COMMAND_REPLY) {
-        if (pa_context_handle_error(o->context, command, t) < 0)
+        if (pa_context_handle_error(o->context, command, t, FALSE) < 0)
             goto finish;
 
         eol = -1;
@@ -261,7 +261,7 @@ static void context_get_source_info_callback(pa_pdispatch *pd, uint32_t command,
         goto finish;
 
     if (command != PA_COMMAND_REPLY) {
-        if (pa_context_handle_error(o->context, command, t) < 0)
+        if (pa_context_handle_error(o->context, command, t, FALSE) < 0)
             goto finish;
 
         eol = -1;
@@ -382,7 +382,7 @@ static void context_get_client_info_callback(pa_pdispatch *pd, uint32_t command,
         goto finish;
 
     if (command != PA_COMMAND_REPLY) {
-        if (pa_context_handle_error(o->context, command, t) < 0)
+        if (pa_context_handle_error(o->context, command, t, FALSE) < 0)
             goto finish;
 
         eol = -1;
@@ -464,7 +464,7 @@ static void context_get_module_info_callback(pa_pdispatch *pd, uint32_t command,
         goto finish;
 
     if (command != PA_COMMAND_REPLY) {
-        if (pa_context_handle_error(o->context, command, t) < 0)
+        if (pa_context_handle_error(o->context, command, t, FALSE) < 0)
             goto finish;
 
         eol = -1;
@@ -543,7 +543,7 @@ static void context_get_sink_input_info_callback(pa_pdispatch *pd, uint32_t comm
         goto finish;
 
     if (command != PA_COMMAND_REPLY) {
-        if (pa_context_handle_error(o->context, command, t) < 0)
+        if (pa_context_handle_error(o->context, command, t, FALSE) < 0)
             goto finish;
 
         eol = -1;
@@ -637,7 +637,7 @@ static void context_get_source_output_info_callback(pa_pdispatch *pd, uint32_t c
         goto finish;
 
     if (command != PA_COMMAND_REPLY) {
-        if (pa_context_handle_error(o->context, command, t) < 0)
+        if (pa_context_handle_error(o->context, command, t, FALSE) < 0)
             goto finish;
 
         eol = -1;
@@ -967,7 +967,7 @@ static void context_get_sample_info_callback(pa_pdispatch *pd, uint32_t command,
         goto finish;
 
     if (command != PA_COMMAND_REPLY) {
-        if (pa_context_handle_error(o->context, command, t) < 0)
+        if (pa_context_handle_error(o->context, command, t, FALSE) < 0)
             goto finish;
 
         eol = -1;
@@ -1111,7 +1111,7 @@ static void context_index_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UN
         goto finish;
 
     if (command != PA_COMMAND_REPLY) {
-        if (pa_context_handle_error(o->context, command, t) < 0)
+        if (pa_context_handle_error(o->context, command, t, FALSE) < 0)
             goto finish;
 
         idx = PA_INVALID_INDEX;
@@ -1172,7 +1172,7 @@ static void context_get_autoload_info_callback(pa_pdispatch *pd, uint32_t comman
         goto finish;
 
     if (command != PA_COMMAND_REPLY) {
-        if (pa_context_handle_error(o->context, command, t) < 0)
+        if (pa_context_handle_error(o->context, command, t, FALSE) < 0)
             goto finish;
 
         eol = -1;
diff --git a/src/pulse/scache.c b/src/pulse/scache.c
index 24f340e..e43a0b9 100644
--- a/src/pulse/scache.c
+++ b/src/pulse/scache.c
@@ -108,7 +108,7 @@ static void play_sample_ack_callback(pa_pdispatch *pd, uint32_t command, uint32_
         goto finish;
 
     if (command != PA_COMMAND_REPLY) {
-        if (pa_context_handle_error(o->context, command, t) < 0)
+        if (pa_context_handle_error(o->context, command, t, FALSE) < 0)
             goto finish;
 
         success = 0;
@@ -141,7 +141,7 @@ static void play_sample_with_proplist_ack_callback(pa_pdispatch *pd, uint32_t co
         goto finish;
 
     if (command != PA_COMMAND_REPLY) {
-        if (pa_context_handle_error(o->context, command, t) < 0)
+        if (pa_context_handle_error(o->context, command, t, FALSE) < 0)
             goto finish;
 
         idx = PA_INVALID_INDEX;
diff --git a/src/pulse/stream.c b/src/pulse/stream.c
index ccbabb5..297e9d7 100644
--- a/src/pulse/stream.c
+++ b/src/pulse/stream.c
@@ -38,16 +38,47 @@
 #include <pulsecore/log.h>
 #include <pulsecore/hashmap.h>
 #include <pulsecore/macro.h>
+#include <pulsecore/rtclock.h>
 
 #include "internal.h"
 
-#define LATENCY_IPOL_INTERVAL_USEC (100000L)
+#define LATENCY_IPOL_INTERVAL_USEC (500*PA_USEC_PER_MSEC)
+
+#define SMOOTHER_ADJUST_TIME (1000*PA_USEC_PER_MSEC)
+#define SMOOTHER_HISTORY_TIME (5000*PA_USEC_PER_MSEC)
 
 pa_stream *pa_stream_new(pa_context *c, const char *name, const pa_sample_spec *ss, const pa_channel_map *map) {
     return pa_stream_new_with_proplist(c, name, ss, map, NULL);
 }
 
-pa_stream *pa_stream_new_with_proplist(pa_context *c, const char *name, const pa_sample_spec *ss, const pa_channel_map *map, pa_proplist *p) {
+static void reset_callbacks(pa_stream *s) {
+    s->read_callback = NULL;
+    s->read_userdata = NULL;
+    s->write_callback = NULL;
+    s->write_userdata = NULL;
+    s->state_callback = NULL;
+    s->state_userdata = NULL;
+    s->overflow_callback = NULL;
+    s->overflow_userdata = NULL;
+    s->underflow_callback = NULL;
+    s->underflow_userdata = NULL;
+    s->latency_update_callback = NULL;
+    s->latency_update_userdata = NULL;
+    s->moved_callback = NULL;
+    s->moved_userdata = NULL;
+    s->suspended_callback = NULL;
+    s->suspended_userdata = NULL;
+    s->started_callback = NULL;
+    s->started_userdata = NULL;
+}
+
+pa_stream *pa_stream_new_with_proplist(
+        pa_context *c,
+        const char *name,
+        const pa_sample_spec *ss,
+        const pa_channel_map *map,
+        pa_proplist *p) {
+
     pa_stream *s;
     int i;
     pa_channel_map tmap;
@@ -58,7 +89,7 @@ pa_stream *pa_stream_new_with_proplist(pa_context *c, const char *name, const pa
     PA_CHECK_VALIDITY_RETURN_NULL(c, ss && pa_sample_spec_valid(ss), PA_ERR_INVALID);
     PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 12 || (ss->format != PA_SAMPLE_S32LE || ss->format != PA_SAMPLE_S32NE), PA_ERR_NOTSUPPORTED);
     PA_CHECK_VALIDITY_RETURN_NULL(c, !map || (pa_channel_map_valid(map) && map->channels == ss->channels), PA_ERR_INVALID);
-    PA_CHECK_VALIDITY_RETURN_NULL(c, name || pa_proplist_contains(p, PA_PROP_MEDIA_NAME), PA_ERR_INVALID);
+    PA_CHECK_VALIDITY_RETURN_NULL(c, name || (p && pa_proplist_contains(p, PA_PROP_MEDIA_NAME)), PA_ERR_INVALID);
 
     if (!map)
         PA_CHECK_VALIDITY_RETURN_NULL(c, map = pa_channel_map_init_auto(&tmap, ss->channels, PA_CHANNEL_MAP_DEFAULT), PA_ERR_INVALID);
@@ -68,70 +99,53 @@ pa_stream *pa_stream_new_with_proplist(pa_context *c, const char *name, const pa
     s->context = c;
     s->mainloop = c->mainloop;
 
-    s->read_callback = NULL;
-    s->read_userdata = NULL;
-    s->write_callback = NULL;
-    s->write_userdata = NULL;
-    s->state_callback = NULL;
-    s->state_userdata = NULL;
-    s->overflow_callback = NULL;
-    s->overflow_userdata = NULL;
-    s->underflow_callback = NULL;
-    s->underflow_userdata = NULL;
-    s->latency_update_callback = NULL;
-    s->latency_update_userdata = NULL;
-    s->moved_callback = NULL;
-    s->moved_userdata = NULL;
-    s->suspended_callback = NULL;
-    s->suspended_userdata = NULL;
-
     s->direction = PA_STREAM_NODIRECTION;
+    s->state = PA_STREAM_UNCONNECTED;
+    s->flags = 0;
+
     s->sample_spec = *ss;
     s->channel_map = *map;
-    s->flags = 0;
 
     s->proplist = p ? pa_proplist_copy(p) : pa_proplist_new();
-
     if (name)
         pa_proplist_sets(s->proplist, PA_PROP_MEDIA_NAME, name);
 
     s->channel = 0;
-    s->channel_valid = 0;
+    s->channel_valid = FALSE;
     s->syncid = c->csyncid++;
     s->stream_index = PA_INVALID_INDEX;
-    s->requested_bytes = 0;
-    s->state = PA_STREAM_UNCONNECTED;
 
-    s->manual_buffer_attr = FALSE;
+    s->requested_bytes = 0;
     memset(&s->buffer_attr, 0, sizeof(s->buffer_attr));
 
     s->device_index = PA_INVALID_INDEX;
     s->device_name = NULL;
     s->suspended = FALSE;
 
-    s->peek_memchunk.index = 0;
-    s->peek_memchunk.length = 0;
-    s->peek_memchunk.memblock = NULL;
+    pa_memchunk_reset(&s->peek_memchunk);
     s->peek_data = NULL;
 
     s->record_memblockq = NULL;
 
-    s->previous_time = 0;
+    s->corked = FALSE;
+
     memset(&s->timing_info, 0, sizeof(s->timing_info));
     s->timing_info_valid = FALSE;
+
+    s->previous_time = 0;
+
     s->read_index_not_before = 0;
     s->write_index_not_before = 0;
-
     for (i = 0; i < PA_MAX_WRITE_INDEX_CORRECTIONS; i++)
         s->write_index_corrections[i].valid = 0;
     s->current_write_index_correction = 0;
 
-    s->corked = 0;
+    s->auto_timing_update_event = NULL;
+    s->auto_timing_update_requested = FALSE;
 
-    s->cached_time_valid = 0;
+    reset_callbacks(s);
 
-    s->auto_timing_update_event = NULL;
-    s->auto_timing_update_requested = 0;
+    s->smoother = NULL;
 
     /* Refcounting is strictly one-way: from the "bigger" to the "smaller" object. */
     PA_LLIST_PREPEND(pa_stream, c->streams, s);
@@ -140,16 +154,51 @@ pa_stream *pa_stream_new_with_proplist(pa_context *c, const char *name, const pa
     return s;
 }
 
-static void stream_free(pa_stream *s) {
+static void stream_unlink(pa_stream *s) {
+    pa_operation *o, *n;
     pa_assert(s);
-    pa_assert(!s->context);
-    pa_assert(!s->channel_valid);
+
+    if (!s->context)
+        return;
+
+    /* Detach from context */
+
+    /* Unref all operatio object that point to us */
+    for (o = s->context->operations; o; o = n) {
+        n = o->next;
+
+        if (o->stream == s)
+            pa_operation_cancel(o);
+    }
+
+    /* Drop all outstanding replies for this stream */
+    if (s->context->pdispatch)
+        pa_pdispatch_unregister_reply(s->context->pdispatch, s);
+
+    if (s->channel_valid) {
+        pa_dynarray_put((s->direction == PA_STREAM_PLAYBACK) ? s->context->playback_streams : s->context->record_streams, s->channel, NULL);
+        s->channel = 0;
+        s->channel_valid = FALSE;
+    }
+
+    PA_LLIST_REMOVE(pa_stream, s->context->streams, s);
+    pa_stream_unref(s);
+
+    s->context = NULL;
 
     if (s->auto_timing_update_event) {
         pa_assert(s->mainloop);
         s->mainloop->time_free(s->auto_timing_update_event);
     }
 
+    reset_callbacks(s);
+}
+
+static void stream_free(pa_stream *s) {
+    pa_assert(s);
+
+    stream_unlink(s);
+
     if (s->peek_memchunk.memblock) {
         if (s->peek_data)
             pa_memblock_release(s->peek_memchunk.memblock);
@@ -162,6 +211,9 @@ static void stream_free(pa_stream *s) {
     if (s->proplist)
         pa_proplist_free(s->proplist);
 
+    if (s->smoother)
+        pa_smoother_free(s->smoother);
+
     pa_xfree(s->device_name);
     pa_xfree(s);
 }
@@ -215,46 +267,41 @@ void pa_stream_set_state(pa_stream *s, pa_stream_state_t st) {
     pa_stream_ref(s);
 
     s->state = st;
+
     if (s->state_callback)
         s->state_callback(s, s->state_userdata);
 
-    if ((st == PA_STREAM_FAILED || st == PA_STREAM_TERMINATED) && s->context) {
-
-        /* Detach from context */
-        pa_operation *o, *n;
+    if ((st == PA_STREAM_FAILED || st == PA_STREAM_TERMINATED))
+        stream_unlink(s);
 
-        /* Unref all operatio object that point to us */
-        for (o = s->context->operations; o; o = n) {
-            n = o->next;
-
-            if (o->stream == s)
-                pa_operation_cancel(o);
-        }
-
-        /* Drop all outstanding replies for this stream */
-        if (s->context->pdispatch)
-            pa_pdispatch_unregister_reply(s->context->pdispatch, s);
+    pa_stream_unref(s);
+}
 
-        if (s->channel_valid)
-            pa_dynarray_put((s->direction == PA_STREAM_PLAYBACK) ? s->context->playback_streams : s->context->record_streams, s->channel, NULL);
+static void request_auto_timing_update(pa_stream *s, pa_bool_t force) {
+    pa_assert(s);
+    pa_assert(PA_REFCNT_VALUE(s) >= 1);
 
-        PA_LLIST_REMOVE(pa_stream, s->context->streams, s);
-        pa_stream_unref(s);
+    if (!(s->flags & PA_STREAM_AUTO_TIMING_UPDATE))
+        return;
 
-        s->channel = 0;
-        s->channel_valid = 0;
+    if (s->state == PA_STREAM_READY &&
+        (force || !s->auto_timing_update_requested)) {
+        pa_operation *o;
 
-        s->context = NULL;
+/*         pa_log("automatically requesting new timing data"); */
 
-        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;
+        if ((o = pa_stream_update_timing_info(s, NULL, NULL))) {
+            pa_operation_unref(o);
+            s->auto_timing_update_requested = TRUE;
+        }
     }
 
-    pa_stream_unref(s);
+    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);
+    }
 }
 
 void pa_command_stream_killed(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) {
@@ -279,6 +326,9 @@ void pa_command_stream_killed(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED
     if (!(s = pa_dynarray_get(command == PA_COMMAND_PLAYBACK_STREAM_KILLED ? c->playback_streams : c->record_streams, channel)))
         goto finish;
 
+    if (s->state != PA_STREAM_READY)
+        goto finish;
+
     pa_context_set_error(c, PA_ERR_KILLED);
     pa_stream_set_state(s, PA_STREAM_FAILED);
 
@@ -293,6 +343,7 @@ void pa_command_stream_moved(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED u
     const char *dn;
     pa_bool_t suspended;
     uint32_t di;
+    pa_usec_t usec;
 
     pa_assert(pd);
     pa_assert(command == PA_COMMAND_PLAYBACK_STREAM_MOVED || command == PA_COMMAND_RECORD_STREAM_MOVED);
@@ -310,12 +361,23 @@ void pa_command_stream_moved(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED u
     if (pa_tagstruct_getu32(t, &channel) < 0 ||
         pa_tagstruct_getu32(t, &di) < 0 ||
         pa_tagstruct_gets(t, &dn) < 0 ||
-        pa_tagstruct_get_boolean(t, &suspended) < 0 ||
-        !pa_tagstruct_eof(t)) {
+        pa_tagstruct_get_boolean(t, &suspended) < 0) {
         pa_context_fail(c, PA_ERR_PROTOCOL);
         goto finish;
     }
 
+    if (c->version >= 13) {
+        if (pa_tagstruct_get_usec(t, &usec) < 0) {
+            pa_context_fail(s->context, PA_ERR_PROTOCOL);
+            goto finish;
+        }
+    }
+
+    if (!pa_tagstruct_eof(t)) {
+        pa_context_fail(s->context, PA_ERR_PROTOCOL);
+        goto finish;
+    }
+
     if (!dn || di == PA_INVALID_INDEX) {
         pa_context_fail(c, PA_ERR_PROTOCOL);
         goto finish;
@@ -324,12 +386,24 @@ void pa_command_stream_moved(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED u
     if (!(s = pa_dynarray_get(command == PA_COMMAND_PLAYBACK_STREAM_MOVED ? c->playback_streams : c->record_streams, channel)))
         goto finish;
 
+    if (s->state != PA_STREAM_READY)
+        goto finish;
+
+    if (c->version >= 13) {
+        if (s->direction == PA_STREAM_RECORD)
+            s->timing_info.configured_source_usec = usec;
+        else
+            s->timing_info.configured_sink_usec = usec;
+    }
+
     pa_xfree(s->device_name);
     s->device_name = pa_xstrdup(dn);
     s->device_index = di;
 
     s->suspended = suspended;
 
+    request_auto_timing_update(s, TRUE);
+
     if (s->moved_callback)
         s->moved_callback(s, s->moved_userdata);
 
@@ -366,8 +440,23 @@ void pa_command_stream_suspended(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUS
     if (!(s = pa_dynarray_get(command == PA_COMMAND_PLAYBACK_STREAM_SUSPENDED ? c->playback_streams : c->record_streams, channel)))
         goto finish;
 
+    if (s->state != PA_STREAM_READY)
+        goto finish;
+
     s->suspended = suspended;
 
+    if (s->smoother) {
+        pa_usec_t x = pa_rtclock_usec();
+
+        if (s->timing_info_valid)
+            x -= s->timing_info.transport_usec;
+
+        if (s->suspended || s->corked)
+            pa_smoother_pause(s->smoother, x);
+    }
+
+    request_auto_timing_update(s, TRUE);
+
     if (s->suspended_callback)
         s->suspended_callback(s, s->suspended_userdata);
 
@@ -375,6 +464,45 @@ finish:
     pa_context_unref(c);
 }
 
+void pa_command_stream_started(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
+    pa_context *c = userdata;
+    pa_stream *s;
+    uint32_t channel;
+
+    pa_assert(pd);
+    pa_assert(command == PA_COMMAND_STARTED);
+    pa_assert(t);
+    pa_assert(c);
+    pa_assert(PA_REFCNT_VALUE(c) >= 1);
+
+    pa_context_ref(c);
+
+    if (c->version < 13) {
+        pa_context_fail(c, PA_ERR_PROTOCOL);
+        goto finish;
+    }
+
+    if (pa_tagstruct_getu32(t, &channel) < 0 ||
+        !pa_tagstruct_eof(t)) {
+        pa_context_fail(c, PA_ERR_PROTOCOL);
+        goto finish;
+    }
+
+    if (!(s = pa_dynarray_get(c->playback_streams, channel)))
+        goto finish;
+
+    if (s->state != PA_STREAM_READY)
+        goto finish;
+
+    request_auto_timing_update(s, TRUE);
+
+    if (s->started_callback)
+        s->started_callback(s, s->suspended_userdata);
+
+finish:
+    pa_context_unref(c);
+}
+
 void pa_command_request(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) {
     pa_stream *s;
     pa_context *c = userdata;
@@ -398,12 +526,13 @@ void pa_command_request(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32
     if (!(s = pa_dynarray_get(c->playback_streams, channel)))
         goto finish;
 
-    if (s->state == PA_STREAM_READY) {
-        s->requested_bytes += bytes;
+    if (s->state != PA_STREAM_READY)
+        goto finish;
 
-        if (s->requested_bytes > 0 && s->write_callback)
-            s->write_callback(s, s->requested_bytes, s->write_userdata);
-    }
+    s->requested_bytes += bytes;
+
+    if (s->requested_bytes > 0 && s->write_callback)
+        s->write_callback(s, s->requested_bytes, s->write_userdata);
 
 finish:
     pa_context_unref(c);
@@ -431,6 +560,21 @@ void pa_command_overflow_or_underflow(pa_pdispatch *pd, uint32_t command, PA_GCC
     if (!(s = pa_dynarray_get(c->playback_streams, channel)))
         goto finish;
 
+    if (s->state != PA_STREAM_READY)
+        goto finish;
+
+    if (s->smoother)
+        if (s->direction == PA_STREAM_PLAYBACK && s->buffer_attr.prebuf > 0) {
+            pa_usec_t x = pa_rtclock_usec();
+
+            if (s->timing_info_valid)
+                x -= s->timing_info.transport_usec;
+
+            pa_smoother_pause(s->smoother, x);
+        }
+
+    request_auto_timing_update(s, TRUE);
+
     if (s->state == PA_STREAM_READY) {
 
         if (command == PA_COMMAND_OVERFLOW) {
@@ -446,34 +590,7 @@ void pa_command_overflow_or_underflow(pa_pdispatch *pd, uint32_t command, PA_GCC
     pa_context_unref(c);
 }
 
-static void request_auto_timing_update(pa_stream *s, int force) {
-    pa_assert(s);
-    pa_assert(PA_REFCNT_VALUE(s) >= 1);
-
-    if (!(s->flags & PA_STREAM_AUTO_TIMING_UPDATE))
-        return;
-
-    if (s->state == PA_STREAM_READY &&
-        (force || !s->auto_timing_update_requested)) {
-        pa_operation *o;
-
-/*         pa_log("automatically requesting new timing data");   */
-
-        if ((o = pa_stream_update_timing_info(s, NULL, NULL))) {
-            pa_operation_unref(o);
-            s->auto_timing_update_requested = TRUE;
-        }
-    }
-
-    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) {
+static void invalidate_indexes(pa_stream *s, pa_bool_t r, pa_bool_t w) {
     pa_assert(s);
     pa_assert(PA_REFCNT_VALUE(s) >= 1);
 
@@ -500,11 +617,7 @@ static void invalidate_indexes(pa_stream *s, int r, int w) {
 /*         pa_log("read_index invalidated"); */
     }
 
-    if ((s->direction == PA_STREAM_PLAYBACK && r) ||
-        (s->direction == PA_STREAM_RECORD && w))
-        s->cached_time_valid = 0;
-
-    request_auto_timing_update(s, 1);
+    request_auto_timing_update(s, TRUE);
 }
 
 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) {
@@ -513,10 +626,8 @@ static void auto_timing_update_callback(PA_GCC_UNUSED pa_mainloop_api *m, PA_GCC
     pa_assert(s);
     pa_assert(PA_REFCNT_VALUE(s) >= 1);
 
-/*     pa_log("time event");    */
-
     pa_stream_ref(s);
-    request_auto_timing_update(s, 0);
+    request_auto_timing_update(s, FALSE);
     pa_stream_unref(s);
 }
 
@@ -536,6 +647,8 @@ static void create_stream_complete(pa_stream *s) {
         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);
+
+        request_auto_timing_update(s, TRUE);
     }
 }
 
@@ -577,7 +690,7 @@ void pa_create_stream_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED
     pa_stream_ref(s);
 
     if (command != PA_COMMAND_REPLY) {
-        if (pa_context_handle_error(s->context, command, t) < 0)
+        if (pa_context_handle_error(s->context, command, t, FALSE) < 0)
             goto finish;
 
         pa_stream_set_state(s, PA_STREAM_FAILED);
@@ -585,7 +698,8 @@ void pa_create_stream_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED
     }
 
     if (pa_tagstruct_getu32(t, &s->channel) < 0 ||
-        ((s->direction != PA_STREAM_UPLOAD) && pa_tagstruct_getu32(t, &s->stream_index) < 0) ||
+        s->channel == PA_INVALID_INDEX ||
+        ((s->direction != PA_STREAM_UPLOAD) && (pa_tagstruct_getu32(t, &s->stream_index) < 0 ||  s->stream_index == PA_INVALID_INDEX)) ||
         ((s->direction != PA_STREAM_RECORD) && pa_tagstruct_getu32(t, &s->requested_bytes) < 0)) {
         pa_context_fail(s->context, PA_ERR_PROTOCOL);
         goto finish;
@@ -676,7 +790,7 @@ void pa_create_stream_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED
                 NULL);
     }
 
-    s->channel_valid = 1;
+    s->channel_valid = TRUE;
     pa_dynarray_put((s->direction == PA_STREAM_RECORD) ? s->context->record_streams : s->context->playback_streams, s->channel, s);
 
     create_stream_complete(s);
@@ -737,16 +851,23 @@ static int create_stream(
     if (sync_stream)
         s->syncid = sync_stream->syncid;
 
-    if (attr) {
+    if (attr)
         s->buffer_attr = *attr;
-        s->manual_buffer_attr = TRUE;
-    } else {
-        memset(&s->buffer_attr, 0, sizeof(s->buffer_attr));
-        s->manual_buffer_attr = FALSE;
-    }
-
     automatic_buffer_attr(s, &s->buffer_attr, &s->sample_spec);
 
+    if (flags & PA_STREAM_INTERPOLATE_TIMING) {
+        pa_usec_t x;
+
+        if (s->smoother)
+            pa_smoother_free(s->smoother);
+
+        s->smoother = pa_smoother_new(SMOOTHER_ADJUST_TIME, SMOOTHER_HISTORY_TIME, !(flags & PA_STREAM_NOT_MONOTONOUS));
+
+        x = pa_rtclock_usec();
+        pa_smoother_set_time_offset(s->smoother, x);
+        pa_smoother_pause(s->smoother, x);
+    }
+
     if (!dev)
         dev = s->direction == PA_STREAM_PLAYBACK ? s->context->conf->default_sink : s->context->conf->default_source;
 
@@ -922,31 +1043,31 @@ int pa_stream_write(
         if (s->write_index_corrections[s->current_write_index_correction].valid) {
 
             if (seek == PA_SEEK_ABSOLUTE) {
-                s->write_index_corrections[s->current_write_index_correction].corrupt = 0;
-                s->write_index_corrections[s->current_write_index_correction].absolute = 1;
+                s->write_index_corrections[s->current_write_index_correction].corrupt = FALSE;
+                s->write_index_corrections[s->current_write_index_correction].absolute = TRUE;
                 s->write_index_corrections[s->current_write_index_correction].value = offset + length;
             } else if (seek == PA_SEEK_RELATIVE) {
                 if (!s->write_index_corrections[s->current_write_index_correction].corrupt)
                     s->write_index_corrections[s->current_write_index_correction].value += offset + length;
             } else
-                s->write_index_corrections[s->current_write_index_correction].corrupt = 1;
+                s->write_index_corrections[s->current_write_index_correction].corrupt = TRUE;
         }
 
         /* Update the write index in the already available latency data */
         if (s->timing_info_valid) {
 
             if (seek == PA_SEEK_ABSOLUTE) {
-                s->timing_info.write_index_corrupt = 0;
+                s->timing_info.write_index_corrupt = FALSE;
                 s->timing_info.write_index = offset + length;
             } else if (seek == PA_SEEK_RELATIVE) {
                 if (!s->timing_info.write_index_corrupt)
                     s->timing_info.write_index += offset + length;
             } else
-                s->timing_info.write_index_corrupt = 1;
+                s->timing_info.write_index_corrupt = TRUE;
         }
 
         if (!s->timing_info_valid || s->timing_info.write_index_corrupt)
-            request_auto_timing_update(s, 1);
+            request_auto_timing_update(s, TRUE);
     }
 
     return 0;
@@ -995,9 +1116,7 @@ int pa_stream_drop(pa_stream *s) {
     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;
-    s->peek_memchunk.memblock = NULL;
+    pa_memchunk_reset(&s->peek_memchunk);
 
     return 0;
 }
@@ -1043,11 +1162,71 @@ pa_operation * pa_stream_drain(pa_stream *s, pa_stream_success_cb_t cb, void *us
     return o;
 }
 
+static pa_usec_t calc_time(pa_stream *s, pa_bool_t ignore_transport) {
+    pa_usec_t usec;
+
+    pa_assert(s);
+    pa_assert(PA_REFCNT_VALUE(s) >= 1);
+    pa_assert(s->state == PA_STREAM_READY);
+    pa_assert(s->direction != PA_STREAM_UPLOAD);
+    pa_assert(s->timing_info_valid);
+    pa_assert(s->direction != PA_STREAM_PLAYBACK || !s->timing_info.read_index_corrupt);
+    pa_assert(s->direction != PA_STREAM_RECORD || !s->timing_info.write_index_corrupt);
+
+    if (s->direction == PA_STREAM_PLAYBACK) {
+        /* The last byte that was written into the output device
+         * had this time value associated */
+        usec = pa_bytes_to_usec(s->timing_info.read_index < 0 ? 0 : (uint64_t) s->timing_info.read_index, &s->sample_spec);
+
+        if (!s->corked && !s->suspended) {
+
+            if (!ignore_transport)
+                /* Because the latency info took a little time to come
+                 * to us, we assume that the real output time is actually
+                 * a little ahead */
+                usec += s->timing_info.transport_usec;
+
+            /* However, the output device usually maintains a buffer
+               too, hence the real sample currently played is a little
+               back  */
+            if (s->timing_info.sink_usec >= usec)
+                usec = 0;
+            else
+                usec -= s->timing_info.sink_usec;
+        }
+
+    } else if (s->direction == PA_STREAM_RECORD) {
+        /* The last byte written into the server side queue had
+         * this time value associated */
+        usec = pa_bytes_to_usec(s->timing_info.write_index < 0 ? 0 : (uint64_t) s->timing_info.write_index, &s->sample_spec);
+
+        if (!s->corked && !s->suspended) {
+
+            if (!ignore_transport)
+                /* Add transport latency */
+                usec += s->timing_info.transport_usec;
+
+            /* Add latency of data in device buffer */
+            usec += s->timing_info.source_usec;
+
+            /* If this is a monitor source, we need to correct the
+             * time by the playback device buffer */
+            if (s->timing_info.sink_usec >= usec)
+                usec = 0;
+            else
+                usec -= s->timing_info.sink_usec;
+        }
+    }
+
+    return usec;
+}
+
 static void stream_get_timing_info_callback(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
     pa_operation *o = userdata;
     struct timeval local, remote, now;
     pa_timing_info *i;
     pa_bool_t playing = FALSE;
+    uint64_t underrun_for = 0, playing_for = 0;
 
     pa_assert(pd);
     pa_assert(o);
@@ -1061,29 +1240,46 @@ static void stream_get_timing_info_callback(pa_pdispatch *pd, uint32_t command,
 /*     pa_log("pre corrupt w:%u r:%u\n", !o->stream->timing_info_valid || i->write_index_corrupt,!o->stream->timing_info_valid || i->read_index_corrupt); */
 
     o->stream->timing_info_valid = FALSE;
-    i->write_index_corrupt = 0;
-    i->read_index_corrupt = 0;
+    i->write_index_corrupt = FALSE;
+    i->read_index_corrupt = FALSE;
 
 /*     pa_log("timing update %u\n", tag); */
 
     if (command != PA_COMMAND_REPLY) {
-        if (pa_context_handle_error(o->context, command, t) < 0)
+        if (pa_context_handle_error(o->context, command, t, FALSE) < 0)
             goto finish;
 
-    } else if (pa_tagstruct_get_usec(t, &i->sink_usec) < 0 ||
-               pa_tagstruct_get_usec(t, &i->source_usec) < 0 ||
-               pa_tagstruct_get_boolean(t, &playing) < 0 ||
-               pa_tagstruct_get_timeval(t, &local) < 0 ||
-               pa_tagstruct_get_timeval(t, &remote) < 0 ||
-               pa_tagstruct_gets64(t, &i->write_index) < 0 ||
-               pa_tagstruct_gets64(t, &i->read_index) < 0 ||
-               !pa_tagstruct_eof(t)) {
-        pa_context_fail(o->context, PA_ERR_PROTOCOL);
-        goto finish;
-
     } else {
-        o->stream->timing_info_valid = 1;
+
+        if (pa_tagstruct_get_usec(t, &i->sink_usec) < 0 ||
+            pa_tagstruct_get_usec(t, &i->source_usec) < 0 ||
+            pa_tagstruct_get_boolean(t, &playing) < 0 ||
+            pa_tagstruct_get_timeval(t, &local) < 0 ||
+            pa_tagstruct_get_timeval(t, &remote) < 0 ||
+            pa_tagstruct_gets64(t, &i->write_index) < 0 ||
+            pa_tagstruct_gets64(t, &i->read_index) < 0) {
+
+            pa_context_fail(o->context, PA_ERR_PROTOCOL);
+            goto finish;
+        }
+
+        if (o->context->version >= 13)
+            if (pa_tagstruct_getu64(t, &underrun_for) < 0 ||
+                pa_tagstruct_getu64(t, &playing_for) < 0) {
+
+                pa_context_fail(o->context, PA_ERR_PROTOCOL);
+                goto finish;
+            }
+
+
+        if (!pa_tagstruct_eof(t)) {
+            pa_context_fail(o->context, PA_ERR_PROTOCOL);
+            goto finish;
+        }
+
+        o->stream->timing_info_valid = TRUE;
         i->playing = (int) playing;
+        i->since_underrun = playing ? playing_for : underrun_for;
 
         pa_gettimeofday(&now);
 
@@ -1096,22 +1292,22 @@ static void stream_get_timing_info_callback(pa_pdispatch *pd, uint32_t command,
             else
                 i->transport_usec = pa_timeval_diff(&now, &remote);
 
-            i->synchronized_clocks = 1;
+            i->synchronized_clocks = TRUE;
             i->timestamp = remote;
         } else {
             /* clocks are not synchronized, let's estimate latency then */
             i->transport_usec = pa_timeval_diff(&now, &local)/2;
-            i->synchronized_clocks = 0;
+            i->synchronized_clocks = FALSE;
             i->timestamp = local;
             pa_timeval_add(&i->timestamp, i->transport_usec);
         }
 
         /* Invalidate read and write indexes if necessary */
         if (tag < o->stream->read_index_not_before)
-            i->read_index_corrupt = 1;
+            i->read_index_corrupt = TRUE;
 
         if (tag < o->stream->write_index_not_before)
-            i->write_index_corrupt = 1;
+            i->write_index_corrupt = TRUE;
 
         if (o->stream->direction == PA_STREAM_PLAYBACK) {
             /* Write index correction */
@@ -1137,11 +1333,11 @@ static void stream_get_timing_info_callback(pa_pdispatch *pd, uint32_t command,
                 if (o->stream->write_index_corrections[j].corrupt) {
                     /* A corrupting seek was made */
                     i->write_index = 0;
-                    i->write_index_corrupt = 1;
+                    i->write_index_corrupt = TRUE;
                 } else if (o->stream->write_index_corrections[j].absolute) {
                     /* An absolute seek was made */
                     i->write_index = o->stream->write_index_corrections[j].value;
-                    i->write_index_corrupt = 0;
+                    i->write_index_corrupt = FALSE;
                 } else if (!i->write_index_corrupt) {
                     /* A relative seek was made */
                     i->write_index += o->stream->write_index_corrections[j].value;
@@ -1156,25 +1352,57 @@ static void stream_get_timing_info_callback(pa_pdispatch *pd, uint32_t command,
                 i->read_index -= pa_memblockq_get_length(o->stream->record_memblockq);
         }
 
-        o->stream->cached_time_valid = 0;
-    }
-
-    o->stream->auto_timing_update_requested = 0;
 /*     pa_log("post corrupt w:%u r:%u\n", i->write_index_corrupt || !o->stream->timing_info_valid, i->read_index_corrupt || !o->stream->timing_info_valid); */
 
-    /* Clear old correction entries */
-    if (o->stream->direction == PA_STREAM_PLAYBACK) {
-        int n;
+        /* Clear old correction entries */
+        if (o->stream->direction == PA_STREAM_PLAYBACK) {
+            int n;
+
+            for (n = 0; n < PA_MAX_WRITE_INDEX_CORRECTIONS; n++) {
+                if (!o->stream->write_index_corrections[n].valid)
+                    continue;
+
+                if (o->stream->write_index_corrections[n].tag <= tag)
+                    o->stream->write_index_corrections[n].valid = FALSE;
+            }
+        }
+
+        /* Update smoother */
+        if (o->stream->smoother) {
+            pa_usec_t u, x;
+
+            u = x = pa_rtclock_usec() - i->transport_usec;
 
-        for (n = 0; n < PA_MAX_WRITE_INDEX_CORRECTIONS; n++) {
-            if (!o->stream->write_index_corrections[n].valid)
-                continue;
+            if (o->stream->direction == PA_STREAM_PLAYBACK &&
+                o->context->version >= 13) {
+                pa_usec_t su;
 
-            if (o->stream->write_index_corrections[n].tag <= tag)
-                o->stream->write_index_corrections[n].valid = 0;
+                /* If we weren't playing then it will take some time
+                 * until the audio will actually come out through the
+                 * speakers. Since we follow that timing here, we need
+                 * to try to fix this up */
+
+                su = pa_bytes_to_usec(i->since_underrun, &o->stream->sample_spec);
+
+                if (su < i->sink_usec)
+                    x += i->sink_usec - su;
+            }
+
+            if (!i->playing)
+                pa_smoother_pause(o->stream->smoother, x);
+
+            /* Update the smoother */
+            if ((o->stream->direction == PA_STREAM_PLAYBACK && !i->read_index_corrupt) ||
+                (o->stream->direction == PA_STREAM_RECORD && !i->write_index_corrupt))
+                pa_smoother_put(o->stream->smoother, u, calc_time(o->stream, TRUE));
+
+            if (i->playing)
+                pa_smoother_resume(o->stream->smoother, x);
         }
     }
 
+    o->stream->auto_timing_update_requested = FALSE;
+
     if (o->stream->latency_update_callback)
         o->stream->latency_update_callback(o->stream, o->stream->latency_update_userdata);
 
@@ -1223,15 +1451,15 @@ pa_operation* pa_stream_update_timing_info(pa_stream *s, pa_stream_success_cb_t
 
     if (s->direction == PA_STREAM_PLAYBACK) {
         /* Fill in initial correction data */
-        o->stream->current_write_index_correction = cidx;
-        o->stream->write_index_corrections[cidx].valid = 1;
-        o->stream->write_index_corrections[cidx].tag = tag;
-        o->stream->write_index_corrections[cidx].absolute = 0;
-        o->stream->write_index_corrections[cidx].value = 0;
-        o->stream->write_index_corrections[cidx].corrupt = 0;
-    }
 
-/*     pa_log("requesting update %u\n", tag); */
+        s->current_write_index_correction = cidx;
+
+        s->write_index_corrections[cidx].valid = TRUE;
+        s->write_index_corrections[cidx].absolute = FALSE;
+        s->write_index_corrections[cidx].corrupt = FALSE;
+        s->write_index_corrections[cidx].tag = tag;
+        s->write_index_corrections[cidx].value = 0;
+    }
 
     return o;
 }
@@ -1246,7 +1474,7 @@ void pa_stream_disconnect_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UN
     pa_stream_ref(s);
 
     if (command != PA_COMMAND_REPLY) {
-        if (pa_context_handle_error(s->context, command, t) < 0)
+        if (pa_context_handle_error(s->context, command, t, FALSE) < 0)
             goto finish;
 
         pa_stream_set_state(s, PA_STREAM_FAILED);
@@ -1291,6 +1519,9 @@ void pa_stream_set_read_callback(pa_stream *s, pa_stream_request_cb_t cb, void *
     pa_assert(s);
     pa_assert(PA_REFCNT_VALUE(s) >= 1);
 
+    if (s->state == PA_STREAM_TERMINATED || s->state == PA_STREAM_FAILED)
+        return;
+
     s->read_callback = cb;
     s->read_userdata = userdata;
 }
@@ -1299,6 +1530,9 @@ void pa_stream_set_write_callback(pa_stream *s, pa_stream_request_cb_t cb, void
     pa_assert(s);
     pa_assert(PA_REFCNT_VALUE(s) >= 1);
 
+    if (s->state == PA_STREAM_TERMINATED || s->state == PA_STREAM_FAILED)
+        return;
+
     s->write_callback = cb;
     s->write_userdata = userdata;
 }
@@ -1307,6 +1541,9 @@ void pa_stream_set_state_callback(pa_stream *s, pa_stream_notify_cb_t cb, void *
     pa_assert(s);
     pa_assert(PA_REFCNT_VALUE(s) >= 1);
 
+    if (s->state == PA_STREAM_TERMINATED || s->state == PA_STREAM_FAILED)
+        return;
+
     s->state_callback = cb;
     s->state_userdata = userdata;
 }
@@ -1315,6 +1552,9 @@ void pa_stream_set_overflow_callback(pa_stream *s, pa_stream_notify_cb_t cb, voi
     pa_assert(s);
     pa_assert(PA_REFCNT_VALUE(s) >= 1);
 
+    if (s->state == PA_STREAM_TERMINATED || s->state == PA_STREAM_FAILED)
+        return;
+
     s->overflow_callback = cb;
     s->overflow_userdata = userdata;
 }
@@ -1323,6 +1563,9 @@ void pa_stream_set_underflow_callback(pa_stream *s, pa_stream_notify_cb_t cb, vo
     pa_assert(s);
     pa_assert(PA_REFCNT_VALUE(s) >= 1);
 
+    if (s->state == PA_STREAM_TERMINATED || s->state == PA_STREAM_FAILED)
+        return;
+
     s->underflow_callback = cb;
     s->underflow_userdata = userdata;
 }
@@ -1331,6 +1574,9 @@ void pa_stream_set_latency_update_callback(pa_stream *s, pa_stream_notify_cb_t c
     pa_assert(s);
     pa_assert(PA_REFCNT_VALUE(s) >= 1);
 
+    if (s->state == PA_STREAM_TERMINATED || s->state == PA_STREAM_FAILED)
+        return;
+
     s->latency_update_callback = cb;
     s->latency_update_userdata = userdata;
 }
@@ -1339,6 +1585,9 @@ void pa_stream_set_moved_callback(pa_stream *s, pa_stream_notify_cb_t cb, void *
     pa_assert(s);
     pa_assert(PA_REFCNT_VALUE(s) >= 1);
 
+    if (s->state == PA_STREAM_TERMINATED || s->state == PA_STREAM_FAILED)
+        return;
+
     s->moved_callback = cb;
     s->moved_userdata = userdata;
 }
@@ -1347,10 +1596,24 @@ void pa_stream_set_suspended_callback(pa_stream *s, pa_stream_notify_cb_t cb, vo
     pa_assert(s);
     pa_assert(PA_REFCNT_VALUE(s) >= 1);
 
+    if (s->state == PA_STREAM_TERMINATED || s->state == PA_STREAM_FAILED)
+        return;
+
     s->suspended_callback = cb;
     s->suspended_userdata = userdata;
 }
 
+void pa_stream_set_started_callback(pa_stream *s, pa_stream_notify_cb_t cb, void *userdata) {
+    pa_assert(s);
+    pa_assert(PA_REFCNT_VALUE(s) >= 1);
+
+    if (s->state == PA_STREAM_TERMINATED || s->state == PA_STREAM_FAILED)
+        return;
+
+    s->started_callback = cb;
+    s->started_userdata = userdata;
+}
+
 void pa_stream_simple_ack_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) {
     pa_operation *o = userdata;
     int success = 1;
@@ -1363,7 +1626,7 @@ void pa_stream_simple_ack_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UN
         goto finish;
 
     if (command != PA_COMMAND_REPLY) {
-        if (pa_context_handle_error(o->context, command, t) < 0)
+        if (pa_context_handle_error(o->context, command, t, FALSE) < 0)
             goto finish;
 
         success = 0;
@@ -1406,8 +1669,18 @@ pa_operation* pa_stream_cork(pa_stream *s, int b, pa_stream_success_cb_t cb, voi
     pa_pstream_send_tagstruct(s->context->pstream, t);
     pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, pa_stream_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
 
+    if (s->smoother) {
+        pa_usec_t x = pa_rtclock_usec();
+
+        if (s->timing_info_valid)
+            x += s->timing_info.transport_usec;
+
+        if (s->suspended || s->corked)
+            pa_smoother_pause(s->smoother, x);
+    }
+
     if (s->direction == PA_STREAM_PLAYBACK)
-        invalidate_indexes(s, 1, 0);
+        invalidate_indexes(s, TRUE, FALSE);
 
     return o;
 }
@@ -1438,23 +1711,34 @@ pa_operation* pa_stream_flush(pa_stream *s, pa_stream_success_cb_t cb, void *use
     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);
 
     if ((o = stream_send_simple_command(s, s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_FLUSH_PLAYBACK_STREAM : PA_COMMAND_FLUSH_RECORD_STREAM, cb, userdata))) {
 
         if (s->direction == PA_STREAM_PLAYBACK) {
             if (s->write_index_corrections[s->current_write_index_correction].valid)
-                s->write_index_corrections[s->current_write_index_correction].corrupt = 1;
+                s->write_index_corrections[s->current_write_index_correction].corrupt = TRUE;
 
             if (s->timing_info_valid)
-                s->timing_info.write_index_corrupt = 1;
+                s->timing_info.write_index_corrupt = TRUE;
 
             if (s->buffer_attr.prebuf > 0)
-                invalidate_indexes(s, 1, 0);
+                invalidate_indexes(s, TRUE, FALSE);
             else
-                request_auto_timing_update(s, 1);
+                request_auto_timing_update(s, TRUE);
+
+            if (s->smoother && s->buffer_attr.prebuf > 0) {
+                pa_usec_t x = pa_rtclock_usec();
+
+                if (s->timing_info_valid)
+                    x += s->timing_info.transport_usec;
+
+                pa_smoother_pause(s->smoother, x);
+            }
+
         } else
-            invalidate_indexes(s, 0, 1);
+            invalidate_indexes(s, FALSE, TRUE);
     }
 
     return o;
@@ -1466,11 +1750,12 @@ pa_operation* pa_stream_prebuf(pa_stream *s, pa_stream_success_cb_t cb, void *us
     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);
     PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->buffer_attr.prebuf > 0, PA_ERR_BADSTATE);
 
     if ((o = stream_send_simple_command(s, PA_COMMAND_PREBUF_PLAYBACK_STREAM, cb, userdata)))
-        invalidate_indexes(s, 1, 0);
+        invalidate_indexes(s, TRUE, FALSE);
 
     return o;
 }
@@ -1481,19 +1766,18 @@ pa_operation* pa_stream_trigger(pa_stream *s, pa_stream_success_cb_t cb, void *u
     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);
     PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->buffer_attr.prebuf > 0, PA_ERR_BADSTATE);
 
     if ((o = stream_send_simple_command(s, PA_COMMAND_TRIGGER_PLAYBACK_STREAM, cb, userdata)))
-        invalidate_indexes(s, 1, 0);
+        invalidate_indexes(s, TRUE, FALSE);
 
     return o;
 }
 
 pa_operation* pa_stream_set_name(pa_stream *s, const char *name, pa_stream_success_cb_t cb, void *userdata) {
     pa_operation *o;
-    pa_tagstruct *t;
-    uint32_t tag;
 
     pa_assert(s);
     pa_assert(PA_REFCNT_VALUE(s) >= 1);
@@ -1502,22 +1786,32 @@ pa_operation* pa_stream_set_name(pa_stream *s, const char *name, pa_stream_succe
     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);
 
-    o = pa_operation_new(s->context, s, (pa_operation_cb_t) cb, userdata);
+    if (s->context->version >= 13) {
+        pa_proplist *p = pa_proplist_new();
 
-    t = pa_tagstruct_command(
-            s->context,
-            s->direction == PA_STREAM_RECORD ? PA_COMMAND_SET_RECORD_STREAM_NAME : PA_COMMAND_SET_PLAYBACK_STREAM_NAME,
-            &tag);
-    pa_tagstruct_putu32(t, s->channel);
-    pa_tagstruct_puts(t, name);
-    pa_pstream_send_tagstruct(s->context->pstream, t);
-    pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, pa_stream_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
+        pa_proplist_sets(p, PA_PROP_APPLICATION_NAME, name);
+        o = pa_stream_proplist_update(s, PA_UPDATE_REPLACE, p, cb, userdata);
+        pa_proplist_free(p);
+    } else {
+        pa_tagstruct *t;
+        uint32_t tag;
+
+        o = pa_operation_new(s->context, s, (pa_operation_cb_t) cb, userdata);
+        t = pa_tagstruct_command(
+                s->context,
+                s->direction == PA_STREAM_RECORD ? PA_COMMAND_SET_RECORD_STREAM_NAME : PA_COMMAND_SET_PLAYBACK_STREAM_NAME,
+                &tag);
+        pa_tagstruct_putu32(t, s->channel);
+        pa_tagstruct_puts(t, name);
+        pa_pstream_send_tagstruct(s->context->pstream, t);
+        pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, pa_stream_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
+    }
 
     return o;
 }
 
 int pa_stream_get_time(pa_stream *s, pa_usec_t *r_usec) {
-    pa_usec_t usec = 0;
+    pa_usec_t usec;
 
     pa_assert(s);
     pa_assert(PA_REFCNT_VALUE(s) >= 1);
@@ -1528,65 +1822,10 @@ int pa_stream_get_time(pa_stream *s, pa_usec_t *r_usec) {
     PA_CHECK_VALIDITY(s->context, s->direction != PA_STREAM_PLAYBACK || !s->timing_info.read_index_corrupt, PA_ERR_NODATA);
     PA_CHECK_VALIDITY(s->context, s->direction != PA_STREAM_RECORD || !s->timing_info.write_index_corrupt, PA_ERR_NODATA);
 
-    if (s->cached_time_valid)
-        /* We alredy calculated the time value for this timing info, so let's reuse it */
-        usec = s->cached_time;
-    else {
-        if (s->direction == PA_STREAM_PLAYBACK) {
-            /* The last byte that was written into the output device
-             * had this time value associated */
-            usec = pa_bytes_to_usec(s->timing_info.read_index < 0 ? 0 : (uint64_t) s->timing_info.read_index, &s->sample_spec);
-
-            if (!s->corked) {
-                /* Because the latency info took a little time to come
-                 * to us, we assume that the real output time is actually
-                 * a little ahead */
-                usec += s->timing_info.transport_usec;
-
-                /* However, the output device usually maintains a buffer
-                   too, hence the real sample currently played is a little
-                   back  */
-                if (s->timing_info.sink_usec >= usec)
-                    usec = 0;
-                else
-                    usec -= s->timing_info.sink_usec;
-            }
-
-        } else if (s->direction == PA_STREAM_RECORD) {
-            /* The last byte written into the server side queue had
-             * this time value associated */
-            usec = pa_bytes_to_usec(s->timing_info.write_index < 0 ? 0 : (uint64_t) s->timing_info.write_index, &s->sample_spec);
-
-            if (!s->corked) {
-                /* Add transport latency */
-                usec += s->timing_info.transport_usec;
-
-                /* Add latency of data in device buffer */
-                usec += s->timing_info.source_usec;
-
-                /* If this is a monitor source, we need to correct the
-                 * time by the playback device buffer */
-                if (s->timing_info.sink_usec >= usec)
-                    usec = 0;
-                else
-                    usec -= s->timing_info.sink_usec;
-            }
-        }
-
-        s->cached_time = usec;
-        s->cached_time_valid = 1;
-    }
-
-    /* Interpolate if requested */
-    if (s->flags & PA_STREAM_INTERPOLATE_TIMING) {
-
-        /* We just add the time that passed since the latency info was
-         * current */
-        if (!s->corked && s->timing_info.playing) {
-            struct timeval now;
-            usec += pa_timeval_diff(pa_gettimeofday(&now), &s->timing_info.timestamp);
-        }
-    }
+    if (s->smoother)
+        usec = pa_smoother_get(s->smoother, pa_rtclock_usec());
+    else
+        usec = calc_time(s, FALSE);
 
     /* Make sure the time runs monotonically */
     if (!(s->flags & PA_STREAM_NOT_MONOTONOUS)) {
@@ -1687,7 +1926,7 @@ const pa_buffer_attr* pa_stream_get_buffer_attr(pa_stream *s) {
 
     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);
-    PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->context->version >= 9, PA_ERR_NODATA);
+    PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->context->version >= 9, PA_ERR_NOTSUPPORTED);
 
     return &s->buffer_attr;
 }
@@ -1704,7 +1943,7 @@ static void stream_set_buffer_attr_callback(pa_pdispatch *pd, uint32_t command,
         goto finish;
 
     if (command != PA_COMMAND_REPLY) {
-        if (pa_context_handle_error(o->context, command, t) < 0)
+        if (pa_context_handle_error(o->context, command, t, FALSE) < 0)
             goto finish;
 
         success = 0;
@@ -1730,8 +1969,6 @@ static void stream_set_buffer_attr_callback(pa_pdispatch *pd, uint32_t command,
             pa_context_fail(o->context, PA_ERR_PROTOCOL);
             goto finish;
         }
-
-        o->stream->manual_buffer_attr = TRUE;
     }
 
     if (o->callback) {
@@ -1822,6 +2059,16 @@ int pa_stream_is_suspended(pa_stream *s) {
     return s->suspended;
 }
 
+int pa_stream_is_corked(pa_stream *s) {
+    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);
+
+    return s->corked;
+}
+
 static void stream_update_sample_rate_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) {
     pa_operation *o = userdata;
     int success = 1;
@@ -1834,7 +2081,7 @@ static void stream_update_sample_rate_callback(pa_pdispatch *pd, uint32_t comman
         goto finish;
 
     if (command != PA_COMMAND_REPLY) {
-        if (pa_context_handle_error(o->context, command, t) < 0)
+        if (pa_context_handle_error(o->context, command, t, FALSE) < 0)
             goto finish;
 
         success = 0;
diff --git a/src/pulse/stream.h b/src/pulse/stream.h
index 69943a7..ebb45f2 100644
--- a/src/pulse/stream.h
+++ b/src/pulse/stream.h
@@ -339,6 +339,10 @@ const char *pa_stream_get_device_name(pa_stream *s);
  * server is older than 0.9.8. \since 0.9.8 */
 int pa_stream_is_suspended(pa_stream *s);
 
+/** Return 1 if the this stream has been corked. This will return 0 if
+ * not, and negative on error. \since 0.9.11 */
+int pa_stream_is_corked(pa_stream *s);
+
 /** Connect the stream to a sink */
 int pa_stream_connect_playback(
         pa_stream *s                  /**< The stream to connect to a sink */,
@@ -368,7 +372,7 @@ int pa_stream_disconnect(pa_stream *s);
 int pa_stream_write(
         pa_stream *p             /**< The stream to use */,
         const void *data         /**< The data to write */,
-        size_t bytes             /**< The length of the data to write in bytes*/,
+        size_t nbytes            /**< The length of the data to write in bytes*/,
         pa_free_cb_t free_cb     /**< A cleanup routine for the data or NULL to request an internal copy */,
         int64_t offset,          /**< Offset for seeking, must be 0 for upload streams */
         pa_seek_mode_t seek      /**< Seek mode, must be PA_SEEK_RELATIVE for upload streams */);
@@ -381,7 +385,7 @@ int pa_stream_write(
 int pa_stream_peek(
         pa_stream *p                 /**< The stream to use */,
         const void **data            /**< Pointer to pointer that will point to data */,
-        size_t *bytes                /**< The length of the data read in bytes */);
+        size_t *nbytes               /**< The length of the data read in bytes */);
 
 /** Remove the current fragment on record streams. It is invalid to do this without first
  * calling pa_stream_peek(). */
@@ -419,6 +423,13 @@ void pa_stream_set_overflow_callback(pa_stream *p, pa_stream_notify_cb_t cb, voi
 /** Set the callback function that is called when a buffer underflow happens. (Only for playback streams) */
 void pa_stream_set_underflow_callback(pa_stream *p, pa_stream_notify_cb_t cb, void *userdata);
 
+/** Set the callback function that is called when a the server starts
+ * playback after an underrun or on initial startup. This only informs
+ * that audio is flowing again, it is no indication that audio startet
+ * to reach the speakers already. (Only for playback streams). \since
+ * 0.9.11 */
+void pa_stream_set_started_callback(pa_stream *p, pa_stream_notify_cb_t cb, void *userdata);
+
 /** Set the callback function that is called whenever a latency
  * information update happens. Useful on PA_STREAM_AUTO_TIMING_UPDATE
  * streams only. (Only for playback streams) */
diff --git a/src/pulsecore/core-util.c b/src/pulsecore/core-util.c
index 28885b2..df11096 100644
--- a/src/pulsecore/core-util.c
+++ b/src/pulsecore/core-util.c
@@ -41,6 +41,7 @@
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <sys/time.h>
+#include <dirent.h>
 
 #ifdef HAVE_STRTOF_L
 #include <locale.h>
@@ -103,12 +104,6 @@
 #define MSG_NOSIGNAL 0
 #endif
 
-#ifndef OS_IS_WIN32
-#define PA_USER_RUNTIME_PATH_PREFIX "/tmp/pulse-"
-#else
-#define PA_USER_RUNTIME_PATH_PREFIX "%TEMP%\\pulse-"
-#endif
-
 #ifdef OS_IS_WIN32
 
 #define PULSE_ROOTENV "PULSE_ROOT"
@@ -221,7 +216,7 @@ int pa_make_secure_dir(const char* dir, mode_t m, uid_t uid, gid_t gid) {
         goto fail;
     }
 #else
-    pa_log_warn("secure directory creation not supported on Win32.");
+    pa_log_warn("Secure directory creation not supported on Win32.");
 #endif
 
     return 0;
@@ -557,6 +552,82 @@ int pa_make_realtime(int rtprio) {
 #endif
 }
 
+/* This is merely used for giving the user a hint. This is not correct
+ * for anything security related */
+pa_bool_t pa_can_realtime(void) {
+
+    if (geteuid() == 0)
+        return TRUE;
+
+#if defined(HAVE_SYS_RESOURCE_H) && defined(RLIMIT_RTPRIO)
+    {
+        struct rlimit rl;
+
+        if (getrlimit(RLIMIT_RTPRIO, &rl) >= 0)
+            if (rl.rlim_cur > 0 || rl.rlim_cur == RLIM_INFINITY)
+                return TRUE;
+    }
+#endif
+
+#if defined(HAVE_SYS_CAPABILITY_H) && defined(CAP_SYS_NICE)
+    {
+        cap_t cap;
+
+        if ((cap = cap_get_proc())) {
+            cap_flag_value_t flag = CAP_CLEAR;
+
+            if (cap_get_flag(cap, CAP_SYS_NICE, CAP_EFFECTIVE, &flag) >= 0)
+                if (flag == CAP_SET) {
+                    cap_free(cap);
+                    return TRUE;
+                }
+
+            cap_free(cap);
+        }
+    }
+#endif
+
+    return FALSE;
+}
+
+/* This is merely used for giving the user a hint. This is not correct
+ * for anything security related */
+pa_bool_t pa_can_high_priority(void) {
+
+    if (geteuid() == 0)
+        return TRUE;
+
+#if defined(HAVE_SYS_RESOURCE_H) && defined(RLIMIT_RTPRIO)
+    {
+        struct rlimit rl;
+
+        if (getrlimit(RLIMIT_NICE, &rl) >= 0)
+            if (rl.rlim_cur >= 21 || rl.rlim_cur == RLIM_INFINITY)
+                return TRUE;
+    }
+#endif
+
+#if defined(HAVE_SYS_CAPABILITY_H) && defined(CAP_SYS_NICE)
+    {
+        cap_t cap;
+
+        if ((cap = cap_get_proc())) {
+            cap_flag_value_t flag = CAP_CLEAR;
+
+            if (cap_get_flag(cap, CAP_SYS_NICE, CAP_EFFECTIVE, &flag) >= 0)
+                if (flag == CAP_SET) {
+                    cap_free(cap);
+                    return TRUE;
+                }
+
+            cap_free(cap);
+        }
+    }
+#endif
+
+    return FALSE;
+}
+
 /* Raise the priority of the current process as much as possible that
  * is <= the specified nice level..*/
 int pa_raise_priority(int nice_level) {
@@ -612,6 +683,7 @@ void pa_reset_priority(void) {
 
 /* Try to parse a boolean string value.*/
 int pa_parse_boolean(const char *v) {
+    pa_assert(v);
 
     if (!strcmp(v, "1") || v[0] == 'y' || v[0] == 'Y' || v[0] == 't' || v[0] == 'T' || !strcasecmp(v, "on"))
         return 1;
@@ -1093,11 +1165,11 @@ int pa_unlock_lockfile(const char *fn, int fd) {
     return r;
 }
 
-char *pa_get_state_dir(void) {
+char *pa_get_runtime_dir(void) {
     const char *e;
     char *d;
 
-    if ((e = getenv("PULSE_STATE_PATH")))
+    if ((e = getenv("PULSE_RUNTIME_PATH")))
         d = pa_xstrdup(e);
     else {
         char h[PATH_MAX];
@@ -1107,19 +1179,15 @@ char *pa_get_state_dir(void) {
             return NULL;
         }
 
-        d = pa_sprintf_malloc("%s/.pulse", h);
+        d = pa_sprintf_malloc("%s" PA_PATH_SEP ".pulse", h);
     }
 
-    mkdir(d, 0755);
-
-    if (access(d, W_OK) == 0)
-        return d;
-
-    pa_log_error("Failed to set up state directory %s", d);
-
-    pa_xfree(d);
+    if (pa_make_secure_dir(d, 0700, (pid_t) -1, (pid_t) -1) < 0)  {
+        pa_log_error("Failed to create secure directory: %s", pa_cstrerror(errno));
+        return NULL;
+    }
 
-    return NULL;
+    return d;
 }
 
 /* Try to open a configuration file. If "env" is specified, open the
@@ -1128,10 +1196,8 @@ char *pa_get_state_dir(void) {
  * file system. If "result" is non-NULL, a pointer to a newly
  * allocated buffer containing the used configuration file is
  * stored there.*/
-FILE *pa_open_config_file(const char *global, const char *local, const char *env, char **result, const char *mode) {
+FILE *pa_open_config_file(const char *global, const char *local, const char *env, char **result) {
     const char *fn;
-    char h[PATH_MAX];
-
 #ifdef OS_IS_WIN32
     char buf[PATH_MAX];
 
@@ -1140,75 +1206,152 @@ FILE *pa_open_config_file(const char *global, const char *local, const char *env
 #endif
 
     if (env && (fn = getenv(env))) {
+        FILE *f;
+
 #ifdef OS_IS_WIN32
         if (!ExpandEnvironmentStrings(fn, buf, PATH_MAX))
             return NULL;
         fn = buf;
 #endif
 
-        if (result)
-            *result = pa_xstrdup(fn);
+        if ((f = fopen(fn, "r"))) {
+            if (result)
+                *result = pa_xstrdup(fn);
+
+            return f;
+        }
 
-        return fopen(fn, mode);
+        pa_log_warn("Failed to open configuration file '%s': %s", fn, pa_cstrerror(errno));
+        return NULL;
     }
 
     if (local) {
         const char *e;
-        char *lfn = NULL;
+        char *lfn;
+        char h[PATH_MAX];
+        FILE *f;
 
         if ((e = getenv("PULSE_CONFIG_PATH")))
-            fn = lfn = pa_sprintf_malloc("%s/%s", e, local);
-        else if (pa_get_home_dir(h, sizeof(h))) {
-            char *d;
+            fn = lfn = pa_sprintf_malloc("%s" PA_PATH_SEP "%s", e, local);
+        else if (pa_get_home_dir(h, sizeof(h)))
+            fn = lfn = pa_sprintf_malloc("%s" PA_PATH_SEP ".pulse" PA_PATH_SEP "%s", h, local);
 
-            d = pa_sprintf_malloc("%s/.pulse", h);
-            mkdir(d, 0755);
-            pa_xfree(d);
+#ifdef OS_IS_WIN32
+        if (!ExpandEnvironmentStrings(lfn, buf, PATH_MAX)) {
+            pa_xfree(lfn);
+            return NULL;
+        }
+        fn = buf;
+#endif
+
+        if ((f = fopen(fn, "r"))) {
+            if (result)
+                *result = pa_xstrdup(fn);
+
+            pa_xfree(lfn);
+            return f;
+        }
 
-            fn = lfn = pa_sprintf_malloc("%s/.pulse/%s", h, local);
+        if (errno != ENOENT) {
+            pa_log_warn("Failed to open configuration file '%s': %s", fn, pa_cstrerror(errno));
+            pa_xfree(lfn);
+            return NULL;
         }
 
-        if (lfn) {
-            FILE *f;
+        pa_xfree(lfn);
+    }
+
+    if (global) {
+        FILE *f;
 
 #ifdef OS_IS_WIN32
-            if (!ExpandEnvironmentStrings(lfn, buf, PATH_MAX))
-                return NULL;
-            fn = buf;
+        if (!ExpandEnvironmentStrings(global, buf, PATH_MAX))
+            return NULL;
+        global = buf;
 #endif
 
-            f = fopen(fn, mode);
-            if (f != NULL) {
-                if (result)
-                    *result = pa_xstrdup(fn);
-                pa_xfree(lfn);
-                return f;
-            }
+        if ((f = fopen(global, "r"))) {
 
-            if (errno != ENOENT)
-                pa_log_warn("Failed to open configuration file '%s': %s", lfn, pa_cstrerror(errno));
+            if (result)
+                *result = pa_xstrdup(global);
 
-            pa_xfree(lfn);
+            return f;
         }
-    }
-
-    if (!global) {
-        if (result)
-            *result = NULL;
+    } else
         errno = ENOENT;
+
+    return NULL;
+}
+
+char *pa_find_config_file(const char *global, const char *local, const char *env) {
+    const char *fn;
+#ifdef OS_IS_WIN32
+    char buf[PATH_MAX];
+
+    if (!getenv(PULSE_ROOTENV))
+        pa_set_root(NULL);
+#endif
+
+    if (env && (fn = getenv(env))) {
+#ifdef OS_IS_WIN32
+        if (!ExpandEnvironmentStrings(fn, buf, PATH_MAX))
+            return NULL;
+        fn = buf;
+#endif
+
+        if (access(fn, R_OK) == 0)
+            return pa_xstrdup(fn);
+
+        pa_log_warn("Failed to access configuration file '%s': %s", fn, pa_cstrerror(errno));
         return NULL;
     }
 
+    if (local) {
+        const char *e;
+        char *lfn;
+        char h[PATH_MAX];
+
+        if ((e = getenv("PULSE_CONFIG_PATH")))
+            fn = lfn = pa_sprintf_malloc("%s" PA_PATH_SEP "%s", e, local);
+        else if (pa_get_home_dir(h, sizeof(h)))
+            fn = lfn = pa_sprintf_malloc("%s" PA_PATH_SEP ".pulse" PA_PATH_SEP "%s", h, local);
+
 #ifdef OS_IS_WIN32
-    if (!ExpandEnvironmentStrings(global, buf, PATH_MAX))
-        return NULL;
-    global = buf;
+        if (!ExpandEnvironmentStrings(lfn, buf, PATH_MAX)) {
+            pa_xfree(lfn);
+            return NULL;
+        }
+        fn = buf;
 #endif
 
-    if (result)
-        *result = pa_xstrdup(global);
+        if (access(fn, R_OK) == 0) {
+            char *r = pa_xstrdup(fn);
+            pa_xfree(lfn);
+            return r;
+        }
+
+        if (errno != ENOENT) {
+            pa_log_warn("Failed to access configuration file '%s': %s", fn, pa_cstrerror(errno));
+            pa_xfree(lfn);
+            return NULL;
+        }
+
+        pa_xfree(lfn);
+    }
+
+    if (global) {
+#ifdef OS_IS_WIN32
+        if (!ExpandEnvironmentStrings(global, buf, PATH_MAX))
+            return NULL;
+        global = buf;
+#endif
+
+        if (access(fn, R_OK) == 0)
+            return pa_xstrdup(global);
+    } else
+        errno = ENOENT;
 
-    return fopen(global, mode);
+    return NULL;
 }
 
 /* Format the specified data as a hexademical string */
@@ -1299,45 +1442,51 @@ int pa_endswith(const char *s, const char *sfx) {
     return l1 >= l2 && strcmp(s+l1-l2, sfx) == 0;
 }
 
-/* if fn is null return the PulseAudio run time path in s (/tmp/pulse)
- * if fn is non-null and starts with / return fn in s
- * otherwise append fn to the run time path and return it in s */
-char *pa_runtime_path(const char *fn, char *s, size_t l) {
-    const char *e;
+pa_bool_t pa_is_path_absolute(const char *fn) {
+    pa_assert(fn);
 
 #ifndef OS_IS_WIN32
-    if (fn && *fn == '/')
+    return *fn == '/';
 #else
-    if (fn && strlen(fn) >= 3 && isalpha(fn[0]) && fn[1] == ':' && fn[2] == '\\')
+    return strlen(fn) >= 3 && isalpha(fn[0]) && fn[1] == ':' && fn[2] == '\\';
 #endif
-        return pa_strlcpy(s, fn, l);
+}
 
-    if ((e = getenv("PULSE_RUNTIME_PATH"))) {
+char *pa_make_path_absolute(const char *p) {
+    char *r;
+    char *cwd;
 
-        if (fn)
-            pa_snprintf(s, l, "%s%c%s", e, PA_PATH_SEP_CHAR, fn);
-        else
-            pa_snprintf(s, l, "%s", e);
+    pa_assert(p);
 
-    } else {
-        char u[256];
+    if (pa_is_path_absolute(p))
+        return pa_xstrdup(p);
 
-        if (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
-            pa_snprintf(s, l, "%s%s", PA_USER_RUNTIME_PATH_PREFIX, pa_get_user_name(u, sizeof(u)));
-    }
+    if (!(cwd = pa_getcwd()))
+        return pa_xstrdup(p);
 
+    r = pa_sprintf_malloc("%s" PA_PATH_SEP "%s", cwd, p);
+    pa_xfree(cwd);
+    return r;
+}
 
-#ifdef OS_IS_WIN32
-    {
-        char buf[l];
-        strcpy(buf, s);
-        ExpandEnvironmentStrings(buf, s, l);
-    }
-#endif
+/* if fn is null return the PulseAudio run time path in s (~/.pulse)
+ * if fn is non-null and starts with / return fn
+ * otherwise append fn to the run time path and return it */
+char *pa_runtime_path(const char *fn) {
+    char *rtp;
 
-    return s;
+    if (pa_is_path_absolute(fn))
+        return pa_xstrdup(fn);
+
+    rtp = pa_get_runtime_dir();
+
+    if (fn) {
+        char *r;
+        r = pa_sprintf_malloc("%s" PA_PATH_SEP "%s", rtp, fn);
+        pa_xfree(rtp);
+        return r;
+    } else
+        return rtp;
 }
 
 /* Convert the string s to a signed integer in *ret_i */
@@ -1484,23 +1633,6 @@ char *pa_getcwd(void) {
     }
 }
 
-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;
@@ -1606,3 +1738,249 @@ char *pa_readlink(const char *p) {
         l *= 2;
     }
 }
+
+int pa_close_all(int except_fd, ...) {
+    va_list ap;
+    int n = 0, i, r;
+    int *p;
+
+    va_start(ap, except_fd);
+
+    if (except_fd >= 0)
+        for (n = 1; va_arg(ap, int) >= 0; n++)
+            ;
+
+    va_end(ap);
+
+    p = pa_xnew(int, n+1);
+
+    va_start(ap, except_fd);
+
+    i = 0;
+    if (except_fd >= 0) {
+        p[i++] = except_fd;
+
+        while ((p[i++] = va_arg(ap, int)) >= 0)
+            ;
+    }
+    p[i] = -1;
+
+    va_end(ap);
+
+    r = pa_close_allv(p);
+    free(p);
+
+    return r;
+}
+
+int pa_close_allv(const int except_fds[]) {
+    struct rlimit rl;
+    int fd;
+    int saved_errno;
+
+#ifdef __linux__
+
+    DIR *d;
+
+    if ((d = opendir("/proc/self/fd"))) {
+
+        struct dirent *de;
+
+        while ((de = readdir(d))) {
+            long l;
+            char *e = NULL;
+            int i;
+
+            if (de->d_name[0] == '.')
+                continue;
+
+            errno = 0;
+            l = strtol(de->d_name, &e, 10);
+            if (errno != 0 || !e || *e) {
+                closedir(d);
+                errno = EINVAL;
+                return -1;
+            }
+
+            fd = (int) l;
+
+            if ((long) fd != l) {
+                closedir(d);
+                errno = EINVAL;
+                return -1;
+            }
+
+            if (fd <= 3)
+                continue;
+
+            if (fd == dirfd(d))
+                continue;
+
+            for (i = 0; except_fds[i] >= 0; i++)
+                if (except_fds[i] == fd)
+                    continue;
+
+            if (close(fd) < 0) {
+                saved_errno = errno;
+                closedir(d);
+                errno = saved_errno;
+
+                return -1;
+            }
+        }
+
+        closedir(d);
+        return 0;
+    }
+
+#endif
+
+    if (getrlimit(RLIMIT_NOFILE, &rl) < 0)
+        return -1;
+
+    for (fd = 0; fd < (int) rl.rlim_max; fd++) {
+        int i;
+
+        if (fd <= 3)
+            continue;
+
+        for (i = 0; except_fds[i] >= 0; i++)
+            if (except_fds[i] == fd)
+                continue;
+
+        if (close(fd) < 0 && errno != EBADF)
+            return -1;
+    }
+
+    return 0;
+}
+
+int pa_unblock_sigs(int except, ...) {
+    va_list ap;
+    int n = 0, i, r;
+    int *p;
+
+    va_start(ap, except);
+
+    if (except >= 1)
+        for (n = 1; va_arg(ap, int) >= 0; n++)
+            ;
+
+    va_end(ap);
+
+    p = pa_xnew(int, n+1);
+
+    va_start(ap, except);
+
+    i = 0;
+    if (except >= 1) {
+        p[i++] = except;
+
+        while ((p[i++] = va_arg(ap, int)) >= 0)
+            ;
+    }
+    p[i] = -1;
+
+    va_end(ap);
+
+    r = pa_unblock_sigsv(p);
+    pa_xfree(p);
+
+    return r;
+}
+
+int pa_unblock_sigsv(const int except[]) {
+    int i;
+    sigset_t ss;
+
+    if (sigemptyset(&ss) < 0)
+        return -1;
+
+    for (i = 0; except[i] > 0; i++)
+        if (sigaddset(&ss, except[i]) < 0)
+            return -1;
+
+    return sigprocmask(SIG_SETMASK, &ss, NULL);
+}
+
+int pa_reset_sigs(int except, ...) {
+    va_list ap;
+    int n = 0, i, r;
+    int *p;
+
+    va_start(ap, except);
+
+    if (except >= 1)
+        for (n = 1; va_arg(ap, int) >= 0; n++)
+            ;
+
+    va_end(ap);
+
+    p = pa_xnew(int, n+1);
+
+    va_start(ap, except);
+
+    i = 0;
+    if (except >= 1) {
+        p[i++] = except;
+
+        while ((p[i++] = va_arg(ap, int)) >= 0)
+            ;
+    }
+    p[i] = -1;
+
+    va_end(ap);
+
+    r = pa_reset_sigsv(p);
+    pa_xfree(p);
+
+    return r;
+}
+
+int pa_reset_sigsv(const int except[]) {
+    int sig;
+
+    for (sig = 1; sig < _NSIG; sig++) {
+        int reset = 1;
+
+        switch (sig) {
+            case SIGKILL:
+            case SIGSTOP:
+                reset = 0;
+                break;
+
+            default: {
+                int i;
+
+                for (i = 0; except[i] > 0; i++) {
+                    if (sig == except[i]) {
+                        reset = 0;
+                        break;
+                    }
+                }
+            }
+        }
+
+        if (reset) {
+            struct sigaction sa;
+
+            memset(&sa, 0, sizeof(sa));
+            sa.sa_handler = SIG_DFL;
+
+            /* On Linux the first two RT signals are reserved by
+             * glibc, and sigaction() will return EINVAL for them. */
+            if ((sigaction(sig, &sa, NULL) < 0))
+                if (errno != EINVAL)
+                    return -1;
+        }
+    }
+
+    return 0;
+}
+
+void pa_set_env(const char *key, const char *value) {
+    pa_assert(key);
+    pa_assert(value);
+
+    putenv(pa_sprintf_malloc("%s=%s", key, value));
+}
diff --git a/src/pulsecore/core-util.h b/src/pulsecore/core-util.h
index d5c0a3f..49315b5 100644
--- a/src/pulsecore/core-util.h
+++ b/src/pulsecore/core-util.h
@@ -30,11 +30,27 @@
 #include <stdarg.h>
 #include <stdio.h>
 
+#ifdef HAVE_SYS_RESOURCE_H
+#include <sys/resource.h>
+#endif
+
 #include <pulse/gccmacro.h>
 #include <pulsecore/macro.h>
 
 struct timeval;
 
+/* These resource limits are pretty new on Linux, let's define them
+ * here manually, in case the kernel is newer than the glibc */
+#if !defined(RLIMIT_NICE) && defined(__linux__)
+#define RLIMIT_NICE 13
+#endif
+#if !defined(RLIMIT_RTPRIO) && defined(__linux__)
+#define RLIMIT_RTPRIO 14
+#endif
+#if !defined(RLIMIT_RTTIME) && defined(__linux__)
+#define RLIMIT_RTTIME 15
+#endif
+
 void pa_make_fd_nonblock(int fd);
 void pa_make_fd_cloexec(int fd);
 
@@ -61,6 +77,9 @@ int pa_make_realtime(int rtprio);
 int pa_raise_priority(int nice_level);
 void pa_reset_priority(void);
 
+pa_bool_t pa_can_realtime(void);
+pa_bool_t pa_can_high_priority(void);
+
 int pa_parse_boolean(const char *s) PA_GCC_PURE;
 
 static inline const char *pa_yes_no(pa_bool_t b) {
@@ -71,6 +90,10 @@ static inline const char *pa_strnull(const char *x) {
     return x ? x : "(null)";
 }
 
+static inline const char *pa_strempty(const char *x) {
+    return x ? x : "";
+}
+
 char *pa_split(const char *c, const char*delimiters, const char **state);
 char *pa_split_spaces(const char *c, const char **state);
 
@@ -88,15 +111,17 @@ int pa_lock_fd(int fd, int b);
 int pa_lock_lockfile(const char *fn);
 int pa_unlock_lockfile(const char *fn, int fd);
 
-FILE *pa_open_config_file(const char *global, const char *local, const char *env, char **result, const char *mode);
-
 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) 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);
+FILE *pa_open_config_file(const char *global, const char *local, const char *env, char **result);
+char* pa_find_config_file(const char *global, const char *local, const char *env);
+
+char *pa_get_runtime_dir(void);
+char *pa_runtime_path(const char *fn);
 
 int pa_atoi(const char *s, int32_t *ret_i);
 int pa_atou(const char *s, uint32_t *ret_u);
@@ -108,6 +133,7 @@ char *pa_truncate_utf8(char *c, size_t l);
 
 char *pa_getcwd(void);
 char *pa_make_path_absolute(const char *p);
+pa_bool_t pa_is_path_absolute(const char *p);
 
 void *pa_will_need(const void *p, size_t l);
 
@@ -133,6 +159,13 @@ void pa_close_pipe(int fds[2]);
 
 char *pa_readlink(const char *p);
 
-char *pa_get_state_dir(void);
+int pa_close_all(int except_fd, ...);
+int pa_close_allv(const int except_fds[]);
+int pa_unblock_sigs(int except, ...);
+int pa_unblock_sigsv(const int except[]);
+int pa_reset_sigs(int except, ...);
+int pa_reset_sigsv(const int except[]);
+
+void pa_set_env(const char *key, const char *value);
 
 #endif
diff --git a/src/pulsecore/native-common.h b/src/pulsecore/native-common.h
index 51f2b30..56f9037 100644
--- a/src/pulsecore/native-common.h
+++ b/src/pulsecore/native-common.h
@@ -147,6 +147,9 @@ enum {
     PA_COMMAND_REMOVE_PLAYBACK_STREAM_PROPLIST,
     PA_COMMAND_REMOVE_CLIENT_PROPLIST,
 
+    /* SERVER->CLIENT */
+    PA_COMMAND_STARTED,
+
     PA_COMMAND_MAX
 };
 
diff --git a/src/pulsecore/pid.c b/src/pulsecore/pid.c
index f3c9faa..2ff132b 100644
--- a/src/pulsecore/pid.c
+++ b/src/pulsecore/pid.c
@@ -144,16 +144,16 @@ fail:
 int pa_pid_file_create(void) {
     int fd = -1;
     int ret = -1;
-    char fn[PATH_MAX];
     char t[20];
     pid_t pid;
     size_t l;
+    char *fn;
 
 #ifdef OS_IS_WIN32
     HANDLE process;
 #endif
 
-    pa_runtime_path("pid", fn, sizeof(fn));
+    fn = pa_runtime_path("pid");
 
     if ((fd = open_pid_file(fn, O_CREAT|O_RDWR)) < 0)
         goto fail;
@@ -200,17 +200,19 @@ fail:
         }
     }
 
+    pa_xfree(fn);
+
     return ret;
 }
 
 /* Remove the PID file, if it is ours */
 int pa_pid_file_remove(void) {
     int fd = -1;
-    char fn[PATH_MAX];
+    char *fn;
     int ret = -1;
     pid_t pid;
 
-    pa_runtime_path("pid", fn, sizeof(fn));
+    fn = pa_runtime_path("pid");
 
     if ((fd = open_pid_file(fn, O_RDWR)) < 0) {
         pa_log_warn("Failed to open PID file '%s': %s", fn, pa_cstrerror(errno));
@@ -254,6 +256,8 @@ fail:
         }
     }
 
+    pa_xfree(fn);
+
     return ret;
 }
 
@@ -272,7 +276,7 @@ int pa_pid_file_check_running(pid_t *pid, const char *binary_name) {
  * process. */
 int pa_pid_file_kill(int sig, pid_t *pid, const char *binary_name) {
     int fd = -1;
-    char fn[PATH_MAX];
+    char *fn;
     int ret = -1;
     pid_t _pid;
 #ifdef __linux__
@@ -281,7 +285,7 @@ int pa_pid_file_kill(int sig, pid_t *pid, const char *binary_name) {
     if (!pid)
         pid = &_pid;
 
-    pa_runtime_path("pid", fn, sizeof(fn));
+    fn = pa_runtime_path("pid");
 
     if ((fd = open_pid_file(fn, O_RDONLY)) < 0)
         goto fail;
@@ -296,7 +300,7 @@ int pa_pid_file_kill(int sig, pid_t *pid, const char *binary_name) {
         if ((e = pa_readlink(fn))) {
             char *f = pa_path_get_filename(e);
             if (strcmp(f, binary_name)
-#if defined(__OPTIMIZE__)
+#if !defined(__OPTIMIZE__)
                 /* libtool likes to rename our binary names ... */
                 && !(pa_startswith(f, "lt-") && strcmp(f+3, binary_name) == 0)
 #endif
@@ -319,6 +323,8 @@ fail:
     pa_xfree(e);
 #endif
 
+    pa_xfree(fn);
+
     return ret;
 
 }
diff --git a/src/pulsecore/protocol-cli.c b/src/pulsecore/protocol-cli.c
index ceb6ae4..2f797a1 100644
--- a/src/pulsecore/protocol-cli.c
+++ b/src/pulsecore/protocol-cli.c
@@ -82,7 +82,7 @@ pa_protocol_cli* pa_protocol_cli_new(pa_core *core, pa_socket_server *server, pa
     p = pa_xnew(pa_protocol_cli, 1);
     p->module = m;
     p->core = core;
-    p->server = server;
+    p->server = pa_socket_server_ref(server);
     p->connections = pa_idxset_new(NULL, NULL);
 
     pa_socket_server_set_callback(p->server, on_connection, p);
diff --git a/src/pulsecore/protocol-esound.c b/src/pulsecore/protocol-esound.c
index 59a4208..388808a 100644
--- a/src/pulsecore/protocol-esound.c
+++ b/src/pulsecore/protocol-esound.c
@@ -1433,7 +1433,7 @@ pa_protocol_esound* pa_protocol_esound_new(pa_core*core, pa_socket_server *serve
     p->core = core;
     p->module = m;
     p->public = public;
-    p->server = server;
+    p->server = pa_socket_server_ref(server);
     pa_socket_server_set_callback(p->server, on_connection, p);
     p->connections = pa_idxset_new(NULL, NULL);
 
diff --git a/src/pulsecore/protocol-http.c b/src/pulsecore/protocol-http.c
index 589eba4..bc2e9af 100644
--- a/src/pulsecore/protocol-http.c
+++ b/src/pulsecore/protocol-http.c
@@ -255,7 +255,7 @@ pa_protocol_http* pa_protocol_http_new(pa_core *core, pa_socket_server *server,
     p = pa_xnew(pa_protocol_http, 1);
     p->module = m;
     p->core = core;
-    p->server = server;
+    p->server = pa_socket_server_ref(server);
     p->connections = pa_idxset_new(NULL, NULL);
 
     pa_socket_server_set_callback(p->server, on_connection, p);
diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c
index ca14b95..5fee4cc 100644
--- a/src/pulsecore/protocol-native.c
+++ b/src/pulsecore/protocol-native.c
@@ -105,7 +105,6 @@ typedef struct playback_stream {
     pa_bool_t drain_request;
     uint32_t drain_tag;
     uint32_t syncid;
-    uint64_t underrun; /* length of underrun */
 
     pa_atomic_t missing;
     size_t minreq;
@@ -193,7 +192,8 @@ 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
+    PLAYBACK_STREAM_MESSAGE_DRAIN_ACK,
+    PLAYBACK_STREAM_MESSAGE_STARTED
 };
 
 enum {
@@ -689,10 +689,24 @@ static int playback_stream_process_msg(pa_msgobject *o, int code, void*userdata,
             break;
         }
 
+        case PLAYBACK_STREAM_MESSAGE_STARTED:
+
+            if (s->connection->version >= 13) {
+                pa_tagstruct *t;
+
+                /* Notify the user we're overflowed*/
+                t = pa_tagstruct_new(NULL, 0);
+                pa_tagstruct_putu32(t, PA_COMMAND_STARTED);
+                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_DRAIN_ACK:
             pa_pstream_send_simple_ack(s->connection->pstream, PA_PTR_TO_UINT(userdata));
             break;
-
     }
 
     return 0;
@@ -886,7 +900,6 @@ static playback_stream* playback_stream_new(
     s->connection = c;
     s->syncid = syncid;
     s->sink_input = sink_input;
-    s->underrun = (uint64_t) -1;
 
     s->sink_input->parent.process_msg = sink_input_process_msg;
     s->sink_input->pop = sink_input_pop_cb;
@@ -1091,7 +1104,7 @@ static void handle_seek(playback_stream *s, int64_t indexw) {
 
 /*     pa_log("handle_seek: %llu -- %i", (unsigned long long) s->underrun, pa_memblockq_is_readable(s->memblockq)); */
 
-    if (s->underrun != 0) {
+    if (s->sink_input->thread_info.underrun_for > 0) {
 
 /*         pa_log("%lu vs. %lu", (unsigned long) pa_memblockq_get_length(s->memblockq), (unsigned long) pa_memblockq_get_prebuf(s->memblockq)); */
 
@@ -1099,13 +1112,13 @@ static void handle_seek(playback_stream *s, int64_t indexw) {
 
             size_t u = pa_memblockq_get_length(s->memblockq);
 
-            if (u >= s->underrun)
-                u = s->underrun;
+            if (u >= s->sink_input->thread_info.underrun_for)
+                u = s->sink_input->thread_info.underrun_for;
 
             /* We just ended an underrun, let's ask the sink
              * to rewrite */
-            s->sink_input->thread_info.ignore_rewind = TRUE;
-            pa_sink_input_request_rewind(s->sink_input, u, TRUE);
+
+            pa_sink_input_request_rewind(s->sink_input, u, TRUE, TRUE);
         }
 
     } else {
@@ -1117,7 +1130,7 @@ static void handle_seek(playback_stream *s, int64_t indexw) {
             /* OK, the sink already asked for this data, so
              * let's have it usk us again */
 
-            pa_sink_input_request_rewind(s->sink_input, indexr - indexw, FALSE);
+            pa_sink_input_request_rewind(s->sink_input, indexr - indexw, FALSE, FALSE);
     }
 
     request_bytes(s);
@@ -1272,12 +1285,9 @@ static int sink_input_pop_cb(pa_sink_input *i, size_t nbytes, pa_memchunk *chunk
         if (s->drain_request && pa_sink_input_safe_to_remove(i)) {
             s->drain_request = FALSE;
             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);
-        } else if (s->underrun == 0)
+        } else if (i->thread_info.playing_for > 0)
             pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(s), PLAYBACK_STREAM_MESSAGE_UNDERFLOW, NULL, 0, NULL, NULL);
 
-        if (s->underrun != (size_t) -1)
-            s->underrun += nbytes;
-
 /*         pa_log("added %llu bytes, total is %llu", (unsigned long long) nbytes, (unsigned long long) s->underrun); */
 
         request_bytes(s);
@@ -1287,7 +1297,8 @@ static int sink_input_pop_cb(pa_sink_input *i, size_t nbytes, pa_memchunk *chunk
 
 /*     pa_log("NOTUNDERRUN"); */
 
-    s->underrun = 0;
+    if (i->thread_info.underrun_for > 0)
+        pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(s), PLAYBACK_STREAM_MESSAGE_STARTED, NULL, 0, NULL, NULL);
 
     pa_memblockq_drop(s->memblockq, chunk->length);
     request_bytes(s);
@@ -1303,7 +1314,7 @@ static void sink_input_process_rewind_cb(pa_sink_input *i, size_t nbytes) {
     playback_stream_assert_ref(s);
 
     /* If we are in an underrun, then we don't rewind */
-    if (s->underrun != 0)
+    if (i->thread_info.underrun_for > 0)
         return;
 
     pa_memblockq_rewind(s->memblockq, nbytes);
@@ -2120,11 +2131,17 @@ static void command_get_playback_latency(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_
     pa_tagstruct_put_usec(reply, latency);
 
     pa_tagstruct_put_usec(reply, 0);
-    pa_tagstruct_put_boolean(reply, pa_sink_input_get_state(s->sink_input) == PA_SINK_INPUT_RUNNING);
+    pa_tagstruct_put_boolean(reply, s->sink_input->thread_info.playing_for > 0);
     pa_tagstruct_put_timeval(reply, &tv);
     pa_tagstruct_put_timeval(reply, pa_gettimeofday(&now));
     pa_tagstruct_puts64(reply, s->write_index);
     pa_tagstruct_puts64(reply, s->read_index);
+
+    if (c->version >= 13) {
+        pa_tagstruct_putu64(reply, s->sink_input->thread_info.underrun_for);
+        pa_tagstruct_putu64(reply, s->sink_input->thread_info.playing_for);
+    }
+
     pa_pstream_send_tagstruct(c->pstream, reply);
 }
 
@@ -2152,7 +2169,7 @@ static void command_get_record_latency(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UN
     reply = reply_new(tag);
     pa_tagstruct_put_usec(reply, s->source_output->source->monitor_of ? pa_sink_get_latency(s->source_output->source->monitor_of) : 0);
     pa_tagstruct_put_usec(reply, pa_source_get_latency(s->source_output->source));
-    pa_tagstruct_put_boolean(reply, FALSE);
+    pa_tagstruct_put_boolean(reply, pa_source_get_state(s->source_output->source) == PA_SOURCE_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));
@@ -3937,7 +3954,7 @@ static pa_protocol_native* protocol_new_internal(pa_core *c, pa_module *m, pa_mo
 
 #ifdef HAVE_CREDS
     {
-        pa_bool_t a = 1;
+        pa_bool_t a = TRUE;
         if (pa_modargs_get_value_boolean(ma, "auth-group-enabled", &a) < 0) {
             pa_log("auth-group-enabled= expects a boolean argument.");
             return NULL;
@@ -3982,7 +3999,7 @@ pa_protocol_native* pa_protocol_native_new(pa_core *core, pa_socket_server *serv
     if (!(p = protocol_new_internal(core, m, ma)))
         return NULL;
 
-    p->server = server;
+    p->server = pa_socket_server_ref(server);
     pa_socket_server_set_callback(p->server, on_connection, p);
 
     if (pa_socket_server_get_address(p->server, t, sizeof(t))) {
diff --git a/src/pulsecore/protocol-simple.c b/src/pulsecore/protocol-simple.c
index 3ee2a05..8ec38fe 100644
--- a/src/pulsecore/protocol-simple.c
+++ b/src/pulsecore/protocol-simple.c
@@ -587,7 +587,7 @@ pa_protocol_simple* pa_protocol_simple_new(pa_core *core, pa_socket_server *serv
     p = pa_xnew0(pa_protocol_simple, 1);
     p->module = m;
     p->core = core;
-    p->server = server;
+    p->server = pa_socket_server_ref(server);
     p->connections = pa_idxset_new(NULL, NULL);
 
     p->sample_spec = core->default_sample_spec;
diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c
index 8df3687..1da920a 100644
--- a/src/pulsecore/sink-input.c
+++ b/src/pulsecore/sink-input.c
@@ -106,6 +106,7 @@ static void reset_callbacks(pa_sink_input *i) {
     i->moved = NULL;
     i->kill = NULL;
     i->get_latency = NULL;
+    i->state_change = NULL;
 }
 
 pa_sink_input* pa_sink_input_new(
@@ -249,8 +250,8 @@ pa_sink_input* pa_sink_input_new(
     i->thread_info.muted = i->muted;
     i->thread_info.requested_sink_latency = (pa_usec_t) -1;
     i->thread_info.rewrite_nbytes = 0;
-    i->thread_info.since_underrun = 0;
-    i->thread_info.ignore_rewind = FALSE;
+    i->thread_info.underrun_for = (uint64_t) -1;
+    i->thread_info.playing_for = 0;
 
     i->thread_info.render_memblockq = pa_memblockq_new(
             0,
@@ -328,7 +329,7 @@ void pa_sink_input_unlink(pa_sink_input *i) {
 
     pa_sink_input_ref(i);
 
-    linked = PA_SINK_INPUT_LINKED(i->state);
+    linked = PA_SINK_INPUT_IS_LINKED(i->state);
 
     if (linked)
         pa_hook_fire(&i->sink->core->hooks[PA_CORE_HOOK_SINK_INPUT_UNLINK], i);
@@ -344,12 +345,11 @@ void pa_sink_input_unlink(pa_sink_input *i) {
     if (pa_idxset_remove_by_data(i->sink->inputs, i, NULL))
         pa_sink_input_unref(i);
 
-    if (linked) {
+    update_n_corked(i, PA_SINK_INPUT_UNLINKED);
+    i->state = PA_SINK_INPUT_UNLINKED;
+
+    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;
 
     reset_callbacks(i);
 
@@ -368,7 +368,7 @@ static void sink_input_free(pa_object *o) {
     pa_assert(i);
     pa_assert(pa_sink_input_refcnt(i) == 0);
 
-    if (PA_SINK_INPUT_LINKED(i->state))
+    if (PA_SINK_INPUT_IS_LINKED(i->state))
         pa_sink_input_unlink(i);
 
     pa_log_info("Freeing input %u \"%s\"", i->index, pa_strnull(pa_proplist_gets(i->proplist, PA_PROP_MEDIA_NAME)));
@@ -402,7 +402,7 @@ void pa_sink_input_put(pa_sink_input *i) {
     state = i->flags & PA_SINK_INPUT_START_CORKED ? PA_SINK_INPUT_CORKED : PA_SINK_INPUT_RUNNING;
 
     update_n_corked(i, state);
-    i->thread_info.state = i->state = state;
+    i->state = state;
 
     pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i->sink), PA_SINK_MESSAGE_ADD_INPUT, i, 0, NULL);
 
@@ -416,7 +416,7 @@ void pa_sink_input_put(pa_sink_input *i) {
 
 void pa_sink_input_kill(pa_sink_input*i) {
     pa_sink_input_assert_ref(i);
-    pa_assert(PA_SINK_INPUT_LINKED(i->state));
+    pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
 
     if (i->kill)
         i->kill(i);
@@ -426,7 +426,7 @@ pa_usec_t pa_sink_input_get_latency(pa_sink_input *i) {
     pa_usec_t r = 0;
 
     pa_sink_input_assert_ref(i);
-    pa_assert(PA_SINK_INPUT_LINKED(i->state));
+    pa_assert(PA_SINK_INPUT_IS_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;
@@ -445,7 +445,7 @@ int pa_sink_input_peek(pa_sink_input *i, size_t slength /* in sink frames */, pa
     size_t ilength;
 
     pa_sink_input_assert_ref(i);
-    pa_assert(PA_SINK_INPUT_LINKED(i->thread_info.state));
+    pa_assert(PA_SINK_INPUT_IS_LINKED(i->thread_info.state));
     pa_assert(pa_frame_aligned(slength, &i->sink->sample_spec));
     pa_assert(chunk);
     pa_assert(volume);
@@ -510,7 +510,9 @@ int pa_sink_input_peek(pa_sink_input *i, size_t slength /* in sink frames */, pa
             pa_atomic_store(&i->thread_info.drained, 1);
 
             pa_memblockq_seek(i->thread_info.render_memblockq, slength, PA_SEEK_RELATIVE_ON_READ);
-            i->thread_info.since_underrun = 0;
+            i->thread_info.playing_for = 0;
+            if (i->thread_info.underrun_for != (uint64_t) -1)
+                i->thread_info.underrun_for += slength;
             break;
         }
 
@@ -519,7 +521,8 @@ int pa_sink_input_peek(pa_sink_input *i, size_t slength /* in sink frames */, pa
         pa_assert(tchunk.length > 0);
         pa_assert(tchunk.memblock);
 
-        i->thread_info.since_underrun += tchunk.length;
+        i->thread_info.underrun_for = 0;
+        i->thread_info.playing_for += tchunk.length;
 
         while (tchunk.length > 0) {
             pa_memchunk wchunk;
@@ -590,7 +593,7 @@ int pa_sink_input_peek(pa_sink_input *i, size_t slength /* in sink frames */, pa
 void pa_sink_input_drop(pa_sink_input *i, size_t nbytes /* in sink sample spec */) {
     pa_sink_input_assert_ref(i);
 
-    pa_assert(PA_SINK_INPUT_LINKED(i->thread_info.state));
+    pa_assert(PA_SINK_INPUT_IS_LINKED(i->thread_info.state));
     pa_assert(pa_frame_aligned(nbytes, &i->sink->sample_spec));
     pa_assert(nbytes > 0);
 
@@ -610,13 +613,13 @@ void pa_sink_input_drop(pa_sink_input *i, size_t nbytes /* in sink sample spec *
 void pa_sink_input_process_rewind(pa_sink_input *i, size_t nbytes /* in sink sample spec */) {
     pa_sink_input_assert_ref(i);
 
-    pa_assert(PA_SINK_INPUT_LINKED(i->thread_info.state));
+    pa_assert(PA_SINK_INPUT_IS_LINKED(i->thread_info.state));
     pa_assert(pa_frame_aligned(nbytes, &i->sink->sample_spec));
 
 /*     pa_log_debug("rewind(%lu, %lu)", (unsigned long) nbytes, (unsigned long) i->thread_info.rewrite_nbytes); */
 
-    if (i->thread_info.ignore_rewind) {
-        i->thread_info.ignore_rewind = FALSE;
+    if (i->thread_info.underrun_for > 0) {
+        /* We don't rewind when we are underrun */
         i->thread_info.rewrite_nbytes = 0;
         return;
     }
@@ -668,7 +671,7 @@ void pa_sink_input_process_rewind(pa_sink_input *i, size_t nbytes /* in sink sam
 /* Called from thread context */
 void pa_sink_input_update_max_rewind(pa_sink_input *i, size_t nbytes  /* in the sink's sample spec */) {
     pa_sink_input_assert_ref(i);
-    pa_assert(PA_SINK_INPUT_LINKED(i->thread_info.state));
+    pa_assert(PA_SINK_INPUT_IS_LINKED(i->thread_info.state));
     pa_assert(pa_frame_aligned(nbytes, &i->sink->sample_spec));
 
     pa_memblockq_set_maxrewind(i->thread_info.render_memblockq, nbytes);
@@ -677,21 +680,41 @@ void pa_sink_input_update_max_rewind(pa_sink_input *i, size_t nbytes  /* in the
         i->update_max_rewind(i, i->thread_info.resampler ? pa_resampler_request(i->thread_info.resampler, nbytes) : nbytes);
 }
 
-pa_usec_t pa_sink_input_set_requested_latency(pa_sink_input *i, pa_usec_t usec) {
-    pa_sink_input_assert_ref(i);
+static pa_usec_t fixup_latency(pa_sink *s, pa_usec_t usec) {
+    pa_sink_assert_ref(s);
 
-    if (usec != (pa_usec_t) -1) {
+    if (usec == (pa_usec_t) -1)
+        return usec;
 
-        if (i->sink->max_latency > 0 && usec > i->sink->max_latency)
-            usec = i->sink->max_latency;
+    if (s->max_latency > 0 && usec > s->max_latency)
+        usec = s->max_latency;
 
-        if (i->sink->min_latency > 0 && usec < i->sink->min_latency)
-            usec = i->sink->min_latency;
-    }
+    if (s->min_latency > 0 && usec < s->min_latency)
+        usec = s->min_latency;
+
+    return usec;
+}
+
+pa_usec_t pa_sink_input_set_requested_latency_within_thread(pa_sink_input *i, pa_usec_t usec) {
+
+    usec = fixup_latency(i->sink, usec);
+
+    i->thread_info.requested_sink_latency = usec;
+    pa_sink_invalidate_requested_latency(i->sink);
 
-    if (PA_SINK_INPUT_LINKED(i->state))
+    return usec;
+}
+
+pa_usec_t pa_sink_input_set_requested_latency(pa_sink_input *i, pa_usec_t usec) {
+    pa_sink_input_assert_ref(i);
+
+    usec = fixup_latency(i->sink, usec);
+
+    if (PA_SINK_INPUT_IS_LINKED(i->state))
         pa_asyncmsgq_post(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_SET_REQUESTED_LATENCY, NULL, (int64_t) usec, NULL, NULL);
     else {
+        /* If this sink input is not realized yet, we have to touch
+         * the thread info data directly */
         i->thread_info.requested_sink_latency = usec;
         i->sink->thread_info.requested_latency_valid = FALSE;
     }
@@ -701,7 +724,7 @@ pa_usec_t pa_sink_input_set_requested_latency(pa_sink_input *i, pa_usec_t usec)
 
 void pa_sink_input_set_volume(pa_sink_input *i, const pa_cvolume *volume) {
     pa_sink_input_assert_ref(i);
-    pa_assert(PA_SINK_INPUT_LINKED(i->state));
+    pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
 
     if (pa_cvolume_equal(&i->volume, volume))
         return;
@@ -714,7 +737,7 @@ 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) {
     pa_sink_input_assert_ref(i);
-    pa_assert(PA_SINK_INPUT_LINKED(i->state));
+    pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
 
     return &i->volume;
 }
@@ -722,7 +745,7 @@ 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) {
     pa_assert(i);
     pa_sink_input_assert_ref(i);
-    pa_assert(PA_SINK_INPUT_LINKED(i->state));
+    pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
 
     if (!i->muted == !mute)
         return;
@@ -735,21 +758,21 @@ void pa_sink_input_set_mute(pa_sink_input *i, pa_bool_t mute) {
 
 int pa_sink_input_get_mute(pa_sink_input *i) {
     pa_sink_input_assert_ref(i);
-    pa_assert(PA_SINK_INPUT_LINKED(i->state));
+    pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
 
     return !!i->muted;
 }
 
 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));
+    pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
 
     sink_input_set_state(i, b ? PA_SINK_INPUT_CORKED : PA_SINK_INPUT_RUNNING);
 }
 
 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_assert(PA_SINK_INPUT_IS_LINKED(i->state));
     pa_return_val_if_fail(i->thread_info.resampler, -1);
 
     if (i->sample_spec.rate == rate)
@@ -780,7 +803,7 @@ void pa_sink_input_set_name(pa_sink_input *i, const char *name) {
     else
         pa_proplist_unset(i->proplist, PA_PROP_MEDIA_NAME);
 
-    if (PA_SINK_INPUT_LINKED(i->state)) {
+    if (PA_SINK_INPUT_IS_LINKED(i->state)) {
         pa_hook_fire(&i->sink->core->hooks[PA_CORE_HOOK_SINK_INPUT_PROPLIST_CHANGED], i);
         pa_subscription_post(i->sink->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index);
     }
@@ -792,7 +815,7 @@ pa_resample_method_t pa_sink_input_get_resample_method(pa_sink_input *i) {
     return i->resample_method;
 }
 
-int pa_sink_input_move_to(pa_sink_input *i, pa_sink *dest, int immediately) {
+int pa_sink_input_move_to(pa_sink_input *i, pa_sink *dest, pa_bool_t immediately) {
     pa_resampler *new_resampler;
     pa_sink *origin;
     pa_usec_t silence_usec = 0;
@@ -800,7 +823,7 @@ int pa_sink_input_move_to(pa_sink_input *i, pa_sink *dest, int immediately) {
     pa_sink_input_move_hook_data hook_data;
 
     pa_sink_input_assert_ref(i);
-    pa_assert(PA_SINK_INPUT_LINKED(i->state));
+    pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
     pa_sink_assert_ref(dest);
 
     origin = i->sink;
@@ -983,7 +1006,7 @@ int pa_sink_input_move_to(pa_sink_input *i, pa_sink *dest, int immediately) {
     return 0;
 }
 
-static void set_state(pa_sink_input *i, pa_sink_input_state_t state) {
+void pa_sink_input_set_state_within_thread(pa_sink_input *i, pa_sink_input_state_t state) {
     pa_sink_input_assert_ref(i);
 
     if ((state == PA_SINK_INPUT_DRAINED || state == PA_SINK_INPUT_RUNNING) &&
@@ -998,17 +1021,18 @@ static void set_state(pa_sink_input *i, pa_sink_input_state_t state) {
 
         /* This will tell the implementing sink input driver to rewind
          * so that the unplayed already mixed data is not lost */
-        pa_sink_input_request_rewind(i, 0, FALSE);
+        pa_sink_input_request_rewind(i, 0, FALSE, FALSE);
 
     } else if (i->thread_info.state == PA_SINK_INPUT_CORKED && state != PA_SINK_INPUT_CORKED) {
 
         /* OK, we're being uncorked. Make sure we're not rewound when
          * the hw buffer is remixed and request a remix. */
-        i->thread_info.ignore_rewind = TRUE;
-        i->thread_info.since_underrun = 0;
-        pa_sink_request_rewind(i->sink, 0);
+        pa_sink_input_request_rewind(i, 0, TRUE, TRUE);
     }
 
+    if (i->state_change)
+        i->state_change(i, state);
+
     i->thread_info.state = state;
 }
 
@@ -1017,17 +1041,17 @@ int pa_sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int64_t
     pa_sink_input *i = PA_SINK_INPUT(o);
 
     pa_sink_input_assert_ref(i);
-    pa_assert(PA_SINK_INPUT_LINKED(i->thread_info.state));
+    pa_assert(PA_SINK_INPUT_IS_LINKED(i->thread_info.state));
 
     switch (code) {
         case PA_SINK_INPUT_MESSAGE_SET_VOLUME:
             i->thread_info.volume = *((pa_cvolume*) userdata);
-            pa_sink_input_request_rewind(i, 0, FALSE);
+            pa_sink_input_request_rewind(i, 0, FALSE, FALSE);
             return 0;
 
         case PA_SINK_INPUT_MESSAGE_SET_MUTE:
             i->thread_info.muted = PA_PTR_TO_UINT(userdata);
-            pa_sink_input_request_rewind(i, 0, FALSE);
+            pa_sink_input_request_rewind(i, 0, FALSE, FALSE);
             return 0;
 
         case PA_SINK_INPUT_MESSAGE_GET_LATENCY: {
@@ -1048,22 +1072,20 @@ int pa_sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int64_t
         case PA_SINK_INPUT_MESSAGE_SET_STATE: {
             pa_sink_input *ssync;
 
-            set_state(i, PA_PTR_TO_UINT(userdata));
+            pa_sink_input_set_state_within_thread(i, PA_PTR_TO_UINT(userdata));
 
             for (ssync = i->thread_info.sync_prev; ssync; ssync = ssync->thread_info.sync_prev)
-                set_state(ssync, PA_PTR_TO_UINT(userdata));
+                pa_sink_input_set_state_within_thread(ssync, PA_PTR_TO_UINT(userdata));
 
             for (ssync = i->thread_info.sync_next; ssync; ssync = ssync->thread_info.sync_next)
-                set_state(ssync, PA_PTR_TO_UINT(userdata));
+                pa_sink_input_set_state_within_thread(ssync, PA_PTR_TO_UINT(userdata));
 
             return 0;
         }
 
         case PA_SINK_INPUT_MESSAGE_SET_REQUESTED_LATENCY:
 
-            i->thread_info.requested_sink_latency = (pa_usec_t) offset;
-            pa_sink_invalidate_requested_latency(i->sink);
-
+            pa_sink_input_set_requested_latency_within_thread(i, (pa_usec_t) offset);
             return 0;
     }
 
@@ -1088,8 +1110,8 @@ pa_bool_t pa_sink_input_safe_to_remove(pa_sink_input *i) {
     return TRUE;
 }
 
-void pa_sink_input_request_rewind(pa_sink_input *i, size_t nbytes  /* in our sample spec */, pa_bool_t ignore_underruns) {
-    size_t l, lbq;
+void pa_sink_input_request_rewind(pa_sink_input *i, size_t nbytes  /* in our sample spec */, pa_bool_t ignore_underruns, pa_bool_t not_here) {
+    size_t lbq;
 
     pa_sink_input_assert_ref(i);
 
@@ -1097,9 +1119,16 @@ void pa_sink_input_request_rewind(pa_sink_input *i, size_t nbytes  /* in our sam
     if (i->state == PA_SINK_INPUT_CORKED)
         return;
 
-    lbq = pa_memblockq_get_length(i->thread_info.render_memblockq);
+    /* Calculate how much we can rewind locally without having to
+     * touch the sink */
+    if (not_here)
+        lbq = 0;
+    else
+        lbq = pa_memblockq_get_length(i->thread_info.render_memblockq);
 
+    /* Check if rewinding for the maximum is requested, and if so, fix up */
     if (nbytes <= 0) {
+
         /* Calulate maximum number of bytes that could be rewound in theory */
         nbytes = i->sink->thread_info.max_rewind + lbq;
 
@@ -1110,26 +1139,33 @@ void pa_sink_input_request_rewind(pa_sink_input *i, size_t nbytes  /* in our sam
             nbytes;
     }
 
-    /* Increase the number of bytes to rewrite, never decrease */
-    if (nbytes > i->thread_info.rewrite_nbytes)
-        i->thread_info.rewrite_nbytes = nbytes;
+    if (not_here) {
+        i->thread_info.playing_for = 0;
+        i->thread_info.underrun_for = (uint64_t) -1;
+    } else {
+        /* Increase the number of bytes to rewrite, never decrease */
+        if (nbytes < i->thread_info.rewrite_nbytes)
+            nbytes = i->thread_info.rewrite_nbytes;
 
-    if (!ignore_underruns) {
         /* Make sure to not overwrite over underruns */
-        if ((int64_t) i->thread_info.rewrite_nbytes > i->thread_info.since_underrun)
-            i->thread_info.rewrite_nbytes = (size_t) i->thread_info.since_underrun;
+        if (!ignore_underruns)
+            if ((int64_t) nbytes > i->thread_info.playing_for)
+                nbytes = (size_t) i->thread_info.playing_for;
+
+        i->thread_info.rewrite_nbytes = nbytes;
     }
 
     /* Transform to sink domain */
-    l = i->thread_info.resampler ?
-        pa_resampler_result(i->thread_info.resampler, i->thread_info.rewrite_nbytes) :
-        i->thread_info.rewrite_nbytes;
+    nbytes =
+        i->thread_info.resampler ?
+        pa_resampler_result(i->thread_info.resampler, nbytes) :
+        nbytes;
 
-    if (l <= 0)
+    if (nbytes <= 0)
         return;
 
-    if (l > lbq)
-        pa_sink_request_rewind(i->sink, l - lbq);
+    if (nbytes > lbq)
+        pa_sink_request_rewind(i->sink, nbytes - lbq);
 }
 
 pa_memchunk* pa_sink_input_get_silence(pa_sink_input *i, pa_memchunk *ret) {
diff --git a/src/pulsecore/sink-input.h b/src/pulsecore/sink-input.h
index b433edc..b70cb0a 100644
--- a/src/pulsecore/sink-input.h
+++ b/src/pulsecore/sink-input.h
@@ -46,7 +46,7 @@ typedef enum pa_sink_input_state {
     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) {
+static inline pa_bool_t PA_SINK_INPUT_IS_LINKED(pa_sink_input_state_t x) {
     return x == PA_SINK_INPUT_DRAINED || x == PA_SINK_INPUT_RUNNING || x == PA_SINK_INPUT_CORKED;
 }
 
@@ -106,7 +106,7 @@ struct pa_sink_input {
     void (*process_rewind) (pa_sink_input *i, size_t nbytes);     /* may NOT be NULL */
 
     /* Called whenever the maximum rewindable size of the sink
-     * changes. Called from RT context. */
+     * changes. Called from IO context. */
     void (*update_max_rewind) (pa_sink_input *i, size_t nbytes); /* may be NULL */
 
     /* If non-NULL this function is called when the input is first
@@ -138,6 +138,10 @@ struct pa_sink_input {
     instead. */
     pa_usec_t (*get_latency) (pa_sink_input *i); /* may be NULL */
 
+    /* If non_NULL this function is called from thread context if the
+     * state changes. The old state is found in thread_info.state.  */
+    void (*state_change) (pa_sink_input *i, pa_sink_input_state_t state); /* may be NULL */
+
     struct {
         pa_sink_input_state_t state;
         pa_atomic_t drained, render_memblockq_is_empty;
@@ -152,7 +156,7 @@ struct pa_sink_input {
         pa_memblockq *render_memblockq;
 
         size_t rewrite_nbytes;
-        int64_t since_underrun;
+        uint64_t underrun_for, playing_for;
         pa_bool_t ignore_rewind;
 
         pa_sink_input *sync_prev, *sync_next;
@@ -237,7 +241,7 @@ fully -- or at all. If the request for a rewrite was successful, the
 sink driver will call ->rewind() and pass the number of bytes that
 could be rewound in the HW device. This functionality is required for
 implementing the "zero latency" write-through functionality. */
-void pa_sink_input_request_rewind(pa_sink_input *i, size_t nbytes, pa_bool_t ignore_rewind);
+void pa_sink_input_request_rewind(pa_sink_input *i, size_t nbytes, pa_bool_t ignore_rewind, pa_bool_t not_here);
 
 /* Callable by everyone from main thread*/
 
@@ -257,7 +261,7 @@ 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);
+int pa_sink_input_move_to(pa_sink_input *i, pa_sink *dest, pa_bool_t immediately);
 
 pa_sink_input_state_t pa_sink_input_get_state(pa_sink_input *i);
 
@@ -269,8 +273,12 @@ void pa_sink_input_drop(pa_sink_input *i, size_t length);
 void pa_sink_input_process_rewind(pa_sink_input *i, size_t nbytes /* in the sink's sample spec */);
 void pa_sink_input_update_max_rewind(pa_sink_input *i, size_t nbytes  /* in the sink's sample spec */);
 
+void pa_sink_input_set_state_within_thread(pa_sink_input *i, pa_sink_input_state_t state);
+
 int pa_sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offset, pa_memchunk *chunk);
 
+pa_usec_t pa_sink_input_set_requested_latency_within_thread(pa_sink_input *i, pa_usec_t usec);
+
 typedef struct pa_sink_input_move_info {
     pa_sink_input *sink_input;
     pa_sink_input *ghost_sink_input;
diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c
index 452dab7..a2a02eb 100644
--- a/src/pulsecore/sink.c
+++ b/src/pulsecore/sink.c
@@ -265,8 +265,8 @@ static int sink_set_state(pa_sink *s, pa_sink_state_t state) {
         return 0;
 
     suspend_change =
-        (s->state == PA_SINK_SUSPENDED && PA_SINK_OPENED(state)) ||
-        (PA_SINK_OPENED(s->state) && state == PA_SINK_SUSPENDED);
+        (s->state == PA_SINK_SUSPENDED && PA_SINK_IS_OPENED(state)) ||
+        (PA_SINK_IS_OPENED(s->state) && state == PA_SINK_SUSPENDED);
 
     if (s->set_state)
         if ((ret = s->set_state(s, state)) < 0)
@@ -328,7 +328,7 @@ void pa_sink_unlink(pa_sink* s) {
      * may be called multiple times on the same sink without bad
      * effects. */
 
-    linked = PA_SINK_LINKED(s->state);
+    linked = PA_SINK_IS_LINKED(s->state);
 
     if (linked)
         pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SINK_UNLINK], s);
@@ -366,7 +366,7 @@ static void sink_free(pa_object *o) {
     pa_assert(s);
     pa_assert(pa_sink_refcnt(s) == 0);
 
-    if (PA_SINK_LINKED(s->state))
+    if (PA_SINK_IS_LINKED(s->state))
         pa_sink_unlink(s);
 
     pa_log_info("Freeing sink %u \"%s\"", s->index, s->name);
@@ -397,7 +397,6 @@ static void sink_free(pa_object *o) {
 
 void pa_sink_set_asyncmsgq(pa_sink *s, pa_asyncmsgq *q) {
     pa_sink_assert_ref(s);
-    pa_assert(q);
 
     s->asyncmsgq = q;
 
@@ -407,7 +406,6 @@ void pa_sink_set_asyncmsgq(pa_sink *s, pa_asyncmsgq *q) {
 
 void pa_sink_set_rtpoll(pa_sink *s, pa_rtpoll *p) {
     pa_sink_assert_ref(s);
-    pa_assert(p);
 
     s->rtpoll = p;
     if (s->monitor_source)
@@ -416,7 +414,7 @@ void pa_sink_set_rtpoll(pa_sink *s, pa_rtpoll *p) {
 
 int pa_sink_update_status(pa_sink*s) {
     pa_sink_assert_ref(s);
-    pa_assert(PA_SINK_LINKED(s->state));
+    pa_assert(PA_SINK_IS_LINKED(s->state));
 
     if (s->state == PA_SINK_SUSPENDED)
         return 0;
@@ -426,7 +424,7 @@ int pa_sink_update_status(pa_sink*s) {
 
 int pa_sink_suspend(pa_sink *s, pa_bool_t suspend) {
     pa_sink_assert_ref(s);
-    pa_assert(PA_SINK_LINKED(s->state));
+    pa_assert(PA_SINK_IS_LINKED(s->state));
 
     if (suspend)
         return sink_set_state(s, PA_SINK_SUSPENDED);
@@ -438,7 +436,10 @@ void pa_sink_process_rewind(pa_sink *s, size_t nbytes) {
     pa_sink_input *i;
     void *state = NULL;
     pa_sink_assert_ref(s);
-    pa_assert(PA_SINK_LINKED(s->state));
+    pa_assert(PA_SINK_IS_LINKED(s->state));
+
+    /* Make sure the sink code already reset the counter! */
+    pa_assert(s->thread_info.rewind_nbytes <= 0);
 
     if (nbytes <= 0)
         return;
@@ -450,8 +451,9 @@ void pa_sink_process_rewind(pa_sink *s, size_t nbytes) {
         pa_sink_input_process_rewind(i, nbytes);
     }
 
-    if (s->monitor_source && PA_SOURCE_OPENED(pa_source_get_state(s->monitor_source)))
+    if (s->monitor_source && PA_SOURCE_IS_OPENED(pa_source_get_state(s->monitor_source)))
         pa_source_process_rewind(s->monitor_source, nbytes);
+
 }
 
 static unsigned fill_mix_info(pa_sink *s, size_t *length, pa_mix_info *info, unsigned maxinfo) {
@@ -557,7 +559,7 @@ void pa_sink_render(pa_sink*s, size_t length, pa_memchunk *result) {
     size_t block_size_max;
 
     pa_sink_assert_ref(s);
-    pa_assert(PA_SINK_OPENED(s->thread_info.state));
+    pa_assert(PA_SINK_IS_OPENED(s->thread_info.state));
     pa_assert(pa_frame_aligned(length, &s->sample_spec));
     pa_assert(result);
 
@@ -621,7 +623,7 @@ void pa_sink_render(pa_sink*s, size_t length, pa_memchunk *result) {
     if (s->thread_info.state == PA_SINK_RUNNING)
         inputs_drop(s, info, n, result->length);
 
-    if (s->monitor_source && PA_SOURCE_OPENED(pa_source_get_state(s->monitor_source)))
+    if (s->monitor_source && PA_SOURCE_IS_OPENED(pa_source_get_state(s->monitor_source)))
         pa_source_post(s->monitor_source, result);
 
     pa_sink_unref(s);
@@ -633,7 +635,7 @@ void pa_sink_render_into(pa_sink*s, pa_memchunk *target) {
     size_t length, block_size_max;
 
     pa_sink_assert_ref(s);
-    pa_assert(PA_SINK_OPENED(s->thread_info.state));
+    pa_assert(PA_SINK_IS_OPENED(s->thread_info.state));
     pa_assert(target);
     pa_assert(target->memblock);
     pa_assert(target->length > 0);
@@ -700,7 +702,7 @@ void pa_sink_render_into(pa_sink*s, pa_memchunk *target) {
     if (s->thread_info.state == PA_SINK_RUNNING)
         inputs_drop(s, info, n, target->length);
 
-    if (s->monitor_source && PA_SOURCE_OPENED(pa_source_get_state(s->monitor_source)))
+    if (s->monitor_source && PA_SOURCE_IS_OPENED(pa_source_get_state(s->monitor_source)))
         pa_source_post(s->monitor_source, target);
 
     pa_sink_unref(s);
@@ -711,7 +713,7 @@ void pa_sink_render_into_full(pa_sink *s, pa_memchunk *target) {
     size_t l, d;
 
     pa_sink_assert_ref(s);
-    pa_assert(PA_SINK_OPENED(s->thread_info.state));
+    pa_assert(PA_SINK_IS_OPENED(s->thread_info.state));
     pa_assert(target);
     pa_assert(target->memblock);
     pa_assert(target->length > 0);
@@ -739,7 +741,7 @@ void pa_sink_render_into_full(pa_sink *s, pa_memchunk *target) {
 
 void pa_sink_render_full(pa_sink *s, size_t length, pa_memchunk *result) {
     pa_sink_assert_ref(s);
-    pa_assert(PA_SINK_OPENED(s->thread_info.state));
+    pa_assert(PA_SINK_IS_OPENED(s->thread_info.state));
     pa_assert(length > 0);
     pa_assert(pa_frame_aligned(length, &s->sample_spec));
     pa_assert(result);
@@ -755,50 +757,15 @@ void pa_sink_render_full(pa_sink *s, size_t length, pa_memchunk *result) {
     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));
-
-    s->thread_info.rewind_nbytes = 0;
-
-    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) {
     pa_usec_t usec = 0;
 
     pa_sink_assert_ref(s);
-    pa_assert(PA_SINK_LINKED(s->state));
+    pa_assert(PA_SINK_IS_LINKED(s->state));
 
     /* The returned value is supposed to be in the time domain of the sound card! */
 
-    if (!PA_SINK_OPENED(s->state))
+    if (!PA_SINK_IS_OPENED(s->state))
         return 0;
 
     if (s->get_latency)
@@ -814,7 +781,7 @@ void pa_sink_set_volume(pa_sink *s, const pa_cvolume *volume) {
     int changed;
 
     pa_sink_assert_ref(s);
-    pa_assert(PA_SINK_LINKED(s->state));
+    pa_assert(PA_SINK_IS_LINKED(s->state));
     pa_assert(volume);
 
     changed = !pa_cvolume_equal(volume, &s->volume);
@@ -834,7 +801,7 @@ const pa_cvolume *pa_sink_get_volume(pa_sink *s) {
     struct pa_cvolume old_volume;
 
     pa_sink_assert_ref(s);
-    pa_assert(PA_SINK_LINKED(s->state));
+    pa_assert(PA_SINK_IS_LINKED(s->state));
 
     old_volume = s->volume;
 
@@ -854,7 +821,7 @@ 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));
+    pa_assert(PA_SINK_IS_LINKED(s->state));
 
     changed = s->muted != mute;
     s->muted = mute;
@@ -873,7 +840,7 @@ pa_bool_t pa_sink_get_mute(pa_sink *s) {
     pa_bool_t old_muted;
 
     pa_sink_assert_ref(s);
-    pa_assert(PA_SINK_LINKED(s->state));
+    pa_assert(PA_SINK_IS_LINKED(s->state));
 
     old_muted = s->muted;
 
@@ -914,7 +881,7 @@ void pa_sink_set_description(pa_sink *s, const char *description) {
         pa_xfree(n);
     }
 
-    if (PA_SINK_LINKED(s->state)) {
+    if (PA_SINK_IS_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_PROPLIST_CHANGED], s);
     }
@@ -924,7 +891,7 @@ unsigned pa_sink_linked_by(pa_sink *s) {
     unsigned ret;
 
     pa_sink_assert_ref(s);
-    pa_assert(PA_SINK_LINKED(s->state));
+    pa_assert(PA_SINK_IS_LINKED(s->state));
 
     ret = pa_idxset_size(s->inputs);
 
@@ -941,7 +908,7 @@ unsigned pa_sink_used_by(pa_sink *s) {
     unsigned ret;
 
     pa_sink_assert_ref(s);
-    pa_assert(PA_SINK_LINKED(s->state));
+    pa_assert(PA_SINK_IS_LINKED(s->state));
 
     ret = pa_idxset_size(s->inputs);
     pa_assert(ret >= s->n_corked);
@@ -980,24 +947,26 @@ int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offse
                 i->thread_info.sync_next->thread_info.sync_prev = i;
             }
 
-            pa_sink_input_update_max_rewind(i, s->thread_info.max_rewind);
-
             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. */
+            pa_sink_input_set_state_within_thread(i, i->state);
+
+            pa_sink_input_update_max_rewind(i, s->thread_info.max_rewind);
 
             pa_sink_invalidate_requested_latency(s);
 
-            /* Make sure we're not rewound when the hw buffer is remixed and request a remix*/
-            i->thread_info.ignore_rewind = TRUE;
-            i->thread_info.since_underrun = 0;
-            pa_sink_request_rewind(s, 0);
+            /* We don't rewind here automatically. This is left to the
+             * sink input implementor because some sink inputs need a
+             * slow start, i.e. need some time to buffer client
+             * samples before beginning streaming. */
+
+            /* 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;
         }
@@ -1009,6 +978,8 @@ int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offse
              * sink input handling a few lines down at
              * PA_SINK_MESSAGE_REMOVE_INPUT_AND_BUFFER, too. */
 
+            pa_sink_input_set_state_within_thread(i, i->state);
+
             if (i->detach)
                 i->detach(i);
 
@@ -1036,7 +1007,6 @@ int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offse
                 pa_sink_input_unref(i);
 
             pa_sink_invalidate_requested_latency(s);
-
             pa_sink_request_rewind(s, 0);
 
             return 0;
@@ -1117,11 +1087,9 @@ int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offse
 
                 if (info->ghost_sink_input->attach)
                     info->ghost_sink_input->attach(info->ghost_sink_input);
-
             }
 
             pa_sink_invalidate_requested_latency(s);
-
             pa_sink_request_rewind(s, 0);
 
             return 0;
@@ -1196,14 +1164,14 @@ int pa_sink_suspend_all(pa_core *c, pa_bool_t suspend) {
 
 void pa_sink_detach(pa_sink *s) {
     pa_sink_assert_ref(s);
-    pa_assert(PA_SINK_LINKED(s->state));
+    pa_assert(PA_SINK_IS_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_assert(PA_SINK_IS_LINKED(s->state));
 
     pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_ATTACH, NULL, 0, NULL);
 }
@@ -1213,7 +1181,7 @@ void pa_sink_detach_within_thread(pa_sink *s) {
     void *state = NULL;
 
     pa_sink_assert_ref(s);
-    pa_assert(PA_SINK_LINKED(s->thread_info.state));
+    pa_assert(PA_SINK_IS_LINKED(s->thread_info.state));
 
     while ((i = pa_hashmap_iterate(s->thread_info.inputs, &state, NULL)))
         if (i->detach)
@@ -1228,7 +1196,7 @@ void pa_sink_attach_within_thread(pa_sink *s) {
     void *state = NULL;
 
     pa_sink_assert_ref(s);
-    pa_assert(PA_SINK_LINKED(s->thread_info.state));
+    pa_assert(PA_SINK_IS_LINKED(s->thread_info.state));
 
     while ((i = pa_hashmap_iterate(s->thread_info.inputs, &state, NULL)))
         if (i->attach)
@@ -1240,7 +1208,7 @@ void pa_sink_attach_within_thread(pa_sink *s) {
 
 void pa_sink_request_rewind(pa_sink*s, size_t nbytes) {
     pa_sink_assert_ref(s);
-    pa_assert(PA_SINK_LINKED(s->thread_info.state));
+    pa_assert(PA_SINK_IS_LINKED(s->thread_info.state));
 
     if (nbytes <= 0)
         nbytes = s->thread_info.max_rewind;
@@ -1290,9 +1258,9 @@ pa_usec_t pa_sink_get_requested_latency(pa_sink *s) {
     pa_usec_t usec = 0;
 
     pa_sink_assert_ref(s);
-    pa_assert(PA_SINK_LINKED(s->state));
+    pa_assert(PA_SINK_IS_LINKED(s->state));
 
-    if (!PA_SINK_OPENED(s->state))
+    if (!PA_SINK_IS_OPENED(s->state))
         return 0;
 
     if (pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_GET_REQUESTED_LATENCY, &usec, 0, NULL) < 0)
@@ -1325,7 +1293,7 @@ void pa_sink_set_max_rewind(pa_sink *s, size_t max_rewind) {
 void pa_sink_invalidate_requested_latency(pa_sink *s) {
 
     pa_sink_assert_ref(s);
-    pa_assert(PA_SINK_LINKED(s->thread_info.state));
+    pa_assert(PA_SINK_IS_LINKED(s->thread_info.state));
 
     if (!s->thread_info.requested_latency_valid)
         return;
diff --git a/src/pulsecore/sink.h b/src/pulsecore/sink.h
index 7bc4a70..f25f48c 100644
--- a/src/pulsecore/sink.h
+++ b/src/pulsecore/sink.h
@@ -33,7 +33,6 @@ typedef struct pa_sink pa_sink;
 #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>
@@ -52,11 +51,11 @@ typedef enum pa_sink_state {
     PA_SINK_UNLINKED
 } pa_sink_state_t;
 
-static inline pa_bool_t PA_SINK_OPENED(pa_sink_state_t x) {
+static inline pa_bool_t PA_SINK_IS_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) {
+static inline pa_bool_t PA_SINK_IS_LINKED(pa_sink_state_t x) {
     return x == PA_SINK_RUNNING || x == PA_SINK_IDLE || x == PA_SINK_SUSPENDED;
 }
 
@@ -94,13 +93,42 @@ struct pa_sink {
     pa_usec_t min_latency; /* we won't go below this latency */
     pa_usec_t max_latency; /* An upper limit for the latencies */
 
+    /* Called when the main loop requests a state change. Called from
+     * main loop context. If returns -1 the state change will be
+     * inhibited */
     int (*set_state)(pa_sink *s, pa_sink_state_t state); /* may be NULL */
-    int (*get_volume)(pa_sink *s);             /* dito */
+
+    /* Callled when the volume is queried. Called from main loop
+     * context. If this is NULL a PA_SINK_MESSAGE_GET_VOLUME message
+     * will be sent to the IO thread instead. */
+    int (*get_volume)(pa_sink *s);             /* may be null */
+
+    /* Called when the volume shall be changed. Called from main loop
+     * context. If this is NULL a PA_SINK_MESSAGE_SET_VOLUME message
+     * will be sent to the IO thread instead. */
     int (*set_volume)(pa_sink *s);             /* dito */
+
+    /* Called when the mute setting is queried. Called from main loop
+     * context. If this is NULL a PA_SINK_MESSAGE_GET_MUTE message
+     * will be sent to the IO thread instead. */
     int (*get_mute)(pa_sink *s);               /* dito */
+
+    /* Called when the mute setting shall be changed. Called from main
+     * loop context. If this is NULL a PA_SINK_MESSAGE_SET_MUTE
+     * message will be sent to the IO thread instead. */
     int (*set_mute)(pa_sink *s);               /* dito */
-    pa_usec_t (*get_latency)(pa_sink *s);      /* dito */
+
+    /* Called when the latency is queried. Called from main loop
+    context. If this is NULL a PA_SINK_MESSAGE_GET_LATENCY message
+    will be sent to the IO thread instead. */
+    pa_usec_t (*get_latency)(pa_sink *s); /* dito */
+
+    /* Called when a rewind request is issued. Called from IO thread
+     * context. */
     void (*request_rewind)(pa_sink *s);        /* dito */
+
+    /* Called when a the requested latency is changed. Called from IO
+     * thread context. */
     void (*update_requested_latency)(pa_sink *s); /* dito */
 
     /* Contains copies of the above data so that the real-time worker
@@ -213,7 +241,6 @@ 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);
 
 void pa_sink_process_rewind(pa_sink *s, size_t nbytes);
 
diff --git a/src/pulsecore/sound-file-stream.c b/src/pulsecore/sound-file-stream.c
index 604723f..918313f 100644
--- a/src/pulsecore/sound-file-stream.c
+++ b/src/pulsecore/sound-file-stream.c
@@ -55,6 +55,8 @@ typedef struct file_stream {
     SNDFILE *sndfile;
     sf_count_t (*readf_function)(SNDFILE *sndfile, void *ptr, sf_count_t frames);
 
+    /* We need this memblockq here to easily fulfill rewind requests
+     * (even beyond the file start!) */
     pa_memblockq *memblockq;
 } file_stream;
 
@@ -66,6 +68,7 @@ PA_DECLARE_CLASS(file_stream);
 #define FILE_STREAM(o) (file_stream_cast(o))
 static PA_DEFINE_CHECK_TYPE(file_stream, pa_msgobject);
 
+/* Called from main context */
 static void file_stream_unlink(file_stream *u) {
     pa_assert(u);
 
@@ -80,6 +83,7 @@ static void file_stream_unlink(file_stream *u) {
     file_stream_unref(u);
 }
 
+/* Called from main context */
 static void file_stream_free(pa_object *o) {
     file_stream *u = FILE_STREAM(o);
     pa_assert(u);
@@ -93,6 +97,7 @@ static void file_stream_free(pa_object *o) {
     pa_xfree(u);
 }
 
+/* Called from main context */
 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);
@@ -106,6 +111,7 @@ static int file_stream_process_msg(pa_msgobject *o, int code, void*userdata, int
     return 0;
 }
 
+/* Called from main context */
 static void sink_input_kill_cb(pa_sink_input *i) {
     file_stream *u;
 
@@ -116,6 +122,22 @@ static void sink_input_kill_cb(pa_sink_input *i) {
     file_stream_unlink(u);
 }
 
+/* Called from IO thread context */
+static void sink_input_state_change_cb(pa_sink_input *i, pa_sink_input_state_t state) {
+    file_stream *u;
+
+    pa_sink_input_assert_ref(i);
+    u = FILE_STREAM(i->userdata);
+    file_stream_assert_ref(u);
+
+    /* If we are added for the first time, ask for a rewinding so that
+     * we are heard right-away. */
+    if (PA_SINK_INPUT_IS_LINKED(state) &&
+        i->thread_info.state == PA_SINK_INPUT_INIT)
+        pa_sink_input_request_rewind(i, 0, FALSE, TRUE);
+}
+
+/* Called from IO thread context */
 static int sink_input_pop_cb(pa_sink_input *i, size_t length, pa_memchunk *chunk) {
     file_stream *u;
 
@@ -131,6 +153,9 @@ static int sink_input_pop_cb(pa_sink_input *i, size_t length, pa_memchunk *chunk
 
     for (;;) {
         pa_memchunk tchunk;
+        size_t fs;
+        void *p;
+        sf_count_t n;
 
         if (pa_memblockq_peek(u->memblockq, chunk) >= 0) {
             pa_memblockq_drop(u->memblockq, chunk->length);
@@ -143,36 +168,19 @@ static int sink_input_pop_cb(pa_sink_input *i, size_t length, pa_memchunk *chunk
         tchunk.memblock = pa_memblock_new(i->sink->core->mempool, length);
         tchunk.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(tchunk.memblock);
 
-            p = pa_memblock_acquire(tchunk.memblock);
+        if (u->readf_function) {
+            fs = pa_frame_size(&i->sample_spec);
             n = u->readf_function(u->sndfile, p, length/fs);
-            pa_memblock_release(tchunk.memblock);
-
-            if (n <= 0)
-                n = 0;
-
-            tchunk.length = n * fs;
-
         } else {
-            sf_count_t n;
-            void *p;
-
-            p = pa_memblock_acquire(tchunk.memblock);
+            fs = 1;
             n = sf_read_raw(u->sndfile, p, length);
-            pa_memblock_release(tchunk.memblock);
-
-            if (n <= 0)
-                n = 0;
-
-            tchunk.length = n;
         }
 
-        if (tchunk.length <= 0) {
+        pa_memblock_release(tchunk.memblock);
 
+        if (n <= 0) {
             pa_memblock_unref(tchunk.memblock);
 
             sf_close(u->sndfile);
@@ -180,6 +188,8 @@ static int sink_input_pop_cb(pa_sink_input *i, size_t length, pa_memchunk *chunk
             break;
         }
 
+        tchunk.length = n * fs;
+
         pa_memblockq_push(u->memblockq, &tchunk);
         pa_memblock_unref(tchunk.memblock);
     }
@@ -196,7 +206,7 @@ static int sink_input_pop_cb(pa_sink_input *i, size_t length, pa_memchunk *chunk
     }
 
     return -1;
-}
+ }
 
 static void sink_input_process_rewind_cb(pa_sink_input *i, size_t nbytes) {
     file_stream *u;
@@ -334,6 +344,7 @@ int pa_play_file(
     u->sink_input->process_rewind = sink_input_process_rewind_cb;
     u->sink_input->update_max_rewind = sink_input_update_max_rewind_cb;
     u->sink_input->kill = sink_input_kill_cb;
+    u->sink_input->state_change = sink_input_state_change_cb;
     u->sink_input->userdata = u;
 
     pa_sink_input_get_silence(u->sink_input, &silence);
diff --git a/src/pulsecore/source-output.c b/src/pulsecore/source-output.c
index de543a5..7f5f374 100644
--- a/src/pulsecore/source-output.c
+++ b/src/pulsecore/source-output.c
@@ -88,6 +88,7 @@ static void reset_callbacks(pa_source_output *o) {
     o->moved = NULL;
     o->kill = NULL;
     o->get_latency = NULL;
+    o->state_change = NULL;
 }
 
 pa_source_output* pa_source_output_new(
@@ -263,7 +264,7 @@ void pa_source_output_unlink(pa_source_output*o) {
 
     pa_source_output_ref(o);
 
-    linked = PA_SOURCE_OUTPUT_LINKED(o->state);
+    linked = PA_SOURCE_OUTPUT_IS_LINKED(o->state);
 
     if (linked)
         pa_hook_fire(&o->source->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_UNLINK], o);
@@ -295,7 +296,7 @@ static void source_output_free(pa_object* mo) {
 
     pa_assert(pa_source_output_refcnt(o) == 0);
 
-    if (PA_SOURCE_OUTPUT_LINKED(o->state))
+    if (PA_SOURCE_OUTPUT_IS_LINKED(o->state))
         pa_source_output_unlink(o);
 
     pa_log_info("Freeing output %u \"%s\"", o->index, pa_strnull(pa_proplist_gets(o->proplist, PA_PROP_MEDIA_NAME)));
@@ -335,7 +336,7 @@ void pa_source_output_put(pa_source_output *o) {
 
 void pa_source_output_kill(pa_source_output*o) {
     pa_source_output_assert_ref(o);
-    pa_assert(PA_SOURCE_OUTPUT_LINKED(o->state));
+    pa_assert(PA_SOURCE_OUTPUT_IS_LINKED(o->state));
 
     if (o->kill)
         o->kill(o);
@@ -345,7 +346,7 @@ 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));
+    pa_assert(PA_SOURCE_OUTPUT_IS_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;
@@ -362,7 +363,7 @@ void pa_source_output_push(pa_source_output *o, const pa_memchunk *chunk) {
     size_t limit, mbs = 0;
 
     pa_source_output_assert_ref(o);
-    pa_assert(PA_SOURCE_OUTPUT_LINKED(o->thread_info.state));
+    pa_assert(PA_SOURCE_OUTPUT_IS_LINKED(o->thread_info.state));
     pa_assert(chunk);
     pa_assert(pa_frame_aligned(chunk->length, &o->source->sample_spec));
 
@@ -419,7 +420,7 @@ void pa_source_output_push(pa_source_output *o, const pa_memchunk *chunk) {
 void pa_source_output_process_rewind(pa_source_output *o, size_t nbytes /* in sink sample spec */) {
     pa_source_output_assert_ref(o);
 
-    pa_assert(PA_SOURCE_OUTPUT_LINKED(o->state));
+    pa_assert(PA_SOURCE_OUTPUT_IS_LINKED(o->state));
     pa_assert(pa_frame_aligned(nbytes, &o->source->sample_spec));
 
     if (nbytes <= 0)
@@ -446,28 +447,48 @@ void pa_source_output_process_rewind(pa_source_output *o, size_t nbytes /* in si
 /* Called from thread context */
 void pa_source_output_update_max_rewind(pa_source_output *o, size_t nbytes  /* in the source's sample spec */) {
     pa_source_output_assert_ref(o);
-    pa_assert(PA_SOURCE_OUTPUT_LINKED(o->thread_info.state));
+    pa_assert(PA_SOURCE_OUTPUT_IS_LINKED(o->thread_info.state));
     pa_assert(pa_frame_aligned(nbytes, &o->source->sample_spec));
 
     if (o->update_max_rewind)
         o->update_max_rewind(o, o->thread_info.resampler ? pa_resampler_result(o->thread_info.resampler, nbytes) : nbytes);
 }
 
-pa_usec_t pa_source_output_set_requested_latency(pa_source_output *o, pa_usec_t usec) {
-    pa_source_output_assert_ref(o);
+static pa_usec_t fixup_latency(pa_source *s, pa_usec_t usec) {
+    pa_source_assert_ref(s);
 
-    if (usec != (pa_usec_t) -1) {
+    if (usec == (pa_usec_t) -1)
+        return usec;
 
-        if (o->source->max_latency > 0 && usec > o->source->max_latency)
-            usec = o->source->max_latency;
+    if (s->max_latency > 0 && usec > s->max_latency)
+        usec = s->max_latency;
 
-        if (o->source->min_latency > 0 && usec < o->source->min_latency)
-            usec = o->source->min_latency;
-    }
+    if (s->min_latency > 0 && usec < s->min_latency)
+        usec = s->min_latency;
+
+    return usec;
+}
+
+pa_usec_t pa_source_output_set_requested_latency_within_thread(pa_source_output *o, pa_usec_t usec) {
 
-    if (PA_SOURCE_OUTPUT_LINKED(o->state))
+    usec = fixup_latency(o->source, usec);
+
+    o->thread_info.requested_source_latency = usec;
+    pa_source_invalidate_requested_latency(o->source);
+
+    return usec;
+}
+
+pa_usec_t pa_source_output_set_requested_latency(pa_source_output *o, pa_usec_t usec) {
+    pa_source_output_assert_ref(o);
+
+    usec = fixup_latency(o->source, usec);
+
+    if (PA_SOURCE_OUTPUT_IS_LINKED(o->state))
         pa_asyncmsgq_post(o->source->asyncmsgq, PA_MSGOBJECT(o), PA_SOURCE_OUTPUT_MESSAGE_SET_REQUESTED_LATENCY, NULL, (int64_t) usec, NULL, NULL);
     else {
+        /* If this sink input is not realized yet, we have to touch
+         * the thread info data directly */
         o->thread_info.requested_source_latency = usec;
         o->source->thread_info.requested_latency_valid = FALSE;
     }
@@ -477,14 +498,14 @@ pa_usec_t pa_source_output_set_requested_latency(pa_source_output *o, pa_usec_t
 
 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));
+    pa_assert(PA_SOURCE_OUTPUT_IS_LINKED(o->state));
 
     source_output_set_state(o, b ? PA_SOURCE_OUTPUT_CORKED : PA_SOURCE_OUTPUT_RUNNING);
 }
 
 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_assert(PA_SOURCE_OUTPUT_IS_LINKED(o->state));
     pa_return_val_if_fail(o->thread_info.resampler, -1);
 
     if (o->sample_spec.rate == rate)
@@ -515,7 +536,7 @@ void pa_source_output_set_name(pa_source_output *o, const char *name) {
     else
         pa_proplist_unset(o->proplist, PA_PROP_MEDIA_NAME);
 
-    if (PA_SOURCE_OUTPUT_LINKED(o->state)) {
+    if (PA_SOURCE_OUTPUT_IS_LINKED(o->state)) {
         pa_hook_fire(&o->source->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_PROPLIST_CHANGED], o);
         pa_subscription_post(o->source->core, PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_CHANGE, o->index);
     }
@@ -533,7 +554,7 @@ int pa_source_output_move_to(pa_source_output *o, pa_source *dest) {
     pa_source_output_move_hook_data hook_data;
 
     pa_source_output_assert_ref(o);
-    pa_assert(PA_SOURCE_OUTPUT_LINKED(o->state));
+    pa_assert(PA_SOURCE_OUTPUT_IS_LINKED(o->state));
     pa_source_assert_ref(dest);
 
     origin = o->source;
@@ -616,12 +637,21 @@ int pa_source_output_move_to(pa_source_output *o, pa_source *dest) {
     return 0;
 }
 
+void pa_source_output_set_state_within_thread(pa_source_output *o, pa_source_output_state_t state) {
+    pa_source_output_assert_ref(o);
+
+    if (o->state_change)
+        o->state_change(o, state);
+
+    o->thread_info.state = state;
+}
+
 /* 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));
+    pa_assert(PA_SOURCE_OUTPUT_IS_LINKED(o->thread_info.state));
 
     switch (code) {
 
@@ -633,25 +663,20 @@ int pa_source_output_process_msg(pa_msgobject *mo, int code, void *userdata, int
             return 0;
         }
 
-        case PA_SOURCE_OUTPUT_MESSAGE_SET_RATE: {
+        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);
+        case PA_SOURCE_OUTPUT_MESSAGE_SET_STATE:
 
+            pa_source_output_set_state_within_thread(o, PA_PTR_TO_UINT(userdata));
             return 0;
-        }
 
         case PA_SOURCE_OUTPUT_MESSAGE_SET_REQUESTED_LATENCY:
 
-            o->thread_info.requested_source_latency = (pa_usec_t) offset;
-            pa_source_invalidate_requested_latency(o->source);
-
+            pa_source_output_set_requested_latency_within_thread(o, (pa_usec_t) offset);
             return 0;
     }
 
diff --git a/src/pulsecore/source-output.h b/src/pulsecore/source-output.h
index e7d8963..67cb376 100644
--- a/src/pulsecore/source-output.h
+++ b/src/pulsecore/source-output.h
@@ -42,7 +42,7 @@ typedef enum pa_source_output_state {
     PA_SOURCE_OUTPUT_UNLINKED
 } pa_source_output_state_t;
 
-static inline pa_bool_t PA_SOURCE_OUTPUT_LINKED(pa_source_output_state_t x) {
+static inline pa_bool_t PA_SOURCE_OUTPUT_IS_LINKED(pa_source_output_state_t x) {
     return x == PA_SOURCE_OUTPUT_RUNNING || x == PA_SOURCE_OUTPUT_CORKED;
 }
 
@@ -83,11 +83,11 @@ struct pa_source_output {
     void (*push)(pa_source_output *o, const pa_memchunk *chunk);
 
     /* Only relevant for monitor sources right now: called when the
-     * recorded stream is rewound. */
+     * recorded stream is rewound. Called from IO context*/
     void (*process_rewind)(pa_source_output *o, size_t nbytes);
 
     /* Called whenever the maximum rewindable size of the source
-     * changes. Called from RT context. */
+     * changes. Called from IO thread context. */
     void (*update_max_rewind) (pa_source_output *o, size_t nbytes); /* may be NULL */
 
     /* If non-NULL this function is called when the output is first
@@ -116,6 +116,10 @@ struct pa_source_output {
     thread instead. */
     pa_usec_t (*get_latency) (pa_source_output *o); /* may be NULL */
 
+    /* If non_NULL this function is called from thread context if the
+     * state changes. The old state is found in thread_info.state.  */
+    void (*state_change) (pa_source_output *o, pa_source_output_state_t state); /* may be NULL */
+
     struct {
         pa_source_output_state_t state;
 
@@ -213,4 +217,8 @@ void pa_source_output_update_max_rewind(pa_source_output *o, size_t nbytes);
 
 int pa_source_output_process_msg(pa_msgobject *mo, int code, void *userdata, int64_t offset, pa_memchunk *chunk);
 
+void pa_source_output_set_state_within_thread(pa_source_output *o, pa_source_output_state_t state);
+
+pa_usec_t pa_source_output_set_requested_latency_within_thread(pa_source_output *o, pa_usec_t usec);
+
 #endif
diff --git a/src/pulsecore/source.c b/src/pulsecore/source.c
index dab307e..4a2173c 100644
--- a/src/pulsecore/source.c
+++ b/src/pulsecore/source.c
@@ -228,8 +228,8 @@ static int source_set_state(pa_source *s, pa_source_state_t state) {
         return 0;
 
     suspend_change =
-        (s->state == PA_SOURCE_SUSPENDED && PA_SOURCE_OPENED(state)) ||
-        (PA_SOURCE_OPENED(s->state) && state == PA_SOURCE_SUSPENDED);
+        (s->state == PA_SOURCE_SUSPENDED && PA_SOURCE_IS_OPENED(state)) ||
+        (PA_SOURCE_IS_OPENED(s->state) && state == PA_SOURCE_SUSPENDED);
 
     if (s->set_state)
         if ((ret = s->set_state(s, state)) < 0)
@@ -284,7 +284,7 @@ void pa_source_unlink(pa_source *s) {
     /* See pa_sink_unlink() for a couple of comments how this function
      * works. */
 
-    linked = PA_SOURCE_LINKED(s->state);
+    linked = PA_SOURCE_IS_LINKED(s->state);
 
     if (linked)
         pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SOURCE_UNLINK], s);
@@ -319,7 +319,7 @@ static void source_free(pa_object *o) {
     pa_assert(s);
     pa_assert(pa_source_refcnt(s) == 0);
 
-    if (PA_SOURCE_LINKED(s->state))
+    if (PA_SOURCE_IS_LINKED(s->state))
         pa_source_unlink(s);
 
     pa_log_info("Freeing source %u \"%s\"", s->index, s->name);
@@ -345,21 +345,19 @@ static void source_free(pa_object *o) {
 
 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;
 }
 
 int pa_source_update_status(pa_source*s) {
     pa_source_assert_ref(s);
-    pa_assert(PA_SOURCE_LINKED(s->state));
+    pa_assert(PA_SOURCE_IS_LINKED(s->state));
 
     if (s->state == PA_SOURCE_SUSPENDED)
         return 0;
@@ -369,7 +367,7 @@ int pa_source_update_status(pa_source*s) {
 
 int pa_source_suspend(pa_source *s, pa_bool_t suspend) {
     pa_source_assert_ref(s);
-    pa_assert(PA_SOURCE_LINKED(s->state));
+    pa_assert(PA_SOURCE_IS_LINKED(s->state));
 
     if (suspend)
         return source_set_state(s, PA_SOURCE_SUSPENDED);
@@ -382,7 +380,7 @@ void pa_source_process_rewind(pa_source *s, size_t nbytes) {
     void *state = NULL;
 
     pa_source_assert_ref(s);
-    pa_assert(PA_SOURCE_OPENED(s->thread_info.state));
+    pa_assert(PA_SOURCE_IS_OPENED(s->thread_info.state));
 
     if (nbytes <= 0)
         return;
@@ -400,7 +398,7 @@ void pa_source_post(pa_source*s, const pa_memchunk *chunk) {
     void *state = NULL;
 
     pa_source_assert_ref(s);
-    pa_assert(PA_SOURCE_OPENED(s->thread_info.state));
+    pa_assert(PA_SOURCE_IS_OPENED(s->thread_info.state));
     pa_assert(chunk);
 
     if (s->thread_info.state != PA_SOURCE_RUNNING)
@@ -436,9 +434,9 @@ pa_usec_t pa_source_get_latency(pa_source *s) {
     pa_usec_t usec;
 
     pa_source_assert_ref(s);
-    pa_assert(PA_SOURCE_LINKED(s->state));
+    pa_assert(PA_SOURCE_IS_LINKED(s->state));
 
-    if (!PA_SOURCE_OPENED(s->state))
+    if (!PA_SOURCE_IS_OPENED(s->state))
         return 0;
 
     if (s->get_latency)
@@ -454,7 +452,7 @@ void pa_source_set_volume(pa_source *s, const pa_cvolume *volume) {
     int changed;
 
     pa_source_assert_ref(s);
-    pa_assert(PA_SOURCE_LINKED(s->state));
+    pa_assert(PA_SOURCE_IS_LINKED(s->state));
     pa_assert(volume);
 
     changed = !pa_cvolume_equal(volume, &s->volume);
@@ -474,7 +472,7 @@ 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));
+    pa_assert(PA_SOURCE_IS_LINKED(s->state));
 
     old_volume = s->volume;
 
@@ -494,7 +492,7 @@ 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));
+    pa_assert(PA_SOURCE_IS_LINKED(s->state));
 
     changed = s->muted != mute;
     s->muted = mute;
@@ -513,7 +511,7 @@ pa_bool_t pa_source_get_mute(pa_source *s) {
     pa_bool_t old_muted;
 
     pa_source_assert_ref(s);
-    pa_assert(PA_SOURCE_LINKED(s->state));
+    pa_assert(PA_SOURCE_IS_LINKED(s->state));
 
     old_muted = s->muted;
 
@@ -546,7 +544,7 @@ void pa_source_set_description(pa_source *s, const char *description) {
     else
         pa_proplist_unset(s->proplist, PA_PROP_DEVICE_DESCRIPTION);
 
-    if (PA_SOURCE_LINKED(s->state)) {
+    if (PA_SOURCE_IS_LINKED(s->state)) {
         pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
         pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SOURCE_PROPLIST_CHANGED], s);
     }
@@ -554,7 +552,7 @@ void pa_source_set_description(pa_source *s, const char *description) {
 
 unsigned pa_source_linked_by(pa_source *s) {
     pa_source_assert_ref(s);
-    pa_assert(PA_SOURCE_LINKED(s->state));
+    pa_assert(PA_SOURCE_IS_LINKED(s->state));
 
     return pa_idxset_size(s->outputs);
 }
@@ -563,7 +561,7 @@ unsigned pa_source_used_by(pa_source *s) {
     unsigned ret;
 
     pa_source_assert_ref(s);
-    pa_assert(PA_SOURCE_LINKED(s->state));
+    pa_assert(PA_SOURCE_IS_LINKED(s->state));
 
     ret = pa_idxset_size(s->outputs);
     pa_assert(ret >= s->n_corked);
@@ -590,6 +588,8 @@ int pa_source_process_msg(pa_msgobject *object, int code, void *userdata, int64_
             if (o->attach)
                 o->attach(o);
 
+            pa_source_output_set_state_within_thread(o, o->state);
+
             pa_source_invalidate_requested_latency(s);
 
             return 0;
@@ -598,6 +598,8 @@ int pa_source_process_msg(pa_msgobject *object, int code, void *userdata, int64_
         case PA_SOURCE_MESSAGE_REMOVE_OUTPUT: {
             pa_source_output *o = PA_SOURCE_OUTPUT(userdata);
 
+            pa_source_output_set_state_within_thread(o, o->state);
+
             if (o->detach)
                 o->detach(o);
 
@@ -676,14 +678,14 @@ int pa_source_suspend_all(pa_core *c, pa_bool_t suspend) {
 
 void pa_source_detach(pa_source *s) {
     pa_source_assert_ref(s);
-    pa_assert(PA_SOURCE_LINKED(s->state));
+    pa_assert(PA_SOURCE_IS_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_assert(PA_SOURCE_IS_LINKED(s->state));
 
     pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_ATTACH, NULL, 0, NULL);
 }
@@ -693,7 +695,7 @@ void pa_source_detach_within_thread(pa_source *s) {
     void *state = NULL;
 
     pa_source_assert_ref(s);
-    pa_assert(PA_SOURCE_LINKED(s->thread_info.state));
+    pa_assert(PA_SOURCE_IS_LINKED(s->thread_info.state));
 
     while ((o = pa_hashmap_iterate(s->thread_info.outputs, &state, NULL)))
         if (o->detach)
@@ -705,7 +707,7 @@ void pa_source_attach_within_thread(pa_source *s) {
     void *state = NULL;
 
     pa_source_assert_ref(s);
-    pa_assert(PA_SOURCE_LINKED(s->thread_info.state));
+    pa_assert(PA_SOURCE_IS_LINKED(s->thread_info.state));
 
     while ((o = pa_hashmap_iterate(s->thread_info.outputs, &state, NULL)))
         if (o->attach)
@@ -746,9 +748,9 @@ pa_usec_t pa_source_get_requested_latency(pa_source *s) {
     pa_usec_t usec;
 
     pa_source_assert_ref(s);
-    pa_assert(PA_SOURCE_LINKED(s->state));
+    pa_assert(PA_SOURCE_IS_LINKED(s->state));
 
-    if (!PA_SOURCE_OPENED(s->state))
+    if (!PA_SOURCE_IS_OPENED(s->state))
         return 0;
 
     if (pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_GET_REQUESTED_LATENCY, &usec, 0, NULL) < 0)
@@ -778,7 +780,7 @@ void pa_source_set_max_rewind(pa_source *s, size_t max_rewind) {
 void pa_source_invalidate_requested_latency(pa_source *s) {
 
     pa_source_assert_ref(s);
-    pa_assert(PA_SOURCE_LINKED(s->thread_info.state));
+    pa_assert(PA_SOURCE_IS_LINKED(s->thread_info.state));
 
     if (!s->thread_info.requested_latency_valid)
         return;
diff --git a/src/pulsecore/source.h b/src/pulsecore/source.h
index b8859c8..cce5462 100644
--- a/src/pulsecore/source.h
+++ b/src/pulsecore/source.h
@@ -33,7 +33,6 @@ typedef struct pa_source pa_source;
 #include <pulse/channelmap.h>
 #include <pulse/volume.h>
 
-#include <pulsecore/core-def.h>
 #include <pulsecore/core.h>
 #include <pulsecore/idxset.h>
 #include <pulsecore/memblock.h>
@@ -54,11 +53,11 @@ typedef enum pa_source_state {
     PA_SOURCE_UNLINKED
 } pa_source_state_t;
 
-static inline pa_bool_t PA_SOURCE_OPENED(pa_source_state_t x) {
+static inline pa_bool_t PA_SOURCE_IS_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) {
+static inline pa_bool_t PA_SOURCE_IS_LINKED(pa_source_state_t x) {
     return x == PA_SOURCE_RUNNING || x == PA_SOURCE_IDLE || x == PA_SOURCE_SUSPENDED;
 }
 
diff --git a/src/utils/pacmd.c b/src/utils/pacmd.c
index daa6a96..dff9af9 100644
--- a/src/utils/pacmd.c
+++ b/src/utils/pacmd.c
@@ -36,6 +36,7 @@
 
 #include <pulse/error.h>
 #include <pulse/util.h>
+#include <pulse/xmalloc.h>
 
 #include <pulsecore/core-util.h>
 #include <pulsecore/log.h>
@@ -49,6 +50,7 @@ int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char*argv[]) {
     char ibuf[256], obuf[256];
     size_t ibuf_index, ibuf_length, obuf_index, obuf_length;
     fd_set ifds, ofds;
+    char *cli;
 
     if (pa_pid_file_check_running(&pid, "pulseaudio") < 0) {
         pa_log("no PulseAudio daemon running");
@@ -62,7 +64,10 @@ int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char*argv[]) {
 
     memset(&sa, 0, sizeof(sa));
     sa.sun_family = AF_UNIX;
-    pa_runtime_path("cli", sa.sun_path, sizeof(sa.sun_path));
+
+    cli = pa_runtime_path("cli");
+    pa_strlcpy(sa.sun_path, cli, sizeof(sa.sun_path));
+    pa_xfree(cli);
 
     for (i = 0; i < 5; i++) {
         int r;

commit 49b1b15ef076e36aa7dc62eb664f848b6a5ca531
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri May 2 01:20:46 2008 +0000

    don't enable prebuffering if we just call is_readable()
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2341 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/memblockq.c b/src/pulsecore/memblockq.c
index 947c69a..13eb110 100644
--- a/src/pulsecore/memblockq.c
+++ b/src/pulsecore/memblockq.c
@@ -428,6 +428,15 @@ finish:
 pa_bool_t pa_memblockq_prebuf_active(pa_memblockq *bq) {
     pa_assert(bq);
 
+    if (bq->in_prebuf)
+        return pa_memblockq_get_length(bq) < bq->prebuf;
+    else
+        return bq->prebuf > 0 && bq->read_index >= bq->write_index;
+}
+
+static pa_bool_t update_prebuf(pa_memblockq *bq) {
+    pa_assert(bq);
+
     if (bq->in_prebuf) {
 
         if (pa_memblockq_get_length(bq) < bq->prebuf)
@@ -452,7 +461,7 @@ int pa_memblockq_peek(pa_memblockq* bq, pa_memchunk *chunk) {
     pa_assert(chunk);
 
     /* We need to pre-buffer */
-    if (pa_memblockq_prebuf_active(bq))
+    if (update_prebuf(bq))
         return -1;
 
     fix_current_read(bq);
@@ -515,7 +524,7 @@ void pa_memblockq_drop(pa_memblockq *bq, size_t length) {
     while (length > 0) {
 
         /* Do not drop any data when we are in prebuffering mode */
-        if (pa_memblockq_prebuf_active(bq))
+        if (update_prebuf(bq))
             break;
 
         fix_current_read(bq);

commit 7d6269e57a529b141d179650f42be58d54f6059a
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri May 2 01:21:22 2008 +0000

    add multiarch paths to default LADSPA search path
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2342 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/Makefile.am b/src/Makefile.am
index 5cc9546..799e7b2 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1311,7 +1311,7 @@ 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_CFLAGS = -DLADSPA_PATH=\"$(libdir)/ladspa:/usr/local/lib/ladspa:/usr/lib/ladspa:/usr/local/lib64/ladspa:/usr/lib64/ladspa\" $(AM_CFLAGS)
 module_ladspa_sink_la_LDFLAGS = -module -avoid-version
 module_ladspa_sink_la_LIBADD = $(AM_LIBADD) $(LIBLTDL) libpulsecore.la
 

commit 775bc6c108cc1070bf97758036b5d9ea745e05ae
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri May 2 01:23:32 2008 +0000

    some modernizations
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2343 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/ioline.c b/src/pulsecore/ioline.c
index 6d11e4f..85bbadc 100644
--- a/src/pulsecore/ioline.c
+++ b/src/pulsecore/ioline.c
@@ -49,7 +49,6 @@ struct pa_ioline {
     pa_iochannel *io;
     pa_defer_event *defer_event;
     pa_mainloop_api *mainloop;
-    int dead;
 
     char *wbuf;
     size_t wbuf_length, wbuf_index, wbuf_valid_length;
@@ -57,10 +56,11 @@ struct pa_ioline {
     char *rbuf;
     size_t rbuf_length, rbuf_index, rbuf_valid_length;
 
-    void (*callback)(pa_ioline*io, const char *s, void *userdata);
+    pa_ioline_cb_t callback;
     void *userdata;
 
-    int defer_close;
+    pa_bool_t dead:1;
+    pa_bool_t defer_close:1;
 };
 
 static void io_callback(pa_iochannel*io, void *userdata);
@@ -73,7 +73,6 @@ pa_ioline* pa_ioline_new(pa_iochannel *io) {
     l = pa_xnew(pa_ioline, 1);
     PA_REFCNT_INIT(l);
     l->io = io;
-    l->dead = 0;
 
     l->wbuf = NULL;
     l->wbuf_length = l->wbuf_index = l->wbuf_valid_length = 0;
@@ -89,7 +88,8 @@ pa_ioline* pa_ioline_new(pa_iochannel *io) {
     l->defer_event = l->mainloop->defer_new(l->mainloop, defer_callback, l);
     l->mainloop->defer_enable(l->defer_event, 0);
 
-    l->defer_close = 0;
+    l->dead = FALSE;
+    l->defer_close = FALSE;
 
     pa_iochannel_set_callback(io, io_callback, l);
 
@@ -130,7 +130,7 @@ void pa_ioline_close(pa_ioline *l) {
     pa_assert(l);
     pa_assert(PA_REFCNT_VALUE(l) >= 1);
 
-    l->dead = 1;
+    l->dead = TRUE;
 
     if (l->io) {
         pa_iochannel_free(l->io);
@@ -166,11 +166,13 @@ void pa_ioline_puts(pa_ioline *l, const char *c) {
         /* In case the allocated buffer is too small, enlarge it. */
         if (l->wbuf_valid_length + len > l->wbuf_length) {
             size_t n = l->wbuf_valid_length+len;
-            char *new = pa_xmalloc(n);
+            char *new = pa_xnew(char, n);
+
             if (l->wbuf) {
                 memcpy(new, l->wbuf+l->wbuf_index, l->wbuf_valid_length);
                 pa_xfree(l->wbuf);
             }
+
             l->wbuf = new;
             l->wbuf_length = n;
             l->wbuf_index = 0;
@@ -191,15 +193,18 @@ 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) {
+void pa_ioline_set_callback(pa_ioline*l, pa_ioline_cb_t callback, void *userdata) {
     pa_assert(l);
     pa_assert(PA_REFCNT_VALUE(l) >= 1);
 
+    if (l->dead)
+        return;
+
     l->callback = callback;
     l->userdata = userdata;
 }
 
-static void failure(pa_ioline *l, int process_leftover) {
+static void failure(pa_ioline *l, pa_bool_t process_leftover) {
     pa_assert(l);
     pa_assert(PA_REFCNT_VALUE(l) >= 1);
     pa_assert(!l->dead);
@@ -282,7 +287,7 @@ static int do_read(pa_ioline *l) {
                     memmove(l->rbuf, l->rbuf+l->rbuf_index, l->rbuf_valid_length);
             } else {
                 /* Enlarge the buffer */
-                char *new = pa_xmalloc(n);
+                char *new = pa_xnew(char, n);
                 if (l->rbuf_valid_length)
                     memcpy(new, l->rbuf+l->rbuf_index, l->rbuf_valid_length);
                 pa_xfree(l->rbuf);
@@ -305,9 +310,9 @@ static int do_read(pa_ioline *l) {
 
             if (r < 0 && errno != ECONNRESET) {
                 pa_log("read(): %s", pa_cstrerror(errno));
-                failure(l, 0);
+                failure(l, FALSE);
             } else
-                failure(l, 1);
+                failure(l, TRUE);
 
             return -1;
         }
@@ -338,7 +343,7 @@ static int do_write(pa_ioline *l) {
             if (r < 0 && errno != EPIPE)
                 pa_log("write(): %s", pa_cstrerror(errno));
 
-            failure(l, 0);
+            failure(l, FALSE);
 
             return -1;
         }
@@ -370,7 +375,7 @@ static void do_work(pa_ioline *l) {
         do_write(l);
 
     if (l->defer_close && !l->wbuf_valid_length)
-        failure(l, 1);
+        failure(l, TRUE);
 
     pa_ioline_unref(l);
 }
@@ -400,7 +405,7 @@ void pa_ioline_defer_close(pa_ioline *l) {
     pa_assert(l);
     pa_assert(PA_REFCNT_VALUE(l) >= 1);
 
-    l->defer_close = 1;
+    l->defer_close = TRUE;
 
     if (!l->wbuf_valid_length)
         l->mainloop->defer_enable(l->defer_event, 1);
diff --git a/src/pulsecore/ioline.h b/src/pulsecore/ioline.h
index 8475b79..f4edc7b 100644
--- a/src/pulsecore/ioline.h
+++ b/src/pulsecore/ioline.h
@@ -33,6 +33,8 @@
 
 typedef struct pa_ioline pa_ioline;
 
+typedef void (*pa_ioline_cb_t)(pa_ioline*io, const char *s, void *userdata);
+
 pa_ioline* pa_ioline_new(pa_iochannel *io);
 void pa_ioline_unref(pa_ioline *l);
 pa_ioline* pa_ioline_ref(pa_ioline *l);
@@ -45,7 +47,7 @@ void pa_ioline_puts(pa_ioline *s, const char *c);
 void pa_ioline_printf(pa_ioline *s, const char *format, ...) PA_GCC_PRINTF_ATTR(2,3);
 
 /* Set the callback function that is called for every recieved line */
-void pa_ioline_set_callback(pa_ioline*io, void (*callback)(pa_ioline*io, const char *s, void *userdata), void *userdata);
+void pa_ioline_set_callback(pa_ioline*io, pa_ioline_cb_t callback, void *userdata);
 
 /* Make sure to close the ioline object as soon as the send buffer is emptied */
 void pa_ioline_defer_close(pa_ioline *io);

commit 792ef5c244f2374d88975f042b2b5f3def99ce0e
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri May 2 01:24:01 2008 +0000

    fix a compiler warning
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2344 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c
index 1da920a..bb377c4 100644
--- a/src/pulsecore/sink-input.c
+++ b/src/pulsecore/sink-input.c
@@ -1149,7 +1149,7 @@ void pa_sink_input_request_rewind(pa_sink_input *i, size_t nbytes  /* in our sam
 
         /* Make sure to not overwrite over underruns */
         if (!ignore_underruns)
-            if ((int64_t) nbytes > i->thread_info.playing_for)
+            if (nbytes > i->thread_info.playing_for)
                 nbytes = (size_t) i->thread_info.playing_for;
 
         i->thread_info.rewrite_nbytes = nbytes;

commit 06b9140e109a591529ec7229085fe138ce79a6d1
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri May 2 01:24:47 2008 +0000

    reorderer a few things
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2345 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/sample-util.c b/src/pulsecore/sample-util.c
index d295742..a802829 100644
--- a/src/pulsecore/sample-util.c
+++ b/src/pulsecore/sample-util.c
@@ -1002,20 +1002,19 @@ pa_memchunk* pa_silence_memchunk_get(pa_silence_cache *cache, pa_mempool *pool,
 }
 
 void pa_sample_clamp(pa_sample_format_t format, void *dst, size_t dstr, const void *src, size_t sstr, unsigned n) {
-
     const float *s;
     float *d;
 
-    if (format != PA_SAMPLE_FLOAT32BE && format != PA_SAMPLE_FLOAT32LE)
-        return;
-
-    s = src;
-    d = dst;
+    s = src; d = dst;
 
     if (format == PA_SAMPLE_FLOAT32NE) {
-        const static float minus_one = -1.0, plus_one = 1.0;
-        oil_clip_f32(dst, dstr, src, sstr, n, &minus_one, &plus_one);
-    } else
+
+        float minus_one = -1.0, plus_one = 1.0;
+        oil_clip_f32(d, dstr, s, sstr, n, &minus_one, &plus_one);
+
+    } else {
+        pa_assert(format == PA_SAMPLE_FLOAT32RE);
+
         for (; n > 0; n--) {
             float f;
 
@@ -1026,4 +1025,5 @@ void pa_sample_clamp(pa_sample_format_t format, void *dst, size_t dstr, const vo
             s = (const float*) ((const uint8_t*) s + sstr);
             d = (float*) ((uint8_t*) d + dstr);
         }
+    }
 }

commit bfb2691fac92a3a6f44ea309b6969e8ed96b7711
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri May 2 01:25:22 2008 +0000

    a few modernizations
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2346 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/socket-client.c b/src/pulsecore/socket-client.c
index 5b5bc5c..a99193b 100644
--- a/src/pulsecore/socket-client.c
+++ b/src/pulsecore/socket-client.c
@@ -77,9 +77,9 @@ struct pa_socket_client {
     pa_io_event *io_event;
     pa_time_event *timeout_event;
     pa_defer_event *defer_event;
-    void (*callback)(pa_socket_client*c, pa_iochannel *io, void *userdata);
+    pa_socket_client_cb_t callback;
     void *userdata;
-    int local;
+    pa_bool_t local;
 #ifdef HAVE_LIBASYNCNS
     asyncns_t *asyncns;
     asyncns_query_t * asyncns_query;
@@ -87,7 +87,7 @@ struct pa_socket_client {
 #endif
 };
 
-static pa_socket_client*pa_socket_client_new(pa_mainloop_api *m) {
+static pa_socket_client* socket_client_new(pa_mainloop_api *m) {
     pa_socket_client *c;
     pa_assert(m);
 
@@ -96,11 +96,11 @@ static pa_socket_client*pa_socket_client_new(pa_mainloop_api *m) {
     c->mainloop = m;
     c->fd = -1;
     c->io_event = NULL;
-    c->defer_event = NULL;
     c->timeout_event = NULL;
+    c->defer_event = NULL;
     c->callback = NULL;
     c->userdata = NULL;
-    c->local = 0;
+    c->local = FALSE;
 
 #ifdef HAVE_LIBASYNCNS
     c->asyncns = NULL;
@@ -119,15 +119,15 @@ static void free_events(pa_socket_client *c) {
         c->io_event = NULL;
     }
 
-    if (c->defer_event) {
-        c->mainloop->defer_free(c->defer_event);
-        c->defer_event = NULL;
-    }
-
     if (c->timeout_event) {
         c->mainloop->time_free(c->timeout_event);
         c->timeout_event = NULL;
     }
+
+    if (c->defer_event) {
+        c->mainloop->defer_free(c->defer_event);
+        c->defer_event = NULL;
+    }
 }
 
 static void do_call(pa_socket_client *c) {
@@ -177,7 +177,7 @@ finish:
     pa_socket_client_unref(c);
 }
 
-static void connect_fixed_cb(pa_mainloop_api *m, pa_defer_event *e, void *userdata) {
+static void connect_defer_cb(pa_mainloop_api *m, pa_defer_event *e, void *userdata) {
     pa_socket_client *c = userdata;
 
     pa_assert(m);
@@ -223,7 +223,7 @@ static int do_connect(pa_socket_client *c, const struct sockaddr *sa, socklen_t
 
         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));
+        pa_assert_se(c->defer_event = c->mainloop->defer_new(c->mainloop, connect_defer_cb, c));
 
     return 0;
 }
@@ -252,8 +252,7 @@ pa_socket_client* pa_socket_client_new_unix(pa_mainloop_api *m, const char *file
 
     memset(&sa, 0, sizeof(sa));
     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_strlcpy(sa.sun_path, filename, sizeof(sa.sun_path));
 
     return pa_socket_client_new_sockaddr(m, (struct sockaddr*) &sa, sizeof(sa));
 }
@@ -273,7 +272,7 @@ static int sockaddr_prepare(pa_socket_client *c, const struct sockaddr *sa, size
 
     switch (sa->sa_family) {
         case AF_UNIX:
-            c->local = 1;
+            c->local = TRUE;
             break;
 
         case AF_INET:
@@ -285,7 +284,7 @@ static int sockaddr_prepare(pa_socket_client *c, const struct sockaddr *sa, size
             break;
 
         default:
-            c->local = 0;
+            c->local = FALSE;
     }
 
     if ((c->fd = socket(sa->sa_family, SOCK_STREAM, 0)) < 0) {
@@ -294,6 +293,7 @@ static int sockaddr_prepare(pa_socket_client *c, const struct sockaddr *sa, size
     }
 
     pa_make_fd_cloexec(c->fd);
+
     if (sa->sa_family == AF_INET || sa->sa_family == AF_INET6)
         pa_make_tcp_socket_low_delay(c->fd);
     else
@@ -312,7 +312,7 @@ pa_socket_client* pa_socket_client_new_sockaddr(pa_mainloop_api *m, const struct
     pa_assert(sa);
     pa_assert(salen > 0);
 
-    pa_assert_se(c = pa_socket_client_new(m));
+    pa_assert_se(c = socket_client_new(m));
 
     if (sockaddr_prepare(c, sa, salen) < 0)
         goto fail;
@@ -361,7 +361,7 @@ pa_socket_client* pa_socket_client_ref(pa_socket_client *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) {
+void pa_socket_client_set_callback(pa_socket_client *c, pa_socket_client_cb_t on_connection, void *userdata) {
     pa_assert(c);
     pa_assert(PA_REFCNT_VALUE(c) >= 1);
 
@@ -489,23 +489,22 @@ pa_socket_client* pa_socket_client_new_string(pa_mainloop_api *m, const char*nam
             hints.ai_family = a.type == PA_PARSED_ADDRESS_TCP4 ? PF_INET : (a.type == PA_PARSED_ADDRESS_TCP6 ? PF_INET6 : PF_UNSPEC);
             hints.ai_socktype = SOCK_STREAM;
 
-#ifdef HAVE_LIBASYNCNS
+#if defined(HAVE_LIBASYNCNS)
             {
                 asyncns_t *asyncns;
 
                 if (!(asyncns = asyncns_new(1)))
                     goto finish;
 
-                c = pa_socket_client_new(m);
+                pa_assert_se(c = socket_client_new(m));
                 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);
                 pa_assert(c->asyncns_query);
                 start_timeout(c);
             }
-#else /* HAVE_LIBASYNCNS */
+#elif defined(HAVE_GETADDRINFO)
             {
-#ifdef HAVE_GETADDRINFO
                 int ret;
                 struct addrinfo *res = NULL;
 
@@ -520,7 +519,9 @@ pa_socket_client* pa_socket_client_new_string(pa_mainloop_api *m, const char*nam
                 }
 
                 freeaddrinfo(res);
-#else /* HAVE_GETADDRINFO */
+            }
+#else
+            {
                 struct hostent *host = NULL;
                 struct sockaddr_in s;
 
@@ -546,7 +547,6 @@ pa_socket_client* pa_socket_client_new_string(pa_mainloop_api *m, const char*nam
 
                 if ((c = pa_socket_client_new_sockaddr(m, (struct sockaddr*)&s, sizeof(s))))
                     start_timeout(c);
-#endif /* HAVE_GETADDRINFO */
             }
 #endif /* HAVE_LIBASYNCNS */
         }
@@ -561,7 +561,7 @@ finish:
 /* Return non-zero when the target sockaddr is considered
    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) {
+pa_bool_t pa_socket_client_is_local(pa_socket_client *c) {
     pa_assert(c);
     pa_assert(PA_REFCNT_VALUE(c) >= 1);
 
diff --git a/src/pulsecore/socket-client.h b/src/pulsecore/socket-client.h
index b1d58ef..41e8c3b 100644
--- a/src/pulsecore/socket-client.h
+++ b/src/pulsecore/socket-client.h
@@ -34,17 +34,19 @@ struct sockaddr;
 
 typedef struct pa_socket_client pa_socket_client;
 
+typedef void (*pa_socket_client_cb_t)(pa_socket_client *c, pa_iochannel*io, void *userdata);
+
 pa_socket_client* pa_socket_client_new_ipv4(pa_mainloop_api *m, uint32_t address, uint16_t port);
 pa_socket_client* pa_socket_client_new_ipv6(pa_mainloop_api *m, uint8_t address[16], uint16_t port);
 pa_socket_client* pa_socket_client_new_unix(pa_mainloop_api *m, const char *filename);
 pa_socket_client* pa_socket_client_new_sockaddr(pa_mainloop_api *m, const struct sockaddr *sa, size_t salen);
 pa_socket_client* pa_socket_client_new_string(pa_mainloop_api *m, const char *a, uint16_t default_port);
 
-void pa_socket_client_unref(pa_socket_client *c);
 pa_socket_client* pa_socket_client_ref(pa_socket_client *c);
+void pa_socket_client_unref(pa_socket_client *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);
+void pa_socket_client_set_callback(pa_socket_client *c, pa_socket_client_cb_t on_connection, void *userdata);
 
-int pa_socket_client_is_local(pa_socket_client *c);
+pa_bool_t pa_socket_client_is_local(pa_socket_client *c);
 
 #endif

commit bb4f83b901c2c18e8bec5b044b1c624759a0113b
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri May 2 01:26:10 2008 +0000

    only send PA_SINK_MESSAGE_SET_STATE if there's still an asyncmsqg around to do so
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2347 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c
index a2a02eb..6c427e1 100644
--- a/src/pulsecore/sink.c
+++ b/src/pulsecore/sink.c
@@ -272,8 +272,9 @@ static int sink_set_state(pa_sink *s, pa_sink_state_t 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;
+    if (s->asyncmsgq)
+        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;
 
diff --git a/src/pulsecore/source.c b/src/pulsecore/source.c
index 4a2173c..efd6dab 100644
--- a/src/pulsecore/source.c
+++ b/src/pulsecore/source.c
@@ -235,8 +235,9 @@ static int source_set_state(pa_source *s, pa_source_state_t 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;
+    if (s->asyncmsgq)
+        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;
 

commit 43a30a2ff176302e68813f0021aee95799560d78
Author: Tanu Kaskinen <tanuk at iki.fi>
Date:   Fri May 2 13:08:15 2008 +0000

    Fix setrlimit() return value comparsion.
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2350 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/daemon/main.c b/src/daemon/main.c
index b1ba5a3..b6260bb 100644
--- a/src/daemon/main.c
+++ b/src/daemon/main.c
@@ -493,7 +493,7 @@ int main(int argc, char *argv[]) {
                 else {
                     rl.rlim_max = rl.rlim_cur = 9;
 
-                    if (setrlimit(RLIMIT_RTPRIO, &rl) < 0) {
+                    if (setrlimit(RLIMIT_RTPRIO, &rl) >= 0) {
                         pa_log_info("Successfully increased RLIMIT_RTPRIO");
                         drop = TRUE;
                     } else

commit ff09fa391ae067c3ab0f84e6cb3bc1e88a92ec62
Author: Tanu Kaskinen <tanuk at iki.fi>
Date:   Fri May 2 13:12:51 2008 +0000

    Fix typo: "now"->"not".
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2351 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/daemon/main.c b/src/daemon/main.c
index b6260bb..f1721b2 100644
--- a/src/daemon/main.c
+++ b/src/daemon/main.c
@@ -469,7 +469,7 @@ int main(int argc, char *argv[]) {
 #endif
 
     if (conf->high_priority && !pa_can_high_priority())
-        pa_log_warn("High-priority scheduling enabled in configuration but now allowed by policy.");
+        pa_log_warn("High-priority scheduling enabled in configuration but not allowed by policy.");
 
     if (conf->high_priority && conf->cmd == PA_CMD_DAEMON)
         pa_raise_priority(conf->nice_level);
@@ -511,7 +511,7 @@ int main(int argc, char *argv[]) {
     }
 
     if (conf->realtime_scheduling && !pa_can_realtime())
-        pa_log_warn("Real-time scheduling enabled in configuration but now allowed by policy.");
+        pa_log_warn("Real-time scheduling enabled in configuration but not allowed by policy.");
 
     LTDL_SET_PRELOADED_SYMBOLS();
     pa_ltdl_init();

commit 59a7467a642e78876f937570d381b1ad959bf612
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sat May 3 01:30:40 2008 +0000

    don't require a module name when resolving a dl symbol
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2352 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/ltdl-helper.c b/src/pulsecore/ltdl-helper.c
index 711396d..b83897a 100644
--- a/src/pulsecore/ltdl-helper.c
+++ b/src/pulsecore/ltdl-helper.c
@@ -42,12 +42,14 @@ pa_void_func_t pa_load_sym(lt_dlhandle handle, const char *module, const char *s
     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))))
+    if ((f = ((pa_void_func_t) (size_t) lt_dlsym(handle, symbol))))
         return f;
 
+    if (!module)
+        return NULL;
+
     /* As the .la files might have been cleansed from the system, we should
      * try with the ltdl prefix as well. */
 
@@ -57,7 +59,7 @@ pa_void_func_t pa_load_sym(lt_dlhandle handle, const char *module, const char *s
         if (!isalnum(*c))
             *c = '_';
 
-    f = (pa_void_func_t) (long) lt_dlsym(handle, sn);
+    f = (pa_void_func_t) (size_t) lt_dlsym(handle, sn);
     pa_xfree(sn);
 
     return f;

commit d2be471ed241273cd1b41c64946d8f0ac47f88ab
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sat May 3 01:31:39 2008 +0000

    make sure to call sink->update_requested_latency() always when we change latency, same for source
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2353 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c
index 6c427e1..d3bacbf 100644
--- a/src/pulsecore/sink.c
+++ b/src/pulsecore/sink.c
@@ -1296,9 +1296,6 @@ void pa_sink_invalidate_requested_latency(pa_sink *s) {
     pa_sink_assert_ref(s);
     pa_assert(PA_SINK_IS_LINKED(s->thread_info.state));
 
-    if (!s->thread_info.requested_latency_valid)
-        return;
-
     s->thread_info.requested_latency_valid = FALSE;
 
     if (s->update_requested_latency)
diff --git a/src/pulsecore/source.c b/src/pulsecore/source.c
index efd6dab..fc4734f 100644
--- a/src/pulsecore/source.c
+++ b/src/pulsecore/source.c
@@ -783,9 +783,6 @@ void pa_source_invalidate_requested_latency(pa_source *s) {
     pa_source_assert_ref(s);
     pa_assert(PA_SOURCE_IS_LINKED(s->thread_info.state));
 
-    if (!s->thread_info.requested_latency_valid)
-        return;
-
     s->thread_info.requested_latency_valid = FALSE;
 
     if (s->update_requested_latency)

commit d2da344fee54f759501952685102f5606d3e2aaa
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sat May 3 01:32:57 2008 +0000

    send PA_SINK_MESSAGE_REMOVE_INPUT only when an asyncmsgq is available, reset resampler only when we really need to
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2354 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c
index bb377c4..317693d 100644
--- a/src/pulsecore/sink-input.c
+++ b/src/pulsecore/sink-input.c
@@ -349,7 +349,8 @@ void pa_sink_input_unlink(pa_sink_input *i) {
     i->state = PA_SINK_INPUT_UNLINKED;
 
     if (linked)
-        pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i->sink), PA_SINK_MESSAGE_REMOVE_INPUT, i, 0, NULL);
+        if (i->sink->asyncmsgq)
+            pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i->sink), PA_SINK_MESSAGE_REMOVE_INPUT, i, 0, NULL);
 
     reset_callbacks(i);
 
@@ -639,7 +640,7 @@ void pa_sink_input_process_rewind(pa_sink_input *i, size_t nbytes /* in sink sam
                 max_rewrite = pa_resampler_request(i->thread_info.resampler, max_rewrite);
 
             /* Calculate how much of the rewinded data should actually be rewritten */
-            amount = PA_MIN(max_rewrite, i->thread_info.rewrite_nbytes);
+            amount = PA_MIN(i->thread_info.rewrite_nbytes, max_rewrite);
 
             /* Convert back to to sink domain */
             r = i->thread_info.resampler ? pa_resampler_result(i->thread_info.resampler, amount) : amount;
@@ -648,17 +649,17 @@ void pa_sink_input_process_rewind(pa_sink_input *i, size_t nbytes /* in sink sam
                 /* Ok, now update the write pointer */
                 pa_memblockq_seek(i->thread_info.render_memblockq, -r, PA_SEEK_RELATIVE);
 
-            if (amount) {
+            if (amount > 0) {
                 pa_log_debug("Have to rewind %lu bytes on implementor.", (unsigned long) amount);
 
                 /* Tell the implementor */
                 if (i->process_rewind)
                     i->process_rewind(i, amount);
-            }
 
-            /* And reset the resampler */
-            if (i->thread_info.resampler)
-                pa_resampler_reset(i->thread_info.resampler);
+                /* And reset the resampler */
+                if (i->thread_info.resampler)
+                    pa_resampler_reset(i->thread_info.resampler);
+            }
         }
 
         i->thread_info.rewrite_nbytes = 0;

commit 3167e0f999f0215e27f769ad76869d0950f0a4e5
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sat May 3 01:33:33 2008 +0000

    follow _unlink() changes from sink-input
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2355 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/source-output.c b/src/pulsecore/source-output.c
index 7f5f374..836e30e 100644
--- a/src/pulsecore/source-output.c
+++ b/src/pulsecore/source-output.c
@@ -273,12 +273,12 @@ void pa_source_output_unlink(pa_source_output*o) {
     if (pa_idxset_remove_by_data(o->source->outputs, o, NULL))
         pa_source_output_unref(o);
 
-    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;
+    update_n_corked(o, PA_SOURCE_OUTPUT_UNLINKED);
+    o->state = PA_SOURCE_OUTPUT_UNLINKED;
+
+    if (linked)
+        if (o->source->asyncmsgq)
+            pa_asyncmsgq_send(o->source->asyncmsgq, PA_MSGOBJECT(o->source), PA_SOURCE_MESSAGE_REMOVE_OUTPUT, o, 0, NULL);
 
     reset_callbacks(o);
 

commit 82caf5a88643e968a3328c1e1fa8fe63f0572084
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sat May 3 01:34:45 2008 +0000

    when rewinding after the end of an underrun, make sure to rewind as much as we can, so that we deal properly with changed latencies of the sink
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2356 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c
index 5fee4cc..d6e5602 100644
--- a/src/pulsecore/protocol-native.c
+++ b/src/pulsecore/protocol-native.c
@@ -1102,7 +1102,7 @@ static void send_record_stream_killed(record_stream *r) {
 static void handle_seek(playback_stream *s, int64_t indexw) {
     playback_stream_assert_ref(s);
 
-/*     pa_log("handle_seek: %llu -- %i", (unsigned long long) s->underrun, pa_memblockq_is_readable(s->memblockq)); */
+/*     pa_log("handle_seek: %llu -- %i", (unsigned long long) s->sink_input->thread_info.underrun_for, pa_memblockq_is_readable(s->memblockq)); */
 
     if (s->sink_input->thread_info.underrun_for > 0) {
 
@@ -1110,15 +1110,13 @@ static void handle_seek(playback_stream *s, int64_t indexw) {
 
         if (pa_memblockq_is_readable(s->memblockq)) {
 
-            size_t u = pa_memblockq_get_length(s->memblockq);
-
-            if (u >= s->sink_input->thread_info.underrun_for)
-                u = s->sink_input->thread_info.underrun_for;
-
             /* We just ended an underrun, let's ask the sink
-             * to rewrite */
+             * for a complete rewind rewrite */
 
-            pa_sink_input_request_rewind(s->sink_input, u, TRUE, TRUE);
+            pa_log_debug("Requesting rewind due to end of underrun.");
+            pa_sink_input_request_rewind(s->sink_input,
+                                         s->sink_input->thread_info.underrun_for == (size_t) -1 ? 0 : s->sink_input->thread_info.underrun_for,
+                                         TRUE, TRUE);
         }
 
     } else {
@@ -1126,11 +1124,13 @@ static void handle_seek(playback_stream *s, int64_t indexw) {
 
         indexr = pa_memblockq_get_read_index(s->memblockq);
 
-        if (indexw < indexr)
+        if (indexw < indexr) {
             /* OK, the sink already asked for this data, so
              * let's have it usk us again */
 
+            pa_log_debug("Requesting rewind due to rewrite.");
             pa_sink_input_request_rewind(s->sink_input, indexr - indexw, FALSE, FALSE);
+        }
     }
 
     request_bytes(s);
@@ -1162,10 +1162,10 @@ static int sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int
 
             pa_assert(chunk);
 
-/*             pa_log("sink input post: %lu", (unsigned long) chunk->length); */
-
             windex = pa_memblockq_get_write_index(s->memblockq);
 
+/*             pa_log("sink input post: %lu %lli", (unsigned long) chunk->length, (long long) windex); */
+
             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);
@@ -1174,6 +1174,8 @@ static int sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int
 
             handle_seek(s, windex);
 
+/*             pa_log("sink input post2: %lu", (unsigned long) pa_memblockq_get_length(s->memblockq)); */
+
             return 0;
         }
 
@@ -1280,7 +1282,7 @@ static int sink_input_pop_cb(pa_sink_input *i, size_t nbytes, pa_memchunk *chunk
 
     if (pa_memblockq_peek(s->memblockq, chunk) < 0) {
 
-/*         pa_log("UNDERRUN"); */
+/*         pa_log("UNDERRUN: %lu", pa_memblockq_get_length(s->memblockq)); */
 
         if (s->drain_request && pa_sink_input_safe_to_remove(i)) {
             s->drain_request = FALSE;
@@ -1288,7 +1290,7 @@ static int sink_input_pop_cb(pa_sink_input *i, size_t nbytes, pa_memchunk *chunk
         } else if (i->thread_info.playing_for > 0)
             pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(s), PLAYBACK_STREAM_MESSAGE_UNDERFLOW, NULL, 0, NULL, NULL);
 
-/*         pa_log("added %llu bytes, total is %llu", (unsigned long long) nbytes, (unsigned long long) s->underrun); */
+/*         pa_log("adding %llu bytes, total is %llu", (unsigned long long) nbytes, (unsigned long long) i->thread_info.underrun_for); */
 
         request_bytes(s);
 

commit 59835d955bf38b7b49cb30c538f02899b15aa1b7
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sat May 3 01:36:05 2008 +0000

    explain why a rewind was requested
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2357 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-alsa-sink.c b/src/modules/module-alsa-sink.c
index efb0fd8..897b955 100644
--- a/src/modules/module-alsa-sink.c
+++ b/src/modules/module-alsa-sink.c
@@ -848,8 +848,10 @@ static void sink_update_requested_latency_cb(pa_sink *s) {
     current fill level. Thus, let's do a full rewind once, to clear
     things up. */
 
-    if (u->hwbuf_unused_frames > before)
+    if (u->hwbuf_unused_frames > before) {
+        pa_log_debug("Requesting rewind due to latency change.");
         pa_sink_request_rewind(s, 0);
+    }
 }
 
 static int process_rewind(struct userdata *u) {
@@ -1311,6 +1313,8 @@ int pa__init(pa_module*m) {
 
                 } else if (snd_mixer_selem_get_playback_dB_range(u->mixer_elem, &u->hw_dB_min, &u->hw_dB_max) >= 0) {
 
+                    /* u->hw_dB_max = 0; u->hw_dB_min = -3000; Use this to make valgrind shut up */
+
                     pa_log_info("Volume ranges from %0.2f dB to %0.2f dB.", u->hw_dB_min/100.0, u->hw_dB_max/100.0);
 
                     /* Let's see if this thing actually is useful for muting */

commit a1c10b5ecb843dbec6a05340ed7297b595a25e91
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sat May 3 01:36:42 2008 +0000

    update LADSPA module for glitch-free moed
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2358 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-ladspa-sink.c b/src/modules/module-ladspa-sink.c
index 6e0faac..f7e7345 100644
--- a/src/modules/module-ladspa-sink.c
+++ b/src/modules/module-ladspa-sink.c
@@ -41,6 +41,7 @@
 #include <pulsecore/thread-mq.h>
 #include <pulsecore/rtpoll.h>
 #include <pulsecore/sample-util.h>
+#include <pulsecore/ltdl-helper.h>
 
 #include "module-ladspa-sink-symdef.h"
 #include "ladspa.h"
@@ -60,6 +61,8 @@ PA_MODULE_USAGE(
         "label=<ladspa plugin label> "
         "control=<comma seperated list of input control values>");
 
+#define MEMBLOCKQ_MAXLENGTH (16*1024*1024)
+
 struct userdata {
     pa_core *core;
     pa_module *module;
@@ -78,6 +81,8 @@ struct userdata {
     /* 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_memblockq *memblockq;
 };
 
 static const char* const valid_modargs[] = {
@@ -141,7 +146,10 @@ static void sink_request_rewind(pa_sink *s) {
     pa_assert_se(u = s->userdata);
 
     /* Just hand this one over to the master sink */
-    pa_sink_input_request_rewind(u->sink_input, s->thread_info.rewind_nbytes, FALSE, FALSE);
+    pa_sink_input_request_rewind(
+            u->sink_input,
+            s->thread_info.rewind_nbytes + pa_memblockq_get_length(u->memblockq),
+            FALSE, FALSE);
 }
 
 /* Called from I/O thread context */
@@ -169,16 +177,29 @@ static int sink_input_pop_cb(pa_sink_input *i, size_t nbytes, pa_memchunk *chunk
     pa_assert(chunk);
     pa_assert_se(u = i->userdata);
 
-    pa_sink_render(u->sink, nbytes, &tchunk);
+    if (!u->sink)
+        return -1;
+
+    while (pa_memblockq_peek(u->memblockq, &tchunk) < 0) {
+        pa_memchunk nchunk;
+
+        pa_sink_render(u->sink, nbytes, &nchunk);
+        pa_memblockq_push(u->memblockq, &nchunk);
+        pa_memblock_unref(nchunk.memblock);
+    }
+
+    pa_assert(tchunk.length > 0);
 
     fs = pa_frame_size(&i->sample_spec);
-    n = tchunk.length / fs;
+    n = PA_MIN(tchunk.length, u->block_size) / fs;
 
     pa_assert(n > 0);
 
-    chunk->memblock = pa_memblock_new(i->sink->core->mempool, tchunk.length);
     chunk->index = 0;
-    chunk->length = tchunk.length;
+    chunk->length = n*fs;
+    chunk->memblock = pa_memblock_new(i->sink->core->mempool, chunk->length);
+
+    pa_memblockq_drop(u->memblockq, chunk->length);
 
     src = (float*) ((uint8_t*) pa_memblock_acquire(tchunk.memblock) + tchunk.index);
     dst = (float*) pa_memblock_acquire(chunk->memblock);
@@ -205,7 +226,35 @@ static void sink_input_process_rewind_cb(pa_sink_input *i, size_t nbytes) {
     pa_assert_se(u = i->userdata);
     pa_assert(nbytes > 0);
 
-    pa_sink_process_rewind(u->sink, nbytes);
+    if (!u->sink)
+        return;
+
+    if (u->sink->thread_info.rewind_nbytes > 0) {
+        size_t max_rewrite, amount;
+
+        max_rewrite = nbytes + pa_memblockq_get_length(u->memblockq);
+        amount = PA_MIN(u->sink->thread_info.rewind_nbytes, max_rewrite);
+        u->sink->thread_info.rewind_nbytes = 0;
+
+        if (amount > 0) {
+            unsigned c;
+
+            pa_memblockq_seek(u->memblockq, -amount, PA_SEEK_RELATIVE);
+            pa_sink_process_rewind(u->sink, amount);
+
+            pa_log_debug("Resetting plugin");
+
+            /* Reset the plugin */
+            if (u->descriptor->deactivate)
+                for (c = 0; c < u->channels; c++)
+                    u->descriptor->deactivate(u->handle[c]);
+            if (u->descriptor->activate)
+                for (c = 0; c < u->channels; c++)
+                    u->descriptor->activate(u->handle[c]);
+        }
+    }
+
+    pa_memblockq_rewind(u->memblockq, nbytes);
 }
 
 /* Called from I/O thread context */
@@ -215,7 +264,10 @@ static void sink_input_update_max_rewind_cb(pa_sink_input *i, size_t nbytes) {
     pa_sink_input_assert_ref(i);
     pa_assert_se(u = i->userdata);
 
-    pa_sink_set_max_rewind(u->sink, nbytes);
+    pa_memblockq_set_maxrewind(u->memblockq, nbytes);
+
+    if (u->sink)
+        pa_sink_set_max_rewind(u->sink, nbytes);
 }
 
 /* Called from I/O thread context */
@@ -225,10 +277,11 @@ static void sink_input_detach_cb(pa_sink_input *i) {
     pa_sink_input_assert_ref(i);
     pa_assert_se(u = i->userdata);
 
-    pa_sink_detach_within_thread(u->sink);
-
-    pa_sink_set_asyncmsgq(u->sink, NULL);
-    pa_sink_set_rtpoll(u->sink, NULL);
+    if (u->sink) {
+        pa_sink_detach_within_thread(u->sink);
+        pa_sink_set_asyncmsgq(u->sink, NULL);
+        pa_sink_set_rtpoll(u->sink, NULL);
+    }
 }
 
 /* Called from I/O thread context */
@@ -238,10 +291,14 @@ static void sink_input_attach_cb(pa_sink_input *i) {
     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);
+    if (u->sink) {
+        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);
 
-    pa_sink_attach_within_thread(u->sink);
+        u->sink->max_latency = u->master->max_latency;
+        u->sink->min_latency = u->master->min_latency;
+    }
 }
 
 /* Called from main context */
@@ -251,17 +308,33 @@ static void sink_input_kill_cb(pa_sink_input *i) {
     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_sink_input_unlink(u->sink_input);
+    pa_sink_input_unref(u->sink_input);
+    u->sink_input = NULL;
+
     pa_module_unload_request(u->module);
 }
 
+/* Called from IO thread context */
+static void sink_input_state_change_cb(pa_sink_input *i, pa_sink_input_state_t state) {
+    struct userdata *u;
+
+    pa_sink_input_assert_ref(i);
+    pa_assert_se(u = i->userdata);
+
+    /* If we are added for the first time, ask for a rewinding so that
+     * we are heard right-away. */
+    if (PA_SINK_INPUT_IS_LINKED(state) &&
+        i->thread_info.state == PA_SINK_INPUT_INIT) {
+        pa_log_debug("Requesting rewind due to state change.");
+        pa_sink_input_request_rewind(i, 0, TRUE, TRUE);
+    }
+}
+
 int pa__init(pa_module*m) {
     struct userdata *u;
     pa_sample_spec ss;
@@ -321,6 +394,7 @@ int pa__init(pa_module*m) {
     u->master = master;
     u->sink = NULL;
     u->sink_input = NULL;
+    u->memblockq = pa_memblockq_new(0, MEMBLOCKQ_MAXLENGTH, 0, pa_frame_size(&ss), 1, 1, 0, NULL);
 
     if (!(e = getenv("LADSPA_PATH")))
         e = LADSPA_PATH;
@@ -337,7 +411,7 @@ int pa__init(pa_module*m) {
         goto fail;
     }
 
-    if (!(descriptor_func = (LADSPA_Descriptor_Function) lt_dlsym(m->dl, "ladspa_descriptor"))) {
+    if (!(descriptor_func = (LADSPA_Descriptor_Function) pa_load_sym(m->dl, NULL, "ladspa_descriptor"))) {
         pa_log("LADSPA module lacks ladspa_descriptor() symbol.");
         goto fail;
     }
@@ -345,7 +419,7 @@ int pa__init(pa_module*m) {
     for (j = 0;; j++) {
 
         if (!(d = descriptor_func(j))) {
-            pa_log("Failed to find plugin label '%s' in plugin '%s'.", plugin, label);
+            pa_log("Failed to find plugin label '%s' in plugin '%s'.", label, plugin);
             goto fail;
         }
 
@@ -587,18 +661,16 @@ int pa__init(pa_module*m) {
     pa_sink_new_data_set_sample_spec(&sink_data, &ss);
     pa_sink_new_data_set_channel_map(&sink_data, &map);
     z = pa_proplist_gets(master->proplist, PA_PROP_DEVICE_DESCRIPTION);
-    pa_proplist_sets(sink_data.proplist, PA_PROP_DEVICE_DESCRIPTION, t = pa_sprintf_malloc("LADSPA Plugin %s on %s", label, z ? z : master->name));
-    pa_xfree(t);
+    pa_proplist_setf(sink_data.proplist, PA_PROP_DEVICE_DESCRIPTION, "LADSPA Plugin %s on %s", label, z ? z : master->name);
     pa_proplist_sets(sink_data.proplist, PA_PROP_DEVICE_MASTER_DEVICE, master->name);
     pa_proplist_sets(sink_data.proplist, "device.ladspa.module", plugin);
     pa_proplist_sets(sink_data.proplist, "device.ladspa.label", d->Label);
     pa_proplist_sets(sink_data.proplist, "device.ladspa.name", d->Name);
     pa_proplist_sets(sink_data.proplist, "device.ladspa.maker", d->Maker);
     pa_proplist_sets(sink_data.proplist, "device.ladspa.copyright", d->Copyright);
-    pa_proplist_sets(sink_data.proplist, "device.ladspa.unique_id", t = pa_sprintf_malloc("%lu", (unsigned long) d->UniqueID));
-    pa_xfree(t);
+    pa_proplist_setf(sink_data.proplist, "device.ladspa.unique_id", "%lu", (unsigned long) d->UniqueID);
 
-    u->sink = pa_sink_new(m->core, &sink_data, 0);
+    u->sink = pa_sink_new(m->core, &sink_data, PA_SINK_LATENCY);
     pa_sink_new_data_done(&sink_data);
 
     if (!u->sink) {
@@ -611,7 +683,6 @@ int pa__init(pa_module*m) {
     u->sink->update_requested_latency = sink_update_requested_latency;
     u->sink->request_rewind = sink_request_rewind;
     u->sink->userdata = u;
-    u->sink->flags = PA_SINK_LATENCY;
 
     pa_sink_set_asyncmsgq(u->sink, master->asyncmsgq);
     pa_sink_set_rtpoll(u->sink, master->rtpoll);
@@ -638,6 +709,7 @@ int pa__init(pa_module*m) {
     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->state_change = sink_input_state_change_cb;
     u->sink_input->userdata = u;
 
     pa_sink_put(u->sink);
@@ -689,6 +761,9 @@ void pa__done(pa_module*m) {
     if (u->output != u->input)
         pa_xfree(u->output);
 
+    if (u->memblockq)
+        pa_memblockq_free(u->memblockq);
+
     pa_xfree(u->input);
 
     pa_xfree(u->control);

commit 71d14d40c81195ea4a76fe45be06e705f1e5ad05
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sat May 3 02:01:29 2008 +0000

    fix remapping sink for glitch-free
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2359 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-ladspa-sink.c b/src/modules/module-ladspa-sink.c
index f7e7345..be509d7 100644
--- a/src/modules/module-ladspa-sink.c
+++ b/src/modules/module-ladspa-sink.c
@@ -3,7 +3,7 @@
 /***
   This file is part of PulseAudio.
 
-  Copyright 2004-2006 Lennart Poettering
+  Copyright 2004-2008 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
@@ -264,10 +264,11 @@ static void sink_input_update_max_rewind_cb(pa_sink_input *i, size_t nbytes) {
     pa_sink_input_assert_ref(i);
     pa_assert_se(u = i->userdata);
 
-    pa_memblockq_set_maxrewind(u->memblockq, nbytes);
+    if (!u->sink)
+        return;
 
-    if (u->sink)
-        pa_sink_set_max_rewind(u->sink, nbytes);
+    pa_memblockq_set_maxrewind(u->memblockq, nbytes);
+    pa_sink_set_max_rewind(u->sink, nbytes);
 }
 
 /* Called from I/O thread context */
@@ -277,11 +278,12 @@ static void sink_input_detach_cb(pa_sink_input *i) {
     pa_sink_input_assert_ref(i);
     pa_assert_se(u = i->userdata);
 
-    if (u->sink) {
-        pa_sink_detach_within_thread(u->sink);
-        pa_sink_set_asyncmsgq(u->sink, NULL);
-        pa_sink_set_rtpoll(u->sink, NULL);
-    }
+    if (!u->sink)
+        return;
+
+    pa_sink_detach_within_thread(u->sink);
+    pa_sink_set_asyncmsgq(u->sink, NULL);
+    pa_sink_set_rtpoll(u->sink, NULL);
 }
 
 /* Called from I/O thread context */
@@ -291,14 +293,15 @@ static void sink_input_attach_cb(pa_sink_input *i) {
     pa_sink_input_assert_ref(i);
     pa_assert_se(u = i->userdata);
 
-    if (u->sink) {
-        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);
+    if (!u->sink)
+        return;
 
-        u->sink->max_latency = u->master->max_latency;
-        u->sink->min_latency = u->master->min_latency;
-    }
+    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);
+
+    u->sink->max_latency = u->master->max_latency;
+    u->sink->min_latency = u->master->min_latency;
 }
 
 /* Called from main context */
@@ -663,6 +666,7 @@ int pa__init(pa_module*m) {
     z = pa_proplist_gets(master->proplist, PA_PROP_DEVICE_DESCRIPTION);
     pa_proplist_setf(sink_data.proplist, PA_PROP_DEVICE_DESCRIPTION, "LADSPA Plugin %s on %s", label, z ? z : master->name);
     pa_proplist_sets(sink_data.proplist, PA_PROP_DEVICE_MASTER_DEVICE, master->name);
+    pa_proplist_sets(sink_data.proplist, PA_PROP_DEVICE_CLASS, "filter");
     pa_proplist_sets(sink_data.proplist, "device.ladspa.module", plugin);
     pa_proplist_sets(sink_data.proplist, "device.ladspa.label", d->Label);
     pa_proplist_sets(sink_data.proplist, "device.ladspa.name", d->Name);
@@ -693,7 +697,7 @@ int pa__init(pa_module*m) {
     sink_input_data.module = m;
     sink_input_data.sink = u->master;
     pa_proplist_sets(sink_input_data.proplist, PA_PROP_MEDIA_NAME, "LADSPA Stream");
-    pa_proplist_sets(sink_input_data.proplist, PA_PROP_MEDIA_ROLE, "routing");
+    pa_proplist_sets(sink_input_data.proplist, PA_PROP_MEDIA_ROLE, "filter");
     pa_sink_input_new_data_set_sample_spec(&sink_input_data, &ss);
     pa_sink_input_new_data_set_channel_map(&sink_input_data, &map);
 
@@ -741,16 +745,16 @@ void pa__done(pa_module*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->sink_input) {
+        pa_sink_input_unlink(u->sink_input);
+        pa_sink_input_unref(u->sink_input);
+    }
+
     for (c = 0; c < u->channels; c++)
         if (u->handle[c]) {
             if (u->descriptor->deactivate)
diff --git a/src/modules/module-remap-sink.c b/src/modules/module-remap-sink.c
index f68b719..c2adf2c 100644
--- a/src/modules/module-remap-sink.c
+++ b/src/modules/module-remap-sink.c
@@ -3,7 +3,7 @@
 /***
   This file is part of PulseAudio.
 
-  Copyright 2004-2006 Lennart Poettering
+  Copyright 2004-2008 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
@@ -119,7 +119,10 @@ static void sink_request_rewind(pa_sink *s) {
     pa_sink_assert_ref(s);
     pa_assert_se(u = s->userdata);
 
-    pa_sink_input_request_rewind(u->sink_input, s->thread_info.rewind_nbytes, FALSE, FALSE);
+    pa_sink_input_request_rewind(
+            u->sink_input,
+            s->thread_info.rewind_nbytes,
+            FALSE, FALSE);
 }
 
 /* Called from I/O thread context */
@@ -143,6 +146,9 @@ static int sink_input_pop_cb(pa_sink_input *i, size_t nbytes, pa_memchunk *chunk
     pa_assert(chunk);
     pa_assert_se(u = i->userdata);
 
+    if (!u->sink)
+        return -1;
+
     pa_sink_render(u->sink, nbytes, chunk);
     return 0;
 }
@@ -155,7 +161,18 @@ static void sink_input_process_rewind_cb(pa_sink_input *i, size_t nbytes) {
     pa_assert_se(u = i->userdata);
     pa_assert(nbytes > 0);
 
-    pa_sink_process_rewind(u->sink, nbytes);
+    if (!u->sink)
+        return;
+
+    if (u->sink->thread_info.rewind_nbytes > 0) {
+        size_t amount;
+
+        amount = PA_MIN(u->sink->thread_info.rewind_nbytes, nbytes);
+        u->sink->thread_info.rewind_nbytes = 0;
+
+        if (amount > 0)
+            pa_sink_process_rewind(u->sink, amount);
+    }
 }
 
 /* Called from I/O thread context */
@@ -165,6 +182,9 @@ static void sink_input_update_max_rewind_cb(pa_sink_input *i, size_t nbytes) {
     pa_sink_input_assert_ref(i);
     pa_assert_se(u = i->userdata);
 
+    if (!u->sink)
+        return;
+
     pa_sink_set_max_rewind(u->sink, nbytes);
 }
 
@@ -175,8 +195,10 @@ static void sink_input_detach_cb(pa_sink_input *i) {
     pa_sink_input_assert_ref(i);
     pa_assert_se(u = i->userdata);
 
-    pa_sink_detach_within_thread(u->sink);
+    if (!u->sink)
+        return;
 
+    pa_sink_detach_within_thread(u->sink);
     pa_sink_set_asyncmsgq(u->sink, NULL);
     pa_sink_set_rtpoll(u->sink, NULL);
 }
@@ -188,10 +210,15 @@ static void sink_input_attach_cb(pa_sink_input *i) {
     pa_sink_input_assert_ref(i);
     pa_assert_se(u = i->userdata);
 
+    if (!u->sink)
+        return;
+
     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);
+
+    u->sink->max_latency = u->master->max_latency;
+    u->sink->min_latency = u->master->min_latency;
 }
 
 /* Called from main context */
@@ -201,23 +228,38 @@ static void sink_input_kill_cb(pa_sink_input *i) {
     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_sink_input_unlink(u->sink_input);
+    pa_sink_input_unref(u->sink_input);
+    u->sink_input = NULL;
+
     pa_module_unload_request(u->module);
 }
 
+/* Called from IO thread context */
+static void sink_input_state_change_cb(pa_sink_input *i, pa_sink_input_state_t state) {
+    struct userdata *u;
+
+    pa_sink_input_assert_ref(i);
+    pa_assert_se(u = i->userdata);
+
+    /* If we are added for the first time, ask for a rewinding so that
+     * we are heard right-away. */
+    if (PA_SINK_INPUT_IS_LINKED(state) &&
+        i->thread_info.state == PA_SINK_INPUT_INIT) {
+        pa_log_debug("Requesting rewind due to state change.");
+        pa_sink_input_request_rewind(i, 0, TRUE, TRUE);
+    }
+}
+
 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;
     const char *k;
     pa_sink *master;
     pa_sink_input_new_data sink_input_data;
@@ -273,11 +315,11 @@ int pa__init(pa_module*m) {
     pa_sink_new_data_set_sample_spec(&sink_data, &ss);
     pa_sink_new_data_set_channel_map(&sink_data, &sink_map);
     k = pa_proplist_gets(master->proplist, PA_PROP_DEVICE_DESCRIPTION);
-    pa_proplist_sets(sink_data.proplist, PA_PROP_DEVICE_DESCRIPTION, t = pa_sprintf_malloc("Remapped %s", k ? k : master->name));
-    pa_xfree(t);
+    pa_proplist_setf(sink_data.proplist, PA_PROP_DEVICE_DESCRIPTION, "Remapped %s", k ? k : master->name);
     pa_proplist_sets(sink_data.proplist, PA_PROP_DEVICE_MASTER_DEVICE, master->name);
+    pa_proplist_sets(sink_data.proplist, PA_PROP_DEVICE_CLASS, "filter");
 
-    u->sink = pa_sink_new(m->core, &sink_data, 0);
+    u->sink = pa_sink_new(m->core, &sink_data, PA_SINK_LATENCY);
     pa_sink_new_data_done(&sink_data);
 
     if (!u->sink) {
@@ -290,7 +332,6 @@ int pa__init(pa_module*m) {
     u->sink->update_requested_latency = sink_update_requested_latency;
     u->sink->request_rewind = sink_request_rewind;
     u->sink->userdata = u;
-    u->sink->flags = PA_SINK_LATENCY;
 
     pa_sink_set_asyncmsgq(u->sink, master->asyncmsgq);
     pa_sink_set_rtpoll(u->sink, master->rtpoll);
@@ -301,7 +342,7 @@ int pa__init(pa_module*m) {
     sink_input_data.module = m;
     sink_input_data.sink = u->master;
     pa_proplist_sets(sink_input_data.proplist, PA_PROP_MEDIA_NAME, "Remapped Stream");
-    pa_proplist_sets(sink_input_data.proplist, PA_PROP_MEDIA_ROLE, "routing");
+    pa_proplist_sets(sink_input_data.proplist, PA_PROP_MEDIA_ROLE, "filter");
     pa_sink_input_new_data_set_sample_spec(&sink_input_data, &ss);
     pa_sink_input_new_data_set_channel_map(&sink_input_data, &stream_map);
 
@@ -317,6 +358,7 @@ int pa__init(pa_module*m) {
     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->state_change = sink_input_state_change_cb;
     u->sink_input->userdata = u;
 
     pa_sink_put(u->sink);
@@ -343,15 +385,15 @@ void pa__done(pa_module*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->sink_input) {
+        pa_sink_input_unlink(u->sink_input);
+        pa_sink_input_unref(u->sink_input);
+    }
+
     pa_xfree(u);
 }

commit 4fa6cb4589516226fd8707610eeb24b1bdaf3c45
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue May 6 21:10:53 2008 +0000

    add a few more asserts, don't allow pa_limit_caps() to fail
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2370 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/daemon/caps.c b/src/daemon/caps.c
index d78e968..e936d6b 100644
--- a/src/daemon/caps.c
+++ b/src/daemon/caps.c
@@ -85,31 +85,21 @@ void pa_drop_root(void) {
 #if defined(HAVE_SYS_CAPABILITY_H) && defined(HAVE_SYS_PRCTL_H)
 
 /* Limit permitted capabilities set to CAPSYS_NICE */
-int pa_limit_caps(void) {
-    int r = -1;
+void pa_limit_caps(void) {
     cap_t caps;
     cap_value_t nice_cap = CAP_SYS_NICE;
 
     pa_assert_se(caps = cap_init());
+    pa_assert_se(cap_clear(caps) == 0);
+    pa_assert_se(cap_set_flag(caps, CAP_EFFECTIVE, 1, &nice_cap, CAP_SET) == 0);
+    pa_assert_se(cap_set_flag(caps, CAP_PERMITTED, 1, &nice_cap, CAP_SET) == 0);
+    pa_assert_se(cap_set_proc(caps) == 0);
 
-    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)
-        goto fail;
-
-    if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) < 0)
-        goto fail;
+    pa_assert_se(prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) == 0);
 
     pa_log_info("Dropped capabilities successfully.");
 
-    r = 1;
-
-fail:
-    cap_free(caps);
-
-    return r;
+    pa_assert_se(cap_free(caps) == 0);
 }
 
 /* Drop all capabilities, effectively becoming a normal user */
@@ -119,9 +109,9 @@ void pa_drop_caps(void) {
     pa_assert_se(prctl(PR_SET_KEEPCAPS, 0, 0, 0, 0) == 0);
 
     pa_assert_se(caps = cap_init());
-    cap_clear(caps);
+    pa_assert_se(cap_clear(caps) == 0);
     pa_assert_se(cap_set_proc(caps) == 0);
-    cap_free(caps);
+    pa_assert_se(cap_free(caps) == 0);
 }
 
 #else
diff --git a/src/daemon/caps.h b/src/daemon/caps.h
index 91c8841..5b21f12 100644
--- a/src/daemon/caps.h
+++ b/src/daemon/caps.h
@@ -26,6 +26,6 @@
 
 void pa_drop_root(void);
 void pa_drop_caps(void);
-int pa_limit_caps(void);
+void pa_limit_caps(void);
 
 #endif

commit dee3555b2a614e3fa824533125ab4b210d7f8377
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue May 6 21:11:55 2008 +0000

    rename 'routing' to 'filter'
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2371 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulse/proplist.h b/src/pulse/proplist.h
index 40c4775..d1bf371 100644
--- a/src/pulse/proplist.h
+++ b/src/pulse/proplist.h
@@ -38,7 +38,7 @@ PA_C_DECL_BEGIN
  *    media.filename
  *    media.icon
  *    media.icon_name
- *    media.role                    video, music, game, event, phone, production, routing, abstract
+ *    media.role                    video, music, game, event, phone, production, filter, abstract
  *    event.id                      button-click, session-login
  *    event.x11.display
  *    event.x11.xid
@@ -60,7 +60,7 @@ PA_C_DECL_BEGIN
  *    device.bus_path
  *    device.serial
  *    device.vendor_product_id
- *    device.class                   sound, modem, monitor
+ *    device.class                   sound, modem, monitor, filter
  *    device.form_factor             laptop-speakers, external-speakers, telephone, tv-capture, webcam-capture, microphone-capture, headset
  *    device.connector               isa, pci, usb, firewire, bluetooth
  *    device.access_mode             mmap, mmap_rewrite, serial

commit 91fbb691a2d46402f64c9ffc337ec35e6df8e262
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue May 6 21:12:39 2008 +0000

    explain why changing rlimits at this time is safe
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2372 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/daemon/main.c b/src/daemon/main.c
index f1721b2..789d104 100644
--- a/src/daemon/main.c
+++ b/src/daemon/main.c
@@ -465,6 +465,13 @@ int main(int argc, char *argv[]) {
     }
 
 #ifdef HAVE_SYS_RESOURCE_H
+    /* Reset resource limits. If we are run as root (for system mode)
+     * this might end up increasing the limits, which is intended
+     * behaviour. For all other cases, i.e. started as normal user, or
+     * SUID root at this point we should have no CAP_SYS_RESOURCE and
+     * increasing the limits thus should fail. Which is, too, intended
+     * behaviour */
+
     set_all_rlimits(conf);
 #endif
 

commit 44241ac2434ee6c5e66b97f5b89a892aa8f75001
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed May 7 01:34:54 2008 +0000

    define callback function types; allow pa_signal_done() to be called even without prior pa_signal_init()
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2377 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulse/mainloop-signal.c b/src/pulse/mainloop-signal.c
index 8ad465b..91c6bf6 100644
--- a/src/pulse/mainloop-signal.c
+++ b/src/pulse/mainloop-signal.c
@@ -3,7 +3,7 @@
 /***
   This file is part of PulseAudio.
 
-  Copyright 2004-2006 Lennart Poettering
+  Copyright 2004-2008 Lennart Poettering
   Copyright 2006 Pierre Ossman <ossman at cendio.se> for Cendio AB
 
   PulseAudio is free software; you can redistribute it and/or modify
@@ -55,9 +55,9 @@ struct pa_signal_event {
 #else
     void (*saved_handler)(int sig);
 #endif
-    void (*callback) (pa_mainloop_api*a, pa_signal_event *e, int sig, void *userdata);
     void *userdata;
-    void (*destroy_callback) (pa_mainloop_api*a, pa_signal_event*e, void *userdata);
+    pa_signal_cb_t callback;
+    pa_signal_destroy_cb_t destroy_callback;
     pa_signal_event *previous, *next;
 };
 
@@ -74,6 +74,7 @@ static void signal_handler(int sig) {
 #ifndef HAVE_SIGACTION
     signal(sig, signal_handler);
 #endif
+
     pa_write(signal_pipe[1], &sig, sizeof(sig), NULL);
 
     errno = saved_errno;
@@ -142,23 +143,21 @@ int pa_signal_init(pa_mainloop_api *a) {
 }
 
 void pa_signal_done(void) {
-    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);
 
-    api->io_free(io_event);
-    io_event = NULL;
+    if (io_event) {
+        pa_assert(api);
+        api->io_free(io_event);
+        io_event = NULL;
+    }
 
     pa_close_pipe(signal_pipe);
 
     api = NULL;
 }
 
-pa_signal_event* pa_signal_new(int sig, void (*_callback) (pa_mainloop_api *api, pa_signal_event*e, int sig, void *userdata), void *userdata) {
+pa_signal_event* pa_signal_new(int sig, pa_signal_cb_t _callback, void *userdata) {
     pa_signal_event *e = NULL;
 
 #ifdef HAVE_SIGACTION
@@ -223,7 +222,7 @@ void pa_signal_free(pa_signal_event *e) {
     pa_xfree(e);
 }
 
-void pa_signal_set_destroy(pa_signal_event *e, void (*_callback) (pa_mainloop_api *api, pa_signal_event*e, void *userdata)) {
+void pa_signal_set_destroy(pa_signal_event *e, pa_signal_destroy_cb_t _callback) {
     pa_assert(e);
 
     e->destroy_callback = _callback;
diff --git a/src/pulse/mainloop-signal.h b/src/pulse/mainloop-signal.h
index 50aa99c..bdb0f73 100644
--- a/src/pulse/mainloop-signal.h
+++ b/src/pulse/mainloop-signal.h
@@ -6,7 +6,7 @@
 /***
   This file is part of PulseAudio.
 
-  Copyright 2004-2006 Lennart Poettering
+  Copyright 2004-2008 Lennart Poettering
   Copyright 2006 Pierre Ossman <ossman at cendio.se> for Cendio AB
 
   PulseAudio is free software; you can redistribute it and/or modify
@@ -39,23 +39,27 @@ PA_C_DECL_BEGIN
  * signals. However, you may hook signal support into an abstract main loop via the routines defined herein.
  */
 
+/** An opaque UNIX signal event source object */
+typedef struct pa_signal_event pa_signal_event;
+
+typedef void (*pa_signal_cb_t) (pa_mainloop_api *api, pa_signal_event*e, int sig, void *userdata);
+
+typedef void (*pa_signal_destroy_cb_t) (pa_mainloop_api *api, pa_signal_event*e, void *userdata);
+
 /** Initialize the UNIX signal subsystem and bind it to the specified main loop */
 int pa_signal_init(pa_mainloop_api *api);
 
 /** Cleanup the signal subsystem */
 void pa_signal_done(void);
 
-/** An opaque UNIX signal event source object */
-typedef struct pa_signal_event pa_signal_event;
-
 /** Create a new UNIX signal event source object */
-pa_signal_event* pa_signal_new(int sig, void (*callback) (pa_mainloop_api *api, pa_signal_event*e, int sig, void *userdata), void *userdata);
+pa_signal_event* pa_signal_new(int sig, pa_signal_cb_t callback, void *userdata);
 
 /** Free a UNIX signal event source object */
 void pa_signal_free(pa_signal_event *e);
 
 /** Set a function that is called when the signal event source is destroyed. Use this to free the userdata argument if required */
-void pa_signal_set_destroy(pa_signal_event *e, void (*callback) (pa_mainloop_api *api, pa_signal_event*e, void *userdata));
+void pa_signal_set_destroy(pa_signal_event *e, pa_signal_destroy_cb_t callback);
 
 PA_C_DECL_END
 

commit 6c28f1d5b962192eaecb78c840377d2a2af05b77
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed May 7 01:36:44 2008 +0000

    decrease verbosity a bit
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2378 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-alsa-sink.c b/src/modules/module-alsa-sink.c
index 897b955..4a997cd 100644
--- a/src/modules/module-alsa-sink.c
+++ b/src/modules/module-alsa-sink.c
@@ -258,7 +258,7 @@ static int mmap_write(struct userdata *u) {
 
         frames = n = n - u->hwbuf_unused_frames;
 
-        pa_log_debug("%lu frames to write", (unsigned long) frames);
+/*        pa_log_debug("%lu frames to write", (unsigned long) frames);*/
 
         if (PA_UNLIKELY((err = snd_pcm_mmap_begin(u->pcm_handle, &areas, &offset, &frames)) < 0)) {
 
@@ -308,7 +308,7 @@ static int mmap_write(struct userdata *u) {
 
         u->frame_index += frames;
 
-        pa_log_debug("wrote %lu frames", (unsigned long) frames);
+/*         pa_log_debug("wrote %lu frames", (unsigned long) frames); */
 
         if (PA_LIKELY(frames >= (snd_pcm_uframes_t) n))
             return work_done;
@@ -349,7 +349,7 @@ static int unix_write(struct userdata *u) {
 
         n -= u->hwbuf_unused_frames;
 
-        pa_log_debug("%lu frames to write", (unsigned long) frames);
+/*         pa_log_debug("%lu frames to write", (unsigned long) frames); */
 
         if (u->memchunk.length <= 0)
             pa_sink_render(u->sink, n * u->frame_size, &u->memchunk);
@@ -389,7 +389,7 @@ static int unix_write(struct userdata *u) {
 
         u->frame_index += frames;
 
-        pa_log_debug("wrote %lu frames", (unsigned long) frames);
+/*         pa_log_debug("wrote %lu frames", (unsigned long) frames); */
 
         if (PA_LIKELY(frames >= n))
             return work_done;

commit 9d7fde5fe33aeebf2b0047f63359d4b051c9579c
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed May 7 01:37:42 2008 +0000

    rework the rewinding logic once again, fixing
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2379 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c
index 317693d..0be1cc9 100644
--- a/src/pulsecore/sink-input.c
+++ b/src/pulsecore/sink-input.c
@@ -250,6 +250,7 @@ pa_sink_input* pa_sink_input_new(
     i->thread_info.muted = i->muted;
     i->thread_info.requested_sink_latency = (pa_usec_t) -1;
     i->thread_info.rewrite_nbytes = 0;
+    i->thread_info.rewrite_flush = FALSE;
     i->thread_info.underrun_for = (uint64_t) -1;
     i->thread_info.playing_for = 0;
 
@@ -602,8 +603,7 @@ void pa_sink_input_drop(pa_sink_input *i, size_t nbytes /* in sink sample spec *
     didn't do this for us, we do it here. However, since the sink
     apparently doesn't support rewinding, we pass 0 here. This still
     allows rewinding through the render buffer. */
-    if (i->thread_info.rewrite_nbytes > 0)
-        pa_sink_input_process_rewind(i, 0);
+    pa_sink_input_process_rewind(i, 0);
 
     pa_memblockq_drop(i->thread_info.render_memblockq, nbytes);
 
@@ -619,54 +619,59 @@ void pa_sink_input_process_rewind(pa_sink_input *i, size_t nbytes /* in sink sam
 
 /*     pa_log_debug("rewind(%lu, %lu)", (unsigned long) nbytes, (unsigned long) i->thread_info.rewrite_nbytes); */
 
-    if (i->thread_info.underrun_for > 0) {
-        /* We don't rewind when we are underrun */
-        i->thread_info.rewrite_nbytes = 0;
-        return;
+    if (nbytes > 0) {
+        pa_log_debug("Have to rewind %lu bytes on render memblockq.", (unsigned long) nbytes);
+        pa_memblockq_rewind(i->thread_info.render_memblockq, nbytes);
     }
 
-    if (nbytes > 0)
-        pa_log_debug("Have to rewind %lu bytes on render memblockq.", (unsigned long) nbytes);
+    if (i->thread_info.rewrite_nbytes == (size_t) -1) {
 
-    if (i->thread_info.rewrite_nbytes > 0) {
-        size_t max_rewrite;
+        /* We were asked to drop all buffered data, and rerequest new
+         * data from implementor the next time push() is called */
 
-        /* Calculate how much make sense to rewrite at most */
-        if ((max_rewrite = nbytes + pa_memblockq_get_length(i->thread_info.render_memblockq)) > 0) {
-            size_t amount, r;
+        pa_memblockq_flush(i->thread_info.render_memblockq);
 
-            /* Transform into local domain */
-            if (i->thread_info.resampler)
-                max_rewrite = pa_resampler_request(i->thread_info.resampler, max_rewrite);
+    } else if (i->thread_info.rewrite_nbytes > 0) {
+        size_t max_rewrite, amount;
 
-            /* Calculate how much of the rewinded data should actually be rewritten */
-            amount = PA_MIN(i->thread_info.rewrite_nbytes, max_rewrite);
+        /* Calculate how much make sense to rewrite at most */
+        max_rewrite = nbytes + pa_memblockq_get_length(i->thread_info.render_memblockq);
 
-            /* Convert back to to sink domain */
-            r = i->thread_info.resampler ? pa_resampler_result(i->thread_info.resampler, amount) : amount;
+        /* Transform into local domain */
+        if (i->thread_info.resampler)
+            max_rewrite = pa_resampler_request(i->thread_info.resampler, max_rewrite);
 
-            if (r > 0)
-                /* Ok, now update the write pointer */
-                pa_memblockq_seek(i->thread_info.render_memblockq, -r, PA_SEEK_RELATIVE);
+        /* Calculate how much of the rewinded data should actually be rewritten */
+        amount = PA_MIN(i->thread_info.rewrite_nbytes, max_rewrite);
 
-            if (amount > 0) {
-                pa_log_debug("Have to rewind %lu bytes on implementor.", (unsigned long) amount);
+        if (amount > 0) {
+            pa_log_debug("Have to rewind %lu bytes on implementor.", (unsigned long) amount);
 
-                /* Tell the implementor */
-                if (i->process_rewind)
-                    i->process_rewind(i, amount);
+            /* Tell the implementor */
+            if (i->process_rewind)
+                i->process_rewind(i, amount);
 
-                /* And reset the resampler */
+            if (i->thread_info.rewrite_flush)
+                pa_memblockq_silence(i->thread_info.render_memblockq);
+            else {
+
+                /* Convert back to to sink domain */
                 if (i->thread_info.resampler)
-                    pa_resampler_reset(i->thread_info.resampler);
+                    amount = pa_resampler_result(i->thread_info.resampler, amount);
+
+                if (amount > 0)
+                    /* Ok, now update the write pointer */
+                    pa_memblockq_seek(i->thread_info.render_memblockq, - ((int64_t) amount), PA_SEEK_RELATIVE);
             }
-        }
 
-        i->thread_info.rewrite_nbytes = 0;
+            /* And reset the resampler */
+            if (i->thread_info.resampler)
+                pa_resampler_reset(i->thread_info.resampler);
+        }
     }
 
-    if (nbytes > 0)
-        pa_memblockq_rewind(i->thread_info.render_memblockq, nbytes);
+    i->thread_info.rewrite_nbytes = 0;
+    i->thread_info.rewrite_flush = FALSE;
 }
 
 /* Called from thread context */
@@ -1016,19 +1021,15 @@ void pa_sink_input_set_state_within_thread(pa_sink_input *i, pa_sink_input_state
 
     if (state == PA_SINK_INPUT_CORKED && i->thread_info.state != PA_SINK_INPUT_CORKED) {
 
-        /* OK, we're corked, so let's make sure we have total silence
-         * from now on on this stream */
-        pa_memblockq_silence(i->thread_info.render_memblockq);
-
         /* This will tell the implementing sink input driver to rewind
          * so that the unplayed already mixed data is not lost */
-        pa_sink_input_request_rewind(i, 0, FALSE, FALSE);
+        pa_sink_input_request_rewind(i, 0, TRUE, TRUE);
 
     } else if (i->thread_info.state == PA_SINK_INPUT_CORKED && state != PA_SINK_INPUT_CORKED) {
 
         /* OK, we're being uncorked. Make sure we're not rewound when
          * the hw buffer is remixed and request a remix. */
-        pa_sink_input_request_rewind(i, 0, TRUE, TRUE);
+        pa_sink_input_request_rewind(i, 0, FALSE, TRUE);
     }
 
     if (i->state_change)
@@ -1047,12 +1048,12 @@ int pa_sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int64_t
     switch (code) {
         case PA_SINK_INPUT_MESSAGE_SET_VOLUME:
             i->thread_info.volume = *((pa_cvolume*) userdata);
-            pa_sink_input_request_rewind(i, 0, FALSE, FALSE);
+            pa_sink_input_request_rewind(i, 0, TRUE, FALSE);
             return 0;
 
         case PA_SINK_INPUT_MESSAGE_SET_MUTE:
             i->thread_info.muted = PA_PTR_TO_UINT(userdata);
-            pa_sink_input_request_rewind(i, 0, FALSE, FALSE);
+            pa_sink_input_request_rewind(i, 0, TRUE, FALSE);
             return 0;
 
         case PA_SINK_INPUT_MESSAGE_GET_LATENCY: {
@@ -1111,59 +1112,60 @@ pa_bool_t pa_sink_input_safe_to_remove(pa_sink_input *i) {
     return TRUE;
 }
 
-void pa_sink_input_request_rewind(pa_sink_input *i, size_t nbytes  /* in our sample spec */, pa_bool_t ignore_underruns, pa_bool_t not_here) {
+void pa_sink_input_request_rewind(pa_sink_input *i, size_t nbytes  /* in our sample spec */, pa_bool_t rewrite, pa_bool_t flush) {
     size_t lbq;
 
+    /* If 'rewrite' is TRUE the sink is rewound as far as requested
+     * and possible and the exact value of this is passed back the
+     * implementor via process_rewind(). If 'flush' is also TRUE all
+     * already rendered data is also dropped.
+     *
+     * If 'rewrite' is FALSE the sink is rewound as far as requested
+     * and possible and the already rendered data is dropped so that
+     * in the next iteration we read new data from the
+     * implementor. This implies 'flush' is TRUE. */
+
     pa_sink_input_assert_ref(i);
+    pa_assert(i->thread_info.rewrite_nbytes == 0);
 
     /* We don't take rewind requests while we are corked */
     if (i->state == PA_SINK_INPUT_CORKED)
         return;
 
+    pa_assert(rewrite || flush);
+
     /* Calculate how much we can rewind locally without having to
      * touch the sink */
-    if (not_here)
-        lbq = 0;
-    else
+    if (rewrite)
         lbq = pa_memblockq_get_length(i->thread_info.render_memblockq);
+    else
+        lbq = 0;
 
     /* Check if rewinding for the maximum is requested, and if so, fix up */
     if (nbytes <= 0) {
 
-        /* Calulate maximum number of bytes that could be rewound in theory */
+        /* Calculate maximum number of bytes that could be rewound in theory */
         nbytes = i->sink->thread_info.max_rewind + lbq;
 
         /* Transform from sink domain */
-        nbytes =
-            i->thread_info.resampler ?
-            pa_resampler_request(i->thread_info.resampler, nbytes) :
-            nbytes;
+        if (i->thread_info.resampler)
+            nbytes = pa_resampler_request(i->thread_info.resampler, nbytes);
     }
 
-    if (not_here) {
-        i->thread_info.playing_for = 0;
-        i->thread_info.underrun_for = (uint64_t) -1;
-    } else {
-        /* Increase the number of bytes to rewrite, never decrease */
-        if (nbytes < i->thread_info.rewrite_nbytes)
-            nbytes = i->thread_info.rewrite_nbytes;
-
+    if (rewrite) {
         /* Make sure to not overwrite over underruns */
-        if (!ignore_underruns)
-            if (nbytes > i->thread_info.playing_for)
-                nbytes = (size_t) i->thread_info.playing_for;
+        if (nbytes > i->thread_info.playing_for)
+            nbytes = (size_t) i->thread_info.playing_for;
 
         i->thread_info.rewrite_nbytes = nbytes;
-    }
+    } else
+        i->thread_info.rewrite_nbytes = (size_t) -1;
 
-    /* Transform to sink domain */
-    nbytes =
-        i->thread_info.resampler ?
-        pa_resampler_result(i->thread_info.resampler, nbytes) :
-        nbytes;
+    i->thread_info.rewrite_flush = flush && i->thread_info.rewrite_nbytes != 0;
 
-    if (nbytes <= 0)
-        return;
+    /* Transform to sink domain */
+    if (i->thread_info.resampler)
+        nbytes = pa_resampler_result(i->thread_info.resampler, nbytes);
 
     if (nbytes > lbq)
         pa_sink_request_rewind(i->sink, nbytes - lbq);
diff --git a/src/pulsecore/sink-input.h b/src/pulsecore/sink-input.h
index b70cb0a..8edd7ec 100644
--- a/src/pulsecore/sink-input.h
+++ b/src/pulsecore/sink-input.h
@@ -156,8 +156,8 @@ struct pa_sink_input {
         pa_memblockq *render_memblockq;
 
         size_t rewrite_nbytes;
+        pa_bool_t rewrite_flush;
         uint64_t underrun_for, playing_for;
-        pa_bool_t ignore_rewind;
 
         pa_sink_input *sync_prev, *sync_next;
 
@@ -241,7 +241,7 @@ fully -- or at all. If the request for a rewrite was successful, the
 sink driver will call ->rewind() and pass the number of bytes that
 could be rewound in the HW device. This functionality is required for
 implementing the "zero latency" write-through functionality. */
-void pa_sink_input_request_rewind(pa_sink_input *i, size_t nbytes, pa_bool_t ignore_rewind, pa_bool_t not_here);
+void pa_sink_input_request_rewind(pa_sink_input *i, size_t nbytes, pa_bool_t rewrite, pa_bool_t flush);
 
 /* Callable by everyone from main thread*/
 

commit 8afbdc375c23c21d484df456d22e982a8e26d85b
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed May 7 01:38:16 2008 +0000

    update to new rewinding logic
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2380 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-ladspa-sink.c b/src/modules/module-ladspa-sink.c
index be509d7..664d73e 100644
--- a/src/modules/module-ladspa-sink.c
+++ b/src/modules/module-ladspa-sink.c
@@ -146,10 +146,7 @@ static void sink_request_rewind(pa_sink *s) {
     pa_assert_se(u = s->userdata);
 
     /* Just hand this one over to the master sink */
-    pa_sink_input_request_rewind(
-            u->sink_input,
-            s->thread_info.rewind_nbytes + pa_memblockq_get_length(u->memblockq),
-            FALSE, FALSE);
+    pa_sink_input_request_rewind(u->sink_input, s->thread_info.rewind_nbytes + pa_memblockq_get_length(u->memblockq), TRUE, FALSE);
 }
 
 /* Called from I/O thread context */
@@ -334,7 +331,7 @@ static void sink_input_state_change_cb(pa_sink_input *i, pa_sink_input_state_t s
     if (PA_SINK_INPUT_IS_LINKED(state) &&
         i->thread_info.state == PA_SINK_INPUT_INIT) {
         pa_log_debug("Requesting rewind due to state change.");
-        pa_sink_input_request_rewind(i, 0, TRUE, TRUE);
+        pa_sink_input_request_rewind(i, 0, FALSE, TRUE);
     }
 }
 
diff --git a/src/modules/module-remap-sink.c b/src/modules/module-remap-sink.c
index c2adf2c..985afbc 100644
--- a/src/modules/module-remap-sink.c
+++ b/src/modules/module-remap-sink.c
@@ -119,10 +119,7 @@ static void sink_request_rewind(pa_sink *s) {
     pa_sink_assert_ref(s);
     pa_assert_se(u = s->userdata);
 
-    pa_sink_input_request_rewind(
-            u->sink_input,
-            s->thread_info.rewind_nbytes,
-            FALSE, FALSE);
+    pa_sink_input_request_rewind(u->sink_input, s->thread_info.rewind_nbytes, TRUE, FALSE);
 }
 
 /* Called from I/O thread context */
@@ -251,7 +248,7 @@ static void sink_input_state_change_cb(pa_sink_input *i, pa_sink_input_state_t s
     if (PA_SINK_INPUT_IS_LINKED(state) &&
         i->thread_info.state == PA_SINK_INPUT_INIT) {
         pa_log_debug("Requesting rewind due to state change.");
-        pa_sink_input_request_rewind(i, 0, TRUE, TRUE);
+        pa_sink_input_request_rewind(i, 0, FALSE, TRUE);
     }
 }
 
diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c
index d6e5602..7eeefb8 100644
--- a/src/pulsecore/protocol-native.c
+++ b/src/pulsecore/protocol-native.c
@@ -1116,7 +1116,7 @@ static void handle_seek(playback_stream *s, int64_t indexw) {
             pa_log_debug("Requesting rewind due to end of underrun.");
             pa_sink_input_request_rewind(s->sink_input,
                                          s->sink_input->thread_info.underrun_for == (size_t) -1 ? 0 : s->sink_input->thread_info.underrun_for,
-                                         TRUE, TRUE);
+                                         FALSE, TRUE);
         }
 
     } else {
@@ -1129,7 +1129,7 @@ static void handle_seek(playback_stream *s, int64_t indexw) {
              * let's have it usk us again */
 
             pa_log_debug("Requesting rewind due to rewrite.");
-            pa_sink_input_request_rewind(s->sink_input, indexr - indexw, FALSE, FALSE);
+            pa_sink_input_request_rewind(s->sink_input, indexr - indexw, TRUE, FALSE);
         }
     }
 
diff --git a/src/pulsecore/sound-file-stream.c b/src/pulsecore/sound-file-stream.c
index 918313f..e209676 100644
--- a/src/pulsecore/sound-file-stream.c
+++ b/src/pulsecore/sound-file-stream.c
@@ -3,7 +3,7 @@
 /***
   This file is part of PulseAudio.
 
-  Copyright 2004-2006 Lennart Poettering
+  Copyright 2004-2008 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
@@ -245,7 +245,6 @@ int pa_play_file(
     pa_sample_spec ss;
     pa_sink_input_new_data data;
     int fd;
-    pa_memchunk silence;
 
     pa_assert(sink);
     pa_assert(fname);
@@ -347,9 +346,7 @@ int pa_play_file(
     u->sink_input->state_change = sink_input_state_change_cb;
     u->sink_input->userdata = u;
 
-    pa_sink_input_get_silence(u->sink_input, &silence);
-    u->memblockq = pa_memblockq_new(0, MEMBLOCKQ_MAXLENGTH, 0, pa_frame_size(&u->sink_input->sample_spec), 1, 1, 0, &silence);
-    pa_memblock_unref(silence.memblock);
+    u->memblockq = pa_memblockq_new(0, MEMBLOCKQ_MAXLENGTH, 0, pa_frame_size(&ss), 1, 1, 0, NULL);
 
     pa_sink_input_put(u->sink_input);
 

commit dafcf2053fc652927b4fd55cf904183f89e9ff81
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed May 7 02:21:10 2008 +0000

    beefup proplist handling for sound events
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2381 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/core-scache.c b/src/pulsecore/core-scache.c
index 4036a55..018b283 100644
--- a/src/pulsecore/core-scache.c
+++ b/src/pulsecore/core-scache.c
@@ -141,10 +141,20 @@ static pa_scache_entry* scache_add_item(pa_core *c, const char *name) {
     pa_channel_map_init(&e->channel_map);
     pa_cvolume_reset(&e->volume, PA_CHANNELS_MAX);
 
+    pa_proplist_sets(e->proplist, PA_PROP_MEDIA_ROLE, "event");
+
     return e;
 }
 
-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, pa_proplist *p, uint32_t *idx) {
+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,
+        pa_proplist *p,
+        uint32_t *idx) {
+
     pa_scache_entry *e;
     char st[PA_SAMPLE_SPEC_SNPRINT_MAX];
     pa_channel_map tmap;
@@ -198,6 +208,7 @@ int pa_scache_add_file(pa_core *c, const char *name, const char *filename, uint3
     pa_channel_map map;
     pa_memchunk chunk;
     int r;
+    pa_proplist *p;
 
 #ifdef OS_IS_WIN32
     char buf[MAX_PATH];
@@ -213,7 +224,9 @@ int pa_scache_add_file(pa_core *c, const char *name, const char *filename, uint3
     if (pa_sound_file_load(c->mempool, filename, &ss, &map, &chunk) < 0)
         return -1;
 
-    r = pa_scache_add_item(c, name, &ss, &map, &chunk, NULL, idx);
+    p = pa_proplist_new();
+    pa_proplist_sets(p, PA_PROP_MEDIA_FILENAME, filename);
+    r = pa_scache_add_item(c, name, &ss, &map, &chunk, p, idx);
     pa_memblock_unref(chunk.memblock);
 
     return r;
@@ -239,6 +252,8 @@ int pa_scache_add_file_lazy(pa_core *c, const char *name, const char *filename,
     e->lazy = TRUE;
     e->filename = pa_xstrdup(filename);
 
+    pa_proplist_sets(e->proplist, PA_PROP_MEDIA_FILENAME, filename);
+
     if (!c->scache_auto_unload_event) {
         struct timeval ntv;
         pa_gettimeofday(&ntv);
@@ -292,7 +307,6 @@ void pa_scache_free(pa_core *c) {
 
 int pa_scache_play_item(pa_core *c, const char *name, pa_sink *sink, pa_volume_t volume, pa_proplist *p, uint32_t *sink_input_idx) {
     pa_scache_entry *e;
-    char *t;
     pa_cvolume r;
     pa_proplist *merged;
 
@@ -323,12 +337,12 @@ int pa_scache_play_item(pa_core *c, const char *name, pa_sink *sink, pa_volume_t
 
     merged = pa_proplist_new();
 
-    t = pa_sprintf_malloc("sample:%s", name);
-    pa_proplist_sets(merged, PA_PROP_MEDIA_NAME, t);
-    pa_xfree(t);
+    pa_proplist_setf(merged, PA_PROP_MEDIA_NAME, "Sample %s", name);
 
     pa_proplist_update(merged, PA_UPDATE_REPLACE, e->proplist);
-    pa_proplist_update(merged, PA_UPDATE_REPLACE, p);
+
+    if (p)
+        pa_proplist_update(merged, PA_UPDATE_REPLACE, p);
 
     if (pa_play_memchunk(sink, &e->sample_spec, &e->channel_map, &e->memchunk, &r, merged, sink_input_idx) < 0) {
         pa_proplist_free(merged);

commit 9354da4960e4dae0441c840b0de6d3131faf174f
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed May 7 02:22:30 2008 +0000

    make memchunk/memblockq streams work with glitch-free
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2382 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/play-memblockq.c b/src/pulsecore/play-memblockq.c
index 99b5913..2688f92 100644
--- a/src/pulsecore/play-memblockq.c
+++ b/src/pulsecore/play-memblockq.c
@@ -3,7 +3,7 @@
 /***
   This file is part of PulseAudio.
 
-  Copyright 2006 Lennart Poettering
+  Copyright 2006-2008 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
@@ -99,6 +99,21 @@ static void sink_input_kill_cb(pa_sink_input *i) {
     memblockq_stream_unlink(u);
 }
 
+/* Called from IO thread context */
+static void sink_input_state_change_cb(pa_sink_input *i, pa_sink_input_state_t state) {
+    memblockq_stream *u;
+
+    pa_sink_input_assert_ref(i);
+    u = MEMBLOCKQ_STREAM(i->userdata);
+    memblockq_stream_assert_ref(u);
+
+    /* If we are added for the first time, ask for a rewinding so that
+     * we are heard right-away. */
+    if (PA_SINK_INPUT_IS_LINKED(state) &&
+        i->thread_info.state == PA_SINK_INPUT_INIT)
+        pa_sink_input_request_rewind(i, 0, FALSE, TRUE);
+}
+
 static int sink_input_pop_cb(pa_sink_input *i, size_t nbytes, pa_memchunk *chunk) {
     memblockq_stream *u;
 
@@ -116,6 +131,7 @@ static int sink_input_pop_cb(pa_sink_input *i, size_t nbytes, pa_memchunk *chunk
 
             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);
         }
 
@@ -141,7 +157,7 @@ static void sink_input_process_rewind_cb(pa_sink_input *i, size_t nbytes) {
     pa_memblockq_rewind(u->memblockq, nbytes);
 }
 
-static void sink_input_update_max_rewind(pa_sink_input *i, size_t nbytes) {
+static void sink_input_update_max_rewind_cb(pa_sink_input *i, size_t nbytes) {
     memblockq_stream *u;
 
     pa_sink_input_assert_ref(i);
@@ -194,8 +210,9 @@ pa_sink_input* pa_memblockq_sink_input_new(
 
     u->sink_input->pop = sink_input_pop_cb;
     u->sink_input->process_rewind = sink_input_process_rewind_cb;
-    u->sink_input->update_max_rewind = sink_input_update_max_rewind;
+    u->sink_input->update_max_rewind = sink_input_update_max_rewind_cb;
     u->sink_input->kill = sink_input_kill_cb;
+    u->sink_input->state_change = sink_input_state_change_cb;
     u->sink_input->userdata = u;
 
     if (q)
@@ -255,14 +272,8 @@ void pa_memblockq_sink_input_set_queue(pa_sink_input *i, pa_memblockq *q) {
         pa_memblockq_free(u->memblockq);
 
     if ((u->memblockq = q)) {
-        pa_memchunk silence;
-
         pa_memblockq_set_prebuf(q, 0);
-
-        pa_sink_input_get_silence(i, &silence);
-        pa_memblockq_set_silence(q, &silence);
-        pa_memblock_unref(silence.memblock);
-
+        pa_memblockq_set_silence(q, NULL);
         pa_memblockq_willneed(q);
     }
 }
diff --git a/src/pulsecore/play-memchunk.c b/src/pulsecore/play-memchunk.c
index e4d24a9..67a9213 100644
--- a/src/pulsecore/play-memchunk.c
+++ b/src/pulsecore/play-memchunk.c
@@ -3,7 +3,7 @@
 /***
   This file is part of PulseAudio.
 
-  Copyright 2004-2006 Lennart Poettering
+  Copyright 2004-2008 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
@@ -54,7 +54,7 @@ int pa_play_memchunk(
     pa_assert(ss);
     pa_assert(chunk);
 
-    q = pa_memblockq_new(0, chunk->length, 0, pa_frame_size(ss), 0, 0, 0, NULL);
+    q = pa_memblockq_new(0, chunk->length, 0, pa_frame_size(ss), 1, 1, 0, NULL);
     pa_assert_se(pa_memblockq_push(q, chunk) >= 0);
 
     if ((r = pa_play_memblockq(sink, ss, map, q, volume, p, sink_input_index)) < 0) {

commit d21f45895182ac8a8cdaa08949e3e4db04217880
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed May 7 20:34:39 2008 +0000

    fix a memory leak
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2383 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/core-scache.c b/src/pulsecore/core-scache.c
index 018b283..e554600 100644
--- a/src/pulsecore/core-scache.c
+++ b/src/pulsecore/core-scache.c
@@ -3,7 +3,7 @@
 /***
   This file is part of PulseAudio.
 
-  Copyright 2004-2006 Lennart Poettering
+  Copyright 2004-2008 Lennart Poettering
   Copyright 2006 Pierre Ossman <ossman at cendio.se> for Cendio AB
 
   PulseAudio is free software; you can redistribute it and/or modify
@@ -228,6 +228,7 @@ int pa_scache_add_file(pa_core *c, const char *name, const char *filename, uint3
     pa_proplist_sets(p, PA_PROP_MEDIA_FILENAME, filename);
     r = pa_scache_add_item(c, name, &ss, &map, &chunk, p, idx);
     pa_memblock_unref(chunk.memblock);
+    pa_proplist_free(p);
 
     return r;
 }

commit 6f4d44bb503409cf4c5a36e1e88517fdd29c7b0f
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed May 7 20:35:25 2008 +0000

    apparently alsa expects us to free the memory for card names
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2384 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/alsa-util.c b/src/modules/alsa-util.c
index 47ed9ac..d212abc 100644
--- a/src/modules/alsa-util.c
+++ b/src/modules/alsa-util.c
@@ -1060,6 +1060,9 @@ void pa_alsa_init_proplist(pa_proplist *p, snd_pcm_info_t *pcm_info) {
         pa_proplist_sets(p, PA_PROP_DEVICE_DESCRIPTION, cn);
     else if (n)
         pa_proplist_sets(p, PA_PROP_DEVICE_DESCRIPTION, n);
+
+    free(lcn);
+    free(cn);
 }
 
 int pa_alsa_recover_from_poll(snd_pcm_t *pcm, int revents) {

commit 876d5b408aa23e053b9c35830512038d3227f8e5
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed May 7 20:36:41 2008 +0000

    fix a race condition when tearing down the ladspa/remap sink
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2385 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-ladspa-sink.c b/src/modules/module-ladspa-sink.c
index 664d73e..245efcb 100644
--- a/src/modules/module-ladspa-sink.c
+++ b/src/modules/module-ladspa-sink.c
@@ -174,7 +174,7 @@ static int sink_input_pop_cb(pa_sink_input *i, size_t nbytes, pa_memchunk *chunk
     pa_assert(chunk);
     pa_assert_se(u = i->userdata);
 
-    if (!u->sink)
+    if (!u->sink || !PA_SINK_IS_OPENED(u->sink->thread_info.state))
         return -1;
 
     while (pa_memblockq_peek(u->memblockq, &tchunk) < 0) {
@@ -223,7 +223,7 @@ static void sink_input_process_rewind_cb(pa_sink_input *i, size_t nbytes) {
     pa_assert_se(u = i->userdata);
     pa_assert(nbytes > 0);
 
-    if (!u->sink)
+    if (!u->sink || !PA_SINK_IS_OPENED(u->sink->thread_info.state))
         return;
 
     if (u->sink->thread_info.rewind_nbytes > 0) {
@@ -236,7 +236,7 @@ static void sink_input_process_rewind_cb(pa_sink_input *i, size_t nbytes) {
         if (amount > 0) {
             unsigned c;
 
-            pa_memblockq_seek(u->memblockq, -amount, PA_SEEK_RELATIVE);
+            pa_memblockq_seek(u->memblockq, - (int64_t) amount, PA_SEEK_RELATIVE);
             pa_sink_process_rewind(u->sink, amount);
 
             pa_log_debug("Resetting plugin");
@@ -261,7 +261,7 @@ static void sink_input_update_max_rewind_cb(pa_sink_input *i, size_t nbytes) {
     pa_sink_input_assert_ref(i);
     pa_assert_se(u = i->userdata);
 
-    if (!u->sink)
+    if (!u->sink || !PA_SINK_IS_OPENED(u->sink->thread_info.state))
         return;
 
     pa_memblockq_set_maxrewind(u->memblockq, nbytes);
@@ -275,7 +275,7 @@ static void sink_input_detach_cb(pa_sink_input *i) {
     pa_sink_input_assert_ref(i);
     pa_assert_se(u = i->userdata);
 
-    if (!u->sink)
+    if (!u->sink || !PA_SINK_IS_OPENED(u->sink->thread_info.state))
         return;
 
     pa_sink_detach_within_thread(u->sink);
@@ -290,7 +290,7 @@ static void sink_input_attach_cb(pa_sink_input *i) {
     pa_sink_input_assert_ref(i);
     pa_assert_se(u = i->userdata);
 
-    if (!u->sink)
+    if (!u->sink || !PA_SINK_IS_OPENED(u->sink->thread_info.state))
         return;
 
     pa_sink_set_asyncmsgq(u->sink, i->sink->asyncmsgq);
@@ -309,10 +309,10 @@ static void sink_input_kill_cb(pa_sink_input *i) {
     pa_assert_se(u = i->userdata);
 
     pa_sink_unlink(u->sink);
+    pa_sink_input_unlink(u->sink_input);
+
     pa_sink_unref(u->sink);
     u->sink = NULL;
-
-    pa_sink_input_unlink(u->sink_input);
     pa_sink_input_unref(u->sink_input);
     u->sink_input = NULL;
 
diff --git a/src/modules/module-remap-sink.c b/src/modules/module-remap-sink.c
index 985afbc..0b9825e 100644
--- a/src/modules/module-remap-sink.c
+++ b/src/modules/module-remap-sink.c
@@ -143,7 +143,7 @@ static int sink_input_pop_cb(pa_sink_input *i, size_t nbytes, pa_memchunk *chunk
     pa_assert(chunk);
     pa_assert_se(u = i->userdata);
 
-    if (!u->sink)
+    if (!u->sink || !PA_SINK_IS_OPENED(u->sink->thread_info.state))
         return -1;
 
     pa_sink_render(u->sink, nbytes, chunk);
@@ -158,7 +158,7 @@ static void sink_input_process_rewind_cb(pa_sink_input *i, size_t nbytes) {
     pa_assert_se(u = i->userdata);
     pa_assert(nbytes > 0);
 
-    if (!u->sink)
+    if (!u->sink || !PA_SINK_IS_OPENED(u->sink->thread_info.state))
         return;
 
     if (u->sink->thread_info.rewind_nbytes > 0) {
@@ -179,7 +179,7 @@ static void sink_input_update_max_rewind_cb(pa_sink_input *i, size_t nbytes) {
     pa_sink_input_assert_ref(i);
     pa_assert_se(u = i->userdata);
 
-    if (!u->sink)
+    if (!u->sink || !PA_SINK_IS_OPENED(u->sink->thread_info.state))
         return;
 
     pa_sink_set_max_rewind(u->sink, nbytes);
@@ -192,7 +192,7 @@ static void sink_input_detach_cb(pa_sink_input *i) {
     pa_sink_input_assert_ref(i);
     pa_assert_se(u = i->userdata);
 
-    if (!u->sink)
+    if (!u->sink || !PA_SINK_IS_OPENED(u->sink->thread_info.state))
         return;
 
     pa_sink_detach_within_thread(u->sink);
@@ -207,7 +207,7 @@ static void sink_input_attach_cb(pa_sink_input *i) {
     pa_sink_input_assert_ref(i);
     pa_assert_se(u = i->userdata);
 
-    if (!u->sink)
+    if (!u->sink || !PA_SINK_IS_OPENED(u->sink->thread_info.state))
         return;
 
     pa_sink_set_asyncmsgq(u->sink, i->sink->asyncmsgq);
@@ -226,10 +226,10 @@ static void sink_input_kill_cb(pa_sink_input *i) {
     pa_assert_se(u = i->userdata);
 
     pa_sink_unlink(u->sink);
+    pa_sink_input_unlink(u->sink_input);
+
     pa_sink_unref(u->sink);
     u->sink = NULL;
-
-    pa_sink_input_unlink(u->sink_input);
     pa_sink_input_unref(u->sink_input);
     u->sink_input = NULL;
 

commit 21fa1cf857069a507b07d568248aabe98157e43e
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed May 7 21:09:49 2008 +0000

    double default asyncq size
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2386 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/asyncq.c b/src/pulsecore/asyncq.c
index 34506e4..91f0e50 100644
--- a/src/pulsecore/asyncq.c
+++ b/src/pulsecore/asyncq.c
@@ -40,7 +40,7 @@
 #include "asyncq.h"
 #include "fdsem.h"
 
-#define ASYNCQ_SIZE 128
+#define ASYNCQ_SIZE 256
 
 /* For debugging purposes we can define _Y to put and extra thread
  * yield between each operation. */
@@ -73,10 +73,6 @@ PA_STATIC_FLIST_DECLARE(localq, 0, pa_xfree);
 
 #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);
 }
@@ -87,7 +83,7 @@ pa_asyncq *pa_asyncq_new(unsigned size) {
     if (!size)
         size = ASYNCQ_SIZE;
 
-    pa_assert(is_power_of_two(size));
+    pa_assert(pa_is_power_of_two(size));
 
     l = pa_xmalloc0(PA_ALIGN(sizeof(pa_asyncq)) + (sizeof(pa_atomic_ptr_t) * size));
 

commit 7b5c6a34e21a5dffe4da17cee471b10bb1c6010d
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed May 7 21:10:19 2008 +0000

    fix recording
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2387 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulse/stream.c b/src/pulse/stream.c
index 297e9d7..3b1975f 100644
--- a/src/pulse/stream.c
+++ b/src/pulse/stream.c
@@ -1263,7 +1263,8 @@ static void stream_get_timing_info_callback(pa_pdispatch *pd, uint32_t command,
             goto finish;
         }
 
-        if (o->context->version >= 13)
+        if (o->context->version >= 13 &&
+            o->stream->direction == PA_STREAM_PLAYBACK)
             if (pa_tagstruct_getu64(t, &underrun_for) < 0 ||
                 pa_tagstruct_getu64(t, &playing_for) < 0) {
 

commit 1f196e79884618d948927c20ddfcd81ae24ad18c
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu May 8 01:08:33 2008 +0000

    fix some comments
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2388 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/asyncq.c b/src/pulsecore/asyncq.c
index 91f0e50..8e0dfbc 100644
--- a/src/pulsecore/asyncq.c
+++ b/src/pulsecore/asyncq.c
@@ -3,7 +3,7 @@
 /***
   This file is part of PulseAudio.
 
-  Copyright 2006 Lennart Poettering
+  Copyright 2006-2008 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
@@ -42,7 +42,7 @@
 
 #define ASYNCQ_SIZE 256
 
-/* For debugging purposes we can define _Y to put and extra thread
+/* For debugging purposes we can define _Y to put an extra thread
  * yield between each operation. */
 
 /* #define PROFILE */

commit e97a347325051e3e606b1d4395ba1975f0de838f
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri May 9 22:11:57 2008 +0000

    bah, english sucks
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2389 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulse/def.h b/src/pulse/def.h
index 1a0b9cb..1072232 100644
--- a/src/pulse/def.h
+++ b/src/pulse/def.h
@@ -238,6 +238,10 @@ typedef enum pa_stream_flags {
                                       * accordingly. \since 0.9.11 */
 } pa_stream_flags_t;
 
+
+/** English is an evil language \since 0.9.11 */
+#define PA_STREAM_NOT_MONOTONIC PA_STREAM_NOT_MONOTONOUS
+
 /** Playback and record buffer metrics */
 typedef struct pa_buffer_attr {
     uint32_t maxlength;      /**< Maximum length of the

commit 0ea0e0694ecd5e8b626b8e8414d5c8f7107233a3
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri May 9 22:27:44 2008 +0000

    make sure the smoother code can deal with incoming data that is out-of-order; start smoothing only when we have at least a configurable number of entries in our history
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2390 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/time-smoother.c b/src/pulsecore/time-smoother.c
index 97e32b7..9b4be29 100644
--- a/src/pulsecore/time-smoother.c
+++ b/src/pulsecore/time-smoother.c
@@ -69,13 +69,14 @@ struct pa_smoother {
 
     pa_usec_t ex, ey;     /* Point e, which we estimated before and need to smooth to */
     double de;            /* Gradient we estimated for point e */
+    pa_usec_t ry;         /* The original y value for ex */
 
                           /* 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;
+    pa_usec_t last_y, last_x;
 
     /* Cached parameters for our interpolation polynomial y=ax^3+b^2+cx */
     double a, b, c;
@@ -85,13 +86,17 @@ struct pa_smoother {
     pa_bool_t paused:1;
 
     pa_usec_t pause_time;
+
+    unsigned min_history;
 };
 
-pa_smoother* pa_smoother_new(pa_usec_t adjust_time, pa_usec_t history_time, pa_bool_t monotonic) {
+pa_smoother* pa_smoother_new(pa_usec_t adjust_time, pa_usec_t history_time, pa_bool_t monotonic, unsigned min_history) {
     pa_smoother *s;
 
     pa_assert(adjust_time > 0);
     pa_assert(history_time > 0);
+    pa_assert(min_history >= 2);
+    pa_assert(min_history <= HISTORY_MAX);
 
     s = pa_xnew(pa_smoother, 1);
     s->adjust_time = adjust_time;
@@ -102,18 +107,20 @@ pa_smoother* pa_smoother_new(pa_usec_t adjust_time, pa_usec_t history_time, pa_b
     s->px = s->py = 0;
     s->dp = 1;
 
-    s->ex = s->ey = 0;
+    s->ex = s->ey = s->ry = 0;
     s->de = 1;
 
     s->history_idx = 0;
     s->n_history = 0;
 
-    s->last_y = 0;
+    s->last_y = s->last_x = 0;
 
     s->abc_valid = FALSE;
 
     s->paused = FALSE;
 
+    s->min_history = min_history;
+
     return s;
 }
 
@@ -137,9 +144,9 @@ void pa_smoother_free(pa_smoother* s) {
 static void drop_old(pa_smoother *s, pa_usec_t x) {
 
     /* Drop items from history which are too old, but make sure to
-     * always keep two entries in the history */
+     * always keep min_history in the history */
 
-    while (s->n_history > 2) {
+    while (s->n_history > s->min_history) {
 
         if (s->history_x[s->history_idx] + s->history_time >= x)
             /* This item is still valid, and thus all following ones
@@ -184,7 +191,7 @@ static void add_to_history(pa_smoother *s, pa_usec_t x, pa_usec_t y) {
     s->n_history ++;
 
     /* And make sure we don't store more entries than fit in */
-    if (s->n_history >= HISTORY_MAX) {
+    if (s->n_history > HISTORY_MAX) {
         s->history_idx += s->n_history - HISTORY_MAX;
         REDUCE(s->history_idx);
         s->n_history = HISTORY_MAX;
@@ -196,7 +203,9 @@ static double avg_gradient(pa_smoother *s, pa_usec_t x) {
     int64_t ax = 0, ay = 0, k, t;
     double r;
 
-    drop_old(s, x);
+    /* Too few measurements, assume gradient of 1 */
+    if (s->n_history < s->min_history)
+        return 1;
 
     /* First, calculate average of all measurements */
     i = s->history_idx;
@@ -209,10 +218,7 @@ static double avg_gradient(pa_smoother *s, pa_usec_t x) {
         REDUCE_INC(i);
     }
 
-    /* Too few measurements, assume gradient of 1 */
-    if (c < 2)
-        return 1;
-
+    pa_assert(c >= s->min_history);
     ax /= c;
     ay /= c;
 
@@ -237,6 +243,39 @@ static double avg_gradient(pa_smoother *s, pa_usec_t x) {
     return (s->monotonic && r < 0) ? 0 : r;
 }
 
+static void calc_abc(pa_smoother *s) {
+    pa_usec_t ex, ey, px, py;
+    int64_t kx, ky;
+    double de, dp;
+
+    pa_assert(s);
+
+    if (s->abc_valid)
+        return;
+
+    /* 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+bx^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;
+}
+
 static void estimate(pa_smoother *s, pa_usec_t x, pa_usec_t *y, double *deriv) {
     pa_assert(s);
     pa_assert(y);
@@ -259,36 +298,10 @@ static void estimate(pa_smoother *s, pa_usec_t x, pa_usec_t *y, double *deriv) {
 
     } 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 */
 
-            /* 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;
-        }
+        calc_abc(s);
 
         /* Move to origin */
         x -= s->ex;
@@ -307,11 +320,6 @@ static void estimate(pa_smoother *s, pa_usec_t x, pa_usec_t *y, double *deriv) {
     /* 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;
     }
@@ -320,6 +328,7 @@ static void estimate(pa_smoother *s, pa_usec_t x, pa_usec_t *y, double *deriv) {
 void pa_smoother_put(pa_smoother *s, pa_usec_t x, pa_usec_t y) {
     pa_usec_t ney;
     double nde;
+    pa_bool_t is_new;
 
     pa_assert(s);
 
@@ -329,12 +338,16 @@ void pa_smoother_put(pa_smoother *s, pa_usec_t x, pa_usec_t y) {
 
     x = PA_LIKELY(x >= s->time_offset) ? x - s->time_offset : 0;
 
-    pa_assert(x >= s->ex);
+    is_new = 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;
+    if (is_new) {
+        /* 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;
+
+        s->ry = y;
+    }
 
     /* Then, we add the new measurement to our history */
     add_to_history(s, x, y);
@@ -343,8 +356,8 @@ void pa_smoother_put(pa_smoother *s, pa_usec_t x, pa_usec_t y) {
     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->px = s->ex + s->adjust_time;
+    s->py = s->ry + s->dp *s->adjust_time;
 
     s->abc_valid = FALSE;
 
@@ -361,10 +374,21 @@ pa_usec_t pa_smoother_get(pa_smoother *s, pa_usec_t x) {
         x = s->pause_time;
 
     x = PA_LIKELY(x >= s->time_offset) ? x - s->time_offset : 0;
-    pa_assert(x >= s->ex);
 
     estimate(s, x, &y, NULL);
 
+    if (s->monotonic) {
+
+        /* Make sure the querier doesn't jump forth and back. */
+        pa_assert(x >= s->last_x);
+        s->last_x = x;
+
+        if (y < s->last_y)
+            y = s->last_y;
+        else
+            s->last_y = y;
+    }
+
 /*     pa_log_debug("get(%llu | %llu) = %llu", (unsigned long long) (x + s->time_offset), (unsigned long long) x, (unsigned long long) y); */
 
     return y;
@@ -416,11 +440,14 @@ pa_usec_t pa_smoother_translate(pa_smoother *s, pa_usec_t x, pa_usec_t y_delay)
 
     x = PA_LIKELY(x >= s->time_offset) ? x - s->time_offset : 0;
 
-    pa_assert(x >= s->ex);
-
     estimate(s, x, &ney, &nde);
 
-/*     pa_log_debug("translate(%llu) = %llu (%0.2f)", (unsigned long long) y_delay, (unsigned long long) ((double) y_delay / s->dp), s->dp); */
+    /* Play safe and take the larger gradient, so that we wakeup
+     * earlier when this is used for sleeping */
+    if (s->dp > nde)
+        nde = s->dp;
+
+/*     pa_log_debug("translate(%llu) = %llu (%0.2f)", (unsigned long long) y_delay, (unsigned long long) ((double) y_delay / nde), nde); */
 
-    return (pa_usec_t) ((double) y_delay / s->dp);
+    return (pa_usec_t) ((double) y_delay / nde);
 }
diff --git a/src/pulsecore/time-smoother.h b/src/pulsecore/time-smoother.h
index 85d9f0f..b301b48 100644
--- a/src/pulsecore/time-smoother.h
+++ b/src/pulsecore/time-smoother.h
@@ -29,7 +29,7 @@
 
 typedef struct pa_smoother pa_smoother;
 
-pa_smoother* pa_smoother_new(pa_usec_t x_adjust_time, pa_usec_t x_history_time, pa_bool_t monotonic);
+pa_smoother* pa_smoother_new(pa_usec_t x_adjust_time, pa_usec_t x_history_time, pa_bool_t monotonic, unsigned min_history);
 void pa_smoother_free(pa_smoother* s);
 
 /* Adds a new value to our dataset. x = local/system time, y = remote time */

commit 580d56358d9d15792613fc4be886c71059c58a36
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri May 9 22:28:38 2008 +0000

    modify test to generate data events out-of-order
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2391 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/tests/smoother-test.c b/src/tests/smoother-test.c
index 0816e76..de03772 100644
--- a/src/tests/smoother-test.c
+++ b/src/tests/smoother-test.c
@@ -47,25 +47,25 @@ int main(int argc, char*argv[]) {
 
     srand(0);
 
-    for (m = 0, u = 0; u < PA_ELEMENTSOF(msec)-2; u+= 2) {
+    for (m = 0, u = 0; u < PA_ELEMENTSOF(msec); u+= 2) {
 
-        msec[u] = m+1;
-        msec[u+1] = m + rand() % 2000 - 1000;
+        msec[u] = m+1 + (rand() % 100) - 50;
+        msec[u+1] = m + (rand() % 2000) - 1000;
 
         m += rand() % 100;
 
+        if (msec[u] < 0)
+            msec[u] = 0;
+
         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);
+    s = pa_smoother_new(700*PA_USEC_PER_MSEC, 2000*PA_USEC_PER_MSEC, TRUE, 6);
 
     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) {
+        while (u < PA_ELEMENTSOF(msec) && (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;

commit df92b23fa6e520127309c2f63e1f22c7d222e734
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri May 9 22:48:37 2008 +0000

    - Fix moving of sink inputs between sinks
    - Don't write more than a single buffer size in the ALSA driver at a time, to give the clients time to fill up the memblockq again
    - Add API for querying the requested latency of a sink input/source output
    - Drop get_letancy() from vtable of sinks/sources
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2392 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-alsa-sink.c b/src/modules/module-alsa-sink.c
index 4a997cd..97e1e59 100644
--- a/src/modules/module-alsa-sink.c
+++ b/src/modules/module-alsa-sink.c
@@ -131,6 +131,7 @@ struct userdata {
 
     pa_smoother *smoother;
     int64_t frame_index;
+    uint64_t since_start;
 
     snd_pcm_sframes_t hwbuf_unused_frames;
 };
@@ -162,6 +163,32 @@ static void fix_tsched_watermark(struct userdata *u) {
         u->tsched_watermark = min_wakeup;
 }
 
+static void hw_sleep_time(struct userdata *u, pa_usec_t *sleep_usec, pa_usec_t*process_usec) {
+    pa_usec_t usec, wm;
+
+    pa_assert(sleep_usec);
+    pa_assert(process_usec);
+
+    pa_assert(u);
+
+    usec = pa_sink_get_requested_latency_within_thread(u->sink);
+
+    if (usec == (pa_usec_t) -1)
+        usec = pa_bytes_to_usec(u->hwbuf_size, &u->sink->sample_spec);
+
+/*     pa_log_debug("hw buffer time: %u ms", (unsigned) (usec / PA_USEC_PER_MSEC)); */
+
+    wm = pa_bytes_to_usec(u->tsched_watermark, &u->sink->sample_spec);
+
+    if (usec >= wm) {
+        *sleep_usec = usec - wm;
+        *process_usec = wm;
+    } else
+        *process_usec = *sleep_usec = usec / 2;
+
+/*     pa_log_debug("after watermark: %u ms", (unsigned) (*sleep_usec / PA_USEC_PER_MSEC)); */
+}
+
 static int try_recover(struct userdata *u, const char *call, int err) {
     pa_assert(u);
     pa_assert(call);
@@ -169,16 +196,14 @@ static int try_recover(struct userdata *u, const char *call, int err) {
 
     pa_log_debug("%s: %s", call, snd_strerror(err));
 
-    if (err == -EAGAIN) {
-        pa_log_debug("%s: EAGAIN", call);
-        return 1;
-    }
+    pa_assert(err != -EAGAIN);
 
     if (err == -EPIPE)
         pa_log_debug("%s: Buffer underrun!", call);
 
     if ((err = snd_pcm_recover(u->pcm_handle, err, 1)) == 0) {
         u->first = TRUE;
+        u->since_start = 0;
         return 0;
     }
 
@@ -186,20 +211,17 @@ static int try_recover(struct userdata *u, const char *call, int err) {
     return -1;
 }
 
-static void check_left_to_play(struct userdata *u, snd_pcm_sframes_t n) {
+static size_t check_left_to_play(struct userdata *u, snd_pcm_sframes_t n) {
     size_t left_to_play;
 
-    if (u->first || u->after_rewind)
-        return;
-
     if (n*u->frame_size < u->hwbuf_size)
         left_to_play = u->hwbuf_size - (n*u->frame_size);
     else
         left_to_play = 0;
 
-    if (left_to_play > 0)
-        pa_log_debug("%0.2f ms left to play", (double) pa_bytes_to_usec(left_to_play, &u->sink->sample_spec) / PA_USEC_PER_MSEC);
-    else {
+    if (left_to_play > 0) {
+/*         pa_log_debug("%0.2f ms left to play", (double) pa_bytes_to_usec(left_to_play, &u->sink->sample_spec) / PA_USEC_PER_MSEC); */
+    } else if (!u->first && !u->after_rewind) {
         pa_log_info("Underrun!");
 
         if (u->use_tsched) {
@@ -213,22 +235,24 @@ static void check_left_to_play(struct userdata *u, snd_pcm_sframes_t n) {
                               (double) pa_bytes_to_usec(u->tsched_watermark, &u->sink->sample_spec) / PA_USEC_PER_MSEC);
         }
     }
+
+    return left_to_play;
 }
 
-static int mmap_write(struct userdata *u) {
+static int mmap_write(struct userdata *u, pa_usec_t *sleep_usec) {
     int work_done = 0;
-    pa_bool_t checked_left_to_play = FALSE;
+    pa_usec_t max_sleep_usec, process_usec;
+    size_t left_to_play;
 
     pa_assert(u);
     pa_sink_assert_ref(u->sink);
 
+    if (u->use_tsched)
+        hw_sleep_time(u, &max_sleep_usec, &process_usec);
+
     for (;;) {
-        pa_memchunk chunk;
-        void *p;
         snd_pcm_sframes_t n;
-        int err, r;
-        const snd_pcm_channel_area_t *areas;
-        snd_pcm_uframes_t offset, frames;
+        int r;
 
         snd_pcm_hwsync(u->pcm_handle);
 
@@ -239,92 +263,110 @@ static int mmap_write(struct userdata *u) {
 
             if ((r = try_recover(u, "snd_pcm_avail_update", n)) == 0)
                 continue;
-            else if (r > 0)
-                return work_done;
 
             return r;
         }
 
-        if (!checked_left_to_play) {
-            check_left_to_play(u, n);
-            checked_left_to_play = TRUE;
-        }
+        left_to_play = check_left_to_play(u, n);
+
+        if (u->use_tsched)
+
+            /* We won't fill up the playback buffer before at least
+            * half the sleep time is over because otherwise we might
+            * ask for more data from the clients then they expect. We
+            * need to guarantee that clients only have to keep around
+            * a single hw buffer length. */
 
-        /* We only use part of the buffer that matches our
-         * dynamically requested latency */
+            if (pa_bytes_to_usec(left_to_play, &u->sink->sample_spec) > max_sleep_usec/2)
+                break;
 
         if (PA_UNLIKELY(n <= u->hwbuf_unused_frames))
-            return work_done;
+            break;
 
-        frames = n = n - u->hwbuf_unused_frames;
+        n -= u->hwbuf_unused_frames;
 
-/*        pa_log_debug("%lu frames to write", (unsigned long) frames);*/
+/*         pa_log_debug("Filling up"); */
 
-        if (PA_UNLIKELY((err = snd_pcm_mmap_begin(u->pcm_handle, &areas, &offset, &frames)) < 0)) {
+        for (;;) {
+            pa_memchunk chunk;
+            void *p;
+            int err;
+            const snd_pcm_channel_area_t *areas;
+            snd_pcm_uframes_t offset, frames = (snd_pcm_uframes_t) n;
 
-            if ((r = try_recover(u, "snd_pcm_mmap_begin", err)) == 0)
-                continue;
-            else if (r > 0)
-                return work_done;
+/*             pa_log_debug("%lu frames to write", (unsigned long) frames); */
 
-            return r;
-        }
+            if (PA_UNLIKELY((err = snd_pcm_mmap_begin(u->pcm_handle, &areas, &offset, &frames)) < 0)) {
 
-        /* Make sure that if these memblocks need to be copied they will fit into one slot */
-        if (frames > pa_mempool_block_size_max(u->sink->core->mempool)/u->frame_size)
-            frames = pa_mempool_block_size_max(u->sink->core->mempool)/u->frame_size;
+                if ((r = try_recover(u, "snd_pcm_mmap_begin", err)) == 0)
+                    continue;
 
-        /* Check these are multiples of 8 bit */
-        pa_assert((areas[0].first & 7) == 0);
-        pa_assert((areas[0].step & 7)== 0);
+                return r;
+            }
 
-        /* We assume a single interleaved memory buffer */
-        pa_assert((areas[0].first >> 3) == 0);
-        pa_assert((areas[0].step >> 3) == u->frame_size);
+            /* Make sure that if these memblocks need to be copied they will fit into one slot */
+            if (frames > pa_mempool_block_size_max(u->sink->core->mempool)/u->frame_size)
+                frames = pa_mempool_block_size_max(u->sink->core->mempool)/u->frame_size;
 
-        p = (uint8_t*) areas[0].addr + (offset * u->frame_size);
+            /* Check these are multiples of 8 bit */
+            pa_assert((areas[0].first & 7) == 0);
+            pa_assert((areas[0].step & 7)== 0);
 
-        chunk.memblock = pa_memblock_new_fixed(u->core->mempool, p, frames * u->frame_size, TRUE);
-        chunk.length = pa_memblock_get_length(chunk.memblock);
-        chunk.index = 0;
+            /* We assume a single interleaved memory buffer */
+            pa_assert((areas[0].first >> 3) == 0);
+            pa_assert((areas[0].step >> 3) == u->frame_size);
 
-        pa_sink_render_into_full(u->sink, &chunk);
+            p = (uint8_t*) areas[0].addr + (offset * u->frame_size);
 
-        /* FIXME: Maybe we can do something to keep this memory block
-         * a little bit longer around? */
-        pa_memblock_unref_fixed(chunk.memblock);
+            chunk.memblock = pa_memblock_new_fixed(u->core->mempool, p, frames * u->frame_size, TRUE);
+            chunk.length = pa_memblock_get_length(chunk.memblock);
+            chunk.index = 0;
 
-        if (PA_UNLIKELY((err = snd_pcm_mmap_commit(u->pcm_handle, offset, frames)) < 0)) {
+            pa_sink_render_into_full(u->sink, &chunk);
 
-            if ((r = try_recover(u, "snd_pcm_mmap_commit", err)) == 0)
-                continue;
-            else if (r > 0)
-                return work_done;
+            /* FIXME: Maybe we can do something to keep this memory block
+             * a little bit longer around? */
+            pa_memblock_unref_fixed(chunk.memblock);
 
-            return r;
-        }
+            if (PA_UNLIKELY((err = snd_pcm_mmap_commit(u->pcm_handle, offset, frames)) < 0)) {
 
-        work_done = 1;
+                if ((r = try_recover(u, "snd_pcm_mmap_commit", err)) == 0)
+                    continue;
 
-        u->frame_index += frames;
+                return r;
+            }
 
-/*         pa_log_debug("wrote %lu frames", (unsigned long) frames); */
+            work_done = 1;
+
+            u->frame_index += frames;
+            u->since_start += frames * u->frame_size;
+
+/*             pa_log_debug("wrote %lu frames", (unsigned long) frames); */
 
-        if (PA_LIKELY(frames >= (snd_pcm_uframes_t) n))
-            return work_done;
+            if (frames >= (snd_pcm_uframes_t) n)
+                break;
+
+            n -= frames;
+        }
     }
+
+    *sleep_usec = pa_bytes_to_usec(left_to_play, &u->sink->sample_spec) - process_usec;
+    return work_done;
 }
 
-static int unix_write(struct userdata *u) {
+static int unix_write(struct userdata *u, pa_usec_t *sleep_usec) {
     int work_done = 0;
-    pa_bool_t checked_left_to_play = FALSE;
+    pa_usec_t max_sleep_usec, process_usec;
+    size_t left_to_play;
 
     pa_assert(u);
     pa_sink_assert_ref(u->sink);
 
+    if (u->use_tsched)
+        hw_sleep_time(u, &max_sleep_usec, &process_usec);
+
     for (;;) {
-        void *p;
-        snd_pcm_sframes_t n, frames;
+        snd_pcm_sframes_t n;
         int r;
 
         snd_pcm_hwsync(u->pcm_handle);
@@ -333,67 +375,82 @@ static int unix_write(struct userdata *u) {
 
             if ((r = try_recover(u, "snd_pcm_avail_update", n)) == 0)
                 continue;
-            else if (r > 0)
-                return work_done;
 
             return r;
         }
 
-        if (!checked_left_to_play) {
-            check_left_to_play(u, n);
-            checked_left_to_play = TRUE;
-        }
+        left_to_play = check_left_to_play(u, n);
+
+        if (u->use_tsched)
+
+            /* We won't fill up the playback buffer before at least
+            * half the sleep time is over because otherwise we might
+            * ask for more data from the clients then they expect. We
+            * need to guarantee that clients only have to keep around
+            * a single hw buffer length. */
+
+            if (pa_bytes_to_usec(left_to_play, &u->sink->sample_spec) > max_sleep_usec/2)
+                break;
 
         if (PA_UNLIKELY(n <= u->hwbuf_unused_frames))
-            return work_done;
+            break;
 
         n -= u->hwbuf_unused_frames;
 
+        for (;;) {
+            snd_pcm_sframes_t frames;
+            void *p;
+
 /*         pa_log_debug("%lu frames to write", (unsigned long) frames); */
 
-        if (u->memchunk.length <= 0)
-            pa_sink_render(u->sink, n * u->frame_size, &u->memchunk);
+            if (u->memchunk.length <= 0)
+                pa_sink_render(u->sink, n * u->frame_size, &u->memchunk);
 
-        pa_assert(u->memchunk.length > 0);
+            pa_assert(u->memchunk.length > 0);
 
-        frames = u->memchunk.length / u->frame_size;
+            frames = u->memchunk.length / u->frame_size;
 
-        if (frames > n)
-            frames = n;
+            if (frames > n)
+                frames = n;
 
-        p = pa_memblock_acquire(u->memchunk.memblock);
-        frames = snd_pcm_writei(u->pcm_handle, (const uint8_t*) p + u->memchunk.index, frames);
-        pa_memblock_release(u->memchunk.memblock);
+            p = pa_memblock_acquire(u->memchunk.memblock);
+            frames = snd_pcm_writei(u->pcm_handle, (const uint8_t*) p + u->memchunk.index, frames);
+            pa_memblock_release(u->memchunk.memblock);
 
-        pa_assert(frames != 0);
+            pa_assert(frames != 0);
 
-        if (PA_UNLIKELY(frames < 0)) {
+            if (PA_UNLIKELY(frames < 0)) {
 
-            if ((r = try_recover(u, "snd_pcm_writei", n)) == 0)
-                continue;
-            else if (r > 0)
-                return work_done;
+                if ((r = try_recover(u, "snd_pcm_writei", n)) == 0)
+                    continue;
 
-            return r;
-        }
+                return r;
+            }
 
-        u->memchunk.index += frames * u->frame_size;
-        u->memchunk.length -= frames * u->frame_size;
+            u->memchunk.index += frames * u->frame_size;
+            u->memchunk.length -= frames * u->frame_size;
 
-        if (u->memchunk.length <= 0) {
-            pa_memblock_unref(u->memchunk.memblock);
-            pa_memchunk_reset(&u->memchunk);
-        }
+            if (u->memchunk.length <= 0) {
+                pa_memblock_unref(u->memchunk.memblock);
+                pa_memchunk_reset(&u->memchunk);
+            }
 
-        work_done = 1;
+            work_done = 1;
 
-        u->frame_index += frames;
+            u->frame_index += frames;
+            u->since_start += frames * u->frame_size;
 
 /*         pa_log_debug("wrote %lu frames", (unsigned long) frames); */
 
-        if (PA_LIKELY(frames >= n))
-            return work_done;
+            if (frames >= n)
+                break;
+
+            n -= frames;
+        }
     }
+
+    *sleep_usec = pa_bytes_to_usec(left_to_play, &u->sink->sample_spec) - process_usec;
+    return work_done;
 }
 
 static void update_smoother(struct userdata *u) {
@@ -494,35 +551,6 @@ static int suspend(struct userdata *u) {
     return 0;
 }
 
-static pa_usec_t hw_sleep_time(struct userdata *u) {
-    pa_usec_t usec, wm;
-
-    pa_assert(u);
-
-    usec = pa_sink_get_requested_latency_within_thread(u->sink);
-
-    if (usec == (pa_usec_t) -1)
-        usec = pa_bytes_to_usec(u->hwbuf_size, &u->sink->sample_spec);
-
-    pa_log_debug("hw buffer time: %u ms", (unsigned) (usec / PA_USEC_PER_MSEC));
-
-    wm = pa_bytes_to_usec(u->tsched_watermark, &u->sink->sample_spec);
-
-    if (usec >= wm)
-        usec -= wm;
-    else
-        usec /= 2;
-
-    if (u->first) {
-        pa_log_debug("Decreasing wakeup time for the first iteration by half.");
-        usec /= 2;
-    }
-
-    pa_log_debug("after watermark: %u ms", (unsigned) (usec / PA_USEC_PER_MSEC));
-
-    return usec;
-}
-
 static int update_sw_params(struct userdata *u) {
     snd_pcm_uframes_t avail_min;
     int err;
@@ -561,10 +589,10 @@ static int update_sw_params(struct userdata *u) {
     avail_min = u->hwbuf_unused_frames + 1;
 
     if (u->use_tsched) {
-        pa_usec_t usec;
+        pa_usec_t sleep_usec, process_usec;
 
-        usec = hw_sleep_time(u);
-        avail_min += pa_usec_to_bytes(usec, &u->sink->sample_spec);
+        hw_sleep_time(u, &sleep_usec, &process_usec);
+        avail_min += pa_usec_to_bytes(sleep_usec, &u->sink->sample_spec);
     }
 
     pa_log_debug("setting avail_min=%lu", (unsigned long) avail_min);
@@ -630,6 +658,7 @@ static int unsuspend(struct userdata *u) {
     /* FIXME: We need to reload the volume somehow */
 
     u->first = TRUE;
+    u->since_start = 0;
 
     pa_log_info("Resumed successfully...");
 
@@ -932,16 +961,17 @@ static void thread_func(void *userdata) {
 
         /* Render some data and write it to the dsp */
         if (PA_SINK_IS_OPENED(u->sink->thread_info.state)) {
-            int work_done = 0;
+            int work_done;
+            pa_usec_t sleep_usec;
 
             if (u->sink->thread_info.rewind_nbytes > 0)
                 if (process_rewind(u) < 0)
                     goto fail;
 
             if (u->use_mmap)
-                work_done = mmap_write(u);
+                work_done = mmap_write(u, &sleep_usec);
             else
-                work_done = unix_write(u);
+                work_done = unix_write(u, &sleep_usec);
 
             if (work_done < 0)
                 goto fail;
@@ -961,23 +991,34 @@ static void thread_func(void *userdata) {
             }
 
             if (u->use_tsched) {
-                pa_usec_t usec, cusec;
+                pa_usec_t cusec;
 
-                /* OK, the playback buffer is now full, let's
-                 * calculate when to wake up next */
+                if (u->since_start <= u->hwbuf_size) {
+
+                    /* USB devices on ALSA seem to hit a buffer
+                     * underrun during the first iterations much
+                     * quicker then we calculate here, probably due to
+                     * the transport latency. To accomodate for that
+                     * we artificially decrease the sleep time until
+                     * we have filled the buffer at least once
+                     * completely.*/
 
-                usec = hw_sleep_time(u);
+                    pa_log_debug("Cutting sleep time for the initial iterations by half.");
+                    sleep_usec /= 2;
+                }
 
-/*                 pa_log_debug("Waking up in %0.2fms (sound card clock).", (double) usec / PA_USEC_PER_MSEC); */
+                /* OK, the playback buffer is now full, let's
+                 * calculate when to wake up next */
+/*                 pa_log_debug("Waking up in %0.2fms (sound card clock).", (double) sleep_usec / PA_USEC_PER_MSEC); */
 
                 /* Convert from the sound card time domain to the
                  * system time domain */
-                cusec = pa_smoother_translate(u->smoother, pa_rtclock_usec(), usec);
+                cusec = pa_smoother_translate(u->smoother, pa_rtclock_usec(), sleep_usec);
 
 /*                 pa_log_debug("Waking up in %0.2fms (system clock).", (double) cusec / PA_USEC_PER_MSEC); */
 
                 /* We don't trust the conversion, so we wake up whatever comes first */
-                pa_rtpoll_set_timer_relative(u->rtpoll, PA_MIN(usec, cusec));
+                pa_rtpoll_set_timer_relative(u->rtpoll, PA_MIN(sleep_usec, cusec));
             }
 
             u->first = FALSE;
@@ -1014,6 +1055,7 @@ static void thread_func(void *userdata) {
                     goto fail;
 
                 u->first = TRUE;
+                u->since_start = 0;
             }
 
             if (revents)
@@ -1115,12 +1157,13 @@ int pa__init(pa_module*m) {
     u->use_mmap = use_mmap;
     u->use_tsched = use_tsched;
     u->first = TRUE;
+    u->since_start = 0;
     u->after_rewind = FALSE;
     u->rtpoll = pa_rtpoll_new();
     pa_thread_mq_init(&u->thread_mq, m->core->mainloop, u->rtpoll);
     u->alsa_rtpoll_item = NULL;
 
-    u->smoother = pa_smoother_new(DEFAULT_TSCHED_BUFFER_USEC*2, DEFAULT_TSCHED_BUFFER_USEC*2, TRUE);
+    u->smoother = pa_smoother_new(DEFAULT_TSCHED_BUFFER_USEC*2, DEFAULT_TSCHED_BUFFER_USEC*2, TRUE, 5);
     usec = pa_rtclock_usec();
     pa_smoother_set_time_offset(u->smoother, usec);
     pa_smoother_pause(u->smoother, usec);
diff --git a/src/modules/module-alsa-source.c b/src/modules/module-alsa-source.c
index 9eb6f06..4838ad2 100644
--- a/src/modules/module-alsa-source.c
+++ b/src/modules/module-alsa-source.c
@@ -988,7 +988,7 @@ int pa__init(pa_module*m) {
     pa_thread_mq_init(&u->thread_mq, m->core->mainloop, u->rtpoll);
     u->alsa_rtpoll_item = NULL;
 
-    u->smoother = pa_smoother_new(DEFAULT_TSCHED_WATERMARK_USEC, DEFAULT_TSCHED_WATERMARK_USEC, TRUE);
+    u->smoother = pa_smoother_new(DEFAULT_TSCHED_WATERMARK_USEC, DEFAULT_TSCHED_WATERMARK_USEC, TRUE, 5);
     pa_smoother_set_time_offset(u->smoother, pa_rtclock_usec());
 
     snd_config_update_free_global();
diff --git a/src/modules/module-combine.c b/src/modules/module-combine.c
index 2409ef8..fc8be18 100644
--- a/src/modules/module-combine.c
+++ b/src/modules/module-combine.c
@@ -618,35 +618,35 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
 }
 
 /* Called from main context */
-static pa_usec_t sink_get_latency_cb(pa_sink *s) {
-    struct userdata *u;
+/* 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);
+/*     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) { */
+/*         /\* 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;
+/*         if (!u->master->sink_input) */
+/*             return 0; */
 
-        return
-            pa_sink_input_get_latency(u->master->sink_input) +
-            pa_sink_get_latency(u->master->sink);
+/*         return */
+/*             pa_sink_input_get_latency(u->master->sink_input) + */
+/*             pa_sink_get_latency(u->master->sink); */
 
-    } else {
-        pa_usec_t usec = 0;
+/*     } else { */
+/*         pa_usec_t usec = 0; */
 
-        /* We have no master, hence let's ask our own thread which
-         * implements the NULL sink */
+/*         /\* 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;
+/*         if (pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_GET_LATENCY, &usec, 0, NULL) < 0) */
+/*             return 0; */
 
-        return usec;
-    }
-}
+/*         return usec; */
+/*     } */
+/* } */
 
 static void update_description(struct userdata *u) {
     int first = 1;
@@ -1025,7 +1025,7 @@ int pa__init(pa_module*m) {
     }
 
     u->sink->parent.process_msg = sink_process_msg;
-    u->sink->get_latency = sink_get_latency_cb;
+/*     u->sink->get_latency = sink_get_latency_cb; */
     u->sink->set_state = sink_set_state;
     u->sink->userdata = u;
 
diff --git a/src/modules/module-esound-sink.c b/src/modules/module-esound-sink.c
index 2206e2b..4aa7d67 100644
--- a/src/modules/module-esound-sink.c
+++ b/src/modules/module-esound-sink.c
@@ -534,7 +534,7 @@ int pa__init(pa_module*m) {
     u->module = m;
     m->userdata = u;
     u->fd = -1;
-    u->smoother = pa_smoother_new(PA_USEC_PER_SEC, PA_USEC_PER_SEC*2, TRUE);
+    u->smoother = pa_smoother_new(PA_USEC_PER_SEC, PA_USEC_PER_SEC*2, TRUE, 10);
     pa_memchunk_reset(&u->memchunk);
     u->offset = 0;
 
diff --git a/src/modules/module-rescue-streams.c b/src/modules/module-rescue-streams.c
index dda5473..7241a99 100644
--- a/src/modules/module-rescue-streams.c
+++ b/src/modules/module-rescue-streams.c
@@ -75,7 +75,7 @@ static pa_hook_result_t sink_hook_callback(pa_core *c, pa_sink *sink, void* user
     }
 
     while ((i = pa_idxset_first(sink->inputs, NULL))) {
-        if (pa_sink_input_move_to(i, target, 1) < 0) {
+        if (pa_sink_input_move_to(i, target) < 0) {
             pa_log_warn("Failed to move sink input %u \"%s\" to %s.", i->index, pa_proplist_gets(i->proplist, PA_PROP_APPLICATION_NAME), target->name);
             return PA_HOOK_OK;
         }
diff --git a/src/modules/module-tunnel.c b/src/modules/module-tunnel.c
index e3ae5e1..7a87fd8 100644
--- a/src/modules/module-tunnel.c
+++ b/src/modules/module-tunnel.c
@@ -577,29 +577,29 @@ static void timeout_callback(pa_mainloop_api *m, pa_time_event*e, PA_GCC_UNUSED
 }
 
 #ifdef TUNNEL_SINK
-static pa_usec_t sink_get_latency(pa_sink *s) {
-    pa_usec_t t, c;
-    struct userdata *u = s->userdata;
+/* static pa_usec_t sink_get_latency(pa_sink *s) { */
+/*     pa_usec_t t, c; */
+/*     struct userdata *u = s->userdata; */
 
-    pa_sink_assert_ref(s);
+/*     pa_sink_assert_ref(s); */
 
-    c = pa_bytes_to_usec(u->counter, &s->sample_spec);
-    t = pa_smoother_get(u->smoother, pa_rtclock_usec());
+/*     c = pa_bytes_to_usec(u->counter, &s->sample_spec); */
+/*     t = pa_smoother_get(u->smoother, pa_rtclock_usec()); */
 
-    return c > t ? c - t : 0;
-}
+/*     return c > t ? c - t : 0; */
+/* } */
 #else
-static pa_usec_t source_get_latency(pa_source *s) {
-    pa_usec_t t, c;
-    struct userdata *u = s->userdata;
+/* static pa_usec_t source_get_latency(pa_source *s) { */
+/*     pa_usec_t t, c; */
+/*     struct userdata *u = s->userdata; */
 
-    pa_source_assert_ref(s);
+/*     pa_source_assert_ref(s); */
 
-    c = pa_bytes_to_usec(u->counter, &s->sample_spec);
-    t = pa_smoother_get(u->smoother, pa_rtclock_usec());
+/*     c = pa_bytes_to_usec(u->counter, &s->sample_spec); */
+/*     t = pa_smoother_get(u->smoother, pa_rtclock_usec()); */
 
-    return t > c ? t - c : 0;
-}
+/*     return t > c ? t - c : 0; */
+/* } */
 #endif
 
 static void update_description(struct userdata *u) {
@@ -1323,7 +1323,7 @@ int pa__init(pa_module*m) {
     u->source_name = pa_xstrdup(pa_modargs_get_value(ma, "source", NULL));;
     u->source = NULL;
 #endif
-    u->smoother = pa_smoother_new(PA_USEC_PER_SEC, PA_USEC_PER_SEC*2, TRUE);
+    u->smoother = pa_smoother_new(PA_USEC_PER_SEC, PA_USEC_PER_SEC*2, TRUE, 10);
     u->ctag = 1;
     u->device_index = u->channel = PA_INVALID_INDEX;
     u->auth_cookie_in_property = FALSE;
@@ -1377,7 +1377,7 @@ int pa__init(pa_module*m) {
     u->sink->parent.process_msg = sink_process_msg;
     u->sink->userdata = u;
     u->sink->set_state = sink_set_state;
-    u->sink->get_latency = sink_get_latency;
+/*     u->sink->get_latency = sink_get_latency; */
     u->sink->get_volume = sink_get_volume;
     u->sink->get_mute = sink_get_mute;
     u->sink->set_volume = sink_set_volume;
@@ -1412,7 +1412,7 @@ int pa__init(pa_module*m) {
     u->source->parent.process_msg = source_process_msg;
     u->source->userdata = u;
     u->source->set_state = source_set_state;
-    u->source->get_latency = source_get_latency;
+/*     u->source->get_latency = source_get_latency; */
 
     pa_source_set_asyncmsgq(u->source, u->thread_mq.inq);
     pa_source_set_rtpoll(u->source, u->rtpoll);
diff --git a/src/pulse/stream.c b/src/pulse/stream.c
index 3b1975f..bd633cf 100644
--- a/src/pulse/stream.c
+++ b/src/pulse/stream.c
@@ -42,10 +42,11 @@
 
 #include "internal.h"
 
-#define LATENCY_IPOL_INTERVAL_USEC (500*PA_USEC_PER_MSEC)
+#define LATENCY_IPOL_INTERVAL_USEC (333*PA_USEC_PER_MSEC)
 
 #define SMOOTHER_ADJUST_TIME (1000*PA_USEC_PER_MSEC)
 #define SMOOTHER_HISTORY_TIME (5000*PA_USEC_PER_MSEC)
+#define SMOOTHER_MIN_HISTORY (4)
 
 pa_stream *pa_stream_new(pa_context *c, const char *name, const pa_sample_spec *ss, const pa_channel_map *map) {
     return pa_stream_new_with_proplist(c, name, ss, map, NULL);
@@ -344,6 +345,7 @@ void pa_command_stream_moved(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED u
     pa_bool_t suspended;
     uint32_t di;
     pa_usec_t usec;
+    uint32_t maxlength = 0, fragsize = 0, minreq = 0, tlength = 0, prebuf = 0;
 
     pa_assert(pd);
     pa_assert(command == PA_COMMAND_PLAYBACK_STREAM_MOVED || command == PA_COMMAND_RECORD_STREAM_MOVED);
@@ -367,14 +369,28 @@ void pa_command_stream_moved(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED u
     }
 
     if (c->version >= 13) {
-        if (pa_tagstruct_get_usec(t, &usec) < 0) {
-            pa_context_fail(s->context, PA_ERR_PROTOCOL);
-            goto finish;
+
+        if (s->direction == PA_STREAM_RECORD) {
+            if (pa_tagstruct_getu32(t, &maxlength) < 0 ||
+                pa_tagstruct_getu32(t, &fragsize) < 0 ||
+                pa_tagstruct_get_usec(t, &usec) < 0) {
+                pa_context_fail(c, PA_ERR_PROTOCOL);
+                goto finish;
+            }
+        } else {
+            if (pa_tagstruct_getu32(t, &maxlength) < 0 ||
+                pa_tagstruct_getu32(t, &tlength) < 0 ||
+                pa_tagstruct_getu32(t, &prebuf) < 0 ||
+                pa_tagstruct_getu32(t, &minreq) < 0 ||
+                pa_tagstruct_get_usec(t, &usec) < 0) {
+                pa_context_fail(c, PA_ERR_PROTOCOL);
+                goto finish;
+            }
         }
     }
 
     if (!pa_tagstruct_eof(t)) {
-        pa_context_fail(s->context, PA_ERR_PROTOCOL);
+        pa_context_fail(c, PA_ERR_PROTOCOL);
         goto finish;
     }
 
@@ -394,6 +410,12 @@ void pa_command_stream_moved(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED u
             s->timing_info.configured_source_usec = usec;
         else
             s->timing_info.configured_sink_usec = usec;
+
+        s->buffer_attr.maxlength = maxlength;
+        s->buffer_attr.fragsize = fragsize;
+        s->buffer_attr.tlength = tlength;
+        s->buffer_attr.prebuf = prebuf;
+        s->buffer_attr.minreq = minreq;
     }
 
     pa_xfree(s->device_name);
@@ -861,7 +883,7 @@ static int create_stream(
         if (s->smoother)
             pa_smoother_free(s->smoother);
 
-        s->smoother = pa_smoother_new(SMOOTHER_ADJUST_TIME, SMOOTHER_HISTORY_TIME, !(flags & PA_STREAM_NOT_MONOTONOUS));
+        s->smoother = pa_smoother_new(SMOOTHER_ADJUST_TIME, SMOOTHER_HISTORY_TIME, !(flags & PA_STREAM_NOT_MONOTONOUS), SMOOTHER_MIN_HISTORY);
 
         x = pa_rtclock_usec();
         pa_smoother_set_time_offset(s->smoother, x);
diff --git a/src/pulsecore/cli-command.c b/src/pulsecore/cli-command.c
index b6194f8..925a2e8 100644
--- a/src/pulsecore/cli-command.c
+++ b/src/pulsecore/cli-command.c
@@ -1055,7 +1055,7 @@ static int pa_cli_command_move_sink_input(pa_core *c, pa_tokenizer *t, pa_strbuf
         return -1;
     }
 
-    if (pa_sink_input_move_to(si, sink, 0) < 0) {
+    if (pa_sink_input_move_to(si, sink) < 0) {
         pa_strbuf_puts(buf, "Moved failed.\n");
         return -1;
     }
diff --git a/src/pulsecore/cli-text.c b/src/pulsecore/cli-text.c
index f251a14..029a708 100644
--- a/src/pulsecore/cli-text.c
+++ b/src/pulsecore/cli-text.c
@@ -253,7 +253,13 @@ char *pa_source_output_list_to_string(pa_core *c) {
     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], *t;
+        char ss[PA_SAMPLE_SPEC_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX], *t, clt[28];
+        pa_usec_t cl;
+
+        if ((cl = pa_source_output_get_requested_latency(o)) == (pa_usec_t) -1)
+            pa_snprintf(clt, sizeof(clt), "n/a");
+        else
+            pa_snprintf(clt, sizeof(clt), "%0.2f ms", (double) cl / PA_USEC_PER_MSEC);
 
         pa_assert(o->source);
 
@@ -264,7 +270,8 @@ char *pa_source_output_list_to_string(pa_core *c) {
             "\tflags: %s%s%s%s%s%s%s%s\n"
             "\tstate: %s\n"
             "\tsource: %u <%s>\n"
-            "\tlatency: %0.2f ms\n"
+            "\tcurrent latency: %0.2f ms\n"
+            "\trequested latency: %s\n"
             "\tsample spec: %s\n"
             "\tchannel map: %s\n"
             "\tresample method: %s\n",
@@ -281,6 +288,7 @@ char *pa_source_output_list_to_string(pa_core *c) {
             state_table[pa_source_output_get_state(o)],
             o->source->index, o->source->name,
             (double) pa_source_output_get_latency(o) / PA_USEC_PER_MSEC,
+            clt,
             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)));
@@ -315,7 +323,13 @@ char *pa_sink_input_list_to_string(pa_core *c) {
     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], *t;
+        char ss[PA_SAMPLE_SPEC_SNPRINT_MAX], cv[PA_CVOLUME_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX], *t, clt[28];
+        pa_usec_t cl;
+
+        if ((cl = pa_sink_input_get_requested_latency(i)) == (pa_usec_t) -1)
+            pa_snprintf(clt, sizeof(clt), "n/a");
+        else
+            pa_snprintf(clt, sizeof(clt), "%0.2f ms", (double) cl / PA_USEC_PER_MSEC);
 
         pa_assert(i->sink);
 
@@ -328,7 +342,8 @@ char *pa_sink_input_list_to_string(pa_core *c) {
             "\tsink: %u <%s>\n"
             "\tvolume: %s\n"
             "\tmuted: %s\n"
-            "\tlatency: %0.2f ms\n"
+            "\tcurrent latency: %0.2f ms\n"
+            "\trequested latency: %s\n"
             "\tsample spec: %s\n"
             "\tchannel map: %s\n"
             "\tresample method: %s\n",
@@ -347,6 +362,7 @@ char *pa_sink_input_list_to_string(pa_core *c) {
             pa_cvolume_snprint(cv, sizeof(cv), pa_sink_input_get_volume(i)),
             pa_yes_no(pa_sink_input_get_mute(i)),
             (double) pa_sink_input_get_latency(i) / PA_USEC_PER_MSEC,
+            clt,
             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)));
diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c
index 7eeefb8..a824b4d 100644
--- a/src/pulsecore/protocol-native.c
+++ b/src/pulsecore/protocol-native.c
@@ -818,6 +818,8 @@ static void fix_playback_buffer_attr_post(playback_stream *s, uint32_t *maxlengt
     *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);
+
+    s->minreq = *minreq;
 }
 
 static playback_stream* playback_stream_new(
@@ -933,7 +935,6 @@ static playback_stream* playback_stream_new(
     *ss = s->sink_input->sample_spec;
     *map = s->sink_input->channel_map;
 
-    s->minreq = *minreq;
     pa_atomic_store(&s->missing, 0);
     s->drain_request = FALSE;
 
@@ -1290,14 +1291,14 @@ static int sink_input_pop_cb(pa_sink_input *i, size_t nbytes, pa_memchunk *chunk
         } else if (i->thread_info.playing_for > 0)
             pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(s), PLAYBACK_STREAM_MESSAGE_UNDERFLOW, NULL, 0, NULL, NULL);
 
-/*         pa_log("adding %llu bytes, total is %llu", (unsigned long long) nbytes, (unsigned long long) i->thread_info.underrun_for); */
+/*         pa_log("adding %llu bytes", (unsigned long long) nbytes); */
 
         request_bytes(s);
 
         return -1;
     }
 
-/*     pa_log("NOTUNDERRUN"); */
+/*     pa_log("NOTUNDERRUN %lu", (unsigned long) chunk->length); */
 
     if (i->thread_info.underrun_for > 0)
         pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(s), PLAYBACK_STREAM_MESSAGE_STARTED, NULL, 0, NULL, NULL);
@@ -1368,11 +1369,24 @@ static void sink_input_suspend_cb(pa_sink_input *i, pa_bool_t suspend) {
 static void sink_input_moved_cb(pa_sink_input *i) {
     playback_stream *s;
     pa_tagstruct *t;
+    uint32_t maxlength, tlength, prebuf, minreq;
 
     pa_sink_input_assert_ref(i);
     s = PLAYBACK_STREAM(i->userdata);
     playback_stream_assert_ref(s);
 
+    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);
+
+    fix_playback_buffer_attr_pre(s, TRUE, &maxlength, &tlength, &prebuf, &minreq);
+    pa_memblockq_set_maxlength(s->memblockq, maxlength);
+    pa_memblockq_set_tlength(s->memblockq, tlength);
+    pa_memblockq_set_prebuf(s->memblockq, prebuf);
+    pa_memblockq_set_minreq(s->memblockq, minreq);
+    fix_playback_buffer_attr_post(s, &maxlength, &tlength, &prebuf, &minreq);
+
     if (s->connection->version < 12)
       return;
 
@@ -1383,6 +1397,15 @@ static void sink_input_moved_cb(pa_sink_input *i) {
     pa_tagstruct_putu32(t, i->sink->index);
     pa_tagstruct_puts(t, i->sink->name);
     pa_tagstruct_put_boolean(t, pa_sink_get_state(i->sink) == PA_SINK_SUSPENDED);
+
+    if (s->connection->version >= 13) {
+        pa_tagstruct_putu32(t, maxlength);
+        pa_tagstruct_putu32(t, tlength);
+        pa_tagstruct_putu32(t, prebuf);
+        pa_tagstruct_putu32(t, minreq);
+        pa_tagstruct_put_usec(t, s->sink_latency);
+    }
+
     pa_pstream_send_tagstruct(s->connection->pstream, t);
 }
 
@@ -1447,11 +1470,19 @@ static void source_output_suspend_cb(pa_source_output *o, pa_bool_t suspend) {
 static void source_output_moved_cb(pa_source_output *o) {
     record_stream *s;
     pa_tagstruct *t;
+    uint32_t maxlength, fragsize;
 
     pa_source_output_assert_ref(o);
     s = RECORD_STREAM(o->userdata);
     record_stream_assert_ref(s);
 
+    fragsize = (uint32_t) s->fragment_size;
+    maxlength = (uint32_t) pa_memblockq_get_length(s->memblockq);
+
+    fix_record_buffer_attr_pre(s, TRUE, &maxlength, &fragsize);
+    pa_memblockq_set_maxlength(s->memblockq, maxlength);
+    fix_record_buffer_attr_post(s, &maxlength, &fragsize);
+
     if (s->connection->version < 12)
       return;
 
@@ -1462,6 +1493,13 @@ static void source_output_moved_cb(pa_source_output *o) {
     pa_tagstruct_putu32(t, o->source->index);
     pa_tagstruct_puts(t, o->source->name);
     pa_tagstruct_put_boolean(t, pa_source_get_state(o->source) == PA_SOURCE_SUSPENDED);
+
+    if (s->connection->version >= 13) {
+        pa_tagstruct_putu32(t, maxlength);
+        pa_tagstruct_putu32(t, fragsize);
+        pa_tagstruct_put_usec(t, s->source_latency);
+    }
+
     pa_pstream_send_tagstruct(s->connection->pstream, t);
 }
 
@@ -1900,27 +1938,28 @@ static void command_auth(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t
     pa_proplist_sets(c->client->proplist, "native-protocol.version", tmp);
 
     if (!c->authorized) {
-        int success = 0;
+        pa_bool_t success = FALSE;
 
 #ifdef HAVE_CREDS
         const pa_creds *creds;
 
         if ((creds = pa_pdispatch_creds(pd))) {
             if (creds->uid == getuid())
-                success = 1;
+                success = TRUE;
             else if (c->protocol->auth_group) {
                 int r;
                 gid_t gid;
 
                 if ((gid = pa_get_gid_of_group(c->protocol->auth_group)) == (gid_t) -1)
-                    pa_log_warn("failed to get GID of group '%s'", c->protocol->auth_group);
+                    pa_log_warn("Failed to get GID of group '%s'", c->protocol->auth_group);
                 else if (gid == creds->gid)
-                    success = 1;
+                    success = TRUE;
+
                 if (!success) {
                     if ((r = pa_uid_in_group(creds->uid, c->protocol->auth_group)) < 0)
-                        pa_log_warn("failed to check group membership.");
+                        pa_log_warn("Failed to check group membership.");
                     else if (r > 0)
-                        success = 1;
+                        success = TRUE;
                 }
             }
 
@@ -1941,7 +1980,7 @@ static void command_auth(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t
 #endif
 
         if (!success && memcmp(c->protocol->auth_cookie, cookie, PA_NATIVE_COOKIE_LENGTH) == 0)
-            success = 1;
+            success = TRUE;
 
         if (!success) {
             pa_log_warn("Denied access to client with invalid authorization data.");
@@ -3037,6 +3076,9 @@ static void command_set_stream_buffer_attr(pa_pdispatch *pd, uint32_t command, u
         pa_tagstruct_putu32(reply, prebuf);
         pa_tagstruct_putu32(reply, minreq);
 
+        if (c->version >= 13)
+            pa_tagstruct_put_usec(reply, s->sink_latency);
+
     } else {
         record_stream *s;
         pa_bool_t adjust_latency = FALSE;
@@ -3063,6 +3105,9 @@ static void command_set_stream_buffer_attr(pa_pdispatch *pd, uint32_t command, u
         reply = reply_new(tag);
         pa_tagstruct_putu32(reply, maxlength);
         pa_tagstruct_putu32(reply, fragsize);
+
+        if (c->version >= 13)
+            pa_tagstruct_put_usec(reply, s->source_latency);
     }
 
     pa_pstream_send_tagstruct(c->pstream, reply);
@@ -3600,7 +3645,7 @@ static void command_move_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag
 
         CHECK_VALIDITY(c->pstream, si && sink, tag, PA_ERR_NOENTITY);
 
-        if (pa_sink_input_move_to(si, sink, 0) < 0) {
+        if (pa_sink_input_move_to(si, sink) < 0) {
             pa_pstream_send_error(c->pstream, tag, PA_ERR_INVALID);
             return;
         }
diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c
index 0be1cc9..d51ff81 100644
--- a/src/pulsecore/sink-input.c
+++ b/src/pulsecore/sink-input.c
@@ -243,7 +243,6 @@ pa_sink_input* pa_sink_input_new(
     i->thread_info.state = i->state;
     i->thread_info.attached = FALSE;
     pa_atomic_store(&i->thread_info.drained, 1);
-    pa_atomic_store(&i->thread_info.render_memblockq_is_empty, 0);
     i->thread_info.sample_spec = i->sample_spec;
     i->thread_info.resampler = resampler;
     i->thread_info.volume = i->volume;
@@ -410,10 +409,6 @@ void pa_sink_input_put(pa_sink_input *i) {
 
     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) {
@@ -511,10 +506,10 @@ int pa_sink_input_peek(pa_sink_input *i, size_t slength /* in sink frames */, pa
              * data, so let's just hand out silence */
             pa_atomic_store(&i->thread_info.drained, 1);
 
-            pa_memblockq_seek(i->thread_info.render_memblockq, slength, PA_SEEK_RELATIVE_ON_READ);
+            pa_memblockq_seek(i->thread_info.render_memblockq, slength, PA_SEEK_RELATIVE);
             i->thread_info.playing_for = 0;
             if (i->thread_info.underrun_for != (uint64_t) -1)
-                i->thread_info.underrun_for += slength;
+                i->thread_info.underrun_for += ilength;
             break;
         }
 
@@ -551,6 +546,8 @@ int pa_sink_input_peek(pa_sink_input *i, size_t slength /* in sink frames */, pa
                 pa_memchunk rchunk;
                 pa_resampler_run(i->thread_info.resampler, &wchunk, &rchunk);
 
+/*                 pa_log_debug("pushing %lu", (unsigned long) rchunk.length); */
+
                 if (rchunk.memblock) {
                     pa_memblockq_push_align(i->thread_info.render_memblockq, &rchunk);
                     pa_memblock_unref(rchunk.memblock);
@@ -571,6 +568,8 @@ int pa_sink_input_peek(pa_sink_input *i, size_t slength /* in sink frames */, pa
     pa_assert(chunk->length > 0);
     pa_assert(chunk->memblock);
 
+/*     pa_log_debug("peeking %lu", (unsigned long) chunk->length); */
+
     if (chunk->length > block_size_max_sink)
         chunk->length = block_size_max_sink;
 
@@ -586,8 +585,6 @@ int pa_sink_input_peek(pa_sink_input *i, size_t slength /* in sink frames */, pa
     else
         *volume = i->thread_info.volume;
 
-    pa_atomic_store(&i->thread_info.render_memblockq_is_empty, pa_memblockq_is_empty(i->thread_info.render_memblockq));
-
     return 0;
 }
 
@@ -599,6 +596,8 @@ void pa_sink_input_drop(pa_sink_input *i, size_t nbytes /* in sink sample spec *
     pa_assert(pa_frame_aligned(nbytes, &i->sink->sample_spec));
     pa_assert(nbytes > 0);
 
+/*     pa_log_debug("dropping %lu", (unsigned long) nbytes); */
+
     /* If there's still some rewrite request the handle, but the sink
     didn't do this for us, we do it here. However, since the sink
     apparently doesn't support rewinding, we pass 0 here. This still
@@ -606,12 +605,11 @@ void pa_sink_input_drop(pa_sink_input *i, size_t nbytes /* in sink sample spec *
     pa_sink_input_process_rewind(i, 0);
 
     pa_memblockq_drop(i->thread_info.render_memblockq, nbytes);
-
-    pa_atomic_store(&i->thread_info.render_memblockq_is_empty, pa_memblockq_is_empty(i->thread_info.render_memblockq));
 }
 
 /* Called from thread context */
 void pa_sink_input_process_rewind(pa_sink_input *i, size_t nbytes /* in sink sample spec */) {
+    size_t lbq;
     pa_sink_input_assert_ref(i);
 
     pa_assert(PA_SINK_INPUT_IS_LINKED(i->thread_info.state));
@@ -619,6 +617,8 @@ void pa_sink_input_process_rewind(pa_sink_input *i, size_t nbytes /* in sink sam
 
 /*     pa_log_debug("rewind(%lu, %lu)", (unsigned long) nbytes, (unsigned long) i->thread_info.rewrite_nbytes); */
 
+    lbq = pa_memblockq_get_length(i->thread_info.render_memblockq);
+
     if (nbytes > 0) {
         pa_log_debug("Have to rewind %lu bytes on render memblockq.", (unsigned long) nbytes);
         pa_memblockq_rewind(i->thread_info.render_memblockq, nbytes);
@@ -635,7 +635,7 @@ void pa_sink_input_process_rewind(pa_sink_input *i, size_t nbytes /* in sink sam
         size_t max_rewrite, amount;
 
         /* Calculate how much make sense to rewrite at most */
-        max_rewrite = nbytes + pa_memblockq_get_length(i->thread_info.render_memblockq);
+        max_rewrite = nbytes + lbq;
 
         /* Transform into local domain */
         if (i->thread_info.resampler)
@@ -651,18 +651,16 @@ void pa_sink_input_process_rewind(pa_sink_input *i, size_t nbytes /* in sink sam
             if (i->process_rewind)
                 i->process_rewind(i, amount);
 
-            if (i->thread_info.rewrite_flush)
-                pa_memblockq_silence(i->thread_info.render_memblockq);
-            else {
+            /* Convert back to to sink domain */
+            if (i->thread_info.resampler)
+                amount = pa_resampler_result(i->thread_info.resampler, amount);
 
-                /* Convert back to to sink domain */
-                if (i->thread_info.resampler)
-                    amount = pa_resampler_result(i->thread_info.resampler, amount);
+            if (amount > 0)
+                /* Ok, now update the write pointer */
+                pa_memblockq_seek(i->thread_info.render_memblockq, - ((int64_t) amount), PA_SEEK_RELATIVE);
 
-                if (amount > 0)
-                    /* Ok, now update the write pointer */
-                    pa_memblockq_seek(i->thread_info.render_memblockq, - ((int64_t) amount), PA_SEEK_RELATIVE);
-            }
+            if (i->thread_info.rewrite_flush)
+                pa_memblockq_silence(i->thread_info.render_memblockq);
 
             /* And reset the resampler */
             if (i->thread_info.resampler)
@@ -702,6 +700,7 @@ static pa_usec_t fixup_latency(pa_sink *s, pa_usec_t usec) {
 }
 
 pa_usec_t pa_sink_input_set_requested_latency_within_thread(pa_sink_input *i, pa_usec_t usec) {
+    pa_sink_input_assert_ref(i);
 
     usec = fixup_latency(i->sink, usec);
 
@@ -728,6 +727,21 @@ pa_usec_t pa_sink_input_set_requested_latency(pa_sink_input *i, pa_usec_t usec)
     return usec;
 }
 
+pa_usec_t pa_sink_input_get_requested_latency(pa_sink_input *i) {
+    pa_usec_t usec = 0;
+
+    pa_sink_input_assert_ref(i);
+
+    if (PA_SINK_INPUT_IS_LINKED(i->state))
+        pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_GET_REQUESTED_LATENCY, &usec, 0, NULL);
+    else
+        /* If this sink input is not realized yet, we have to touch
+         * the thread info data directly */
+        usec = i->thread_info.requested_sink_latency;
+
+    return usec;
+}
+
 void pa_sink_input_set_volume(pa_sink_input *i, const pa_cvolume *volume) {
     pa_sink_input_assert_ref(i);
     pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
@@ -821,11 +835,9 @@ pa_resample_method_t pa_sink_input_get_resample_method(pa_sink_input *i) {
     return i->resample_method;
 }
 
-int pa_sink_input_move_to(pa_sink_input *i, pa_sink *dest, pa_bool_t immediately) {
+int pa_sink_input_move_to(pa_sink_input *i, pa_sink *dest) {
     pa_resampler *new_resampler;
     pa_sink *origin;
-    pa_usec_t silence_usec = 0;
-    pa_sink_input_move_info info;
     pa_sink_input_move_hook_data hook_data;
 
     pa_sink_input_assert_ref(i);
@@ -881,80 +893,7 @@ int pa_sink_input_move_to(pa_sink_input *i, pa_sink *dest, pa_bool_t immediately
     hook_data.destination = dest;
     pa_hook_fire(&i->sink->core->hooks[PA_CORE_HOOK_SINK_INPUT_MOVE], &hook_data);
 
-    memset(&info, 0, sizeof(info));
-    info.sink_input = i;
-
-    if (!immediately) {
-        pa_usec_t old_latency, new_latency;
-
-        /* Let's do a little bit of Voodoo for compensating latency
-         * 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);
-
-        /* The already resampled data should go to the old sink */
-
-        if (old_latency >= new_latency) {
-
-            /* The latency of the old sink is larger than the latency
-             * of the new sink. Therefore to compensate for the
-             * difference we to play silence on the new one for a
-             * while */
-
-            silence_usec = old_latency - new_latency;
-
-        } else {
-
-            /* The latency of new sink is larger than the latency of
-             * the old sink. Therefore we have to precompute a little
-             * and make sure that this is still played on the old
-             * sink, until we can play the first sample on the new
-             * sink.*/
-
-            info.buffer_bytes = pa_usec_to_bytes(new_latency - old_latency, &origin->sample_spec);
-        }
-
-        /* Okey, let's move it */
-
-        if (info.buffer_bytes > 0) {
-            pa_proplist *p;
-
-            p = pa_proplist_new();
-            pa_proplist_sets(p, PA_PROP_MEDIA_NAME, "Ghost For Moved Stream");
-            pa_proplist_sets(p, PA_PROP_MEDIA_ROLE, "routing");
-
-            info.ghost_sink_input = pa_memblockq_sink_input_new(
-                    origin,
-                    &origin->sample_spec,
-                    &origin->channel_map,
-                    NULL,
-                    NULL,
-                    p);
-
-            pa_proplist_free(p);
-
-            if (info.ghost_sink_input) {
-                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;
-
-                info.buffer = pa_memblockq_new(0, MOVE_BUFFER_LENGTH, 0, pa_frame_size(&origin->sample_spec), 0, 0, 0, NULL);
-            }
-        }
-    }
-
-    pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i->sink), PA_SINK_MESSAGE_REMOVE_INPUT_AND_BUFFER, &info, 0, NULL);
-
-    if (info.ghost_sink_input) {
-        /* Basically, do what pa_sink_input_put() does ...*/
-
-        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);
-    }
+    pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i->sink), PA_SINK_MESSAGE_START_MOVE, i, 0, NULL);
 
     pa_idxset_remove_by_data(origin->inputs, i, NULL);
     pa_idxset_put(dest->inputs, i, NULL);
@@ -965,40 +904,31 @@ int pa_sink_input_move_to(pa_sink_input *i, pa_sink *dest, pa_bool_t immediately
         dest->n_corked++;
     }
 
-    /* Replace resampler */
+    /* Replace resampler and render queue */
     if (new_resampler != i->thread_info.resampler) {
-        pa_memchunk silence;
 
         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 */
-
-        pa_silence_memchunk_get(
-                &i->sink->core->silence_cache,
-                i->sink->core->mempool,
-                &silence,
-                &dest->sample_spec,
-                0);
-
-        pa_memblockq_set_silence(i->thread_info.render_memblockq, &silence);
-        pa_memblock_unref(silence.memblock);
+        pa_memblockq_free(i->thread_info.render_memblockq);
 
+        i->thread_info.render_memblockq = pa_memblockq_new(
+                0,
+                MEMBLOCKQ_MAXLENGTH,
+                0,
+                pa_frame_size(&i->sink->sample_spec),
+                0,
+                1,
+                0,
+                &i->sink->silence);
     }
 
-    pa_memblockq_flush(i->thread_info.render_memblockq);
-
-    /* Calculate the new sleeping time */
-    if (!immediately)
-        pa_memblockq_seek(i->thread_info.render_memblockq, pa_usec_to_bytes(silence_usec, &dest->sample_spec), PA_SEEK_RELATIVE);
-
-    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_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i->sink), PA_SINK_MESSAGE_FINISH_MOVE, i, 0, NULL);
+
     if (i->moved)
         i->moved(i);
 
@@ -1015,6 +945,9 @@ int pa_sink_input_move_to(pa_sink_input *i, pa_sink *dest, pa_bool_t immediately
 void pa_sink_input_set_state_within_thread(pa_sink_input *i, pa_sink_input_state_t state) {
     pa_sink_input_assert_ref(i);
 
+    if (state == i->thread_info.state)
+        return;
+
     if ((state == PA_SINK_INPUT_DRAINED || state == 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);
@@ -1060,7 +993,6 @@ int pa_sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int64_t
             pa_usec_t *r = userdata;
 
             *r += pa_bytes_to_usec(pa_memblockq_get_length(i->thread_info.render_memblockq), &i->sink->sample_spec);
-
             return 0;
         }
 
@@ -1089,6 +1021,13 @@ int pa_sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int64_t
 
             pa_sink_input_set_requested_latency_within_thread(i, (pa_usec_t) offset);
             return 0;
+
+        case PA_SINK_INPUT_MESSAGE_GET_REQUESTED_LATENCY: {
+            pa_usec_t *r = userdata;
+
+            *r = i->thread_info.requested_sink_latency;
+            return 0;
+        }
     }
 
     return -1;
@@ -1103,11 +1042,12 @@ pa_sink_input_state_t pa_sink_input_get_state(pa_sink_input *i) {
     return i->state;
 }
 
+/* Called from IO context */
 pa_bool_t pa_sink_input_safe_to_remove(pa_sink_input *i) {
     pa_sink_input_assert_ref(i);
 
-    if (i->state == PA_SINK_INPUT_RUNNING || i->state == PA_SINK_INPUT_DRAINED || i->state == PA_SINK_INPUT_CORKED)
-        return pa_atomic_load(&i->thread_info.render_memblockq_is_empty);
+    if (PA_SINK_INPUT_IS_LINKED(i->thread_info.state))
+        return pa_memblockq_is_empty(i->thread_info.render_memblockq);
 
     return TRUE;
 }
@@ -1129,7 +1069,7 @@ void pa_sink_input_request_rewind(pa_sink_input *i, size_t nbytes  /* in our sam
     pa_assert(i->thread_info.rewrite_nbytes == 0);
 
     /* We don't take rewind requests while we are corked */
-    if (i->state == PA_SINK_INPUT_CORKED)
+    if (i->thread_info.state == PA_SINK_INPUT_CORKED)
         return;
 
     pa_assert(rewrite || flush);
diff --git a/src/pulsecore/sink-input.h b/src/pulsecore/sink-input.h
index 8edd7ec..5f14612 100644
--- a/src/pulsecore/sink-input.h
+++ b/src/pulsecore/sink-input.h
@@ -144,7 +144,7 @@ struct pa_sink_input {
 
     struct {
         pa_sink_input_state_t state;
-        pa_atomic_t drained, render_memblockq_is_empty;
+        pa_atomic_t drained;
 
         pa_bool_t attached; /* True only between ->attach() and ->detach() calls */
 
@@ -181,6 +181,7 @@ enum {
     PA_SINK_INPUT_MESSAGE_SET_RATE,
     PA_SINK_INPUT_MESSAGE_SET_STATE,
     PA_SINK_INPUT_MESSAGE_SET_REQUESTED_LATENCY,
+    PA_SINK_INPUT_MESSAGE_GET_REQUESTED_LATENCY,
     PA_SINK_INPUT_MESSAGE_MAX
 };
 
@@ -243,6 +244,10 @@ could be rewound in the HW device. This functionality is required for
 implementing the "zero latency" write-through functionality. */
 void pa_sink_input_request_rewind(pa_sink_input *i, size_t nbytes, pa_bool_t rewrite, pa_bool_t flush);
 
+void pa_sink_input_cork(pa_sink_input *i, pa_bool_t b);
+
+int pa_sink_input_set_rate(pa_sink_input *i, uint32_t rate);
+
 /* Callable by everyone from main thread*/
 
 /* External code may request disconnection with this function */
@@ -255,17 +260,14 @@ 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, pa_bool_t b);
-
-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, pa_bool_t immediately);
+int pa_sink_input_move_to(pa_sink_input *i, pa_sink *dest);
 
 pa_sink_input_state_t pa_sink_input_get_state(pa_sink_input *i);
 
-pa_bool_t pa_sink_input_safe_to_remove(pa_sink_input *i);
+pa_usec_t pa_sink_input_get_requested_latency(pa_sink_input *i);
+
 /* To be used exclusively by the sink driver IO thread */
 
 int pa_sink_input_peek(pa_sink_input *i, size_t length, pa_memchunk *chunk, pa_cvolume *volume);
@@ -279,12 +281,7 @@ int pa_sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int64_t
 
 pa_usec_t pa_sink_input_set_requested_latency_within_thread(pa_sink_input *i, pa_usec_t usec);
 
-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;
+pa_bool_t pa_sink_input_safe_to_remove(pa_sink_input *i);
 
 pa_memchunk* pa_sink_input_get_silence(pa_sink_input *i, pa_memchunk *ret);
 
diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c
index d3bacbf..31c3cfc 100644
--- a/src/pulsecore/sink.c
+++ b/src/pulsecore/sink.c
@@ -113,7 +113,6 @@ static void reset_callbacks(pa_sink *s) {
     s->set_volume = NULL;
     s->get_mute = NULL;
     s->set_mute = NULL;
-    s->get_latency = NULL;
     s->request_rewind = NULL;
     s->update_requested_latency = NULL;
 }
@@ -769,9 +768,6 @@ pa_usec_t pa_sink_get_latency(pa_sink *s) {
     if (!PA_SINK_IS_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;
 
@@ -930,6 +926,10 @@ int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offse
         case PA_SINK_MESSAGE_ADD_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_FINISH_MOVE, too. */
+
             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
@@ -965,10 +965,6 @@ int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offse
              * slow start, i.e. need some time to buffer client
              * samples before beginning streaming. */
 
-            /* 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;
         }
 
@@ -977,7 +973,7 @@ int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offse
 
             /* 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. */
+             * PA_SINK_MESSAGE_PREPAPRE_MOVE, too. */
 
             pa_sink_input_set_state_within_thread(i, i->state);
 
@@ -1013,85 +1009,88 @@ int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offse
             return 0;
         }
 
-        case PA_SINK_MESSAGE_REMOVE_INPUT_AND_BUFFER: {
-            pa_sink_input_move_info *info = userdata;
-            int volume_is_norm;
+        case PA_SINK_MESSAGE_START_MOVE: {
+            pa_sink_input *i = PA_SINK_INPUT(userdata);
 
             /* 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);
+            pa_assert(!i->sync_prev);
+            pa_assert(!i->sync_next);
+            pa_assert(!i->thread_info.sync_next);
+            pa_assert(!i->thread_info.sync_prev);
 
-            if (info->sink_input->detach)
-                info->sink_input->detach(info->sink_input);
+            if (i->thread_info.state != PA_SINK_INPUT_CORKED) {
+                pa_usec_t usec = 0;
+                size_t sink_nbytes, total_nbytes;
 
-            pa_assert(info->sink_input->thread_info.attached);
-            info->sink_input->thread_info.attached = FALSE;
-            pa_sink_invalidate_requested_latency(info->sink_input->sink);
+                /* Get the latency of the sink */
+                if (PA_MSGOBJECT(s)->process_msg(PA_MSGOBJECT(s), PA_SINK_MESSAGE_GET_LATENCY, &usec, 0, NULL) < 0)
+                    usec = 0;
 
-            if (info->ghost_sink_input) {
-                pa_assert(info->buffer_bytes > 0);
-                pa_assert(info->buffer);
+                sink_nbytes = pa_usec_to_bytes(usec, &s->sample_spec);
+                total_nbytes = sink_nbytes + pa_memblockq_get_length(i->thread_info.render_memblockq);
 
-                volume_is_norm = pa_cvolume_is_norm(&info->sink_input->thread_info.volume);
+                if (total_nbytes > 0) {
+                    i->thread_info.rewrite_nbytes = i->thread_info.resampler ? pa_resampler_request(i->thread_info.resampler, total_nbytes) : total_nbytes;
+                    i->thread_info.rewrite_flush = TRUE;
+                    pa_sink_input_process_rewind(i, sink_nbytes);
+                }
+            }
 
-                pa_log_debug("Buffering %lu bytes ...", (unsigned long) info->buffer_bytes);
+            if (i->detach)
+                i->detach(i);
 
-                while (info->buffer_bytes > 0) {
-                    pa_memchunk memchunk;
-                    pa_cvolume volume;
-                    size_t n;
+            pa_assert(i->thread_info.attached);
+            i->thread_info.attached = FALSE;
 
-                    if (pa_sink_input_peek(info->sink_input, info->buffer_bytes, &memchunk, &volume) < 0)
-                        break;
+            /* Let's remove the sink input ...*/
+            if (pa_hashmap_remove(s->thread_info.inputs, PA_UINT32_TO_PTR(i->index)))
+                pa_sink_input_unref(i);
 
-                    n = memchunk.length > info->buffer_bytes ? info->buffer_bytes : memchunk.length;
-                    pa_sink_input_drop(info->sink_input, n);
-                    memchunk.length = n;
+            pa_sink_invalidate_requested_latency(s);
 
-                    if (!volume_is_norm) {
-                        pa_memchunk_make_writable(&memchunk, 0);
-                        pa_volume_memchunk(&memchunk, &s->sample_spec, &volume);
-                    }
+            pa_log_debug("Requesting rewind due to started move");
+            pa_sink_request_rewind(s, 0);
 
-                    if (pa_memblockq_push(info->buffer, &memchunk) < 0) {
-                        pa_memblock_unref(memchunk.memblock);
-                        break;
-                    }
+            return 0;
+        }
 
-                    pa_memblock_unref(memchunk.memblock);
-                    info->buffer_bytes -= n;
-                }
+        case PA_SINK_MESSAGE_FINISH_MOVE: {
+            pa_sink_input *i = PA_SINK_INPUT(userdata);
 
-                /* Add the remaining already resampled chunks to the buffer */
-                pa_memblockq_splice(info->buffer, info->sink_input->thread_info.render_memblockq);
+            /* We don't support moving synchronized streams. */
+            pa_assert(!i->sync_prev);
+            pa_assert(!i->sync_next);
+            pa_assert(!i->thread_info.sync_next);
+            pa_assert(!i->thread_info.sync_prev);
 
-                pa_memblockq_sink_input_set_queue(info->ghost_sink_input, info->buffer);
+            pa_hashmap_put(s->thread_info.inputs, PA_UINT32_TO_PTR(i->index), pa_sink_input_ref(i));
 
-                pa_log_debug("Buffered %lu bytes ...", (unsigned long) pa_memblockq_get_length(info->buffer));
-            }
+            pa_assert(!i->thread_info.attached);
+            i->thread_info.attached = TRUE;
 
-            /* 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);
+            if (i->attach)
+                i->attach(i);
 
-            /* .. 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_sink_input_update_max_rewind(i, s->thread_info.max_rewind);
 
-                pa_sink_input_update_max_rewind(info->ghost_sink_input, s->thread_info.max_rewind);
+            pa_sink_input_set_requested_latency_within_thread(i, i->thread_info.requested_sink_latency);
 
-                pa_assert(!info->ghost_sink_input->thread_info.attached);
-                info->ghost_sink_input->thread_info.attached = TRUE;
+            if (i->thread_info.state != PA_SINK_INPUT_CORKED) {
+                pa_usec_t usec = 0;
+                size_t nbytes;
 
-                if (info->ghost_sink_input->attach)
-                    info->ghost_sink_input->attach(info->ghost_sink_input);
-            }
+                /* Get the latency of the sink */
+                if (PA_MSGOBJECT(s)->process_msg(PA_MSGOBJECT(s), PA_SINK_MESSAGE_GET_LATENCY, &usec, 0, NULL) < 0)
+                    usec = 0;
 
-            pa_sink_invalidate_requested_latency(s);
-            pa_sink_request_rewind(s, 0);
+                nbytes = pa_usec_to_bytes(usec, &s->sample_spec);
+
+                if (nbytes > 0)
+                    pa_sink_input_drop(i, nbytes);
+
+                pa_log_debug("Requesting rewind due to finished move");
+                pa_sink_request_rewind(s, nbytes);
+            }
 
             return 0;
         }
diff --git a/src/pulsecore/sink.h b/src/pulsecore/sink.h
index f25f48c..f297c8f 100644
--- a/src/pulsecore/sink.h
+++ b/src/pulsecore/sink.h
@@ -118,11 +118,6 @@ struct pa_sink {
      * message will be sent to the IO thread instead. */
     int (*set_mute)(pa_sink *s);               /* dito */
 
-    /* Called when the latency is queried. Called from main loop
-    context. If this is NULL a PA_SINK_MESSAGE_GET_LATENCY message
-    will be sent to the IO thread instead. */
-    pa_usec_t (*get_latency)(pa_sink *s); /* dito */
-
     /* Called when a rewind request is issued. Called from IO thread
      * context. */
     void (*request_rewind)(pa_sink *s);        /* dito */
@@ -166,7 +161,8 @@ typedef enum pa_sink_message {
     PA_SINK_MESSAGE_GET_LATENCY,
     PA_SINK_MESSAGE_GET_REQUESTED_LATENCY,
     PA_SINK_MESSAGE_SET_STATE,
-    PA_SINK_MESSAGE_REMOVE_INPUT_AND_BUFFER,
+    PA_SINK_MESSAGE_START_MOVE,
+    PA_SINK_MESSAGE_FINISH_MOVE,
     PA_SINK_MESSAGE_ATTACH,
     PA_SINK_MESSAGE_DETACH,
     PA_SINK_MESSAGE_MAX
diff --git a/src/pulsecore/source-output.c b/src/pulsecore/source-output.c
index 836e30e..3940d76 100644
--- a/src/pulsecore/source-output.c
+++ b/src/pulsecore/source-output.c
@@ -294,6 +294,7 @@ void pa_source_output_unlink(pa_source_output*o) {
 static void source_output_free(pa_object* mo) {
     pa_source_output *o = PA_SOURCE_OUTPUT(mo);
 
+    pa_assert(o);
     pa_assert(pa_source_output_refcnt(o) == 0);
 
     if (PA_SOURCE_OUTPUT_IS_LINKED(o->state))
@@ -326,7 +327,7 @@ void pa_source_output_put(pa_source_output *o) {
     state = o->flags & PA_SOURCE_OUTPUT_START_CORKED ? PA_SOURCE_OUTPUT_CORKED : PA_SOURCE_OUTPUT_RUNNING;
 
     update_n_corked(o, state);
-    o->thread_info.state = o->state = state;
+    o->state = state;
 
     pa_asyncmsgq_send(o->source->asyncmsgq, PA_MSGOBJECT(o->source), PA_SOURCE_MESSAGE_ADD_OUTPUT, o, 0, NULL);
 
@@ -470,6 +471,7 @@ static pa_usec_t fixup_latency(pa_source *s, pa_usec_t usec) {
 }
 
 pa_usec_t pa_source_output_set_requested_latency_within_thread(pa_source_output *o, pa_usec_t usec) {
+    pa_source_output_assert_ref(o);
 
     usec = fixup_latency(o->source, usec);
 
@@ -496,6 +498,21 @@ pa_usec_t pa_source_output_set_requested_latency(pa_source_output *o, pa_usec_t
     return usec;
 }
 
+pa_usec_t pa_source_output_get_requested_latency(pa_source_output *o) {
+    pa_usec_t usec = 0;
+
+    pa_source_output_assert_ref(o);
+
+    if (PA_SOURCE_OUTPUT_IS_LINKED(o->state))
+        pa_asyncmsgq_send(o->source->asyncmsgq, PA_MSGOBJECT(o), PA_SOURCE_OUTPUT_MESSAGE_GET_REQUESTED_LATENCY, &usec, 0, NULL);
+    else
+        /* If this sink input is not realized yet, we have to touch
+         * the thread info data directly */
+        usec = o->thread_info.requested_source_latency;
+
+    return usec;
+}
+
 void pa_source_output_cork(pa_source_output *o, pa_bool_t b) {
     pa_source_output_assert_ref(o);
     pa_assert(PA_SOURCE_OUTPUT_IS_LINKED(o->state));
@@ -523,11 +540,11 @@ void pa_source_output_set_name(pa_source_output *o, const char *name) {
     const char *old;
     pa_source_output_assert_ref(o);
 
-    old = pa_proplist_gets(o->proplist, PA_PROP_MEDIA_NAME);
-
-    if (!old && !name)
+    if (!name && !pa_proplist_contains(o->proplist, PA_PROP_MEDIA_NAME))
         return;
 
+    old = pa_proplist_gets(o->proplist, PA_PROP_MEDIA_NAME);
+
     if (old && name && !strcmp(old, name))
         return;
 
@@ -550,7 +567,7 @@ 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) {
     pa_source *origin;
-    pa_resampler *new_resampler = NULL;
+    pa_resampler *new_resampler;
     pa_source_output_move_hook_data hook_data;
 
     pa_source_output_assert_ref(o);
@@ -594,7 +611,8 @@ int pa_source_output_move_to(pa_source_output *o, pa_source *dest) {
             pa_log_warn("Unsupported resampling operation.");
             return -1;
         }
-    }
+    } else
+        new_resampler = NULL;
 
     hook_data.source_output = o;
     hook_data.destination = dest;
@@ -640,6 +658,9 @@ int pa_source_output_move_to(pa_source_output *o, pa_source *dest) {
 void pa_source_output_set_state_within_thread(pa_source_output *o, pa_source_output_state_t state) {
     pa_source_output_assert_ref(o);
 
+    if (state == o->thread_info.state)
+        return;
+
     if (o->state_change)
         o->state_change(o, state);
 
@@ -659,7 +680,6 @@ int pa_source_output_process_msg(pa_msgobject *mo, int code, void *userdata, int
             pa_usec_t *r = userdata;
 
             *r += pa_bytes_to_usec(pa_memblockq_get_length(o->thread_info.delay_memblockq), &o->source->sample_spec);
-
             return 0;
         }
 
@@ -678,6 +698,13 @@ int pa_source_output_process_msg(pa_msgobject *mo, int code, void *userdata, int
 
             pa_source_output_set_requested_latency_within_thread(o, (pa_usec_t) offset);
             return 0;
+
+        case PA_SINK_INPUT_MESSAGE_GET_REQUESTED_LATENCY: {
+            pa_usec_t *r = userdata;
+
+            *r = o->thread_info.requested_source_latency;
+            return 0;
+        }
     }
 
     return -1;
diff --git a/src/pulsecore/source-output.h b/src/pulsecore/source-output.h
index 67cb376..2dadb5c 100644
--- a/src/pulsecore/source-output.h
+++ b/src/pulsecore/source-output.h
@@ -148,6 +148,7 @@ enum {
     PA_SOURCE_OUTPUT_MESSAGE_SET_RATE,
     PA_SOURCE_OUTPUT_MESSAGE_SET_STATE,
     PA_SOURCE_OUTPUT_MESSAGE_SET_REQUESTED_LATENCY,
+    PA_SOURCE_OUTPUT_MESSAGE_GET_REQUESTED_LATENCY,
     PA_SOURCE_OUTPUT_MESSAGE_MAX
 };
 
@@ -168,16 +169,16 @@ typedef struct pa_source_output_new_data {
     pa_resample_method_t resample_method;
 } pa_source_output_new_data;
 
-typedef struct pa_source_output_move_hook_data {
-    pa_source_output *source_output;
-    pa_source *destination;
-} pa_source_output_move_hook_data;
-
 pa_source_output_new_data* pa_source_output_new_data_init(pa_source_output_new_data *data);
 void pa_source_output_new_data_set_sample_spec(pa_source_output_new_data *data, const pa_sample_spec *spec);
 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_done(pa_source_output_new_data *data);
 
+typedef struct pa_source_output_move_hook_data {
+    pa_source_output *source_output;
+    pa_source *destination;
+} pa_source_output_move_hook_data;
+
 /* To be called by the implementing module only */
 
 pa_source_output* pa_source_output_new(
@@ -192,6 +193,10 @@ void pa_source_output_set_name(pa_source_output *i, const char *name);
 
 pa_usec_t pa_source_output_set_requested_latency(pa_source_output *i, pa_usec_t usec);
 
+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);
+
 /* Callable by everyone */
 
 /* External code may request disconnection with this funcion */
@@ -199,26 +204,24 @@ void pa_source_output_kill(pa_source_output*o);
 
 pa_usec_t pa_source_output_get_latency(pa_source_output *i);
 
-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)
 
+pa_usec_t pa_source_output_get_requested_latency(pa_source_output *o);
+
 /* To be used exclusively by the source driver thread */
 
 void pa_source_output_push(pa_source_output *o, const pa_memchunk *chunk);
 void pa_source_output_process_rewind(pa_source_output *o, size_t nbytes);
 void pa_source_output_update_max_rewind(pa_source_output *o, size_t nbytes);
 
-int pa_source_output_process_msg(pa_msgobject *mo, int code, void *userdata, int64_t offset, pa_memchunk *chunk);
-
 void pa_source_output_set_state_within_thread(pa_source_output *o, pa_source_output_state_t state);
 
+int pa_source_output_process_msg(pa_msgobject *mo, int code, void *userdata, int64_t offset, pa_memchunk *chunk);
+
 pa_usec_t pa_source_output_set_requested_latency_within_thread(pa_source_output *o, pa_usec_t usec);
 
 #endif
diff --git a/src/pulsecore/source.c b/src/pulsecore/source.c
index fc4734f..426906e 100644
--- a/src/pulsecore/source.c
+++ b/src/pulsecore/source.c
@@ -107,7 +107,6 @@ static void reset_callbacks(pa_source *s) {
     s->set_volume = NULL;
     s->get_mute = NULL;
     s->set_mute = NULL;
-    s->get_latency = NULL;
     s->update_requested_latency = NULL;
 }
 
@@ -440,9 +439,6 @@ pa_usec_t pa_source_get_latency(pa_source *s) {
     if (!PA_SOURCE_IS_OPENED(s->state))
         return 0;
 
-    if (s->get_latency)
-        return s->get_latency(s);
-
     if (pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_GET_LATENCY, &usec, 0, NULL) < 0)
         return 0;
 
diff --git a/src/pulsecore/source.h b/src/pulsecore/source.h
index cce5462..f9c9cbf 100644
--- a/src/pulsecore/source.h
+++ b/src/pulsecore/source.h
@@ -100,7 +100,6 @@ struct pa_source {
     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 */
     void (*update_requested_latency)(pa_source *s); /* dito */
 
     /* Contains copies of the above data so that the real-time worker

commit f124445f89b19fa6554e9b3210c18f8740059439
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri May 9 23:15:06 2008 +0000

    fix module-sine for glitch-free
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2393 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-sine.c b/src/modules/module-sine.c
index f6718fd..3d91705 100644
--- a/src/modules/module-sine.c
+++ b/src/modules/module-sine.c
@@ -67,12 +67,30 @@ static int sink_input_pop_cb(pa_sink_input *i, size_t nbytes, pa_memchunk *chunk
     pa_assert(chunk);
 
     chunk->memblock = pa_memblock_ref(u->memblock);
-    chunk->length = pa_memblock_get_length(chunk->memblock);
-    chunk->index = 0;
+    chunk->length = pa_memblock_get_length(u->memblock) - u->peek_index;
+    chunk->index = u->peek_index;
+
+    u->peek_index = 0;
 
     return 0;
 }
 
+static void sink_input_process_rewind_cb(pa_sink_input *i, size_t nbytes) {
+    size_t l;
+    struct userdata *u;
+
+    pa_sink_input_assert_ref(i);
+    pa_assert_se(u = i->userdata);
+
+    l = pa_memblock_get_length(u->memblock);
+    nbytes %= l;
+
+    if (u->peek_index >= nbytes)
+        u->peek_index -= nbytes;
+    else
+        u->peek_index = l + u->peek_index - nbytes;
+}
+
 static void sink_input_kill_cb(pa_sink_input *i) {
     struct userdata *u;
 
@@ -86,6 +104,20 @@ static void sink_input_kill_cb(pa_sink_input *i) {
     pa_module_unload_request(u->module);
 }
 
+/* Called from IO thread context */
+static void sink_input_state_change_cb(pa_sink_input *i, pa_sink_input_state_t state) {
+    struct userdata *u;
+
+    pa_sink_input_assert_ref(i);
+    pa_assert_se(u = i->userdata);
+
+    /* If we are added for the first time, ask for a rewinding so that
+     * we are heard right-away. */
+    if (PA_SINK_INPUT_IS_LINKED(state) &&
+        i->thread_info.state == PA_SINK_INPUT_INIT)
+        pa_sink_input_request_rewind(i, 0, FALSE, TRUE);
+}
+
 static void calc_sine(float *f, size_t l, float freq) {
     size_t i;
 
@@ -101,7 +133,6 @@ int pa__init(pa_module*m) {
     pa_sink *sink;
     pa_sample_spec ss;
     uint32_t frequency;
-    char t[256];
     void *p;
     pa_sink_input_new_data data;
 
@@ -137,13 +168,12 @@ int pa__init(pa_module*m) {
     calc_sine(p, pa_memblock_get_length(u->memblock), frequency);
     pa_memblock_release(u->memblock);
 
-    pa_snprintf(t, sizeof(t), "%u Hz Sine", frequency);
-
     pa_sink_input_new_data_init(&data);
     data.sink = sink;
     data.driver = __FILE__;
-    pa_proplist_sets(data.proplist, PA_PROP_MEDIA_NAME, t);
+    pa_proplist_setf(data.proplist, PA_PROP_MEDIA_NAME, "%u Hz Sine", frequency);
     pa_proplist_sets(data.proplist, PA_PROP_MEDIA_ROLE, "abstract");
+    pa_proplist_setf(data.proplist, "sine.hz", "%u", frequency);
     pa_sink_input_new_data_set_sample_spec(&data, &ss);
     data.module = m;
 
@@ -154,7 +184,9 @@ int pa__init(pa_module*m) {
         goto fail;
 
     u->sink_input->pop = sink_input_pop_cb;
+    u->sink_input->process_rewind = sink_input_process_rewind_cb;
     u->sink_input->kill = sink_input_kill_cb;
+    u->sink_input->state_change = sink_input_state_change_cb;
     u->sink_input->userdata = u;
 
     pa_sink_input_put(u->sink_input);

commit aae8beb8cc83244900fe3ab19a12b972833f30ca
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed May 14 00:40:36 2008 +0000

    if zero is passed to pa_memblock_new() allocate largest memory block possible from mempool
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2412 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/memblock.c b/src/pulsecore/memblock.c
index 33b3874..a555278 100644
--- a/src/pulsecore/memblock.c
+++ b/src/pulsecore/memblock.c
@@ -204,7 +204,9 @@ pa_memblock *pa_memblock_new(pa_mempool *p, size_t length) {
     pa_memblock *b;
 
     pa_assert(p);
-    pa_assert(length > 0);
+
+    if (length <= 0)
+        length = pa_mempool_block_size_max(p);
 
     if (!(b = pa_memblock_new_pool(p, length)))
         b = memblock_new_appended(p, length);

commit c5faeb1390e849a61a223ca3c6e2a87c87f3a349
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed May 14 00:41:58 2008 +0000

    store peer name in native-protocol.peer property
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2413 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c
index a824b4d..ee7e1ed 100644
--- a/src/pulsecore/protocol-native.c
+++ b/src/pulsecore/protocol-native.c
@@ -1038,10 +1038,8 @@ static void request_bytes(playback_stream *s) {
     previous_missing = pa_atomic_add(&s->missing, m);
 
     if (pa_memblockq_prebuf_active(s->memblockq) ||
-        (previous_missing < s->minreq && previous_missing+m >= s->minreq)) {
-        pa_assert(pa_thread_mq_get());
+        (previous_missing < s->minreq && previous_missing+m >= s->minreq))
         pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(s), PLAYBACK_STREAM_MESSAGE_REQUEST_DATA, NULL, 0, NULL, NULL);
-    }
 }
 
 static void send_memblock(connection *c) {
@@ -3921,6 +3919,7 @@ static void on_connection(PA_GCC_UNUSED pa_socket_server*s, pa_iochannel *io, vo
     pa_iochannel_socket_peer_to_string(io, pname, sizeof(pname));
     pa_snprintf(cname, sizeof(cname), "Native client (%s)", pname);
     c->client = pa_client_new(p->core, __FILE__, cname);
+    pa_proplist_sets(c->client, "native-protocol.peer", pname);
     c->client->kill = client_kill_cb;
     c->client->userdata = c;
     c->client->module = p->module;

commit 8df6529ee6d1fb53f5fffece06fa820b393daebd
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed May 14 00:42:46 2008 +0000

    some fixes to make the simple protocol work on glitch-free again
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2414 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/protocol-simple.c b/src/pulsecore/protocol-simple.c
index 8ec38fe..cbe4844 100644
--- a/src/pulsecore/protocol-simple.c
+++ b/src/pulsecore/protocol-simple.c
@@ -32,6 +32,7 @@
 #include <string.h>
 
 #include <pulse/xmalloc.h>
+#include <pulse/timeval.h>
 
 #include <pulsecore/sink-input.h>
 #include <pulsecore/source-output.h>
@@ -42,6 +43,7 @@
 #include <pulsecore/core-error.h>
 #include <pulsecore/atomic.h>
 #include <pulsecore/thread-mq.h>
+#include <pulsecore/core-util.h>
 
 #include "protocol-simple.h"
 
@@ -57,12 +59,13 @@ typedef struct connection {
     pa_client *client;
     pa_memblockq *input_memblockq, *output_memblockq;
 
-    int dead;
+    pa_bool_t dead;
 
     struct {
         pa_memblock *current_memblock;
-        size_t memblock_index, fragment_size;
+        size_t memblock_index;
         pa_atomic_t missing;
+        pa_bool_t underrun;
     } playback;
 } connection;
 
@@ -101,7 +104,8 @@ enum {
 #define PLAYBACK_BUFFER_SECONDS (.5)
 #define PLAYBACK_BUFFER_FRAGMENTS (10)
 #define RECORD_BUFFER_SECONDS (5)
-#define RECORD_BUFFER_FRAGMENTS (100)
+#define DEFAULT_SINK_LATENCY (300*PA_USEC_PER_MSEC)
+#define DEFAULT_SOURCE_LATENCY (300*PA_USEC_PER_MSEC)
 
 static void connection_unlink(connection *c) {
     pa_assert(c);
@@ -140,8 +144,6 @@ 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);
 
@@ -158,27 +160,33 @@ static int do_read(connection *c) {
     ssize_t r;
     size_t l;
     void *p;
+    size_t space;
 
     connection_assert_ref(c);
 
     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)
-        if (pa_memblock_get_length(c->playback.current_memblock) - c->playback.memblock_index < l) {
+        space = pa_memblock_get_length(c->playback.current_memblock) - c->playback.memblock_index;
+
+        if (space <= 0) {
             pa_memblock_unref(c->playback.current_memblock);
             c->playback.current_memblock = NULL;
-            c->playback.memblock_index = 0;
         }
+    }
 
     if (!c->playback.current_memblock) {
-        pa_assert_se(c->playback.current_memblock = pa_memblock_new(c->protocol->core->mempool, l));
+        pa_assert_se(c->playback.current_memblock = pa_memblock_new(c->protocol->core->mempool, 0));
         c->playback.memblock_index = 0;
+
+        space = pa_memblock_get_length(c->playback.current_memblock);
     }
 
+    if (l > space)
+        l = space;
+
     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);
@@ -248,16 +256,16 @@ static void do_work(connection *c) {
     if (c->dead)
         return;
 
-    if (pa_iochannel_is_readable(c->io)) {
+    if (pa_iochannel_is_readable(c->io))
         if (do_read(c) < 0)
             goto fail;
-    } else if (pa_iochannel_is_hungup(c->io))
+
+    if (!c->sink_input && pa_iochannel_is_hungup(c->io))
         goto fail;
 
-    if (pa_iochannel_is_writable(c->io)) {
+    if (pa_iochannel_is_writable(c->io))
         if (do_write(c) < 0)
             goto fail;
-    }
 
     return;
 
@@ -266,7 +274,7 @@ 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;
+        c->dead = TRUE;
 
         pa_iochannel_free(c->io);
         c->io = NULL;
@@ -318,15 +326,19 @@ static int sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int
             /* New data from the main loop */
             pa_memblockq_push_align(c->input_memblockq, chunk);
 
+            if (pa_memblockq_is_readable(c->input_memblockq) && c->playback.underrun) {
+                pa_log_debug("Requesting rewind due to end of underrun.");
+                pa_sink_input_request_rewind(c->sink_input, 0, FALSE, TRUE);
+            }
+
 /*             pa_log("got data, %u", pa_memblockq_get_length(c->input_memblockq)); */
 
             return 0;
         }
 
-        case SINK_INPUT_MESSAGE_DISABLE_PREBUF: {
+        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;
@@ -345,32 +357,60 @@ static int sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int
 /* Called from thread context */
 static int sink_input_pop_cb(pa_sink_input *i, size_t length, pa_memchunk *chunk) {
     connection *c;
-    int r;
 
-    pa_assert(i);
+    pa_sink_input_assert_ref(i);
     c = CONNECTION(i->userdata);
     connection_assert_ref(c);
     pa_assert(chunk);
 
-    if ((r = pa_memblockq_peek(c->input_memblockq, chunk)) < 0) {
+    if (pa_memblockq_peek(c->input_memblockq, chunk) < 0) {
+
+        c->playback.underrun = TRUE;
 
         if (c->dead && pa_sink_input_safe_to_remove(i))
             pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(c), CONNECTION_MESSAGE_UNLINK_CONNECTION, NULL, 0, NULL, NULL);
 
+        return -1;
     } else {
-        size_t old, new;
+        size_t m;
+
+        c->playback.underrun = FALSE;
 
-        old = pa_memblockq_missing(c->input_memblockq);
         pa_memblockq_drop(c->input_memblockq, chunk->length);
-        new = pa_memblockq_missing(c->input_memblockq);
+        m = pa_memblockq_pop_missing(c->input_memblockq);
 
-        if (new > old) {
-            if (pa_atomic_add(&c->playback.missing, new - old) <= 0)
+        if (m > 0)
+            if (pa_atomic_add(&c->playback.missing, m) <= 0)
                 pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(c), CONNECTION_MESSAGE_REQUEST_DATA, NULL, 0, NULL, NULL);
-        }
+
+        return 0;
     }
+}
+
+/* Called from thread context */
+static void sink_input_process_rewind_cb(pa_sink_input *i, size_t nbytes) {
+    connection *c;
 
-    return r;
+    pa_sink_input_assert_ref(i);
+    c = CONNECTION(i->userdata);
+    connection_assert_ref(c);
+
+    /* If we are in an underrun, then we don't rewind */
+    if (i->thread_info.underrun_for > 0)
+        return;
+
+    pa_memblockq_rewind(c->input_memblockq, nbytes);
+}
+
+/* Called from thread context */
+static void sink_input_update_max_rewind_cb(pa_sink_input *i, size_t nbytes) {
+    connection *c;
+
+    pa_sink_input_assert_ref(i);
+    c = CONNECTION(i->userdata);
+    connection_assert_ref(c);
+
+    pa_memblockq_set_maxrewind(c->input_memblockq, nbytes);
 }
 
 /* Called from main context */
@@ -386,7 +426,7 @@ static void sink_input_kill_cb(pa_sink_input *i) {
 static void source_output_push_cb(pa_source_output *o, const pa_memchunk *chunk) {
     connection *c;
 
-    pa_assert(o);
+    pa_source_output_assert_ref(o);
     c = CONNECTION(o->userdata);
     pa_assert(c);
     pa_assert(chunk);
@@ -405,7 +445,7 @@ static void source_output_kill_cb(pa_source_output *o) {
 static pa_usec_t source_output_get_latency_cb(pa_source_output *o) {
     connection*c;
 
-    pa_assert(o);
+    pa_source_output_assert_ref(o);
     c = CONNECTION(o->userdata);
     pa_assert(c);
 
@@ -440,7 +480,7 @@ static void io_callback(pa_iochannel*io, void *userdata) {
 static void on_connection(pa_socket_server*s, pa_iochannel *io, void *userdata) {
     pa_protocol_simple *p = userdata;
     connection *c = NULL;
-    char cname[256];
+    char cname[256], pname[128];
 
     pa_assert(s);
     pa_assert(io);
@@ -462,12 +502,14 @@ static void on_connection(pa_socket_server*s, pa_iochannel *io, void *userdata)
     c->protocol = p;
     c->playback.current_memblock = NULL;
     c->playback.memblock_index = 0;
-    c->playback.fragment_size = 0;
-    c->dead = 0;
+    c->dead = FALSE;
+    c->playback.underrun = TRUE;
     pa_atomic_store(&c->playback.missing, 0);
 
-    pa_iochannel_socket_peer_to_string(io, cname, sizeof(cname));
+    pa_iochannel_socket_peer_to_string(io, pname, sizeof(pname));
+    pa_snprintf(cname, sizeof(cname), "Simple client (%s)", pname);
     pa_assert_se(c->client = pa_client_new(p->core, __FILE__, cname));
+    pa_proplist_sets(c->client->proplist, "simple-protocol.peer", pname);
     c->client->module = p->module;
     c->client->kill = client_kill_cb;
     c->client->userdata = c;
@@ -500,21 +542,24 @@ static void on_connection(pa_socket_server*s, pa_iochannel *io, void *userdata)
 
         c->sink_input->parent.process_msg = sink_input_process_msg;
         c->sink_input->pop = sink_input_pop_cb;
+        c->sink_input->process_rewind = sink_input_process_rewind_cb;
+        c->sink_input->update_max_rewind = sink_input_update_max_rewind_cb;
         c->sink_input->kill = sink_input_kill_cb;
         c->sink_input->userdata = c;
 
+        pa_sink_input_set_requested_latency(c->sink_input, DEFAULT_SINK_LATENCY);
+
         l = (size_t) (pa_bytes_per_second(&p->sample_spec)*PLAYBACK_BUFFER_SECONDS);
         c->input_memblockq = pa_memblockq_new(
                 0,
                 l,
-                0,
+                l,
                 pa_frame_size(&p->sample_spec),
                 (size_t) -1,
                 l/PLAYBACK_BUFFER_FRAGMENTS,
                 0,
                 NULL);
-        pa_iochannel_socket_set_rcvbuf(io, l/PLAYBACK_BUFFER_FRAGMENTS*5);
-        c->playback.fragment_size = l/PLAYBACK_BUFFER_FRAGMENTS;
+        pa_iochannel_socket_set_rcvbuf(io, l);
 
         pa_atomic_store(&c->playback.missing, pa_memblockq_missing(c->input_memblockq));
 
@@ -551,6 +596,8 @@ static void on_connection(pa_socket_server*s, pa_iochannel *io, void *userdata)
         c->source_output->get_latency = source_output_get_latency_cb;
         c->source_output->userdata = c;
 
+        pa_source_output_set_requested_latency(c->source_output, DEFAULT_SOURCE_LATENCY);
+
         l = (size_t) (pa_bytes_per_second(&p->sample_spec)*RECORD_BUFFER_SECONDS);
         c->output_memblockq = pa_memblockq_new(
                 0,
@@ -561,7 +608,7 @@ static void on_connection(pa_socket_server*s, pa_iochannel *io, void *userdata)
                 0,
                 0,
                 NULL);
-        pa_iochannel_socket_set_sndbuf(io, l/RECORD_BUFFER_FRAGMENTS*2);
+        pa_iochannel_socket_set_sndbuf(io, l);
 
         pa_source_output_put(c->source_output);
     }
@@ -582,6 +629,7 @@ pa_protocol_simple* pa_protocol_simple_new(pa_core *core, pa_socket_server *serv
 
     pa_assert(core);
     pa_assert(server);
+    pa_assert(m);
     pa_assert(ma);
 
     p = pa_xnew0(pa_protocol_simple, 1);
@@ -606,7 +654,7 @@ pa_protocol_simple* pa_protocol_simple_new(pa_core *core, pa_socket_server *serv
     }
     p->mode = enable ? RECORD : 0;
 
-    enable = 1;
+    enable = TRUE;
     if (pa_modargs_get_value_boolean(ma, "playback", &enable) < 0) {
         pa_log("playback= expects a numeric argument.");
         goto fail;

commit 94c269e0f4f6c33c0d4f0be66a17504fe1561094
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed May 14 00:43:24 2008 +0000

    some fixes to make the esound protocol work on glitch-free again
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2415 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/protocol-esound.c b/src/pulsecore/protocol-esound.c
index 388808a..492dc9f 100644
--- a/src/pulsecore/protocol-esound.c
+++ b/src/pulsecore/protocol-esound.c
@@ -70,10 +70,12 @@
 #define PLAYBACK_BUFFER_SECONDS (.25)
 #define PLAYBACK_BUFFER_FRAGMENTS (10)
 #define RECORD_BUFFER_SECONDS (5)
-#define RECORD_BUFFER_FRAGMENTS (100)
 
 #define MAX_CACHE_SAMPLE_SIZE (2048000)
 
+#define DEFAULT_SINK_LATENCY (150*PA_USEC_PER_MSEC)
+#define DEFAULT_SOURCE_LATENCY (150*PA_USEC_PER_MSEC)
+
 #define SCACHE_PREFIX "esound."
 
 /* This is heavily based on esound's code */
@@ -102,8 +104,9 @@ typedef struct connection {
 
     struct {
         pa_memblock *current_memblock;
-        size_t memblock_index, fragment_size;
+        size_t memblock_index;
         pa_atomic_t missing;
+        pa_bool_t underrun;
     } playback;
 
     struct {
@@ -122,7 +125,7 @@ static PA_DEFINE_CHECK_TYPE(connection, pa_msgobject);
 struct pa_protocol_esound {
     pa_module *module;
     pa_core *core;
-    int public;
+    pa_bool_t public;
     pa_socket_server *server;
     pa_idxset *connections;
 
@@ -150,6 +153,8 @@ typedef struct proto_handler {
 } esd_proto_handler_info_t;
 
 static int sink_input_pop_cb(pa_sink_input *i, size_t length, pa_memchunk *chunk);
+static void sink_input_process_rewind_cb(pa_sink_input *i, size_t nbytes);
+static void sink_input_update_max_rewind_cb(pa_sink_input *i, size_t nbytes);
 static void sink_input_kill_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);
@@ -397,8 +402,7 @@ static int esd_proto_stream_play(connection *c, PA_GCC_UNUSED esd_proto_t reques
         CHECK_VALIDITY(sink, "No such sink: %s", c->protocol->sink_name);
     }
 
-    strncpy(name, data, sizeof(name));
-    name[sizeof(name)-1] = 0;
+    pa_strlcpy(name, data, sizeof(name));
 
     utf8_name = pa_utf8_filter(name);
     pa_client_set_name(c->client, utf8_name);
@@ -425,20 +429,23 @@ static int esd_proto_stream_play(connection *c, PA_GCC_UNUSED esd_proto_t reques
     c->input_memblockq = pa_memblockq_new(
             0,
             l,
-            0,
+            l,
             pa_frame_size(&ss),
             (size_t) -1,
             l/PLAYBACK_BUFFER_FRAGMENTS,
             0,
             NULL);
-    pa_iochannel_socket_set_rcvbuf(c->io, l/PLAYBACK_BUFFER_FRAGMENTS*2);
-    c->playback.fragment_size = l/PLAYBACK_BUFFER_FRAGMENTS;
+    pa_iochannel_socket_set_rcvbuf(c->io, l);
 
     c->sink_input->parent.process_msg = sink_input_process_msg;
     c->sink_input->pop = sink_input_pop_cb;
+    c->sink_input->process_rewind = sink_input_process_rewind_cb;
+    c->sink_input->update_max_rewind = sink_input_update_max_rewind_cb;
     c->sink_input->kill = sink_input_kill_cb;
     c->sink_input->userdata = c;
 
+    pa_sink_input_set_requested_latency(c->sink_input, DEFAULT_SINK_LATENCY);
+
     c->state = ESD_STREAMING_DATA;
 
     c->protocol->n_player++;
@@ -498,8 +505,7 @@ static int esd_proto_stream_record(connection *c, esd_proto_t request, const voi
         }
     }
 
-    strncpy(name, data, sizeof(name));
-    name[sizeof(name)-1] = 0;
+    pa_strlcpy(name, data, sizeof(name));
 
     utf8_name = pa_utf8_filter(name);
     pa_client_set_name(c->client, utf8_name);
@@ -520,25 +526,27 @@ static int esd_proto_stream_record(connection *c, esd_proto_t request, const voi
     c->source_output = pa_source_output_new(c->protocol->core, &sdata, 0);
     pa_source_output_new_data_done(&sdata);
 
-    CHECK_VALIDITY(c->source_output, "Failed to create source_output.");
+    CHECK_VALIDITY(c->source_output, "Failed to create source output.");
 
     l = (size_t) (pa_bytes_per_second(&ss)*RECORD_BUFFER_SECONDS);
     c->output_memblockq = pa_memblockq_new(
             0,
             l,
-            0,
+            l,
             pa_frame_size(&ss),
             1,
             0,
             0,
             NULL);
-    pa_iochannel_socket_set_sndbuf(c->io, l/RECORD_BUFFER_FRAGMENTS*2);
+    pa_iochannel_socket_set_sndbuf(c->io, l);
 
     c->source_output->push = source_output_push_cb;
     c->source_output->kill = source_output_kill_cb;
     c->source_output->get_latency = source_output_get_latency_cb;
     c->source_output->userdata = c;
 
+    pa_source_output_set_requested_latency(c->source_output, DEFAULT_SOURCE_LATENCY);
+
     c->state = ESD_STREAMING_DATA;
 
     c->protocol->n_player++;
@@ -789,8 +797,7 @@ static int esd_proto_sample_cache(connection *c, PA_GCC_UNUSED esd_proto_t reque
     CHECK_VALIDITY(sc_length <= MAX_CACHE_SAMPLE_SIZE, "Sample too large (%d bytes).", (int)sc_length);
 
     strcpy(name, SCACHE_PREFIX);
-    strncpy(name+sizeof(SCACHE_PREFIX)-1, data, ESD_NAME_MAX);
-    name[sizeof(name)-1] = 0;
+    pa_strlcpy(name+sizeof(SCACHE_PREFIX)-1, data, ESD_NAME_MAX);
 
     CHECK_VALIDITY(pa_utf8_valid(name), "Invalid UTF8 in sample name.");
 
@@ -822,8 +829,7 @@ static int esd_proto_sample_get_id(connection *c, PA_GCC_UNUSED esd_proto_t requ
     pa_assert(length == ESD_NAME_MAX);
 
     strcpy(name, SCACHE_PREFIX);
-    strncpy(name+sizeof(SCACHE_PREFIX)-1, data, ESD_NAME_MAX);
-    name[sizeof(name)-1] = 0;
+    pa_strlcpy(name+sizeof(SCACHE_PREFIX)-1, data, ESD_NAME_MAX);
 
     CHECK_VALIDITY(pa_utf8_valid(name), "Invalid UTF8 in sample name.");
 
@@ -1016,6 +1022,7 @@ static int do_read(connection *c) {
         ssize_t r;
         size_t l;
         void *p;
+        size_t space;
 
         pa_assert(c->input_memblockq);
 
@@ -1024,21 +1031,26 @@ static int do_read(connection *c) {
         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) {
+
+            space = pa_memblock_get_length(c->playback.current_memblock) - c->playback.memblock_index;
 
-        if (c->playback.current_memblock)
-            if (pa_memblock_get_length(c->playback.current_memblock) - c->playback.memblock_index < l) {
+            if (space <= 0) {
                 pa_memblock_unref(c->playback.current_memblock);
                 c->playback.current_memblock = NULL;
-                c->playback.memblock_index = 0;
             }
+        }
 
         if (!c->playback.current_memblock) {
-            pa_assert_se(c->playback.current_memblock = pa_memblock_new(c->protocol->core->mempool, c->playback.fragment_size*2));
+            pa_assert_se(c->playback.current_memblock = pa_memblock_new(c->protocol->core->mempool, 0));
             c->playback.memblock_index = 0;
+
+            space = pa_memblock_get_length(c->playback.current_memblock);
         }
 
+        if (l > space)
+            l = space;
+
         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);
@@ -1126,12 +1138,11 @@ static void do_work(connection *c) {
     if (c->dead)
         return;
 
-    if (pa_iochannel_is_readable(c->io)) {
+    if (pa_iochannel_is_readable(c->io))
         if (do_read(c) < 0)
             goto fail;
-    }
 
-    if (c->state == ESD_STREAMING_DATA && c->source_output && pa_iochannel_is_hungup(c->io))
+    if (c->state == ESD_STREAMING_DATA && !c->sink_input && pa_iochannel_is_hungup(c->io))
         /* In case we are in capture mode we will never call read()
          * on the socket, hence we need to detect the hangup manually
          * here, instead of simply waiting for read() to return 0. */
@@ -1216,15 +1227,19 @@ static int sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int
             /* New data from the main loop */
             pa_memblockq_push_align(c->input_memblockq, chunk);
 
+            if (pa_memblockq_is_readable(c->input_memblockq) && c->playback.underrun) {
+                pa_log_debug("Requesting rewind due to end of underrun.");
+                pa_sink_input_request_rewind(c->sink_input, 0, FALSE, TRUE);
+            }
+
 /*             pa_log("got data, %u", pa_memblockq_get_length(c->input_memblockq)); */
 
             return 0;
         }
 
-        case SINK_INPUT_MESSAGE_DISABLE_PREBUF: {
+        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;
@@ -1243,32 +1258,60 @@ static int sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int
 /* Called from thread context */
 static int sink_input_pop_cb(pa_sink_input *i, size_t length, pa_memchunk *chunk) {
     connection*c;
-    int r;
 
-    pa_assert(i);
+    pa_sink_input_assert_ref(i);
     c = CONNECTION(i->userdata);
     connection_assert_ref(c);
     pa_assert(chunk);
 
-    if ((r = pa_memblockq_peek(c->input_memblockq, chunk)) < 0) {
+    if (pa_memblockq_peek(c->input_memblockq, chunk) < 0) {
 
+        c->playback.underrun = TRUE;
 
         if (c->dead && pa_sink_input_safe_to_remove(i))
             pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(c), CONNECTION_MESSAGE_UNLINK_CONNECTION, NULL, 0, NULL, NULL);
+
+        return -1;
     } else {
-        size_t old, new;
+        size_t m;
+
+        c->playback.underrun = FALSE;
 
-        old = pa_memblockq_missing(c->input_memblockq);
         pa_memblockq_drop(c->input_memblockq, chunk->length);
-        new = pa_memblockq_missing(c->input_memblockq);
+        m = pa_memblockq_pop_missing(c->input_memblockq);
 
-        if (new > old) {
-            if (pa_atomic_add(&c->playback.missing, new - old) <= 0)
+        if (m > 0)
+            if (pa_atomic_add(&c->playback.missing, m) <= 0)
                 pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(c), CONNECTION_MESSAGE_REQUEST_DATA, NULL, 0, NULL, NULL);
-        }
+
+        return 0;
     }
+}
+
+/* Called from thread context */
+static void sink_input_process_rewind_cb(pa_sink_input *i, size_t nbytes) {
+    connection *c;
 
-    return r;
+    pa_sink_input_assert_ref(i);
+    c = CONNECTION(i->userdata);
+    connection_assert_ref(c);
+
+    /* If we are in an underrun, then we don't rewind */
+    if (i->thread_info.underrun_for > 0)
+        return;
+
+    pa_memblockq_rewind(c->input_memblockq, nbytes);
+}
+
+/* Called from thread context */
+static void sink_input_update_max_rewind_cb(pa_sink_input *i, size_t nbytes) {
+    connection *c;
+
+    pa_sink_input_assert_ref(i);
+    c = CONNECTION(i->userdata);
+    connection_assert_ref(c);
+
+    pa_memblockq_set_maxrewind(c->input_memblockq, nbytes);
 }
 
 static void sink_input_kill_cb(pa_sink_input *i) {
@@ -1283,7 +1326,7 @@ static void sink_input_kill_cb(pa_sink_input *i) {
 static void source_output_push_cb(pa_source_output *o, const pa_memchunk *chunk) {
     connection *c;
 
-    pa_assert(o);
+    pa_source_output_assert_ref(o);
     c = CONNECTION(o->userdata);
     pa_assert(c);
     pa_assert(chunk);
@@ -1300,7 +1343,7 @@ static void source_output_kill_cb(pa_source_output *o) {
 static pa_usec_t source_output_get_latency_cb(pa_source_output *o) {
     connection*c;
 
-    pa_assert(o);
+    pa_source_output_assert_ref(o);
     c = CONNECTION(o->userdata);
     pa_assert(c);
 
@@ -1346,6 +1389,7 @@ static void on_connection(pa_socket_server*s, pa_iochannel *io, void *userdata)
     pa_iochannel_socket_peer_to_string(io, pname, sizeof(pname));
     pa_snprintf(cname, sizeof(cname), "EsounD client (%s)", pname);
     c->client = pa_client_new(p->core, __FILE__, cname);
+    pa_proplist_sets(c->client->proplist, "esound-protocol.peer", pname);
     c->client->module = p->module;
     c->client->kill = client_kill_cb;
     c->client->userdata = c;
@@ -1371,11 +1415,10 @@ 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;
+    c->playback.underrun = TRUE;
     pa_atomic_store(&c->playback.missing, 0);
 
-    c->scache.memchunk.length = c->scache.memchunk.index = 0;
-    c->scache.memchunk.memblock = NULL;
+    pa_memchunk_reset(&c->scache.memchunk);
     c->scache.name = NULL;
 
     c->original_name = NULL;
@@ -1456,7 +1499,8 @@ void pa_protocol_esound_free(pa_protocol_esound *p) {
         connection_unlink(c);
     pa_idxset_free(p->connections, NULL, NULL);
 
-    pa_socket_server_unref(p->server);
+    if (p->server)
+        pa_socket_server_unref(p->server);
 
     if (p->auth_ip_acl)
         pa_ip_acl_free(p->auth_ip_acl);

commit dd29f677034c71024d703ebe45fcd7404808ec7d
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed May 14 01:00:35 2008 +0000

    fix braindead mistake
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2416 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c
index ee7e1ed..2adcdfc 100644
--- a/src/pulsecore/protocol-native.c
+++ b/src/pulsecore/protocol-native.c
@@ -3919,7 +3919,7 @@ static void on_connection(PA_GCC_UNUSED pa_socket_server*s, pa_iochannel *io, vo
     pa_iochannel_socket_peer_to_string(io, pname, sizeof(pname));
     pa_snprintf(cname, sizeof(cname), "Native client (%s)", pname);
     c->client = pa_client_new(p->core, __FILE__, cname);
-    pa_proplist_sets(c->client, "native-protocol.peer", pname);
+    pa_proplist_sets(c->client->proplist, "native-protocol.peer", pname);
     c->client->kill = client_kill_cb;
     c->client->userdata = c;
     c->client->module = p->module;

commit 8baa1a46e3a0995e2609bad7052676f9e86dd9a2
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed May 14 01:58:24 2008 +0000

    fix pipe sink for glitch-free
    
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2417 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-null-sink.c b/src/modules/module-null-sink.c
index 606b87d..ded4df9 100644
--- a/src/modules/module-null-sink.c
+++ b/src/modules/module-null-sink.c
@@ -160,6 +160,8 @@ static void process_render(struct userdata *u, pa_usec_t now) {
     size_t nbytes;
     size_t ate = 0;
 
+    pa_assert(u);
+
     /* This is the configured latency. Sink inputs connected to us
     might not have a single frame more than this value queued. Hence:
     at maximum read this many bytes from the sink inputs. */
diff --git a/src/modules/module-pipe-sink.c b/src/modules/module-pipe-sink.c
index 870b32f..f172e20 100644
--- a/src/modules/module-pipe-sink.c
+++ b/src/modules/module-pipe-sink.c
@@ -62,7 +62,7 @@ PA_MODULE_USAGE(
         "rate=<sample rate>"
         "channel_map=<channel map>");
 
-#define DEFAULT_FILE_NAME "/tmp/music.output"
+#define DEFAULT_FILE_NAME "fifo_output"
 #define DEFAULT_SINK_NAME "fifo_output"
 
 struct userdata {
@@ -80,6 +80,8 @@ struct userdata {
     pa_memchunk memchunk;
 
     pa_rtpoll_item *rtpoll_item;
+
+    int write_type;
 };
 
 static const char* const valid_modargs[] = {
@@ -109,16 +111,64 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
             n += u->memchunk.length;
 
             *((pa_usec_t*) data) = pa_bytes_to_usec(n, &u->sink->sample_spec);
-            break;
+            return 0;
         }
     }
 
     return pa_sink_process_msg(o, code, data, offset, chunk);
 }
 
+static void process_rewind(struct userdata *u) {
+    pa_assert(u);
+
+    pa_log_debug("Rewind requested but not supported by pipe sink. Ignoring.");
+    u->sink->thread_info.rewind_nbytes = 0;
+}
+
+static int process_render(struct userdata *u) {
+    pa_assert(u);
+
+    if (u->memchunk.length <= 0)
+        pa_sink_render(u->sink, PIPE_BUF, &u->memchunk);
+
+    pa_assert(u->memchunk.length > 0);
+
+    for (;;) {
+        ssize_t l;
+        void *p;
+
+        p = pa_memblock_acquire(u->memchunk.memblock);
+        l = pa_write(u->fd, (uint8_t*) p + u->memchunk.index, u->memchunk.length, &u->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));
+                return -1;
+            }
+
+        } 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);
+            }
+        }
+
+        return 0;
+    }
+}
+
 static void thread_func(void *userdata) {
     struct userdata *u = userdata;
-    int write_type = 0;
 
     pa_assert(u);
 
@@ -134,39 +184,14 @@ static void thread_func(void *userdata) {
         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->sink->thread_info.state == PA_SINK_RUNNING) {
 
-            if (u->memchunk.length <= 0)
-                pa_sink_render(u->sink, PIPE_BUF, &u->memchunk);
+            if (u->sink->thread_info.rewind_nbytes > 0)
+                process_rewind(u);
 
-            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));
+            if (pollfd->revents) {
+                if (process_render(u) < 0)
                     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;
             }
@@ -229,8 +254,9 @@ int pa__init(pa_module*m) {
     pa_memchunk_reset(&u->memchunk);
     u->rtpoll = pa_rtpoll_new();
     pa_thread_mq_init(&u->thread_mq, m->core->mainloop, u->rtpoll);
+    u->write_type = 0;
 
-    u->filename = pa_xstrdup(pa_modargs_get_value(ma, "file", DEFAULT_FILE_NAME));
+    u->filename = pa_runtime_path(pa_modargs_get_value(ma, "file", DEFAULT_FILE_NAME));
 
     mkfifo(u->filename, 0666);
     if ((u->fd = open(u->filename, O_RDWR|O_NOCTTY)) < 0) {
@@ -256,8 +282,7 @@ int pa__init(pa_module*m) {
     data.module = m;
     pa_sink_new_data_set_name(&data, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME));
     pa_proplist_sets(data.proplist, PA_PROP_DEVICE_STRING, u->filename);
-    pa_proplist_sets(data.proplist, PA_PROP_DEVICE_DESCRIPTION, t = pa_sprintf_malloc("Unix FIFO sink %s", u->filename));
-    pa_xfree(t);
+    pa_proplist_setf(data.proplist, PA_PROP_DEVICE_DESCRIPTION, "Unix FIFO sink %s", u->filename);
     pa_sink_new_data_set_sample_spec(&data, &ss);
     pa_sink_new_data_set_channel_map(&data, &map);
 

commit 9c48ed116c33e4f3ec559e8e479e4b948bcd4e1a
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed May 14 02:03:01 2008 +0000

    update pipe source for glitch-free, too
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2418 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-pipe-sink.c b/src/modules/module-pipe-sink.c
index f172e20..cc64892 100644
--- a/src/modules/module-pipe-sink.c
+++ b/src/modules/module-pipe-sink.c
@@ -230,7 +230,6 @@ int pa__init(pa_module*m) {
     pa_sample_spec ss;
     pa_channel_map map;
     pa_modargs *ma;
-    char *t;
     struct pollfd *pollfd;
     pa_sink_new_data data;
 
diff --git a/src/modules/module-pipe-source.c b/src/modules/module-pipe-source.c
index 5bf4da1..c2f464b 100644
--- a/src/modules/module-pipe-source.c
+++ b/src/modules/module-pipe-source.c
@@ -160,6 +160,7 @@ static void thread_func(void *userdata) {
             goto finish;
 
         pollfd = pa_rtpoll_item_get_pollfd(u->rtpoll_item, NULL);
+
         if (pollfd->revents & ~POLLIN) {
             pa_log("FIFO shutdown.");
             goto fail;
@@ -182,7 +183,6 @@ int pa__init(pa_module*m) {
     pa_sample_spec ss;
     pa_channel_map map;
     pa_modargs *ma;
-    char *t;
     struct pollfd *pollfd;
     pa_source_new_data data;
 
@@ -207,7 +207,7 @@ int pa__init(pa_module*m) {
     u->rtpoll = pa_rtpoll_new();
     pa_thread_mq_init(&u->thread_mq, m->core->mainloop, u->rtpoll);
 
-    u->filename = pa_xstrdup(pa_modargs_get_value(ma, "file", DEFAULT_FILE_NAME));
+    u->filename = pa_runtime_path(pa_modargs_get_value(ma, "file", DEFAULT_FILE_NAME));
 
     mkfifo(u->filename, 0666);
     if ((u->fd = open(u->filename, O_RDWR|O_NOCTTY)) < 0) {
@@ -233,8 +233,7 @@ int pa__init(pa_module*m) {
     data.module = m;
     pa_source_new_data_set_name(&data, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME));
     pa_proplist_sets(data.proplist, PA_PROP_DEVICE_STRING, u->filename);
-    pa_proplist_sets(data.proplist, PA_PROP_DEVICE_DESCRIPTION, t = pa_sprintf_malloc("Unix FIFO source %s", u->filename));
-    pa_xfree(t);
+    pa_proplist_setf(data.proplist, PA_PROP_DEVICE_DESCRIPTION, "Unix FIFO source %s", u->filename);
     pa_source_new_data_set_sample_spec(&data, &ss);
     pa_source_new_data_set_channel_map(&data, &map);
 

commit 2eca8c9496e1fb66aa8b041f91a1dcb026c5818f
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed May 14 02:35:50 2008 +0000

    don't spam us with wakeup msgs in non-tsched mode
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2419 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-alsa-sink.c b/src/modules/module-alsa-sink.c
index 97e1e59..9c4da07 100644
--- a/src/modules/module-alsa-sink.c
+++ b/src/modules/module-alsa-sink.c
@@ -1058,7 +1058,7 @@ static void thread_func(void *userdata) {
                 u->since_start = 0;
             }
 
-            if (revents)
+            if (revents && u->use_tsched)
                 pa_log_debug("Wakeup from ALSA! (%i)", revents);
         }
     }

commit 787b8696943ba3683486a9efcf729cb92e70ce39
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed May 14 02:36:38 2008 +0000

    initialize volume properly, set more properties, modernizations
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2420 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-oss.c b/src/modules/module-oss.c
index 3dd4508..cf7584d 100644
--- a/src/modules/module-oss.c
+++ b/src/modules/module-oss.c
@@ -1146,6 +1146,8 @@ int pa__init(pa_module*m) {
     char hwdesc[64];
     const char *name;
     pa_bool_t namereg_fail;
+    pa_sink_new_data sink_new_data;
+    pa_source_new_data source_new_data;
 
     pa_assert(m);
 
@@ -1226,8 +1228,8 @@ int pa__init(pa_module*m) {
     m->userdata = u;
     u->fd = fd;
     u->mixer_fd = -1;
-    u->use_getospace = u->use_getispace = 1;
-    u->use_getodelay = 1;
+    u->use_getospace = u->use_getispace = TRUE;
+    u->use_getodelay = TRUE;
     u->mode = mode;
     u->frame_size = pa_frame_size(&ss);
     u->device_name = pa_xstrdup(dev);
@@ -1243,27 +1245,26 @@ int pa__init(pa_module*m) {
         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;
+        u->use_getispace = TRUE;
     }
 
     if (ioctl(fd, SNDCTL_DSP_GETOSPACE, &info) >= 0) {
         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->use_getospace = TRUE;
     }
 
     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) {
-        pa_source_new_data data;
         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;
+                use_mmap = u->use_mmap = FALSE;
                 u->in_mmap = NULL;
             } else
                 pa_log_debug("Successfully mmap()ed input buffer.");
@@ -1276,20 +1277,22 @@ int pa__init(pa_module*m) {
             namereg_fail = FALSE;
         }
 
-        pa_source_new_data_init(&data);
-        data.driver = __FILE__;
-        data.module = m;
-        pa_source_new_data_set_name(&data, name);
-        data.namereg_fail = namereg_fail;
-        pa_source_new_data_set_sample_spec(&data, &ss);
-        pa_source_new_data_set_channel_map(&data, &map);
-        pa_proplist_sets(data.proplist, PA_PROP_DEVICE_STRING, dev);
-        pa_proplist_sets(data.proplist, PA_PROP_DEVICE_API, "oss");
-        pa_proplist_sets(data.proplist, PA_PROP_DEVICE_DESCRIPTION, hwdesc[0] ? hwdesc : dev);
-        pa_proplist_sets(data.proplist, PA_PROP_DEVICE_ACCESS_MODE, use_mmap ? "mmap" : "serial");
-
-        u->source = pa_source_new(m->core, &data, PA_SOURCE_HARDWARE|PA_SOURCE_LATENCY);
-        pa_source_new_data_done(&data);
+        pa_source_new_data_init(&source_new_data);
+        source_new_data.driver = __FILE__;
+        source_new_data.module = m;
+        pa_source_new_data_set_name(&source_new_data, name);
+        source_new_data.namereg_fail = namereg_fail;
+        pa_source_new_data_set_sample_spec(&source_new_data, &ss);
+        pa_source_new_data_set_channel_map(&source_new_data, &map);
+        pa_proplist_sets(source_new_data.proplist, PA_PROP_DEVICE_STRING, dev);
+        pa_proplist_sets(source_new_data.proplist, PA_PROP_DEVICE_API, "oss");
+        pa_proplist_sets(source_new_data.proplist, PA_PROP_DEVICE_DESCRIPTION, hwdesc[0] ? hwdesc : dev);
+        pa_proplist_sets(source_new_data.proplist, PA_PROP_DEVICE_ACCESS_MODE, use_mmap ? "mmap" : "serial");
+        pa_proplist_setf(source_new_data.proplist, PA_PROP_DEVICE_BUFFERING_BUFFER_SIZE, "%lu", (unsigned long) (u->in_hwbuf_size));
+        pa_proplist_setf(source_new_data.proplist, PA_PROP_DEVICE_BUFFERING_FRAGMENT_SIZE, "%lu", (unsigned long) (u->in_fragment_size));
+
+        u->source = pa_source_new(m->core, &source_new_data, PA_SOURCE_HARDWARE|PA_SOURCE_LATENCY);
+        pa_source_new_data_done(&source_new_data);
         pa_xfree(name_buf);
 
         if (!u->source) {
@@ -1309,7 +1312,6 @@ int pa__init(pa_module*m) {
     }
 
     if (mode != O_RDONLY) {
-        pa_sink_new_data data;
         char *name_buf = NULL;
 
         if (use_mmap) {
@@ -1320,7 +1322,7 @@ int pa__init(pa_module*m) {
                     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->use_mmap = use_mmap = FALSE;
                     u->out_mmap = NULL;
                 }
             } else {
@@ -1330,26 +1332,28 @@ int pa__init(pa_module*m) {
         }
 
         if ((name = pa_modargs_get_value(ma, "sink_name", NULL)))
-            namereg_fail = 1;
+            namereg_fail = TRUE;
         else {
             name = name_buf = pa_sprintf_malloc("oss_output.%s", pa_path_get_filename(dev));
-            namereg_fail = 0;
+            namereg_fail = FALSE;
         }
 
-        pa_sink_new_data_init(&data);
-        data.driver = __FILE__;
-        data.module = m;
-        pa_sink_new_data_set_name(&data, name);
-        data.namereg_fail = namereg_fail;
-        pa_sink_new_data_set_sample_spec(&data, &ss);
-        pa_sink_new_data_set_channel_map(&data, &map);
-        pa_proplist_sets(data.proplist, PA_PROP_DEVICE_STRING, dev);
-        pa_proplist_sets(data.proplist, PA_PROP_DEVICE_API, "oss");
-        pa_proplist_sets(data.proplist, PA_PROP_DEVICE_DESCRIPTION, hwdesc[0] ? hwdesc : dev);
-        pa_proplist_sets(data.proplist, PA_PROP_DEVICE_ACCESS_MODE, use_mmap ? "mmap" : "serial");
-
-        u->sink = pa_sink_new(m->core, &data, PA_SINK_HARDWARE|PA_SINK_LATENCY);
-        pa_sink_new_data_done(&data);
+        pa_sink_new_data_init(&sink_new_data);
+        sink_new_data.driver = __FILE__;
+        sink_new_data.module = m;
+        pa_sink_new_data_set_name(&sink_new_data, name);
+        sink_new_data.namereg_fail = namereg_fail;
+        pa_sink_new_data_set_sample_spec(&sink_new_data, &ss);
+        pa_sink_new_data_set_channel_map(&sink_new_data, &map);
+        pa_proplist_sets(sink_new_data.proplist, PA_PROP_DEVICE_STRING, dev);
+        pa_proplist_sets(sink_new_data.proplist, PA_PROP_DEVICE_API, "oss");
+        pa_proplist_sets(sink_new_data.proplist, PA_PROP_DEVICE_DESCRIPTION, hwdesc[0] ? hwdesc : dev);
+        pa_proplist_sets(sink_new_data.proplist, PA_PROP_DEVICE_ACCESS_MODE, use_mmap ? "mmap" : "serial");
+        pa_proplist_setf(sink_new_data.proplist, PA_PROP_DEVICE_BUFFERING_BUFFER_SIZE, "%lu", (unsigned long) (u->out_hwbuf_size));
+        pa_proplist_setf(sink_new_data.proplist, PA_PROP_DEVICE_BUFFERING_FRAGMENT_SIZE, "%lu", (unsigned long) (u->out_fragment_size));
+
+        u->sink = pa_sink_new(m->core, &sink_new_data, PA_SINK_HARDWARE|PA_SINK_LATENCY);
+        pa_sink_new_data_done(&sink_new_data);
         pa_xfree(name_buf);
 
         if (!u->sink) {
@@ -1369,7 +1373,7 @@ int pa__init(pa_module*m) {
     }
 
     if ((u->mixer_fd = pa_oss_open_mixer_for_device(u->device_name)) >= 0) {
-        int do_close = 1;
+        pa_bool_t do_close = TRUE;
         u->mixer_devmask = 0;
 
         if (ioctl(fd, SOUND_MIXER_READ_DEVMASK, &u->mixer_devmask) < 0)
@@ -1381,7 +1385,7 @@ int pa__init(pa_module*m) {
                 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;
+                do_close = FALSE;
             }
 
             if (u->source && (u->mixer_devmask & (SOUND_MASK_RECLEV|SOUND_MASK_IGAIN))) {
@@ -1389,7 +1393,7 @@ int pa__init(pa_module*m) {
                 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;
+                do_close = FALSE;
             }
         }
 
@@ -1411,10 +1415,25 @@ go_on:
     }
 
     /* Read mixer settings */
-    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) {
+        if (sink_new_data.volume_is_set) {
+            if (u->sink->set_volume)
+                u->sink->set_volume(u->sink);
+        } else {
+            if (u->sink->get_volume)
+                u->sink->get_volume(u->sink);
+        }
+    }
+
+    if (u->source) {
+        if (source_new_data.volume_is_set) {
+            if (u->source->set_volume)
+                u->source->set_volume(u->source);
+        } else {
+            if (u->source->get_volume)
+                u->source->get_volume(u->source);
+        }
+    }
 
     if (u->sink)
         pa_sink_put(u->sink);

commit 37813d97452095b87cb160a21f52b9bdea5c50fb
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed May 14 02:44:38 2008 +0000

    modernizations
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2421 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-jack-sink.c b/src/modules/module-jack-sink.c
index f97041a..1ef5d23 100644
--- a/src/modules/module-jack-sink.c
+++ b/src/modules/module-jack-sink.c
@@ -53,7 +53,7 @@
 
 /* General overview:
  *
- * Because JACK has a very unflexible event loop management, which
+ * 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
@@ -276,7 +276,6 @@ int pa__init(pa_module*m) {
     pa_bool_t do_connect = TRUE;
     unsigned i;
     const char **ports = NULL, **p;
-    char *t;
     pa_sink_new_data data;
 
     pa_assert(m);
@@ -364,8 +363,7 @@ int pa__init(pa_module*m) {
     pa_proplist_sets(data.proplist, PA_PROP_DEVICE_API, "jack");
     if (server_name)
         pa_proplist_sets(data.proplist, PA_PROP_DEVICE_STRING, server_name);
-    pa_proplist_sets(data.proplist, PA_PROP_DEVICE_DESCRIPTION, t = pa_sprintf_malloc("Jack sink (%s)", jack_get_client_name(u->client)));
-    pa_xfree(t);
+    pa_proplist_setf(data.proplist, PA_PROP_DEVICE_DESCRIPTION, "Jack sink (%s)", jack_get_client_name(u->client));
     pa_proplist_sets(data.proplist, "jack.client_name", jack_get_client_name(u->client));
 
     u->sink = pa_sink_new(m->core, &data, PA_SINK_LATENCY);
diff --git a/src/modules/module-jack-source.c b/src/modules/module-jack-source.c
index 18ffa55..fa2ec5e 100644
--- a/src/modules/module-jack-source.c
+++ b/src/modules/module-jack-source.c
@@ -253,7 +253,6 @@ int pa__init(pa_module*m) {
     pa_bool_t do_connect = TRUE;
     unsigned i;
     const char **ports = NULL, **p;
-    char *t;
     pa_source_new_data data;
 
     pa_assert(m);
@@ -335,8 +334,7 @@ int pa__init(pa_module*m) {
     pa_proplist_sets(data.proplist, PA_PROP_DEVICE_API, "jack");
     if (server_name)
         pa_proplist_sets(data.proplist, PA_PROP_DEVICE_STRING, server_name);
-    pa_proplist_sets(data.proplist, PA_PROP_DEVICE_DESCRIPTION, t = pa_sprintf_malloc("Jack source (%s)", jack_get_client_name(u->client)));
-    pa_xfree(t);
+    pa_proplist_setf(data.proplist, PA_PROP_DEVICE_DESCRIPTION, "Jack source (%s)", jack_get_client_name(u->client));
     pa_proplist_sets(data.proplist, "jack.client_name", jack_get_client_name(u->client));
 
     u->source = pa_source_new(m->core, &data, PA_SOURCE_LATENCY);
diff --git a/src/modules/module-null-sink.c b/src/modules/module-null-sink.c
index ded4df9..aff244f 100644
--- a/src/modules/module-null-sink.c
+++ b/src/modules/module-null-sink.c
@@ -219,7 +219,7 @@ static void thread_func(void *userdata) {
             pa_rtpoll_set_timer_disabled(u->rtpoll);
 
         /* Hmm, nothing to do. Let's sleep */
-        if ((ret = pa_rtpoll_run(u->rtpoll, 1)) < 0)
+        if ((ret = pa_rtpoll_run(u->rtpoll, TRUE)) < 0)
             goto fail;
 
         if (ret == 0)
diff --git a/src/modules/module-pipe-source.c b/src/modules/module-pipe-source.c
index c2f464b..83eb4f8 100644
--- a/src/modules/module-pipe-source.c
+++ b/src/modules/module-pipe-source.c
@@ -153,7 +153,7 @@ static void thread_func(void *userdata) {
         /* 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)
+        if ((ret = pa_rtpoll_run(u->rtpoll, TRUE)) < 0)
             goto fail;
 
         if (ret == 0)

commit df73688440230ac62e7e4e190a99194274473029
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed May 14 17:13:28 2008 +0000

    modernizations
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2422 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-esound-sink.c b/src/modules/module-esound-sink.c
index 4aa7d67..87b87c3 100644
--- a/src/modules/module-esound-sink.c
+++ b/src/modules/module-esound-sink.c
@@ -294,7 +294,7 @@ static void thread_func(void *userdata) {
             }
 
             /* Hmm, nothing to do. Let's sleep */
-            pollfd->events = PA_SINK_IS_OPENED(u->sink->thread_info.state)  ? POLLOUT : 0;
+            pollfd->events = PA_SINK_IS_OPENED(u->sink->thread_info.state) ? POLLOUT : 0;
         }
 
         if ((ret = pa_rtpoll_run(u->rtpoll, TRUE)) < 0)
@@ -502,10 +502,8 @@ static void on_connection(PA_GCC_UNUSED pa_socket_client *c, pa_iochannel*io, vo
 
 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;
     uint32_t key;
     pa_sink_new_data data;
@@ -554,11 +552,18 @@ int pa__init(pa_module*m) {
     u->state = STATE_AUTH;
     u->latency = 0;
 
+    if (!(espeaker = getenv("ESPEAKER")))
+        espeaker = ESD_UNIX_SOCKET_NAME;
+
+    espeaker = pa_modargs_get_value(ma, "server", espeaker);
+
     pa_sink_new_data_init(&data);
     data.driver = __FILE__;
     data.module = m;
     pa_sink_new_data_set_name(&data, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME));
     pa_sink_new_data_set_sample_spec(&data, &ss);
+    pa_proplist_sets(data.proplist, PA_PROP_DEVICE_STRING, espeaker);
+    pa_proplist_setf(data.proplist, PA_PROP_DEVICE_DESCRIPTION, "Esound sink '%s'", espeaker);
 
     u->sink = pa_sink_new(m->core, &data, PA_SINK_LATENCY|PA_SINK_NETWORK);
     pa_sink_new_data_done(&data);
@@ -574,17 +579,11 @@ int pa__init(pa_module*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))) {
+    if (!(u->client = pa_socket_client_new_string(u->core->mainloop, 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 */

commit 103ceaa94488516b0ce0f7b2d428348469db43ce
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu May 15 17:57:52 2008 +0000

    add pa_memblockq_get_nblocks()
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2423 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/memblockq.c b/src/pulsecore/memblockq.c
index 13eb110..c047e56 100644
--- a/src/pulsecore/memblockq.c
+++ b/src/pulsecore/memblockq.c
@@ -902,3 +902,9 @@ void pa_memblockq_silence(pa_memblockq *bq) {
 
     pa_assert(bq->n_blocks == 0);
 }
+
+unsigned pa_memblockq_get_nblocks(pa_memblockq *bq) {
+    pa_assert(bq);
+
+    return bq->n_blocks;
+}
diff --git a/src/pulsecore/memblockq.h b/src/pulsecore/memblockq.h
index a6065de..7c38757 100644
--- a/src/pulsecore/memblockq.h
+++ b/src/pulsecore/memblockq.h
@@ -167,4 +167,6 @@ void pa_memblockq_silence(pa_memblockq *bq);
 /* Check whether we currently are in prebuf state */
 pa_bool_t pa_memblockq_prebuf_active(pa_memblockq *bq);
 
+unsigned pa_memblockq_get_nblocks(pa_memblockq *bq);
+
 #endif

commit 689528045e63843040ea2db24bc027224b342368
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu May 15 17:58:11 2008 +0000

    add pa_ulog2()
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2424 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/core-util.h b/src/pulsecore/core-util.h
index 49315b5..e9313d4 100644
--- a/src/pulsecore/core-util.h
+++ b/src/pulsecore/core-util.h
@@ -155,6 +155,17 @@ static inline unsigned pa_make_power_of_two(unsigned n) {
     return n + 1;
 }
 
+static inline unsigned pa_ulog2(unsigned n) {
+    unsigned r = 0;
+
+    while (n) {
+        r++;
+        n = n >> 1;
+    }
+
+    return r;
+}
+
 void pa_close_pipe(int fds[2]);
 
 char *pa_readlink(const char *p);

commit 1b7157a8d64ae4a389346805cb7a74c4bf50c19c
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu May 15 17:58:26 2008 +0000

    add PA_REFCNT_INIT_ZERO
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2425 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/refcnt.h b/src/pulsecore/refcnt.h
index 64271ab..f0885fb 100644
--- a/src/pulsecore/refcnt.h
+++ b/src/pulsecore/refcnt.h
@@ -32,6 +32,9 @@
 #define PA_REFCNT_INIT(p) \
     pa_atomic_store(&(p)->_ref, 1)
 
+#define PA_REFCNT_INIT_ZERO(p) \
+    pa_atomic_store(&(p)->_ref, 0)
+
 #define PA_REFCNT_INC(p) \
     pa_atomic_inc(&(p)->_ref)
 

commit 076ffa340a05965f12713b8ea0bb78313c066c7c
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu May 15 17:58:53 2008 +0000

    add 'stream' as media role
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2426 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulse/proplist.h b/src/pulse/proplist.h
index d1bf371..f433ec6 100644
--- a/src/pulse/proplist.h
+++ b/src/pulse/proplist.h
@@ -38,7 +38,7 @@ PA_C_DECL_BEGIN
  *    media.filename
  *    media.icon
  *    media.icon_name
- *    media.role                    video, music, game, event, phone, production, filter, abstract
+ *    media.role                    video, music, game, event, phone, production, filter, abstract, stream
  *    event.id                      button-click, session-login
  *    event.x11.display
  *    event.x11.xid

commit c801d089cd7c6248dc362278fe6212298448ffa9
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu May 15 17:59:12 2008 +0000

    use pa_bool_t
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2427 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/rtp/sdp.c b/src/modules/rtp/sdp.c
index 50ac157..9265a20 100644
--- a/src/modules/rtp/sdp.c
+++ b/src/modules/rtp/sdp.c
@@ -117,7 +117,7 @@ static pa_sample_spec *parse_sdp_sample_spec(pa_sample_spec *ss, char *c) {
 
 pa_sdp_info *pa_sdp_parse(const char *t, pa_sdp_info *i, int is_goodbye) {
     uint16_t port = 0;
-    int ss_valid = 0;
+    pa_bool_t ss_valid = FALSE;
 
     pa_assert(t);
     pa_assert(i);
@@ -202,7 +202,7 @@ pa_sdp_info *pa_sdp_parse(const char *t, pa_sdp_info *i, int is_goodbye) {
                     i->payload = (uint8_t) _payload;
 
                     if (pa_rtp_sample_spec_from_payload(i->payload, &i->sample_spec))
-                        ss_valid = 1;
+                        ss_valid = TRUE;
                 }
             }
         } else if (pa_startswith(t, "a=rtpmap:")) {
@@ -222,7 +222,7 @@ pa_sdp_info *pa_sdp_parse(const char *t, pa_sdp_info *i, int is_goodbye) {
                         c[strcspn(c, "\n")] = 0;
 
                         if (parse_sdp_sample_spec(&i->sample_spec, c))
-                            ss_valid = 1;
+                            ss_valid = TRUE;
                     }
                 }
             }

commit d10ee7d6e2ddeebf4308aa4fcd049dac9c4ddf02
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu May 15 17:59:42 2008 +0000

    more pa_bool_t'ization
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2428 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/rtp/sap.c b/src/modules/rtp/sap.c
index ed7eb0b..123bc49 100644
--- a/src/modules/rtp/sap.c
+++ b/src/modules/rtp/sap.c
@@ -71,7 +71,7 @@ void pa_sap_context_destroy(pa_sap_context *c) {
     pa_xfree(c->sdp_data);
 }
 
-int pa_sap_send(pa_sap_context *c, int goodbye) {
+int pa_sap_send(pa_sap_context *c, pa_bool_t goodbye) {
     uint32_t header;
     struct sockaddr_storage sa_buf;
     struct sockaddr *sa = (struct sockaddr*) &sa_buf;
@@ -127,7 +127,7 @@ pa_sap_context* pa_sap_context_init_recv(pa_sap_context *c, int fd) {
     return c;
 }
 
-int pa_sap_recv(pa_sap_context *c, int *goodbye) {
+int pa_sap_recv(pa_sap_context *c, pa_bool_t *goodbye) {
     struct msghdr m;
     struct iovec iov;
     int size, k;
diff --git a/src/modules/rtp/sap.h b/src/modules/rtp/sap.h
index f906a32..db096d6 100644
--- a/src/modules/rtp/sap.h
+++ b/src/modules/rtp/sap.h
@@ -40,9 +40,9 @@ typedef struct pa_sap_context {
 pa_sap_context* pa_sap_context_init_send(pa_sap_context *c, int fd, char *sdp_data);
 void pa_sap_context_destroy(pa_sap_context *c);
 
-int pa_sap_send(pa_sap_context *c, int goodbye);
+int pa_sap_send(pa_sap_context *c, pa_bool_t goodbye);
 
 pa_sap_context* pa_sap_context_init_recv(pa_sap_context *c, int fd);
-int pa_sap_recv(pa_sap_context *c, int *goodbye);
+int pa_sap_recv(pa_sap_context *c, pa_bool_t *goodbye);
 
 #endif

commit 2bc77ff49aa06eb87645d493cb345a41bab69b19
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu May 15 18:00:31 2008 +0000

    reduce number of allocated memblocks when receiving RTP data by reusing blocks
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2429 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/rtp/rtp.c b/src/modules/rtp/rtp.c
index 997fcc3..5c29984 100644
--- a/src/modules/rtp/rtp.c
+++ b/src/modules/rtp/rtp.c
@@ -55,6 +55,8 @@ pa_rtp_context* pa_rtp_context_init_send(pa_rtp_context *c, int fd, uint32_t ssr
     c->payload = payload & 127;
     c->frame_size = frame_size;
 
+    pa_memchunk_reset(&c->memchunk);
+
     return c;
 }
 
@@ -152,6 +154,8 @@ pa_rtp_context* pa_rtp_context_init_recv(pa_rtp_context *c, int fd, size_t frame
 
     c->fd = fd;
     c->frame_size = frame_size;
+
+    pa_memchunk_reset(&c->memchunk);
     return c;
 }
 
@@ -173,12 +177,28 @@ int pa_rtp_recv(pa_rtp_context *c, pa_memchunk *chunk, pa_mempool *pool) {
         goto fail;
     }
 
-    if (!size)
+    if (size <= 0)
         return 0;
 
-    chunk->memblock = pa_memblock_new(pool, size);
+    if (c->memchunk.length < (unsigned) size) {
+        size_t l;
+
+        if (c->memchunk.memblock)
+            pa_memblock_unref(c->memchunk.memblock);
+
+        l = PA_MAX((size_t) size, pa_mempool_block_size_max(pool));
+
+        c->memchunk.memblock = pa_memblock_new(pool, l);
+        c->memchunk.index = 0;
+        c->memchunk.length = pa_memblock_get_length(c->memchunk.memblock);
+    }
+
+    pa_assert(c->memchunk.length >= (size_t) size);
 
-    iov.iov_base = pa_memblock_acquire(chunk->memblock);
+    chunk->memblock = pa_memblock_ref(c->memchunk.memblock);
+    chunk->index = c->memchunk.index;
+
+    iov.iov_base = (uint8_t*) pa_memblock_acquire(chunk->memblock) + chunk->index;
     iov.iov_len = size;
 
     m.msg_name = NULL;
@@ -236,14 +256,22 @@ int pa_rtp_recv(pa_rtp_context *c, pa_memchunk *chunk, pa_mempool *pool) {
         goto fail;
     }
 
-    chunk->index = 12 + cc*4;
-    chunk->length = size - chunk->index;
+    chunk->index += 12 + cc*4;
+    chunk->length = size - 12 + cc*4;
 
     if (chunk->length % c->frame_size != 0) {
         pa_log_warn("Bad RTP packet size.");
         goto fail;
     }
 
+    c->memchunk.index = chunk->index + chunk->length;
+    c->memchunk.length = pa_memblock_get_length(c->memchunk.memblock) - c->memchunk.index;
+
+    if (c->memchunk.length <= 0) {
+        pa_memblock_unref(c->memchunk.memblock);
+        pa_memchunk_reset(&c->memchunk);
+    }
+
     return 0;
 
 fail:
@@ -329,7 +357,10 @@ int pa_rtp_sample_spec_valid(const pa_sample_spec *ss) {
 void pa_rtp_context_destroy(pa_rtp_context *c) {
     pa_assert(c);
 
-    pa_close(c->fd);
+    pa_assert_se(pa_close(c->fd) == 0);
+
+    if (c->memchunk.memblock)
+        pa_memblock_unref(c->memchunk.memblock);
 }
 
 const char* pa_rtp_format_to_string(pa_sample_format_t f) {
@@ -361,4 +392,3 @@ pa_sample_format_t pa_rtp_string_to_format(const char *s) {
     else
         return PA_SAMPLE_INVALID;
 }
-
diff --git a/src/modules/rtp/rtp.h b/src/modules/rtp/rtp.h
index ad7175c..a366d7a 100644
--- a/src/modules/rtp/rtp.h
+++ b/src/modules/rtp/rtp.h
@@ -37,6 +37,8 @@ typedef struct pa_rtp_context {
     uint32_t ssrc;
     uint8_t payload;
     size_t frame_size;
+
+    pa_memchunk memchunk;
 } pa_rtp_context;
 
 pa_rtp_context* pa_rtp_context_init_send(pa_rtp_context *c, int fd, uint32_t ssrc, uint8_t payload, size_t frame_size);

commit 70c5967806da744dc2a3c121d89043dcceb4a260
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu May 15 20:38:29 2008 +0000

    increase shm size limit, modernizations
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2430 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/shm.c b/src/pulsecore/shm.c
index a1bbf60..a684381 100644
--- a/src/pulsecore/shm.c
+++ b/src/pulsecore/shm.c
@@ -57,7 +57,7 @@
 #define MADV_REMOVE 9
 #endif
 
-#define MAX_SHM_SIZE (PA_ALIGN(1024*1024*20))
+#define MAX_SHM_SIZE (PA_ALIGN(1024*1024*64))
 
 #ifdef __linux__
 /* On Linux we know that the shared memory blocks are files in
@@ -86,13 +86,13 @@ static char *segment_name(char *fn, size_t l, unsigned id) {
     return fn;
 }
 
-int pa_shm_create_rw(pa_shm *m, size_t size, int shared, mode_t mode) {
+int pa_shm_create_rw(pa_shm *m, size_t size, pa_bool_t shared, mode_t mode) {
     char fn[32];
     int fd = -1;
 
     pa_assert(m);
     pa_assert(size > 0);
-    pa_assert(size < MAX_SHM_SIZE);
+    pa_assert(size <= MAX_SHM_SIZE);
     pa_assert(mode >= 0600);
 
     /* Each time we create a new SHM area, let's first drop all stale
@@ -124,7 +124,7 @@ int pa_shm_create_rw(pa_shm *m, size_t size, int shared, mode_t mode) {
         m->ptr = pa_xmalloc(m->size);
 #endif
 
-        m->do_unlink = 0;
+        m->do_unlink = FALSE;
 
     } else {
 #ifdef HAVE_SHM_OPEN
@@ -157,7 +157,7 @@ int pa_shm_create_rw(pa_shm *m, size_t size, int shared, mode_t mode) {
         pa_atomic_store(&marker->marker, SHM_MARKER);
 
         pa_assert_se(close(fd) == 0);
-        m->do_unlink = 1;
+        m->do_unlink = TRUE;
 #else
         return -1;
 #endif
@@ -375,7 +375,7 @@ int pa_shm_cleanup(void) {
         /* 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)
+        if (shm_unlink(fn) < 0 && errno != EACCES && errno != ENOENT)
             pa_log_warn("Failed to remove SHM segment %s: %s\n", fn, pa_cstrerror(errno));
     }
 
diff --git a/src/pulsecore/shm.h b/src/pulsecore/shm.h
index 270591d..60bc355 100644
--- a/src/pulsecore/shm.h
+++ b/src/pulsecore/shm.h
@@ -26,15 +26,17 @@
 
 #include <sys/types.h>
 
+#include <pulsecore/macro.h>
+
 typedef struct pa_shm {
     unsigned id;
     void *ptr;
     size_t size;
-    int do_unlink;
-    int shared;
+    pa_bool_t do_unlink:1;
+    pa_bool_t shared:1;
 } pa_shm;
 
-int pa_shm_create_rw(pa_shm *m, size_t size, int shared, mode_t mode);
+int pa_shm_create_rw(pa_shm *m, size_t size, pa_bool_t shared, mode_t mode);
 int pa_shm_attach_ro(pa_shm *m, unsigned id);
 
 void pa_shm_punch(pa_shm *m, size_t offset, size_t size);

commit f96a8adb0cd0679ddc45711c1d943ccc13ea764b
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu May 15 20:39:46 2008 +0000

    increase default mempool size, make mempool_slot an abstract struct because the only fields it defined where actually unused
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2431 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/memblock.c b/src/pulsecore/memblock.c
index a555278..7005b44 100644
--- a/src/pulsecore/memblock.c
+++ b/src/pulsecore/memblock.c
@@ -46,8 +46,12 @@
 
 #include "memblock.h"
 
-#define PA_MEMPOOL_SLOTS_MAX 512
-#define PA_MEMPOOL_SLOT_SIZE (32*1024)
+/* We can allocate 64*1024*1024 bytes at maximum. That's 64MB. Please
+ * note that the footprint is usually much smaller, since the data is
+ * stored in SHM and our OS does not commit the memory before we use
+ * it for the first time. */
+#define PA_MEMPOOL_SLOTS_MAX 1024
+#define PA_MEMPOOL_SLOT_SIZE (64*1024)
 
 #define PA_MEMEXPORT_SLOTS_MAX 128
 
@@ -127,11 +131,6 @@ struct pa_memexport {
     PA_LLIST_FIELDS(pa_memexport);
 };
 
-struct mempool_slot {
-    PA_LLIST_FIELDS(struct mempool_slot);
-    /* the actual data follows immediately hereafter */
-};
-
 struct pa_mempool {
     pa_semaphore *semaphore;
     pa_mutex *mutex;
@@ -204,9 +203,7 @@ pa_memblock *pa_memblock_new(pa_mempool *p, size_t length) {
     pa_memblock *b;
 
     pa_assert(p);
-
-    if (length <= 0)
-        length = pa_mempool_block_size_max(p);
+    pa_assert(length);
 
     if (!(b = pa_memblock_new_pool(p, length)))
         b = memblock_new_appended(p, length);
@@ -219,12 +216,12 @@ static pa_memblock *memblock_new_appended(pa_mempool *p, size_t length) {
     pa_memblock *b;
 
     pa_assert(p);
-    pa_assert(length > 0);
+    pa_assert(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));
+        length = p->block_size - PA_ALIGN(sizeof(pa_memblock));
 
     b = pa_xmalloc(PA_ALIGN(sizeof(pa_memblock)) + length);
     PA_REFCNT_INIT(b);
@@ -265,11 +262,9 @@ static struct mempool_slot* mempool_allocate_slot(pa_mempool *p) {
     return slot;
 }
 
-/* No lock necessary */
-static void* mempool_slot_data(struct mempool_slot *slot) {
-    pa_assert(slot);
-
-    return (uint8_t*) slot + PA_ALIGN(sizeof(struct mempool_slot));
+/* No lock necessary, totally redundant anyway */
+static inline void* mempool_slot_data(struct mempool_slot *slot) {
+    return slot;
 }
 
 /* No lock necessary */
@@ -298,7 +293,7 @@ pa_memblock *pa_memblock_new_pool(pa_mempool *p, size_t length) {
     struct mempool_slot *slot;
 
     pa_assert(p);
-    pa_assert(length > 0);
+    pa_assert(length);
 
     /* 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. */
@@ -306,7 +301,7 @@ pa_memblock *pa_memblock_new_pool(pa_mempool *p, size_t 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 (p->block_size >= PA_ALIGN(sizeof(pa_memblock)) + length) {
 
         if (!(slot = mempool_allocate_slot(p)))
             return NULL;
@@ -315,7 +310,7 @@ pa_memblock *pa_memblock_new_pool(pa_mempool *p, size_t length) {
         b->type = PA_MEMBLOCK_POOL;
         pa_atomic_ptr_store(&b->data, (uint8_t*) b + PA_ALIGN(sizeof(pa_memblock)));
 
-    } else if (p->block_size - PA_ALIGN(sizeof(struct mempool_slot)) >= length) {
+    } else if (p->block_size >= length) {
 
         if (!(slot = mempool_allocate_slot(p)))
             return NULL;
@@ -327,7 +322,7 @@ pa_memblock *pa_memblock_new_pool(pa_mempool *p, size_t length) {
         pa_atomic_ptr_store(&b->data, mempool_slot_data(slot));
 
     } else {
-        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_log_debug("Memory block too large for pool: %lu > %lu", (unsigned long) length, (unsigned long) p->block_size);
         pa_atomic_inc(&p->stat.n_too_large_for_pool);
         return NULL;
     }
@@ -350,7 +345,7 @@ pa_memblock *pa_memblock_new_fixed(pa_mempool *p, void *d, size_t length, pa_boo
     pa_assert(p);
     pa_assert(d);
     pa_assert(length != (size_t) -1);
-    pa_assert(length > 0);
+    pa_assert(length);
 
     if (!(b = pa_flist_pop(PA_STATIC_FLIST_GET(unused_memblocks))))
         b = pa_xnew(pa_memblock, 1);
@@ -374,7 +369,7 @@ pa_memblock *pa_memblock_new_user(pa_mempool *p, void *d, size_t length, pa_free
 
     pa_assert(p);
     pa_assert(d);
-    pa_assert(length > 0);
+    pa_assert(length);
     pa_assert(length != (size_t) -1);
     pa_assert(free_cb);
 
@@ -423,7 +418,6 @@ void pa_memblock_set_is_silence(pa_memblock *b, pa_bool_t v) {
 /* No lock necessary */
 pa_bool_t pa_memblock_ref_is_one(pa_memblock *b) {
     int r;
-
     pa_assert(b);
 
     pa_assert_se((r = PA_REFCNT_VALUE(b)) > 0);
@@ -588,7 +582,7 @@ static void memblock_make_local(pa_memblock *b) {
 
     pa_atomic_dec(&b->pool->stat.n_allocated_by_type[b->type]);
 
-    if (b->length <= b->pool->block_size - PA_ALIGN(sizeof(struct mempool_slot))) {
+    if (b->length <= b->pool->block_size) {
         struct mempool_slot *slot;
 
         if ((slot = mempool_allocate_slot(b->pool))) {
@@ -676,7 +670,7 @@ static void memblock_replace_import(pa_memblock *b) {
         pa_mutex_unlock(seg->import->mutex);
 }
 
-pa_mempool* pa_mempool_new(int shared) {
+pa_mempool* pa_mempool_new(pa_bool_t shared) {
     pa_mempool *p;
 
     p = pa_xnew(pa_mempool, 1);
@@ -690,8 +684,6 @@ pa_mempool* pa_mempool_new(int shared) {
 
     p->n_blocks = PA_MEMPOOL_SLOTS_MAX;
 
-    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;
@@ -747,7 +739,7 @@ const pa_mempool_stat* pa_mempool_get_stat(pa_mempool *p) {
 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));
+    return p->block_size - PA_ALIGN(sizeof(pa_memblock));
 }
 
 /* No lock necessary */
@@ -764,9 +756,7 @@ void pa_mempool_vacuum(pa_mempool *p) {
             ;
 
     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)));
+        pa_shm_punch(&p->memory, (uint8_t*) slot - (uint8_t*) p->memory.ptr, p->block_size);
 
         while (pa_flist_push(p->free_slots, slot))
             ;
diff --git a/src/pulsecore/memblock.h b/src/pulsecore/memblock.h
index 338d1a1..8dc3f5a 100644
--- a/src/pulsecore/memblock.h
+++ b/src/pulsecore/memblock.h
@@ -119,7 +119,7 @@ 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);
+pa_mempool* pa_mempool_new(pa_bool_t shared);
 void pa_mempool_free(pa_mempool *p);
 const pa_mempool_stat* pa_mempool_get_stat(pa_mempool *p);
 void pa_mempool_vacuum(pa_mempool *p);

commit cfc48422c8554403155c3f5ee3476c90e9ae7b8a
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu May 15 20:40:20 2008 +0000

    export a few more properties for RTP streams
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2432 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/rtp/module-rtp-send.c b/src/modules/rtp/module-rtp-send.c
index a441753..3a526c1 100644
--- a/src/modules/rtp/module-rtp-send.c
+++ b/src/modules/rtp/module-rtp-send.c
@@ -289,6 +289,9 @@ int pa__init(pa_module*m) {
 
     pa_source_output_new_data_init(&data);
     pa_proplist_sets(data.proplist, PA_PROP_MEDIA_NAME, "RTP Monitor Stream");
+    pa_proplist_sets(data.proplist, "rtp.destination", dest);
+    pa_proplist_setf(data.proplist, "rtp.mtu", "%lu", (unsigned long) mtu);
+    pa_proplist_setf(data.proplist, "rtp.port", "%lu", (unsigned long) port);
     data.driver = __FILE__;
     data.module = m;
     data.source = s;

commit 1a2e5a8a8026a40ab351901216ffe8dcb173cfdb
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu May 15 20:45:32 2008 +0000

    add adaptive resampler to the RTP receiver, other modernizations
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2433 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/rtp/module-rtp-recv.c b/src/modules/rtp/module-rtp-recv.c
index 92b43dd..cff5cf8 100644
--- a/src/modules/rtp/module-rtp-recv.c
+++ b/src/modules/rtp/module-rtp-recv.c
@@ -51,6 +51,7 @@
 #include <pulsecore/atomic.h>
 #include <pulsecore/rtclock.h>
 #include <pulsecore/atomic.h>
+#include <pulsecore/time-smoother.h>
 
 #include "module-rtp-recv-symdef.h"
 
@@ -69,9 +70,11 @@ PA_MODULE_USAGE(
 
 #define SAP_PORT 9875
 #define DEFAULT_SAP_ADDRESS "224.0.0.56"
-#define MEMBLOCKQ_MAXLENGTH (1024*170)
+#define MEMBLOCKQ_MAXLENGTH (1024*1024*40)
 #define MAX_SESSIONS 16
 #define DEATH_TIMEOUT 20
+#define RATE_UPDATE_INTERVAL (5*PA_USEC_PER_SEC)
+#define LATENCY_USEC (500*PA_USEC_PER_MSEC)
 
 static const char* const valid_modargs[] = {
     "sink",
@@ -97,6 +100,12 @@ struct session {
     pa_rtpoll_item *rtpoll_item;
 
     pa_atomic_t timestamp;
+
+    pa_smoother *smoother;
+    pa_usec_t intended_latency;
+    pa_usec_t sink_latency;
+
+    pa_usec_t last_rate_update;
 };
 
 struct userdata {
@@ -133,7 +142,7 @@ static int sink_input_process_msg(pa_msgobject *o, int code, void *data, int64_t
 }
 
 /* Called from I/O thread context */
-static int sink_input_pop(pa_sink_input *i, size_t length, pa_memchunk *chunk) {
+static int sink_input_pop_cb(pa_sink_input *i, size_t length, pa_memchunk *chunk) {
     struct session *s;
     pa_sink_input_assert_ref(i);
     pa_assert_se(s = i->userdata);
@@ -146,6 +155,26 @@ static int sink_input_pop(pa_sink_input *i, size_t length, pa_memchunk *chunk) {
     return 0;
 }
 
+/* Called from I/O thread context */
+static void sink_input_process_rewind_cb(pa_sink_input *i, size_t nbytes) {
+    struct session *s;
+
+    pa_sink_input_assert_ref(i);
+    pa_assert_se(s = i->userdata);
+
+    pa_memblockq_rewind(s->memblockq, nbytes);
+}
+
+/* Called from thread context */
+static void sink_input_update_max_rewind_cb(pa_sink_input *i, size_t nbytes) {
+    struct session *s;
+
+    pa_sink_input_assert_ref(i);
+    pa_assert_se(s = i->userdata);
+
+    pa_memblockq_set_maxrewind(s->memblockq, nbytes);
+}
+
 /* Called from main context */
 static void sink_input_kill(pa_sink_input* i) {
     struct session *s;
@@ -211,20 +240,82 @@ static int rtpoll_work_cb(pa_rtpoll_item *i) {
 
     pa_memblockq_seek(s->memblockq, delta * s->rtp_context.frame_size, PA_SEEK_RELATIVE);
 
+    pa_rtclock_get(&now);
+
+    pa_smoother_put(s->smoother, pa_timeval_load(&now), pa_bytes_to_usec(pa_memblockq_get_write_index(s->memblockq), &s->sink_input->sample_spec));
+
     if (pa_memblockq_push(s->memblockq, &chunk) < 0) {
-        /* queue overflow, let's flush it and try again */
-        pa_memblockq_flush(s->memblockq);
-        pa_memblockq_push(s->memblockq, &chunk);
+        pa_log_warn("Queue overrun");
+        pa_memblockq_seek(s->memblockq, chunk.length, PA_SEEK_RELATIVE);
     }
 
-    /* The next timestamp we expect */
-    s->offset = s->rtp_context.timestamp + (chunk.length / s->rtp_context.frame_size);
+    pa_log("blocks in q: %u", pa_memblockq_get_nblocks(s->memblockq));
 
     pa_memblock_unref(chunk.memblock);
 
-    pa_rtclock_get(&now);
+    /* The next timestamp we expect */
+    s->offset = s->rtp_context.timestamp + (chunk.length / s->rtp_context.frame_size);
+
     pa_atomic_store(&s->timestamp, now.tv_sec);
 
+    if (s->last_rate_update + RATE_UPDATE_INTERVAL < pa_timeval_load(&now)) {
+        pa_usec_t wi, ri, render_delay, sink_delay = 0, latency, fix;
+        unsigned fix_samples;
+
+        pa_log("Updating sample rate");
+
+        wi = pa_smoother_get(s->smoother, pa_timeval_load(&now));
+        ri = pa_bytes_to_usec(pa_memblockq_get_read_index(s->memblockq), &s->sink_input->sample_spec);
+
+        if (PA_MSGOBJECT(s->sink_input->sink)->process_msg(PA_MSGOBJECT(s->sink_input->sink), PA_SINK_MESSAGE_GET_LATENCY, &sink_delay, 0, NULL) < 0)
+            sink_delay = 0;
+
+        render_delay = pa_bytes_to_usec(pa_memblockq_get_length(s->sink_input->thread_info.render_memblockq), &s->sink_input->sink->sample_spec);
+
+        if (ri > render_delay+sink_delay)
+            ri -= render_delay+sink_delay;
+        else
+            ri = 0;
+
+        if (wi < ri)
+            latency = 0;
+        else
+            latency = wi - ri;
+
+        pa_log_debug("Write index deviates by %0.2f ms, expected %0.2f ms", (double) latency/PA_USEC_PER_MSEC, (double)  s->intended_latency/PA_USEC_PER_MSEC);
+
+        /* Calculate deviation */
+        if (latency < s->intended_latency)
+            fix = s->intended_latency - latency;
+        else
+            fix = latency - s->intended_latency;
+
+        /* How many samples is this per second? */
+        fix_samples = fix * s->sink_input->thread_info.sample_spec.rate / RATE_UPDATE_INTERVAL;
+
+        /* Check if deviation is in bounds */
+        if (fix_samples > s->sink_input->sample_spec.rate*.20)
+            pa_log_debug("Hmmm, rate fix is too large (%lu Hz), not applying.", (unsigned long) fix_samples);
+
+        /* Fix up rate */
+        if (latency < s->intended_latency)
+            s->sink_input->sample_spec.rate -= fix_samples;
+        else
+            s->sink_input->sample_spec.rate += fix_samples;
+
+        pa_resampler_set_input_rate(s->sink_input->thread_info.resampler, s->sink_input->sample_spec.rate);
+
+        pa_log_debug("Updated sampling rate to %lu Hz.", (unsigned long) s->sink_input->sample_spec.rate);
+
+        s->last_rate_update = pa_timeval_load(&now);
+    }
+
+    if (pa_memblockq_is_readable(s->memblockq) &&
+        s->sink_input->thread_info.underrun_for > 0) {
+        pa_log_debug("Requesting rewind due to end of underrun");
+        pa_sink_input_request_rewind(s->sink_input, 0, FALSE, TRUE);
+    }
+
     return 1;
 }
 
@@ -310,7 +401,6 @@ fail:
 
 static struct session *session_new(struct userdata *u, const pa_sdp_info *sdp_info) {
     struct session *s = NULL;
-    char *c;
     pa_sink *sink;
     int fd = -1;
     pa_memchunk silence;
@@ -325,33 +415,41 @@ static struct session *session_new(struct userdata *u, const pa_sdp_info *sdp_in
         goto fail;
     }
 
-    if (!(sink = pa_namereg_get(u->module->core, u->sink_name, PA_NAMEREG_SINK, 1))) {
+    if (!(sink = pa_namereg_get(u->module->core, u->sink_name, PA_NAMEREG_SINK, TRUE))) {
         pa_log("Sink does not exist.");
         goto fail;
     }
 
+    pa_rtclock_get(&now);
+
     s = pa_xnew0(struct session, 1);
     s->userdata = u;
     s->first_packet = FALSE;
     s->sdp_info = *sdp_info;
     s->rtpoll_item = NULL;
-
-    pa_rtclock_get(&now);
+    s->intended_latency = LATENCY_USEC;
+    s->smoother = pa_smoother_new(PA_USEC_PER_SEC*5, PA_USEC_PER_SEC*2, TRUE, 10);
+    pa_smoother_set_time_offset(s->smoother, pa_timeval_load(&now));
+    s->last_rate_update = pa_timeval_load(&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;
 
-    c = pa_sprintf_malloc("RTP Stream%s%s%s",
-                          sdp_info->session_name ? " (" : "",
-                          sdp_info->session_name ? sdp_info->session_name : "",
-                          sdp_info->session_name ? ")" : "");
-
     pa_sink_input_new_data_init(&data);
     data.sink = sink;
     data.driver = __FILE__;
-    pa_proplist_sets(data.proplist, PA_PROP_MEDIA_NAME, c);
-    pa_xfree(c);
+    pa_proplist_sets(data.proplist, PA_PROP_MEDIA_ROLE, "stream");
+    pa_proplist_setf(data.proplist, PA_PROP_MEDIA_NAME,
+                     "RTP Stream%s%s%s",
+                     sdp_info->session_name ? " (" : "",
+                     sdp_info->session_name ? sdp_info->session_name : "",
+                     sdp_info->session_name ? ")" : "");
+
+    if (sdp_info->session_name)
+        pa_proplist_sets(data.proplist, "rtp.session", sdp_info->session_name);
+    pa_proplist_sets(data.proplist, "rtp.origin", sdp_info->origin);
+    pa_proplist_setf(data.proplist, "rtp.payload", "%u", (unsigned) sdp_info->payload);
     data.module = u->module;
     pa_sink_input_new_data_set_sample_spec(&data, &sdp_info->sample_spec);
 
@@ -366,19 +464,26 @@ static struct session *session_new(struct userdata *u, const pa_sdp_info *sdp_in
     s->sink_input->userdata = s;
 
     s->sink_input->parent.process_msg = sink_input_process_msg;
-    s->sink_input->pop = sink_input_pop;
+    s->sink_input->pop = sink_input_pop_cb;
+    s->sink_input->process_rewind = sink_input_process_rewind_cb;
+    s->sink_input->update_max_rewind = sink_input_update_max_rewind_cb;
     s->sink_input->kill = sink_input_kill;
     s->sink_input->attach = sink_input_attach;
     s->sink_input->detach = sink_input_detach;
 
     pa_sink_input_get_silence(s->sink_input, &silence);
 
+    s->sink_latency = pa_sink_input_set_requested_latency(s->sink_input, s->intended_latency/2);
+
+    if (s->intended_latency < s->sink_latency*2)
+        s->intended_latency = s->sink_latency*2;
+
     s->memblockq = pa_memblockq_new(
             0,
             MEMBLOCKQ_MAXLENGTH,
             MEMBLOCKQ_MAXLENGTH,
             pa_frame_size(&s->sink_input->sample_spec),
-            pa_bytes_per_second(&s->sink_input->sample_spec)/10+1,
+            pa_usec_to_bytes(s->intended_latency - s->sink_latency, &s->sink_input->sample_spec),
             0,
             0,
             &silence);
@@ -423,12 +528,14 @@ static void session_free(struct session *s) {
     pa_sdp_info_destroy(&s->sdp_info);
     pa_rtp_context_destroy(&s->rtp_context);
 
+    pa_smoother_free(s->smoother);
+
     pa_xfree(s);
 }
 
 static void sap_event_cb(pa_mainloop_api *m, pa_io_event *e, int fd, pa_io_event_flags_t flags, void *userdata) {
     struct userdata *u = userdata;
-    int goodbye;
+    pa_bool_t goodbye = FALSE;
     pa_sdp_info info;
     struct session *s;
 

commit b57c520149e12339417813cbee07442ccbc788f7
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu May 15 22:14:45 2008 +0000

    add pa_vsnprintf()
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2434 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/core-util.c b/src/pulsecore/core-util.c
index df11096..c8ea4f5 100644
--- a/src/pulsecore/core-util.c
+++ b/src/pulsecore/core-util.c
@@ -1592,12 +1592,28 @@ int pa_snprintf(char *str, size_t size, const char *format, ...) {
     pa_assert(format);
 
     va_start(ap, format);
-    ret = vsnprintf(str, size, format, ap);
+    ret = pa_vsnprintf(str, size, format, ap);
     va_end(ap);
 
+    return ret;
+}
+
+/* Same as vsnprintf, but guarantees NUL-termination on every platform */
+int pa_vsnprintf(char *str, size_t size, const char *format, va_list ap) {
+    int ret;
+
+    pa_assert(str);
+    pa_assert(size > 0);
+    pa_assert(format);
+
+    ret = vsnprintf(str, size, format, ap);
+
     str[size-1] = 0;
 
-    return ret;
+    if (ret < 0)
+        ret = strlen(str);
+
+    return PA_MIN((int) size-1, ret);
 }
 
 /* Truncate the specified string, but guarantee that the string
diff --git a/src/pulsecore/core-util.h b/src/pulsecore/core-util.h
index e9313d4..ec4cdc4 100644
--- a/src/pulsecore/core-util.h
+++ b/src/pulsecore/core-util.h
@@ -128,6 +128,7 @@ 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, ...);
+int pa_vsnprintf(char *str, size_t size, const char *format, va_list ap);
 
 char *pa_truncate_utf8(char *c, size_t l);
 

commit 86ea73acd366817e555e5a83fb9f3db4dc88b791
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu May 15 22:21:05 2008 +0000

    reduce malloc() usage when logging, to minimize the hit of logging in RT threads. Not complete yet, i18n still uses malloc
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2435 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/log.c b/src/pulsecore/log.c
index a898578..b5929ec 100644
--- a/src/pulsecore/log.c
+++ b/src/pulsecore/log.c
@@ -109,9 +109,13 @@ void pa_log_levelv_meta(
         va_list ap) {
 
     const char *e;
-    char *text, *t, *n, *location;
+    char *t, *n;
     int saved_errno = errno;
 
+    /* We don't use dynamic memory allocation here to minimize the hit
+     * in RT threads */
+    char text[1024], location[128];
+
     pa_assert(level < PA_LOG_LEVEL_MAX);
     pa_assert(format);
 
@@ -123,14 +127,14 @@ void pa_log_levelv_meta(
         return;
     }
 
-    text = pa_vsprintf_malloc(format, ap);
+    pa_vsnprintf(text, sizeof(text), format, ap);
 
     if (getenv(ENV_LOGMETA) && file && line > 0 && func)
-        location = pa_sprintf_malloc("[%s:%i %s()] ", file, line, func);
+        pa_snprintf(location, sizeof(location), "[%s:%i %s()] ", file, line, func);
     else if (file)
-        location = pa_sprintf_malloc("%s: ", pa_path_get_filename(file));
+        pa_snprintf(location, sizeof(location), "%s: ", pa_path_get_filename(file));
     else
-        location = pa_xstrdup("");
+        location[0] = 0;
 
     if (!pa_utf8_valid(text))
         pa_log_level(level, __FILE__": invalid UTF-8 string following below:");
@@ -162,6 +166,8 @@ void pa_log_levelv_meta(
                 }
 #endif
 
+                /* We shouldn't be using dynamic allocation here to
+                 * minimize the hit in RT threads */
                 local_t = pa_utf8_to_locale(t);
                 if (!local_t)
                     fprintf(stderr, "%c: %s%s%s%s\n", level_to_char[level], location, prefix, t, suffix);
@@ -193,11 +199,10 @@ void pa_log_levelv_meta(
 #endif
 
             case PA_LOG_USER: {
-                char *x;
+                char x[1024];
 
-                x = pa_sprintf_malloc("%s%s", location, t);
+                pa_snprintf(x, sizeof(x), "%s%s", location, t);
                 user_log_func(level, x);
-                pa_xfree(x);
 
                 break;
             }
@@ -208,9 +213,6 @@ void pa_log_levelv_meta(
         }
     }
 
-    pa_xfree(text);
-    pa_xfree(location);
-
     errno = saved_errno;
 }
 

commit e0dc1e483c2be1f48c1e357505b6eecf606d7348
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu May 15 22:22:41 2008 +0000

    Print message when stream started playback, use terminal sequence to clear line when printing that message
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2436 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/utils/pacat.c b/src/utils/pacat.c
index e802015..fc9d56d 100644
--- a/src/utils/pacat.c
+++ b/src/utils/pacat.c
@@ -44,6 +44,8 @@
 #error Invalid PulseAudio API version
 #endif
 
+#define CLEAR_LINE "\x1B[K"
+
 static enum { RECORD, PLAYBACK } mode = PLAYBACK;
 
 static pa_context *context = NULL;
@@ -206,29 +208,38 @@ static void stream_suspended_callback(pa_stream *s, void *userdata) {
 
     if (verbose) {
         if (pa_stream_is_suspended(s))
-            fprintf(stderr, "Stream device suspended.\n");
+            fprintf(stderr, "Stream device suspended." CLEAR_LINE " \n");
         else
-            fprintf(stderr, "Stream device resumed.\n");
+            fprintf(stderr, "Stream device resumed." CLEAR_LINE " \n");
     }
 }
 
 static void stream_underflow_callback(pa_stream *s, void *userdata) {
     assert(s);
 
-    fprintf(stderr, "Underrun.\n");
+    if (verbose)
+        fprintf(stderr, "Stream underrun." CLEAR_LINE " \n");
 }
 
 static void stream_overflow_callback(pa_stream *s, void *userdata) {
     assert(s);
 
-    fprintf(stderr, "Overrun.\n");
+    if (verbose)
+        fprintf(stderr, "Stream overrun." CLEAR_LINE " \n");
+}
+
+static void stream_started_callback(pa_stream *s, void *userdata) {
+    assert(s);
+
+    if (verbose)
+        fprintf(stderr, "Stream started." CLEAR_LINE " \n");
 }
 
 static void stream_moved_callback(pa_stream *s, void *userdata) {
     assert(s);
 
     if (verbose)
-        fprintf(stderr, "Stream moved to device %s (%u, %ssuspended).\n", pa_stream_get_device_name(s), pa_stream_get_device_index(s), pa_stream_is_suspended(s) ? "" : "not ");
+        fprintf(stderr, "Stream moved to device %s (%u, %ssuspended)." CLEAR_LINE " \n", pa_stream_get_device_name(s), pa_stream_get_device_index(s), pa_stream_is_suspended(s) ? "" : "not ");
 }
 
 /* This is called whenever the context status changes */
@@ -249,7 +260,7 @@ static void context_state_callback(pa_context *c, void *userdata) {
             assert(!stream);
 
             if (verbose)
-                fprintf(stderr, "Connection established.\n");
+                fprintf(stderr, "Connection established." CLEAR_LINE " \n");
 
             if (!(stream = pa_stream_new(c, stream_name, &sample_spec, channel_map_set ? &channel_map : NULL))) {
                 fprintf(stderr, "pa_stream_new() failed: %s\n", pa_strerror(pa_context_errno(c)));
@@ -263,6 +274,7 @@ static void context_state_callback(pa_context *c, void *userdata) {
             pa_stream_set_moved_callback(stream, stream_moved_callback, NULL);
             pa_stream_set_underflow_callback(stream, stream_underflow_callback, NULL);
             pa_stream_set_overflow_callback(stream, stream_overflow_callback, NULL);
+            pa_stream_set_started_callback(stream, stream_started_callback, NULL);
 
             if (latency > 0) {
                 memset(&buffer_attr, 0, sizeof(buffer_attr));

commit f021538d918a86c47010f663e911c77657af5a07
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu May 15 22:23:14 2008 +0000

    export a couple of more functions from libpulse
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2437 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/map-file b/src/map-file
index ffa5d10..d918974 100644
--- a/src/map-file
+++ b/src/map-file
@@ -30,6 +30,7 @@ pa_context_get_autoload_info_by_name;
 pa_context_get_autoload_info_list;
 pa_context_get_client_info;
 pa_context_get_client_info_list;
+pa_context_get_index;
 pa_context_get_module_info;
 pa_context_get_module_info_list;
 pa_context_get_protocol_version;
@@ -61,7 +62,11 @@ pa_context_move_sink_input_by_name;
 pa_context_move_source_output_by_index;
 pa_context_move_source_output_by_name;
 pa_context_new;
+pa_context_new_with_proplist;
 pa_context_play_sample;
+pa_context_play_sample_with_proplist;
+pa_context_proplist_remove;
+pa_context_proplist_update;
 pa_context_ref;
 pa_context_remove_autoload_by_index;
 pa_context_remove_autoload_by_name;
@@ -128,14 +133,19 @@ pa_operation_unref;
 pa_parse_sample_format;
 pa_path_get_filename;
 pa_proplist_free;
+pa_proplist_contains;
+pa_proplist_clear;
+pa_proplist_copy;
 pa_proplist_get;
 pa_proplist_gets;
 pa_proplist_iterate;
-pa_proplist_merge;
+pa_proplist_update;
 pa_proplist_new;
-pa_proplist_put;
-pa_proplist_puts;
-pa_proplist_remove;
+pa_proplist_set;
+pa_proplist_sets;
+pa_proplist_setf;
+pa_proplist_unset;
+pa_proplist_unset_many;
 pa_proplist_to_string;
 pa_sample_format_to_string;
 pa_sample_size;
@@ -174,10 +184,14 @@ pa_stream_get_sample_spec;
 pa_stream_get_state;
 pa_stream_get_time;
 pa_stream_get_timing_info;
+pa_stream_is_corked;
 pa_stream_is_suspended;
 pa_stream_new;
+pa_stream_new_with_proplist;
 pa_stream_peek;
 pa_stream_prebuf;
+pa_stream_proplist_remove;
+pa_stream_proplist_update;
 pa_stream_readable_size;
 pa_stream_ref;
 pa_stream_set_buffer_attr;
@@ -186,6 +200,7 @@ pa_stream_set_moved_callback;
 pa_stream_set_name;
 pa_stream_set_overflow_callback;
 pa_stream_set_read_callback;
+pa_stream_set_started_callback;
 pa_stream_set_state_callback;
 pa_stream_set_suspended_callback;
 pa_stream_set_underflow_callback;
@@ -221,6 +236,7 @@ pa_timeval_cmp;
 pa_timeval_diff;
 pa_timeval_load;
 pa_timeval_store;
+pa_timeval_sub;
 pa_usec_to_bytes;
 pa_utf8_filter;
 pa_utf8_to_locale;

commit 74f8a67e98965127416c8f8b720b26cfed927596
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu May 15 22:24:18 2008 +0000

    fix suspend for alsa sink
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2438 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-alsa-sink.c b/src/modules/module-alsa-sink.c
index 9c4da07..f4211ed 100644
--- a/src/modules/module-alsa-sink.c
+++ b/src/modules/module-alsa-sink.c
@@ -868,6 +868,9 @@ static void sink_update_requested_latency_cb(pa_sink *s) {
     snd_pcm_sframes_t before;
     pa_assert(u);
 
+    if (!u->pcm_handle)
+        return;
+
     before = u->hwbuf_unused_frames;
     update_sw_params(u);
 
@@ -1003,7 +1006,7 @@ static void thread_func(void *userdata) {
                      * we have filled the buffer at least once
                      * completely.*/
 
-                    pa_log_debug("Cutting sleep time for the initial iterations by half.");
+                    /*pa_log_debug("Cutting sleep time for the initial iterations by half.");*/
                     sleep_usec /= 2;
                 }
 

commit 99a451655a2db4c6c7a70f7e54b68991a046ff16
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu May 15 23:16:28 2008 +0000

    don't access stream before it is valid
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2439 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulse/stream.c b/src/pulse/stream.c
index bd633cf..4268fd6 100644
--- a/src/pulse/stream.c
+++ b/src/pulse/stream.c
@@ -370,7 +370,7 @@ void pa_command_stream_moved(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED u
 
     if (c->version >= 13) {
 
-        if (s->direction == PA_STREAM_RECORD) {
+        if (command == PA_COMMAND_RECORD_STREAM_MOVED) {
             if (pa_tagstruct_getu32(t, &maxlength) < 0 ||
                 pa_tagstruct_getu32(t, &fragsize) < 0 ||
                 pa_tagstruct_get_usec(t, &usec) < 0) {

commit e3c5a777504f0c19027806c1639c596469259324
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu May 15 23:16:49 2008 +0000

    fix moving of record streams
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2440 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/source-output.c b/src/pulsecore/source-output.c
index 3940d76..5c36937 100644
--- a/src/pulsecore/source-output.c
+++ b/src/pulsecore/source-output.c
@@ -635,13 +635,25 @@ int pa_source_output_move_to(pa_source_output *o, pa_source *dest) {
         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_memblockq_free(o->thread_info.delay_memblockq);
+
+        o->thread_info.delay_memblockq = pa_memblockq_new(
+                0,
+                MEMBLOCKQ_MAXLENGTH,
+                0,
+                pa_frame_size(&o->source->sample_spec),
+                0,
+                1,
+                0,
+                &o->source->silence);
+    }
 
     pa_source_update_status(origin);
     pa_source_update_status(dest);
 
+    pa_asyncmsgq_send(o->source->asyncmsgq, PA_MSGOBJECT(o->source), PA_SOURCE_MESSAGE_ADD_OUTPUT, o, 0, NULL);
+
     if (o->moved)
         o->moved(o);
 

commit 813d40c13d27b15e647e014e0fb1e4508a2532a0
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu May 15 23:17:22 2008 +0000

    fix up requested latency when we move a record stream
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2441 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/pulsecore/source.c b/src/pulsecore/source.c
index 426906e..c767abc 100644
--- a/src/pulsecore/source.c
+++ b/src/pulsecore/source.c
@@ -577,8 +577,6 @@ int pa_source_process_msg(pa_msgobject *object, int code, void *userdata, int64_
 
             pa_hashmap_put(s->thread_info.outputs, PA_UINT32_TO_PTR(o->index), pa_source_output_ref(o));
 
-            pa_source_output_update_max_rewind(o, s->thread_info.max_rewind);
-
             pa_assert(!o->thread_info.attached);
             o->thread_info.attached = TRUE;
 
@@ -587,7 +585,12 @@ int pa_source_process_msg(pa_msgobject *object, int code, void *userdata, int64_
 
             pa_source_output_set_state_within_thread(o, o->state);
 
-            pa_source_invalidate_requested_latency(s);
+            pa_source_output_update_max_rewind(o, s->thread_info.max_rewind);
+
+            /* We don't just invalidate the requested latency here,
+             * because if we are in a move we might need to fix up the
+             * requested latency. */
+            pa_source_output_set_requested_latency_within_thread(o, o->thread_info.requested_source_latency);
 
             return 0;
         }

commit 734f071df7a0a3678cafb4db62e0a7ba26585e93
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu May 15 23:17:58 2008 +0000

    decrease default tsched buffer to 2s to reduce overall memory consumption
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2442 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-alsa-sink.c b/src/modules/module-alsa-sink.c
index f4211ed..95a72fd 100644
--- a/src/modules/module-alsa-sink.c
+++ b/src/modules/module-alsa-sink.c
@@ -3,7 +3,7 @@
 /***
   This file is part of PulseAudio.
 
-  Copyright 2004-2006 Lennart Poettering
+  Copyright 2004-2008 Lennart Poettering
   Copyright 2006 Pierre Ossman <ossman at cendio.se> for Cendio AB
 
   PulseAudio is free software; you can redistribute it and/or modify
@@ -92,10 +92,10 @@ static const char* const valid_modargs[] = {
 };
 
 #define DEFAULT_DEVICE "default"
-#define DEFAULT_TSCHED_BUFFER_USEC (5*PA_USEC_PER_SEC)           /* 5s */
+#define DEFAULT_TSCHED_BUFFER_USEC (2*PA_USEC_PER_SEC)            /* 2s */
 #define DEFAULT_TSCHED_WATERMARK_USEC (20*PA_USEC_PER_MSEC)       /* 20ms */
-#define TSCHED_MIN_SLEEP_USEC (3*PA_USEC_PER_MSEC)        /* 3ms */
-#define TSCHED_MIN_WAKEUP_USEC (3*PA_USEC_PER_MSEC)        /* 3ms */
+#define TSCHED_MIN_SLEEP_USEC (3*PA_USEC_PER_MSEC)                /* 3ms */
+#define TSCHED_MIN_WAKEUP_USEC (3*PA_USEC_PER_MSEC)               /* 3ms */
 
 struct userdata {
     pa_core *core;

commit 43dfc2a00035af3eac5bef812877d7b3fd61efdc
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu May 15 23:19:37 2008 +0000

    follow recent alsa sink changes in the alsa source
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2443 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/src/modules/module-alsa-source.c b/src/modules/module-alsa-source.c
index 4838ad2..e309010 100644
--- a/src/modules/module-alsa-source.c
+++ b/src/modules/module-alsa-source.c
@@ -3,7 +3,7 @@
 /***
   This file is part of PulseAudio.
 
-  Copyright 2004-2006 Lennart Poettering
+  Copyright 2004-2008 Lennart Poettering
   Copyright 2006 Pierre Ossman <ossman at cendio.se> for Cendio AB
 
   PulseAudio is free software; you can redistribute it and/or modify
@@ -93,10 +93,10 @@ static const char* const valid_modargs[] = {
 };
 
 #define DEFAULT_DEVICE "default"
-#define DEFAULT_TSCHED_BUFFER_USEC (5*PA_USEC_PER_SEC)
-#define DEFAULT_TSCHED_WATERMARK_USEC (20*PA_USEC_PER_MSEC)
-#define TSCHED_MIN_SLEEP_USEC (3*PA_USEC_PER_MSEC)        /* 3ms */
-#define TSCHED_MIN_WAKEUP_USEC (3*PA_USEC_PER_MSEC)        /* 3ms */
+#define DEFAULT_TSCHED_BUFFER_USEC (2*PA_USEC_PER_SEC)       /* 2s */
+#define DEFAULT_TSCHED_WATERMARK_USEC (20*PA_USEC_PER_MSEC)  /* 20ms */
+#define TSCHED_MIN_SLEEP_USEC (3*PA_USEC_PER_MSEC)           /* 3ms */
+#define TSCHED_MIN_WAKEUP_USEC (3*PA_USEC_PER_MSEC)          /* 3ms */
 
 struct userdata {
     pa_core *core;
@@ -160,6 +160,31 @@ static void fix_tsched_watermark(struct userdata *u) {
         u->tsched_watermark = min_wakeup;
 }
 
+static pa_usec_t hw_sleep_time(struct userdata *u, pa_usec_t *sleep_usec, pa_usec_t*process_usec) {
+    pa_usec_t wm, usec;
+
+    pa_assert(u);
+
+    usec = pa_source_get_requested_latency_within_thread(u->source);
+
+    if (usec == (pa_usec_t) -1)
+        usec = pa_bytes_to_usec(u->hwbuf_size, &u->source->sample_spec);
+
+/*     pa_log_debug("hw buffer time: %u ms", (unsigned) (usec / PA_USEC_PER_MSEC)); */
+
+    wm = pa_bytes_to_usec(u->tsched_watermark, &u->source->sample_spec);
+
+    if (usec >= wm) {
+        *sleep_usec = usec - wm;
+        *process_usec = wm;
+    } else
+        *process_usec = *sleep_usec = usec /= 2;
+
+/*     pa_log_debug("after watermark: %u ms", (unsigned) (*sleep_usec / PA_USEC_PER_MSEC)); */
+
+    return usec;
+}
+
 static int try_recover(struct userdata *u, const char *call, int err) {
     pa_assert(u);
     pa_assert(call);
@@ -167,10 +192,7 @@ static int try_recover(struct userdata *u, const char *call, int err) {
 
     pa_log_debug("%s: %s", call, snd_strerror(err));
 
-    if (err == -EAGAIN) {
-        pa_log_debug("%s: EAGAIN", call);
-        return 1;
-    }
+    pa_assert(err != -EAGAIN);
 
     if (err == -EPIPE)
         pa_log_debug("%s: Buffer overrun!", call);
@@ -184,7 +206,7 @@ static int try_recover(struct userdata *u, const char *call, int err) {
     return -1;
 }
 
-static void check_left_to_record(struct userdata *u, snd_pcm_sframes_t n) {
+static size_t check_left_to_record(struct userdata *u, snd_pcm_sframes_t n) {
     size_t left_to_record;
 
     if (n*u->frame_size < u->hwbuf_size)
@@ -192,9 +214,9 @@ static void check_left_to_record(struct userdata *u, snd_pcm_sframes_t n) {
     else
         left_to_record = 0;
 
-    if (left_to_record > 0)
-        pa_log_debug("%0.2f ms left to record", (double) pa_bytes_to_usec(left_to_record, &u->source->sample_spec) / PA_USEC_PER_MSEC);
-    else {
+    if (left_to_record > 0) {
+/*         pa_log_debug("%0.2f ms left to record", (double) pa_bytes_to_usec(left_to_record, &u->source->sample_spec) / PA_USEC_PER_MSEC); */
+    } else {
         pa_log_info("Overrun!");
 
         if (u->use_tsched) {
@@ -208,111 +230,121 @@ static void check_left_to_record(struct userdata *u, snd_pcm_sframes_t n) {
                               (double) pa_bytes_to_usec(u->tsched_watermark, &u->source->sample_spec) / PA_USEC_PER_MSEC);
         }
     }
+
+    return left_to_record;
 }
 
-static int mmap_read(struct userdata *u) {
+static int mmap_read(struct userdata *u, pa_usec_t *sleep_usec) {
     int work_done = 0;
-    pa_bool_t checked_left_to_record = FALSE;
+    pa_usec_t max_sleep_usec, process_usec;
+    size_t left_to_record;
 
     pa_assert(u);
     pa_source_assert_ref(u->source);
 
+    if (u->use_tsched)
+        hw_sleep_time(u, &max_sleep_usec, &process_usec);
+
     for (;;) {
         snd_pcm_sframes_t n;
-        int err, r;
-        const snd_pcm_channel_area_t *areas;
-        snd_pcm_uframes_t offset, frames;
-        pa_memchunk chunk;
-        void *p;
+        int r;
 
         snd_pcm_hwsync(u->pcm_handle);
 
         if (PA_UNLIKELY((n = snd_pcm_avail_update(u->pcm_handle)) < 0)) {
 
-            if ((r = try_recover(u, "snd_pcm_avail_update", err)) == 0)
+            if ((r = try_recover(u, "snd_pcm_avail_update", n)) == 0)
                 continue;
-            else if (r > 0)
-                return work_done;
 
             return r;
         }
 
-        if (checked_left_to_record) {
-            check_left_to_record(u, n);
-            checked_left_to_record = TRUE;
-        }
+        left_to_record = check_left_to_record(u, n);
+
+        if (u->use_tsched)
+            if (pa_bytes_to_usec(left_to_record, &u->source->sample_spec) > max_sleep_usec/2)
+                break;
 
         if (PA_UNLIKELY(n <= 0))
-            return work_done;
+            break;
 
-        frames = n;
+        for (;;) {
+            int err;
+            const snd_pcm_channel_area_t *areas;
+            snd_pcm_uframes_t offset, frames = (snd_pcm_uframes_t) n;
+            pa_memchunk chunk;
+            void *p;
 
-        pa_log_debug("%lu frames to read", (unsigned long) frames);
+/*             pa_log_debug("%lu frames to read", (unsigned long) frames); */
 
-        if (PA_UNLIKELY((err = snd_pcm_mmap_begin(u->pcm_handle, &areas, &offset, &frames)) < 0)) {
+            if (PA_UNLIKELY((err = snd_pcm_mmap_begin(u->pcm_handle, &areas, &offset, &frames)) < 0)) {
 
-            if ((r = try_recover(u, "snd_pcm_mmap_begin", err)) == 0)
-                continue;
-            else if (r > 0)
-                return work_done;
+                if ((r = try_recover(u, "snd_pcm_mmap_begin", err)) == 0)
+                    continue;
 
-            return r;
-        }
+                return r;
+            }
 
-        /* Make sure that if these memblocks need to be copied they will fit into one slot */
-        if (frames > pa_mempool_block_size_max(u->source->core->mempool)/u->frame_size)
-            frames = pa_mempool_block_size_max(u->source->core->mempool)/u->frame_size;
+            /* Make sure that if these memblocks need to be copied they will fit into one slot */
+            if (frames > pa_mempool_block_size_max(u->source->core->mempool)/u->frame_size)
+                frames = pa_mempool_block_size_max(u->source->core->mempool)/u->frame_size;
 
-        /* Check these are multiples of 8 bit */
-        pa_assert((areas[0].first & 7) == 0);
-        pa_assert((areas[0].step & 7)== 0);
+            /* Check these are multiples of 8 bit */
+            pa_assert((areas[0].first & 7) == 0);
+            pa_assert((areas[0].step & 7)== 0);
 
-        /* We assume a single interleaved memory buffer */
-        pa_assert((areas[0].first >> 3) == 0);
-        pa_assert((areas[0].step >> 3) == u->frame_size);
+            /* We assume a single interleaved memory buffer */
+            pa_assert((areas[0].first >> 3) == 0);
+            pa_assert((areas[0].step >> 3) == u->frame_size);
 
-        p = (uint8_t*) areas[0].addr + (offset * u->frame_size);
+            p = (uint8_t*) areas[0].addr + (offset * u->frame_size);
 
-        chunk.memblock = pa_memblock_new_fixed(u->core->mempool, p, frames * u->frame_size, TRUE);
-        chunk.length = pa_memblock_get_length(chunk.memblock);
-        chunk.index = 0;
+            chunk.memblock = pa_memblock_new_fixed(u->core->mempool, p, frames * u->frame_size, TRUE);
+            chunk.length = pa_memblock_get_length(chunk.memblock);
+            chunk.index = 0;
 
-        pa_source_post(u->source, &chunk);
-        pa_memblock_unref_fixed(chunk.memblock);
+            pa_source_post(u->source, &chunk);
+            pa_memblock_unref_fixed(chunk.memblock);
 
-        if (PA_UNLIKELY((err = snd_pcm_mmap_commit(u->pcm_handle, offset, frames)) < 0)) {
+            if (PA_UNLIKELY((err = snd_pcm_mmap_commit(u->pcm_handle, offset, frames)) < 0)) {
 
-            if ((r = try_recover(u, "snd_pcm_mmap_commit", err)) == 0)
-                continue;
-            else if (r > 0)
-                return work_done;
+                if ((r = try_recover(u, "snd_pcm_mmap_commit", err)) == 0)
+                    continue;
 
-            return r;
-        }
+                return r;
+            }
 
-        work_done = 1;
+            work_done = 1;
 
-        u->frame_index += frames;
+            u->frame_index += frames;
 
-        pa_log_debug("read %lu frames", (unsigned long) frames);
+/*             pa_log_debug("read %lu frames", (unsigned long) frames); */
 
-        if (PA_LIKELY(frames >= (snd_pcm_uframes_t) n))
-            return work_done;
+            if (frames >= (snd_pcm_uframes_t) n)
+                break;
+
+            n -= frames;
+        }
     }
+
+    *sleep_usec = pa_bytes_to_usec(left_to_record, &u->source->sample_spec) - process_usec;
+    return work_done;
 }
 
-static int unix_read(struct userdata *u) {
+static int unix_read(struct userdata *u, pa_usec_t *sleep_usec) {
     int work_done = 0;
-    pa_bool_t checked_left_to_record = FALSE;
+    pa_usec_t max_sleep_usec, process_usec;
+    size_t left_to_record;
 
     pa_assert(u);
     pa_source_assert_ref(u->source);
 
+    if (u->use_tsched)
+        hw_sleep_time(u, &max_sleep_usec, &process_usec);
+
     for (;;) {
-        void *p;
-        snd_pcm_sframes_t n, frames;
+        snd_pcm_sframes_t n;
         int r;
-        pa_memchunk chunk;
 
         snd_pcm_hwsync(u->pcm_handle);
 
@@ -320,61 +352,69 @@ static int unix_read(struct userdata *u) {
 
             if ((r = try_recover(u, "snd_pcm_avail_update", n)) == 0)
                 continue;
-            else if (r > 0)
-                return work_done;
 
             return r;
         }
 
-        if (checked_left_to_record) {
-            check_left_to_record(u, n);
-            checked_left_to_record = TRUE;
-        }
+        left_to_record = check_left_to_record(u, n);
+
+        if (u->use_tsched)
+            if (pa_bytes_to_usec(left_to_record, &u->source->sample_spec) > max_sleep_usec/2)
+                break;
 
         if (PA_UNLIKELY(n <= 0))
             return work_done;
 
-        chunk.memblock = pa_memblock_new(u->core->mempool, (size_t) -1);
+        for (;;) {
+            void *p;
+            snd_pcm_sframes_t frames;
+            pa_memchunk chunk;
 
-        frames = pa_memblock_get_length(chunk.memblock) / u->frame_size;
+            chunk.memblock = pa_memblock_new(u->core->mempool, (size_t) -1);
 
-        if (frames > n)
-            frames = n;
+            frames = pa_memblock_get_length(chunk.memblock) / u->frame_size;
 
-        pa_log_debug("%lu frames to read", (unsigned long) n);
+            if (frames > n)
+                frames = n;
 
-        p = pa_memblock_acquire(chunk.memblock);
-        frames = snd_pcm_readi(u->pcm_handle, (uint8_t*) p, frames);
-        pa_memblock_release(chunk.memblock);
+/*             pa_log_debug("%lu frames to read", (unsigned long) n); */
 
-        pa_assert(frames != 0);
+            p = pa_memblock_acquire(chunk.memblock);
+            frames = snd_pcm_readi(u->pcm_handle, (uint8_t*) p, frames);
+            pa_memblock_release(chunk.memblock);
 
-        if (PA_UNLIKELY(frames < 0)) {
-            pa_memblock_unref(chunk.memblock);
+            pa_assert(frames != 0);
 
-            if ((r = try_recover(u, "snd_pcm_readi", n)) == 0)
-                continue;
-            else if (r > 0)
-                return work_done;
+            if (PA_UNLIKELY(frames < 0)) {
+                pa_memblock_unref(chunk.memblock);
 
-            return r;
-        }
+                if ((r = try_recover(u, "snd_pcm_readi", n)) == 0)
+                    continue;
 
-        chunk.index = 0;
-        chunk.length = frames * u->frame_size;
+                return r;
+            }
 
-        pa_source_post(u->source, &chunk);
-        pa_memblock_unref(chunk.memblock);
+            chunk.index = 0;
+            chunk.length = frames * u->frame_size;
 
-        work_done = 1;
+            pa_source_post(u->source, &chunk);
+            pa_memblock_unref(chunk.memblock);
 
-        u->frame_index += frames;
+            work_done = 1;
 
-        pa_log_debug("read %lu frames", (unsigned long) frames);
+            u->frame_index += frames;
 
-        if (PA_LIKELY(frames >= n))
-            return work_done;
+/*             pa_log_debug("read %lu frames", (unsigned long) frames); */
+
+            if (frames >= n)
+                break;
+
+            n -= frames;
+        }
     }
+
+    *sleep_usec = pa_bytes_to_usec(left_to_record, &u->source->sample_spec) - process_usec;
+    return work_done;
 }
 
 static void update_smoother(struct userdata *u) {
@@ -455,30 +495,6 @@ static int suspend(struct userdata *u) {
     return 0;
 }
 
-static pa_usec_t hw_sleep_time(struct userdata *u) {
-    pa_usec_t wm, usec;
-
-    pa_assert(u);
-
-    usec = pa_source_get_requested_latency_within_thread(u->source);
-
-    if (usec == (pa_usec_t) -1)
-        usec = pa_bytes_to_usec(u->hwbuf_size, &u->source->sample_spec);
-
-/*     pa_log_debug("hw buffer time: %u ms", (unsigned) (usec / PA_USEC_PER_MSEC)); */
-
-    wm = pa_bytes_to_usec(u->tsched_watermark, &u->source->sample_spec);
-
-    if (usec >= wm)
-        usec -= wm;
-    else
-        usec /= 2;
-
-/*     pa_log_debug("after watermark: %u ms", (unsigned) (usec / PA_USEC_PER_MSEC)); */
-
-    return usec;
-}
-
 static int update_sw_params(struct userdata *u) {
     snd_pcm_uframes_t avail_min;
     int err;
@@ -516,10 +532,10 @@ static int update_sw_params(struct userdata *u) {
     avail_min = 1;
 
     if (u->use_tsched) {
-        pa_usec_t usec;
+        pa_usec_t sleep_usec, process_usec;
 
-        usec = hw_sleep_time(u);
-        avail_min += pa_usec_to_bytes(usec, &u->source->sample_spec);
+        hw_sleep_time(u, &sleep_usec, &process_usec);
+        avail_min += pa_usec_to_bytes(sleep_usec, &u->source->sample_spec);
     }
 
     pa_log_debug("setting avail_min=%lu", (unsigned long) avail_min);
@@ -794,9 +810,11 @@ static int source_set_mute_cb(pa_source *s) {
 
 static void source_update_requested_latency_cb(pa_source *s) {
     struct userdata *u = s->userdata;
-
     pa_assert(u);
 
+    if (!u->pcm_handle)
+        return;
+
     update_sw_params(u);
 }
 
@@ -816,43 +834,42 @@ static void thread_func(void *userdata) {
     for (;;) {
         int ret;
 
-        pa_log_debug("loop");
+/*         pa_log_debug("loop"); */
 
         /* Read some data and pass it to the sources */
         if (PA_SOURCE_IS_OPENED(u->source->thread_info.state)) {
             int work_done = 0;
+            pa_usec_t sleep_usec;
 
             if (u->use_mmap)
-                work_done = mmap_read(u);
+                work_done = mmap_read(u, &sleep_usec);
             else
-                work_done = unix_read(u);
+                work_done = unix_read(u, &sleep_usec);
 
             if (work_done < 0)
                 goto fail;
 
-            pa_log_debug("work_done = %i", work_done);
+/*             pa_log_debug("work_done = %i", work_done); */
 
             if (work_done)
                 update_smoother(u);
 
             if (u->use_tsched) {
-                pa_usec_t usec, cusec;
+                pa_usec_t cusec;
 
                 /* OK, the capture buffer is now empty, let's
                  * calculate when to wake up next */
 
-                usec = hw_sleep_time(u);
-
-                pa_log_debug("Waking up in %0.2fms (sound card clock).", (double) usec / PA_USEC_PER_MSEC);
+/*                 pa_log_debug("Waking up in %0.2fms (sound card clock).", (double) sleep_usec / PA_USEC_PER_MSEC); */
 
                 /* Convert from the sound card time domain to the
                  * system time domain */
-                cusec = pa_smoother_translate(u->smoother, pa_rtclock_usec(), usec);
+                cusec = pa_smoother_translate(u->smoother, pa_rtclock_usec(), sleep_usec);
 
-                pa_log_debug("Waking up in %0.2fms (system clock).", (double) cusec / PA_USEC_PER_MSEC);
+/*                 pa_log_debug("Waking up in %0.2fms (system clock).", (double) cusec / PA_USEC_PER_MSEC); */
 
                 /* We don't trust the conversion, so we wake up whatever comes first */
-                pa_rtpoll_set_timer_relative(u->rtpoll, PA_MIN(usec, cusec));
+                pa_rtpoll_set_timer_relative(u->rtpoll, PA_MIN(sleep_usec, cusec));
             }
         } else if (u->use_tsched)
 
@@ -887,7 +904,7 @@ static void thread_func(void *userdata) {
                 snd_pcm_start(u->pcm_handle);
             }
 
-            if (revents)
+            if (revents && u->use_tsched)
                 pa_log_debug("Wakeup from ALSA! (%i)", revents);
         }
     }

commit 3aadad12a08b8d976dabfeb5be3774be2e32a981
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu May 15 23:25:11 2008 +0000

    update protocol spec
    
    git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2444 fefdeb5f-60dc-0310-8127-8f9354f1896f

diff --git a/PROTOCOL b/PROTOCOL
index 74c08b4..4439c71 100644
--- a/PROTOCOL
+++ b/PROTOCOL
@@ -84,6 +84,7 @@ New opcodes for notifications:
 New fields for PA_COMMAND_CREATE_PLAYBACK_STREAM, PA_COMMAND_CREATE_RECORD_STREAM request at the end:
 
  peak_detect (bool)
+ adjust_latency  (bool)
 
 Replace field "name" for PA_COMMAND_CREATE_PLAYBACK_STREAM, PA_COMMAND_CREATE_RECORD_STREAM at the end:
 
@@ -124,3 +125,12 @@ New field for PA_COMMAND_CREATE_PLAYBACK_STREAM at the end:
 
 Buffer attributes for PA_COMMAND_CREATE_PLAYBACK_STREAM and
 PA_COMMAND_CREATE_RECORD_STREAM may now be 0 for default values.
+
+New filed for PA_COMMAND_SET_PLAYBACK_STREAM_BUFFER_ATTR,
+PA_COMMAND_SET_RECORD_STREAM_BUFFER_ATTR at the end:
+
+  adjust_latency (bool)
+
+new message:
+
+  PA_COMMAND_STARTED

commit 1a3984cb4c517a0b9e04c82c002c993be9483d93
Merge: 8885ddf... 3e314b7...
Author: CJ van den Berg <cj at vdbonline.com>
Date:   Mon Jun 23 16:09:08 2008 +0200

    Merge dead branch 'prepare-0.9.10'


commit a87ba420698b7f58d8eaa9236bb01bf11558ed35
Merge: 1a3984c... e1f008f...
Author: CJ van den Berg <cj at vdbonline.com>
Date:   Mon Jun 23 16:09:58 2008 +0200

    Merge dead branch 'liboil-test'


commit 63c1eb14d889fe052afad16dfc470802cc48bb4a
Merge: a87ba42... 34e81ff...
Author: CJ van den Berg <cj at vdbonline.com>
Date:   Mon Jun 23 16:10:18 2008 +0200

    Merge dead branch 'ossman'


commit 0be9bc21d57bdbd18806ceae03289a0bde636e30
Merge: 63c1eb1... d664492...
Author: CJ van den Berg <cj at vdbonline.com>
Date:   Mon Jun 23 16:10:41 2008 +0200

    Merge dead branch 'lockfree'


commit 126e4cf89f5ccfe393e60a930c88ab513eeee085
Merge: 0be9bc2... 575541d...
Author: CJ van den Berg <cj at vdbonline.com>
Date:   Mon Jun 23 16:10:58 2008 +0200

    Merge dead branch 'lennart'


commit 1562671b9b3048759b210a329764fac8880b62dd
Merge: 126e4cf... 3aadad1...
Author: CJ van den Berg <cj at vdbonline.com>
Date:   Mon Jun 23 16:11:20 2008 +0200

    Merge dead branch 'glitch-free'


commit ac032549cd7eba9459f1fcd8983f1d513913f14f
Merge: 398514f... 1562671...
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Jun 24 02:16:49 2008 +0200

    Merge branch 'master' of git://git.debian.org/git/pkg-pulseaudio/pulseaudio-upstream


-- 
hooks/post-receive
PulseAudio Sound Server



More information about the pulseaudio-commits mailing list