[pulseaudio-commits] [SCM] PulseAudio Sound Server branch, master-tx, updated. v0.9.13-11-g5925d44

Lennart Poettering gitmailer-noreply at 0pointer.de
Tue Oct 7 12:38:34 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-tx branch has been updated
      from  8c2a7c8707a556e4891383bc1786958304828dd9 (commit)

- Log -----------------------------------------------------------------
5925d44... Merge commit 'origin/master-tx' into master-tx
3d7b76d... Unload module-bluetooth-device if the remote device disconnects.
c8a963a... Initialize exit_idle_time to -1 instead of 0  when in system mode.
fa93cb7... make distcheck pass
e26ffc9... Merge branch 'master' of ssh://rootserver/home/lennart/git/public/pulseaudio
be667af... Merge branch 'master' of ssh://rootserver/home/lennart/git/public/pulseaudio
0274651... bump version and sonames
f64d6af... Merge commit 'vudentz/master'
aa43739... make sure we send a started messages when we are uncorking
5996f59... update module-tunnel for recent protocol changes
f728e9c... disable valgrind macro usage for now since valgrind generates a lot of spurious warnings as it seems
6d52a41... add missing include
a9c1bb3... substract the unused record buffer size from the overall size before calculating the space still left for recording
83b1d7a... get rid of pa_alsa_volume_divide() since we have pa_sw_volume_divide() now
da4ad5e... implement pa_sw_volume_divide() and pa_sw_cvolume_divide()
87c8132... increase suspend timeout to 5s so that it is always longer then the default tsched buffer size of 2s
530b95f... don't call snd_pcm_drain() when we suspend because that might take awfully long with our long buffer sizes these days
88130eb... add missing inclusion
82c46f2... do not cleanup staticly allocated memory unless we are in valgrind mode
3c19352... show valgrind status on startup
9b00664... instead of checking for  directly use new function pa_in_valgrind()
8222f12... add new API function pa_in_valgrind() to check for
fef63d7... Fix loading module-bluetooth-device with an invalid parameter.
0c998b0... Replace handlers of deprecated Connected signals with new PropertyChanged.
b205fcc... Cleanup module-bluetooth-discover.
20f68bc... Fix Connected signal handler.
04677cb... Fix match rule problems.
0be845f... Remove PropertyChanged signal handler.
3b427b7... Add signal handlers for Connected signals.
443ea47... Add match rules for org.bluez.Headset and org.bluez.AudioSink.
7a1a147... rename pa_cvolume_snprint_dB to pa_sw_cvolume_snprint_dB since it is useful only for software volumes
c0815de... allow - in sample names
28af994... increase PA_CVOLUME_SNPRINT_MAX to a proper value and document that it is not considered part of the ABI
bde142c... when checking the validity of a cvolume check whether all values are not -1
c0a9e8b... add missing calls to map file
ebb2ecb... add new API call pa_cvolume_compatible()
619ed8a... add new API call pa_cvolume_snprint_dB()
be77bcd... add new API call pa_cvolume_init()
db975c7... extend documentation for pa_channel_map_init()
2367212... make a few casts explicit to remove compiler warnings
7c2cb77... a bit of late pa_bool_t'ization
d56f375... treat a channel map only then as compatible with a sample spec if it is valid
8919898... add new API function pa_sample_spec_init()
8a50105... if a volume or channel map is invalid show so when printing it
33b186e... user lrint() and friends in inner loops instead of normal C casts to speed up a few things
1bb5e58... use PA_FLOAT32_SWAP where useful
7d442e3... optimize mixing routines a bit by pulling the multiplication with the global volume out of the inner loop by applying it first to the per-stream volumes
a0f4ffd... make sure we call pa_sink_process_rewind() if a rewind was requested under all circumstances
ea82dec... when we mix into a 16bit accumulator make sure we clamp before we scale with a volume to avoid range faults when multiplying
08cf9db... properly parse response to pa_stream_set_buffer_attr() calls. closes #370
54afcf2... inform dsp_empty_socket() *after* we emptied the dsp socket, that it is now empty
9f5d052... make simple protocol not crash when allocating a memory block
cf3f80e... when killing gconf helper, loop over EINTR
ea15ca9... PA_WARN_REFERENCE works only for ELF targets
3853070... don't hit an assert if a kernel driver reports invalid dB information, instead just warn the user
5d18b62... remove useless log message
4b67ea1... remove useless log message, re #367
99acad7... fix support for ALSA devices which lack dB information
c4bdc2f... it's --daemonize, not --daemon
9e79c87... Merge commit 'coling/master'
644f39d... a few FreeBSD fixes, from alexis
f04cfcd... replace module-volume-restore by module-stream-restore in system mode, too
6d74504... it might be a bit too early to initialize bluetooth by default for now, since it's still very rough around the edges
0c3eb9f... fix typo in default.conf, closes bug #354
00b70a8... follow PropertyChanged signals from BlueZ
d299ac5... Some man page updates, add missing documentation, other fixes.
79ad4e6... Make the shared memory segment size configurable
a84b72b... esound auth-ip-acl fix
564ef2b... have make_random_dir respect $TMPDIR
f5c301d... make module-bluetooth-discover actually load modules and smaller other fixes
3f4bc03... all kinds of minor type, memory leak, initializatio fixes
a35f84a... instead of failing when the requested sampling rate is not available find the next one that is higher
aa1974b... Use the same module parameter names for module-bluetooth-device as for most other modules
7923731... use TRUE for pa_bool_t arguments
60e9744... remove a few compiler warnings in BlueZ code
87971c8... fix compilation errors in priority queue code
9adf7c5... ignore bt proximity helper
3ad8c04... add a generic priority queue implementation
3e16d2f... make pa_idxset_trivial_compare_func() do a full compare instea of just equakity check
183f2e0... some minor fixes and cleanups in the bt code
6188737... make sure ~/.pulse exists before we create the runtime dir link beneath it
d68c2c9... replace Makefile stub copies by symlinks
8257214... enable bluetooth by default
c0a1706... downgrade a D-Bus log message to debug
db955e8... add trivial redirecting makefile to bt dir
4ae124b... Move bluetooth proximity module to src/modules/bluetooth/
8b02c2f... Change all int vars that doesn't allow negative values to uint
78a3c72... Move bluetooth discover and device modules to src/modules/bluetooth
76bae38... Cleanup some code
6093e32... Remove some warnings
02a9273... Free mempool
447e027... Fix "file not found" error on load of module-bt-device for Ubuntu Intrepid Ibex
8769bf4... Merge A2DP and SCO thread functions
199bdf2... Add some more device properties to the sink properties list
e2f3a86... Remove check for SIOCOUTQ and add proper includes
dc4f796... Use union instead of different pointer types to the same memory area to make the code C99 compliant
d1cc632... Move render and write to the fd to a separate function
88a21e9... Change MIN/MAX to PA_MIN/PA_MAX
27bc1ea... Remove unnecessary initialization of getcaps_req->flags
027940b... Remove u->channels and u->rates, since it's redundant info
0e81757... Fix some memory leaking
e752cac... Change sbc_initialized to pa_bool_t
708905c... pa__done for module-bt-device
61013fb... Fix some debug messages and other cosmetic changes
e570767... Refactor a2dp thread execution flow and improve time estimation
2f455bf... A2DP poorly working
c89301d... Fix sample size
e545479... Fix block_size calculation
b5c4d2e... Configure bt connection for a2dp
85a931f... Get rid of hw_constraint function. It's code now lives inside bt_setconf().
77138dd... Change default sink name to bluetooth_sink
6c10b10... Try to improve time estimation
123ba4f... Fix handling of PA_SINK_MESSAGE_GET_LATENCY
0d37b91... Remove PA_SINK_NETWORK flag and move the passage of streamfd to the rt thread just before the thread creation
435eb07... Change pa_sink_render to pa_sink_render_into_full and remove some unnecessary checks on the rt thread
2e51b93... Make stream socket non-blocking
71f1d68... Fix block size for SCO
fcd7dc1... Add include for core-util.h
eb1e308... Initialize rtpoll_item
0519e5d... Add include for sample.h
d48961f... Change close() to pa_close()
b4ded21... Change strerror() to pa_cstrerror()
16d5aab... Get rid of SINK_MESSAGE_PASS_SOCKET, since we don't really need it
aa310a4... Changes for pa_modargs_get_value_u32 for integer arguments and correct some error messages
0396a60... Copy arguments values instead of just getting a pointer for them
f992296... Hand the stream socket to the rt thread
255f9b0... Initial code for rt thread
b8b761a... Fix PA_USEC_PER_SEC missing
a3f0756... BlueZ connection configuration done
e7b0839... Adds SBC Codec to pa tree
c62c2ff... Add module-bt-device and dependencies to automake
ee68292... Initial file for module-bt-device
d8a0ec5... Add code from bluez/audio/ipc.[ch]
ffe76a2... Add sender=org.bluez to dbus add match
fe8bd53... Remove modargs, since module-bt-discover doesn't have any argument
1e03c32... Refactor all linked lists to use pulsecore/llist.h
d893a1f... Remove block delimiters from single line if blocks
cadc666... Remove some unused vars and labels
a69c020... Change booleans to pa_bool_t
d90bb18... We don't need call_dbus_method anymore
9907b46... Don't need to explicity check if hcid is running anymore
2b68562... Improve dbus communication
e5d25e0... Changing all private functions to static
3909d9b... Remove VERBOSE definition
c9f5659... Adding dynamic bluetooth audio devices detection
314dade... Fix the symdef include
6fccd58... Fix comparison of strings of different case
9d18b90... Adding module-bt-discover to Makefile.am
8b511f5... Adding module-bt-discover
2ab4bb7... fix pa_stream_set_name
f6670a1... stream_started_callback userdata bug
636b520... fix S32 validity check
cd704f8... Linking fix for rtclock on libpulsedsp
-----------------------------------------------------------------------

Summary of changes:
 configure.ac                                       |    6 +-
 man/pulse-client.conf.5.xml.in                     |   19 +-
 man/pulse-daemon.conf.5.xml.in                     |   51 +-
 man/pulseaudio.1.xml.in                            |    2 +-
 po/POTFILES.in                                     |    4 +-
 po/de.po                                           |  552 ++++----
 po/el.po                                           |  138 ++-
 po/fr.po                                           |  175 ++-
 po/pl.po                                           |   90 +-
 po/pt_BR.po                                        |  490 ++++---
 po/sv.po                                           |  357 +++---
 src/.gitignore                                     |    3 +-
 src/Makefile.am                                    |   71 +-
 src/daemon/caps.c                                  |    5 +-
 src/daemon/daemon-conf.c                           |   36 +-
 src/daemon/daemon-conf.h                           |    1 +
 src/daemon/daemon.conf.in                          |    3 +-
 src/daemon/default.pa.in                           |    5 +
 src/daemon/main.c                                  |    8 +-
 src/daemon/system.pa.in                            |    5 +-
 src/map-file                                       |    4 +
 src/modules/alsa-util.c                            |   24 -
 src/modules/alsa-util.h                            |    2 -
 src/modules/bluetooth/Makefile                     |    1 +
 src/modules/bluetooth/ipc.c                        |  118 ++
 src/modules/bluetooth/ipc.h                        |  308 +++++
 src/modules/bluetooth/module-bluetooth-device.c    |  922 +++++++++++++
 src/modules/bluetooth/module-bluetooth-discover.c  |  543 ++++++++
 .../module-bluetooth-proximity.c}                  |    4 +-
 .../proximity-helper.c}                            |    0 
 src/modules/bluetooth/rtp.h                        |   76 ++
 src/modules/bluetooth/sbc.c                        | 1411 ++++++++++++++++++++
 src/modules/bluetooth/sbc.h                        |   97 ++
 src/modules/bluetooth/sbc_math.h                   |   72 +
 src/modules/bluetooth/sbc_tables.h                 |  167 +++
 src/modules/gconf/Makefile                         |   14 +-
 src/modules/gconf/module-gconf.c                   |   12 +-
 src/modules/module-alsa-sink.c                     |  101 +-
 src/modules/module-alsa-source.c                   |  105 +-
 src/modules/module-null-sink.c                     |    9 +-
 src/modules/module-protocol-stub.c                 |    2 +-
 src/modules/module-suspend-on-idle.c               |    2 +-
 src/modules/module-tunnel.c                        |    9 +-
 src/modules/rtp/Makefile                           |   14 +-
 src/modules/rtp/module-rtp-recv.c                  |    2 +-
 src/pulse/channelmap.c                             |   13 +
 src/pulse/channelmap.h                             |   10 +-
 src/pulse/client-conf.c                            |    3 +
 src/pulse/client-conf.h                            |    1 +
 src/pulse/client.conf.in                           |    1 +
 src/pulse/context.c                                |    4 +-
 src/pulse/introspect.c                             |    2 +
 src/pulse/sample.c                                 |   12 +-
 src/pulse/sample.h                                 |   11 +-
 src/pulse/stream.c                                 |   21 +-
 src/pulse/volume.c                                 |  110 ++-
 src/pulse/volume.h                                 |   44 +-
 src/pulsecore/conf-parser.c                        |   18 +
 src/pulsecore/conf-parser.h                        |    3 +-
 src/pulsecore/core-scache.c                        |   31 +-
 src/pulsecore/core-util.c                          |   54 +-
 src/pulsecore/core-util.h                          |   13 +
 src/pulsecore/core.c                               |    8 +-
 src/pulsecore/core.h                               |    2 +-
 src/pulsecore/flist.h                              |    3 +
 src/pulsecore/idxset.c                             |    2 +-
 src/pulsecore/log.c                                |    3 +
 src/pulsecore/macro.h                              |    2 +-
 src/pulsecore/memblock.c                           |   36 +-
 src/pulsecore/memblock.h                           |    2 +-
 src/pulsecore/namereg.c                            |    3 +-
 src/pulsecore/namereg.h                            |    2 +-
 src/pulsecore/prioq.c                              |  256 ++++
 src/pulsecore/prioq.h                              |   64 +
 src/pulsecore/proplist-util.c                      |    2 +-
 src/pulsecore/protocol-native.c                    |    6 +
 src/pulsecore/protocol-simple.c                    |   12 +-
 src/pulsecore/sample-util.c                        |  197 ++--
 src/pulsecore/sconv-s16le.c                        |   20 +-
 src/pulsecore/sconv.c                              |    4 +-
 src/pulsecore/sink-input.c                         |    3 +
 src/pulsecore/sink.c                               |    1 -
 src/pulsecore/thread.h                             |    3 +
 src/pulsecore/time-smoother.c                      |    8 +-
 src/tests/envelope-test.c                          |    2 +-
 src/tests/mcalign-test.c                           |    2 +-
 src/tests/memblock-test.c                          |    6 +-
 src/tests/memblockq-test.c                         |    2 +-
 src/tests/mix-test.c                               |    8 +-
 src/tests/prioq-test.c                             |   44 +
 src/tests/remix-test.c                             |    2 +-
 src/tests/resampler-test.c                         |    2 +-
 src/tests/voltest.c                                |   12 +
 src/utils/padsp.c                                  |   13 +-
 94 files changed, 5932 insertions(+), 1191 deletions(-)
 create mode 120000 src/modules/bluetooth/Makefile
 create mode 100644 src/modules/bluetooth/ipc.c
 create mode 100644 src/modules/bluetooth/ipc.h
 create mode 100644 src/modules/bluetooth/module-bluetooth-device.c
 create mode 100644 src/modules/bluetooth/module-bluetooth-discover.c
 rename src/modules/{module-bt-proximity.c => bluetooth/module-bluetooth-proximity.c} (99%)
 rename src/modules/{bt-proximity-helper.c => bluetooth/proximity-helper.c} (100%)
 create mode 100644 src/modules/bluetooth/rtp.h
 create mode 100644 src/modules/bluetooth/sbc.c
 create mode 100644 src/modules/bluetooth/sbc.h
 create mode 100644 src/modules/bluetooth/sbc_math.h
 create mode 100644 src/modules/bluetooth/sbc_tables.h
 mode change 100644 => 120000 src/modules/gconf/Makefile
 mode change 100644 => 120000 src/modules/rtp/Makefile
 create mode 100644 src/pulsecore/prioq.c
 create mode 100644 src/pulsecore/prioq.h
 create mode 100644 src/tests/prioq-test.c

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

commit cd704f8a84635bc6ea152d44d2dd183c22157d36
Author: Colin Guthrie <pulse at colin.guthr.ie>
Date:   Sat Sep 6 12:25:46 2008 +0100

    Linking fix for rtclock on libpulsedsp

diff --git a/src/Makefile.am b/src/Makefile.am
index 3ee5372..22e691f 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -654,7 +654,7 @@ bin_SCRIPTS += utils/padsp
 
 endif
 
-libpulsedsp_la_SOURCES = utils/padsp.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)
+libpulsedsp_la_SOURCES = utils/padsp.c pulsecore/core-util.c pulsecore/core-util.h pulsecore/core-error.c pulsecore/core-error.h  pulsecore/log.c pulsecore/log.h pulsecore/rtclock.c pulsecore/rtclock.h pulsecore/once.c pulsecore/once.h $(PA_THREAD_OBJS)
 libpulsedsp_la_CFLAGS = $(AM_CFLAGS)
 libpulsedsp_la_LIBADD = $(AM_LIBADD) libpulse.la
 libpulsedsp_la_LDFLAGS = -avoid-version

commit 636b520d745397841373bdf4112e24ff443c0359
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Sep 10 12:18:05 2008 +0300

    fix S32 validity check

diff --git a/src/pulse/stream.c b/src/pulse/stream.c
index d0c7d67..5be6007 100644
--- a/src/pulse/stream.c
+++ b/src/pulse/stream.c
@@ -86,7 +86,7 @@ pa_stream *pa_stream_new_with_proplist(
     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, c->version >= 12 || (ss->format != PA_SAMPLE_S32LE || ss->format != PA_SAMPLE_S32NE), PA_ERR_NOTSUPPORTED);
+    PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 12 || (ss->format != PA_SAMPLE_S32LE && ss->format != PA_SAMPLE_S32BE), 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 || (p && pa_proplist_contains(p, PA_PROP_MEDIA_NAME)), PA_ERR_INVALID);
 

commit f6670a1f2e0407e22226713bdf6fc6db68383b68
Author: Arthur Taylor <theycallhimart at gmail.com>
Date:   Tue Sep 9 20:28:20 2008 -0700

    stream_started_callback userdata bug
    
    Hello
    
    I came across a bug where the userdata parameter of the
    stream_started_callback was always NULL in some cases. I couldn't seem
    to make a ticket, so here's the one line patch:
    
    Signed-off-by: Lennart Poettering <lennart at poettering.net>

diff --git a/src/pulse/stream.c b/src/pulse/stream.c
index 5be6007..6890b7a 100644
--- a/src/pulse/stream.c
+++ b/src/pulse/stream.c
@@ -557,7 +557,7 @@ void pa_command_stream_started(pa_pdispatch *pd, uint32_t command, uint32_t tag,
     request_auto_timing_update(s, TRUE);
 
     if (s->started_callback)
-        s->started_callback(s, s->suspended_userdata);
+        s->started_callback(s, s->started_userdata);
 
 finish:
     pa_context_unref(c);

commit 2ab4bb76b217e481cf28cff0138726d9a7672895
Author: Omair Majid <omajid at redhat.com>
Date:   Wed Sep 10 17:07:50 2008 -0400

    fix pa_stream_set_name
    
    This patch fixes a bug in pa_stream_set_name. It uses the media.name
    property instead of the application.name property when setting a
    stream's name
    
    >From aa1bda11d2084365cb0cec57f37d59f07ab80052 Mon Sep 17 00:00:00 2001
    From: Omair Majid <omajid at redhat.com>
    Date: Wed, 10 Sep 2008 17:02:28 -0400
    Subject: [PATCH] Fix bug in pa_stream_set_name
    
    Signed-off-by: Lennart Poettering <lennart at poettering.net>

diff --git a/src/pulse/stream.c b/src/pulse/stream.c
index 6890b7a..ababe17 100644
--- a/src/pulse/stream.c
+++ b/src/pulse/stream.c
@@ -1851,7 +1851,7 @@ pa_operation* pa_stream_set_name(pa_stream *s, const char *name, pa_stream_succe
     if (s->context->version >= 13) {
         pa_proplist *p = pa_proplist_new();
 
-        pa_proplist_sets(p, PA_PROP_APPLICATION_NAME, name);
+        pa_proplist_sets(p, PA_PROP_MEDIA_NAME, name);
         o = pa_stream_proplist_update(s, PA_UPDATE_REPLACE, p, cb, userdata);
         pa_proplist_free(p);
     } else {

commit 8b511f55985c4c881f34a2bd625450dee3dc7c4a
Author: João Paulo Rechi Vita <joao.vita at gmail.com>
Date:   Thu Jul 17 16:29:49 2008 -0300

    Adding module-bt-discover

diff --git a/src/modules/module-bt-discover.c b/src/modules/module-bt-discover.c
new file mode 100644
index 0000000..f855ad1
--- /dev/null
+++ b/src/modules/module-bt-discover.c
@@ -0,0 +1,461 @@
+/* TODO LIST
+ * listen to signals AdapterAdded, AdapterRemoved, DeviceCreated and DeviceRemoved
+ * listen to org.freedesktop.DBus.NameOwnerChanged, to properly handle hcid activity
+ */
+
+/***
+    This file is part of PulseAudio.
+
+    Copyright 2008 Joao Paulo Rechi Vita
+
+    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 <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <pulse/xmalloc.h>
+#include <pulsecore/module.h>
+#include <pulsecore/modargs.h>
+
+#include "dbus-util.h"
+/* TODO: Create symdef file for static linking
+ * #include "module-bt-proximity-symdef.h" */
+
+PA_MODULE_AUTHOR("Joao Paulo Rechi Vita");
+PA_MODULE_DESCRIPTION("Detect available bluetooth audio devices and load bluetooth audio drivers");
+PA_MODULE_VERSION(PACKAGE_VERSION);
+PA_MODULE_USAGE("");
+
+#define AUDIO_DEVICE_INTERFACE  "org.bluez.audio.Device"
+#define GENERIC_AUDIO_UUID      "00001203-0000-1000-8000-00805F9B34FB"
+#define HSP_HS_UUID             "00001108-0000-1000-8000-00805F9B34FB"
+#define HSP_AG_UUID             "00001112-0000-1000-8000-00805F9B34FB"
+#define HFP_HS_UUID             "0000111E-0000-1000-8000-00805F9B34FB"
+#define HFP_AG_UUID             "0000111F-0000-1000-8000-00805F9B34FB"
+#define ADVANCED_AUDIO_UUID     "0000110D-0000-1000-8000-00805F9B34FB"
+#define A2DP_SOURCE_UUID        "0000110A-0000-1000-8000-00805F9B34FB"
+#define A2DP_SINK_UUID          "0000110B-0000-1000-8000-00805F9B34FB"
+#define AVRCP_REMOTE_UUID       "0000110E-0000-1000-8000-00805F9B34FB"
+#define AVRCP_TARGET_UUID       "0000110C-0000-1000-8000-00805F9B34FB"
+
+#define VERBOSE 1
+
+typedef struct adapter adapter_t;
+typedef struct device device_t;
+typedef struct uuid uuid_t;
+
+struct uuid {
+    char *uuid;
+    uuid_t *next;
+};
+
+struct device {
+    char *name;
+    char *object_path;
+    int paired;
+    adapter_t *adapter;
+    char *alias;
+    int connected;
+    uuid_t *uuid_list;
+    char *address;
+    int class;
+    int trusted;
+    device_t *next;
+};
+
+struct adapter {
+    char *object_path;
+    char *mode;
+    char *address;
+    device_t *device_list;
+    adapter_t *next;
+};
+
+struct userdata {
+    pa_module *module;
+    pa_dbus_connection *conn;
+    adapter_t *adapter_list;
+};
+
+uuid_t *uuid_new(const char *uuid) {
+    uuid_t *node = pa_xnew0(uuid_t, 1);
+    node->uuid = pa_xstrdup(uuid);
+    node->next = NULL;
+    return node;
+}
+
+void uuid_list_append(uuid_t *node, const char *uuid) {
+    while (node->next != NULL) node = node->next;
+    node->next = uuid_new(uuid);
+}
+
+device_t *device_new(const char *device, adapter_t *adapter) {
+    device_t *node = pa_xnew0(device_t, 1);
+    node->name = NULL;
+    node->object_path = pa_xstrdup(device);
+    node->paired = -1;
+    node->adapter = adapter;
+    node->alias = NULL;
+    node->connected = -1;
+    node->uuid_list = uuid_new("UUID_HEAD");
+    node->address = NULL;
+    node->class = -1;
+    node->trusted = -1;
+    node->next = NULL;
+    return node;
+}
+
+void device_list_append(device_t *node, const char *device, adapter_t *adapter) {
+    while (node->next != NULL) node = node->next;
+    node->next = device_new(device, adapter);
+}
+
+adapter_t *adapter_new(const char *adapter) {
+    adapter_t *node = pa_xnew0(adapter_t, 1);
+    node->object_path = pa_xstrdup(adapter);
+    node->mode = NULL;
+    node->address = NULL;
+    node->device_list = device_new("/DEVICE_HEAD", NULL);
+    node->next = NULL;
+    return node;
+}
+
+void adapter_list_append(adapter_t *node, const char *adapter) {
+    while (node->next != NULL) node = node->next;
+    node->next = adapter_new(adapter);
+}
+
+void print_devices(device_t *device_list) {
+    device_t *device_list_i = device_list;
+    while (device_list_i != NULL) {
+        uuid_t *uuid_list_i = device_list_i->uuid_list;
+        if (strcmp(device_list_i->object_path, "/DEVICE_HEAD") != 0) {
+            pa_log("    [ %s ]", device_list_i->object_path);
+            pa_log("        Name = %s", device_list_i->name);
+            pa_log("        Paired = %d", device_list_i->paired);
+            pa_log("        Adapter = %s", device_list_i->adapter->object_path);
+            pa_log("        Alias = %s", device_list_i->alias);
+            pa_log("        Connected = %d", device_list_i->connected);
+            pa_log("        UUIDs = ");
+            while (uuid_list_i != NULL) {
+                if (strcmp(uuid_list_i->uuid, "UUID_HEAD") != 0) {
+                    pa_log("            %s", uuid_list_i->uuid);
+                }
+                uuid_list_i = uuid_list_i->next;
+            }
+            pa_log("        Address = %s", device_list_i->address);
+            pa_log("        Class = 0x%x", device_list_i->class);
+            pa_log("        Trusted = %d", device_list_i->trusted);
+        }
+        device_list_i = device_list_i->next;
+    }
+}
+
+void print_adapters(adapter_t *adapter_list) {
+    adapter_t *adapter_list_i = adapter_list;
+    while (adapter_list_i != NULL) {
+        if (strcmp(adapter_list_i->object_path, "/ADAPTER_HEAD") != 0) {
+            pa_log("[ %s ]", adapter_list_i->object_path);
+            pa_log("    Mode = %s", adapter_list_i->mode);
+            pa_log("    Address = %s", adapter_list_i->address);
+            print_devices(adapter_list_i->device_list);
+        }
+        adapter_list_i = adapter_list_i->next;
+    }
+}
+
+DBusMessageIter call_dbus_method(pa_dbus_connection *conn, const char *destination, const char *path, const char *interface,
+        const char *method) {
+    DBusMessage *msg;
+    DBusPendingCall *pending;
+    DBusMessageIter args;
+
+    /* construct the DBusMessage */
+    msg = dbus_message_new_method_call(destination, path, interface, method);
+
+    /* send the message and get a handle for a reply */
+    if (!dbus_connection_send_with_reply(pa_dbus_connection_get(conn), msg, &pending, -1)) { 
+        pa_log("Out Of Memory!"); 
+    }
+    if (pending == NULL) { 
+        pa_log("Pending Call Null"); 
+    }
+    dbus_connection_flush(pa_dbus_connection_get(conn));
+
+    /* free msg */
+    dbus_message_unref(msg);
+
+    /* wait for reply */
+    dbus_pending_call_block(pending);
+
+    /* get the reply */
+    msg = dbus_pending_call_steal_reply(pending);
+    if (msg == NULL) {
+        pa_log("Reply Null");
+    }
+
+    /* free pending */
+    dbus_pending_call_unref(pending);
+
+    /* read the reply */
+    if (!dbus_message_iter_init(msg, &args))
+        pa_log("Reply has no arguments");
+
+    dbus_message_unref(msg);
+
+    return args;
+
+}
+
+void detect_adapters(adapter_t *adapter_list, pa_dbus_connection *conn) {
+    DBusMessageIter arg_i, element_i, dict_i, variant_i;
+    adapter_t *adapter_list_i;
+    const char *key, *value;
+
+    /* get adapters */
+    arg_i = call_dbus_method(conn, "org.bluez", "/", "org.bluez.Manager", "ListAdapters");
+    dbus_message_iter_recurse(&arg_i, &element_i);
+    while (dbus_message_iter_get_arg_type(&element_i) != DBUS_TYPE_INVALID) {
+        if (dbus_message_iter_get_arg_type(&element_i) == DBUS_TYPE_OBJECT_PATH) {
+            dbus_message_iter_get_basic(&element_i, &value);
+            adapter_list_append(adapter_list, value);
+        }
+        dbus_message_iter_next(&element_i);
+    }
+
+    /* get adapter properties */
+    adapter_list_i = adapter_list->next;
+    while (adapter_list_i != NULL) {
+        arg_i = call_dbus_method(conn, "org.bluez", adapter_list_i->object_path, "org.bluez.Adapter", "GetProperties");
+        dbus_message_iter_recurse(&arg_i, &element_i);
+        while (dbus_message_iter_get_arg_type(&element_i) != DBUS_TYPE_INVALID) {
+            if (dbus_message_iter_get_arg_type(&element_i) == DBUS_TYPE_DICT_ENTRY) {
+                dbus_message_iter_recurse(&element_i, &dict_i);
+                dbus_message_iter_get_basic(&dict_i, &key);
+                dbus_message_iter_next(&dict_i);
+                dbus_message_iter_recurse(&dict_i, &variant_i);
+                dbus_message_iter_get_basic(&variant_i, &value);
+                if (strcmp(key, "Mode") == 0) {
+                    adapter_list_i->mode = pa_xstrdup(value);
+                }
+                else if (strcmp(key, "Address") == 0) {
+                    adapter_list_i->address = pa_xstrdup(value);
+                }
+            }
+            dbus_message_iter_next(&element_i);
+        }
+        adapter_list_i = adapter_list_i->next;
+    }
+}
+
+void detect_devices(adapter_t *adapter_list, pa_dbus_connection *conn) {
+    DBusMessageIter arg_i, element_i, dict_i, variant_i;
+    adapter_t *adapter_list_i;
+    device_t *device_list_i, *device_list_prev_i;
+    const char *key, *value;
+    unsigned int uvalue;
+
+    /* get devices of each adapter */
+    adapter_list_i = adapter_list->next;
+    while (adapter_list_i != NULL) {
+        arg_i = call_dbus_method(conn, "org.bluez", adapter_list_i->object_path , "org.bluez.Adapter", "ListDevices");
+        dbus_message_iter_recurse(&arg_i, &element_i);
+        while (dbus_message_iter_get_arg_type(&element_i) != DBUS_TYPE_INVALID) {
+            if (dbus_message_iter_get_arg_type(&element_i) == DBUS_TYPE_OBJECT_PATH) {
+                dbus_message_iter_get_basic(&element_i, &value);
+                device_list_append(adapter_list_i->device_list, value, adapter_list_i);
+            }
+            dbus_message_iter_next(&element_i);
+        }
+        adapter_list_i = adapter_list_i->next;
+    }
+
+    /* get device properties */
+    adapter_list_i = adapter_list->next;
+    while (adapter_list_i != NULL) {
+        device_list_prev_i = adapter_list_i->device_list;
+        device_list_i = adapter_list_i->device_list->next;
+        while (device_list_i != NULL) {
+            arg_i = call_dbus_method(conn, "org.bluez", device_list_i->object_path, "org.bluez.Device", "GetProperties");
+            dbus_message_iter_recurse(&arg_i, &element_i);
+            while (dbus_message_iter_get_arg_type(&element_i) != DBUS_TYPE_INVALID) {
+                if (dbus_message_iter_get_arg_type(&element_i) == DBUS_TYPE_DICT_ENTRY) {
+                    dbus_message_iter_recurse(&element_i, &dict_i);
+                    dbus_message_iter_get_basic(&dict_i, &key);
+                    dbus_message_iter_next(&dict_i);
+                    dbus_message_iter_recurse(&dict_i, &variant_i);
+                    if (strcmp(key, "Name") == 0) {
+                        dbus_message_iter_get_basic(&variant_i, &value);
+                        device_list_i->name = pa_xstrdup(value);
+                    }
+                    else if (strcmp(key, "Paired") == 0) {
+                        dbus_message_iter_get_basic(&variant_i, &uvalue);
+                        device_list_i->paired = uvalue;
+                    }
+                    else if (strcmp(key, "Alias") == 0) {
+                        dbus_message_iter_get_basic(&variant_i, &value);
+                        device_list_i->alias = pa_xstrdup(value);
+                    }
+                    else if (strcmp(key, "Connected") == 0) {
+                        dbus_message_iter_get_basic(&variant_i, &uvalue);
+                        device_list_i->connected = uvalue;
+                    }
+                    else if (strcmp(key, "UUIDs") == 0) {
+                        DBusMessageIter uuid_i;
+                        int is_audio_device = 0;
+                        dbus_message_iter_recurse(&variant_i, &uuid_i);
+                        while (dbus_message_iter_get_arg_type(&uuid_i) != DBUS_TYPE_INVALID) {
+                            dbus_message_iter_get_basic(&uuid_i, &value);
+                            if ( (strcmp(value, HSP_HS_UUID) == 0) || (strcmp(value, HFP_HS_UUID) == 0) ||
+                                (strcmp(value, A2DP_SOURCE_UUID) == 0) || (strcmp(value, A2DP_SINK_UUID) == 0) )
+                                is_audio_device = 1;
+                            uuid_list_append(device_list_i->uuid_list, value);
+                            dbus_message_iter_next(&uuid_i);
+                        }
+                        if (!is_audio_device) {
+                            /* remove current device */
+                            device_list_prev_i->next = device_list_i->next;
+                            pa_xfree(device_list_i);
+                            break;
+                        }
+                    }
+                    else if (strcmp(key, "Address") == 0) {
+                        dbus_message_iter_get_basic(&variant_i, &value);
+                        device_list_i->address = pa_xstrdup(value);
+                    }
+                    else if (strcmp(key, "Class") == 0) {
+                        dbus_message_iter_get_basic(&variant_i, &uvalue);
+                        device_list_i->class = uvalue;
+                    }
+                    else if (strcmp(key, "Trusted") == 0) {
+                        dbus_message_iter_get_basic(&variant_i, &uvalue);
+                        device_list_i->trusted = uvalue;
+                    }
+                }
+                dbus_message_iter_next(&element_i);
+            }
+            device_list_prev_i = device_list_prev_i->next;
+            if (device_list_prev_i == NULL)
+                device_list_i = NULL;
+            else
+                device_list_i = device_list_prev_i->next;
+        }
+        adapter_list_i = adapter_list_i->next;
+    }
+}
+
+void pa__done(pa_module* m) {
+    struct userdata *u;
+    adapter_t *adapter_list_i, *adapter_list_next_i;
+    device_t *device_list_i, *device_list_next_i;
+
+    pa_assert(m);
+
+    if (!(u = m->userdata))
+        return;
+
+    if ((adapter_list_i = u->adapter_list) != NULL) {
+        while ((adapter_list_next_i = adapter_list_i->next) != NULL) {
+            if ((device_list_i = adapter_list_i->device_list) != NULL) {
+                while ((device_list_next_i = device_list_i->next) != NULL) {
+                    pa_xfree(device_list_i);
+                    device_list_i = device_list_next_i;
+                }
+                pa_xfree(device_list_i);
+            }
+            pa_xfree(adapter_list_i);
+            adapter_list_i = adapter_list_next_i;
+        }
+        pa_xfree(adapter_list_i);
+    }
+
+    pa_dbus_connection_unref(u->conn);
+    pa_xfree(u);
+    pa_log("Unloading module-bt-discover");
+    return;
+}
+
+int pa__init(pa_module* m) {
+    pa_modargs *ma = NULL;
+    DBusError err;
+    DBusMessageIter arg_i, element_i;
+    adapter_t *adapter_list_i;
+    device_t *device_list_i;
+    const char *value;
+    unsigned int hcid_running = 0;
+    struct userdata *u;
+
+    pa_assert(m);
+    dbus_error_init(&err);
+    pa_log("Loading module-bt-discover");
+    m->userdata = u = pa_xnew0(struct userdata, 1);
+    u->module = m;
+
+    /* connect to the bus */
+    u->conn = pa_dbus_bus_get(m->core, DBUS_BUS_SYSTEM, &err);
+    if ( dbus_error_is_set(&err) || (u->conn == NULL) ) {
+        pa_log("Failed to get D-Bus connection: %s", err.message);
+        goto fail;
+    }
+
+    /* check if hcid is running */
+    arg_i = call_dbus_method(u->conn, "org.freedesktop.DBus", "/org/freedesktop/DBus" , "org.freedesktop.DBus", "ListNames");
+    dbus_message_iter_recurse(&arg_i, &element_i);
+    while (dbus_message_iter_get_arg_type(&element_i) != DBUS_TYPE_INVALID) {
+        if (dbus_message_iter_get_arg_type(&element_i) == DBUS_TYPE_STRING) {
+            dbus_message_iter_get_basic(&element_i, &value);
+            if (strcmp(value, "org.bluez") == 0)
+                hcid_running = 1;
+        }
+        dbus_message_iter_next(&element_i);
+    }
+    if (!hcid_running) {
+        pa_log("hcid not running");
+        goto fail;
+    }
+
+    /* static detection of bluetooth devices */
+    u->adapter_list = adapter_new("/ADAPTER_HEAD");
+    detect_adapters(u->adapter_list, u->conn);
+    detect_devices(u->adapter_list, u->conn);
+
+    if (VERBOSE) print_adapters(u->adapter_list);
+
+    /* load device modules */
+    adapter_list_i = u->adapter_list->next;
+    while (adapter_list_i != NULL) {
+        device_list_i = adapter_list_i->device_list->next;
+        while (device_list_i != NULL) {
+            pa_log("Loading module-bt-device for %s", device_list_i->name); /* CHECK: Should it be name or alias? */
+            /* call module */
+            device_list_i = device_list_i->next;
+        }
+        adapter_list_i = adapter_list_i->next;
+    }
+
+    return 0;
+
+fail:
+    if (ma)
+        pa_modargs_free(ma);
+    dbus_error_free(&err);
+    pa__done(m);
+    return -1;
+}

commit 9d18b90d05712d751f82b03ade51a2fca4ea10b2
Author: João Paulo Rechi Vita <joao.vita at gmail.com>
Date:   Thu Jul 17 16:30:53 2008 -0300

    Adding module-bt-discover to Makefile.am

diff --git a/src/Makefile.am b/src/Makefile.am
index 1663d66..ae0fca0 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1160,7 +1160,8 @@ endif
 
 if HAVE_BLUEZ
 modlibexec_LTLIBRARIES += \
-		module-bt-proximity.la
+		module-bt-proximity.la \
+		module-bt-discover.la
 
 pulselibexec_PROGRAMS += \
 		bt-proximity-helper
@@ -1220,6 +1221,7 @@ SYMDEF_FILES = \
 		modules/module-suspend-on-idle-symdef.h \
 		modules/module-hal-detect-symdef.h \
 		modules/module-bt-proximity-symdef.h \
+		modules/module-bt-discover-symdef.h \
 		modules/gconf/module-gconf-symdef.h \
 		modules/module-position-event-sounds-symdef.h \
 		modules/module-console-kit-symdef.h
@@ -1560,6 +1562,12 @@ bt_proximity_helper_LDADD = $(AM_LDADD) $(BLUEZ_LIBS)
 bt_proximity_helper_CFLAGS = $(AM_CFLAGS) $(BLUEZ_CFLAGS)
 bt_proximity_helper_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS)
 
+# Bluetooth discover
+module_bt_discover_la_SOURCES = modules/module-bt-discover.c
+module_bt_discover_la_LDFLAGS = -module -avoid-version
+module_bt_discover_la_LIBADD = $(AM_LIBADD) $(DBUS_LIBS) libpulsecore.la libdbus-util.la
+module_bt_discover_la_CFLAGS = $(AM_CFLAGS) $(DBUS_CFLAGS)
+
 ###################################
 #        Some minor stuff         #
 ###################################

commit 6fccd5828ac7971216bdf43ded4f76960bf98516
Author: João Paulo Rechi Vita <joao.vita at gmail.com>
Date:   Thu Jul 17 16:56:03 2008 -0300

    Fix comparison of strings of different case

diff --git a/src/modules/module-bt-discover.c b/src/modules/module-bt-discover.c
index f855ad1..5c3cc1b 100644
--- a/src/modules/module-bt-discover.c
+++ b/src/modules/module-bt-discover.c
@@ -1,8 +1,3 @@
-/* TODO LIST
- * listen to signals AdapterAdded, AdapterRemoved, DeviceCreated and DeviceRemoved
- * listen to org.freedesktop.DBus.NameOwnerChanged, to properly handle hcid activity
- */
-
 /***
     This file is part of PulseAudio.
 
@@ -35,25 +30,17 @@
 #include <pulsecore/modargs.h>
 
 #include "dbus-util.h"
-/* TODO: Create symdef file for static linking
- * #include "module-bt-proximity-symdef.h" */
+#include "module-bt-proximity-symdef.h"
 
 PA_MODULE_AUTHOR("Joao Paulo Rechi Vita");
 PA_MODULE_DESCRIPTION("Detect available bluetooth audio devices and load bluetooth audio drivers");
 PA_MODULE_VERSION(PACKAGE_VERSION);
 PA_MODULE_USAGE("");
 
-#define AUDIO_DEVICE_INTERFACE  "org.bluez.audio.Device"
-#define GENERIC_AUDIO_UUID      "00001203-0000-1000-8000-00805F9B34FB"
 #define HSP_HS_UUID             "00001108-0000-1000-8000-00805F9B34FB"
-#define HSP_AG_UUID             "00001112-0000-1000-8000-00805F9B34FB"
 #define HFP_HS_UUID             "0000111E-0000-1000-8000-00805F9B34FB"
-#define HFP_AG_UUID             "0000111F-0000-1000-8000-00805F9B34FB"
-#define ADVANCED_AUDIO_UUID     "0000110D-0000-1000-8000-00805F9B34FB"
 #define A2DP_SOURCE_UUID        "0000110A-0000-1000-8000-00805F9B34FB"
 #define A2DP_SINK_UUID          "0000110B-0000-1000-8000-00805F9B34FB"
-#define AVRCP_REMOTE_UUID       "0000110E-0000-1000-8000-00805F9B34FB"
-#define AVRCP_TARGET_UUID       "0000110C-0000-1000-8000-00805F9B34FB"
 
 #define VERBOSE 1
 
@@ -323,8 +310,8 @@ void detect_devices(adapter_t *adapter_list, pa_dbus_connection *conn) {
                         dbus_message_iter_recurse(&variant_i, &uuid_i);
                         while (dbus_message_iter_get_arg_type(&uuid_i) != DBUS_TYPE_INVALID) {
                             dbus_message_iter_get_basic(&uuid_i, &value);
-                            if ( (strcmp(value, HSP_HS_UUID) == 0) || (strcmp(value, HFP_HS_UUID) == 0) ||
-                                (strcmp(value, A2DP_SOURCE_UUID) == 0) || (strcmp(value, A2DP_SINK_UUID) == 0) )
+                            if ( (strcasecmp(value, HSP_HS_UUID) == 0) || (strcasecmp(value, HFP_HS_UUID) == 0) ||
+                                (strcasecmp(value, A2DP_SOURCE_UUID) == 0) || (strcasecmp(value, A2DP_SINK_UUID) == 0) )
                                 is_audio_device = 1;
                             uuid_list_append(device_list_i->uuid_list, value);
                             dbus_message_iter_next(&uuid_i);

commit 314dadeade9046167f6c47cde2719b805de523c0
Author: João Paulo Rechi Vita <joao.vita at gmail.com>
Date:   Fri Jul 18 11:02:59 2008 -0300

    Fix the symdef include

diff --git a/src/modules/module-bt-discover.c b/src/modules/module-bt-discover.c
index 5c3cc1b..4f862f9 100644
--- a/src/modules/module-bt-discover.c
+++ b/src/modules/module-bt-discover.c
@@ -30,7 +30,7 @@
 #include <pulsecore/modargs.h>
 
 #include "dbus-util.h"
-#include "module-bt-proximity-symdef.h"
+#include "module-bt-discover-symdef.h"
 
 PA_MODULE_AUTHOR("Joao Paulo Rechi Vita");
 PA_MODULE_DESCRIPTION("Detect available bluetooth audio devices and load bluetooth audio drivers");

commit c9f56593e37a27e68d2fdfb26b3a48043dd072cb
Author: João Paulo Rechi Vita <joao.vita at gmail.com>
Date:   Mon Jul 21 09:42:29 2008 -0300

    Adding dynamic bluetooth audio devices detection

diff --git a/src/modules/module-bt-discover.c b/src/modules/module-bt-discover.c
index 4f862f9..f6a9736 100644
--- a/src/modules/module-bt-discover.c
+++ b/src/modules/module-bt-discover.c
@@ -348,6 +348,69 @@ void detect_devices(adapter_t *adapter_list, pa_dbus_connection *conn) {
     }
 }
 
+static DBusHandlerResult filter_cb(DBusConnection *bus, DBusMessage *msg, void *userdata) {
+    DBusMessageIter arg_i;
+    DBusError err;
+    const char *value;
+    struct userdata *u;
+
+    pa_assert(bus);
+    pa_assert(msg);
+    pa_assert(userdata);
+    u = userdata;
+    dbus_error_init(&err);
+
+    pa_log("dbus: interface=%s, path=%s, member=%s\n",
+            dbus_message_get_interface(msg),
+            dbus_message_get_path(msg),
+            dbus_message_get_member(msg));
+
+    if (dbus_message_is_signal(msg, "org.bluez.Manager", "AdapterAdded")) {
+        if (!dbus_message_iter_init(msg, &arg_i))
+            pa_log("dbus: message has no parameters");
+        else if (dbus_message_iter_get_arg_type(&arg_i) != DBUS_TYPE_OBJECT_PATH)
+            pa_log("dbus: argument is not object path");
+        else {
+            dbus_message_iter_get_basic(&arg_i, &value);
+            pa_log("hcid: adapter %s added", value);
+        }
+    }
+    else if (dbus_message_is_signal(msg, "org.bluez.Manager", "AdapterRemoved")) {
+        if (!dbus_message_iter_init(msg, &arg_i))
+            pa_log("dbus: message has no parameters");
+        else if (dbus_message_iter_get_arg_type(&arg_i) != DBUS_TYPE_OBJECT_PATH)
+            pa_log("dbus: argument is not object path");
+        else {
+            dbus_message_iter_get_basic(&arg_i, &value);
+            pa_log("hcid: adapter %s removed", value);
+        }
+    }
+    else if (dbus_message_is_signal(msg, "org.bluez.Adapter", "DeviceCreated")) {
+        if (!dbus_message_iter_init(msg, &arg_i))
+            pa_log("dbus: message has no parameters");
+        else if (dbus_message_iter_get_arg_type(&arg_i) != DBUS_TYPE_OBJECT_PATH)
+            pa_log("dbus: argument is not object path");
+        else {
+            dbus_message_iter_get_basic(&arg_i, &value);
+            pa_log("hcid: device %s created", value);
+        }
+    }
+    else if (dbus_message_is_signal(msg, "org.bluez.Adapter", "DeviceRemoved")) {
+        if (!dbus_message_iter_init(msg, &arg_i))
+            pa_log("dbus: message has no parameters");
+        else if (dbus_message_iter_get_arg_type(&arg_i) != DBUS_TYPE_OBJECT_PATH)
+            pa_log("dbus: argument is not object path");
+        else {
+            dbus_message_iter_get_basic(&arg_i, &value);
+            pa_log("hcid: device %s removed", value);
+        }
+    }
+
+finish:
+    dbus_error_free(&err);
+    return DBUS_HANDLER_RESULT_HANDLED;
+}
+
 void pa__done(pa_module* m) {
     struct userdata *u;
     adapter_t *adapter_list_i, *adapter_list_next_i;
@@ -418,7 +481,7 @@ int pa__init(pa_module* m) {
         goto fail;
     }
 
-    /* static detection of bluetooth devices */
+    /* static detection of bluetooth audio devices */
     u->adapter_list = adapter_new("/ADAPTER_HEAD");
     detect_adapters(u->adapter_list, u->conn);
     detect_devices(u->adapter_list, u->conn);
@@ -437,6 +500,25 @@ int pa__init(pa_module* m) {
         adapter_list_i = adapter_list_i->next;
     }
 
+    /* dynamic detection of bluetooth audio devices */
+    if (!dbus_connection_add_filter(pa_dbus_connection_get(u->conn), filter_cb, u, NULL)) {
+        pa_log_error("Failed to add filter function");
+        goto fail;
+    }
+    dbus_connection_flush(pa_dbus_connection_get(u->conn));
+    dbus_bus_add_match(pa_dbus_connection_get(u->conn), "type='signal',interface='org.bluez.Manager'", &err);
+    dbus_connection_flush(pa_dbus_connection_get(u->conn));
+    if (dbus_error_is_set(&err)) {
+        pa_log_error("Unable to subscribe to org.bluez.Manager signals: %s: %s", err.name, err.message);
+        goto fail;
+    }
+    dbus_bus_add_match(pa_dbus_connection_get(u->conn), "type='signal',interface='org.bluez.Adapter'", &err);
+    dbus_connection_flush(pa_dbus_connection_get(u->conn));
+    if (dbus_error_is_set(&err)) {
+        pa_log_error("Unable to subscribe to org.bluez.Adapter signals: %s: %s", err.name, err.message);
+        goto fail;
+    }
+
     return 0;
 
 fail:

commit 3909d9bf90529204c96a9ba70f17582038df6e93
Author: João Paulo Rechi Vita <joao.vita at gmail.com>
Date:   Mon Jul 21 10:53:20 2008 -0300

    Remove VERBOSE definition

diff --git a/src/modules/module-bt-discover.c b/src/modules/module-bt-discover.c
index f6a9736..f8ec2e9 100644
--- a/src/modules/module-bt-discover.c
+++ b/src/modules/module-bt-discover.c
@@ -42,8 +42,6 @@ PA_MODULE_USAGE("");
 #define A2DP_SOURCE_UUID        "0000110A-0000-1000-8000-00805F9B34FB"
 #define A2DP_SINK_UUID          "0000110B-0000-1000-8000-00805F9B34FB"
 
-#define VERBOSE 1
-
 typedef struct adapter adapter_t;
 typedef struct device device_t;
 typedef struct uuid uuid_t;
@@ -486,7 +484,7 @@ int pa__init(pa_module* m) {
     detect_adapters(u->adapter_list, u->conn);
     detect_devices(u->adapter_list, u->conn);
 
-    if (VERBOSE) print_adapters(u->adapter_list);
+    print_adapters(u->adapter_list);
 
     /* load device modules */
     adapter_list_i = u->adapter_list->next;

commit e5d25e0542819d14f0ae58c3ac2d481243c0eb32
Author: João Paulo Rechi Vita <joao.vita at gmail.com>
Date:   Mon Jul 21 11:23:25 2008 -0300

    Changing all private functions to static

diff --git a/src/modules/module-bt-discover.c b/src/modules/module-bt-discover.c
index f8ec2e9..f1dcd2e 100644
--- a/src/modules/module-bt-discover.c
+++ b/src/modules/module-bt-discover.c
@@ -79,19 +79,19 @@ struct userdata {
     adapter_t *adapter_list;
 };
 
-uuid_t *uuid_new(const char *uuid) {
+static uuid_t *uuid_new(const char *uuid) {
     uuid_t *node = pa_xnew0(uuid_t, 1);
     node->uuid = pa_xstrdup(uuid);
     node->next = NULL;
     return node;
 }
 
-void uuid_list_append(uuid_t *node, const char *uuid) {
+static void uuid_list_append(uuid_t *node, const char *uuid) {
     while (node->next != NULL) node = node->next;
     node->next = uuid_new(uuid);
 }
 
-device_t *device_new(const char *device, adapter_t *adapter) {
+static device_t *device_new(const char *device, adapter_t *adapter) {
     device_t *node = pa_xnew0(device_t, 1);
     node->name = NULL;
     node->object_path = pa_xstrdup(device);
@@ -107,12 +107,12 @@ device_t *device_new(const char *device, adapter_t *adapter) {
     return node;
 }
 
-void device_list_append(device_t *node, const char *device, adapter_t *adapter) {
+static void device_list_append(device_t *node, const char *device, adapter_t *adapter) {
     while (node->next != NULL) node = node->next;
     node->next = device_new(device, adapter);
 }
 
-adapter_t *adapter_new(const char *adapter) {
+static adapter_t *adapter_new(const char *adapter) {
     adapter_t *node = pa_xnew0(adapter_t, 1);
     node->object_path = pa_xstrdup(adapter);
     node->mode = NULL;
@@ -122,12 +122,12 @@ adapter_t *adapter_new(const char *adapter) {
     return node;
 }
 
-void adapter_list_append(adapter_t *node, const char *adapter) {
+static void adapter_list_append(adapter_t *node, const char *adapter) {
     while (node->next != NULL) node = node->next;
     node->next = adapter_new(adapter);
 }
 
-void print_devices(device_t *device_list) {
+static void print_devices(device_t *device_list) {
     device_t *device_list_i = device_list;
     while (device_list_i != NULL) {
         uuid_t *uuid_list_i = device_list_i->uuid_list;
@@ -153,7 +153,7 @@ void print_devices(device_t *device_list) {
     }
 }
 
-void print_adapters(adapter_t *adapter_list) {
+static void print_adapters(adapter_t *adapter_list) {
     adapter_t *adapter_list_i = adapter_list;
     while (adapter_list_i != NULL) {
         if (strcmp(adapter_list_i->object_path, "/ADAPTER_HEAD") != 0) {
@@ -166,7 +166,7 @@ void print_adapters(adapter_t *adapter_list) {
     }
 }
 
-DBusMessageIter call_dbus_method(pa_dbus_connection *conn, const char *destination, const char *path, const char *interface,
+static DBusMessageIter call_dbus_method(pa_dbus_connection *conn, const char *destination, const char *path, const char *interface,
         const char *method) {
     DBusMessage *msg;
     DBusPendingCall *pending;
@@ -209,7 +209,7 @@ DBusMessageIter call_dbus_method(pa_dbus_connection *conn, const char *destinati
 
 }
 
-void detect_adapters(adapter_t *adapter_list, pa_dbus_connection *conn) {
+static void detect_adapters(adapter_t *adapter_list, pa_dbus_connection *conn) {
     DBusMessageIter arg_i, element_i, dict_i, variant_i;
     adapter_t *adapter_list_i;
     const char *key, *value;
@@ -250,7 +250,7 @@ void detect_adapters(adapter_t *adapter_list, pa_dbus_connection *conn) {
     }
 }
 
-void detect_devices(adapter_t *adapter_list, pa_dbus_connection *conn) {
+static void detect_devices(adapter_t *adapter_list, pa_dbus_connection *conn) {
     DBusMessageIter arg_i, element_i, dict_i, variant_i;
     adapter_t *adapter_list_i;
     device_t *device_list_i, *device_list_prev_i;

commit 2b68562323acea24530d938e0a78984c8a73e5ae
Author: João Paulo Rechi Vita <joao.vita at gmail.com>
Date:   Tue Jul 22 10:07:30 2008 -0300

    Improve dbus communication

diff --git a/src/modules/module-bt-discover.c b/src/modules/module-bt-discover.c
index f1dcd2e..6c388a3 100644
--- a/src/modules/module-bt-discover.c
+++ b/src/modules/module-bt-discover.c
@@ -209,26 +209,57 @@ static DBusMessageIter call_dbus_method(pa_dbus_connection *conn, const char *de
 
 }
 
-static void detect_adapters(adapter_t *adapter_list, pa_dbus_connection *conn) {
+static void detect_adapters(struct userdata *u) {
+    DBusError e;
+    DBusMessage *m = NULL, *r = NULL;
     DBusMessageIter arg_i, element_i, dict_i, variant_i;
     adapter_t *adapter_list_i;
     const char *key, *value;
 
+    pa_assert(u);
+    dbus_error_init(&e);
+
     /* get adapters */
-    arg_i = call_dbus_method(conn, "org.bluez", "/", "org.bluez.Manager", "ListAdapters");
+    pa_assert_se(m = dbus_message_new_method_call("org.bluez", "/", "org.bluez.Manager", "ListAdapters"));
+    r = dbus_connection_send_with_reply_and_block(pa_dbus_connection_get(u->conn), m, -1, &e);
+    if (!r) {
+        pa_log("org.bluez.Manager.ListAdapters failed: %s", e.message);
+        goto fail;
+    }
+    if (!dbus_message_iter_init(r, &arg_i)) {
+        pa_log("org.bluez.Manager.ListAdapters reply has no arguments");
+        goto fail;
+    }
+    if (dbus_message_iter_get_arg_type(&arg_i) != DBUS_TYPE_ARRAY) {
+        pa_log("org.bluez.Manager.ListAdapters argument is not an array");
+        goto fail;
+    }
     dbus_message_iter_recurse(&arg_i, &element_i);
     while (dbus_message_iter_get_arg_type(&element_i) != DBUS_TYPE_INVALID) {
         if (dbus_message_iter_get_arg_type(&element_i) == DBUS_TYPE_OBJECT_PATH) {
             dbus_message_iter_get_basic(&element_i, &value);
-            adapter_list_append(adapter_list, value);
+            adapter_list_append(u->adapter_list, value);
         }
         dbus_message_iter_next(&element_i);
     }
 
     /* get adapter properties */
-    adapter_list_i = adapter_list->next;
+    adapter_list_i = u->adapter_list->next;
     while (adapter_list_i != NULL) {
-        arg_i = call_dbus_method(conn, "org.bluez", adapter_list_i->object_path, "org.bluez.Adapter", "GetProperties");
+        pa_assert_se(m = dbus_message_new_method_call("org.bluez", adapter_list_i->object_path, "org.bluez.Adapter", "GetProperties"));
+        r = dbus_connection_send_with_reply_and_block(pa_dbus_connection_get(u->conn), m, -1, &e);
+        if (!r) {
+            pa_log("org.bluez.Adapter.GetProperties failed: %s", e.message);
+            goto fail;
+        }
+        if (!dbus_message_iter_init(r, &arg_i)) {
+            pa_log("org.bluez.Adapter.GetProperties reply has no arguments");
+            goto fail;
+        }
+        if (dbus_message_iter_get_arg_type(&arg_i) != DBUS_TYPE_ARRAY) {
+            pa_log("org.bluez.Adapter.GetProperties argument is not an array");
+            goto fail;
+        }
         dbus_message_iter_recurse(&arg_i, &element_i);
         while (dbus_message_iter_get_arg_type(&element_i) != DBUS_TYPE_INVALID) {
             if (dbus_message_iter_get_arg_type(&element_i) == DBUS_TYPE_DICT_ENTRY) {
@@ -248,19 +279,44 @@ static void detect_adapters(adapter_t *adapter_list, pa_dbus_connection *conn) {
         }
         adapter_list_i = adapter_list_i->next;
     }
+
+fail:
+    if (m)
+        dbus_message_unref(m);
+    if (r)
+        dbus_message_unref(r);
+    dbus_error_free(&e);
 }
 
-static void detect_devices(adapter_t *adapter_list, pa_dbus_connection *conn) {
+static void detect_devices(struct userdata *u) {
+    DBusError e;
+    DBusMessage *m = NULL, *r = NULL;
     DBusMessageIter arg_i, element_i, dict_i, variant_i;
     adapter_t *adapter_list_i;
     device_t *device_list_i, *device_list_prev_i;
     const char *key, *value;
     unsigned int uvalue;
 
+    pa_assert(u);
+    dbus_error_init(&e);
+
     /* get devices of each adapter */
-    adapter_list_i = adapter_list->next;
+    adapter_list_i = u->adapter_list->next;
     while (adapter_list_i != NULL) {
-        arg_i = call_dbus_method(conn, "org.bluez", adapter_list_i->object_path , "org.bluez.Adapter", "ListDevices");
+        pa_assert_se(m = dbus_message_new_method_call("org.bluez", adapter_list_i->object_path, "org.bluez.Adapter", "ListDevices"));
+        r = dbus_connection_send_with_reply_and_block(pa_dbus_connection_get(u->conn), m, -1, &e);
+        if (!r) {
+            pa_log("org.bluez.Adapter.ListDevices failed: %s", e.message);
+            goto fail;
+        }
+        if (!dbus_message_iter_init(r, &arg_i)) {
+            pa_log("org.bluez.Adapter.ListDevices reply has no arguments");
+            goto fail;
+        }
+        if (dbus_message_iter_get_arg_type(&arg_i) != DBUS_TYPE_ARRAY) {
+            pa_log("org.bluez.Adapter.ListDevices argument is not an array");
+            goto fail;
+        }
         dbus_message_iter_recurse(&arg_i, &element_i);
         while (dbus_message_iter_get_arg_type(&element_i) != DBUS_TYPE_INVALID) {
             if (dbus_message_iter_get_arg_type(&element_i) == DBUS_TYPE_OBJECT_PATH) {
@@ -273,12 +329,25 @@ static void detect_devices(adapter_t *adapter_list, pa_dbus_connection *conn) {
     }
 
     /* get device properties */
-    adapter_list_i = adapter_list->next;
+    adapter_list_i = u->adapter_list->next;
     while (adapter_list_i != NULL) {
         device_list_prev_i = adapter_list_i->device_list;
         device_list_i = adapter_list_i->device_list->next;
         while (device_list_i != NULL) {
-            arg_i = call_dbus_method(conn, "org.bluez", device_list_i->object_path, "org.bluez.Device", "GetProperties");
+            pa_assert_se(m = dbus_message_new_method_call("org.bluez", device_list_i->object_path, "org.bluez.Device", "GetProperties"));
+            r = dbus_connection_send_with_reply_and_block(pa_dbus_connection_get(u->conn), m, -1, &e);
+            if (!r) {
+                pa_log("org.bluez.Device.GetProperties failed: %s", e.message);
+                goto fail;
+            }
+            if (!dbus_message_iter_init(r, &arg_i)) {
+                pa_log("org.bluez.Device.GetProperties reply has no arguments");
+                goto fail;
+            }
+            if (dbus_message_iter_get_arg_type(&arg_i) != DBUS_TYPE_ARRAY) {
+                pa_log("org.bluez.Device.GetProperties argument is not an array");
+                goto fail;
+            }
             dbus_message_iter_recurse(&arg_i, &element_i);
             while (dbus_message_iter_get_arg_type(&element_i) != DBUS_TYPE_INVALID) {
                 if (dbus_message_iter_get_arg_type(&element_i) == DBUS_TYPE_DICT_ENTRY) {
@@ -344,6 +413,13 @@ static void detect_devices(adapter_t *adapter_list, pa_dbus_connection *conn) {
         }
         adapter_list_i = adapter_list_i->next;
     }
+
+fail:
+    if (m)
+        dbus_message_unref(m);
+    if (r)
+        dbus_message_unref(r);
+    dbus_error_free(&e);
 }
 
 static DBusHandlerResult filter_cb(DBusConnection *bus, DBusMessage *msg, void *userdata) {
@@ -481,8 +557,8 @@ int pa__init(pa_module* m) {
 
     /* static detection of bluetooth audio devices */
     u->adapter_list = adapter_new("/ADAPTER_HEAD");
-    detect_adapters(u->adapter_list, u->conn);
-    detect_devices(u->adapter_list, u->conn);
+    detect_adapters(u);
+    detect_devices(u);
 
     print_adapters(u->adapter_list);
 

commit 9907b461d486d50b5ae5ace2cc133f482789af5f
Author: João Paulo Rechi Vita <joao.vita at gmail.com>
Date:   Tue Jul 22 10:08:37 2008 -0300

    Don't need to explicity check if hcid is running anymore

diff --git a/src/modules/module-bt-discover.c b/src/modules/module-bt-discover.c
index 6c388a3..19c8282 100644
--- a/src/modules/module-bt-discover.c
+++ b/src/modules/module-bt-discover.c
@@ -235,6 +235,8 @@ static void detect_adapters(struct userdata *u) {
         goto fail;
     }
     dbus_message_iter_recurse(&arg_i, &element_i);
+    // TODO: Review error checking
+    // should this be changed to while (dbus_message_iter_get_arg_type(&element_i) == DBUS_TYPE_OBJECT_PATH) ?
     while (dbus_message_iter_get_arg_type(&element_i) != DBUS_TYPE_INVALID) {
         if (dbus_message_iter_get_arg_type(&element_i) == DBUS_TYPE_OBJECT_PATH) {
             dbus_message_iter_get_basic(&element_i, &value);
@@ -318,6 +320,8 @@ static void detect_devices(struct userdata *u) {
             goto fail;
         }
         dbus_message_iter_recurse(&arg_i, &element_i);
+        // TODO: Review error checking
+        // should this be changed to while (dbus_message_iter_get_arg_type(&element_i) == DBUS_TYPE_OBJECT_PATH) ?
         while (dbus_message_iter_get_arg_type(&element_i) != DBUS_TYPE_INVALID) {
             if (dbus_message_iter_get_arg_type(&element_i) == DBUS_TYPE_OBJECT_PATH) {
                 dbus_message_iter_get_basic(&element_i, &value);
@@ -523,7 +527,6 @@ int pa__init(pa_module* m) {
     adapter_t *adapter_list_i;
     device_t *device_list_i;
     const char *value;
-    unsigned int hcid_running = 0;
     struct userdata *u;
 
     pa_assert(m);
@@ -539,22 +542,6 @@ int pa__init(pa_module* m) {
         goto fail;
     }
 
-    /* check if hcid is running */
-    arg_i = call_dbus_method(u->conn, "org.freedesktop.DBus", "/org/freedesktop/DBus" , "org.freedesktop.DBus", "ListNames");
-    dbus_message_iter_recurse(&arg_i, &element_i);
-    while (dbus_message_iter_get_arg_type(&element_i) != DBUS_TYPE_INVALID) {
-        if (dbus_message_iter_get_arg_type(&element_i) == DBUS_TYPE_STRING) {
-            dbus_message_iter_get_basic(&element_i, &value);
-            if (strcmp(value, "org.bluez") == 0)
-                hcid_running = 1;
-        }
-        dbus_message_iter_next(&element_i);
-    }
-    if (!hcid_running) {
-        pa_log("hcid not running");
-        goto fail;
-    }
-
     /* static detection of bluetooth audio devices */
     u->adapter_list = adapter_new("/ADAPTER_HEAD");
     detect_adapters(u);

commit d90bb1859a543e3783e1293ada37d5c0545b420b
Author: João Paulo Rechi Vita <joao.vita at gmail.com>
Date:   Tue Jul 22 10:11:26 2008 -0300

    We don't need call_dbus_method anymore

diff --git a/src/modules/module-bt-discover.c b/src/modules/module-bt-discover.c
index 19c8282..35d6365 100644
--- a/src/modules/module-bt-discover.c
+++ b/src/modules/module-bt-discover.c
@@ -166,49 +166,6 @@ static void print_adapters(adapter_t *adapter_list) {
     }
 }
 
-static DBusMessageIter call_dbus_method(pa_dbus_connection *conn, const char *destination, const char *path, const char *interface,
-        const char *method) {
-    DBusMessage *msg;
-    DBusPendingCall *pending;
-    DBusMessageIter args;
-
-    /* construct the DBusMessage */
-    msg = dbus_message_new_method_call(destination, path, interface, method);
-
-    /* send the message and get a handle for a reply */
-    if (!dbus_connection_send_with_reply(pa_dbus_connection_get(conn), msg, &pending, -1)) { 
-        pa_log("Out Of Memory!"); 
-    }
-    if (pending == NULL) { 
-        pa_log("Pending Call Null"); 
-    }
-    dbus_connection_flush(pa_dbus_connection_get(conn));
-
-    /* free msg */
-    dbus_message_unref(msg);
-
-    /* wait for reply */
-    dbus_pending_call_block(pending);
-
-    /* get the reply */
-    msg = dbus_pending_call_steal_reply(pending);
-    if (msg == NULL) {
-        pa_log("Reply Null");
-    }
-
-    /* free pending */
-    dbus_pending_call_unref(pending);
-
-    /* read the reply */
-    if (!dbus_message_iter_init(msg, &args))
-        pa_log("Reply has no arguments");
-
-    dbus_message_unref(msg);
-
-    return args;
-
-}
-
 static void detect_adapters(struct userdata *u) {
     DBusError e;
     DBusMessage *m = NULL, *r = NULL;
@@ -235,8 +192,8 @@ static void detect_adapters(struct userdata *u) {
         goto fail;
     }
     dbus_message_iter_recurse(&arg_i, &element_i);
-    // TODO: Review error checking
-    // should this be changed to while (dbus_message_iter_get_arg_type(&element_i) == DBUS_TYPE_OBJECT_PATH) ?
+    /* TODO: Review error checking
+     * should this be changed to while (dbus_message_iter_get_arg_type(&element_i) == DBUS_TYPE_OBJECT_PATH) ? */
     while (dbus_message_iter_get_arg_type(&element_i) != DBUS_TYPE_INVALID) {
         if (dbus_message_iter_get_arg_type(&element_i) == DBUS_TYPE_OBJECT_PATH) {
             dbus_message_iter_get_basic(&element_i, &value);
@@ -320,8 +277,8 @@ static void detect_devices(struct userdata *u) {
             goto fail;
         }
         dbus_message_iter_recurse(&arg_i, &element_i);
-        // TODO: Review error checking
-        // should this be changed to while (dbus_message_iter_get_arg_type(&element_i) == DBUS_TYPE_OBJECT_PATH) ?
+        /* TODO: Review error checking
+         * should this be changed to while (dbus_message_iter_get_arg_type(&element_i) == DBUS_TYPE_OBJECT_PATH) ? */
         while (dbus_message_iter_get_arg_type(&element_i) != DBUS_TYPE_INVALID) {
             if (dbus_message_iter_get_arg_type(&element_i) == DBUS_TYPE_OBJECT_PATH) {
                 dbus_message_iter_get_basic(&element_i, &value);

commit a69c020c552e1152d3a321020ea41a3ac3c76e12
Author: João Paulo Rechi Vita <joao.vita at gmail.com>
Date:   Tue Jul 22 10:37:34 2008 -0300

    Change booleans to pa_bool_t

diff --git a/src/modules/module-bt-discover.c b/src/modules/module-bt-discover.c
index 35d6365..6d93974 100644
--- a/src/modules/module-bt-discover.c
+++ b/src/modules/module-bt-discover.c
@@ -28,6 +28,7 @@
 #include <pulse/xmalloc.h>
 #include <pulsecore/module.h>
 #include <pulsecore/modargs.h>
+#include <pulsecore/macro.h>
 
 #include "dbus-util.h"
 #include "module-bt-discover-symdef.h"
@@ -334,13 +335,13 @@ static void detect_devices(struct userdata *u) {
                     }
                     else if (strcmp(key, "UUIDs") == 0) {
                         DBusMessageIter uuid_i;
-                        int is_audio_device = 0;
+                        pa_bool_t is_audio_device = FALSE;
                         dbus_message_iter_recurse(&variant_i, &uuid_i);
                         while (dbus_message_iter_get_arg_type(&uuid_i) != DBUS_TYPE_INVALID) {
                             dbus_message_iter_get_basic(&uuid_i, &value);
                             if ( (strcasecmp(value, HSP_HS_UUID) == 0) || (strcasecmp(value, HFP_HS_UUID) == 0) ||
                                 (strcasecmp(value, A2DP_SOURCE_UUID) == 0) || (strcasecmp(value, A2DP_SINK_UUID) == 0) )
-                                is_audio_device = 1;
+                                is_audio_device = TRUE;
                             uuid_list_append(device_list_i->uuid_list, value);
                             dbus_message_iter_next(&uuid_i);
                         }

commit cadc6660dd6344f142c57fce306bde551f7a8685
Author: João Paulo Rechi Vita <joao.vita at gmail.com>
Date:   Tue Jul 22 10:48:50 2008 -0300

    Remove some unused vars and labels

diff --git a/src/modules/module-bt-discover.c b/src/modules/module-bt-discover.c
index 6d93974..9c18a86 100644
--- a/src/modules/module-bt-discover.c
+++ b/src/modules/module-bt-discover.c
@@ -442,7 +442,6 @@ static DBusHandlerResult filter_cb(DBusConnection *bus, DBusMessage *msg, void *
         }
     }
 
-finish:
     dbus_error_free(&err);
     return DBUS_HANDLER_RESULT_HANDLED;
 }
@@ -481,10 +480,8 @@ void pa__done(pa_module* m) {
 int pa__init(pa_module* m) {
     pa_modargs *ma = NULL;
     DBusError err;
-    DBusMessageIter arg_i, element_i;
     adapter_t *adapter_list_i;
     device_t *device_list_i;
-    const char *value;
     struct userdata *u;
 
     pa_assert(m);

commit d893a1ff530cc4fe5c3ad8623ba2eb9f89770914
Author: João Paulo Rechi Vita <joao.vita at gmail.com>
Date:   Tue Jul 22 10:55:04 2008 -0300

    Remove block delimiters from single line if blocks

diff --git a/src/modules/module-bt-discover.c b/src/modules/module-bt-discover.c
index 9c18a86..8b662a1 100644
--- a/src/modules/module-bt-discover.c
+++ b/src/modules/module-bt-discover.c
@@ -141,9 +141,8 @@ static void print_devices(device_t *device_list) {
             pa_log("        Connected = %d", device_list_i->connected);
             pa_log("        UUIDs = ");
             while (uuid_list_i != NULL) {
-                if (strcmp(uuid_list_i->uuid, "UUID_HEAD") != 0) {
+                if (strcmp(uuid_list_i->uuid, "UUID_HEAD") != 0)
                     pa_log("            %s", uuid_list_i->uuid);
-                }
                 uuid_list_i = uuid_list_i->next;
             }
             pa_log("        Address = %s", device_list_i->address);
@@ -228,12 +227,10 @@ static void detect_adapters(struct userdata *u) {
                 dbus_message_iter_next(&dict_i);
                 dbus_message_iter_recurse(&dict_i, &variant_i);
                 dbus_message_iter_get_basic(&variant_i, &value);
-                if (strcmp(key, "Mode") == 0) {
+                if (strcmp(key, "Mode") == 0)
                     adapter_list_i->mode = pa_xstrdup(value);
-                }
-                else if (strcmp(key, "Address") == 0) {
+                else if (strcmp(key, "Address") == 0)
                     adapter_list_i->address = pa_xstrdup(value);
-                }
             }
             dbus_message_iter_next(&element_i);
         }

commit 1e03c323cac98528a514d7c605a82b8b7a521a29
Author: João Paulo Rechi Vita <joao.vita at gmail.com>
Date:   Wed Jul 23 11:12:57 2008 -0300

    Refactor all linked lists to use pulsecore/llist.h

diff --git a/src/modules/module-bt-discover.c b/src/modules/module-bt-discover.c
index 8b662a1..b00a9c1 100644
--- a/src/modules/module-bt-discover.c
+++ b/src/modules/module-bt-discover.c
@@ -29,6 +29,7 @@
 #include <pulsecore/module.h>
 #include <pulsecore/modargs.h>
 #include <pulsecore/macro.h>
+#include <pulsecore/llist.h>
 
 #include "dbus-util.h"
 #include "module-bt-discover-symdef.h"
@@ -43,95 +44,100 @@ PA_MODULE_USAGE("");
 #define A2DP_SOURCE_UUID        "0000110A-0000-1000-8000-00805F9B34FB"
 #define A2DP_SINK_UUID          "0000110B-0000-1000-8000-00805F9B34FB"
 
-typedef struct adapter adapter_t;
-typedef struct device device_t;
-typedef struct uuid uuid_t;
-
 struct uuid {
     char *uuid;
-    uuid_t *next;
+    PA_LLIST_FIELDS(struct uuid);
 };
 
 struct device {
     char *name;
     char *object_path;
     int paired;
-    adapter_t *adapter;
+    struct adapter *adapter;
     char *alias;
     int connected;
-    uuid_t *uuid_list;
+    PA_LLIST_HEAD(struct uuid, uuid_list);
     char *address;
     int class;
     int trusted;
-    device_t *next;
+    PA_LLIST_FIELDS(struct device);
 };
 
 struct adapter {
     char *object_path;
     char *mode;
     char *address;
-    device_t *device_list;
-    adapter_t *next;
+    PA_LLIST_HEAD(struct device, device_list);
+    PA_LLIST_FIELDS(struct adapter);
 };
 
 struct userdata {
     pa_module *module;
     pa_dbus_connection *conn;
-    adapter_t *adapter_list;
+    PA_LLIST_HEAD(struct adapter, adapter_list);
 };
 
-static uuid_t *uuid_new(const char *uuid) {
-    uuid_t *node = pa_xnew0(uuid_t, 1);
+static struct uuid *uuid_new(const char *uuid) {
+    struct uuid *node = pa_xnew(struct uuid, 1);
     node->uuid = pa_xstrdup(uuid);
-    node->next = NULL;
+    PA_LLIST_INIT(struct uuid, node);
     return node;
 }
 
-static void uuid_list_append(uuid_t *node, const char *uuid) {
-    while (node->next != NULL) node = node->next;
-    node->next = uuid_new(uuid);
+static void uuid_free(struct uuid *uuid) {
+    pa_xfree(uuid);
 }
 
-static device_t *device_new(const char *device, adapter_t *adapter) {
-    device_t *node = pa_xnew0(device_t, 1);
+static struct device *device_new(const char *device, struct adapter *adapter) {
+    struct device *node = pa_xnew(struct device, 1);
     node->name = NULL;
     node->object_path = pa_xstrdup(device);
     node->paired = -1;
     node->adapter = adapter;
     node->alias = NULL;
     node->connected = -1;
-    node->uuid_list = uuid_new("UUID_HEAD");
+    PA_LLIST_HEAD_INIT(struct uuid, node->uuid_list);
     node->address = NULL;
     node->class = -1;
     node->trusted = -1;
-    node->next = NULL;
+    PA_LLIST_INIT(struct device, node);
     return node;
 }
 
-static void device_list_append(device_t *node, const char *device, adapter_t *adapter) {
-    while (node->next != NULL) node = node->next;
-    node->next = device_new(device, adapter);
+static void device_free(struct device *device) {
+    struct uuid *uuid_list_i;
+    while (device->uuid_list) {
+        uuid_list_i = device->uuid_list;
+        PA_LLIST_REMOVE(struct uuid, device->uuid_list, uuid_list_i);
+        uuid_free(uuid_list_i);
+    }
+    pa_xfree(device);
 }
 
-static adapter_t *adapter_new(const char *adapter) {
-    adapter_t *node = pa_xnew0(adapter_t, 1);
+static struct adapter *adapter_new(const char *adapter) {
+    struct adapter *node = pa_xnew(struct adapter, 1);
     node->object_path = pa_xstrdup(adapter);
     node->mode = NULL;
     node->address = NULL;
-    node->device_list = device_new("/DEVICE_HEAD", NULL);
-    node->next = NULL;
+    PA_LLIST_HEAD_INIT(struct device, node->device_list);
+    PA_LLIST_INIT(struct adapter, node);
     return node;
 }
 
-static void adapter_list_append(adapter_t *node, const char *adapter) {
-    while (node->next != NULL) node = node->next;
-    node->next = adapter_new(adapter);
+static void adapter_free(struct adapter *adapter) {
+    struct device *device_list_i;
+    while (adapter->device_list) {
+        device_list_i = adapter->device_list;
+        PA_LLIST_REMOVE(struct device, adapter->device_list, device_list_i);
+        device_free(device_list_i);
+    }
+    pa_xfree(adapter);
 }
 
-static void print_devices(device_t *device_list) {
-    device_t *device_list_i = device_list;
+static void print_devices(struct device *device_list) {
+    struct device *device_list_i = device_list;
     while (device_list_i != NULL) {
-        uuid_t *uuid_list_i = device_list_i->uuid_list;
+        struct uuid *uuid_list_i = device_list_i->uuid_list;
         if (strcmp(device_list_i->object_path, "/DEVICE_HEAD") != 0) {
             pa_log("    [ %s ]", device_list_i->object_path);
             pa_log("        Name = %s", device_list_i->name);
@@ -153,8 +159,8 @@ static void print_devices(device_t *device_list) {
     }
 }
 
-static void print_adapters(adapter_t *adapter_list) {
-    adapter_t *adapter_list_i = adapter_list;
+static void print_adapters(struct adapter *adapter_list) {
+    struct adapter *adapter_list_i = adapter_list;
     while (adapter_list_i != NULL) {
         if (strcmp(adapter_list_i->object_path, "/ADAPTER_HEAD") != 0) {
             pa_log("[ %s ]", adapter_list_i->object_path);
@@ -170,7 +176,7 @@ static void detect_adapters(struct userdata *u) {
     DBusError e;
     DBusMessage *m = NULL, *r = NULL;
     DBusMessageIter arg_i, element_i, dict_i, variant_i;
-    adapter_t *adapter_list_i;
+    struct adapter *adapter_list_i;
     const char *key, *value;
 
     pa_assert(u);
@@ -192,18 +198,18 @@ static void detect_adapters(struct userdata *u) {
         goto fail;
     }
     dbus_message_iter_recurse(&arg_i, &element_i);
-    /* TODO: Review error checking
-     * should this be changed to while (dbus_message_iter_get_arg_type(&element_i) == DBUS_TYPE_OBJECT_PATH) ? */
     while (dbus_message_iter_get_arg_type(&element_i) != DBUS_TYPE_INVALID) {
         if (dbus_message_iter_get_arg_type(&element_i) == DBUS_TYPE_OBJECT_PATH) {
+            struct adapter *node;
             dbus_message_iter_get_basic(&element_i, &value);
-            adapter_list_append(u->adapter_list, value);
+            node = adapter_new(value);
+            PA_LLIST_PREPEND(struct adapter, u->adapter_list, node);
         }
         dbus_message_iter_next(&element_i);
     }
 
     /* get adapter properties */
-    adapter_list_i = u->adapter_list->next;
+    adapter_list_i = u->adapter_list;
     while (adapter_list_i != NULL) {
         pa_assert_se(m = dbus_message_new_method_call("org.bluez", adapter_list_i->object_path, "org.bluez.Adapter", "GetProperties"));
         r = dbus_connection_send_with_reply_and_block(pa_dbus_connection_get(u->conn), m, -1, &e);
@@ -249,8 +255,8 @@ static void detect_devices(struct userdata *u) {
     DBusError e;
     DBusMessage *m = NULL, *r = NULL;
     DBusMessageIter arg_i, element_i, dict_i, variant_i;
-    adapter_t *adapter_list_i;
-    device_t *device_list_i, *device_list_prev_i;
+    struct adapter *adapter_list_i;
+    struct device *device_list_i;
     const char *key, *value;
     unsigned int uvalue;
 
@@ -258,7 +264,7 @@ static void detect_devices(struct userdata *u) {
     dbus_error_init(&e);
 
     /* get devices of each adapter */
-    adapter_list_i = u->adapter_list->next;
+    adapter_list_i = u->adapter_list;
     while (adapter_list_i != NULL) {
         pa_assert_se(m = dbus_message_new_method_call("org.bluez", adapter_list_i->object_path, "org.bluez.Adapter", "ListDevices"));
         r = dbus_connection_send_with_reply_and_block(pa_dbus_connection_get(u->conn), m, -1, &e);
@@ -275,12 +281,12 @@ static void detect_devices(struct userdata *u) {
             goto fail;
         }
         dbus_message_iter_recurse(&arg_i, &element_i);
-        /* TODO: Review error checking
-         * should this be changed to while (dbus_message_iter_get_arg_type(&element_i) == DBUS_TYPE_OBJECT_PATH) ? */
         while (dbus_message_iter_get_arg_type(&element_i) != DBUS_TYPE_INVALID) {
             if (dbus_message_iter_get_arg_type(&element_i) == DBUS_TYPE_OBJECT_PATH) {
+                struct device *node;
                 dbus_message_iter_get_basic(&element_i, &value);
-                device_list_append(adapter_list_i->device_list, value, adapter_list_i);
+                node = device_new(value, adapter_list_i);
+                PA_LLIST_PREPEND(struct device, adapter_list_i->device_list, node);
             }
             dbus_message_iter_next(&element_i);
         }
@@ -288,10 +294,9 @@ static void detect_devices(struct userdata *u) {
     }
 
     /* get device properties */
-    adapter_list_i = u->adapter_list->next;
+    adapter_list_i = u->adapter_list;
     while (adapter_list_i != NULL) {
-        device_list_prev_i = adapter_list_i->device_list;
-        device_list_i = adapter_list_i->device_list->next;
+        device_list_i = adapter_list_i->device_list;
         while (device_list_i != NULL) {
             pa_assert_se(m = dbus_message_new_method_call("org.bluez", device_list_i->object_path, "org.bluez.Device", "GetProperties"));
             r = dbus_connection_send_with_reply_and_block(pa_dbus_connection_get(u->conn), m, -1, &e);
@@ -335,16 +340,18 @@ static void detect_devices(struct userdata *u) {
                         pa_bool_t is_audio_device = FALSE;
                         dbus_message_iter_recurse(&variant_i, &uuid_i);
                         while (dbus_message_iter_get_arg_type(&uuid_i) != DBUS_TYPE_INVALID) {
+                            struct uuid *node;
                             dbus_message_iter_get_basic(&uuid_i, &value);
+                            node = uuid_new(value);
+                            PA_LLIST_PREPEND(struct uuid, device_list_i->uuid_list, node);
                             if ( (strcasecmp(value, HSP_HS_UUID) == 0) || (strcasecmp(value, HFP_HS_UUID) == 0) ||
                                 (strcasecmp(value, A2DP_SOURCE_UUID) == 0) || (strcasecmp(value, A2DP_SINK_UUID) == 0) )
                                 is_audio_device = TRUE;
-                            uuid_list_append(device_list_i->uuid_list, value);
                             dbus_message_iter_next(&uuid_i);
                         }
                         if (!is_audio_device) {
-                            /* remove current device */
-                            device_list_prev_i->next = device_list_i->next;
+                            /* remove the current device from the list */
+                            PA_LLIST_REMOVE(struct device, adapter_list_i->device_list, device_list_i);
                             pa_xfree(device_list_i);
                             break;
                         }
@@ -364,11 +371,7 @@ static void detect_devices(struct userdata *u) {
                 }
                 dbus_message_iter_next(&element_i);
             }
-            device_list_prev_i = device_list_prev_i->next;
-            if (device_list_prev_i == NULL)
-                device_list_i = NULL;
-            else
-                device_list_i = device_list_prev_i->next;
+            device_list_i = device_list_i->next;
         }
         adapter_list_i = adapter_list_i->next;
     }
@@ -445,27 +448,17 @@ static DBusHandlerResult filter_cb(DBusConnection *bus, DBusMessage *msg, void *
 
 void pa__done(pa_module* m) {
     struct userdata *u;
-    adapter_t *adapter_list_i, *adapter_list_next_i;
-    device_t *device_list_i, *device_list_next_i;
+    struct adapter *adapter_list_i;
 
     pa_assert(m);
 
     if (!(u = m->userdata))
         return;
 
-    if ((adapter_list_i = u->adapter_list) != NULL) {
-        while ((adapter_list_next_i = adapter_list_i->next) != NULL) {
-            if ((device_list_i = adapter_list_i->device_list) != NULL) {
-                while ((device_list_next_i = device_list_i->next) != NULL) {
-                    pa_xfree(device_list_i);
-                    device_list_i = device_list_next_i;
-                }
-                pa_xfree(device_list_i);
-            }
-            pa_xfree(adapter_list_i);
-            adapter_list_i = adapter_list_next_i;
-        }
-        pa_xfree(adapter_list_i);
+    while (u->adapter_list) {
+        adapter_list_i = u->adapter_list;
+        PA_LLIST_REMOVE(struct adapter, u->adapter_list, adapter_list_i);
+        adapter_free(adapter_list_i);
     }
 
     pa_dbus_connection_unref(u->conn);
@@ -477,15 +470,16 @@ void pa__done(pa_module* m) {
 int pa__init(pa_module* m) {
     pa_modargs *ma = NULL;
     DBusError err;
-    adapter_t *adapter_list_i;
-    device_t *device_list_i;
+    struct adapter *adapter_list_i;
+    struct device *device_list_i;
     struct userdata *u;
 
     pa_assert(m);
-    dbus_error_init(&err);
     pa_log("Loading module-bt-discover");
+    dbus_error_init(&err);
     m->userdata = u = pa_xnew0(struct userdata, 1);
     u->module = m;
+    PA_LLIST_HEAD_INIT(struct adapter, u->adapter_list);
 
     /* connect to the bus */
     u->conn = pa_dbus_bus_get(m->core, DBUS_BUS_SYSTEM, &err);
@@ -495,19 +489,18 @@ int pa__init(pa_module* m) {
     }
 
     /* static detection of bluetooth audio devices */
-    u->adapter_list = adapter_new("/ADAPTER_HEAD");
     detect_adapters(u);
     detect_devices(u);
 
     print_adapters(u->adapter_list);
 
     /* load device modules */
-    adapter_list_i = u->adapter_list->next;
+    adapter_list_i = u->adapter_list;
     while (adapter_list_i != NULL) {
-        device_list_i = adapter_list_i->device_list->next;
+        device_list_i = adapter_list_i->device_list;
         while (device_list_i != NULL) {
-            pa_log("Loading module-bt-device for %s", device_list_i->name); /* CHECK: Should it be name or alias? */
-            /* call module */
+            pa_log("Loading module-bt-device for %s", device_list_i->name);
+            /* TODO: call module */
             device_list_i = device_list_i->next;
         }
         adapter_list_i = adapter_list_i->next;

commit fe8bd53e22e5f8cffe44c2d773e1f0f51360fa28
Author: João Paulo Rechi Vita <joao.vita at gmail.com>
Date:   Thu Jul 24 14:36:01 2008 -0300

    Remove modargs, since module-bt-discover doesn't have any argument

diff --git a/src/modules/module-bt-discover.c b/src/modules/module-bt-discover.c
index b00a9c1..af3448b 100644
--- a/src/modules/module-bt-discover.c
+++ b/src/modules/module-bt-discover.c
@@ -468,7 +468,6 @@ void pa__done(pa_module* m) {
 }
 
 int pa__init(pa_module* m) {
-    pa_modargs *ma = NULL;
     DBusError err;
     struct adapter *adapter_list_i;
     struct device *device_list_i;
@@ -511,15 +510,12 @@ int pa__init(pa_module* m) {
         pa_log_error("Failed to add filter function");
         goto fail;
     }
-    dbus_connection_flush(pa_dbus_connection_get(u->conn));
     dbus_bus_add_match(pa_dbus_connection_get(u->conn), "type='signal',interface='org.bluez.Manager'", &err);
-    dbus_connection_flush(pa_dbus_connection_get(u->conn));
     if (dbus_error_is_set(&err)) {
         pa_log_error("Unable to subscribe to org.bluez.Manager signals: %s: %s", err.name, err.message);
         goto fail;
     }
     dbus_bus_add_match(pa_dbus_connection_get(u->conn), "type='signal',interface='org.bluez.Adapter'", &err);
-    dbus_connection_flush(pa_dbus_connection_get(u->conn));
     if (dbus_error_is_set(&err)) {
         pa_log_error("Unable to subscribe to org.bluez.Adapter signals: %s: %s", err.name, err.message);
         goto fail;
@@ -528,8 +524,6 @@ int pa__init(pa_module* m) {
     return 0;
 
 fail:
-    if (ma)
-        pa_modargs_free(ma);
     dbus_error_free(&err);
     pa__done(m);
     return -1;

commit ffe76a2daf873e04e39e6a7019f39bbd731b7df2
Author: João Paulo Rechi Vita <joao.vita at gmail.com>
Date:   Thu Jul 31 16:17:03 2008 -0300

    Add sender=org.bluez to dbus add match

diff --git a/src/modules/module-bt-discover.c b/src/modules/module-bt-discover.c
index af3448b..2b0d6c5 100644
--- a/src/modules/module-bt-discover.c
+++ b/src/modules/module-bt-discover.c
@@ -19,7 +19,9 @@
     USA.
 ***/
 
+#ifdef HAVE_CONFIG_H
 #include <config.h>
+#endif
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -510,12 +512,12 @@ int pa__init(pa_module* m) {
         pa_log_error("Failed to add filter function");
         goto fail;
     }
-    dbus_bus_add_match(pa_dbus_connection_get(u->conn), "type='signal',interface='org.bluez.Manager'", &err);
+    dbus_bus_add_match(pa_dbus_connection_get(u->conn), "type='signal',sender='org.bluez',interface='org.bluez.Manager'", &err);
     if (dbus_error_is_set(&err)) {
         pa_log_error("Unable to subscribe to org.bluez.Manager signals: %s: %s", err.name, err.message);
         goto fail;
     }
-    dbus_bus_add_match(pa_dbus_connection_get(u->conn), "type='signal',interface='org.bluez.Adapter'", &err);
+    dbus_bus_add_match(pa_dbus_connection_get(u->conn), "type='signal',sender='org.bluez',interface='org.bluez.Adapter'", &err);
     if (dbus_error_is_set(&err)) {
         pa_log_error("Unable to subscribe to org.bluez.Adapter signals: %s: %s", err.name, err.message);
         goto fail;

commit d8a0ec53da1afa182ab246f8798160ba1047b749
Author: João Paulo Rechi Vita <joao.vita at gmail.com>
Date:   Thu Jul 31 20:15:32 2008 -0300

    Add code from bluez/audio/ipc.[ch]

diff --git a/src/modules/bt-ipc.c b/src/modules/bt-ipc.c
new file mode 100644
index 0000000..e585328
--- /dev/null
+++ b/src/modules/bt-ipc.c
@@ -0,0 +1,119 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2004-2008  Marcel Holtmann <marcel at holtmann.org>
+ *
+ *  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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include "bt-ipc.h"
+
+/* This table contains the string representation for messages */
+static const char *strmsg[] = {
+	"BT_GETCAPABILITIES_REQ",
+	"BT_GETCAPABILITIES_RSP",
+	"BT_SETCONFIGURATION_REQ",
+	"BT_SETCONFIGURATION_RSP",
+	"BT_STREAMSTART_REQ",
+	"BT_STREAMSTART_RSP",
+	"BT_STREAMSTOP_REQ",
+	"BT_STREAMSTOP_RSP",
+	"BT_STREAMSUSPEND_IND",
+	"BT_STREAMRESUME_IND",
+	"BT_CONTROL_REQ",
+	"BT_CONTROL_RSP",
+	"BT_CONTROL_IND",
+	"BT_STREAMFD_IND",
+};
+
+int bt_audio_service_open()
+{
+	int sk;
+	int err;
+	struct sockaddr_un addr = {
+		AF_UNIX, BT_IPC_SOCKET_NAME
+	};
+
+	sk = socket(PF_LOCAL, SOCK_STREAM, 0);
+	if (sk < 0) {
+		err = errno;
+		fprintf(stderr, "%s: Cannot open socket: %s (%d)\n",
+			__FUNCTION__, strerror(err), err);
+		errno = err;
+		return -1;
+	}
+
+	if (connect(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
+		err = errno;
+		fprintf(stderr, "%s: connect() failed: %s (%d)\n",
+			__FUNCTION__, strerror(err), err);
+		close(sk);
+		errno = err;
+		return -1;
+	}
+
+	return sk;
+}
+
+int bt_audio_service_close(int sk)
+{
+	return close(sk);
+}
+
+int bt_audio_service_get_data_fd(int sk)
+{
+	char cmsg_b[CMSG_SPACE(sizeof(int))], m;
+	int err, ret;
+	struct iovec iov = { &m, sizeof(m) };
+	struct msghdr msgh;
+	struct cmsghdr *cmsg;
+
+	memset(&msgh, 0, sizeof(msgh));
+	msgh.msg_iov = &iov;
+	msgh.msg_iovlen = 1;
+	msgh.msg_control = &cmsg_b;
+	msgh.msg_controllen = CMSG_LEN(sizeof(int));
+
+	ret = recvmsg(sk, &msgh, 0);
+	if (ret < 0) {
+		err = errno;
+		fprintf(stderr, "%s: Unable to receive fd: %s (%d)\n",
+			__FUNCTION__, strerror(err), err);
+		errno = err;
+		return -1;
+	}
+
+	/* Receive auxiliary data in msgh */
+	for (cmsg = CMSG_FIRSTHDR(&msgh); cmsg != NULL;
+			cmsg = CMSG_NXTHDR(&msgh, cmsg)) {
+		if (cmsg->cmsg_level == SOL_SOCKET
+				&& cmsg->cmsg_type == SCM_RIGHTS)
+			return (*(int *) CMSG_DATA(cmsg));
+	}
+
+	errno = EINVAL;
+	return -1;
+}
+
+const char *bt_audio_strmsg(int type)
+{
+	if (type < 0 || type > (sizeof(strmsg) / sizeof(strmsg[0])))
+		return NULL;
+
+	return strmsg[type];
+}
+
diff --git a/src/modules/bt-ipc.h b/src/modules/bt-ipc.h
new file mode 100644
index 0000000..c900fcd
--- /dev/null
+++ b/src/modules/bt-ipc.h
@@ -0,0 +1,308 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2004-2008  Marcel Holtmann <marcel at holtmann.org>
+ *
+ *  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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+/*
+  Message sequence chart of streaming sequence for A2DP transport
+
+  Audio daemon                       User
+                             on snd_pcm_open
+                 <--BT_GETCAPABILITIES_REQ
+
+  BT_GETCAPABILITIES_RSP-->
+
+                        on snd_pcm_hw_params
+                <--BT_SETCONFIGURATION_REQ
+
+  BT_SETCONFIGURATION_RSP-->
+
+			on snd_pcm_prepare
+                <--BT_STREAMSTART_REQ
+
+  <Moves to streaming state>
+  BT_STREAMSTART_RSP-->
+
+  BT_STREAMFD_IND -->
+
+                          <  streams data >
+                             ..........
+
+               on snd_pcm_drop/snd_pcm_drain
+
+                <--BT_STREAMSTOP_REQ
+
+  <Moves to open state>
+  BT_STREAMSTOP_RSP-->
+
+			on IPC close or appl crash
+  <Moves to idle>
+
+ */
+
+#ifndef BT_AUDIOCLIENT_H
+#define BT_AUDIOCLIENT_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <errno.h>
+
+#define BT_AUDIO_IPC_PACKET_SIZE   128
+#define BT_IPC_SOCKET_NAME "\0/org/bluez/audio"
+
+/* Generic message header definition, except for RSP messages */
+typedef struct {
+	uint8_t msg_type;
+} __attribute__ ((packed)) bt_audio_msg_header_t;
+
+/* Generic message header definition, for all RSP messages */
+typedef struct {
+	bt_audio_msg_header_t	msg_h;
+	uint8_t			posix_errno;
+} __attribute__ ((packed)) bt_audio_rsp_msg_header_t;
+
+/* Messages list */
+#define BT_GETCAPABILITIES_REQ		0
+#define BT_GETCAPABILITIES_RSP		1
+
+#define BT_SETCONFIGURATION_REQ		2
+#define BT_SETCONFIGURATION_RSP		3
+
+#define BT_STREAMSTART_REQ		4
+#define BT_STREAMSTART_RSP		5
+
+#define BT_STREAMSTOP_REQ		6
+#define BT_STREAMSTOP_RSP		7
+
+#define BT_STREAMSUSPEND_IND		8
+#define BT_STREAMRESUME_IND		9
+
+#define BT_CONTROL_REQ		       10
+#define BT_CONTROL_RSP		       11
+#define BT_CONTROL_IND		       12
+
+#define BT_STREAMFD_IND		       13
+
+/* BT_GETCAPABILITIES_REQ */
+
+#define BT_CAPABILITIES_TRANSPORT_A2DP	0
+#define BT_CAPABILITIES_TRANSPORT_SCO	1
+#define BT_CAPABILITIES_TRANSPORT_ANY	2
+
+#define BT_CAPABILITIES_ACCESS_MODE_READ	1
+#define BT_CAPABILITIES_ACCESS_MODE_WRITE	2
+#define BT_CAPABILITIES_ACCESS_MODE_READWRITE	3
+
+#define BT_FLAG_AUTOCONNECT	1
+
+struct bt_getcapabilities_req {
+	bt_audio_msg_header_t	h;
+	char			device[18];	/* Address of the remote Device */
+	uint8_t			transport;	/* Requested transport */
+	uint8_t			flags;		/* Requested flags */
+} __attribute__ ((packed));
+
+/* BT_GETCAPABILITIES_RSP */
+
+/**
+ * SBC Codec parameters as per A2DP profile 1.0 § 4.3
+ */
+
+#define BT_SBC_SAMPLING_FREQ_16000		(1 << 3)
+#define BT_SBC_SAMPLING_FREQ_32000		(1 << 2)
+#define BT_SBC_SAMPLING_FREQ_44100		(1 << 1)
+#define BT_SBC_SAMPLING_FREQ_48000		1
+
+#define BT_A2DP_CHANNEL_MODE_MONO		(1 << 3)
+#define BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL	(1 << 2)
+#define BT_A2DP_CHANNEL_MODE_STEREO		(1 << 1)
+#define BT_A2DP_CHANNEL_MODE_JOINT_STEREO	1
+
+#define BT_A2DP_BLOCK_LENGTH_4			(1 << 3)
+#define BT_A2DP_BLOCK_LENGTH_8			(1 << 2)
+#define BT_A2DP_BLOCK_LENGTH_12			(1 << 1)
+#define BT_A2DP_BLOCK_LENGTH_16			1
+
+#define BT_A2DP_SUBBANDS_4			(1 << 1)
+#define BT_A2DP_SUBBANDS_8			1
+
+#define BT_A2DP_ALLOCATION_SNR			(1 << 1)
+#define BT_A2DP_ALLOCATION_LOUDNESS		1
+
+#define BT_MPEG_SAMPLING_FREQ_16000		(1 << 5)
+#define BT_MPEG_SAMPLING_FREQ_22050		(1 << 4)
+#define BT_MPEG_SAMPLING_FREQ_24000		(1 << 3)
+#define BT_MPEG_SAMPLING_FREQ_32000		(1 << 2)
+#define BT_MPEG_SAMPLING_FREQ_44100		(1 << 1)
+#define BT_MPEG_SAMPLING_FREQ_48000		1
+
+#define BT_MPEG_LAYER_1				(1 << 2)
+#define BT_MPEG_LAYER_2				(1 << 1)
+#define BT_MPEG_LAYER_3				1
+
+typedef struct {
+	uint8_t channel_mode;
+	uint8_t frequency;
+	uint8_t allocation_method;
+	uint8_t subbands;
+	uint8_t block_length;
+	uint8_t min_bitpool;
+	uint8_t max_bitpool;
+} __attribute__ ((packed)) sbc_capabilities_t;
+
+typedef struct {
+	uint8_t channel_mode;
+	uint8_t crc;
+	uint8_t layer;
+	uint8_t frequency;
+	uint8_t mpf;
+	uint16_t bitrate;
+} __attribute__ ((packed)) mpeg_capabilities_t;
+
+struct bt_getcapabilities_rsp {
+	bt_audio_rsp_msg_header_t	rsp_h;
+	uint8_t				transport;	   /* Granted transport */
+	sbc_capabilities_t		sbc_capabilities;  /* A2DP only */
+	mpeg_capabilities_t		mpeg_capabilities; /* A2DP only */
+	uint16_t			sampling_rate;	   /* SCO only */
+} __attribute__ ((packed));
+
+/* BT_SETCONFIGURATION_REQ */
+struct bt_setconfiguration_req {
+	bt_audio_msg_header_t	h;
+	char			device[18];		/* Address of the remote Device */
+	uint8_t			transport;		/* Requested transport */
+	uint8_t			access_mode;		/* Requested access mode */
+	sbc_capabilities_t	sbc_capabilities;	/* A2DP only - only one of this field
+							and next one must be filled */
+	mpeg_capabilities_t	mpeg_capabilities;	/* A2DP only */
+} __attribute__ ((packed));
+
+/* BT_SETCONFIGURATION_RSP */
+struct bt_setconfiguration_rsp {
+	bt_audio_rsp_msg_header_t	rsp_h;
+	uint8_t				transport;	/* Granted transport */
+	uint8_t				access_mode;	/* Granted access mode */
+	uint16_t			link_mtu;	/* Max length that transport supports */
+} __attribute__ ((packed));
+
+/* BT_STREAMSTART_REQ */
+#define BT_STREAM_ACCESS_READ		0
+#define BT_STREAM_ACCESS_WRITE		1
+#define BT_STREAM_ACCESS_READWRITE	2
+struct bt_streamstart_req {
+	bt_audio_msg_header_t	h;
+} __attribute__ ((packed));
+
+/* BT_STREAMSTART_RSP */
+struct bt_streamstart_rsp {
+	bt_audio_rsp_msg_header_t	rsp_h;
+} __attribute__ ((packed));
+
+/* BT_STREAMFD_IND */
+/* This message is followed by one byte of data containing the stream data fd
+   as ancilliary data */
+struct bt_streamfd_ind {
+	bt_audio_msg_header_t	h;
+} __attribute__ ((packed));
+
+/* BT_STREAMSTOP_REQ */
+struct bt_streamstop_req {
+	bt_audio_msg_header_t	h;
+} __attribute__ ((packed));
+
+/* BT_STREAMSTOP_RSP */
+struct bt_streamstop_rsp {
+	bt_audio_rsp_msg_header_t	rsp_h;
+} __attribute__ ((packed));
+
+/* BT_STREAMSUSPEND_IND */
+struct bt_streamsuspend_ind {
+	bt_audio_msg_header_t	h;
+} __attribute__ ((packed));
+
+/* BT_STREAMRESUME_IND */
+struct bt_streamresume_ind {
+	bt_audio_msg_header_t	h;
+} __attribute__ ((packed));
+
+/* BT_CONTROL_REQ */
+
+#define BT_CONTROL_KEY_POWER			0x40
+#define BT_CONTROL_KEY_VOL_UP			0x41
+#define BT_CONTROL_KEY_VOL_DOWN			0x42
+#define BT_CONTROL_KEY_MUTE			0x43
+#define BT_CONTROL_KEY_PLAY			0x44
+#define BT_CONTROL_KEY_STOP			0x45
+#define BT_CONTROL_KEY_PAUSE			0x46
+#define BT_CONTROL_KEY_RECORD			0x47
+#define BT_CONTROL_KEY_REWIND			0x48
+#define BT_CONTROL_KEY_FAST_FORWARD		0x49
+#define BT_CONTROL_KEY_EJECT			0x4A
+#define BT_CONTROL_KEY_FORWARD			0x4B
+#define BT_CONTROL_KEY_BACKWARD			0x4C
+
+struct bt_control_req {
+	bt_audio_msg_header_t	h;
+	uint8_t			mode;		/* Control Mode */
+	uint8_t			key;		/* Control Key */
+} __attribute__ ((packed));
+
+/* BT_CONTROL_RSP */
+struct bt_control_rsp {
+	bt_audio_rsp_msg_header_t	rsp_h;
+	uint8_t				mode;	/* Control Mode */
+	uint8_t				key;	/* Control Key */
+} __attribute__ ((packed));
+
+/* BT_CONTROL_IND */
+struct bt_control_ind {
+	bt_audio_msg_header_t	h;
+	uint8_t			mode;		/* Control Mode */
+	uint8_t			key;		/* Control Key */
+} __attribute__ ((packed));
+
+/* Function declaration */
+
+/* Opens a connection to the audio service: return a socket descriptor */
+int bt_audio_service_open();
+
+/* Closes a connection to the audio service */
+int bt_audio_service_close(int sk);
+
+/* Receives stream data file descriptor : must be called after a
+BT_STREAMFD_IND message is returned */
+int bt_audio_service_get_data_fd(int sk);
+
+/* Human readable message type string */
+const char *bt_audio_strmsg(int type);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* BT_AUDIOCLIENT_H */

commit ee68292c6165218bf8c488edb38036dae780766a
Author: João Paulo Rechi Vita <joao.vita at gmail.com>
Date:   Thu Jul 31 20:16:43 2008 -0300

    Initial file for module-bt-device

diff --git a/src/modules/module-bt-device.c b/src/modules/module-bt-device.c
new file mode 100644
index 0000000..8690e31
--- /dev/null
+++ b/src/modules/module-bt-device.c
@@ -0,0 +1,154 @@
+/***
+    This file is part of PulseAudio.
+
+    Copyright 2008 Joao Paulo Rechi Vita
+
+    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.
+
+    1. Connects to the BlueZ audio service via one BlueZ specific well known unix socket
+        bluez/audio/ipc: bt_audio_service_open()
+    2. Configures a connection to the BT device
+    3. Gets a BT socket fd passed in via the unix socket
+        bluez/audio/ipc: bt_audio_service_get_data_fd()
+    4. Hands this over to its RT thread.
+        pa_thread_mq
+***/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <pulse/xmalloc.h>
+#include <pulsecore/module.h>
+#include <pulsecore/modargs.h>
+
+#include "dbus-util.h"
+#include "module-bt-device-symdef.h"
+#include "bt-ipc.h"
+
+PA_MODULE_AUTHOR("Joao Paulo Rechi Vita");
+PA_MODULE_DESCRIPTION("Bluetooth audio sink and source");
+PA_MODULE_VERSION(PACKAGE_VERSION);
+PA_MODULE_LOAD_ONCE(FALSE);
+PA_MODULE_USAGE(
+        "addr=<address of the device> "
+        "uuid=<the profile that this device will work on>");
+
+struct userdata {
+    pa_core *core;
+    pa_module *module;
+    pa_sink *sink;
+
+    const char *addr;
+    const char *uuid;
+};
+
+static const char* const valid_modargs[] = {
+    "addr",
+    "uuid",
+    NULL
+};
+
+static int audioservice_send(int sk, const bt_audio_msg_header_t *msg) {
+    int e;
+    pa_log("sending %s", bt_audio_strmsg(msg->msg_type)); /*debug*/
+    if (send(sk, msg, BT_AUDIO_IPC_PACKET_SIZE, 0) > 0)
+        e = 0;
+    else {
+        e = -errno;
+        pa_log_error("Error sending data to audio service: %s(%d)", strerror(errno), errno);
+    }
+    return e;
+}
+
+static int audioservice_recv(int sk, bt_audio_msg_header_t *inmsg) {
+    int err;
+    const char *type;
+
+    pa_log/*_debug*/("trying to receive msg from audio service...");
+    if (recv(sk, inmsg, BT_AUDIO_IPC_PACKET_SIZE, 0) > 0) {
+        type = bt_audio_strmsg(inmsg->msg_type);
+        if (type) {
+            pa_log/*_debug*/("Received %s", type);
+            err = 0;
+        }
+        else {
+            err = -EINVAL;
+            pa_log_error("Bogus message type %d received from audio service", inmsg->msg_type);
+        }
+    }
+    else {
+        err = -errno;
+        pa_log_error("Error receiving data from audio service: %s(%d)", strerror(errno), errno);
+    }
+
+    return err;
+}
+
+static int audioservice_expect(int sk, bt_audio_msg_header_t *rsp_hdr, int expected_type) {
+    int err = audioservice_recv(sk, rsp_hdr);
+    if (err == 0) {
+        if (rsp_hdr->msg_type != expected_type) {
+            err = -EINVAL;
+            pa_log_error("Bogus message %s received while %s was expected", bt_audio_strmsg(rsp_hdr->msg_type),
+                    bt_audio_strmsg(expected_type));
+        }
+    }
+    return err;
+}
+
+int pa__init(pa_module* m) {
+    pa_modargs *ma;
+    struct userdata *u;
+    int sk = -1;
+
+    pa_assert(m);
+    m->userdata = u = pa_xnew0(struct userdata, 1);
+    u->module = m;
+
+    if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
+        pa_log_error("failed to parse module arguments");
+        goto fail;
+    }
+    if (!(u->addr = pa_modargs_get_value(ma, "addr", NULL))) {
+        pa_log_error("failed to parse device address from module arguments");
+        goto fail;
+    }
+    if (!(u->uuid = pa_modargs_get_value(ma, "uuid", NULL))) {
+        pa_log_error("failed to parse device uuid from module arguments");
+        goto fail;
+    }
+    pa_log("Loading module-bt-device for %s, UUID=%s", u->addr, u->uuid);
+
+    /* Connects to the BlueZ audio service via one BlueZ specific well known unix socket */
+    sk = bt_audio_service_open();
+    if (sk <= 0) {
+        pa_log_error("couldn't connect to bluetooth audio service");
+        goto fail;
+    }
+    pa_log("socket to audio service: %d", sk); /*debug*/
+
+    return 0;
+
+fail:
+    pa__done(m);
+    return -1;
+}
+
+void pa__done(pa_module *m) {
+    pa_log("Unloading module-bt-device");
+}
+

commit c62c2ff4ad334baf6fb3a74af2e24f1a48421fbe
Author: João Paulo Rechi Vita <joao.vita at gmail.com>
Date:   Thu Jul 31 20:17:17 2008 -0300

    Add module-bt-device and dependencies to automake

diff --git a/src/Makefile.am b/src/Makefile.am
index ae0fca0..71bddd5 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1161,7 +1161,9 @@ endif
 if HAVE_BLUEZ
 modlibexec_LTLIBRARIES += \
 		module-bt-proximity.la \
-		module-bt-discover.la
+		module-bt-discover.la \
+		libbt-ipc.la \
+		module-bt-device.la
 
 pulselibexec_PROGRAMS += \
 		bt-proximity-helper
@@ -1222,6 +1224,7 @@ SYMDEF_FILES = \
 		modules/module-hal-detect-symdef.h \
 		modules/module-bt-proximity-symdef.h \
 		modules/module-bt-discover-symdef.h \
+		modules/module-bt-device-symdef.h \
 		modules/gconf/module-gconf-symdef.h \
 		modules/module-position-event-sounds-symdef.h \
 		modules/module-console-kit-symdef.h
@@ -1568,6 +1571,17 @@ module_bt_discover_la_LDFLAGS = -module -avoid-version
 module_bt_discover_la_LIBADD = $(AM_LIBADD) $(DBUS_LIBS) libpulsecore.la libdbus-util.la
 module_bt_discover_la_CFLAGS = $(AM_CFLAGS) $(DBUS_CFLAGS)
 
+# Bluetooth device
+libbt_ipc_la_SOURCES = modules/bt-ipc.c modules/bt-ipc.h
+libbt_ipc_la_LDFLAGS = -avoid-version
+libbt_ipc_la_LIBADD = $(AM_LIBADD)
+libbt_ipc_la_CFLAGS = $(AM_CFLAGS)
+
+module_bt_device_la_SOURCES = modules/module-bt-device.c
+module_bt_device_la_LDFLAGS = -module -avoid-version
+module_bt_device_la_LIBADD = $(AM_LIBADD) $(DBUS_LIBS) libpulsecore.la libdbus-util.la libbt-ipc.la
+module_bt_device_la_CFLAGS = $(AM_CFLAGS) $(DBUS_CFLAGS)
+
 ###################################
 #        Some minor stuff         #
 ###################################

commit e7b0839d17a0d9c084ee7301e9db651ddd3b5e30
Author: João Paulo Rechi Vita <joao.vita at gmail.com>
Date:   Mon Aug 11 13:26:10 2008 -0300

    Adds SBC Codec to pa tree

diff --git a/src/Makefile.am b/src/Makefile.am
index 71bddd5..055ece5 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1163,6 +1163,7 @@ modlibexec_LTLIBRARIES += \
 		module-bt-proximity.la \
 		module-bt-discover.la \
 		libbt-ipc.la \
+		libbt-sbc.la \
 		module-bt-device.la
 
 pulselibexec_PROGRAMS += \
@@ -1572,6 +1573,11 @@ module_bt_discover_la_LIBADD = $(AM_LIBADD) $(DBUS_LIBS) libpulsecore.la libdbus
 module_bt_discover_la_CFLAGS = $(AM_CFLAGS) $(DBUS_CFLAGS)
 
 # Bluetooth device
+libbt_sbc_la_SOURCES = modules/bt-sbc.c modules/bt-sbc.h modules/bt-sbc_tables.h modules/bt-sbc_math.h
+libbt_sbc_la_LDFLAGS = -avoid-version
+libbt_sbc_la_LIBADD = $(AM_LIBADD)
+libbt_sbc_la_CFLAGS = $(AM_CFLAGS)
+
 libbt_ipc_la_SOURCES = modules/bt-ipc.c modules/bt-ipc.h
 libbt_ipc_la_LDFLAGS = -avoid-version
 libbt_ipc_la_LIBADD = $(AM_LIBADD)
@@ -1579,7 +1585,7 @@ libbt_ipc_la_CFLAGS = $(AM_CFLAGS)
 
 module_bt_device_la_SOURCES = modules/module-bt-device.c
 module_bt_device_la_LDFLAGS = -module -avoid-version
-module_bt_device_la_LIBADD = $(AM_LIBADD) $(DBUS_LIBS) libpulsecore.la libdbus-util.la libbt-ipc.la
+module_bt_device_la_LIBADD = $(AM_LIBADD) $(DBUS_LIBS) libpulsecore.la libdbus-util.la libbt-ipc.la libbt-sbc.la
 module_bt_device_la_CFLAGS = $(AM_CFLAGS) $(DBUS_CFLAGS)
 
 ###################################
diff --git a/src/modules/bt-sbc.c b/src/modules/bt-sbc.c
new file mode 100644
index 0000000..8e7b060
--- /dev/null
+++ b/src/modules/bt-sbc.c
@@ -0,0 +1,1411 @@
+/*
+ *
+ *  Bluetooth low-complexity, subband codec (SBC) library
+ *
+ *  Copyright (C) 2004-2008  Marcel Holtmann <marcel at holtmann.org>
+ *  Copyright (C) 2004-2005  Henryk Ploetz <henryk at ploetzli.ch>
+ *  Copyright (C) 2005-2008  Brad Midgley <bmidgley at xmission.com>
+ *
+ *
+ *  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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+/* todo items:
+
+  use a log2 table for byte integer scale factors calculation (sum log2 results
+  for high and low bytes) fill bitpool by 16 bits instead of one at a time in
+  bits allocation/bitpool generation port to the dsp
+
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/types.h>
+
+#include "bt-sbc_math.h"
+#include "bt-sbc_tables.h"
+
+#include "bt-sbc.h"
+
+#define SBC_SYNCWORD	0x9C
+
+/* This structure contains an unpacked SBC frame.
+   Yes, there is probably quite some unused space herein */
+struct sbc_frame {
+	uint8_t frequency;
+	uint8_t block_mode;
+	uint8_t blocks;
+	enum {
+		MONO		= SBC_MODE_MONO,
+		DUAL_CHANNEL	= SBC_MODE_DUAL_CHANNEL,
+		STEREO		= SBC_MODE_STEREO,
+		JOINT_STEREO	= SBC_MODE_JOINT_STEREO
+	} mode;
+	uint8_t channels;
+	enum {
+		LOUDNESS	= SBC_AM_LOUDNESS,
+		SNR		= SBC_AM_SNR
+	} allocation;
+	uint8_t subband_mode;
+	uint8_t subbands;
+	uint8_t bitpool;
+	uint8_t codesize;
+	uint8_t length;
+
+	/* bit number x set means joint stereo has been used in subband x */
+	uint8_t joint;
+
+	/* only the lower 4 bits of every element are to be used */
+	uint8_t scale_factor[2][8];
+
+	/* raw integer subband samples in the frame */
+
+	int32_t sb_sample_f[16][2][8];
+	int32_t sb_sample[16][2][8];	/* modified subband samples */
+	int16_t pcm_sample[2][16*8];	/* original pcm audio samples */
+};
+
+struct sbc_decoder_state {
+	int subbands;
+	int32_t V[2][170];
+	int offset[2][16];
+};
+
+struct sbc_encoder_state {
+	int subbands;
+	int position[2];
+	int32_t X[2][160];
+};
+
+/*
+ * Calculates the CRC-8 of the first len bits in data
+ */
+static const uint8_t crc_table[256] = {
+	0x00, 0x1D, 0x3A, 0x27, 0x74, 0x69, 0x4E, 0x53,
+	0xE8, 0xF5, 0xD2, 0xCF, 0x9C, 0x81, 0xA6, 0xBB,
+	0xCD, 0xD0, 0xF7, 0xEA, 0xB9, 0xA4, 0x83, 0x9E,
+	0x25, 0x38, 0x1F, 0x02, 0x51, 0x4C, 0x6B, 0x76,
+	0x87, 0x9A, 0xBD, 0xA0, 0xF3, 0xEE, 0xC9, 0xD4,
+	0x6F, 0x72, 0x55, 0x48, 0x1B, 0x06, 0x21, 0x3C,
+	0x4A, 0x57, 0x70, 0x6D, 0x3E, 0x23, 0x04, 0x19,
+	0xA2, 0xBF, 0x98, 0x85, 0xD6, 0xCB, 0xEC, 0xF1,
+	0x13, 0x0E, 0x29, 0x34, 0x67, 0x7A, 0x5D, 0x40,
+	0xFB, 0xE6, 0xC1, 0xDC, 0x8F, 0x92, 0xB5, 0xA8,
+	0xDE, 0xC3, 0xE4, 0xF9, 0xAA, 0xB7, 0x90, 0x8D,
+	0x36, 0x2B, 0x0C, 0x11, 0x42, 0x5F, 0x78, 0x65,
+	0x94, 0x89, 0xAE, 0xB3, 0xE0, 0xFD, 0xDA, 0xC7,
+	0x7C, 0x61, 0x46, 0x5B, 0x08, 0x15, 0x32, 0x2F,
+	0x59, 0x44, 0x63, 0x7E, 0x2D, 0x30, 0x17, 0x0A,
+	0xB1, 0xAC, 0x8B, 0x96, 0xC5, 0xD8, 0xFF, 0xE2,
+	0x26, 0x3B, 0x1C, 0x01, 0x52, 0x4F, 0x68, 0x75,
+	0xCE, 0xD3, 0xF4, 0xE9, 0xBA, 0xA7, 0x80, 0x9D,
+	0xEB, 0xF6, 0xD1, 0xCC, 0x9F, 0x82, 0xA5, 0xB8,
+	0x03, 0x1E, 0x39, 0x24, 0x77, 0x6A, 0x4D, 0x50,
+	0xA1, 0xBC, 0x9B, 0x86, 0xD5, 0xC8, 0xEF, 0xF2,
+	0x49, 0x54, 0x73, 0x6E, 0x3D, 0x20, 0x07, 0x1A,
+	0x6C, 0x71, 0x56, 0x4B, 0x18, 0x05, 0x22, 0x3F,
+	0x84, 0x99, 0xBE, 0xA3, 0xF0, 0xED, 0xCA, 0xD7,
+	0x35, 0x28, 0x0F, 0x12, 0x41, 0x5C, 0x7B, 0x66,
+	0xDD, 0xC0, 0xE7, 0xFA, 0xA9, 0xB4, 0x93, 0x8E,
+	0xF8, 0xE5, 0xC2, 0xDF, 0x8C, 0x91, 0xB6, 0xAB,
+	0x10, 0x0D, 0x2A, 0x37, 0x64, 0x79, 0x5E, 0x43,
+	0xB2, 0xAF, 0x88, 0x95, 0xC6, 0xDB, 0xFC, 0xE1,
+	0x5A, 0x47, 0x60, 0x7D, 0x2E, 0x33, 0x14, 0x09,
+	0x7F, 0x62, 0x45, 0x58, 0x0B, 0x16, 0x31, 0x2C,
+	0x97, 0x8A, 0xAD, 0xB0, 0xE3, 0xFE, 0xD9, 0xC4
+};
+
+static uint8_t sbc_crc8(const uint8_t *data, size_t len)
+{
+	uint8_t crc = 0x0f;
+	size_t i;
+	uint8_t octet;
+
+	for (i = 0; i < len / 8; i++)
+		crc = crc_table[crc ^ data[i]];
+
+	octet = data[i];
+	for (i = 0; i < len % 8; i++) {
+		char bit = ((octet ^ crc) & 0x80) >> 7;
+
+		crc = ((crc & 0x7f) << 1) ^ (bit ? 0x1d : 0);
+
+		octet = octet << 1;
+	}
+
+	return crc;
+}
+
+/*
+ * Code straight from the spec to calculate the bits array
+ * Takes a pointer to the frame in question, a pointer to the bits array and
+ * the sampling frequency (as 2 bit integer)
+ */
+static void sbc_calculate_bits(const struct sbc_frame *frame, int (*bits)[8])
+{
+	uint8_t sf = frame->frequency;
+
+	if (frame->mode == MONO || frame->mode == DUAL_CHANNEL) {
+		int bitneed[2][8], loudness, max_bitneed, bitcount, slicecount, bitslice;
+		int ch, sb;
+
+		for (ch = 0; ch < frame->channels; ch++) {
+			max_bitneed = 0;
+			if (frame->allocation == SNR) {
+				for (sb = 0; sb < frame->subbands; sb++) {
+					bitneed[ch][sb] = frame->scale_factor[ch][sb];
+					if (bitneed[ch][sb] > max_bitneed)
+						max_bitneed = bitneed[ch][sb];
+				}
+			} else {
+				for (sb = 0; sb < frame->subbands; sb++) {
+					if (frame->scale_factor[ch][sb] == 0)
+						bitneed[ch][sb] = -5;
+					else {
+						if (frame->subbands == 4)
+							loudness = frame->scale_factor[ch][sb] - sbc_offset4[sf][sb];
+						else
+							loudness = frame->scale_factor[ch][sb] - sbc_offset8[sf][sb];
+						if (loudness > 0)
+							bitneed[ch][sb] = loudness / 2;
+						else
+							bitneed[ch][sb] = loudness;
+					}
+					if (bitneed[ch][sb] > max_bitneed)
+						max_bitneed = bitneed[ch][sb];
+				}
+			}
+
+			bitcount = 0;
+			slicecount = 0;
+			bitslice = max_bitneed + 1;
+			do {
+				bitslice--;
+				bitcount += slicecount;
+				slicecount = 0;
+				for (sb = 0; sb < frame->subbands; sb++) {
+					if ((bitneed[ch][sb] > bitslice + 1) && (bitneed[ch][sb] < bitslice + 16))
+						slicecount++;
+					else if (bitneed[ch][sb] == bitslice + 1)
+						slicecount += 2;
+				}
+			} while (bitcount + slicecount < frame->bitpool);
+
+			if (bitcount + slicecount == frame->bitpool) {
+				bitcount += slicecount;
+				bitslice--;
+			}
+
+			for (sb = 0; sb < frame->subbands; sb++) {
+				if (bitneed[ch][sb] < bitslice + 2)
+					bits[ch][sb] = 0;
+				else {
+					bits[ch][sb] = bitneed[ch][sb] - bitslice;
+					if (bits[ch][sb] > 16)
+						bits[ch][sb] = 16;
+				}
+			}
+
+			for (sb = 0; bitcount < frame->bitpool && sb < frame->subbands; sb++) {
+				if ((bits[ch][sb] >= 2) && (bits[ch][sb] < 16)) {
+					bits[ch][sb]++;
+					bitcount++;
+				} else if ((bitneed[ch][sb] == bitslice + 1) && (frame->bitpool > bitcount + 1)) {
+					bits[ch][sb] = 2;
+					bitcount += 2;
+				}
+			}
+
+			for (sb = 0; bitcount < frame->bitpool && sb < frame->subbands; sb++) {
+				if (bits[ch][sb] < 16) {
+					bits[ch][sb]++;
+					bitcount++;
+				}
+			}
+
+		}
+
+	} else if (frame->mode == STEREO || frame->mode == JOINT_STEREO) {
+		int bitneed[2][8], loudness, max_bitneed, bitcount, slicecount, bitslice;
+		int ch, sb;
+
+		max_bitneed = 0;
+		if (frame->allocation == SNR) {
+			for (ch = 0; ch < 2; ch++) {
+				for (sb = 0; sb < frame->subbands; sb++) {
+					bitneed[ch][sb] = frame->scale_factor[ch][sb];
+					if (bitneed[ch][sb] > max_bitneed)
+						max_bitneed = bitneed[ch][sb];
+				}
+			}
+		} else {
+			for (ch = 0; ch < 2; ch++) {
+				for (sb = 0; sb < frame->subbands; sb++) {
+					if (frame->scale_factor[ch][sb] == 0)
+						bitneed[ch][sb] = -5;
+					else {
+						if (frame->subbands == 4)
+							loudness = frame->scale_factor[ch][sb] - sbc_offset4[sf][sb];
+						else
+							loudness = frame->scale_factor[ch][sb] - sbc_offset8[sf][sb];
+						if (loudness > 0)
+							bitneed[ch][sb] = loudness / 2;
+						else
+							bitneed[ch][sb] = loudness;
+					}
+					if (bitneed[ch][sb] > max_bitneed)
+						max_bitneed = bitneed[ch][sb];
+				}
+			}
+		}
+
+		bitcount = 0;
+		slicecount = 0;
+		bitslice = max_bitneed + 1;
+		do {
+			bitslice--;
+			bitcount += slicecount;
+			slicecount = 0;
+			for (ch = 0; ch < 2; ch++) {
+				for (sb = 0; sb < frame->subbands; sb++) {
+					if ((bitneed[ch][sb] > bitslice + 1) && (bitneed[ch][sb] < bitslice + 16))
+						slicecount++;
+					else if (bitneed[ch][sb] == bitslice + 1)
+						slicecount += 2;
+				}
+			}
+		} while (bitcount + slicecount < frame->bitpool);
+
+		if (bitcount + slicecount == frame->bitpool) {
+			bitcount += slicecount;
+			bitslice--;
+		}
+
+		for (ch = 0; ch < 2; ch++) {
+			for (sb = 0; sb < frame->subbands; sb++) {
+				if (bitneed[ch][sb] < bitslice + 2) {
+					bits[ch][sb] = 0;
+				} else {
+					bits[ch][sb] = bitneed[ch][sb] - bitslice;
+					if (bits[ch][sb] > 16)
+						bits[ch][sb] = 16;
+				}
+			}
+		}
+
+		ch = 0;
+		sb = 0;
+		while (bitcount < frame->bitpool) {
+			if ((bits[ch][sb] >= 2) && (bits[ch][sb] < 16)) {
+				bits[ch][sb]++;
+				bitcount++;
+			} else if ((bitneed[ch][sb] == bitslice + 1) && (frame->bitpool > bitcount + 1)) {
+				bits[ch][sb] = 2;
+				bitcount += 2;
+			}
+			if (ch == 1) {
+				ch = 0;
+				sb++;
+				if (sb >= frame->subbands) break;
+			} else
+				ch = 1;
+		}
+
+		ch = 0;
+		sb = 0;
+		while (bitcount < frame->bitpool) {
+			if (bits[ch][sb] < 16) {
+				bits[ch][sb]++;
+				bitcount++;
+			}
+			if (ch == 1) {
+				ch = 0;
+				sb++;
+				if (sb >= frame->subbands) break;
+			} else
+				ch = 1;
+		}
+
+	}
+
+}
+
+/*
+ * Unpacks a SBC frame at the beginning of the stream in data,
+ * which has at most len bytes into frame.
+ * Returns the length in bytes of the packed frame, or a negative
+ * value on error. The error codes are:
+ *
+ *  -1   Data stream too short
+ *  -2   Sync byte incorrect
+ *  -3   CRC8 incorrect
+ *  -4   Bitpool value out of bounds
+ */
+static int sbc_unpack_frame(const uint8_t *data, struct sbc_frame *frame,
+				size_t len)
+{
+	int consumed;
+	/* Will copy the parts of the header that are relevant to crc
+	 * calculation here */
+	uint8_t crc_header[11] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+	int crc_pos = 0;
+	int32_t temp;
+
+	int audio_sample;
+	int ch, sb, blk, bit;	/* channel, subband, block and bit standard
+				   counters */
+	int bits[2][8];		/* bits distribution */
+	uint32_t levels[2][8];	/* levels derived from that */
+
+	if (len < 4)
+		return -1;
+
+	if (data[0] != SBC_SYNCWORD)
+		return -2;
+
+	frame->frequency = (data[1] >> 6) & 0x03;
+
+	frame->block_mode = (data[1] >> 4) & 0x03;
+	switch (frame->block_mode) {
+	case SBC_BLK_4:
+		frame->blocks = 4;
+		break;
+	case SBC_BLK_8:
+		frame->blocks = 8;
+		break;
+	case SBC_BLK_12:
+		frame->blocks = 12;
+		break;
+	case SBC_BLK_16:
+		frame->blocks = 16;
+		break;
+	}
+
+	frame->mode = (data[1] >> 2) & 0x03;
+	switch (frame->mode) {
+	case MONO:
+		frame->channels = 1;
+		break;
+	case DUAL_CHANNEL:	/* fall-through */
+	case STEREO:
+	case JOINT_STEREO:
+		frame->channels = 2;
+		break;
+	}
+
+	frame->allocation = (data[1] >> 1) & 0x01;
+
+	frame->subband_mode = (data[1] & 0x01);
+	frame->subbands = frame->subband_mode ? 8 : 4;
+
+	frame->bitpool = data[2];
+
+	if ((frame->mode == MONO || frame->mode == DUAL_CHANNEL) &&
+			frame->bitpool > 16 * frame->subbands)
+		return -4;
+
+	if ((frame->mode == STEREO || frame->mode == JOINT_STEREO) &&
+			frame->bitpool > 32 * frame->subbands)
+		return -4;
+
+	/* data[3] is crc, we're checking it later */
+
+	consumed = 32;
+
+	crc_header[0] = data[1];
+	crc_header[1] = data[2];
+	crc_pos = 16;
+
+	if (frame->mode == JOINT_STEREO) {
+		if (len * 8 < consumed + frame->subbands)
+			return -1;
+
+		frame->joint = 0x00;
+		for (sb = 0; sb < frame->subbands - 1; sb++)
+			frame->joint |= ((data[4] >> (7 - sb)) & 0x01) << sb;
+		if (frame->subbands == 4)
+			crc_header[crc_pos / 8] = data[4] & 0xf0;
+		else
+			crc_header[crc_pos / 8] = data[4];
+
+		consumed += frame->subbands;
+		crc_pos += frame->subbands;
+	}
+
+	if (len * 8 < consumed + (4 * frame->subbands * frame->channels))
+		return -1;
+
+	for (ch = 0; ch < frame->channels; ch++) {
+		for (sb = 0; sb < frame->subbands; sb++) {
+			/* FIXME assert(consumed % 4 == 0); */
+			frame->scale_factor[ch][sb] =
+				(data[consumed >> 3] >> (4 - (consumed & 0x7))) & 0x0F;
+			crc_header[crc_pos >> 3] |=
+				frame->scale_factor[ch][sb] << (4 - (crc_pos & 0x7));
+
+			consumed += 4;
+			crc_pos += 4;
+		}
+	}
+
+	if (data[3] != sbc_crc8(crc_header, crc_pos))
+		return -3;
+
+	sbc_calculate_bits(frame, bits);
+
+	for (ch = 0; ch < frame->channels; ch++) {
+		for (sb = 0; sb < frame->subbands; sb++)
+			levels[ch][sb] = (1 << bits[ch][sb]) - 1;
+	}
+
+	for (blk = 0; blk < frame->blocks; blk++) {
+		for (ch = 0; ch < frame->channels; ch++) {
+			for (sb = 0; sb < frame->subbands; sb++) {
+				if (levels[ch][sb] > 0) {
+					audio_sample = 0;
+					for (bit = 0; bit < bits[ch][sb]; bit++) {
+						if (consumed > len * 8)
+							return -1;
+
+						if ((data[consumed >> 3] >> (7 - (consumed & 0x7))) & 0x01)
+							audio_sample |= 1 << (bits[ch][sb] - bit - 1);
+
+						consumed++;
+					}
+
+					frame->sb_sample[blk][ch][sb] =
+						(((audio_sample << 1) | 1) << frame->scale_factor[ch][sb]) /
+						levels[ch][sb] - (1 << frame->scale_factor[ch][sb]);
+				} else
+					frame->sb_sample[blk][ch][sb] = 0;
+			}
+		}
+	}
+
+	if (frame->mode == JOINT_STEREO) {
+		for (blk = 0; blk < frame->blocks; blk++) {
+			for (sb = 0; sb < frame->subbands; sb++) {
+				if (frame->joint & (0x01 << sb)) {
+					temp = frame->sb_sample[blk][0][sb] +
+						frame->sb_sample[blk][1][sb];
+					frame->sb_sample[blk][1][sb] =
+						frame->sb_sample[blk][0][sb] -
+						frame->sb_sample[blk][1][sb];
+					frame->sb_sample[blk][0][sb] = temp;
+				}
+			}
+		}
+	}
+
+	if ((consumed & 0x7) != 0)
+		consumed += 8 - (consumed & 0x7);
+
+	return consumed >> 3;
+}
+
+static void sbc_decoder_init(struct sbc_decoder_state *state,
+				const struct sbc_frame *frame)
+{
+	int i, ch;
+
+	memset(state->V, 0, sizeof(state->V));
+	state->subbands = frame->subbands;
+
+	for (ch = 0; ch < 2; ch++)
+		for (i = 0; i < frame->subbands * 2; i++)
+			state->offset[ch][i] = (10 * i + 10);
+}
+
+static inline void sbc_synthesize_four(struct sbc_decoder_state *state,
+				struct sbc_frame *frame, int ch, int blk)
+{
+	int i, k, idx;
+	int32_t *v = state->V[ch];
+	int *offset = state->offset[ch];
+
+	for (i = 0; i < 8; i++) {
+		/* Shifting */
+		offset[i]--;
+		if (offset[i] < 0) {
+			offset[i] = 79;
+			memcpy(v + 80, v, 9 * sizeof(*v));
+		}
+
+		/* Distribute the new matrix value to the shifted position */
+		v[offset[i]] = SCALE4_STAGED1(
+			MULA(synmatrix4[i][0], frame->sb_sample[blk][ch][0],
+			MULA(synmatrix4[i][1], frame->sb_sample[blk][ch][1],
+			MULA(synmatrix4[i][2], frame->sb_sample[blk][ch][2],
+			MUL (synmatrix4[i][3], frame->sb_sample[blk][ch][3])))));
+	}
+
+	/* Compute the samples */
+	for (idx = 0, i = 0; i < 4; i++, idx += 5) {
+		k = (i + 4) & 0xf;
+
+		/* Store in output, Q0 */
+		frame->pcm_sample[ch][blk * 4 + i] = SCALE4_STAGED2(
+			MULA(v[offset[i] + 0], sbc_proto_4_40m0[idx + 0],
+			MULA(v[offset[k] + 1], sbc_proto_4_40m1[idx + 0],
+			MULA(v[offset[i] + 2], sbc_proto_4_40m0[idx + 1],
+			MULA(v[offset[k] + 3], sbc_proto_4_40m1[idx + 1],
+			MULA(v[offset[i] + 4], sbc_proto_4_40m0[idx + 2],
+			MULA(v[offset[k] + 5], sbc_proto_4_40m1[idx + 2],
+			MULA(v[offset[i] + 6], sbc_proto_4_40m0[idx + 3],
+			MULA(v[offset[k] + 7], sbc_proto_4_40m1[idx + 3],
+			MULA(v[offset[i] + 8], sbc_proto_4_40m0[idx + 4],
+			MUL( v[offset[k] + 9], sbc_proto_4_40m1[idx + 4])))))))))));
+	}
+}
+
+static inline void sbc_synthesize_eight(struct sbc_decoder_state *state,
+				struct sbc_frame *frame, int ch, int blk)
+{
+	int i, j, k, idx;
+	int *offset = state->offset[ch];
+
+	for (i = 0; i < 16; i++) {
+		/* Shifting */
+		offset[i]--;
+		if (offset[i] < 0) {
+			offset[i] = 159;
+			for (j = 0; j < 9; j++)
+				state->V[ch][j + 160] = state->V[ch][j];
+		}
+
+		/* Distribute the new matrix value to the shifted position */
+		state->V[ch][offset[i]] = SCALE8_STAGED1(
+			MULA(synmatrix8[i][0], frame->sb_sample[blk][ch][0],
+			MULA(synmatrix8[i][1], frame->sb_sample[blk][ch][1],
+			MULA(synmatrix8[i][2], frame->sb_sample[blk][ch][2],
+			MULA(synmatrix8[i][3], frame->sb_sample[blk][ch][3],
+			MULA(synmatrix8[i][4], frame->sb_sample[blk][ch][4],
+			MULA(synmatrix8[i][5], frame->sb_sample[blk][ch][5],
+			MULA(synmatrix8[i][6], frame->sb_sample[blk][ch][6],
+			MUL( synmatrix8[i][7], frame->sb_sample[blk][ch][7])))))))));
+	}
+
+	/* Compute the samples */
+	for (idx = 0, i = 0; i < 8; i++, idx += 5) {
+		k = (i + 8) & 0xf;
+
+		/* Store in output */
+		frame->pcm_sample[ch][blk * 8 + i] = SCALE8_STAGED2( // Q0
+			MULA(state->V[ch][offset[i] + 0], sbc_proto_8_80m0[idx + 0],
+			MULA(state->V[ch][offset[k] + 1], sbc_proto_8_80m1[idx + 0],
+			MULA(state->V[ch][offset[i] + 2], sbc_proto_8_80m0[idx + 1],
+			MULA(state->V[ch][offset[k] + 3], sbc_proto_8_80m1[idx + 1],
+			MULA(state->V[ch][offset[i] + 4], sbc_proto_8_80m0[idx + 2],
+			MULA(state->V[ch][offset[k] + 5], sbc_proto_8_80m1[idx + 2],
+			MULA(state->V[ch][offset[i] + 6], sbc_proto_8_80m0[idx + 3],
+			MULA(state->V[ch][offset[k] + 7], sbc_proto_8_80m1[idx + 3],
+			MULA(state->V[ch][offset[i] + 8], sbc_proto_8_80m0[idx + 4],
+			MUL( state->V[ch][offset[k] + 9], sbc_proto_8_80m1[idx + 4])))))))))));
+	}
+}
+
+static int sbc_synthesize_audio(struct sbc_decoder_state *state,
+				struct sbc_frame *frame)
+{
+	int ch, blk;
+
+	switch (frame->subbands) {
+	case 4:
+		for (ch = 0; ch < frame->channels; ch++) {
+			for (blk = 0; blk < frame->blocks; blk++)
+				sbc_synthesize_four(state, frame, ch, blk);
+		}
+		return frame->blocks * 4;
+
+	case 8:
+		for (ch = 0; ch < frame->channels; ch++) {
+			for (blk = 0; blk < frame->blocks; blk++)
+				sbc_synthesize_eight(state, frame, ch, blk);
+		}
+		return frame->blocks * 8;
+
+	default:
+		return -EIO;
+	}
+}
+
+static void sbc_encoder_init(struct sbc_encoder_state *state,
+				const struct sbc_frame *frame)
+{
+	memset(&state->X, 0, sizeof(state->X));
+	state->subbands = frame->subbands;
+	state->position[0] = state->position[1] = 9 * frame->subbands;
+}
+
+static inline void _sbc_analyze_four(const int32_t *in, int32_t *out)
+{
+	sbc_fixed_t t[8], s[5];
+
+	t[0] = SCALE4_STAGE1( /* Q8 */
+		MULA(_sbc_proto_4[0], in[8] - in[32], /* Q18 */
+		MUL( _sbc_proto_4[1], in[16] - in[24])));
+
+	t[1] = SCALE4_STAGE1(
+		MULA(_sbc_proto_4[2], in[1],
+		MULA(_sbc_proto_4[3], in[9],
+		MULA(_sbc_proto_4[4], in[17],
+		MULA(_sbc_proto_4[5], in[25],
+		MUL( _sbc_proto_4[6], in[33]))))));
+
+	t[2] = SCALE4_STAGE1(
+		MULA(_sbc_proto_4[7], in[2],
+		MULA(_sbc_proto_4[8], in[10],
+		MULA(_sbc_proto_4[9], in[18],
+		MULA(_sbc_proto_4[10], in[26],
+		MUL( _sbc_proto_4[11], in[34]))))));
+
+	t[3] = SCALE4_STAGE1(
+		MULA(_sbc_proto_4[12], in[3],
+		MULA(_sbc_proto_4[13], in[11],
+		MULA(_sbc_proto_4[14], in[19],
+		MULA(_sbc_proto_4[15], in[27],
+		MUL( _sbc_proto_4[16], in[35]))))));
+
+	t[4] = SCALE4_STAGE1(
+		MULA(_sbc_proto_4[17], in[4] + in[36],
+		MULA(_sbc_proto_4[18], in[12] + in[28],
+		MUL( _sbc_proto_4[19], in[20]))));
+
+	t[5] = SCALE4_STAGE1(
+		MULA(_sbc_proto_4[16], in[5],
+		MULA(_sbc_proto_4[15], in[13],
+		MULA(_sbc_proto_4[14], in[21],
+		MULA(_sbc_proto_4[13], in[29],
+		MUL( _sbc_proto_4[12], in[37]))))));
+
+	/* don't compute t[6]... this term always multiplies
+	 * with cos(pi/2) = 0 */
+
+	t[7] = SCALE4_STAGE1(
+		MULA(_sbc_proto_4[6], in[7],
+		MULA(_sbc_proto_4[5], in[15],
+		MULA(_sbc_proto_4[4], in[23],
+		MULA(_sbc_proto_4[3], in[31],
+		MUL( _sbc_proto_4[2], in[39]))))));
+
+	s[0] = MUL( _anamatrix4[0], t[0] + t[4]);
+	s[1] = MUL( _anamatrix4[2], t[2]);
+	s[2] = MULA(_anamatrix4[1], t[1] + t[3],
+		MUL(_anamatrix4[3], t[5]));
+	s[3] = MULA(_anamatrix4[3], t[1] + t[3],
+		MUL(_anamatrix4[1], -t[5] + t[7]));
+	s[4] = MUL( _anamatrix4[3], t[7]);
+
+	out[0] = SCALE4_STAGE2( s[0] + s[1] + s[2] + s[4]); /* Q0 */
+	out[1] = SCALE4_STAGE2(-s[0] + s[1] + s[3]);
+	out[2] = SCALE4_STAGE2(-s[0] + s[1] - s[3]);
+	out[3] = SCALE4_STAGE2( s[0] + s[1] - s[2] - s[4]);
+}
+
+static inline void sbc_analyze_four(struct sbc_encoder_state *state,
+				struct sbc_frame *frame, int ch, int blk)
+{
+	int32_t *x = &state->X[ch][state->position[ch]];
+	int16_t *pcm = &frame->pcm_sample[ch][blk * 4];
+
+	/* Input 4 Audio Samples */
+	x[40] = x[0] = pcm[3];
+	x[41] = x[1] = pcm[2];
+	x[42] = x[2] = pcm[1];
+	x[43] = x[3] = pcm[0];
+
+	_sbc_analyze_four(x, frame->sb_sample_f[blk][ch]);
+
+	state->position[ch] -= 4;
+	if (state->position[ch] < 0)
+		state->position[ch] = 36;
+}
+
+static inline void _sbc_analyze_eight(const int32_t *in, int32_t *out)
+{
+	sbc_fixed_t t[8], s[8];
+
+	t[0] = SCALE8_STAGE1( /* Q10 */
+		MULA(_sbc_proto_8[0], (in[16] - in[64]), /* Q18 = Q18 * Q0 */
+		MULA(_sbc_proto_8[1], (in[32] - in[48]),
+		MULA(_sbc_proto_8[2], in[4],
+		MULA(_sbc_proto_8[3], in[20],
+		MULA(_sbc_proto_8[4], in[36],
+		MUL( _sbc_proto_8[5], in[52])))))));
+
+	t[1] = SCALE8_STAGE1(
+		MULA(_sbc_proto_8[6], in[2],
+		MULA(_sbc_proto_8[7], in[18],
+		MULA(_sbc_proto_8[8], in[34],
+		MULA(_sbc_proto_8[9], in[50],
+		MUL(_sbc_proto_8[10], in[66]))))));
+
+	t[2] = SCALE8_STAGE1(
+		MULA(_sbc_proto_8[11], in[1],
+		MULA(_sbc_proto_8[12], in[17],
+		MULA(_sbc_proto_8[13], in[33],
+		MULA(_sbc_proto_8[14], in[49],
+		MULA(_sbc_proto_8[15], in[65],
+		MULA(_sbc_proto_8[16], in[3],
+		MULA(_sbc_proto_8[17], in[19],
+		MULA(_sbc_proto_8[18], in[35],
+		MULA(_sbc_proto_8[19], in[51],
+		MUL( _sbc_proto_8[20], in[67])))))))))));
+
+	t[3] = SCALE8_STAGE1(
+		MULA( _sbc_proto_8[21], in[5],
+		MULA( _sbc_proto_8[22], in[21],
+		MULA( _sbc_proto_8[23], in[37],
+		MULA( _sbc_proto_8[24], in[53],
+		MULA( _sbc_proto_8[25], in[69],
+		MULA(-_sbc_proto_8[15], in[15],
+		MULA(-_sbc_proto_8[14], in[31],
+		MULA(-_sbc_proto_8[13], in[47],
+		MULA(-_sbc_proto_8[12], in[63],
+		MUL( -_sbc_proto_8[11], in[79])))))))))));
+
+	t[4] = SCALE8_STAGE1(
+		MULA( _sbc_proto_8[26], in[6],
+		MULA( _sbc_proto_8[27], in[22],
+		MULA( _sbc_proto_8[28], in[38],
+		MULA( _sbc_proto_8[29], in[54],
+		MULA( _sbc_proto_8[30], in[70],
+		MULA(-_sbc_proto_8[10], in[14],
+		MULA(-_sbc_proto_8[9], in[30],
+		MULA(-_sbc_proto_8[8], in[46],
+		MULA(-_sbc_proto_8[7], in[62],
+		MUL( -_sbc_proto_8[6], in[78])))))))))));
+
+	t[5] = SCALE8_STAGE1(
+		MULA( _sbc_proto_8[31], in[7],
+		MULA( _sbc_proto_8[32], in[23],
+		MULA( _sbc_proto_8[33], in[39],
+		MULA( _sbc_proto_8[34], in[55],
+		MULA( _sbc_proto_8[35], in[71],
+		MULA(-_sbc_proto_8[20], in[13],
+		MULA(-_sbc_proto_8[19], in[29],
+		MULA(-_sbc_proto_8[18], in[45],
+		MULA(-_sbc_proto_8[17], in[61],
+		MUL( -_sbc_proto_8[16], in[77])))))))))));
+
+	t[6] = SCALE8_STAGE1(
+		MULA( _sbc_proto_8[36], (in[8] + in[72]),
+		MULA( _sbc_proto_8[37], (in[24] + in[56]),
+		MULA( _sbc_proto_8[38], in[40],
+		MULA(-_sbc_proto_8[39], in[12],
+		MULA(-_sbc_proto_8[5], in[28],
+		MULA(-_sbc_proto_8[4], in[44],
+		MULA(-_sbc_proto_8[3], in[60],
+		MUL( -_sbc_proto_8[2], in[76])))))))));
+
+	t[7] = SCALE8_STAGE1(
+		MULA( _sbc_proto_8[35], in[9],
+		MULA( _sbc_proto_8[34], in[25],
+		MULA( _sbc_proto_8[33], in[41],
+		MULA( _sbc_proto_8[32], in[57],
+		MULA( _sbc_proto_8[31], in[73],
+		MULA(-_sbc_proto_8[25], in[11],
+		MULA(-_sbc_proto_8[24], in[27],
+		MULA(-_sbc_proto_8[23], in[43],
+		MULA(-_sbc_proto_8[22], in[59],
+		MUL( -_sbc_proto_8[21], in[75])))))))))));
+
+	s[0] = MULA(  _anamatrix8[0], t[0],
+		MUL(  _anamatrix8[1], t[6]));
+	s[1] = MUL(   _anamatrix8[7], t[1]);
+	s[2] = MULA(  _anamatrix8[2], t[2],
+		MULA( _anamatrix8[3], t[3],
+		MULA( _anamatrix8[4], t[5],
+		MUL(  _anamatrix8[5], t[7]))));
+	s[3] = MUL(   _anamatrix8[6], t[4]);
+	s[4] = MULA(  _anamatrix8[3], t[2],
+		MULA(-_anamatrix8[5], t[3],
+		MULA(-_anamatrix8[2], t[5],
+		MUL( -_anamatrix8[4], t[7]))));
+	s[5] = MULA(  _anamatrix8[4], t[2],
+		MULA(-_anamatrix8[2], t[3],
+		MULA( _anamatrix8[5], t[5],
+		MUL(  _anamatrix8[3], t[7]))));
+	s[6] = MULA(  _anamatrix8[1], t[0],
+		MUL( -_anamatrix8[0], t[6]));
+	s[7] = MULA(  _anamatrix8[5], t[2],
+		MULA(-_anamatrix8[4], t[3],
+		MULA( _anamatrix8[3], t[5],
+		MUL( -_anamatrix8[2], t[7]))));
+
+	out[0] = SCALE8_STAGE2( s[0] + s[1] + s[2] + s[3]);
+	out[1] = SCALE8_STAGE2( s[1] - s[3] + s[4] + s[6]);
+	out[2] = SCALE8_STAGE2( s[1] - s[3] + s[5] - s[6]);
+	out[3] = SCALE8_STAGE2(-s[0] + s[1] + s[3] + s[7]);
+	out[4] = SCALE8_STAGE2(-s[0] + s[1] + s[3] - s[7]);
+	out[5] = SCALE8_STAGE2( s[1] - s[3] - s[5] - s[6]);
+	out[6] = SCALE8_STAGE2( s[1] - s[3] - s[4] + s[6]);
+	out[7] = SCALE8_STAGE2( s[0] + s[1] - s[2] + s[3]);
+}
+
+static inline void sbc_analyze_eight(struct sbc_encoder_state *state,
+					struct sbc_frame *frame, int ch,
+					int blk)
+{
+	int32_t *x = &state->X[ch][state->position[ch]];
+	int16_t *pcm = &frame->pcm_sample[ch][blk * 8];
+
+	/* Input 8 Audio Samples */
+	x[80] = x[0] = pcm[7];
+	x[81] = x[1] = pcm[6];
+	x[82] = x[2] = pcm[5];
+	x[83] = x[3] = pcm[4];
+	x[84] = x[4] = pcm[3];
+	x[85] = x[5] = pcm[2];
+	x[86] = x[6] = pcm[1];
+	x[87] = x[7] = pcm[0];
+
+	_sbc_analyze_eight(x, frame->sb_sample_f[blk][ch]);
+
+	state->position[ch] -= 8;
+	if (state->position[ch] < 0)
+		state->position[ch] = 72;
+}
+
+static int sbc_analyze_audio(struct sbc_encoder_state *state,
+				struct sbc_frame *frame)
+{
+	int ch, blk;
+
+	switch (frame->subbands) {
+	case 4:
+		for (ch = 0; ch < frame->channels; ch++)
+			for (blk = 0; blk < frame->blocks; blk++)
+				sbc_analyze_four(state, frame, ch, blk);
+		return frame->blocks * 4;
+
+	case 8:
+		for (ch = 0; ch < frame->channels; ch++)
+			for (blk = 0; blk < frame->blocks; blk++)
+				sbc_analyze_eight(state, frame, ch, blk);
+		return frame->blocks * 8;
+
+	default:
+		return -EIO;
+	}
+}
+
+/*
+ * Packs the SBC frame from frame into the memory at data. At most len
+ * bytes will be used, should more memory be needed an appropriate
+ * error code will be returned. Returns the length of the packed frame
+ * on success or a negative value on error.
+ *
+ * The error codes are:
+ * -1 Not enough memory reserved
+ * -2 Unsupported sampling rate
+ * -3 Unsupported number of blocks
+ * -4 Unsupported number of subbands
+ * -5 Bitpool value out of bounds
+ * -99 not implemented
+ */
+
+static int sbc_pack_frame(uint8_t *data, struct sbc_frame *frame, size_t len)
+{
+	int produced;
+	/* Will copy the header parts for CRC-8 calculation here */
+	uint8_t crc_header[11] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+	int crc_pos = 0;
+
+	uint16_t audio_sample;
+
+	int ch, sb, blk, bit;	/* channel, subband, block and bit counters */
+	int bits[2][8];		/* bits distribution */
+	int levels[2][8];	/* levels are derived from that */
+
+	u_int32_t scalefactor[2][8];	/* derived from frame->scale_factor */
+
+	data[0] = SBC_SYNCWORD;
+
+	data[1] = (frame->frequency & 0x03) << 6;
+
+	data[1] |= (frame->block_mode & 0x03) << 4;
+
+	data[1] |= (frame->mode & 0x03) << 2;
+
+	data[1] |= (frame->allocation & 0x01) << 1;
+
+	switch (frame->subbands) {
+	case 4:
+		/* Nothing to do */
+		break;
+	case 8:
+		data[1] |= 0x01;
+		break;
+	default:
+		return -4;
+		break;
+	}
+
+	data[2] = frame->bitpool;
+
+	if ((frame->mode == MONO || frame->mode == DUAL_CHANNEL) &&
+			frame->bitpool > frame->subbands << 4)
+		return -5;
+
+	if ((frame->mode == STEREO || frame->mode == JOINT_STEREO) &&
+			frame->bitpool > frame->subbands << 5)
+		return -5;
+
+	/* Can't fill in crc yet */
+
+	produced = 32;
+
+	crc_header[0] = data[1];
+	crc_header[1] = data[2];
+	crc_pos = 16;
+
+	for (ch = 0; ch < frame->channels; ch++) {
+		for (sb = 0; sb < frame->subbands; sb++) {
+			frame->scale_factor[ch][sb] = 0;
+			scalefactor[ch][sb] = 2;
+			for (blk = 0; blk < frame->blocks; blk++) {
+				while (scalefactor[ch][sb] < fabs(frame->sb_sample_f[blk][ch][sb])) {
+					frame->scale_factor[ch][sb]++;
+					scalefactor[ch][sb] *= 2;
+				}
+			}
+		}
+	}
+
+	if (frame->mode == JOINT_STEREO) {
+		/* like frame->sb_sample but joint stereo */
+		int32_t sb_sample_j[16][2];
+		/* scalefactor and scale_factor in joint case */
+		u_int32_t scalefactor_j[2];
+		uint8_t scale_factor_j[2];
+
+		frame->joint = 0;
+
+		for (sb = 0; sb < frame->subbands - 1; sb++) {
+			scale_factor_j[0] = 0;
+			scalefactor_j[0] = 2;
+			scale_factor_j[1] = 0;
+			scalefactor_j[1] = 2;
+
+			for (blk = 0; blk < frame->blocks; blk++) {
+				/* Calculate joint stereo signal */
+				sb_sample_j[blk][0] =
+					(frame->sb_sample_f[blk][0][sb] +
+						frame->sb_sample_f[blk][1][sb]) >> 1;
+				sb_sample_j[blk][1] =
+					(frame->sb_sample_f[blk][0][sb] -
+						frame->sb_sample_f[blk][1][sb]) >> 1;
+
+				/* calculate scale_factor_j and scalefactor_j for joint case */
+				while (scalefactor_j[0] < fabs(sb_sample_j[blk][0])) {
+					scale_factor_j[0]++;
+					scalefactor_j[0] *= 2;
+				}
+				while (scalefactor_j[1] < fabs(sb_sample_j[blk][1])) {
+					scale_factor_j[1]++;
+					scalefactor_j[1] *= 2;
+				}
+			}
+
+			/* decide whether to join this subband */
+			if ((scalefactor[0][sb] + scalefactor[1][sb]) >
+					(scalefactor_j[0] + scalefactor_j[1]) ) {
+				/* use joint stereo for this subband */
+				frame->joint |= 1 << sb;
+				frame->scale_factor[0][sb] = scale_factor_j[0];
+				frame->scale_factor[1][sb] = scale_factor_j[1];
+				scalefactor[0][sb] = scalefactor_j[0];
+				scalefactor[1][sb] = scalefactor_j[1];
+				for (blk = 0; blk < frame->blocks; blk++) {
+					frame->sb_sample_f[blk][0][sb] =
+							sb_sample_j[blk][0];
+					frame->sb_sample_f[blk][1][sb] =
+							sb_sample_j[blk][1];
+				}
+			}
+		}
+
+		data[4] = 0;
+		for (sb = 0; sb < frame->subbands - 1; sb++)
+			data[4] |= ((frame->joint >> sb) & 0x01) << (frame->subbands - 1 - sb);
+
+		crc_header[crc_pos >> 3] = data[4];
+
+		produced += frame->subbands;
+		crc_pos += frame->subbands;
+	}
+
+	for (ch = 0; ch < frame->channels; ch++) {
+		for (sb = 0; sb < frame->subbands; sb++) {
+			data[produced >> 3] <<= 4;
+			crc_header[crc_pos >> 3] <<= 4;
+			data[produced >> 3] |= frame->scale_factor[ch][sb] & 0x0F;
+			crc_header[crc_pos >> 3] |= frame->scale_factor[ch][sb] & 0x0F;
+
+			produced += 4;
+			crc_pos += 4;
+		}
+	}
+
+	/* align the last crc byte */
+	if (crc_pos % 8)
+		crc_header[crc_pos >> 3] <<= 8 - (crc_pos % 8);
+
+	data[3] = sbc_crc8(crc_header, crc_pos);
+
+	sbc_calculate_bits(frame, bits);
+
+	for (ch = 0; ch < frame->channels; ch++) {
+		for (sb = 0; sb < frame->subbands; sb++)
+			levels[ch][sb] = (1 << bits[ch][sb]) - 1;
+	}
+
+	for (blk = 0; blk < frame->blocks; blk++) {
+		for (ch = 0; ch < frame->channels; ch++) {
+			for (sb = 0; sb < frame->subbands; sb++) {
+				if (levels[ch][sb] > 0) {
+					audio_sample =
+						(uint16_t) ((((frame->sb_sample_f[blk][ch][sb]*levels[ch][sb]) >>
+									(frame->scale_factor[ch][sb] + 1)) +
+								levels[ch][sb]) >> 1);
+					audio_sample <<= 16 - bits[ch][sb];
+					for (bit = 0; bit < bits[ch][sb]; bit++) {
+						data[produced >> 3] <<= 1;
+						if (audio_sample & 0x8000)
+							data[produced >> 3] |= 0x1;
+						audio_sample <<= 1;
+						produced++;
+					}
+				}
+			}
+		}
+	}
+
+	/* align the last byte */
+	if (produced % 8) {
+		data[produced >> 3] <<= 8 - (produced % 8);
+	}
+
+	return (produced + 7) >> 3;
+}
+
+struct sbc_priv {
+	int init;
+	struct sbc_frame frame;
+	struct sbc_decoder_state dec_state;
+	struct sbc_encoder_state enc_state;
+};
+
+static void sbc_set_defaults(sbc_t *sbc, unsigned long flags)
+{
+	sbc->frequency = SBC_FREQ_44100;
+	sbc->mode = SBC_MODE_STEREO;
+	sbc->subbands = SBC_SB_8;
+	sbc->blocks = SBC_BLK_16;
+	sbc->bitpool = 32;
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+	sbc->endian = SBC_LE;
+#elif __BYTE_ORDER == __BIG_ENDIAN
+	sbc->endian = SBC_BE;
+#else
+#error "Unknown byte order"
+#endif
+}
+
+int sbc_init(sbc_t *sbc, unsigned long flags)
+{
+	if (!sbc)
+		return -EIO;
+
+	memset(sbc, 0, sizeof(sbc_t));
+
+	sbc->priv = malloc(sizeof(struct sbc_priv));
+	if (!sbc->priv)
+		return -ENOMEM;
+
+	memset(sbc->priv, 0, sizeof(struct sbc_priv));
+
+	sbc_set_defaults(sbc, flags);
+
+	return 0;
+}
+
+int sbc_parse(sbc_t *sbc, void *input, int input_len)
+{
+	return sbc_decode(sbc, input, input_len, NULL, 0, NULL);
+}
+
+int sbc_decode(sbc_t *sbc, void *input, int input_len, void *output,
+		int output_len, int *written)
+{
+	struct sbc_priv *priv;
+	char *ptr;
+	int i, ch, framelen, samples;
+
+	if (!sbc && !input)
+		return -EIO;
+
+	priv = sbc->priv;
+
+	framelen = sbc_unpack_frame(input, &priv->frame, input_len);
+
+	if (!priv->init) {
+		sbc_decoder_init(&priv->dec_state, &priv->frame);
+		priv->init = 1;
+
+		sbc->frequency = priv->frame.frequency;
+		sbc->mode = priv->frame.mode;
+		sbc->subbands = priv->frame.subband_mode;
+		sbc->blocks = priv->frame.block_mode;
+		sbc->allocation = priv->frame.allocation;
+		sbc->bitpool = priv->frame.bitpool;
+
+		priv->frame.codesize = sbc_get_codesize(sbc);
+		priv->frame.length = sbc_get_frame_length(sbc);
+	}
+
+	if (!output)
+		return framelen;
+
+	if (written)
+		*written = 0;
+
+	samples = sbc_synthesize_audio(&priv->dec_state, &priv->frame);
+
+	ptr = output;
+
+	if (output_len < samples * priv->frame.channels * 2)
+		samples = output_len / (priv->frame.channels * 2);
+
+	for (i = 0; i < samples; i++) {
+		for (ch = 0; ch < priv->frame.channels; ch++) {
+			int16_t s;
+			s = priv->frame.pcm_sample[ch][i];
+
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+			if (sbc->endian == SBC_BE) {
+#elif __BYTE_ORDER == __BIG_ENDIAN
+			if (sbc->endian == SBC_LE) {
+#else
+#error "Unknown byte order"
+#endif
+				*ptr++ = (s & 0xff00) >> 8;
+				*ptr++ = (s & 0x00ff);
+			} else {
+				*ptr++ = (s & 0x00ff);
+				*ptr++ = (s & 0xff00) >> 8;
+			}
+		}
+	}
+
+	if (written)
+		*written = samples * priv->frame.channels * 2;
+
+	return framelen;
+}
+
+int sbc_encode(sbc_t *sbc, void *input, int input_len, void *output,
+		int output_len, int *written)
+{
+	struct sbc_priv *priv;
+	char *ptr;
+	int i, ch, framelen, samples;
+
+	if (!sbc && !input)
+		return -EIO;
+
+	priv = sbc->priv;
+
+	if (written)
+		*written = 0;
+
+	if (!priv->init) {
+		priv->frame.frequency = sbc->frequency;
+		priv->frame.mode = sbc->mode;
+		priv->frame.channels = sbc->mode == SBC_MODE_MONO ? 1 : 2;
+		priv->frame.allocation = sbc->allocation;
+		priv->frame.subband_mode = sbc->subbands;
+		priv->frame.subbands = sbc->subbands ? 8 : 4;
+		priv->frame.block_mode = sbc->blocks;
+		priv->frame.blocks = 4 + (sbc->blocks * 4);
+		priv->frame.bitpool = sbc->bitpool;
+		priv->frame.codesize = sbc_get_codesize(sbc);
+		priv->frame.length = sbc_get_frame_length(sbc);
+
+		sbc_encoder_init(&priv->enc_state, &priv->frame);
+		priv->init = 1;
+	}
+
+	/* input must be large enough to encode a complete frame */
+	if (input_len < priv->frame.codesize)
+		return 0;
+
+	/* output must be large enough to receive the encoded frame */
+	if (!output || output_len < priv->frame.length)
+		return -ENOSPC;
+
+	ptr = input;
+
+	for (i = 0; i < priv->frame.subbands * priv->frame.blocks; i++) {
+		for (ch = 0; ch < priv->frame.channels; ch++) {
+			int16_t s;
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+			if (sbc->endian == SBC_BE)
+#elif __BYTE_ORDER == __BIG_ENDIAN
+			if (sbc->endian == SBC_LE)
+#else
+#error "Unknown byte order"
+#endif
+				s = (ptr[0] & 0xff) << 8 | (ptr[1] & 0xff);
+			else
+				s = (ptr[0] & 0xff) | (ptr[1] & 0xff) << 8;
+			ptr += 2;
+			priv->frame.pcm_sample[ch][i] = s;
+		}
+	}
+
+	samples = sbc_analyze_audio(&priv->enc_state, &priv->frame);
+
+	framelen = sbc_pack_frame(output, &priv->frame, output_len);
+
+	if (written)
+		*written = framelen;
+
+	return samples * priv->frame.channels * 2;
+}
+
+void sbc_finish(sbc_t *sbc)
+{
+	if (!sbc)
+		return;
+
+	if (sbc->priv)
+		free(sbc->priv);
+
+	memset(sbc, 0, sizeof(sbc_t));
+}
+
+int sbc_get_frame_length(sbc_t *sbc)
+{
+	int ret;
+	uint8_t subbands, channels, blocks, joint;
+	struct sbc_priv *priv;
+
+	priv = sbc->priv;
+	if (!priv->init) {
+		subbands = sbc->subbands ? 8 : 4;
+		blocks = 4 + (sbc->blocks * 4);
+		channels = sbc->mode == SBC_MODE_MONO ? 1 : 2;
+		joint = sbc->mode == SBC_MODE_JOINT_STEREO ? 1 : 0;
+	} else {
+		subbands = priv->frame.subbands;
+		blocks = priv->frame.blocks;
+		channels = priv->frame.channels;
+		joint = priv->frame.joint;
+	}
+
+	ret = 4 + (4 * subbands * channels) / 8;
+
+	/* This term is not always evenly divide so we round it up */
+	if (channels == 1)
+		ret += ((blocks * channels * sbc->bitpool) + 7) / 8;
+	else
+		ret += (((joint ? subbands : 0) + blocks * sbc->bitpool) + 7)
+			/ 8;
+
+	return ret;
+}
+
+int sbc_get_frame_duration(sbc_t *sbc)
+{
+	uint8_t subbands, blocks;
+	uint16_t frequency;
+	struct sbc_priv *priv;
+
+	priv = sbc->priv;
+	if (!priv->init) {
+		subbands = sbc->subbands ? 8 : 4;
+		blocks = 4 + (sbc->blocks * 4);
+	} else {
+		subbands = priv->frame.subbands;
+		blocks = priv->frame.blocks;
+	}
+
+	switch (sbc->frequency) {
+	case SBC_FREQ_16000:
+		frequency = 16000;
+		break;
+
+	case SBC_FREQ_32000:
+		frequency = 32000;
+		break;
+
+	case SBC_FREQ_44100:
+		frequency = 44100;
+		break;
+
+	case SBC_FREQ_48000:
+		frequency = 48000;
+		break;
+	default:
+		return 0;
+	}
+
+	return (1000000 * blocks * subbands) / frequency;
+}
+
+int sbc_get_codesize(sbc_t *sbc)
+{
+	uint8_t subbands, channels, blocks;
+	struct sbc_priv *priv;
+
+	priv = sbc->priv;
+	if (!priv->init) {
+		subbands = sbc->subbands ? 8 : 4;
+		blocks = 4 + (sbc->blocks * 4);
+		channels = sbc->mode == SBC_MODE_MONO ? 1 : 2;
+	} else {
+		subbands = priv->frame.subbands;
+		blocks = priv->frame.blocks;
+		channels = priv->frame.channels;
+	}
+
+	return subbands * blocks * channels * 2;
+}
+
+int sbc_reinit(sbc_t *sbc, unsigned long flags)
+{
+	struct sbc_priv *priv;
+
+	if (!sbc || !sbc->priv)
+		return -EIO;
+
+	priv = sbc->priv;
+
+	if (priv->init == 1)
+		memset(sbc->priv, 0, sizeof(struct sbc_priv));
+
+	sbc_set_defaults(sbc, flags);
+
+	return 0;
+}
diff --git a/src/modules/bt-sbc.h b/src/modules/bt-sbc.h
new file mode 100644
index 0000000..ab47e32
--- /dev/null
+++ b/src/modules/bt-sbc.h
@@ -0,0 +1,97 @@
+/*
+ *
+ *  Bluetooth low-complexity, subband codec (SBC) library
+ *
+ *  Copyright (C) 2004-2008  Marcel Holtmann <marcel at holtmann.org>
+ *  Copyright (C) 2004-2005  Henryk Ploetz <henryk at ploetzli.ch>
+ *  Copyright (C) 2005-2006  Brad Midgley <bmidgley at xmission.com>
+ *
+ *
+ *  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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef __SBC_H
+#define __SBC_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+
+/* sampling frequency */
+#define SBC_FREQ_16000		0x00
+#define SBC_FREQ_32000		0x01
+#define SBC_FREQ_44100		0x02
+#define SBC_FREQ_48000		0x03
+
+/* blocks */
+#define SBC_BLK_4		0x00
+#define SBC_BLK_8		0x01
+#define SBC_BLK_12		0x02
+#define SBC_BLK_16		0x03
+
+/* channel mode */
+#define SBC_MODE_MONO		0x00
+#define SBC_MODE_DUAL_CHANNEL	0x01
+#define SBC_MODE_STEREO		0x02
+#define SBC_MODE_JOINT_STEREO	0x03
+
+/* allocation method */
+#define SBC_AM_LOUDNESS		0x00
+#define SBC_AM_SNR		0x01
+
+/* subbands */
+#define SBC_SB_4		0x00
+#define SBC_SB_8		0x01
+
+/* Data endianess */
+#define SBC_LE			0x00
+#define SBC_BE			0x01
+
+struct sbc_struct {
+	unsigned long flags;
+
+	uint8_t frequency;
+	uint8_t blocks;
+	uint8_t subbands;
+	uint8_t mode;
+	uint8_t allocation;
+	uint8_t bitpool;
+	uint8_t endian;
+
+	void *priv;
+};
+
+typedef struct sbc_struct sbc_t;
+
+int sbc_init(sbc_t *sbc, unsigned long flags);
+int sbc_reinit(sbc_t *sbc, unsigned long flags);
+int sbc_parse(sbc_t *sbc, void *input, int input_len);
+int sbc_decode(sbc_t *sbc, void *input, int input_len, void *output,
+		int output_len, int *len);
+int sbc_encode(sbc_t *sbc, void *input, int input_len, void *output,
+		int output_len, int *written);
+int sbc_get_frame_length(sbc_t *sbc);
+int sbc_get_frame_duration(sbc_t *sbc);
+int sbc_get_codesize(sbc_t *sbc);
+void sbc_finish(sbc_t *sbc);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __SBC_H */
diff --git a/src/modules/bt-sbc_math.h b/src/modules/bt-sbc_math.h
new file mode 100644
index 0000000..b3d87a6
--- /dev/null
+++ b/src/modules/bt-sbc_math.h
@@ -0,0 +1,72 @@
+/*
+ *
+ *  Bluetooth low-complexity, subband codec (SBC) library
+ *
+ *  Copyright (C) 2004-2008  Marcel Holtmann <marcel at holtmann.org>
+ *  Copyright (C) 2004-2005  Henryk Ploetz <henryk at ploetzli.ch>
+ *  Copyright (C) 2005-2008  Brad Midgley <bmidgley at xmission.com>
+ *
+ *
+ *  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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#define fabs(x) ((x) < 0 ? -(x) : (x))
+/* C does not provide an explicit arithmetic shift right but this will
+   always be correct and every compiler *should* generate optimal code */
+#define ASR(val, bits) ((-2 >> 1 == -1) ? \
+		 ((int32_t)(val)) >> (bits) : ((int32_t) (val)) / (1 << (bits)))
+
+#define SCALE_PROTO4_TBL	15
+#define SCALE_ANA4_TBL		17
+#define SCALE_PROTO8_TBL	16
+#define SCALE_ANA8_TBL		17
+#define SCALE_SPROTO4_TBL	12
+#define SCALE_SPROTO8_TBL	14
+#define SCALE_NPROTO4_TBL	11
+#define SCALE_NPROTO8_TBL	11
+#define SCALE4_STAGE1_BITS	15
+#define SCALE4_STAGE2_BITS	16
+#define SCALE4_STAGED1_BITS	15
+#define SCALE4_STAGED2_BITS	16
+#define SCALE8_STAGE1_BITS	15
+#define SCALE8_STAGE2_BITS	15
+#define SCALE8_STAGED1_BITS	15
+#define SCALE8_STAGED2_BITS	16
+
+typedef int32_t sbc_fixed_t;
+
+#define SCALE4_STAGE1(src)  ASR(src, SCALE4_STAGE1_BITS)
+#define SCALE4_STAGE2(src)  ASR(src, SCALE4_STAGE2_BITS)
+#define SCALE4_STAGED1(src) ASR(src, SCALE4_STAGED1_BITS)
+#define SCALE4_STAGED2(src) ASR(src, SCALE4_STAGED2_BITS)
+#define SCALE8_STAGE1(src)  ASR(src, SCALE8_STAGE1_BITS)
+#define SCALE8_STAGE2(src)  ASR(src, SCALE8_STAGE2_BITS)
+#define SCALE8_STAGED1(src) ASR(src, SCALE8_STAGED1_BITS)
+#define SCALE8_STAGED2(src) ASR(src, SCALE8_STAGED2_BITS)
+
+#define SBC_FIXED_0(val) { val = 0; }
+#define MUL(a, b)        ((a) * (b))
+#ifdef __arm__
+#define MULA(a, b, res) ({				\
+		int tmp = res;			\
+		__asm__(				\
+			"mla %0, %2, %3, %0"		\
+			: "=&r" (tmp)			\
+			: "0" (tmp), "r" (a), "r" (b));	\
+		tmp; })
+#else
+#define MULA(a, b, res)  ((a) * (b) + (res))
+#endif
diff --git a/src/modules/bt-sbc_tables.h b/src/modules/bt-sbc_tables.h
new file mode 100644
index 0000000..7ac4e68
--- /dev/null
+++ b/src/modules/bt-sbc_tables.h
@@ -0,0 +1,167 @@
+/*
+ *
+ *  Bluetooth low-complexity, subband codec (SBC) library
+ *
+ *  Copyright (C) 2004-2008  Marcel Holtmann <marcel at holtmann.org>
+ *  Copyright (C) 2004-2005  Henryk Ploetz <henryk at ploetzli.ch>
+ *  Copyright (C) 2005-2006  Brad Midgley <bmidgley at xmission.com>
+ *
+ *
+ *  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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+/* A2DP specification: Appendix B, page 69 */
+static const int sbc_offset4[4][4] = {
+	{ -1, 0, 0, 0 },
+	{ -2, 0, 0, 1 },
+	{ -2, 0, 0, 1 },
+	{ -2, 0, 0, 1 }
+};
+
+/* A2DP specification: Appendix B, page 69 */
+static const int sbc_offset8[4][8] = {
+	{ -2, 0, 0, 0, 0, 0, 0, 1 },
+	{ -3, 0, 0, 0, 0, 0, 1, 2 },
+	{ -4, 0, 0, 0, 0, 0, 1, 2 },
+	{ -4, 0, 0, 0, 0, 0, 1, 2 }
+};
+
+#define SP4(val) ASR(val, SCALE_PROTO4_TBL)
+#define SA4(val) ASR(val, SCALE_ANA4_TBL)
+#define SP8(val) ASR(val, SCALE_PROTO8_TBL)
+#define SA8(val) ASR(val, SCALE_ANA8_TBL)
+#define SS4(val) ASR(val, SCALE_SPROTO4_TBL)
+#define SS8(val) ASR(val, SCALE_SPROTO8_TBL)
+#define SN4(val) ASR(val, SCALE_NPROTO4_TBL)
+#define SN8(val) ASR(val, SCALE_NPROTO8_TBL)
+
+static const int32_t _sbc_proto_4[20] = {
+	SP4(0x02cb3e8c), SP4(0x22b63dc0), SP4(0x002329cc), SP4(0x053b7548),
+	SP4(0x31eab940), SP4(0xec1f5e60), SP4(0xff3773a8), SP4(0x0061c5a7),
+	SP4(0x07646680), SP4(0x3f239480), SP4(0xf89f23a8), SP4(0x007a4737),
+	SP4(0x00b32807), SP4(0x083ddc80), SP4(0x4825e480), SP4(0x0191e578),
+	SP4(0x00ff11ca), SP4(0x00fb7991), SP4(0x069fdc58), SP4(0x4b584000)
+};
+
+static const int32_t _anamatrix4[4] = {
+	SA4(0x2d413cc0), SA4(0x3b20d780), SA4(0x40000000), SA4(0x187de2a0)
+};
+
+static const int32_t _sbc_proto_8[40] = {
+	SP8(0x02e5cd20), SP8(0x22d0c200), SP8(0x006bfe27), SP8(0x07808930),
+	SP8(0x3f1c8800), SP8(0xf8810d70), SP8(0x002cfdc6), SP8(0x055acf28),
+	SP8(0x31f566c0), SP8(0xebfe57e0), SP8(0xff27c437), SP8(0x001485cc),
+	SP8(0x041c6e58), SP8(0x2a7cfa80), SP8(0xe4c4a240), SP8(0xfe359e4c),
+	SP8(0x0048b1f8), SP8(0x0686ce30), SP8(0x38eec5c0), SP8(0xf2a1b9f0),
+	SP8(0xffe8904a), SP8(0x0095698a), SP8(0x0824a480), SP8(0x443b3c00),
+	SP8(0xfd7badc8), SP8(0x00d3e2d9), SP8(0x00c183d2), SP8(0x084e1950),
+	SP8(0x4810d800), SP8(0x017f43fe), SP8(0x01056dd8), SP8(0x00e9cb9f),
+	SP8(0x07d7d090), SP8(0x4a708980), SP8(0x0488fae8), SP8(0x0113bd20),
+	SP8(0x0107b1a8), SP8(0x069fb3c0), SP8(0x4b3db200), SP8(0x00763f48)
+};
+
+static const int32_t sbc_proto_4_40m0[] = {
+	SS4(0x00000000), SS4(0xffa6982f), SS4(0xfba93848), SS4(0x0456c7b8),
+	SS4(0x005967d1), SS4(0xfffb9ac7), SS4(0xff589157), SS4(0xf9c2a8d8),
+	SS4(0x027c1434), SS4(0x0019118b), SS4(0xfff3c74c), SS4(0xff137330),
+	SS4(0xf81b8d70), SS4(0x00ec1b8b), SS4(0xfff0b71a), SS4(0xffe99b00),
+	SS4(0xfef84470), SS4(0xf6fb4370), SS4(0xffcdc351), SS4(0xffe01dc7)
+};
+
+static const int32_t sbc_proto_4_40m1[] = {
+	SS4(0xffe090ce), SS4(0xff2c0475), SS4(0xf694f800), SS4(0xff2c0475),
+	SS4(0xffe090ce), SS4(0xffe01dc7), SS4(0xffcdc351), SS4(0xf6fb4370),
+	SS4(0xfef84470), SS4(0xffe99b00), SS4(0xfff0b71a), SS4(0x00ec1b8b),
+	SS4(0xf81b8d70), SS4(0xff137330), SS4(0xfff3c74c), SS4(0x0019118b),
+	SS4(0x027c1434), SS4(0xf9c2a8d8), SS4(0xff589157), SS4(0xfffb9ac7)
+};
+
+static const int32_t sbc_proto_8_80m0[] = {
+	SS8(0x00000000), SS8(0xfe8d1970), SS8(0xee979f00), SS8(0x11686100),
+	SS8(0x0172e690), SS8(0xfff5bd1a), SS8(0xfdf1c8d4), SS8(0xeac182c0),
+	SS8(0x0d9daee0), SS8(0x00e530da), SS8(0xffe9811d), SS8(0xfd52986c),
+	SS8(0xe7054ca0), SS8(0x0a00d410), SS8(0x006c1de4), SS8(0xffdba705),
+	SS8(0xfcbc98e8), SS8(0xe3889d20), SS8(0x06af2308), SS8(0x000bb7db),
+	SS8(0xffca00ed), SS8(0xfc3fbb68), SS8(0xe071bc00), SS8(0x03bf7948),
+	SS8(0xffc4e05c), SS8(0xffb54b3b), SS8(0xfbedadc0), SS8(0xdde26200),
+	SS8(0x0142291c), SS8(0xff960e94), SS8(0xff9f3e17), SS8(0xfbd8f358),
+	SS8(0xdbf79400), SS8(0xff405e01), SS8(0xff7d4914), SS8(0xff8b1a31),
+	SS8(0xfc1417b8), SS8(0xdac7bb40), SS8(0xfdbb828c), SS8(0xff762170)
+};
+
+static const int32_t sbc_proto_8_80m1[] = {
+	SS8(0xff7c272c), SS8(0xfcb02620), SS8(0xda612700), SS8(0xfcb02620),
+	SS8(0xff7c272c), SS8(0xff762170), SS8(0xfdbb828c), SS8(0xdac7bb40),
+	SS8(0xfc1417b8), SS8(0xff8b1a31), SS8(0xff7d4914), SS8(0xff405e01),
+	SS8(0xdbf79400), SS8(0xfbd8f358), SS8(0xff9f3e17), SS8(0xff960e94),
+	SS8(0x0142291c), SS8(0xdde26200), SS8(0xfbedadc0), SS8(0xffb54b3b),
+	SS8(0xffc4e05c), SS8(0x03bf7948), SS8(0xe071bc00), SS8(0xfc3fbb68),
+	SS8(0xffca00ed), SS8(0x000bb7db), SS8(0x06af2308), SS8(0xe3889d20),
+	SS8(0xfcbc98e8), SS8(0xffdba705), SS8(0x006c1de4), SS8(0x0a00d410),
+	SS8(0xe7054ca0), SS8(0xfd52986c), SS8(0xffe9811d), SS8(0x00e530da),
+	SS8(0x0d9daee0), SS8(0xeac182c0), SS8(0xfdf1c8d4), SS8(0xfff5bd1a)
+};
+
+static const int32_t _anamatrix8[8] = {
+	SA8(0x3b20d780), SA8(0x187de2a0), SA8(0x3ec52f80), SA8(0x3536cc40),
+	SA8(0x238e7680), SA8(0x0c7c5c20), SA8(0x2d413cc0), SA8(0x40000000)
+};
+
+static const int32_t synmatrix4[8][4] = {
+	{ SN4(0x05a82798), SN4(0xfa57d868), SN4(0xfa57d868), SN4(0x05a82798) },
+	{ SN4(0x030fbc54), SN4(0xf89be510), SN4(0x07641af0), SN4(0xfcf043ac) },
+	{ SN4(0x00000000), SN4(0x00000000), SN4(0x00000000), SN4(0x00000000) },
+	{ SN4(0xfcf043ac), SN4(0x07641af0), SN4(0xf89be510), SN4(0x030fbc54) },
+	{ SN4(0xfa57d868), SN4(0x05a82798), SN4(0x05a82798), SN4(0xfa57d868) },
+	{ SN4(0xf89be510), SN4(0xfcf043ac), SN4(0x030fbc54), SN4(0x07641af0) },
+	{ SN4(0xf8000000), SN4(0xf8000000), SN4(0xf8000000), SN4(0xf8000000) },
+	{ SN4(0xf89be510), SN4(0xfcf043ac), SN4(0x030fbc54), SN4(0x07641af0) }
+};
+
+static const int32_t synmatrix8[16][8] = {
+	{ SN8(0x05a82798), SN8(0xfa57d868), SN8(0xfa57d868), SN8(0x05a82798),
+	  SN8(0x05a82798), SN8(0xfa57d868), SN8(0xfa57d868), SN8(0x05a82798) },
+	{ SN8(0x0471ced0), SN8(0xf8275a10), SN8(0x018f8b84), SN8(0x06a6d988),
+	  SN8(0xf9592678), SN8(0xfe70747c), SN8(0x07d8a5f0), SN8(0xfb8e3130) },
+	{ SN8(0x030fbc54), SN8(0xf89be510), SN8(0x07641af0), SN8(0xfcf043ac),
+	  SN8(0xfcf043ac), SN8(0x07641af0), SN8(0xf89be510), SN8(0x030fbc54) },
+	{ SN8(0x018f8b84), SN8(0xfb8e3130), SN8(0x06a6d988), SN8(0xf8275a10),
+	  SN8(0x07d8a5f0), SN8(0xf9592678), SN8(0x0471ced0), SN8(0xfe70747c) },
+	{ SN8(0x00000000), SN8(0x00000000), SN8(0x00000000), SN8(0x00000000),
+	  SN8(0x00000000), SN8(0x00000000), SN8(0x00000000), SN8(0x00000000) },
+	{ SN8(0xfe70747c), SN8(0x0471ced0), SN8(0xf9592678), SN8(0x07d8a5f0),
+	  SN8(0xf8275a10), SN8(0x06a6d988), SN8(0xfb8e3130), SN8(0x018f8b84) },
+	{ SN8(0xfcf043ac), SN8(0x07641af0), SN8(0xf89be510), SN8(0x030fbc54),
+	  SN8(0x030fbc54), SN8(0xf89be510), SN8(0x07641af0), SN8(0xfcf043ac) },
+	{ SN8(0xfb8e3130), SN8(0x07d8a5f0), SN8(0xfe70747c), SN8(0xf9592678),
+	  SN8(0x06a6d988), SN8(0x018f8b84), SN8(0xf8275a10), SN8(0x0471ced0) },
+	{ SN8(0xfa57d868), SN8(0x05a82798), SN8(0x05a82798), SN8(0xfa57d868),
+	  SN8(0xfa57d868), SN8(0x05a82798), SN8(0x05a82798), SN8(0xfa57d868) },
+	{ SN8(0xf9592678), SN8(0x018f8b84), SN8(0x07d8a5f0), SN8(0x0471ced0),
+	  SN8(0xfb8e3130), SN8(0xf8275a10), SN8(0xfe70747c), SN8(0x06a6d988) },
+	{ SN8(0xf89be510), SN8(0xfcf043ac), SN8(0x030fbc54), SN8(0x07641af0),
+	  SN8(0x07641af0), SN8(0x030fbc54), SN8(0xfcf043ac), SN8(0xf89be510) },
+	{ SN8(0xf8275a10), SN8(0xf9592678), SN8(0xfb8e3130), SN8(0xfe70747c),
+	  SN8(0x018f8b84), SN8(0x0471ced0), SN8(0x06a6d988), SN8(0x07d8a5f0) },
+	{ SN8(0xf8000000), SN8(0xf8000000), SN8(0xf8000000), SN8(0xf8000000),
+	  SN8(0xf8000000), SN8(0xf8000000), SN8(0xf8000000), SN8(0xf8000000) },
+	{ SN8(0xf8275a10), SN8(0xf9592678), SN8(0xfb8e3130), SN8(0xfe70747c),
+	  SN8(0x018f8b84), SN8(0x0471ced0), SN8(0x06a6d988), SN8(0x07d8a5f0) },
+	{ SN8(0xf89be510), SN8(0xfcf043ac), SN8(0x030fbc54), SN8(0x07641af0),
+	  SN8(0x07641af0), SN8(0x030fbc54), SN8(0xfcf043ac), SN8(0xf89be510) },
+	{ SN8(0xf9592678), SN8(0x018f8b84), SN8(0x07d8a5f0), SN8(0x0471ced0),
+	  SN8(0xfb8e3130), SN8(0xf8275a10), SN8(0xfe70747c), SN8(0x06a6d988) }
+};

commit a3f075670af9ad50b10543572c7bf70ac5476fae
Author: João Paulo Rechi Vita <joao.vita at gmail.com>
Date:   Mon Aug 11 13:27:13 2008 -0300

    BlueZ connection configuration done

diff --git a/src/modules/module-bt-device.c b/src/modules/module-bt-device.c
index 8690e31..21dfa4d 100644
--- a/src/modules/module-bt-device.c
+++ b/src/modules/module-bt-device.c
@@ -17,54 +17,97 @@
     along with PulseAudio; if not, write to the Free Software
     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
     USA.
-
-    1. Connects to the BlueZ audio service via one BlueZ specific well known unix socket
-        bluez/audio/ipc: bt_audio_service_open()
-    2. Configures a connection to the BT device
-    3. Gets a BT socket fd passed in via the unix socket
-        bluez/audio/ipc: bt_audio_service_get_data_fd()
-    4. Hands this over to its RT thread.
-        pa_thread_mq
 ***/
 
 #ifdef HAVE_CONFIG_H
 #include <config.h>
 #endif
 
+#include <string.h>
+
 #include <pulse/xmalloc.h>
 #include <pulsecore/module.h>
 #include <pulsecore/modargs.h>
+#include <pulsecore/thread.h>
+#include <pulsecore/thread-mq.h>
+#include <pulsecore/rtpoll.h>
+#include <pulsecore/time-smoother.h>
+#include <pulsecore/rtclock.h>
 
 #include "dbus-util.h"
 #include "module-bt-device-symdef.h"
 #include "bt-ipc.h"
+#include "bt-sbc.h"
+
+#define DEFAULT_SINK_NAME "bt_sink"
+#define BUFFER_SIZE 2048
+#define MAX_BITPOOL 64
+#define MIN_BITPOOL 2
 
 PA_MODULE_AUTHOR("Joao Paulo Rechi Vita");
 PA_MODULE_DESCRIPTION("Bluetooth audio sink and source");
 PA_MODULE_VERSION(PACKAGE_VERSION);
 PA_MODULE_LOAD_ONCE(FALSE);
 PA_MODULE_USAGE(
+        "name=<name of the device> "
         "addr=<address of the device> "
-        "uuid=<the profile that this device will work on>");
+        "profile=<a2dp|hsp>");
+
+struct bt_a2dp {
+    sbc_capabilities_t sbc_capabilities;
+    sbc_t sbc;                           /* Codec data */
+    int sbc_initialized;                 /* Keep track if the encoder is initialized */
+    int codesize;                        /* SBC codesize */
+    int samples;                         /* Number of encoded samples */
+    uint8_t buffer[BUFFER_SIZE];         /* Codec transfer buffer */
+    int count;                           /* Codec transfer buffer counter */
+
+    int nsamples;                        /* Cumulative number of codec samples */
+    uint16_t seq_num;                    /* Cumulative packet sequence */
+    int frame_count;                     /* Current frames in buffer*/
+};
 
 struct userdata {
     pa_core *core;
     pa_module *module;
     pa_sink *sink;
 
+    pa_thread_mq thread_mq;
+    pa_rtpoll *rtpoll;
+    pa_rtpoll_item *rtpoll_item;
+    pa_thread *thread;
+
+    pa_sample_spec ss;
+    pa_smoother *smoother;
+
+    pa_memchunk memchunk;
+
+    const char *name;
     const char *addr;
-    const char *uuid;
+    const char *profile;
+    int rate;
+    int channels;
+
+    int audioservice_fd;
+    int stream_fd;
+    int transport;
+    int link_mtu;
+
+    struct bt_a2dp a2dp;
 };
 
 static const char* const valid_modargs[] = {
+    "name",
     "addr",
-    "uuid",
+    "profile",
+    "rate",
+    "channels",
     NULL
 };
 
-static int audioservice_send(int sk, const bt_audio_msg_header_t *msg) {
+static int bt_audioservice_send(int sk, const bt_audio_msg_header_t *msg) {
     int e;
-    pa_log("sending %s", bt_audio_strmsg(msg->msg_type)); /*debug*/
+    pa_log/*_debug*/("sending %s", bt_audio_strmsg(msg->msg_type));
     if (send(sk, msg, BT_AUDIO_IPC_PACKET_SIZE, 0) > 0)
         e = 0;
     else {
@@ -74,8 +117,8 @@ static int audioservice_send(int sk, const bt_audio_msg_header_t *msg) {
     return e;
 }
 
-static int audioservice_recv(int sk, bt_audio_msg_header_t *inmsg) {
-    int err;
+static int bt_audioservice_recv(int sk, bt_audio_msg_header_t *inmsg) {
+    int e;
     const char *type;
 
     pa_log/*_debug*/("trying to receive msg from audio service...");
@@ -83,67 +126,686 @@ static int audioservice_recv(int sk, bt_audio_msg_header_t *inmsg) {
         type = bt_audio_strmsg(inmsg->msg_type);
         if (type) {
             pa_log/*_debug*/("Received %s", type);
-            err = 0;
+            e = 0;
         }
         else {
-            err = -EINVAL;
+            e = -EINVAL;
             pa_log_error("Bogus message type %d received from audio service", inmsg->msg_type);
         }
     }
     else {
-        err = -errno;
+        e = -errno;
         pa_log_error("Error receiving data from audio service: %s(%d)", strerror(errno), errno);
     }
 
-    return err;
+    return e;
 }
 
-static int audioservice_expect(int sk, bt_audio_msg_header_t *rsp_hdr, int expected_type) {
-    int err = audioservice_recv(sk, rsp_hdr);
-    if (err == 0) {
+static int bt_audioservice_expect(int sk, bt_audio_msg_header_t *rsp_hdr, int expected_type) {
+    int e = bt_audioservice_recv(sk, rsp_hdr);
+    if (e == 0) {
         if (rsp_hdr->msg_type != expected_type) {
-            err = -EINVAL;
+            e = -EINVAL;
             pa_log_error("Bogus message %s received while %s was expected", bt_audio_strmsg(rsp_hdr->msg_type),
                     bt_audio_strmsg(expected_type));
         }
     }
-    return err;
+    return e;
+}
+
+static int bt_getcaps(struct userdata *u) {
+    int e;
+    char buf[BT_AUDIO_IPC_PACKET_SIZE];
+    bt_audio_rsp_msg_header_t *rsp_hdr = (void*) buf;
+    struct bt_getcapabilities_req *getcaps_req = (void*) buf;
+    struct bt_getcapabilities_rsp *getcaps_rsp = (void*) buf;
+
+    memset(getcaps_req, 0, BT_AUDIO_IPC_PACKET_SIZE);
+    getcaps_req->h.msg_type = BT_GETCAPABILITIES_REQ;
+    strncpy(getcaps_req->device, u->addr, 18);
+    if (strcasecmp(u->profile, "a2dp") == 0)
+        getcaps_req->transport = BT_CAPABILITIES_TRANSPORT_A2DP;
+    else if (strcasecmp(u->profile, "hsp") == 0)
+        getcaps_req->transport = BT_CAPABILITIES_TRANSPORT_SCO;
+    else {
+        pa_log_error("invalid profile argument: %s", u->profile);
+        return -1;
+    }
+    getcaps_req->flags = 0;
+    getcaps_req->flags |= BT_FLAG_AUTOCONNECT;
+
+    e = bt_audioservice_send(u->audioservice_fd, &getcaps_req->h);
+    if (e < 0) {
+        pa_log_error("failed to send GETCAPABILITIES_REQ");
+        return e;
+    }
+
+    e = bt_audioservice_expect(u->audioservice_fd, &rsp_hdr->msg_h, BT_GETCAPABILITIES_RSP);
+    if (e < 0) {
+        pa_log_error("failed to expect for GETCAPABILITIES_RSP");
+        return e;
+    }
+    if (rsp_hdr->posix_errno != 0) {
+        pa_log_error("BT_GETCAPABILITIES failed : %s (%d)", strerror(rsp_hdr->posix_errno), rsp_hdr->posix_errno);
+        return -rsp_hdr->posix_errno;
+    }
+
+    if ((u->transport = getcaps_rsp->transport) == BT_CAPABILITIES_TRANSPORT_A2DP)
+        u->a2dp.sbc_capabilities = getcaps_rsp->sbc_capabilities;
+
+    return 0;
+}
+
+static uint8_t default_bitpool(uint8_t freq, uint8_t mode) {
+    switch (freq) {
+        case BT_SBC_SAMPLING_FREQ_16000:
+        case BT_SBC_SAMPLING_FREQ_32000:
+            return 53;
+        case BT_SBC_SAMPLING_FREQ_44100:
+            switch (mode) {
+                case BT_A2DP_CHANNEL_MODE_MONO:
+                case BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL:
+                    return 31;
+                case BT_A2DP_CHANNEL_MODE_STEREO:
+                case BT_A2DP_CHANNEL_MODE_JOINT_STEREO:
+                    return 53;
+                default:
+                    pa_log_warn("Invalid channel mode %u", mode);
+                    return 53;
+            }
+        case BT_SBC_SAMPLING_FREQ_48000:
+            switch (mode) {
+                case BT_A2DP_CHANNEL_MODE_MONO:
+                case BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL:
+                    return 29;
+                case BT_A2DP_CHANNEL_MODE_STEREO:
+                case BT_A2DP_CHANNEL_MODE_JOINT_STEREO:
+                    return 51;
+                default:
+                    pa_log_warn("Invalid channel mode %u", mode);
+                    return 51;
+            }
+        default:
+            pa_log_warn("Invalid sampling freq %u", freq);
+            return 53;
+    }
+}
+
+static int bt_a2dp_init(struct userdata *u) {
+    sbc_capabilities_t *cap = &u->a2dp.sbc_capabilities;
+    unsigned int max_bitpool, min_bitpool, rate, channels;
+    int dir;
+
+    switch (u->rate) {
+        case 48000:
+            cap->frequency = BT_SBC_SAMPLING_FREQ_48000;
+            break;
+        case 44100:
+            cap->frequency = BT_SBC_SAMPLING_FREQ_44100;
+            break;
+        case 32000:
+            cap->frequency = BT_SBC_SAMPLING_FREQ_32000;
+            break;
+        case 16000:
+            cap->frequency = BT_SBC_SAMPLING_FREQ_16000;
+            break;
+        default:
+            pa_log_error("Rate %d not supported", rate);
+            return -1;
+    }
+
+//    if (cfg->has_channel_mode)
+//        cap->channel_mode = cfg->channel_mode;
+//    else 
+    if (channels == 2) {
+        if (cap->channel_mode & BT_A2DP_CHANNEL_MODE_JOINT_STEREO)
+            cap->channel_mode = BT_A2DP_CHANNEL_MODE_JOINT_STEREO;
+        else if (cap->channel_mode & BT_A2DP_CHANNEL_MODE_STEREO)
+            cap->channel_mode = BT_A2DP_CHANNEL_MODE_STEREO;
+        else if (cap->channel_mode & BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL)
+            cap->channel_mode = BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL;
+    } else {
+        if (cap->channel_mode & BT_A2DP_CHANNEL_MODE_MONO)
+            cap->channel_mode = BT_A2DP_CHANNEL_MODE_MONO;
+    }
+
+    if (!cap->channel_mode) {
+        pa_log_error("No supported channel modes");
+        return -1;
+    }
+
+//    if (cfg->has_block_length)
+//        cap->block_length = cfg->block_length;
+//    else 
+    if (cap->block_length & BT_A2DP_BLOCK_LENGTH_16)
+        cap->block_length = BT_A2DP_BLOCK_LENGTH_16;
+    else if (cap->block_length & BT_A2DP_BLOCK_LENGTH_12)
+        cap->block_length = BT_A2DP_BLOCK_LENGTH_12;
+    else if (cap->block_length & BT_A2DP_BLOCK_LENGTH_8)
+        cap->block_length = BT_A2DP_BLOCK_LENGTH_8;
+    else if (cap->block_length & BT_A2DP_BLOCK_LENGTH_4)
+        cap->block_length = BT_A2DP_BLOCK_LENGTH_4;
+    else {
+        pa_log_error("No supported block lengths");
+        return -1;
+    }
+
+//    if (cfg->has_subbands)
+//        cap->subbands = cfg->subbands;
+    if (cap->subbands & BT_A2DP_SUBBANDS_8)
+        cap->subbands = BT_A2DP_SUBBANDS_8;
+    else if (cap->subbands & BT_A2DP_SUBBANDS_4)
+        cap->subbands = BT_A2DP_SUBBANDS_4;
+    else {
+        pa_log_error("No supported subbands");
+        return -1;
+    }
+
+//    if (cfg->has_allocation_method)
+//        cap->allocation_method = cfg->allocation_method;
+    if (cap->allocation_method & BT_A2DP_ALLOCATION_LOUDNESS)
+        cap->allocation_method = BT_A2DP_ALLOCATION_LOUDNESS;
+    else if (cap->allocation_method & BT_A2DP_ALLOCATION_SNR)
+        cap->allocation_method = BT_A2DP_ALLOCATION_SNR;
+
+//    if (cfg->has_bitpool)
+//        min_bitpool = max_bitpool = cfg->bitpool;
+//    else {
+    min_bitpool = MAX(MIN_BITPOOL, cap->min_bitpool);
+    max_bitpool = MIN(default_bitpool(cap->frequency, cap->channel_mode), cap->max_bitpool);
+//    }
+
+    cap->min_bitpool = min_bitpool;
+    cap->max_bitpool = max_bitpool;
+
+    return 0;
+}
+
+static void bt_a2dp_setup(struct bt_a2dp *a2dp) {
+    sbc_capabilities_t active_capabilities = a2dp->sbc_capabilities;
+
+    if (a2dp->sbc_initialized)
+        sbc_reinit(&a2dp->sbc, 0);
+    else
+        sbc_init(&a2dp->sbc, 0);
+    a2dp->sbc_initialized = 1;
+
+    if (active_capabilities.frequency & BT_SBC_SAMPLING_FREQ_16000)
+        a2dp->sbc.frequency = SBC_FREQ_16000;
+
+    if (active_capabilities.frequency & BT_SBC_SAMPLING_FREQ_32000)
+        a2dp->sbc.frequency = SBC_FREQ_32000;
+
+    if (active_capabilities.frequency & BT_SBC_SAMPLING_FREQ_44100)
+        a2dp->sbc.frequency = SBC_FREQ_44100;
+
+    if (active_capabilities.frequency & BT_SBC_SAMPLING_FREQ_48000)
+        a2dp->sbc.frequency = SBC_FREQ_48000;
+
+    if (active_capabilities.channel_mode & BT_A2DP_CHANNEL_MODE_MONO)
+        a2dp->sbc.mode = SBC_MODE_MONO;
+
+    if (active_capabilities.channel_mode & BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL)
+        a2dp->sbc.mode = SBC_MODE_DUAL_CHANNEL;
+
+    if (active_capabilities.channel_mode & BT_A2DP_CHANNEL_MODE_STEREO)
+        a2dp->sbc.mode = SBC_MODE_STEREO;
+
+    if (active_capabilities.channel_mode & BT_A2DP_CHANNEL_MODE_JOINT_STEREO)
+        a2dp->sbc.mode = SBC_MODE_JOINT_STEREO;
+
+    a2dp->sbc.allocation = active_capabilities.allocation_method == BT_A2DP_ALLOCATION_SNR ? SBC_AM_SNR : SBC_AM_LOUDNESS;
+
+    switch (active_capabilities.subbands) {
+        case BT_A2DP_SUBBANDS_4:
+            a2dp->sbc.subbands = SBC_SB_4;
+            break;
+        case BT_A2DP_SUBBANDS_8:
+            a2dp->sbc.subbands = SBC_SB_8;
+            break;
+    }
+
+    switch (active_capabilities.block_length) {
+        case BT_A2DP_BLOCK_LENGTH_4:
+            a2dp->sbc.blocks = SBC_BLK_4;
+            break;
+        case BT_A2DP_BLOCK_LENGTH_8:
+            a2dp->sbc.blocks = SBC_BLK_8;
+            break;
+        case BT_A2DP_BLOCK_LENGTH_12:
+            a2dp->sbc.blocks = SBC_BLK_12;
+            break;
+        case BT_A2DP_BLOCK_LENGTH_16:
+            a2dp->sbc.blocks = SBC_BLK_16;
+            break;
+    }
+
+    a2dp->sbc.bitpool = active_capabilities.max_bitpool;
+    a2dp->codesize = sbc_get_codesize(&a2dp->sbc);
+//    a2dp->count = sizeof(struct rtp_header) + sizeof(struct rtp_payload);
+}
+
+static int bt_setconf(struct userdata *u) {
+    int e;
+    char buf[BT_AUDIO_IPC_PACKET_SIZE];
+    bt_audio_rsp_msg_header_t *rsp_hdr = (void*) buf;
+    struct bt_setconfiguration_req *setconf_req = (void*) buf;
+    struct bt_setconfiguration_rsp *setconf_rsp = (void*) buf;
+
+    if (u->transport == BT_CAPABILITIES_TRANSPORT_A2DP) {
+        e = bt_a2dp_init(u);
+        if (e < 0) {
+            pa_log_error("a2dp_init error");
+            return e;
+        }
+    }
+
+    memset(setconf_req, 0, BT_AUDIO_IPC_PACKET_SIZE);
+    setconf_req->h.msg_type = BT_SETCONFIGURATION_REQ;
+    strncpy(setconf_req->device, u->addr, 18);
+    setconf_req->transport = u->transport;
+    if (u->transport == BT_CAPABILITIES_TRANSPORT_A2DP)
+        setconf_req->sbc_capabilities = u->a2dp.sbc_capabilities;
+    setconf_req->access_mode = BT_CAPABILITIES_ACCESS_MODE_WRITE;
+
+    e = bt_audioservice_send(u->audioservice_fd, &setconf_req->h);
+    if (e < 0) {
+        pa_log_error("failed to send BT_SETCONFIGURATION_REQ");
+        return e;
+    }
+
+    e = bt_audioservice_expect(u->audioservice_fd, &rsp_hdr->msg_h, BT_SETCONFIGURATION_RSP);
+    if (e < 0) {
+        pa_log_error("failed to expect BT_SETCONFIGURATION_RSP");
+        return e;
+    }
+
+    if (rsp_hdr->posix_errno != 0) {
+        pa_log_error("BT_SETCONFIGURATION failed : %s(%d)", strerror(rsp_hdr->posix_errno), rsp_hdr->posix_errno);
+        return -rsp_hdr->posix_errno;
+    }
+
+    u->transport = setconf_rsp->transport;
+    u->link_mtu = setconf_rsp->link_mtu;
+
+    /* setup SBC encoder now we agree on parameters */
+    if (u->transport == BT_CAPABILITIES_TRANSPORT_A2DP) {
+        bt_a2dp_setup(&u->a2dp);
+        pa_log/*debug*/("\tallocation=%u\n\tsubbands=%u\n\tblocks=%u\n\tbitpool=%u\n",
+                u->a2dp.sbc.allocation, u->a2dp.sbc.subbands, u->a2dp.sbc.blocks, u->a2dp.sbc.bitpool);
+    }
+
+    return 0;
+}
+
+static int bt_getstreamfd(struct userdata *u) {
+    int e, opt_name;
+    char buf[BT_AUDIO_IPC_PACKET_SIZE];
+    struct bt_streamstart_req *start_req = (void*) buf;
+    bt_audio_rsp_msg_header_t *rsp_hdr = (void*) buf;
+    struct bt_streamfd_ind *streamfd_ind = (void*) buf;
+
+    memset(start_req, 0, BT_AUDIO_IPC_PACKET_SIZE);
+    start_req->h.msg_type = BT_STREAMSTART_REQ;
+
+    e = bt_audioservice_send(u->audioservice_fd, &start_req->h);
+    if (e < 0) {
+        pa_log_error("failed to send BT_STREAMSTART_REQ");
+        return e;
+    }
+
+    e = bt_audioservice_expect(u->audioservice_fd, &rsp_hdr->msg_h, BT_STREAMSTART_RSP);
+    if (e < 0) {
+        pa_log_error("failed to expect BT_STREAMSTART_RSP");
+        return e;
+    }
+
+    if (rsp_hdr->posix_errno != 0) {
+        pa_log_error("BT_START failed : %s(%d)", strerror(rsp_hdr->posix_errno), rsp_hdr->posix_errno);
+        return -rsp_hdr->posix_errno;
+    }
+
+    e = bt_audioservice_expect(u->audioservice_fd, &streamfd_ind->h, BT_STREAMFD_IND);
+    if (e < 0) {
+        pa_log_error("failed to expect BT_STREAMFD_IND");
+        return e;
+    }
+
+    if (u->stream_fd >= 0)
+        close(u->stream_fd);
+
+    u->stream_fd = bt_audio_service_get_data_fd(u->audioservice_fd);
+    if (u->stream_fd < 0) {
+        pa_log_error("failed to get data fd");
+        return -errno;
+    }
+
+//    if (u->transport == BT_CAPABILITIES_TRANSPORT_A2DP) {
+//        opt_name = SO_SNDTIMEO;
+//        if (setsockopt(u->stream_fd, SOL_SOCKET, opt_name, &t, sizeof(t)) < 0) {
+//            pa_log_error("failed to set socket options for A2DP");
+//            return -errno;
+//        }
+//    }
+//    else {
+//        opt_name = SCO_TXBUFS;
+//        if (setsockopt(u->stream_fd, SOL_SCO, opt_name, &period_count, sizeof(period_count)) == 0)
+//            return 0;
+//        opt_name = SO_SNDBUF;
+//        if (setsockopt(u->stream_fd, SOL_SCO, opt_name, &period_count, sizeof(period_count)) == 0)
+//            return 0;
+//        /* FIXME : handle error codes */
+//    }
+
+    return 0;
+}
+
+static int bt_hw_constraint(struct userdata *u) {
+    /*TODO: A2DP */
+    u->ss.format = PA_SAMPLE_S16LE;
+    u->ss.rate = 8000;
+    u->ss.channels = 1;
+    return 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;
+
+    switch (code) {
+
+        case PA_SINK_MESSAGE_SET_STATE:
+            switch ((pa_sink_state_t) PA_PTR_TO_UINT(data)) {
+                case PA_SINK_SUSPENDED:
+                    pa_assert(PA_SINK_IS_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;
+//        }
+    }
+
+    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 (PA_SINK_IS_OPENED(u->sink->thread_info.state))
+//            if (u->sink->thread_info.rewind_requested)
+//                pa_sink_process_rewind(u->sink, 0);
+//
+//        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_IS_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_IS_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");
 }
 
 int pa__init(pa_module* m) {
+    int e;
+    char *rate, *channels;
     pa_modargs *ma;
+    pa_sink_new_data data;
     struct userdata *u;
-    int sk = -1;
 
     pa_assert(m);
     m->userdata = u = pa_xnew0(struct userdata, 1);
     u->module = m;
+    u->core = m->core;
+    u->audioservice_fd = -1;
+    u->stream_fd = -1;
+    u->transport = -1;
+    u->smoother = pa_smoother_new(PA_USEC_PER_SEC, PA_USEC_PER_SEC*2, TRUE, 10);
+    pa_memchunk_reset(&u->memchunk);
+    u->rtpoll = pa_rtpoll_new();
+    pa_thread_mq_init(&u->thread_mq, u->core->mainloop, u->rtpoll);
+    u->rtpoll_item = NULL;
 
     if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
         pa_log_error("failed to parse module arguments");
         goto fail;
     }
+    if (!(u->name = pa_modargs_get_value(ma, "name", DEFAULT_SINK_NAME))) {
+        pa_log_error("failed to get device address from module arguments");
+        goto fail;
+    }
     if (!(u->addr = pa_modargs_get_value(ma, "addr", NULL))) {
-        pa_log_error("failed to parse device address from module arguments");
+        pa_log_error("failed to get device address from module arguments");
         goto fail;
     }
-    if (!(u->uuid = pa_modargs_get_value(ma, "uuid", NULL))) {
-        pa_log_error("failed to parse device uuid from module arguments");
+    if (!(u->profile = pa_modargs_get_value(ma, "profile", NULL))) {
+        pa_log_error("failed to get profile from module arguments");
         goto fail;
     }
-    pa_log("Loading module-bt-device for %s, UUID=%s", u->addr, u->uuid);
+    if (!(rate = pa_modargs_get_value(ma, "rate", NULL))) {
+        pa_log_error("failed to get rate from module arguments");
+        goto fail;
+    }
+    u->rate = atoi(rate);
+    if (!(channels = pa_modargs_get_value(ma, "channels", NULL))) {
+        pa_log_error("failed to get profile from module arguments");
+        goto fail;
+    }
+    u->channels = atoi(channels);
+    pa_log("Loading module-bt-device for %s (%s), profile %s", u->name, u->addr, u->profile);
 
-    /* Connects to the BlueZ audio service via one BlueZ specific well known unix socket */
-    sk = bt_audio_service_open();
-    if (sk <= 0) {
+    /* connect to the bluez audio service */
+    u->audioservice_fd = bt_audio_service_open();
+    if (u->audioservice_fd <= 0) {
         pa_log_error("couldn't connect to bluetooth audio service");
         goto fail;
     }
-    pa_log("socket to audio service: %d", sk); /*debug*/
 
+    /* queries device capabilities */
+    e = bt_getcaps(u);
+    if (e < 0) {
+        pa_log_error("failed to get device capabilities");
+        goto fail;
+    }
+
+    /* configures the connection */
+    e = bt_setconf(u);
+    if (e < 0) {
+        pa_log_error("failed to set config");
+        goto fail;
+    }
+
+    /* gets the device socket */
+    e = bt_getstreamfd(u);
+    if (e < 0) {
+        pa_log_error("failed to get stream fd (%d)", e);
+        goto fail;
+    }
+
+    /* configure hw supported sample specs */
+    e = bt_hw_constraint(u);
+    if (e < 0) {
+        pa_log_error("failed to configure sample spec");
+        goto fail;
+    }
+
+    /* create sink */
+    pa_sink_new_data_init(&data);
+    data.driver = __FILE__;
+    data.module = m;
+    pa_sink_new_data_set_name(&data, u->name);
+    pa_sink_new_data_set_sample_spec(&data, &u->ss);
+    pa_proplist_sets(data.proplist, PA_PROP_DEVICE_STRING, u->name);
+    pa_proplist_setf(data.proplist, PA_PROP_DEVICE_DESCRIPTION, "Bluetooth sink '%s' (%s)", u->name, u->addr);
+    u->sink = pa_sink_new(m->core, &data, PA_SINK_HARDWARE|PA_SINK_NETWORK);
+    pa_sink_new_data_done(&data);
+    if (!u->sink) {
+        pa_log_error("failed to create sink");
+        goto fail;
+    }
+    u->sink->userdata = u;
+    u->sink->parent.process_msg = sink_process_msg;
+    pa_sink_set_asyncmsgq(u->sink, u->thread_mq.inq);
+    pa_sink_set_rtpoll(u->sink, u->rtpoll);
+
+    /* start rt thread */
+    if (!(u->thread = pa_thread_new(thread_func, u))) {
+        pa_log_error("failed to create thread");
+        goto fail;
+    }
+    pa_sink_put(u->sink);
+
+    pa_modargs_free(ma);
     return 0;
 
 fail:
+    if (ma)
+        pa_modargs_free(ma);
     pa__done(m);
     return -1;
 }

commit b8b761a81f613269db3822491aa2724f8172f92d
Author: João Paulo Rechi Vita <joao.vita at gmail.com>
Date:   Mon Aug 11 13:52:59 2008 -0300

    Fix PA_USEC_PER_SEC missing

diff --git a/src/modules/module-bt-device.c b/src/modules/module-bt-device.c
index 21dfa4d..9a40c55 100644
--- a/src/modules/module-bt-device.c
+++ b/src/modules/module-bt-device.c
@@ -26,6 +26,7 @@
 #include <string.h>
 
 #include <pulse/xmalloc.h>
+#include <pulse/timeval.h>
 #include <pulsecore/module.h>
 #include <pulsecore/modargs.h>
 #include <pulsecore/thread.h>

commit 255f9b0fe65631815895c7a2c0c4dd6752ec23f3
Author: João Paulo Rechi Vita <joao.vita at gmail.com>
Date:   Mon Aug 11 18:10:14 2008 -0300

    Initial code for rt thread

diff --git a/src/modules/module-bt-device.c b/src/modules/module-bt-device.c
index 9a40c55..c0ca637 100644
--- a/src/modules/module-bt-device.c
+++ b/src/modules/module-bt-device.c
@@ -24,9 +24,12 @@
 #endif
 
 #include <string.h>
+#include <errno.h>
+#include <poll.h>
 
 #include <pulse/xmalloc.h>
 #include <pulse/timeval.h>
+#include <pulsecore/core-error.h>
 #include <pulsecore/module.h>
 #include <pulsecore/modargs.h>
 #include <pulsecore/thread.h>
@@ -78,7 +81,7 @@ struct userdata {
     pa_rtpoll_item *rtpoll_item;
     pa_thread *thread;
 
-    pa_sample_spec ss;
+    int64_t offset;
     pa_smoother *smoother;
 
     pa_memchunk memchunk;
@@ -88,11 +91,15 @@ struct userdata {
     const char *profile;
     int rate;
     int channels;
+    pa_sample_spec ss;
 
     int audioservice_fd;
     int stream_fd;
+
     int transport;
     int link_mtu;
+    size_t block_size;
+    pa_usec_t latency;
 
     struct bt_a2dp a2dp;
 };
@@ -235,7 +242,6 @@ static uint8_t default_bitpool(uint8_t freq, uint8_t mode) {
 static int bt_a2dp_init(struct userdata *u) {
     sbc_capabilities_t *cap = &u->a2dp.sbc_capabilities;
     unsigned int max_bitpool, min_bitpool, rate, channels;
-    int dir;
 
     switch (u->rate) {
         case 48000:
@@ -427,7 +433,7 @@ static int bt_setconf(struct userdata *u) {
     }
 
     u->transport = setconf_rsp->transport;
-    u->link_mtu = setconf_rsp->link_mtu;
+    u->block_size = u->link_mtu = setconf_rsp->link_mtu;
 
     /* setup SBC encoder now we agree on parameters */
     if (u->transport == BT_CAPABILITIES_TRANSPORT_A2DP) {
@@ -440,7 +446,7 @@ static int bt_setconf(struct userdata *u) {
 }
 
 static int bt_getstreamfd(struct userdata *u) {
-    int e, opt_name;
+    int e/*, opt_name*/;
     char buf[BT_AUDIO_IPC_PACKET_SIZE];
     struct bt_streamstart_req *start_req = (void*) buf;
     bt_audio_rsp_msg_header_t *rsp_hdr = (void*) buf;
@@ -532,10 +538,10 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
             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;
+            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;
         }
 
@@ -554,94 +560,94 @@ 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;
-//    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 (PA_SINK_IS_OPENED(u->sink->thread_info.state))
-//            if (u->sink->thread_info.rewind_requested)
-//                pa_sink_process_rewind(u->sink, 0);
-//
-//        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_IS_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;
-//
+    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 (PA_SINK_IS_OPENED(u->sink->thread_info.state))
+            if (u->sink->thread_info.rewind_requested)
+                pa_sink_process_rewind(u->sink, 0);
+
+        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_IS_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->stream_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;
@@ -649,52 +655,52 @@ static void thread_func(void *userdata) {
 //                        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_IS_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");
+
+                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_IS_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");
 }
 
 int pa__init(pa_module* m) {
     int e;
-    char *rate, *channels;
+    const char *rate, *channels;
     pa_modargs *ma;
     pa_sink_new_data data;
     struct userdata *u;
@@ -706,6 +712,8 @@ int pa__init(pa_module* m) {
     u->audioservice_fd = -1;
     u->stream_fd = -1;
     u->transport = -1;
+    u->offset = 0;
+    u->latency = 0;
     u->smoother = pa_smoother_new(PA_USEC_PER_SEC, PA_USEC_PER_SEC*2, TRUE, 10);
     pa_memchunk_reset(&u->memchunk);
     u->rtpoll = pa_rtpoll_new();
@@ -783,7 +791,7 @@ int pa__init(pa_module* m) {
     pa_sink_new_data_set_sample_spec(&data, &u->ss);
     pa_proplist_sets(data.proplist, PA_PROP_DEVICE_STRING, u->name);
     pa_proplist_setf(data.proplist, PA_PROP_DEVICE_DESCRIPTION, "Bluetooth sink '%s' (%s)", u->name, u->addr);
-    u->sink = pa_sink_new(m->core, &data, PA_SINK_HARDWARE|PA_SINK_NETWORK);
+    u->sink = pa_sink_new(m->core, &data, PA_SINK_HARDWARE|PA_SINK_LATENCY|PA_SINK_NETWORK);
     pa_sink_new_data_done(&data);
     if (!u->sink) {
         pa_log_error("failed to create sink");

commit f992296b9763ceef1f2f013a89b98fe3e68366d5
Author: João Paulo Rechi Vita <joao.vita at gmail.com>
Date:   Mon Aug 11 22:54:09 2008 -0300

    Hand the stream socket to the rt thread

diff --git a/src/modules/module-bt-device.c b/src/modules/module-bt-device.c
index c0ca637..da2fa33 100644
--- a/src/modules/module-bt-device.c
+++ b/src/modules/module-bt-device.c
@@ -113,6 +113,10 @@ static const char* const valid_modargs[] = {
     NULL
 };
 
+enum {
+    SINK_MESSAGE_PASS_SOCKET = PA_SINK_MESSAGE_MAX
+};
+
 static int bt_audioservice_send(int sk, const bt_audio_msg_header_t *msg) {
     int e;
     pa_log/*_debug*/("sending %s", bt_audio_strmsg(msg->msg_type));
@@ -545,15 +549,15 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
             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;
-//        }
+        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->stream_fd;
+            pollfd->events = pollfd->revents = 0;
+            return 0;
+        }
     }
 
     return pa_sink_process_msg(o, code, data, offset, chunk);
@@ -809,6 +813,9 @@ int pa__init(pa_module* m) {
     }
     pa_sink_put(u->sink);
 
+    /* hand the socket to the rt thread */
+    pa_asyncmsgq_post(u->thread_mq.inq, PA_MSGOBJECT(u->sink), SINK_MESSAGE_PASS_SOCKET, NULL, 0, NULL, NULL);
+
     pa_modargs_free(ma);
     return 0;
 

commit 0396a6052903b8ceec71c3159fa1a84eb6d3aa96
Author: João Paulo Rechi Vita <joao.vita at gmail.com>
Date:   Wed Aug 13 14:52:26 2008 -0300

    Copy arguments values instead of just getting a pointer for them

diff --git a/src/modules/module-bt-device.c b/src/modules/module-bt-device.c
index da2fa33..ab50f24 100644
--- a/src/modules/module-bt-device.c
+++ b/src/modules/module-bt-device.c
@@ -728,15 +728,15 @@ int pa__init(pa_module* m) {
         pa_log_error("failed to parse module arguments");
         goto fail;
     }
-    if (!(u->name = pa_modargs_get_value(ma, "name", DEFAULT_SINK_NAME))) {
+    if (!(u->name = pa_xstrdup(pa_modargs_get_value(ma, "name", DEFAULT_SINK_NAME)))) {
         pa_log_error("failed to get device address from module arguments");
         goto fail;
     }
-    if (!(u->addr = pa_modargs_get_value(ma, "addr", NULL))) {
+    if (!(u->addr = pa_xstrdup(pa_modargs_get_value(ma, "addr", NULL)))) {
         pa_log_error("failed to get device address from module arguments");
         goto fail;
     }
-    if (!(u->profile = pa_modargs_get_value(ma, "profile", NULL))) {
+    if (!(u->profile = pa_xstrdup(pa_modargs_get_value(ma, "profile", NULL)))) {
         pa_log_error("failed to get profile from module arguments");
         goto fail;
     }

commit aa310a40f88379db3ee976721ac666b89f09aabe
Author: João Paulo Rechi Vita <joao.vita at gmail.com>
Date:   Wed Aug 13 15:56:05 2008 -0300

    Changes for pa_modargs_get_value_u32 for integer arguments and correct some error messages

diff --git a/src/modules/module-bt-device.c b/src/modules/module-bt-device.c
index ab50f24..be6795e 100644
--- a/src/modules/module-bt-device.c
+++ b/src/modules/module-bt-device.c
@@ -729,7 +729,7 @@ int pa__init(pa_module* m) {
         goto fail;
     }
     if (!(u->name = pa_xstrdup(pa_modargs_get_value(ma, "name", DEFAULT_SINK_NAME)))) {
-        pa_log_error("failed to get device address from module arguments");
+        pa_log_error("failed to get device name from module arguments");
         goto fail;
     }
     if (!(u->addr = pa_xstrdup(pa_modargs_get_value(ma, "addr", NULL)))) {
@@ -740,16 +740,14 @@ int pa__init(pa_module* m) {
         pa_log_error("failed to get profile from module arguments");
         goto fail;
     }
-    if (!(rate = pa_modargs_get_value(ma, "rate", NULL))) {
+    if (pa_modargs_get_value_u32(ma, "rate", &u->rate) < 0) {
         pa_log_error("failed to get rate from module arguments");
         goto fail;
     }
-    u->rate = atoi(rate);
-    if (!(channels = pa_modargs_get_value(ma, "channels", NULL))) {
-        pa_log_error("failed to get profile from module arguments");
+    if (pa_modargs_get_value_u32(ma, "channels", &u->channels) < 0) {
+        pa_log_error("failed to get channels from module arguments");
         goto fail;
     }
-    u->channels = atoi(channels);
     pa_log("Loading module-bt-device for %s (%s), profile %s", u->name, u->addr, u->profile);
 
     /* connect to the bluez audio service */

commit 16d5aab0202fac8a57f2a486d141b9d789eb39ad
Author: João Paulo Rechi Vita <joao.vita at gmail.com>
Date:   Wed Aug 13 16:06:36 2008 -0300

    Get rid of SINK_MESSAGE_PASS_SOCKET, since we don't really need it

diff --git a/src/modules/module-bt-device.c b/src/modules/module-bt-device.c
index be6795e..a92cc55 100644
--- a/src/modules/module-bt-device.c
+++ b/src/modules/module-bt-device.c
@@ -113,10 +113,6 @@ static const char* const valid_modargs[] = {
     NULL
 };
 
-enum {
-    SINK_MESSAGE_PASS_SOCKET = PA_SINK_MESSAGE_MAX
-};
-
 static int bt_audioservice_send(int sk, const bt_audio_msg_header_t *msg) {
     int e;
     pa_log/*_debug*/("sending %s", bt_audio_strmsg(msg->msg_type));
@@ -549,15 +545,6 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
             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->stream_fd;
-            pollfd->events = pollfd->revents = 0;
-            return 0;
-        }
     }
 
     return pa_sink_process_msg(o, code, data, offset, chunk);
@@ -811,9 +798,6 @@ int pa__init(pa_module* m) {
     }
     pa_sink_put(u->sink);
 
-    /* hand the socket to the rt thread */
-    pa_asyncmsgq_post(u->thread_mq.inq, PA_MSGOBJECT(u->sink), SINK_MESSAGE_PASS_SOCKET, NULL, 0, NULL, NULL);
-
     pa_modargs_free(ma);
     return 0;
 

commit b4ded21e08f9c397cd13b1e6701544940598d702
Author: João Paulo Rechi Vita <joao.vita at gmail.com>
Date:   Wed Aug 13 16:07:19 2008 -0300

    Change strerror() to pa_cstrerror()

diff --git a/src/modules/module-bt-device.c b/src/modules/module-bt-device.c
index a92cc55..9b91a7c 100644
--- a/src/modules/module-bt-device.c
+++ b/src/modules/module-bt-device.c
@@ -120,7 +120,7 @@ static int bt_audioservice_send(int sk, const bt_audio_msg_header_t *msg) {
         e = 0;
     else {
         e = -errno;
-        pa_log_error("Error sending data to audio service: %s(%d)", strerror(errno), errno);
+        pa_log_error("Error sending data to audio service: %s(%d)", pa_cstrerror(errno), errno);
     }
     return e;
 }
@@ -143,7 +143,7 @@ static int bt_audioservice_recv(int sk, bt_audio_msg_header_t *inmsg) {
     }
     else {
         e = -errno;
-        pa_log_error("Error receiving data from audio service: %s(%d)", strerror(errno), errno);
+        pa_log_error("Error receiving data from audio service: %s(%d)", pa_cstrerror(errno), errno);
     }
 
     return e;
@@ -194,7 +194,7 @@ static int bt_getcaps(struct userdata *u) {
         return e;
     }
     if (rsp_hdr->posix_errno != 0) {
-        pa_log_error("BT_GETCAPABILITIES failed : %s (%d)", strerror(rsp_hdr->posix_errno), rsp_hdr->posix_errno);
+        pa_log_error("BT_GETCAPABILITIES failed : %s (%d)", pa_cstrerror(rsp_hdr->posix_errno), rsp_hdr->posix_errno);
         return -rsp_hdr->posix_errno;
     }
 
@@ -428,7 +428,7 @@ static int bt_setconf(struct userdata *u) {
     }
 
     if (rsp_hdr->posix_errno != 0) {
-        pa_log_error("BT_SETCONFIGURATION failed : %s(%d)", strerror(rsp_hdr->posix_errno), rsp_hdr->posix_errno);
+        pa_log_error("BT_SETCONFIGURATION failed : %s(%d)", pa_cstrerror(rsp_hdr->posix_errno), rsp_hdr->posix_errno);
         return -rsp_hdr->posix_errno;
     }
 
@@ -468,7 +468,7 @@ static int bt_getstreamfd(struct userdata *u) {
     }
 
     if (rsp_hdr->posix_errno != 0) {
-        pa_log_error("BT_START failed : %s(%d)", strerror(rsp_hdr->posix_errno), rsp_hdr->posix_errno);
+        pa_log_error("BT_START failed : %s(%d)", pa_cstrerror(rsp_hdr->posix_errno), rsp_hdr->posix_errno);
         return -rsp_hdr->posix_errno;
     }
 

commit d48961f2588f5058b7abffb0a006efe1518e2afb
Author: João Paulo Rechi Vita <joao.vita at gmail.com>
Date:   Wed Aug 13 16:08:20 2008 -0300

    Change close() to pa_close()

diff --git a/src/modules/module-bt-device.c b/src/modules/module-bt-device.c
index 9b91a7c..474e590 100644
--- a/src/modules/module-bt-device.c
+++ b/src/modules/module-bt-device.c
@@ -479,7 +479,7 @@ static int bt_getstreamfd(struct userdata *u) {
     }
 
     if (u->stream_fd >= 0)
-        close(u->stream_fd);
+        pa_close(u->stream_fd);
 
     u->stream_fd = bt_audio_service_get_data_fd(u->audioservice_fd);
     if (u->stream_fd < 0) {

commit 0519e5d446123649c1f0ae6bc3f88bb6a1e63c68
Author: João Paulo Rechi Vita <joao.vita at gmail.com>
Date:   Wed Aug 13 16:52:28 2008 -0300

    Add include for sample.h

diff --git a/src/modules/module-bt-device.c b/src/modules/module-bt-device.c
index 474e590..383ff4e 100644
--- a/src/modules/module-bt-device.c
+++ b/src/modules/module-bt-device.c
@@ -29,6 +29,7 @@
 
 #include <pulse/xmalloc.h>
 #include <pulse/timeval.h>
+#include <pulse/sample.h>
 #include <pulsecore/core-error.h>
 #include <pulsecore/module.h>
 #include <pulsecore/modargs.h>

commit eb1e308710a27e0bba13a1b948225762c71946cf
Author: João Paulo Rechi Vita <joao.vita at gmail.com>
Date:   Thu Aug 14 18:05:01 2008 -0300

    Initialize rtpoll_item

diff --git a/src/modules/module-bt-device.c b/src/modules/module-bt-device.c
index 383ff4e..3a75684 100644
--- a/src/modules/module-bt-device.c
+++ b/src/modules/module-bt-device.c
@@ -695,6 +695,7 @@ int pa__init(pa_module* m) {
     const char *rate, *channels;
     pa_modargs *ma;
     pa_sink_new_data data;
+    struct pollfd *pollfd;
     struct userdata *u;
 
     pa_assert(m);
@@ -765,6 +766,10 @@ int pa__init(pa_module* m) {
         pa_log_error("failed to get stream fd (%d)", e);
         goto fail;
     }
+    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->stream_fd;
+    pollfd->events = pollfd->revents = 0;
 
     /* configure hw supported sample specs */
     e = bt_hw_constraint(u);

commit fcd7dc1fd715b13f7fe29f8041a4e00a3666af2e
Author: João Paulo Rechi Vita <joao.vita at gmail.com>
Date:   Thu Aug 14 18:12:26 2008 -0300

    Add include for core-util.h

diff --git a/src/modules/module-bt-device.c b/src/modules/module-bt-device.c
index 3a75684..8769d18 100644
--- a/src/modules/module-bt-device.c
+++ b/src/modules/module-bt-device.c
@@ -30,6 +30,7 @@
 #include <pulse/xmalloc.h>
 #include <pulse/timeval.h>
 #include <pulse/sample.h>
+#include <pulsecore/core-util.h>
 #include <pulsecore/core-error.h>
 #include <pulsecore/module.h>
 #include <pulsecore/modargs.h>

commit 71f1d68dac9ec3b8f94b0e3bbfdddc28b4abaf7d
Author: João Paulo Rechi Vita <joao.vita at gmail.com>
Date:   Thu Aug 14 20:56:58 2008 -0300

    Fix block size for SCO

diff --git a/src/modules/module-bt-device.c b/src/modules/module-bt-device.c
index 8769d18..619a4d4 100644
--- a/src/modules/module-bt-device.c
+++ b/src/modules/module-bt-device.c
@@ -435,7 +435,11 @@ static int bt_setconf(struct userdata *u) {
     }
 
     u->transport = setconf_rsp->transport;
-    u->block_size = u->link_mtu = setconf_rsp->link_mtu;
+    u->link_mtu = setconf_rsp->link_mtu;
+    if (u->transport == BT_CAPABILITIES_TRANSPORT_A2DP)
+        /* TODO: Check the max possible size */ u->block_size = u->link_mtu / 2;
+    else
+        u->block_size = u->link_mtu;
 
     /* setup SBC encoder now we agree on parameters */
     if (u->transport == BT_CAPABILITIES_TRANSPORT_A2DP) {

commit 2e51b9302631ad1105381ae97b20f5adbee47cff
Author: João Paulo Rechi Vita <joao.vita at gmail.com>
Date:   Thu Aug 14 20:57:32 2008 -0300

    Make stream socket non-blocking

diff --git a/src/modules/module-bt-device.c b/src/modules/module-bt-device.c
index 619a4d4..79ed101 100644
--- a/src/modules/module-bt-device.c
+++ b/src/modules/module-bt-device.c
@@ -509,6 +509,7 @@ static int bt_getstreamfd(struct userdata *u) {
 //            return 0;
 //        /* FIXME : handle error codes */
 //    }
+    pa_make_fd_nonblock(u->stream_fd);
 
     return 0;
 }

commit 435eb0711b10ac0f33051a31bd74ed1f41277aa6
Author: João Paulo Rechi Vita <joao.vita at gmail.com>
Date:   Thu Aug 14 20:59:28 2008 -0300

    Change pa_sink_render to pa_sink_render_into_full and remove some unnecessary checks on the rt thread

diff --git a/src/modules/module-bt-device.c b/src/modules/module-bt-device.c
index 79ed101..cb16601 100644
--- a/src/modules/module-bt-device.c
+++ b/src/modules/module-bt-device.c
@@ -87,6 +87,7 @@ struct userdata {
     pa_smoother *smoother;
 
     pa_memchunk memchunk;
+    pa_mempool *mempool;
 
     const char *name;
     const char *addr;
@@ -572,123 +573,115 @@ static void thread_func(void *userdata) {
 
     for (;;) {
         int ret;
+        struct pollfd *pollfd;
 
-        if (PA_SINK_IS_OPENED(u->sink->thread_info.state))
-            if (u->sink->thread_info.rewind_requested)
+        if (PA_SINK_IS_OPENED(u->sink->thread_info.state)) {
+            if (u->sink->thread_info.rewind_requested) {
+                pa_log("rewind_requested");
                 pa_sink_process_rewind(u->sink, 0);
+                pa_log("rewind_finished");
+            }
+        }
 
-        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_IS_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->stream_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;
+        pollfd = pa_rtpoll_item_get_pollfd(u->rtpoll_item, NULL);
+
+        /* Render some data and write it to the fifo */
+        if (PA_SINK_IS_OPENED(u->sink->thread_info.state) && pollfd->revents) {
+            pa_usec_t usec;
+            int64_t n;
+            pa_log("Render some data and write it to the fifo");
+
+            for (;;) {
+                ssize_t l;
+                void *p;
+
+                u->memchunk.memblock = pa_memblock_new(u->mempool, u->block_size);
+                pa_log("memblock allocated");
+                u->memchunk.length = pa_memblock_get_length(u->memchunk.memblock);
+                pa_log("memchunk length");
+                pa_sink_render_into_full(u->sink, &u->memchunk);
+                pa_log("rendered");
+
+                pa_assert(u->memchunk.length > 0);
+
+                p = pa_memblock_acquire(u->memchunk.memblock);
+                pa_log("memblock acquired");
+                l = pa_write(u->stream_fd, (uint8_t*) p, u->memchunk.length, &write_type);
+                pa_log("memblock written");
+                pa_memblock_release(u->memchunk.memblock);
+                pa_log("memblock released");
+
+                pa_assert(l != 0);
+
+                if (l < 0) {
+                    pa_log("l = %d < 0", l);
+                    if (errno == EINTR)
+                        continue;
+                    else if (errno == EAGAIN)
+                        goto filled_up;
+                    else {
+                        pa_log("Failed to write data to FIFO: %s", pa_cstrerror(errno));
+                        goto fail;
                     }
+                } else {
+                    pa_log("l = %d >= 0", l);
+                    u->offset += l;
+                    pa_memblock_unref(u->memchunk.memblock);
+                    pa_log("memblock unrefered");
+                    pa_memchunk_reset(&u->memchunk);
+                    pa_log("memchunk reseted");
+                    pollfd->revents = 0;
                 }
+            }
 
-            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 */
+filled_up:
 
-                n = u->offset;
+            pa_log("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;
-//                }
+//           {
+//               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_IS_OPENED(u->sink->thread_info.state) ? POLLOUT : 0;
+            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);
         }
 
-        if ((ret = pa_rtpoll_run(u->rtpoll, TRUE)) < 0)
+        /* Hmm, nothing to do. Let's sleep */
+        pa_log("let's sleep");
+        pollfd->events = PA_SINK_IS_OPENED(u->sink->thread_info.state) ? POLLOUT : 0;
+
+        if ((ret = pa_rtpoll_run(u->rtpoll, TRUE)) < 0) {
+            pa_log("ret < 0");
             goto fail;
+        }
+        pa_log("waking up");
 
-        if (ret == 0)
+        if (ret == 0) {
+            pa_log("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;
-            }
+        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 */
+    /* If this was no regular exit from the loop we have to continue processing messages until we receive PA_MESSAGE_SHUTDOWN */
+    pa_log("fail");
     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);
 
@@ -714,6 +707,7 @@ int pa__init(pa_module* m) {
     u->offset = 0;
     u->latency = 0;
     u->smoother = pa_smoother_new(PA_USEC_PER_SEC, PA_USEC_PER_SEC*2, TRUE, 10);
+    u->mempool = pa_mempool_new(FALSE);
     pa_memchunk_reset(&u->memchunk);
     u->rtpoll = pa_rtpoll_new();
     pa_thread_mq_init(&u->thread_mq, u->core->mainloop, u->rtpoll);

commit 0d37b912ee342a8b50a25fb29fdfdcf1ddac742c
Author: João Paulo Rechi Vita <joao.vita at gmail.com>
Date:   Fri Aug 15 16:23:54 2008 -0300

    Remove PA_SINK_NETWORK flag and move the passage of streamfd to the rt thread just before the thread creation

diff --git a/src/modules/module-bt-device.c b/src/modules/module-bt-device.c
index cb16601..3881dd8 100644
--- a/src/modules/module-bt-device.c
+++ b/src/modules/module-bt-device.c
@@ -766,10 +766,6 @@ int pa__init(pa_module* m) {
         pa_log_error("failed to get stream fd (%d)", e);
         goto fail;
     }
-    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->stream_fd;
-    pollfd->events = pollfd->revents = 0;
 
     /* configure hw supported sample specs */
     e = bt_hw_constraint(u);
@@ -786,7 +782,7 @@ int pa__init(pa_module* m) {
     pa_sink_new_data_set_sample_spec(&data, &u->ss);
     pa_proplist_sets(data.proplist, PA_PROP_DEVICE_STRING, u->name);
     pa_proplist_setf(data.proplist, PA_PROP_DEVICE_DESCRIPTION, "Bluetooth sink '%s' (%s)", u->name, u->addr);
-    u->sink = pa_sink_new(m->core, &data, PA_SINK_HARDWARE|PA_SINK_LATENCY|PA_SINK_NETWORK);
+    u->sink = pa_sink_new(m->core, &data, PA_SINK_HARDWARE|PA_SINK_LATENCY);
     pa_sink_new_data_done(&data);
     if (!u->sink) {
         pa_log_error("failed to create sink");
@@ -797,6 +793,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);
 
+    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->stream_fd;
+    pollfd->events = pollfd->revents = 0;
+
     /* start rt thread */
     if (!(u->thread = pa_thread_new(thread_func, u))) {
         pa_log_error("failed to create thread");

commit 123ba4f5f17dbc82b2e82be3db1bf11a12e7c84a
Author: João Paulo Rechi Vita <joao.vita at gmail.com>
Date:   Fri Aug 15 16:56:26 2008 -0300

    Fix handling of PA_SINK_MESSAGE_GET_LATENCY

diff --git a/src/modules/module-bt-device.c b/src/modules/module-bt-device.c
index 3881dd8..4c2a92f 100644
--- a/src/modules/module-bt-device.c
+++ b/src/modules/module-bt-device.c
@@ -526,6 +526,7 @@ static int bt_hw_constraint(struct userdata *u) {
 static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offset, pa_memchunk *chunk) {
     struct userdata *u = PA_SINK(o)->userdata;
 
+    pa_log/*_debug*/("got message: %d", code);
     switch (code) {
 
         case PA_SINK_MESSAGE_SET_STATE:
@@ -550,7 +551,7 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
             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;
+            return 0;
         }
 
     }

commit 6c10b106d8836a18de3a4d7986dafdb426557669
Author: João Paulo Rechi Vita <joao.vita at gmail.com>
Date:   Fri Aug 15 18:13:25 2008 -0300

    Try to improve time estimation

diff --git a/src/modules/module-bt-device.c b/src/modules/module-bt-device.c
index 4c2a92f..1a231df 100644
--- a/src/modules/module-bt-device.c
+++ b/src/modules/module-bt-device.c
@@ -642,13 +642,13 @@ 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
+#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)

commit 77138dd8f702cf8dd15892ea6199b604493d97a9
Author: João Paulo Rechi Vita <joao.vita at gmail.com>
Date:   Sat Aug 16 13:54:28 2008 -0300

    Change default sink name to bluetooth_sink

diff --git a/src/modules/module-bt-device.c b/src/modules/module-bt-device.c
index 1a231df..95257da 100644
--- a/src/modules/module-bt-device.c
+++ b/src/modules/module-bt-device.c
@@ -45,7 +45,7 @@
 #include "bt-ipc.h"
 #include "bt-sbc.h"
 
-#define DEFAULT_SINK_NAME "bt_sink"
+#define DEFAULT_SINK_NAME "bluetooth_sink"
 #define BUFFER_SIZE 2048
 #define MAX_BITPOOL 64
 #define MIN_BITPOOL 2

commit 85a931f3334c7e743a3f7afdca7e23d5989ba672
Author: João Paulo Rechi Vita <joao.vita at gmail.com>
Date:   Sat Aug 16 16:00:32 2008 -0300

    Get rid of hw_constraint function. It's code now lives inside bt_setconf().

diff --git a/src/modules/module-bt-device.c b/src/modules/module-bt-device.c
index 95257da..e808cfb 100644
--- a/src/modules/module-bt-device.c
+++ b/src/modules/module-bt-device.c
@@ -410,6 +410,10 @@ static int bt_setconf(struct userdata *u) {
         }
     }
 
+    u->ss.format = PA_SAMPLE_S16LE;
+    u->ss.rate = u->rate;
+    u->ss.channels = u->channels;
+
     memset(setconf_req, 0, BT_AUDIO_IPC_PACKET_SIZE);
     setconf_req->h.msg_type = BT_SETCONFIGURATION_REQ;
     strncpy(setconf_req->device, u->addr, 18);
@@ -515,14 +519,6 @@ static int bt_getstreamfd(struct userdata *u) {
     return 0;
 }
 
-static int bt_hw_constraint(struct userdata *u) {
-    /*TODO: A2DP */
-    u->ss.format = PA_SAMPLE_S16LE;
-    u->ss.rate = 8000;
-    u->ss.channels = 1;
-    return 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;
 
@@ -768,13 +764,6 @@ int pa__init(pa_module* m) {
         goto fail;
     }
 
-    /* configure hw supported sample specs */
-    e = bt_hw_constraint(u);
-    if (e < 0) {
-        pa_log_error("failed to configure sample spec");
-        goto fail;
-    }
-
     /* create sink */
     pa_sink_new_data_init(&data);
     data.driver = __FILE__;

commit b5c4d2e5f1a9a8ac013e95163d5513736b2534ca
Author: João Paulo Rechi Vita <joao.vita at gmail.com>
Date:   Sat Aug 16 16:03:20 2008 -0300

    Configure bt connection for a2dp

diff --git a/src/modules/bt-rtp.h b/src/modules/bt-rtp.h
new file mode 100644
index 0000000..690bd43
--- /dev/null
+++ b/src/modules/bt-rtp.h
@@ -0,0 +1,76 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2004-2008  Marcel Holtmann <marcel at holtmann.org>
+ *
+ *
+ *  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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+
+struct rtp_header {
+	uint8_t cc:4;
+	uint8_t x:1;
+	uint8_t p:1;
+	uint8_t v:2;
+
+	uint8_t pt:7;
+	uint8_t m:1;
+
+	uint16_t sequence_number;
+	uint32_t timestamp;
+	uint32_t ssrc;
+	uint32_t csrc[0];
+} __attribute__ ((packed));
+
+struct rtp_payload {
+	uint8_t frame_count:4;
+	uint8_t rfa0:1;
+	uint8_t is_last_fragment:1;
+	uint8_t is_first_fragment:1;
+	uint8_t is_fragmented:1;
+} __attribute__ ((packed));
+
+#elif __BYTE_ORDER == __BIG_ENDIAN
+
+struct rtp_header {
+	uint8_t v:2;
+	uint8_t p:1;
+	uint8_t x:1;
+	uint8_t cc:4;
+
+	uint8_t m:1;
+	uint8_t pt:7;
+
+	uint16_t sequence_number;
+	uint32_t timestamp;
+	uint32_t ssrc;
+	uint32_t csrc[0];
+} __attribute__ ((packed));
+
+struct rtp_payload {
+	uint8_t is_fragmented:1;
+	uint8_t is_first_fragment:1;
+	uint8_t is_last_fragment:1;
+	uint8_t rfa0:1;
+	uint8_t frame_count:4;
+} __attribute__ ((packed));
+
+#else
+#error "Unknown byte order"
+#endif
diff --git a/src/modules/module-bt-device.c b/src/modules/module-bt-device.c
index e808cfb..87d6ea6 100644
--- a/src/modules/module-bt-device.c
+++ b/src/modules/module-bt-device.c
@@ -44,11 +44,15 @@
 #include "module-bt-device-symdef.h"
 #include "bt-ipc.h"
 #include "bt-sbc.h"
+#include "bt-rtp.h"
 
 #define DEFAULT_SINK_NAME "bluetooth_sink"
 #define BUFFER_SIZE 2048
 #define MAX_BITPOOL 64
 #define MIN_BITPOOL 2
+#define SOL_SCO 17
+#define SCO_TXBUFS 0x03
+#define SCO_RXBUFS 0x04
 
 PA_MODULE_AUTHOR("Joao Paulo Rechi Vita");
 PA_MODULE_DESCRIPTION("Bluetooth audio sink and source");
@@ -244,7 +248,7 @@ static uint8_t default_bitpool(uint8_t freq, uint8_t mode) {
 
 static int bt_a2dp_init(struct userdata *u) {
     sbc_capabilities_t *cap = &u->a2dp.sbc_capabilities;
-    unsigned int max_bitpool, min_bitpool, rate, channels;
+    unsigned int max_bitpool, min_bitpool;
 
     switch (u->rate) {
         case 48000:
@@ -260,14 +264,14 @@ static int bt_a2dp_init(struct userdata *u) {
             cap->frequency = BT_SBC_SAMPLING_FREQ_16000;
             break;
         default:
-            pa_log_error("Rate %d not supported", rate);
+            pa_log_error("Rate %d not supported", u->rate);
             return -1;
     }
 
 //    if (cfg->has_channel_mode)
 //        cap->channel_mode = cfg->channel_mode;
 //    else 
-    if (channels == 2) {
+    if (u->channels == 2) {
         if (cap->channel_mode & BT_A2DP_CHANNEL_MODE_JOINT_STEREO)
             cap->channel_mode = BT_A2DP_CHANNEL_MODE_JOINT_STEREO;
         else if (cap->channel_mode & BT_A2DP_CHANNEL_MODE_STEREO)
@@ -364,7 +368,7 @@ static void bt_a2dp_setup(struct bt_a2dp *a2dp) {
     if (active_capabilities.channel_mode & BT_A2DP_CHANNEL_MODE_JOINT_STEREO)
         a2dp->sbc.mode = SBC_MODE_JOINT_STEREO;
 
-    a2dp->sbc.allocation = active_capabilities.allocation_method == BT_A2DP_ALLOCATION_SNR ? SBC_AM_SNR : SBC_AM_LOUDNESS;
+    a2dp->sbc.allocation = (active_capabilities.allocation_method == BT_A2DP_ALLOCATION_SNR ? SBC_AM_SNR : SBC_AM_LOUDNESS);
 
     switch (active_capabilities.subbands) {
         case BT_A2DP_SUBBANDS_4:
@@ -392,7 +396,7 @@ static void bt_a2dp_setup(struct bt_a2dp *a2dp) {
 
     a2dp->sbc.bitpool = active_capabilities.max_bitpool;
     a2dp->codesize = sbc_get_codesize(&a2dp->sbc);
-//    a2dp->count = sizeof(struct rtp_header) + sizeof(struct rtp_payload);
+    a2dp->count = sizeof(struct rtp_header) + sizeof(struct rtp_payload);
 }
 
 static int bt_setconf(struct userdata *u) {
@@ -457,7 +461,9 @@ static int bt_setconf(struct userdata *u) {
 }
 
 static int bt_getstreamfd(struct userdata *u) {
-    int e/*, opt_name*/;
+    int e;
+//    uint32_t period_count = io->buffer_size / io->period_size;
+//    struct timeval t = { 0, period_count };
     char buf[BT_AUDIO_IPC_PACKET_SIZE];
     struct bt_streamstart_req *start_req = (void*) buf;
     bt_audio_rsp_msg_header_t *rsp_hdr = (void*) buf;
@@ -494,23 +500,20 @@ static int bt_getstreamfd(struct userdata *u) {
 
     u->stream_fd = bt_audio_service_get_data_fd(u->audioservice_fd);
     if (u->stream_fd < 0) {
-        pa_log_error("failed to get data fd");
+        pa_log_error("failed to get data fd: %s (%d)",pa_cstrerror(errno), errno);
         return -errno;
     }
 
 //    if (u->transport == BT_CAPABILITIES_TRANSPORT_A2DP) {
-//        opt_name = SO_SNDTIMEO;
-//        if (setsockopt(u->stream_fd, SOL_SOCKET, opt_name, &t, sizeof(t)) < 0) {
-//            pa_log_error("failed to set socket options for A2DP");
+//        if (setsockopt(u->stream_fd, SOL_SOCKET, SO_SNDTIMEO, &t, sizeof(t)) < 0) {
+//            pa_log_error("failed to set socket options for A2DP: %s (%d)",pa_cstrerror(errno), errno);
 //            return -errno;
 //        }
 //    }
 //    else {
-//        opt_name = SCO_TXBUFS;
-//        if (setsockopt(u->stream_fd, SOL_SCO, opt_name, &period_count, sizeof(period_count)) == 0)
+//        if (setsockopt(u->stream_fd, SOL_SCO, SCO_TXBUFS, &period_count, sizeof(period_count)) == 0)
 //            return 0;
-//        opt_name = SO_SNDBUF;
-//        if (setsockopt(u->stream_fd, SOL_SCO, opt_name, &period_count, sizeof(period_count)) == 0)
+//        if (setsockopt(u->stream_fd, SOL_SCO, SO_SNDBUF, &period_count, sizeof(period_count)) == 0)
 //            return 0;
 //        /* FIXME : handle error codes */
 //    }
@@ -703,6 +706,7 @@ int pa__init(pa_module* m) {
     u->transport = -1;
     u->offset = 0;
     u->latency = 0;
+    u->a2dp.sbc_initialized = 0;
     u->smoother = pa_smoother_new(PA_USEC_PER_SEC, PA_USEC_PER_SEC*2, TRUE, 10);
     u->mempool = pa_mempool_new(FALSE);
     pa_memchunk_reset(&u->memchunk);

commit e54547956306485e4c0c961c9499ee8f19628bca
Author: João Paulo Rechi Vita <joao.vita at gmail.com>
Date:   Sun Aug 17 01:54:12 2008 -0300

    Fix block_size calculation

diff --git a/src/modules/module-bt-device.c b/src/modules/module-bt-device.c
index 87d6ea6..4fb4fd7 100644
--- a/src/modules/module-bt-device.c
+++ b/src/modules/module-bt-device.c
@@ -445,17 +445,16 @@ static int bt_setconf(struct userdata *u) {
 
     u->transport = setconf_rsp->transport;
     u->link_mtu = setconf_rsp->link_mtu;
-    if (u->transport == BT_CAPABILITIES_TRANSPORT_A2DP)
-        /* TODO: Check the max possible size */ u->block_size = u->link_mtu / 2;
-    else
-        u->block_size = u->link_mtu;
 
     /* setup SBC encoder now we agree on parameters */
     if (u->transport == BT_CAPABILITIES_TRANSPORT_A2DP) {
         bt_a2dp_setup(&u->a2dp);
+        u->block_size = u->a2dp.codesize;
         pa_log/*debug*/("\tallocation=%u\n\tsubbands=%u\n\tblocks=%u\n\tbitpool=%u\n",
                 u->a2dp.sbc.allocation, u->a2dp.sbc.subbands, u->a2dp.sbc.blocks, u->a2dp.sbc.bitpool);
     }
+    else
+        u->block_size = u->link_mtu;
 
     return 0;
 }

commit c89301da262cdb835bb852f0b3d43aaf12a520f7
Author: João Paulo Rechi Vita <joao.vita at gmail.com>
Date:   Sun Aug 17 20:35:56 2008 -0300

    Fix sample size

diff --git a/src/modules/module-bt-device.c b/src/modules/module-bt-device.c
index 4fb4fd7..5c69e90 100644
--- a/src/modules/module-bt-device.c
+++ b/src/modules/module-bt-device.c
@@ -412,9 +412,11 @@ static int bt_setconf(struct userdata *u) {
             pa_log_error("a2dp_init error");
             return e;
         }
+        u->ss.format = PA_SAMPLE_S16LE;
     }
+    else
+        u->ss.format = PA_SAMPLE_U8;
 
-    u->ss.format = PA_SAMPLE_S16LE;
     u->ss.rate = u->rate;
     u->ss.channels = u->channels;
 

commit 2f455bfa5a8cfde0df9df1510e1bce560be12fe9
Author: João Paulo Rechi Vita <joao.vita at gmail.com>
Date:   Sun Aug 17 20:36:33 2008 -0300

    A2DP poorly working

diff --git a/src/modules/module-bt-device.c b/src/modules/module-bt-device.c
index 5c69e90..4e1b051 100644
--- a/src/modules/module-bt-device.c
+++ b/src/modules/module-bt-device.c
@@ -597,9 +597,9 @@ static void thread_func(void *userdata) {
                 void *p;
 
                 u->memchunk.memblock = pa_memblock_new(u->mempool, u->block_size);
-                pa_log("memblock allocated");
+                pa_log("memblock allocated %d", u->block_size);
                 u->memchunk.length = pa_memblock_get_length(u->memchunk.memblock);
-                pa_log("memchunk length");
+                pa_log("memchunk length %d", u->memchunk.length);
                 pa_sink_render_into_full(u->sink, &u->memchunk);
                 pa_log("rendered");
 
@@ -608,7 +608,7 @@ static void thread_func(void *userdata) {
                 p = pa_memblock_acquire(u->memchunk.memblock);
                 pa_log("memblock acquired");
                 l = pa_write(u->stream_fd, (uint8_t*) p, u->memchunk.length, &write_type);
-                pa_log("memblock written");
+                pa_log("memblock written %d bytes", l);
                 pa_memblock_release(u->memchunk.memblock);
                 pa_log("memblock released");
 
@@ -690,6 +690,186 @@ finish:
     pa_log_debug("Thread shutting down");
 }
 
+static void a2dp_thread_func(void *userdata) {
+    struct userdata *u = userdata;
+    int write_type = 0;
+
+    pa_assert(u);
+
+    pa_log/*_debug*/("A2DP 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;
+        struct pollfd *pollfd;
+
+        if (PA_SINK_IS_OPENED(u->sink->thread_info.state)) {
+            if (u->sink->thread_info.rewind_requested) {
+                pa_log("rewind_requested");
+                pa_sink_process_rewind(u->sink, 0);
+                pa_log("rewind_finished");
+            }
+        }
+
+        pollfd = pa_rtpoll_item_get_pollfd(u->rtpoll_item, NULL);
+
+        /* Render some data and write it to the fifo */
+        if (PA_SINK_IS_OPENED(u->sink->thread_info.state) && pollfd->revents) {
+            pa_usec_t usec;
+            int64_t n;
+            pa_log("Render some data and write it to the fifo");
+
+            for (;;) {
+                ssize_t l;
+                void *p;
+                struct bt_a2dp *a2dp = &u->a2dp;
+                int frame_size, encoded, written;
+
+                u->memchunk.memblock = pa_memblock_new(u->mempool, u->block_size);
+                pa_log("memblock allocated %d", u->block_size);
+                u->memchunk.length = pa_memblock_get_length(u->memchunk.memblock);
+                pa_log("memchunk length %d", u->memchunk.length);
+                pa_sink_render_into_full(u->sink, &u->memchunk);
+                pa_log("rendered");
+
+                pa_assert(u->memchunk.length > 0);
+
+                p = pa_memblock_acquire(u->memchunk.memblock);
+                pa_log("memblock acquired");
+
+                frame_size = sbc_get_frame_length(&a2dp->sbc);
+                pa_log("frame_size: %d", frame_size);
+
+                encoded = sbc_encode(&a2dp->sbc, (uint8_t*) p, a2dp->codesize, a2dp->buffer + a2dp->count,
+                        sizeof(a2dp->buffer) - a2dp->count, &written);
+                pa_log("encoded: %d", encoded);
+                pa_log("written: %d", encoded);
+                if (encoded <= 0) {
+                    pa_log_error("SBC encoding error (%d)", encoded);
+                    goto fail;
+                }
+                pa_memblock_release(u->memchunk.memblock);
+                pa_log("memblock released");
+                pa_memblock_unref(u->memchunk.memblock);
+                pa_log("memblock unrefered");
+                pa_memchunk_reset(&u->memchunk);
+                pa_log("memchunk reseted");
+
+                a2dp->count += written;
+                a2dp->frame_count++;
+                a2dp->samples += encoded / frame_size;
+                a2dp->nsamples += encoded / frame_size;
+
+                if (a2dp->count + written >= u->link_mtu) {
+                    struct rtp_header *header = (void *) a2dp->buffer;
+                    struct rtp_payload *payload = (void *) (a2dp->buffer + sizeof(*header));
+
+                    memset(a2dp->buffer, 0, sizeof(*header) + sizeof(*payload));
+
+                    payload->frame_count = a2dp->frame_count;
+                    header->v = 2;
+                    header->pt = 1;
+                    header->sequence_number = htons(a2dp->seq_num);
+                    header->timestamp = htonl(a2dp->nsamples);
+                    header->ssrc = htonl(1);
+
+                    l = pa_write(u->stream_fd, a2dp->buffer, a2dp->count, 0);
+                    pa_log("avdtp_write %d", a2dp->count);
+
+                    if (l > 0) {
+                        /* Reset buffer of data to send */
+                        a2dp->count = sizeof(struct rtp_header) + sizeof(struct rtp_payload);
+                        a2dp->frame_count = 0;
+                        a2dp->samples = 0;
+                        a2dp->seq_num++;
+                    }
+
+                    pa_log("avdtp written %d bytes", l);
+
+                    pa_assert(l != 0);
+
+                    if (l < 0) {
+                        pa_log("l = %d < 0", l);
+                        if (errno == EINTR) {
+                            pa_log("EINTR");
+                            continue;
+                        }
+                        else if (errno == EAGAIN) {
+                            pa_log("EAGAIN");
+                            goto filled_up;
+                        }
+                        else {
+                            pa_log("Failed to write data to FIFO: %s", pa_cstrerror(errno));
+                            goto fail;
+                        }
+                    } else {
+                        pa_log("l = %d >= 0", l);
+                        u->offset += l;
+                        pollfd->revents = 0;
+                        goto filled_up;
+                    }
+                }
+            }
+
+filled_up:
+
+            pa_log("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 */
+        pa_log("let's sleep");
+        pollfd->events = PA_SINK_IS_OPENED(u->sink->thread_info.state) ? POLLOUT : 0;
+
+        if ((ret = pa_rtpoll_run(u->rtpoll, TRUE)) < 0) {
+            pa_log("ret < 0");
+            goto fail;
+        }
+        pa_log("waking up");
+
+        if (ret == 0) {
+            pa_log("ret == 0");
+            goto finish;
+        }
+
+        pollfd = pa_rtpoll_item_get_pollfd(u->rtpoll_item, NULL);
+        if (pollfd->revents & ~POLLOUT) {
+            pa_log("FIFO shutdown.");
+            goto fail;
+        }
+    }
+
+fail:
+    /* If this was no regular exit from the loop we have to continue processing messages until we receive PA_MESSAGE_SHUTDOWN */
+    pa_log("fail");
+    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("A2DP Thread shutting down");
+}
+
 int pa__init(pa_module* m) {
     int e;
     const char *rate, *channels;
@@ -794,9 +974,17 @@ int pa__init(pa_module* m) {
     pollfd->events = pollfd->revents = 0;
 
     /* start rt thread */
-    if (!(u->thread = pa_thread_new(thread_func, u))) {
-        pa_log_error("failed to create thread");
-        goto fail;
+    if (u->transport == BT_CAPABILITIES_TRANSPORT_A2DP) {
+        if (!(u->thread = pa_thread_new(a2dp_thread_func, u))) {
+            pa_log_error("failed to create thread");
+            goto fail;
+        }
+    }
+    else {
+        if (!(u->thread = pa_thread_new(thread_func, u))) {
+            pa_log_error("failed to create thread");
+            goto fail;
+        }
     }
     pa_sink_put(u->sink);
 

commit e570767896371336e76813231f7dc939a08db157
Author: João Paulo Rechi Vita <joao.vita at gmail.com>
Date:   Tue Aug 19 16:06:21 2008 -0300

    Refactor a2dp thread execution flow and improve time estimation

diff --git a/src/modules/module-bt-device.c b/src/modules/module-bt-device.c
index 4e1b051..b5eccb3 100644
--- a/src/modules/module-bt-device.c
+++ b/src/modules/module-bt-device.c
@@ -30,10 +30,11 @@
 #include <pulse/xmalloc.h>
 #include <pulse/timeval.h>
 #include <pulse/sample.h>
-#include <pulsecore/core-util.h>
-#include <pulsecore/core-error.h>
 #include <pulsecore/module.h>
 #include <pulsecore/modargs.h>
+#include <pulsecore/core-util.h>
+#include <pulsecore/core-error.h>
+#include <pulsecore/socket-util.h>
 #include <pulsecore/thread.h>
 #include <pulsecore/thread-mq.h>
 #include <pulsecore/rtpoll.h>
@@ -505,20 +506,20 @@ static int bt_getstreamfd(struct userdata *u) {
         return -errno;
     }
 
-//    if (u->transport == BT_CAPABILITIES_TRANSPORT_A2DP) {
-//        if (setsockopt(u->stream_fd, SOL_SOCKET, SO_SNDTIMEO, &t, sizeof(t)) < 0) {
-//            pa_log_error("failed to set socket options for A2DP: %s (%d)",pa_cstrerror(errno), errno);
-//            return -errno;
-//        }
-//    }
-//    else {
-//        if (setsockopt(u->stream_fd, SOL_SCO, SCO_TXBUFS, &period_count, sizeof(period_count)) == 0)
-//            return 0;
-//        if (setsockopt(u->stream_fd, SOL_SCO, SO_SNDBUF, &period_count, sizeof(period_count)) == 0)
-//            return 0;
-//        /* FIXME : handle error codes */
-//    }
+    if (u->transport == BT_CAPABILITIES_TRANSPORT_A2DP) {
+        if (pa_socket_set_sndbuf(u->stream_fd, 10*u->link_mtu) < 0) {
+            pa_log_error("failed to set socket options for A2DP: %s (%d)",pa_cstrerror(errno), errno);
+            return -errno;
+        }
+    }
+
+//   if (setsockopt(u->stream_fd, SOL_SCO, SCO_TXBUFS, &period_count, sizeof(period_count)) == 0)
+//       return 0;
+//   if (setsockopt(u->stream_fd, SOL_SCO, SO_SNDBUF, &period_count, sizeof(period_count)) == 0)
+//       return 0;
+//   /* FIXME : handle error codes */
     pa_make_fd_nonblock(u->stream_fd);
+//    pa_make_socket_low_delay(u->stream_fd);
 
     return 0;
 }
@@ -692,11 +693,10 @@ finish:
 
 static void a2dp_thread_func(void *userdata) {
     struct userdata *u = userdata;
-    int write_type = 0;
 
     pa_assert(u);
 
-    pa_log/*_debug*/("A2DP Thread starting up");
+    pa_log_debug("A2DP Thread starting up");
 
     pa_thread_mq_install(&u->thread_mq);
     pa_rtpoll_install(u->rtpoll);
@@ -709,127 +709,107 @@ static void a2dp_thread_func(void *userdata) {
 
         if (PA_SINK_IS_OPENED(u->sink->thread_info.state)) {
             if (u->sink->thread_info.rewind_requested) {
-                pa_log("rewind_requested");
                 pa_sink_process_rewind(u->sink, 0);
-                pa_log("rewind_finished");
             }
         }
 
         pollfd = pa_rtpoll_item_get_pollfd(u->rtpoll_item, NULL);
 
-        /* Render some data and write it to the fifo */
         if (PA_SINK_IS_OPENED(u->sink->thread_info.state) && pollfd->revents) {
             pa_usec_t usec;
             int64_t n;
-            pa_log("Render some data and write it to the fifo");
-
-            for (;;) {
-                ssize_t l;
+            ssize_t l;
+            int write_type = 0, written;
+            struct bt_a2dp *a2dp = &u->a2dp;
+            struct rtp_header *header = (void *) a2dp->buffer;
+            struct rtp_payload *payload = (void *) (a2dp->buffer + sizeof(*header));
+
+            do {
+                /* Render some data */
                 void *p;
-                struct bt_a2dp *a2dp = &u->a2dp;
-                int frame_size, encoded, written;
+                int frame_size, encoded;
 
                 u->memchunk.memblock = pa_memblock_new(u->mempool, u->block_size);
-                pa_log("memblock allocated %d", u->block_size);
+                pa_log_debug("memblock asked size%d", u->block_size);
                 u->memchunk.length = pa_memblock_get_length(u->memchunk.memblock);
-                pa_log("memchunk length %d", u->memchunk.length);
+                pa_log_debug("memchunk length %d", u->memchunk.length);
                 pa_sink_render_into_full(u->sink, &u->memchunk);
-                pa_log("rendered");
+                pa_log_debug("rendered");
 
                 pa_assert(u->memchunk.length > 0);
 
                 p = pa_memblock_acquire(u->memchunk.memblock);
-                pa_log("memblock acquired");
-
                 frame_size = sbc_get_frame_length(&a2dp->sbc);
-                pa_log("frame_size: %d", frame_size);
+                pa_log_debug("frame_size: %d", frame_size);
 
                 encoded = sbc_encode(&a2dp->sbc, (uint8_t*) p, a2dp->codesize, a2dp->buffer + a2dp->count,
                         sizeof(a2dp->buffer) - a2dp->count, &written);
-                pa_log("encoded: %d", encoded);
-                pa_log("written: %d", encoded);
+                pa_log_debug("encoded: %d", encoded);
+                pa_log_debug("written: %d", written);
                 if (encoded <= 0) {
                     pa_log_error("SBC encoding error (%d)", encoded);
                     goto fail;
                 }
                 pa_memblock_release(u->memchunk.memblock);
-                pa_log("memblock released");
                 pa_memblock_unref(u->memchunk.memblock);
-                pa_log("memblock unrefered");
                 pa_memchunk_reset(&u->memchunk);
-                pa_log("memchunk reseted");
+                pa_log_debug("memchunk reseted");
 
                 a2dp->count += written;
                 a2dp->frame_count++;
                 a2dp->samples += encoded / frame_size;
                 a2dp->nsamples += encoded / frame_size;
 
-                if (a2dp->count + written >= u->link_mtu) {
-                    struct rtp_header *header = (void *) a2dp->buffer;
-                    struct rtp_payload *payload = (void *) (a2dp->buffer + sizeof(*header));
-
-                    memset(a2dp->buffer, 0, sizeof(*header) + sizeof(*payload));
+            } while (a2dp->count + written <= u->link_mtu);
 
-                    payload->frame_count = a2dp->frame_count;
-                    header->v = 2;
-                    header->pt = 1;
-                    header->sequence_number = htons(a2dp->seq_num);
-                    header->timestamp = htonl(a2dp->nsamples);
-                    header->ssrc = htonl(1);
+            /* write it to the fifo */
+            memset(a2dp->buffer, 0, sizeof(*header) + sizeof(*payload));
+            payload->frame_count = a2dp->frame_count;
+            header->v = 2;
+            header->pt = 1;
+            header->sequence_number = htons(a2dp->seq_num);
+            header->timestamp = htonl(a2dp->nsamples);
+            header->ssrc = htonl(1);
 
-                    l = pa_write(u->stream_fd, a2dp->buffer, a2dp->count, 0);
-                    pa_log("avdtp_write %d", a2dp->count);
+avdtp_write:
+            l = pa_write(u->stream_fd, a2dp->buffer, a2dp->count, write_type);
+            pa_log_debug("avdtp_write: requested %d bytes; written %d bytes", a2dp->count, l);
 
-                    if (l > 0) {
-                        /* Reset buffer of data to send */
-                        a2dp->count = sizeof(struct rtp_header) + sizeof(struct rtp_payload);
-                        a2dp->frame_count = 0;
-                        a2dp->samples = 0;
-                        a2dp->seq_num++;
-                    }
+            pa_assert(l != 0);
 
-                    pa_log("avdtp written %d bytes", l);
-
-                    pa_assert(l != 0);
-
-                    if (l < 0) {
-                        pa_log("l = %d < 0", l);
-                        if (errno == EINTR) {
-                            pa_log("EINTR");
-                            continue;
-                        }
-                        else if (errno == EAGAIN) {
-                            pa_log("EAGAIN");
-                            goto filled_up;
-                        }
-                        else {
-                            pa_log("Failed to write data to FIFO: %s", pa_cstrerror(errno));
-                            goto fail;
-                        }
-                    } else {
-                        pa_log("l = %d >= 0", l);
-                        u->offset += l;
-                        pollfd->revents = 0;
-                        goto filled_up;
-                    }
+            if (l < 0) {
+                if (errno == EINTR) {
+                    pa_log_debug("EINTR");
+                    continue;
+                }
+                else if (errno == EAGAIN) {
+                    pa_log_debug("EAGAIN");
+                    goto avdtp_write;
+                }
+                else {
+                    pa_log_error("Failed to write data to FIFO: %s", pa_cstrerror(errno));
+                    goto fail;
                 }
             }
 
-filled_up:
+            u->offset += a2dp->codesize*a2dp->frame_count;
+            pollfd->revents = 0;
 
-            pa_log("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;
+            /* Reset buffer of data to send */
+            a2dp->count = sizeof(struct rtp_header) + sizeof(struct rtp_payload);
+            a2dp->frame_count = 0;
+            a2dp->samples = 0;
+            a2dp->seq_num++;
 
+            /* feed the time smoother */
+            n = u->offset;
 #ifdef SIOCOUTQ
             {
-                int l;
-                if (ioctl(u->fd, SIOCOUTQ, &l) >= 0 && l > 0)
-                    n -= l;
+                int ll;
+                if (ioctl(u->fd, SIOCOUTQ, &ll) >= 0 && ll > 0)
+                    n -= ll;
             }
 #endif
-
             usec = pa_bytes_to_usec(n, &u->sink->sample_spec);
             if (usec > u->latency)
                 usec -= u->latency;
@@ -839,35 +819,34 @@ filled_up:
         }
 
         /* Hmm, nothing to do. Let's sleep */
-        pa_log("let's sleep");
+        pa_log_debug("A2DP thread going to sleep");
         pollfd->events = PA_SINK_IS_OPENED(u->sink->thread_info.state) ? POLLOUT : 0;
-
         if ((ret = pa_rtpoll_run(u->rtpoll, TRUE)) < 0) {
             pa_log("ret < 0");
             goto fail;
         }
-        pa_log("waking up");
+        pa_log_debug("A2DP thread waking up");
 
         if (ret == 0) {
-            pa_log("ret == 0");
+            pa_log_warn("ret == 0");
             goto finish;
         }
 
         pollfd = pa_rtpoll_item_get_pollfd(u->rtpoll_item, NULL);
         if (pollfd->revents & ~POLLOUT) {
-            pa_log("FIFO shutdown.");
+            pa_log_error("FIFO shutdown.");
             goto fail;
         }
     }
 
 fail:
     /* If this was no regular exit from the loop we have to continue processing messages until we receive PA_MESSAGE_SHUTDOWN */
-    pa_log("fail");
+    pa_log_debug("A2DP thread failed");
     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("A2DP Thread shutting down");
+    pa_log_debug("A2DP thread shutting down");
 }
 
 int pa__init(pa_module* m) {

commit 61013fbb3d4c41eb22576da18c7d9ed00c77bf47
Author: João Paulo Rechi Vita <joao.vita at gmail.com>
Date:   Tue Aug 19 17:35:43 2008 -0300

    Fix some debug messages and other cosmetic changes

diff --git a/src/modules/module-bt-device.c b/src/modules/module-bt-device.c
index b5eccb3..374171e 100644
--- a/src/modules/module-bt-device.c
+++ b/src/modules/module-bt-device.c
@@ -123,7 +123,7 @@ static const char* const valid_modargs[] = {
 
 static int bt_audioservice_send(int sk, const bt_audio_msg_header_t *msg) {
     int e;
-    pa_log/*_debug*/("sending %s", bt_audio_strmsg(msg->msg_type));
+    pa_log_debug("sending %s", bt_audio_strmsg(msg->msg_type));
     if (send(sk, msg, BT_AUDIO_IPC_PACKET_SIZE, 0) > 0)
         e = 0;
     else {
@@ -137,11 +137,11 @@ static int bt_audioservice_recv(int sk, bt_audio_msg_header_t *inmsg) {
     int e;
     const char *type;
 
-    pa_log/*_debug*/("trying to receive msg from audio service...");
+    pa_log_debug("trying to receive msg from audio service...");
     if (recv(sk, inmsg, BT_AUDIO_IPC_PACKET_SIZE, 0) > 0) {
         type = bt_audio_strmsg(inmsg->msg_type);
         if (type) {
-            pa_log/*_debug*/("Received %s", type);
+            pa_log_debug("Received %s", type);
             e = 0;
         }
         else {
@@ -453,7 +453,7 @@ static int bt_setconf(struct userdata *u) {
     if (u->transport == BT_CAPABILITIES_TRANSPORT_A2DP) {
         bt_a2dp_setup(&u->a2dp);
         u->block_size = u->a2dp.codesize;
-        pa_log/*debug*/("\tallocation=%u\n\tsubbands=%u\n\tblocks=%u\n\tbitpool=%u\n",
+        pa_log_info("sbc parameters:\n\tallocation=%u\n\tsubbands=%u\n\tblocks=%u\n\tbitpool=%u\n",
                 u->a2dp.sbc.allocation, u->a2dp.sbc.subbands, u->a2dp.sbc.blocks, u->a2dp.sbc.bitpool);
     }
     else
@@ -465,7 +465,6 @@ static int bt_setconf(struct userdata *u) {
 static int bt_getstreamfd(struct userdata *u) {
     int e;
 //    uint32_t period_count = io->buffer_size / io->period_size;
-//    struct timeval t = { 0, period_count };
     char buf[BT_AUDIO_IPC_PACKET_SIZE];
     struct bt_streamstart_req *start_req = (void*) buf;
     bt_audio_rsp_msg_header_t *rsp_hdr = (void*) buf;
@@ -527,7 +526,7 @@ static int bt_getstreamfd(struct userdata *u) {
 static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offset, pa_memchunk *chunk) {
     struct userdata *u = PA_SINK(o)->userdata;
 
-    pa_log/*_debug*/("got message: %d", code);
+    pa_log_debug("got message: %d", code);
     switch (code) {
 
         case PA_SINK_MESSAGE_SET_STATE:
@@ -560,13 +559,13 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
     return pa_sink_process_msg(o, code, data, offset, chunk);
 }
 
-static void thread_func(void *userdata) {
+static void sco_thread_func(void *userdata) {
     struct userdata *u = userdata;
     int write_type = 0;
 
     pa_assert(u);
 
-    pa_log/*_debug*/("Thread starting up");
+    pa_log_debug("SCO thread starting up");
 
     pa_thread_mq_install(&u->thread_mq);
     pa_rtpoll_install(u->rtpoll);
@@ -579,70 +578,61 @@ static void thread_func(void *userdata) {
 
         if (PA_SINK_IS_OPENED(u->sink->thread_info.state)) {
             if (u->sink->thread_info.rewind_requested) {
-                pa_log("rewind_requested");
                 pa_sink_process_rewind(u->sink, 0);
-                pa_log("rewind_finished");
             }
         }
 
         pollfd = pa_rtpoll_item_get_pollfd(u->rtpoll_item, NULL);
 
-        /* Render some data and write it to the fifo */
         if (PA_SINK_IS_OPENED(u->sink->thread_info.state) && pollfd->revents) {
             pa_usec_t usec;
             int64_t n;
-            pa_log("Render some data and write it to the fifo");
 
             for (;;) {
+                /* Render some data and write it to the fifo */
                 ssize_t l;
                 void *p;
 
                 u->memchunk.memblock = pa_memblock_new(u->mempool, u->block_size);
-                pa_log("memblock allocated %d", u->block_size);
+                pa_log_debug("memblock asked size %d", u->block_size);
                 u->memchunk.length = pa_memblock_get_length(u->memchunk.memblock);
-                pa_log("memchunk length %d", u->memchunk.length);
+                pa_log_debug("memchunk length %d", u->memchunk.length);
                 pa_sink_render_into_full(u->sink, &u->memchunk);
-                pa_log("rendered");
 
                 pa_assert(u->memchunk.length > 0);
 
                 p = pa_memblock_acquire(u->memchunk.memblock);
-                pa_log("memblock acquired");
+
                 l = pa_write(u->stream_fd, (uint8_t*) p, u->memchunk.length, &write_type);
-                pa_log("memblock written %d bytes", l);
+                pa_log_debug("memblock written to socket: %d bytes", l);
                 pa_memblock_release(u->memchunk.memblock);
-                pa_log("memblock released");
+                pa_memblock_unref(u->memchunk.memblock);
+                pa_memchunk_reset(&u->memchunk);
+                pa_log("memchunk reseted");
 
                 pa_assert(l != 0);
 
                 if (l < 0) {
-                    pa_log("l = %d < 0", l);
-                    if (errno == EINTR)
+                    if (errno == EINTR) {
+                        pa_log_debug("EINTR");
                         continue;
-                    else if (errno == EAGAIN)
+                    }
+                    else if (errno == EAGAIN) {
+                        pa_log_debug("EAGAIN");
                         goto filled_up;
+                    }
                     else {
                         pa_log("Failed to write data to FIFO: %s", pa_cstrerror(errno));
                         goto fail;
                     }
                 } else {
-                    pa_log("l = %d >= 0", l);
                     u->offset += l;
-                    pa_memblock_unref(u->memchunk.memblock);
-                    pa_log("memblock unrefered");
-                    pa_memchunk_reset(&u->memchunk);
-                    pa_log("memchunk reseted");
                     pollfd->revents = 0;
                 }
             }
 
 filled_up:
-
-            pa_log("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;
@@ -650,7 +640,6 @@ filled_up:
                     n -= l;
             }
 #endif
-
             usec = pa_bytes_to_usec(n, &u->sink->sample_spec);
             if (usec > u->latency)
                 usec -= u->latency;
@@ -660,35 +649,34 @@ filled_up:
         }
 
         /* Hmm, nothing to do. Let's sleep */
-        pa_log("let's sleep");
+        pa_log_debug("SCO thread going to sleep");
         pollfd->events = PA_SINK_IS_OPENED(u->sink->thread_info.state) ? POLLOUT : 0;
-
         if ((ret = pa_rtpoll_run(u->rtpoll, TRUE)) < 0) {
             pa_log("ret < 0");
             goto fail;
         }
-        pa_log("waking up");
+        pa_log_debug("SCO thread waking up");
 
         if (ret == 0) {
-            pa_log("ret == 0");
+            pa_log_warn("ret == 0");
             goto finish;
         }
 
         pollfd = pa_rtpoll_item_get_pollfd(u->rtpoll_item, NULL);
         if (pollfd->revents & ~POLLOUT) {
-            pa_log("FIFO shutdown.");
+            pa_log_error("FIFO shutdown.");
             goto fail;
         }
     }
 
 fail:
     /* If this was no regular exit from the loop we have to continue processing messages until we receive PA_MESSAGE_SHUTDOWN */
-    pa_log("fail");
+    pa_log_debug("SCO thread failed");
     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");
+    pa_log_debug("SCO thread shutting down");
 }
 
 static void a2dp_thread_func(void *userdata) {
@@ -726,26 +714,24 @@ static void a2dp_thread_func(void *userdata) {
 
             do {
                 /* Render some data */
-                void *p;
                 int frame_size, encoded;
+                void *p;
 
                 u->memchunk.memblock = pa_memblock_new(u->mempool, u->block_size);
-                pa_log_debug("memblock asked size%d", u->block_size);
+                pa_log_debug("memblock asked size %d", u->block_size);
                 u->memchunk.length = pa_memblock_get_length(u->memchunk.memblock);
                 pa_log_debug("memchunk length %d", u->memchunk.length);
                 pa_sink_render_into_full(u->sink, &u->memchunk);
-                pa_log_debug("rendered");
 
                 pa_assert(u->memchunk.length > 0);
 
                 p = pa_memblock_acquire(u->memchunk.memblock);
                 frame_size = sbc_get_frame_length(&a2dp->sbc);
-                pa_log_debug("frame_size: %d", frame_size);
+                pa_log_debug("SBC frame_size: %d", frame_size);
 
                 encoded = sbc_encode(&a2dp->sbc, (uint8_t*) p, a2dp->codesize, a2dp->buffer + a2dp->count,
                         sizeof(a2dp->buffer) - a2dp->count, &written);
-                pa_log_debug("encoded: %d", encoded);
-                pa_log_debug("written: %d", written);
+                pa_log_debug("SBC: encoded: %d; written: %d", encoded, written);
                 if (encoded <= 0) {
                     pa_log_error("SBC encoding error (%d)", encoded);
                     goto fail;
@@ -822,7 +808,7 @@ avdtp_write:
         pa_log_debug("A2DP thread going to sleep");
         pollfd->events = PA_SINK_IS_OPENED(u->sink->thread_info.state) ? POLLOUT : 0;
         if ((ret = pa_rtpoll_run(u->rtpoll, TRUE)) < 0) {
-            pa_log("ret < 0");
+            pa_log_error("rtpoll_run < 0");
             goto fail;
         }
         pa_log_debug("A2DP thread waking up");
@@ -898,7 +884,6 @@ int pa__init(pa_module* m) {
         pa_log_error("failed to get channels from module arguments");
         goto fail;
     }
-    pa_log("Loading module-bt-device for %s (%s), profile %s", u->name, u->addr, u->profile);
 
     /* connect to the bluez audio service */
     u->audioservice_fd = bt_audio_service_open();
@@ -906,6 +891,7 @@ int pa__init(pa_module* m) {
         pa_log_error("couldn't connect to bluetooth audio service");
         goto fail;
     }
+    pa_log_debug("connected to the bluetooth audio service");
 
     /* queries device capabilities */
     e = bt_getcaps(u);
@@ -913,6 +899,7 @@ int pa__init(pa_module* m) {
         pa_log_error("failed to get device capabilities");
         goto fail;
     }
+    pa_log_debug("got device capabilities");
 
     /* configures the connection */
     e = bt_setconf(u);
@@ -920,6 +907,7 @@ int pa__init(pa_module* m) {
         pa_log_error("failed to set config");
         goto fail;
     }
+    pa_log_debug("connection to the device configured");
 
     /* gets the device socket */
     e = bt_getstreamfd(u);
@@ -927,6 +915,7 @@ int pa__init(pa_module* m) {
         pa_log_error("failed to get stream fd (%d)", e);
         goto fail;
     }
+    pa_log_debug("got the device socket");
 
     /* create sink */
     pa_sink_new_data_init(&data);
@@ -955,13 +944,13 @@ int pa__init(pa_module* m) {
     /* start rt thread */
     if (u->transport == BT_CAPABILITIES_TRANSPORT_A2DP) {
         if (!(u->thread = pa_thread_new(a2dp_thread_func, u))) {
-            pa_log_error("failed to create thread");
+            pa_log_error("failed to create A2DP thread");
             goto fail;
         }
     }
     else {
-        if (!(u->thread = pa_thread_new(thread_func, u))) {
-            pa_log_error("failed to create thread");
+        if (!(u->thread = pa_thread_new(sco_thread_func, u))) {
+            pa_log_error("failed to create SCO thread");
             goto fail;
         }
     }
@@ -978,6 +967,5 @@ fail:
 }
 
 void pa__done(pa_module *m) {
-    pa_log("Unloading module-bt-device");
 }
 

commit 708905c1dc46e301984000febfd5a0675f1e8940
Author: João Paulo Rechi Vita <joao.vita at gmail.com>
Date:   Wed Aug 20 10:52:25 2008 -0300

    pa__done for module-bt-device

diff --git a/src/modules/module-bt-device.c b/src/modules/module-bt-device.c
index 374171e..790cf0a 100644
--- a/src/modules/module-bt-device.c
+++ b/src/modules/module-bt-device.c
@@ -652,13 +652,13 @@ filled_up:
         pa_log_debug("SCO thread going to sleep");
         pollfd->events = PA_SINK_IS_OPENED(u->sink->thread_info.state) ? POLLOUT : 0;
         if ((ret = pa_rtpoll_run(u->rtpoll, TRUE)) < 0) {
-            pa_log("ret < 0");
+            pa_log("rtpoll_run < 0");
             goto fail;
         }
         pa_log_debug("SCO thread waking up");
 
         if (ret == 0) {
-            pa_log_warn("ret == 0");
+            pa_log_debug("rtpoll_run == 0");
             goto finish;
         }
 
@@ -814,7 +814,7 @@ avdtp_write:
         pa_log_debug("A2DP thread waking up");
 
         if (ret == 0) {
-            pa_log_warn("ret == 0");
+            pa_log_debug("rtpoll_run == 0");
             goto finish;
         }
 
@@ -967,5 +967,42 @@ fail:
 }
 
 void pa__done(pa_module *m) {
-}
+    struct userdata *u;
+    pa_assert(m);
+
+    if (!(u = m->userdata))
+        return;
+
+    if (u->sink)
+        pa_sink_unlink(u->sink);
+
+    if (u->thread) {
+        pa_asyncmsgq_send(u->thread_mq.inq, NULL, PA_MESSAGE_SHUTDOWN, NULL, 0, NULL);
+        pa_thread_free(u->thread);
+    }
+
+    pa_thread_mq_done(&u->thread_mq);
+
+    if (u->sink)
+        pa_sink_unref(u->sink);
 
+    if (u->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);
+
+    if (u->smoother)
+        pa_smoother_free(u->smoother);
+
+    if (u->stream_fd >= 0)
+        pa_close(u->stream_fd);
+
+    if (u->audioservice_fd >= 0)
+        pa_close(u->audioservice_fd);
+
+    pa_xfree(u);
+}

commit e752caca80df70070c34554db81e2089db8d1961
Author: João Paulo Rechi Vita <joao.vita at gmail.com>
Date:   Thu Aug 21 15:12:03 2008 -0300

    Change sbc_initialized to pa_bool_t

diff --git a/src/modules/module-bt-device.c b/src/modules/module-bt-device.c
index 790cf0a..053ef08 100644
--- a/src/modules/module-bt-device.c
+++ b/src/modules/module-bt-device.c
@@ -67,7 +67,7 @@ PA_MODULE_USAGE(
 struct bt_a2dp {
     sbc_capabilities_t sbc_capabilities;
     sbc_t sbc;                           /* Codec data */
-    int sbc_initialized;                 /* Keep track if the encoder is initialized */
+    pa_bool_t sbc_initialized;           /* Keep track if the encoder is initialized */
     int codesize;                        /* SBC codesize */
     int samples;                         /* Number of encoded samples */
     uint8_t buffer[BUFFER_SIZE];         /* Codec transfer buffer */
@@ -343,7 +343,7 @@ static void bt_a2dp_setup(struct bt_a2dp *a2dp) {
         sbc_reinit(&a2dp->sbc, 0);
     else
         sbc_init(&a2dp->sbc, 0);
-    a2dp->sbc_initialized = 1;
+    a2dp->sbc_initialized = TRUE;
 
     if (active_capabilities.frequency & BT_SBC_SAMPLING_FREQ_16000)
         a2dp->sbc.frequency = SBC_FREQ_16000;
@@ -852,7 +852,7 @@ int pa__init(pa_module* m) {
     u->transport = -1;
     u->offset = 0;
     u->latency = 0;
-    u->a2dp.sbc_initialized = 0;
+    u->a2dp.sbc_initialized = FALSE;
     u->smoother = pa_smoother_new(PA_USEC_PER_SEC, PA_USEC_PER_SEC*2, TRUE, 10);
     u->mempool = pa_mempool_new(FALSE);
     pa_memchunk_reset(&u->memchunk);

commit 0e817579ee13904e7751860a1c91291143d6e53c
Author: João Paulo Rechi Vita <joao.vita at gmail.com>
Date:   Thu Aug 21 17:06:41 2008 -0300

    Fix some memory leaking

diff --git a/src/modules/module-bt-device.c b/src/modules/module-bt-device.c
index 053ef08..5bc0f28 100644
--- a/src/modules/module-bt-device.c
+++ b/src/modules/module-bt-device.c
@@ -94,9 +94,9 @@ struct userdata {
     pa_memchunk memchunk;
     pa_mempool *mempool;
 
-    const char *name;
-    const char *addr;
-    const char *profile;
+    char *name;
+    char *addr;
+    char *profile;
     int rate;
     int channels;
     pa_sample_spec ss;
@@ -994,10 +994,20 @@ void pa__done(pa_module *m) {
 
     if (u->memchunk.memblock)
         pa_memblock_unref(u->memchunk.memblock);
+    /* TODO: free mempool */
 
     if (u->smoother)
         pa_smoother_free(u->smoother);
 
+    if (u->name)
+        pa_xfree(u->name);
+
+    if (u->addr)
+        pa_xfree(u->addr);
+
+    if (u->profile)
+        pa_xfree(u->profile);
+
     if (u->stream_fd >= 0)
         pa_close(u->stream_fd);
 

commit 027940b316e51bda5fe7a8b8d9d4bde925ffb04d
Author: João Paulo Rechi Vita <joao.vita at gmail.com>
Date:   Thu Aug 21 17:23:16 2008 -0300

    Remove u->channels and u->rates, since it's redundant info

diff --git a/src/modules/module-bt-device.c b/src/modules/module-bt-device.c
index 5bc0f28..30f8c70 100644
--- a/src/modules/module-bt-device.c
+++ b/src/modules/module-bt-device.c
@@ -97,8 +97,6 @@ struct userdata {
     char *name;
     char *addr;
     char *profile;
-    int rate;
-    int channels;
     pa_sample_spec ss;
 
     int audioservice_fd;
@@ -251,7 +249,7 @@ static int bt_a2dp_init(struct userdata *u) {
     sbc_capabilities_t *cap = &u->a2dp.sbc_capabilities;
     unsigned int max_bitpool, min_bitpool;
 
-    switch (u->rate) {
+    switch (u->ss.rate) {
         case 48000:
             cap->frequency = BT_SBC_SAMPLING_FREQ_48000;
             break;
@@ -265,14 +263,14 @@ static int bt_a2dp_init(struct userdata *u) {
             cap->frequency = BT_SBC_SAMPLING_FREQ_16000;
             break;
         default:
-            pa_log_error("Rate %d not supported", u->rate);
+            pa_log_error("Rate %d not supported", u->ss.rate);
             return -1;
     }
 
 //    if (cfg->has_channel_mode)
 //        cap->channel_mode = cfg->channel_mode;
 //    else 
-    if (u->channels == 2) {
+    if (u->ss.channels == 2) {
         if (cap->channel_mode & BT_A2DP_CHANNEL_MODE_JOINT_STEREO)
             cap->channel_mode = BT_A2DP_CHANNEL_MODE_JOINT_STEREO;
         else if (cap->channel_mode & BT_A2DP_CHANNEL_MODE_STEREO)
@@ -418,9 +416,6 @@ static int bt_setconf(struct userdata *u) {
     else
         u->ss.format = PA_SAMPLE_U8;
 
-    u->ss.rate = u->rate;
-    u->ss.channels = u->channels;
-
     memset(setconf_req, 0, BT_AUDIO_IPC_PACKET_SIZE);
     setconf_req->h.msg_type = BT_SETCONFIGURATION_REQ;
     strncpy(setconf_req->device, u->addr, 18);
@@ -837,7 +832,6 @@ finish:
 
 int pa__init(pa_module* m) {
     int e;
-    const char *rate, *channels;
     pa_modargs *ma;
     pa_sink_new_data data;
     struct pollfd *pollfd;
@@ -876,11 +870,11 @@ int pa__init(pa_module* m) {
         pa_log_error("failed to get profile from module arguments");
         goto fail;
     }
-    if (pa_modargs_get_value_u32(ma, "rate", &u->rate) < 0) {
+    if (pa_modargs_get_value_u32(ma, "rate", &u->ss.rate) < 0) {
         pa_log_error("failed to get rate from module arguments");
         goto fail;
     }
-    if (pa_modargs_get_value_u32(ma, "channels", &u->channels) < 0) {
+    if (pa_modargs_get_value_u32(ma, "channels", &u->ss.channels) < 0) {
         pa_log_error("failed to get channels from module arguments");
         goto fail;
     }

commit 27bc1ea423c30744b5e1688a190ecacb312d19aa
Author: João Paulo Rechi Vita <joao.vita at gmail.com>
Date:   Thu Aug 21 17:34:27 2008 -0300

    Remove unnecessary initialization of getcaps_req->flags

diff --git a/src/modules/module-bt-device.c b/src/modules/module-bt-device.c
index 30f8c70..ee78350 100644
--- a/src/modules/module-bt-device.c
+++ b/src/modules/module-bt-device.c
@@ -185,8 +185,7 @@ static int bt_getcaps(struct userdata *u) {
         pa_log_error("invalid profile argument: %s", u->profile);
         return -1;
     }
-    getcaps_req->flags = 0;
-    getcaps_req->flags |= BT_FLAG_AUTOCONNECT;
+    getcaps_req->flags = BT_FLAG_AUTOCONNECT;
 
     e = bt_audioservice_send(u->audioservice_fd, &getcaps_req->h);
     if (e < 0) {

commit 88a21e967760a7cc71b8b41f8d5f45bb3be21d58
Author: João Paulo Rechi Vita <joao.vita at gmail.com>
Date:   Thu Aug 21 17:36:17 2008 -0300

    Change MIN/MAX to PA_MIN/PA_MAX

diff --git a/src/modules/module-bt-device.c b/src/modules/module-bt-device.c
index ee78350..ee094e7 100644
--- a/src/modules/module-bt-device.c
+++ b/src/modules/module-bt-device.c
@@ -323,8 +323,8 @@ static int bt_a2dp_init(struct userdata *u) {
 //    if (cfg->has_bitpool)
 //        min_bitpool = max_bitpool = cfg->bitpool;
 //    else {
-    min_bitpool = MAX(MIN_BITPOOL, cap->min_bitpool);
-    max_bitpool = MIN(default_bitpool(cap->frequency, cap->channel_mode), cap->max_bitpool);
+    min_bitpool = PA_MAX(MIN_BITPOOL, cap->min_bitpool);
+    max_bitpool = PA_MIN(default_bitpool(cap->frequency, cap->channel_mode), cap->max_bitpool);
 //    }
 
     cap->min_bitpool = min_bitpool;

commit d1cc63227853238ec9a9b90ddaee05e147303def
Author: João Paulo Rechi Vita <joao.vita at gmail.com>
Date:   Thu Aug 21 21:31:43 2008 -0300

    Move render and write to the fd to a separate function

diff --git a/src/modules/module-bt-device.c b/src/modules/module-bt-device.c
index ee094e7..8bac98b 100644
--- a/src/modules/module-bt-device.c
+++ b/src/modules/module-bt-device.c
@@ -673,6 +673,92 @@ finish:
     pa_log_debug("SCO thread shutting down");
 }
 
+static int a2dp_process_render(struct userdata *u) {
+    ssize_t l;
+    int write_type = 0, written;
+    struct bt_a2dp *a2dp = &u->a2dp;
+    struct rtp_header *header = (void *) a2dp->buffer;
+    struct rtp_payload *payload = (void *) (a2dp->buffer + sizeof(*header));
+
+    pa_assert(u);
+
+    do {
+        /* Render some data */
+        int frame_size, encoded;
+        void *p;
+
+        u->memchunk.memblock = pa_memblock_new(u->mempool, u->block_size);
+        pa_log_debug("memblock asked size %d", u->block_size);
+        u->memchunk.length = pa_memblock_get_length(u->memchunk.memblock);
+        pa_log_debug("memchunk length %d", u->memchunk.length);
+        pa_sink_render_into_full(u->sink, &u->memchunk);
+
+        pa_assert(u->memchunk.length > 0);
+
+        p = pa_memblock_acquire(u->memchunk.memblock);
+        frame_size = sbc_get_frame_length(&a2dp->sbc);
+        pa_log_debug("SBC frame_size: %d", frame_size);
+
+        encoded = sbc_encode(&a2dp->sbc, (uint8_t*) p, a2dp->codesize, a2dp->buffer + a2dp->count,
+                sizeof(a2dp->buffer) - a2dp->count, &written);
+        pa_log_debug("SBC: encoded: %d; written: %d", encoded, written);
+        if (encoded <= 0) {
+            pa_log_error("SBC encoding error (%d)", encoded);
+            return -1;
+        }
+        pa_memblock_release(u->memchunk.memblock);
+        pa_memblock_unref(u->memchunk.memblock);
+        pa_memchunk_reset(&u->memchunk);
+        pa_log_debug("memchunk reseted");
+
+        a2dp->count += written;
+        a2dp->frame_count++;
+        a2dp->samples += encoded / frame_size;
+        a2dp->nsamples += encoded / frame_size;
+
+    } while (a2dp->count + written <= u->link_mtu);
+
+    /* write it to the fifo */
+    memset(a2dp->buffer, 0, sizeof(*header) + sizeof(*payload));
+    payload->frame_count = a2dp->frame_count;
+    header->v = 2;
+    header->pt = 1;
+    header->sequence_number = htons(a2dp->seq_num);
+    header->timestamp = htonl(a2dp->nsamples);
+    header->ssrc = htonl(1);
+
+avdtp_write:
+    l = pa_write(u->stream_fd, a2dp->buffer, a2dp->count, write_type);
+    pa_log_debug("avdtp_write: requested %d bytes; written %d bytes", a2dp->count, l);
+
+    pa_assert(l != 0);
+
+    if (l < 0) {
+        if (errno == EINTR) {
+            pa_log_debug("EINTR");
+            goto avdtp_write;
+        }
+        else if (errno == EAGAIN) {
+            pa_log_debug("EAGAIN");
+            goto avdtp_write;
+        }
+        else {
+            pa_log_error("Failed to write data to FIFO: %s", pa_cstrerror(errno));
+            return -1;
+        }
+    }
+
+    u->offset += a2dp->codesize*a2dp->frame_count;
+
+    /* Reset buffer of data to send */
+    a2dp->count = sizeof(struct rtp_header) + sizeof(struct rtp_payload);
+    a2dp->frame_count = 0;
+    a2dp->samples = 0;
+    a2dp->seq_num++;
+
+    return 0;
+}
+
 static void a2dp_thread_func(void *userdata) {
     struct userdata *u = userdata;
 
@@ -688,6 +774,8 @@ static void a2dp_thread_func(void *userdata) {
     for (;;) {
         int ret;
         struct pollfd *pollfd;
+        int64_t n;
+        pa_usec_t usec;
 
         if (PA_SINK_IS_OPENED(u->sink->thread_info.state)) {
             if (u->sink->thread_info.rewind_requested) {
@@ -698,89 +786,10 @@ static void a2dp_thread_func(void *userdata) {
         pollfd = pa_rtpoll_item_get_pollfd(u->rtpoll_item, NULL);
 
         if (PA_SINK_IS_OPENED(u->sink->thread_info.state) && pollfd->revents) {
-            pa_usec_t usec;
-            int64_t n;
-            ssize_t l;
-            int write_type = 0, written;
-            struct bt_a2dp *a2dp = &u->a2dp;
-            struct rtp_header *header = (void *) a2dp->buffer;
-            struct rtp_payload *payload = (void *) (a2dp->buffer + sizeof(*header));
-
-            do {
-                /* Render some data */
-                int frame_size, encoded;
-                void *p;
-
-                u->memchunk.memblock = pa_memblock_new(u->mempool, u->block_size);
-                pa_log_debug("memblock asked size %d", u->block_size);
-                u->memchunk.length = pa_memblock_get_length(u->memchunk.memblock);
-                pa_log_debug("memchunk length %d", u->memchunk.length);
-                pa_sink_render_into_full(u->sink, &u->memchunk);
-
-                pa_assert(u->memchunk.length > 0);
-
-                p = pa_memblock_acquire(u->memchunk.memblock);
-                frame_size = sbc_get_frame_length(&a2dp->sbc);
-                pa_log_debug("SBC frame_size: %d", frame_size);
-
-                encoded = sbc_encode(&a2dp->sbc, (uint8_t*) p, a2dp->codesize, a2dp->buffer + a2dp->count,
-                        sizeof(a2dp->buffer) - a2dp->count, &written);
-                pa_log_debug("SBC: encoded: %d; written: %d", encoded, written);
-                if (encoded <= 0) {
-                    pa_log_error("SBC encoding error (%d)", encoded);
-                    goto fail;
-                }
-                pa_memblock_release(u->memchunk.memblock);
-                pa_memblock_unref(u->memchunk.memblock);
-                pa_memchunk_reset(&u->memchunk);
-                pa_log_debug("memchunk reseted");
-
-                a2dp->count += written;
-                a2dp->frame_count++;
-                a2dp->samples += encoded / frame_size;
-                a2dp->nsamples += encoded / frame_size;
-
-            } while (a2dp->count + written <= u->link_mtu);
-
-            /* write it to the fifo */
-            memset(a2dp->buffer, 0, sizeof(*header) + sizeof(*payload));
-            payload->frame_count = a2dp->frame_count;
-            header->v = 2;
-            header->pt = 1;
-            header->sequence_number = htons(a2dp->seq_num);
-            header->timestamp = htonl(a2dp->nsamples);
-            header->ssrc = htonl(1);
-
-avdtp_write:
-            l = pa_write(u->stream_fd, a2dp->buffer, a2dp->count, write_type);
-            pa_log_debug("avdtp_write: requested %d bytes; written %d bytes", a2dp->count, l);
-
-            pa_assert(l != 0);
-
-            if (l < 0) {
-                if (errno == EINTR) {
-                    pa_log_debug("EINTR");
-                    continue;
-                }
-                else if (errno == EAGAIN) {
-                    pa_log_debug("EAGAIN");
-                    goto avdtp_write;
-                }
-                else {
-                    pa_log_error("Failed to write data to FIFO: %s", pa_cstrerror(errno));
-                    goto fail;
-                }
-            }
-
-            u->offset += a2dp->codesize*a2dp->frame_count;
+            if (a2dp_process_render(u) < 0)
+                goto fail;
             pollfd->revents = 0;
 
-            /* Reset buffer of data to send */
-            a2dp->count = sizeof(struct rtp_header) + sizeof(struct rtp_payload);
-            a2dp->frame_count = 0;
-            a2dp->samples = 0;
-            a2dp->seq_num++;
-
             /* feed the time smoother */
             n = u->offset;
 #ifdef SIOCOUTQ

commit dc4f79657f52b6b7baf22488246e8537add20834
Author: João Paulo Rechi Vita <joao.vita at gmail.com>
Date:   Mon Aug 25 21:56:31 2008 -0300

    Use union instead of different pointer types to the same memory area to make the code C99 compliant

diff --git a/src/modules/module-bt-device.c b/src/modules/module-bt-device.c
index 8bac98b..304feb8 100644
--- a/src/modules/module-bt-device.c
+++ b/src/modules/module-bt-device.c
@@ -169,42 +169,44 @@ static int bt_audioservice_expect(int sk, bt_audio_msg_header_t *rsp_hdr, int ex
 
 static int bt_getcaps(struct userdata *u) {
     int e;
-    char buf[BT_AUDIO_IPC_PACKET_SIZE];
-    bt_audio_rsp_msg_header_t *rsp_hdr = (void*) buf;
-    struct bt_getcapabilities_req *getcaps_req = (void*) buf;
-    struct bt_getcapabilities_rsp *getcaps_rsp = (void*) buf;
-
-    memset(getcaps_req, 0, BT_AUDIO_IPC_PACKET_SIZE);
-    getcaps_req->h.msg_type = BT_GETCAPABILITIES_REQ;
-    strncpy(getcaps_req->device, u->addr, 18);
+    union {
+        bt_audio_rsp_msg_header_t rsp_hdr;
+        struct bt_getcapabilities_req getcaps_req;
+        struct bt_getcapabilities_rsp getcaps_rsp;
+        uint8_t buf[BT_AUDIO_IPC_PACKET_SIZE];
+    } msg;
+
+    memset(msg.buf, 0, BT_AUDIO_IPC_PACKET_SIZE);
+    msg.getcaps_req.h.msg_type = BT_GETCAPABILITIES_REQ;
+    strncpy(msg.getcaps_req.device, u->addr, 18);
     if (strcasecmp(u->profile, "a2dp") == 0)
-        getcaps_req->transport = BT_CAPABILITIES_TRANSPORT_A2DP;
+        msg.getcaps_req.transport = BT_CAPABILITIES_TRANSPORT_A2DP;
     else if (strcasecmp(u->profile, "hsp") == 0)
-        getcaps_req->transport = BT_CAPABILITIES_TRANSPORT_SCO;
+        msg.getcaps_req.transport = BT_CAPABILITIES_TRANSPORT_SCO;
     else {
         pa_log_error("invalid profile argument: %s", u->profile);
         return -1;
     }
-    getcaps_req->flags = BT_FLAG_AUTOCONNECT;
+    msg.getcaps_req.flags = BT_FLAG_AUTOCONNECT;
 
-    e = bt_audioservice_send(u->audioservice_fd, &getcaps_req->h);
+    e = bt_audioservice_send(u->audioservice_fd, &msg.getcaps_req.h);
     if (e < 0) {
         pa_log_error("failed to send GETCAPABILITIES_REQ");
         return e;
     }
 
-    e = bt_audioservice_expect(u->audioservice_fd, &rsp_hdr->msg_h, BT_GETCAPABILITIES_RSP);
+    e = bt_audioservice_expect(u->audioservice_fd, &msg.rsp_hdr.msg_h, BT_GETCAPABILITIES_RSP);
     if (e < 0) {
         pa_log_error("failed to expect for GETCAPABILITIES_RSP");
         return e;
     }
-    if (rsp_hdr->posix_errno != 0) {
-        pa_log_error("BT_GETCAPABILITIES failed : %s (%d)", pa_cstrerror(rsp_hdr->posix_errno), rsp_hdr->posix_errno);
-        return -rsp_hdr->posix_errno;
+    if (msg.rsp_hdr.posix_errno != 0) {
+        pa_log_error("BT_GETCAPABILITIES failed : %s (%d)", pa_cstrerror(msg.rsp_hdr.posix_errno), msg.rsp_hdr.posix_errno);
+        return -msg.rsp_hdr.posix_errno;
     }
 
-    if ((u->transport = getcaps_rsp->transport) == BT_CAPABILITIES_TRANSPORT_A2DP)
-        u->a2dp.sbc_capabilities = getcaps_rsp->sbc_capabilities;
+    if ((u->transport = msg.getcaps_rsp.transport) == BT_CAPABILITIES_TRANSPORT_A2DP)
+        u->a2dp.sbc_capabilities = msg.getcaps_rsp.sbc_capabilities;
 
     return 0;
 }
@@ -399,10 +401,12 @@ static void bt_a2dp_setup(struct bt_a2dp *a2dp) {
 
 static int bt_setconf(struct userdata *u) {
     int e;
-    char buf[BT_AUDIO_IPC_PACKET_SIZE];
-    bt_audio_rsp_msg_header_t *rsp_hdr = (void*) buf;
-    struct bt_setconfiguration_req *setconf_req = (void*) buf;
-    struct bt_setconfiguration_rsp *setconf_rsp = (void*) buf;
+    union {
+        bt_audio_rsp_msg_header_t rsp_hdr;
+        struct bt_setconfiguration_req setconf_req;
+        struct bt_setconfiguration_rsp setconf_rsp;
+        uint8_t buf[BT_AUDIO_IPC_PACKET_SIZE];
+    } msg;
 
     if (u->transport == BT_CAPABILITIES_TRANSPORT_A2DP) {
         e = bt_a2dp_init(u);
@@ -415,33 +419,33 @@ static int bt_setconf(struct userdata *u) {
     else
         u->ss.format = PA_SAMPLE_U8;
 
-    memset(setconf_req, 0, BT_AUDIO_IPC_PACKET_SIZE);
-    setconf_req->h.msg_type = BT_SETCONFIGURATION_REQ;
-    strncpy(setconf_req->device, u->addr, 18);
-    setconf_req->transport = u->transport;
+    memset(msg.buf, 0, BT_AUDIO_IPC_PACKET_SIZE);
+    msg.setconf_req.h.msg_type = BT_SETCONFIGURATION_REQ;
+    strncpy(msg.setconf_req.device, u->addr, 18);
+    msg.setconf_req.transport = u->transport;
     if (u->transport == BT_CAPABILITIES_TRANSPORT_A2DP)
-        setconf_req->sbc_capabilities = u->a2dp.sbc_capabilities;
-    setconf_req->access_mode = BT_CAPABILITIES_ACCESS_MODE_WRITE;
+        msg.setconf_req.sbc_capabilities = u->a2dp.sbc_capabilities;
+    msg.setconf_req.access_mode = BT_CAPABILITIES_ACCESS_MODE_WRITE;
 
-    e = bt_audioservice_send(u->audioservice_fd, &setconf_req->h);
+    e = bt_audioservice_send(u->audioservice_fd, &msg.setconf_req.h);
     if (e < 0) {
         pa_log_error("failed to send BT_SETCONFIGURATION_REQ");
         return e;
     }
 
-    e = bt_audioservice_expect(u->audioservice_fd, &rsp_hdr->msg_h, BT_SETCONFIGURATION_RSP);
+    e = bt_audioservice_expect(u->audioservice_fd, &msg.rsp_hdr.msg_h, BT_SETCONFIGURATION_RSP);
     if (e < 0) {
         pa_log_error("failed to expect BT_SETCONFIGURATION_RSP");
         return e;
     }
 
-    if (rsp_hdr->posix_errno != 0) {
-        pa_log_error("BT_SETCONFIGURATION failed : %s(%d)", pa_cstrerror(rsp_hdr->posix_errno), rsp_hdr->posix_errno);
-        return -rsp_hdr->posix_errno;
+    if (msg.rsp_hdr.posix_errno != 0) {
+        pa_log_error("BT_SETCONFIGURATION failed : %s(%d)", pa_cstrerror(msg.rsp_hdr.posix_errno), msg.rsp_hdr.posix_errno);
+        return -msg.rsp_hdr.posix_errno;
     }
 
-    u->transport = setconf_rsp->transport;
-    u->link_mtu = setconf_rsp->link_mtu;
+    u->transport = msg.setconf_rsp.transport;
+    u->link_mtu = msg.setconf_rsp.link_mtu;
 
     /* setup SBC encoder now we agree on parameters */
     if (u->transport == BT_CAPABILITIES_TRANSPORT_A2DP) {
@@ -459,32 +463,34 @@ static int bt_setconf(struct userdata *u) {
 static int bt_getstreamfd(struct userdata *u) {
     int e;
 //    uint32_t period_count = io->buffer_size / io->period_size;
-    char buf[BT_AUDIO_IPC_PACKET_SIZE];
-    struct bt_streamstart_req *start_req = (void*) buf;
-    bt_audio_rsp_msg_header_t *rsp_hdr = (void*) buf;
-    struct bt_streamfd_ind *streamfd_ind = (void*) buf;
+    union {
+        bt_audio_rsp_msg_header_t rsp_hdr;
+        struct bt_streamstart_req start_req;
+        struct bt_streamfd_ind streamfd_ind;
+        uint8_t buf[BT_AUDIO_IPC_PACKET_SIZE];
+    } msg;
 
-    memset(start_req, 0, BT_AUDIO_IPC_PACKET_SIZE);
-    start_req->h.msg_type = BT_STREAMSTART_REQ;
+    memset(msg.buf, 0, BT_AUDIO_IPC_PACKET_SIZE);
+    msg.start_req.h.msg_type = BT_STREAMSTART_REQ;
 
-    e = bt_audioservice_send(u->audioservice_fd, &start_req->h);
+    e = bt_audioservice_send(u->audioservice_fd, &msg.start_req.h);
     if (e < 0) {
         pa_log_error("failed to send BT_STREAMSTART_REQ");
         return e;
     }
 
-    e = bt_audioservice_expect(u->audioservice_fd, &rsp_hdr->msg_h, BT_STREAMSTART_RSP);
+    e = bt_audioservice_expect(u->audioservice_fd, &msg.rsp_hdr.msg_h, BT_STREAMSTART_RSP);
     if (e < 0) {
         pa_log_error("failed to expect BT_STREAMSTART_RSP");
         return e;
     }
 
-    if (rsp_hdr->posix_errno != 0) {
-        pa_log_error("BT_START failed : %s(%d)", pa_cstrerror(rsp_hdr->posix_errno), rsp_hdr->posix_errno);
-        return -rsp_hdr->posix_errno;
+    if (msg.rsp_hdr.posix_errno != 0) {
+        pa_log_error("BT_START failed : %s(%d)", pa_cstrerror(msg.rsp_hdr.posix_errno), msg.rsp_hdr.posix_errno);
+        return -msg.rsp_hdr.posix_errno;
     }
 
-    e = bt_audioservice_expect(u->audioservice_fd, &streamfd_ind->h, BT_STREAMFD_IND);
+    e = bt_audioservice_expect(u->audioservice_fd, &msg.streamfd_ind.h, BT_STREAMFD_IND);
     if (e < 0) {
         pa_log_error("failed to expect BT_STREAMFD_IND");
         return e;

commit e2f3a86ac28d8c9b8621ce6f83a35508f852148c
Author: João Paulo Rechi Vita <joao.vita at gmail.com>
Date:   Mon Aug 25 22:15:25 2008 -0300

    Remove check for SIOCOUTQ and add proper includes

diff --git a/src/modules/module-bt-device.c b/src/modules/module-bt-device.c
index 304feb8..985ad7e 100644
--- a/src/modules/module-bt-device.c
+++ b/src/modules/module-bt-device.c
@@ -26,6 +26,8 @@
 #include <string.h>
 #include <errno.h>
 #include <poll.h>
+#include <sys/ioctl.h>
+#include <linux/sockios.h>
 
 #include <pulse/xmalloc.h>
 #include <pulse/timeval.h>
@@ -587,10 +589,10 @@ static void sco_thread_func(void *userdata) {
         if (PA_SINK_IS_OPENED(u->sink->thread_info.state) && pollfd->revents) {
             pa_usec_t usec;
             int64_t n;
+            ssize_t l;
 
             for (;;) {
                 /* Render some data and write it to the fifo */
-                ssize_t l;
                 void *p;
 
                 u->memchunk.memblock = pa_memblock_new(u->mempool, u->block_size);
@@ -633,13 +635,8 @@ static void sco_thread_func(void *userdata) {
 
 filled_up:
             n = u->offset;
-#ifdef SIOCOUTQ
-            {
-                int l;
-                if (ioctl(u->fd, SIOCOUTQ, &l) >= 0 && l > 0)
-                    n -= l;
-            }
-#endif
+            if (ioctl(u->stream_fd, SIOCOUTQ, &l) >= 0 && l > 0)
+                n -= l;
             usec = pa_bytes_to_usec(n, &u->sink->sample_spec);
             if (usec > u->latency)
                 usec -= u->latency;
@@ -778,7 +775,7 @@ static void a2dp_thread_func(void *userdata) {
     pa_smoother_set_time_offset(u->smoother, pa_rtclock_usec());
 
     for (;;) {
-        int ret;
+        int ret, l;
         struct pollfd *pollfd;
         int64_t n;
         pa_usec_t usec;
@@ -792,19 +789,14 @@ static void a2dp_thread_func(void *userdata) {
         pollfd = pa_rtpoll_item_get_pollfd(u->rtpoll_item, NULL);
 
         if (PA_SINK_IS_OPENED(u->sink->thread_info.state) && pollfd->revents) {
-            if (a2dp_process_render(u) < 0)
+            if (l = a2dp_process_render(u) < 0)
                 goto fail;
             pollfd->revents = 0;
 
             /* feed the time smoother */
             n = u->offset;
-#ifdef SIOCOUTQ
-            {
-                int ll;
-                if (ioctl(u->fd, SIOCOUTQ, &ll) >= 0 && ll > 0)
-                    n -= ll;
-            }
-#endif
+            if (ioctl(u->stream_fd, SIOCOUTQ, &l) >= 0 && l > 0)
+                n -= l;
             usec = pa_bytes_to_usec(n, &u->sink->sample_spec);
             if (usec > u->latency)
                 usec -= u->latency;

commit 199bdf2f45088b59fa897ff6098da40577f3022e
Author: João Paulo Rechi Vita <joao.vita at gmail.com>
Date:   Mon Aug 25 22:48:27 2008 -0300

    Add some more device properties to the sink properties list

diff --git a/src/modules/module-bt-device.c b/src/modules/module-bt-device.c
index 985ad7e..e6763f9 100644
--- a/src/modules/module-bt-device.c
+++ b/src/modules/module-bt-device.c
@@ -105,6 +105,7 @@ struct userdata {
     int stream_fd;
 
     int transport;
+    char *strtransport;
     int link_mtu;
     size_t block_size;
     pa_usec_t latency;
@@ -447,6 +448,7 @@ static int bt_setconf(struct userdata *u) {
     }
 
     u->transport = msg.setconf_rsp.transport;
+    u->strtransport = (u->transport == BT_CAPABILITIES_TRANSPORT_A2DP ? pa_xstrdup("A2DP") : pa_xstrdup("SCO"));
     u->link_mtu = msg.setconf_rsp.link_mtu;
 
     /* setup SBC encoder now we agree on parameters */
@@ -924,7 +926,14 @@ int pa__init(pa_module* m) {
     pa_sink_new_data_set_name(&data, u->name);
     pa_sink_new_data_set_sample_spec(&data, &u->ss);
     pa_proplist_sets(data.proplist, PA_PROP_DEVICE_STRING, u->name);
-    pa_proplist_setf(data.proplist, PA_PROP_DEVICE_DESCRIPTION, "Bluetooth sink '%s' (%s)", u->name, u->addr);
+    pa_proplist_setf(data.proplist, PA_PROP_DEVICE_DESCRIPTION, "Bluetooth %s '%s' (%s)", u->strtransport, u->name, u->addr);
+    pa_proplist_setf(data.proplist, "bluetooth.protocol", u->profile);
+    pa_proplist_setf(data.proplist, PA_PROP_DEVICE_API, "bluez");
+    pa_proplist_setf(data.proplist, PA_PROP_DEVICE_CLASS, "sound");
+    pa_proplist_setf(data.proplist, PA_PROP_DEVICE_CONNECTOR, "bluetooth");
+    pa_proplist_setf(data.proplist, PA_PROP_DEVICE_FORM_FACTOR, "headset"); /*FIXME*/
+    pa_proplist_setf(data.proplist, PA_PROP_DEVICE_VENDOR_PRODUCT_ID, "product_id"); /*FIXME*/
+    pa_proplist_setf(data.proplist, PA_PROP_DEVICE_SERIAL, "serial"); /*FIXME*/
     u->sink = pa_sink_new(m->core, &data, PA_SINK_HARDWARE|PA_SINK_LATENCY);
     pa_sink_new_data_done(&data);
     if (!u->sink) {

commit 8769bf455f5df4b8338e36186d078aeb13a1c59d
Author: João Paulo Rechi Vita <joao.vita at gmail.com>
Date:   Tue Aug 26 09:43:48 2008 -0300

    Merge A2DP and SCO thread functions

diff --git a/src/modules/module-bt-device.c b/src/modules/module-bt-device.c
index e6763f9..aa67d61 100644
--- a/src/modules/module-bt-device.c
+++ b/src/modules/module-bt-device.c
@@ -563,119 +563,52 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
     return pa_sink_process_msg(o, code, data, offset, chunk);
 }
 
-static void sco_thread_func(void *userdata) {
-    struct userdata *u = userdata;
+static int sco_process_render(struct userdata *u) {
+    void *p;
+    ssize_t l;
     int write_type = 0;
 
-    pa_assert(u);
+    u->memchunk.memblock = pa_memblock_new(u->mempool, u->block_size);
+    pa_log_debug("memblock asked size %d", u->block_size);
+    u->memchunk.length = pa_memblock_get_length(u->memchunk.memblock);
+    pa_log_debug("memchunk length %d", u->memchunk.length);
+    pa_sink_render_into_full(u->sink, &u->memchunk);
 
-    pa_log_debug("SCO thread starting up");
-
-    pa_thread_mq_install(&u->thread_mq);
-    pa_rtpoll_install(u->rtpoll);
+    pa_assert(u->memchunk.length > 0);
 
-    pa_smoother_set_time_offset(u->smoother, pa_rtclock_usec());
+    p = pa_memblock_acquire(u->memchunk.memblock);
 
-    for (;;) {
-        int ret;
-        struct pollfd *pollfd;
+sco_write:
+    l = pa_write(u->stream_fd, (uint8_t*) p, u->memchunk.length, &write_type);
+    pa_log_debug("memblock written to socket: %d bytes", l);
 
-        if (PA_SINK_IS_OPENED(u->sink->thread_info.state)) {
-            if (u->sink->thread_info.rewind_requested) {
-                pa_sink_process_rewind(u->sink, 0);
-            }
-        }
-
-        pollfd = pa_rtpoll_item_get_pollfd(u->rtpoll_item, NULL);
-
-        if (PA_SINK_IS_OPENED(u->sink->thread_info.state) && pollfd->revents) {
-            pa_usec_t usec;
-            int64_t n;
-            ssize_t l;
-
-            for (;;) {
-                /* Render some data and write it to the fifo */
-                void *p;
-
-                u->memchunk.memblock = pa_memblock_new(u->mempool, u->block_size);
-                pa_log_debug("memblock asked size %d", u->block_size);
-                u->memchunk.length = pa_memblock_get_length(u->memchunk.memblock);
-                pa_log_debug("memchunk length %d", u->memchunk.length);
-                pa_sink_render_into_full(u->sink, &u->memchunk);
-
-                pa_assert(u->memchunk.length > 0);
-
-                p = pa_memblock_acquire(u->memchunk.memblock);
-
-                l = pa_write(u->stream_fd, (uint8_t*) p, u->memchunk.length, &write_type);
-                pa_log_debug("memblock written to socket: %d bytes", l);
-                pa_memblock_release(u->memchunk.memblock);
-                pa_memblock_unref(u->memchunk.memblock);
-                pa_memchunk_reset(&u->memchunk);
-                pa_log("memchunk reseted");
-
-                pa_assert(l != 0);
-
-                if (l < 0) {
-                    if (errno == EINTR) {
-                        pa_log_debug("EINTR");
-                        continue;
-                    }
-                    else if (errno == EAGAIN) {
-                        pa_log_debug("EAGAIN");
-                        goto filled_up;
-                    }
-                    else {
-                        pa_log("Failed to write data to FIFO: %s", pa_cstrerror(errno));
-                        goto fail;
-                    }
-                } else {
-                    u->offset += l;
-                    pollfd->revents = 0;
-                }
-            }
-
-filled_up:
-            n = u->offset;
-            if (ioctl(u->stream_fd, SIOCOUTQ, &l) >= 0 && l > 0)
-                n -= l;
-            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);
-        }
+    pa_assert(l != 0);
 
-        /* Hmm, nothing to do. Let's sleep */
-        pa_log_debug("SCO thread going to sleep");
-        pollfd->events = PA_SINK_IS_OPENED(u->sink->thread_info.state) ? POLLOUT : 0;
-        if ((ret = pa_rtpoll_run(u->rtpoll, TRUE)) < 0) {
-            pa_log("rtpoll_run < 0");
-            goto fail;
+    if (l < 0) {
+        if (errno == EINTR) {
+            pa_log_debug("EINTR");
+            goto sco_write;
         }
-        pa_log_debug("SCO thread waking up");
-
-        if (ret == 0) {
-            pa_log_debug("rtpoll_run == 0");
-            goto finish;
+        else if (errno == EAGAIN) {
+            pa_log_debug("EAGAIN");
+            goto sco_write;
         }
-
-        pollfd = pa_rtpoll_item_get_pollfd(u->rtpoll_item, NULL);
-        if (pollfd->revents & ~POLLOUT) {
-            pa_log_error("FIFO shutdown.");
-            goto fail;
+        else {
+            pa_memblock_release(u->memchunk.memblock);
+            pa_memblock_unref(u->memchunk.memblock);
+            pa_memchunk_reset(&u->memchunk);
+            pa_log_debug("memchunk reseted");
+            pa_log_error("Failed to write data to FIFO: %s", pa_cstrerror(errno));
+            return -1;
         }
+    } else {
+        pa_memblock_release(u->memchunk.memblock);
+        pa_memblock_unref(u->memchunk.memblock);
+        pa_memchunk_reset(&u->memchunk);
+        pa_log_debug("memchunk reseted");
+        u->offset += l;
+        return 0;
     }
-
-fail:
-    /* If this was no regular exit from the loop we have to continue processing messages until we receive PA_MESSAGE_SHUTDOWN */
-    pa_log_debug("SCO thread failed");
-    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("SCO thread shutting down");
 }
 
 static int a2dp_process_render(struct userdata *u) {
@@ -764,12 +697,12 @@ avdtp_write:
     return 0;
 }
 
-static void a2dp_thread_func(void *userdata) {
+static void thread_func(void *userdata) {
     struct userdata *u = userdata;
 
     pa_assert(u);
 
-    pa_log_debug("A2DP Thread starting up");
+    pa_log_debug("IO Thread starting up");
 
     pa_thread_mq_install(&u->thread_mq);
     pa_rtpoll_install(u->rtpoll);
@@ -791,8 +724,14 @@ static void a2dp_thread_func(void *userdata) {
         pollfd = pa_rtpoll_item_get_pollfd(u->rtpoll_item, NULL);
 
         if (PA_SINK_IS_OPENED(u->sink->thread_info.state) && pollfd->revents) {
-            if (l = a2dp_process_render(u) < 0)
-                goto fail;
+            if (u->transport == BT_CAPABILITIES_TRANSPORT_A2DP) {
+                if (l = a2dp_process_render(u) < 0)
+                    goto fail;
+            }
+            else {
+                if ((l = sco_process_render(u)) < 0)
+                    goto fail;
+            }
             pollfd->revents = 0;
 
             /* feed the time smoother */
@@ -808,13 +747,13 @@ static void a2dp_thread_func(void *userdata) {
         }
 
         /* Hmm, nothing to do. Let's sleep */
-        pa_log_debug("A2DP thread going to sleep");
+        pa_log_debug("IO thread going to sleep");
         pollfd->events = PA_SINK_IS_OPENED(u->sink->thread_info.state) ? POLLOUT : 0;
         if ((ret = pa_rtpoll_run(u->rtpoll, TRUE)) < 0) {
             pa_log_error("rtpoll_run < 0");
             goto fail;
         }
-        pa_log_debug("A2DP thread waking up");
+        pa_log_debug("IO thread waking up");
 
         if (ret == 0) {
             pa_log_debug("rtpoll_run == 0");
@@ -830,12 +769,12 @@ static void a2dp_thread_func(void *userdata) {
 
 fail:
     /* If this was no regular exit from the loop we have to continue processing messages until we receive PA_MESSAGE_SHUTDOWN */
-    pa_log_debug("A2DP thread failed");
+    pa_log_debug("IO thread failed");
     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("A2DP thread shutting down");
+    pa_log_debug("IO thread shutting down");
 }
 
 int pa__init(pa_module* m) {
@@ -951,17 +890,9 @@ int pa__init(pa_module* m) {
     pollfd->events = pollfd->revents = 0;
 
     /* start rt thread */
-    if (u->transport == BT_CAPABILITIES_TRANSPORT_A2DP) {
-        if (!(u->thread = pa_thread_new(a2dp_thread_func, u))) {
-            pa_log_error("failed to create A2DP thread");
-            goto fail;
-        }
-    }
-    else {
-        if (!(u->thread = pa_thread_new(sco_thread_func, u))) {
-            pa_log_error("failed to create SCO thread");
-            goto fail;
-        }
+    if (!(u->thread = pa_thread_new(thread_func, u))) {
+        pa_log_error("failed to create IO thread");
+        goto fail;
     }
     pa_sink_put(u->sink);
 

commit 447e02721725a543d8181904889ed540a95f0425
Author: Russ Dill <russ.dill at gmail.com>
Date:   Thu Aug 28 10:38:47 2008 -0300

    Fix "file not found" error on load of module-bt-device for Ubuntu Intrepid Ibex

diff --git a/src/Makefile.am b/src/Makefile.am
index 055ece5..6e39681 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1585,7 +1585,7 @@ libbt_ipc_la_CFLAGS = $(AM_CFLAGS)
 
 module_bt_device_la_SOURCES = modules/module-bt-device.c
 module_bt_device_la_LDFLAGS = -module -avoid-version
-module_bt_device_la_LIBADD = $(AM_LIBADD) $(DBUS_LIBS) libpulsecore.la libdbus-util.la libbt-ipc.la libbt-sbc.la
+module_bt_device_la_LIBADD = $(AM_LIBADD) $(DBUS_LIBS) libpulsecore.la libdbus-util.la libbt-ipc.la libbt-sbc.la libsocket-util.la
 module_bt_device_la_CFLAGS = $(AM_CFLAGS) $(DBUS_CFLAGS)
 
 ###################################

commit 02a9273a2ec8405a6a72e462cb6204e10ebf8c1e
Author: João Paulo Rechi Vita <joao.vita at gmail.com>
Date:   Fri Aug 29 11:05:00 2008 -0300

    Free mempool

diff --git a/src/modules/module-bt-device.c b/src/modules/module-bt-device.c
index aa67d61..0f137b7 100644
--- a/src/modules/module-bt-device.c
+++ b/src/modules/module-bt-device.c
@@ -934,7 +934,9 @@ void pa__done(pa_module *m) {
 
     if (u->memchunk.memblock)
         pa_memblock_unref(u->memchunk.memblock);
-    /* TODO: free mempool */
+
+    if (u->mempool)
+        pa_mempool_free(u->mempool);
 
     if (u->smoother)
         pa_smoother_free(u->smoother);

commit 6093e325ccd620c16cb6f96ea19ab271cb94e2ad
Author: João Paulo Rechi Vita <joao.vita at gmail.com>
Date:   Fri Aug 29 11:46:02 2008 -0300

    Remove some warnings

diff --git a/src/modules/module-bt-device.c b/src/modules/module-bt-device.c
index 0f137b7..c738a99 100644
--- a/src/modules/module-bt-device.c
+++ b/src/modules/module-bt-device.c
@@ -28,6 +28,7 @@
 #include <poll.h>
 #include <sys/ioctl.h>
 #include <linux/sockios.h>
+#include <arpa/inet.h>
 
 #include <pulse/xmalloc.h>
 #include <pulse/timeval.h>
@@ -75,7 +76,7 @@ struct bt_a2dp {
     uint8_t buffer[BUFFER_SIZE];         /* Codec transfer buffer */
     int count;                           /* Codec transfer buffer counter */
 
-    int nsamples;                        /* Cumulative number of codec samples */
+    uint32_t nsamples;                   /* Cumulative number of codec samples */
     uint16_t seq_num;                    /* Cumulative packet sequence */
     int frame_count;                     /* Current frames in buffer*/
 };
@@ -666,7 +667,7 @@ static int a2dp_process_render(struct userdata *u) {
     header->ssrc = htonl(1);
 
 avdtp_write:
-    l = pa_write(u->stream_fd, a2dp->buffer, a2dp->count, write_type);
+    l = pa_write(u->stream_fd, a2dp->buffer, a2dp->count, &write_type);
     pa_log_debug("avdtp_write: requested %d bytes; written %d bytes", a2dp->count, l);
 
     pa_assert(l != 0);
@@ -712,7 +713,7 @@ static void thread_func(void *userdata) {
     for (;;) {
         int ret, l;
         struct pollfd *pollfd;
-        int64_t n;
+        uint64_t n;
         pa_usec_t usec;
 
         if (PA_SINK_IS_OPENED(u->sink->thread_info.state)) {
@@ -725,7 +726,7 @@ static void thread_func(void *userdata) {
 
         if (PA_SINK_IS_OPENED(u->sink->thread_info.state) && pollfd->revents) {
             if (u->transport == BT_CAPABILITIES_TRANSPORT_A2DP) {
-                if (l = a2dp_process_render(u) < 0)
+                if ((l = a2dp_process_render(u)) < 0)
                     goto fail;
             }
             else {
@@ -780,6 +781,7 @@ finish:
 int pa__init(pa_module* m) {
     int e;
     pa_modargs *ma;
+    uint32_t channels;
     pa_sink_new_data data;
     struct pollfd *pollfd;
     struct userdata *u;
@@ -821,10 +823,11 @@ int pa__init(pa_module* m) {
         pa_log_error("failed to get rate from module arguments");
         goto fail;
     }
-    if (pa_modargs_get_value_u32(ma, "channels", &u->ss.channels) < 0) {
+    if (pa_modargs_get_value_u32(ma, "channels", &channels) < 0) {
         pa_log_error("failed to get channels from module arguments");
         goto fail;
     }
+    u->ss.channels = (uint8_t) channels;
 
     /* connect to the bluez audio service */
     u->audioservice_fd = bt_audio_service_open();

commit 76bae38460807d2c9f877f546f2b8be2ef728378
Author: João Paulo Rechi Vita <joao.vita at gmail.com>
Date:   Fri Aug 29 11:56:12 2008 -0300

    Cleanup some code

diff --git a/src/modules/module-bt-device.c b/src/modules/module-bt-device.c
index c738a99..654130b 100644
--- a/src/modules/module-bt-device.c
+++ b/src/modules/module-bt-device.c
@@ -272,9 +272,6 @@ static int bt_a2dp_init(struct userdata *u) {
             return -1;
     }
 
-//    if (cfg->has_channel_mode)
-//        cap->channel_mode = cfg->channel_mode;
-//    else 
     if (u->ss.channels == 2) {
         if (cap->channel_mode & BT_A2DP_CHANNEL_MODE_JOINT_STEREO)
             cap->channel_mode = BT_A2DP_CHANNEL_MODE_JOINT_STEREO;
@@ -292,9 +289,6 @@ static int bt_a2dp_init(struct userdata *u) {
         return -1;
     }
 
-//    if (cfg->has_block_length)
-//        cap->block_length = cfg->block_length;
-//    else 
     if (cap->block_length & BT_A2DP_BLOCK_LENGTH_16)
         cap->block_length = BT_A2DP_BLOCK_LENGTH_16;
     else if (cap->block_length & BT_A2DP_BLOCK_LENGTH_12)
@@ -308,8 +302,6 @@ static int bt_a2dp_init(struct userdata *u) {
         return -1;
     }
 
-//    if (cfg->has_subbands)
-//        cap->subbands = cfg->subbands;
     if (cap->subbands & BT_A2DP_SUBBANDS_8)
         cap->subbands = BT_A2DP_SUBBANDS_8;
     else if (cap->subbands & BT_A2DP_SUBBANDS_4)
@@ -319,19 +311,13 @@ static int bt_a2dp_init(struct userdata *u) {
         return -1;
     }
 
-//    if (cfg->has_allocation_method)
-//        cap->allocation_method = cfg->allocation_method;
     if (cap->allocation_method & BT_A2DP_ALLOCATION_LOUDNESS)
         cap->allocation_method = BT_A2DP_ALLOCATION_LOUDNESS;
     else if (cap->allocation_method & BT_A2DP_ALLOCATION_SNR)
         cap->allocation_method = BT_A2DP_ALLOCATION_SNR;
 
-//    if (cfg->has_bitpool)
-//        min_bitpool = max_bitpool = cfg->bitpool;
-//    else {
     min_bitpool = PA_MAX(MIN_BITPOOL, cap->min_bitpool);
     max_bitpool = PA_MIN(default_bitpool(cap->frequency, cap->channel_mode), cap->max_bitpool);
-//    }
 
     cap->min_bitpool = min_bitpool;
     cap->max_bitpool = max_bitpool;

commit 78a3c72f60646ab9a44eab94b3afa4652ddeb8db
Author: João Paulo Rechi Vita <joao.vita at gmail.com>
Date:   Fri Aug 29 20:22:14 2008 -0300

    Move bluetooth discover and device modules to src/modules/bluetooth

diff --git a/src/Makefile.am b/src/Makefile.am
index 6e39681..c5af829 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -45,7 +45,7 @@ endif
 #     Compiler/linker flags       #
 ###################################
 
-AM_CFLAGS = -I$(top_srcdir)/src -I$(top_builddir)/src/modules -I$(top_builddir)/src/modules/rtp -I$(top_builddir)/src/modules/gconf
+AM_CFLAGS = -I$(top_srcdir)/src -I$(top_builddir)/src/modules -I$(top_builddir)/src/modules/rtp -I$(top_builddir)/src/modules/gconf -I$(top_builddir)/src/modules/bluetooth
 AM_CFLAGS += $(PTHREAD_CFLAGS) -D_POSIX_PTHREAD_SEMANTICS
 AM_CFLAGS += $(LTDLINCL)
 AM_CFLAGS += $(LIBSAMPLERATE_CFLAGS) $(LIBSNDFILE_CFLAGS) $(LIBSPEEX_CFLAGS)
@@ -1161,10 +1161,10 @@ endif
 if HAVE_BLUEZ
 modlibexec_LTLIBRARIES += \
 		module-bt-proximity.la \
-		module-bt-discover.la \
-		libbt-ipc.la \
-		libbt-sbc.la \
-		module-bt-device.la
+		module-bluetooth-discover.la \
+		libbluetooth-ipc.la \
+		libbluetooth-sbc.la \
+		module-bluetooth-device.la
 
 pulselibexec_PROGRAMS += \
 		bt-proximity-helper
@@ -1224,8 +1224,8 @@ SYMDEF_FILES = \
 		modules/module-suspend-on-idle-symdef.h \
 		modules/module-hal-detect-symdef.h \
 		modules/module-bt-proximity-symdef.h \
-		modules/module-bt-discover-symdef.h \
-		modules/module-bt-device-symdef.h \
+		modules/bluetooth/module-bluetooth-discover-symdef.h \
+		modules/bluetooth/module-bluetooth-device-symdef.h \
 		modules/gconf/module-gconf-symdef.h \
 		modules/module-position-event-sounds-symdef.h \
 		modules/module-console-kit-symdef.h
@@ -1237,6 +1237,7 @@ $(SYMDEF_FILES): modules/module-defs.h.m4
 	$(MKDIR_P) modules
 	$(MKDIR_P) modules/gconf
 	$(MKDIR_P) modules/rtp
+	$(MKDIR_P) modules/bluetooth
 	$(M4) -Dfname="$@" $< > $@
 
 # Simple protocol
@@ -1566,27 +1567,26 @@ bt_proximity_helper_LDADD = $(AM_LDADD) $(BLUEZ_LIBS)
 bt_proximity_helper_CFLAGS = $(AM_CFLAGS) $(BLUEZ_CFLAGS)
 bt_proximity_helper_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS)
 
-# Bluetooth discover
-module_bt_discover_la_SOURCES = modules/module-bt-discover.c
-module_bt_discover_la_LDFLAGS = -module -avoid-version
-module_bt_discover_la_LIBADD = $(AM_LIBADD) $(DBUS_LIBS) libpulsecore.la libdbus-util.la
-module_bt_discover_la_CFLAGS = $(AM_CFLAGS) $(DBUS_CFLAGS)
-
-# Bluetooth device
-libbt_sbc_la_SOURCES = modules/bt-sbc.c modules/bt-sbc.h modules/bt-sbc_tables.h modules/bt-sbc_math.h
-libbt_sbc_la_LDFLAGS = -avoid-version
-libbt_sbc_la_LIBADD = $(AM_LIBADD)
-libbt_sbc_la_CFLAGS = $(AM_CFLAGS)
-
-libbt_ipc_la_SOURCES = modules/bt-ipc.c modules/bt-ipc.h
-libbt_ipc_la_LDFLAGS = -avoid-version
-libbt_ipc_la_LIBADD = $(AM_LIBADD)
-libbt_ipc_la_CFLAGS = $(AM_CFLAGS)
-
-module_bt_device_la_SOURCES = modules/module-bt-device.c
-module_bt_device_la_LDFLAGS = -module -avoid-version
-module_bt_device_la_LIBADD = $(AM_LIBADD) $(DBUS_LIBS) libpulsecore.la libdbus-util.la libbt-ipc.la libbt-sbc.la libsocket-util.la
-module_bt_device_la_CFLAGS = $(AM_CFLAGS) $(DBUS_CFLAGS)
+# Bluetooth sink / source
+module_bluetooth_discover_la_SOURCES = modules/bluetooth/module-bluetooth-discover.c
+module_bluetooth_discover_la_LDFLAGS = -module -avoid-version
+module_bluetooth_discover_la_LIBADD = $(AM_LIBADD) $(DBUS_LIBS) libpulsecore.la libdbus-util.la
+module_bluetooth_discover_la_CFLAGS = $(AM_CFLAGS) $(DBUS_CFLAGS)
+
+libbluetooth_sbc_la_SOURCES = modules/bluetooth/sbc.c modules/bluetooth/sbc.h modules/bluetooth/sbc_tables.h modules/bluetooth/sbc_math.h
+libbluetooth_sbc_la_LDFLAGS = -avoid-version
+libbluetooth_sbc_la_LIBADD = $(AM_LIBADD)
+libbluetooth_sbc_la_CFLAGS = $(AM_CFLAGS)
+
+libbluetooth_ipc_la_SOURCES = modules/bluetooth/ipc.c modules/bluetooth/ipc.h
+libbluetooth_ipc_la_LDFLAGS = -avoid-version
+libbluetooth_ipc_la_LIBADD = $(AM_LIBADD)
+libbluetooth_ipc_la_CFLAGS = $(AM_CFLAGS)
+
+module_bluetooth_device_la_SOURCES = modules/bluetooth/module-bluetooth-device.c
+module_bluetooth_device_la_LDFLAGS = -module -avoid-version
+module_bluetooth_device_la_LIBADD = $(AM_LIBADD) $(DBUS_LIBS) libpulsecore.la libdbus-util.la libbluetooth-ipc.la libbluetooth-sbc.la libsocket-util.la
+module_bluetooth_device_la_CFLAGS = $(AM_CFLAGS) $(DBUS_CFLAGS)
 
 ###################################
 #        Some minor stuff         #
diff --git a/src/modules/bt-ipc.c b/src/modules/bluetooth/ipc.c
similarity index 99%
rename from src/modules/bt-ipc.c
rename to src/modules/bluetooth/ipc.c
index e585328..e7b712d 100644
--- a/src/modules/bt-ipc.c
+++ b/src/modules/bluetooth/ipc.c
@@ -20,7 +20,7 @@
  *
  */
 
-#include "bt-ipc.h"
+#include "ipc.h"
 
 /* This table contains the string representation for messages */
 static const char *strmsg[] = {
diff --git a/src/modules/bt-ipc.h b/src/modules/bluetooth/ipc.h
similarity index 100%
rename from src/modules/bt-ipc.h
rename to src/modules/bluetooth/ipc.h
diff --git a/src/modules/module-bt-device.c b/src/modules/bluetooth/module-bluetooth-device.c
similarity index 99%
rename from src/modules/module-bt-device.c
rename to src/modules/bluetooth/module-bluetooth-device.c
index 654130b..335a8ed 100644
--- a/src/modules/module-bt-device.c
+++ b/src/modules/bluetooth/module-bluetooth-device.c
@@ -45,10 +45,10 @@
 #include <pulsecore/rtclock.h>
 
 #include "dbus-util.h"
-#include "module-bt-device-symdef.h"
-#include "bt-ipc.h"
-#include "bt-sbc.h"
-#include "bt-rtp.h"
+#include "module-bluetooth-device-symdef.h"
+#include "ipc.h"
+#include "sbc.h"
+#include "rtp.h"
 
 #define DEFAULT_SINK_NAME "bluetooth_sink"
 #define BUFFER_SIZE 2048
diff --git a/src/modules/module-bt-discover.c b/src/modules/bluetooth/module-bluetooth-discover.c
similarity index 99%
rename from src/modules/module-bt-discover.c
rename to src/modules/bluetooth/module-bluetooth-discover.c
index 2b0d6c5..12473df 100644
--- a/src/modules/module-bt-discover.c
+++ b/src/modules/bluetooth/module-bluetooth-discover.c
@@ -34,7 +34,7 @@
 #include <pulsecore/llist.h>
 
 #include "dbus-util.h"
-#include "module-bt-discover-symdef.h"
+#include "module-bluetooth-discover-symdef.h"
 
 PA_MODULE_AUTHOR("Joao Paulo Rechi Vita");
 PA_MODULE_DESCRIPTION("Detect available bluetooth audio devices and load bluetooth audio drivers");
diff --git a/src/modules/bt-rtp.h b/src/modules/bluetooth/rtp.h
similarity index 100%
rename from src/modules/bt-rtp.h
rename to src/modules/bluetooth/rtp.h
diff --git a/src/modules/bt-sbc.c b/src/modules/bluetooth/sbc.c
similarity index 99%
rename from src/modules/bt-sbc.c
rename to src/modules/bluetooth/sbc.c
index 8e7b060..6303421 100644
--- a/src/modules/bt-sbc.c
+++ b/src/modules/bluetooth/sbc.c
@@ -41,10 +41,10 @@
 #include <stdlib.h>
 #include <sys/types.h>
 
-#include "bt-sbc_math.h"
-#include "bt-sbc_tables.h"
+#include "sbc_math.h"
+#include "sbc_tables.h"
 
-#include "bt-sbc.h"
+#include "sbc.h"
 
 #define SBC_SYNCWORD	0x9C
 
diff --git a/src/modules/bt-sbc.h b/src/modules/bluetooth/sbc.h
similarity index 100%
rename from src/modules/bt-sbc.h
rename to src/modules/bluetooth/sbc.h
diff --git a/src/modules/bt-sbc_math.h b/src/modules/bluetooth/sbc_math.h
similarity index 100%
rename from src/modules/bt-sbc_math.h
rename to src/modules/bluetooth/sbc_math.h
diff --git a/src/modules/bt-sbc_tables.h b/src/modules/bluetooth/sbc_tables.h
similarity index 100%
rename from src/modules/bt-sbc_tables.h
rename to src/modules/bluetooth/sbc_tables.h

commit 8b02c2fbc16db2a1d7dc34835bd939f984816f7e
Author: João Paulo Rechi Vita <joao.vita at gmail.com>
Date:   Sat Aug 30 17:41:00 2008 -0300

    Change all int vars that doesn't allow negative values to uint

diff --git a/src/modules/bluetooth/module-bluetooth-device.c b/src/modules/bluetooth/module-bluetooth-device.c
index 335a8ed..e76264a 100644
--- a/src/modules/bluetooth/module-bluetooth-device.c
+++ b/src/modules/bluetooth/module-bluetooth-device.c
@@ -71,14 +71,14 @@ struct bt_a2dp {
     sbc_capabilities_t sbc_capabilities;
     sbc_t sbc;                           /* Codec data */
     pa_bool_t sbc_initialized;           /* Keep track if the encoder is initialized */
-    int codesize;                        /* SBC codesize */
-    int samples;                         /* Number of encoded samples */
+    uint16_t codesize;                   /* SBC codesize */
+    uint8_t samples;                     /* Number of encoded samples */
     uint8_t buffer[BUFFER_SIZE];         /* Codec transfer buffer */
-    int count;                           /* Codec transfer buffer counter */
+    uint16_t count;                      /* Codec transfer buffer counter */
 
     uint32_t nsamples;                   /* Cumulative number of codec samples */
     uint16_t seq_num;                    /* Cumulative packet sequence */
-    int frame_count;                     /* Current frames in buffer*/
+    uint8_t frame_count;                 /* Current frames in buffer*/
 };
 
 struct userdata {
@@ -102,12 +102,12 @@ struct userdata {
     char *profile;
     pa_sample_spec ss;
 
-    int audioservice_fd;
-    int stream_fd;
+    uint8_t audioservice_fd;
+    uint8_t stream_fd;
 
-    int transport;
+    uint8_t transport;
     char *strtransport;
-    int link_mtu;
+    uint16_t link_mtu;
     size_t block_size;
     pa_usec_t latency;
 
@@ -600,7 +600,8 @@ sco_write:
 
 static int a2dp_process_render(struct userdata *u) {
     ssize_t l;
-    int write_type = 0, written;
+    uint8_t write_type = 0;
+    uint16_t written;
     struct bt_a2dp *a2dp = &u->a2dp;
     struct rtp_header *header = (void *) a2dp->buffer;
     struct rtp_payload *payload = (void *) (a2dp->buffer + sizeof(*header));
@@ -609,7 +610,8 @@ static int a2dp_process_render(struct userdata *u) {
 
     do {
         /* Render some data */
-        int frame_size, encoded;
+        uint16_t frame_size;
+        uint16_t encoded;
         void *p;
 
         u->memchunk.memblock = pa_memblock_new(u->mempool, u->block_size);
@@ -640,7 +642,6 @@ static int a2dp_process_render(struct userdata *u) {
         a2dp->frame_count++;
         a2dp->samples += encoded / frame_size;
         a2dp->nsamples += encoded / frame_size;
-
     } while (a2dp->count + written <= u->link_mtu);
 
     /* write it to the fifo */

commit 4ae124b1c92f21bc6b089863bf9c97145f44eb99
Author: João Paulo Rechi Vita <joao.vita at gmail.com>
Date:   Sun Aug 31 09:22:36 2008 -0300

    Move bluetooth proximity module to src/modules/bluetooth/

diff --git a/src/Makefile.am b/src/Makefile.am
index c5af829..4c92f91 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1160,14 +1160,14 @@ endif
 
 if HAVE_BLUEZ
 modlibexec_LTLIBRARIES += \
-		module-bt-proximity.la \
+		module-bluetooth-proximity.la \
 		module-bluetooth-discover.la \
 		libbluetooth-ipc.la \
 		libbluetooth-sbc.la \
 		module-bluetooth-device.la
 
 pulselibexec_PROGRAMS += \
-		bt-proximity-helper
+		proximity-helper
 endif
 
 # These are generated by a M4 script
@@ -1223,7 +1223,7 @@ SYMDEF_FILES = \
 		modules/module-rescue-streams-symdef.h \
 		modules/module-suspend-on-idle-symdef.h \
 		modules/module-hal-detect-symdef.h \
-		modules/module-bt-proximity-symdef.h \
+		modules/bluetooth/module-bluetooth-proximity-symdef.h \
 		modules/bluetooth/module-bluetooth-discover-symdef.h \
 		modules/bluetooth/module-bluetooth-device-symdef.h \
 		modules/gconf/module-gconf-symdef.h \
@@ -1557,15 +1557,15 @@ gconf_helper_CFLAGS = $(AM_CFLAGS) $(GCONF_CFLAGS)
 gconf_helper_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS)
 
 # Bluetooth proximity
-module_bt_proximity_la_SOURCES = modules/module-bt-proximity.c
-module_bt_proximity_la_LDFLAGS = -module -avoid-version
-module_bt_proximity_la_LIBADD = $(AM_LIBADD) $(DBUS_LIBS) libpulsecore.la libdbus-util.la
-module_bt_proximity_la_CFLAGS = $(AM_CFLAGS) $(DBUS_CFLAGS) -DPA_BT_PROXIMITY_HELPER=\"$(pulselibexecdir)/bt-proximity-helper\"
+module_bluetooth_proximity_la_SOURCES = modules/bluetooth/module-bluetooth-proximity.c
+module_bluetooth_proximity_la_LDFLAGS = -module -avoid-version
+module_bluetooth_proximity_la_LIBADD = $(AM_LIBADD) $(DBUS_LIBS) libpulsecore.la libdbus-util.la
+module_bluetooth_proximity_la_CFLAGS = $(AM_CFLAGS) $(DBUS_CFLAGS) -DPA_BT_PROXIMITY_HELPER=\"$(pulselibexecdir)/proximity-helper\"
 
-bt_proximity_helper_SOURCES = modules/bt-proximity-helper.c
-bt_proximity_helper_LDADD = $(AM_LDADD) $(BLUEZ_LIBS)
-bt_proximity_helper_CFLAGS = $(AM_CFLAGS) $(BLUEZ_CFLAGS)
-bt_proximity_helper_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS)
+proximity_helper_SOURCES = modules/bluetooth/proximity-helper.c
+proximity_helper_LDADD = $(AM_LDADD) $(BLUEZ_LIBS)
+proximity_helper_CFLAGS = $(AM_CFLAGS) $(BLUEZ_CFLAGS)
+proximity_helper_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS)
 
 # Bluetooth sink / source
 module_bluetooth_discover_la_SOURCES = modules/bluetooth/module-bluetooth-discover.c
@@ -1635,7 +1635,7 @@ daemon.conf: daemon/daemon.conf.in Makefile
 install-exec-hook:
 	chown root $(DESTDIR)$(bindir)/pulseaudio ; true
 	chmod u+s $(DESTDIR)$(bindir)/pulseaudio
-	-chmod u+s $(DESTDIR)$(pulselibexecdir)/bt-proximity-helper
+	-chmod u+s $(DESTDIR)$(pulselibexecdir)/proximity-helper
 	ln -sf pacat $(DESTDIR)$(bindir)/parec
 	rm -f $(DESTDIR)$(modlibexecdir)/*.a
 	rm -f $(DESTDIR)$(libdir)/libpulsedsp.a
diff --git a/src/modules/module-bt-proximity.c b/src/modules/bluetooth/module-bluetooth-proximity.c
similarity index 99%
rename from src/modules/module-bt-proximity.c
rename to src/modules/bluetooth/module-bluetooth-proximity.c
index f924c3c..5cca36e 100644
--- a/src/modules/module-bt-proximity.c
+++ b/src/modules/bluetooth/module-bluetooth-proximity.c
@@ -44,7 +44,7 @@
 #include <pulsecore/start-child.h>
 
 #include "dbus-util.h"
-#include "module-bt-proximity-symdef.h"
+#include "module-bluetooth-proximity-symdef.h"
 
 PA_MODULE_AUTHOR("Lennart Poettering");
 PA_MODULE_DESCRIPTION("Bluetooth Proximity Volume Control");
diff --git a/src/modules/bt-proximity-helper.c b/src/modules/bluetooth/proximity-helper.c
similarity index 100%
rename from src/modules/bt-proximity-helper.c
rename to src/modules/bluetooth/proximity-helper.c

commit db955e87ec0b68571377f4e49cc8c7b533249c92
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Sep 11 01:39:20 2008 +0300

    add trivial redirecting makefile to bt dir

diff --git a/src/modules/bluetooth/Makefile b/src/modules/bluetooth/Makefile
new file mode 120000
index 0000000..efe5a33
--- /dev/null
+++ b/src/modules/bluetooth/Makefile
@@ -0,0 +1 @@
+../../pulse/Makefile
\ No newline at end of file

commit c0a17064280742aa0754dc798dc62e4bad8f60ec
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Sep 11 01:40:18 2008 +0300

    downgrade a D-Bus log message to debug

diff --git a/src/modules/bluetooth/module-bluetooth-discover.c b/src/modules/bluetooth/module-bluetooth-discover.c
index 12473df..780135c 100644
--- a/src/modules/bluetooth/module-bluetooth-discover.c
+++ b/src/modules/bluetooth/module-bluetooth-discover.c
@@ -398,7 +398,7 @@ static DBusHandlerResult filter_cb(DBusConnection *bus, DBusMessage *msg, void *
     u = userdata;
     dbus_error_init(&err);
 
-    pa_log("dbus: interface=%s, path=%s, member=%s\n",
+    pa_log_debug("dbus: interface=%s, path=%s, member=%s\n",
             dbus_message_get_interface(msg),
             dbus_message_get_path(msg),
             dbus_message_get_member(msg));

commit 82572142001acc8af096000bec9b76279deeb55a
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Sep 11 01:40:40 2008 +0300

    enable bluetooth by default

diff --git a/src/daemon/default.pa.in b/src/daemon/default.pa.in
index 5f35e3e..0af9931 100755
--- a/src/daemon/default.pa.in
+++ b/src/daemon/default.pa.in
@@ -48,6 +48,11 @@ load-module module-hal-detect
 load-module module-detect
 .endif
 
+### Automatically load driver modules for Bluetooth hardware
+.ifexists module-bluetooth-discover at PA_SOEXT@
+load-module module-bluetooth-discover
+.endif
+
 ### Load several protocols
 .ifexists module-esound-protocol-unix at PA_SOEXT@
 load-module module-esound-protocol-unix

commit d68c2c9f4374d480a02d096430fdc94fa1eb8740
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Sep 11 01:41:08 2008 +0300

    replace Makefile stub copies by symlinks

diff --git a/src/modules/gconf/Makefile b/src/modules/gconf/Makefile
deleted file mode 100644
index 316beb7..efe5a33
--- a/src/modules/gconf/Makefile
+++ /dev/null
@@ -1,13 +0,0 @@
-# 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/modules/gconf/Makefile b/src/modules/gconf/Makefile
new file mode 120000
index 316beb7..efe5a33
--- /dev/null
+++ b/src/modules/gconf/Makefile
@@ -0,0 +1 @@
+../../pulse/Makefile
\ No newline at end of file
diff --git a/src/modules/rtp/Makefile b/src/modules/rtp/Makefile
deleted file mode 100644
index 316beb7..efe5a33
--- a/src/modules/rtp/Makefile
+++ /dev/null
@@ -1,13 +0,0 @@
-# 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/modules/rtp/Makefile b/src/modules/rtp/Makefile
new file mode 120000
index 316beb7..efe5a33
--- /dev/null
+++ b/src/modules/rtp/Makefile
@@ -0,0 +1 @@
+../../pulse/Makefile
\ No newline at end of file

commit 61887370219ea124ca9cbda3706c4d4704694a15
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Sep 12 17:39:08 2008 +0300

    make sure ~/.pulse exists before we create the runtime dir link beneath it

diff --git a/src/pulsecore/core-util.c b/src/pulsecore/core-util.c
index 3e5ea49..a9e2a70 100644
--- a/src/pulsecore/core-util.c
+++ b/src/pulsecore/core-util.c
@@ -1370,6 +1370,7 @@ static int make_random_dir_and_link(mode_t m, const char *k) {
 char *pa_get_runtime_dir(void) {
     char *d, *k = NULL, *p = NULL, *t = NULL, *mid;
     struct stat st;
+    mode_t m;
 
     /* The runtime directory shall contain dynamic data that needs NOT
      * to be kept accross reboots and is usuallly private to the user,
@@ -1378,10 +1379,9 @@ char *pa_get_runtime_dir(void) {
      * this directory, we link it to a random subdir in /tmp, if it
      * was not explicitly configured. */
 
-    if ((d = getenv("PULSE_RUNTIME_PATH"))) {
-        mode_t m;
+    m = pa_in_system_mode() ? 0755U : 0700U;
 
-        m = pa_in_system_mode() ? 0755U : 0700U;
+    if ((d = getenv("PULSE_RUNTIME_PATH"))) {
 
         if (pa_make_secure_dir(d, m, (uid_t) -1, (gid_t) -1) < 0)  {
             pa_log_error("Failed to create secure directory: %s", pa_cstrerror(errno));
@@ -1394,6 +1394,11 @@ char *pa_get_runtime_dir(void) {
     if (!(d = get_pulse_home()))
         goto fail;
 
+    if (pa_make_secure_dir(d, m, (uid_t) -1, (gid_t) -1) < 0)  {
+        pa_log_error("Failed to create secure directory: %s", pa_cstrerror(errno));
+        goto fail;
+    }
+
     if (!(mid = pa_machine_id())) {
         pa_xfree(d);
         goto fail;

commit 183f2e0bffb527757780638b70020fab15ab6ec9
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Sep 26 09:35:00 2008 -0700

    some minor fixes and cleanups in the bt code

diff --git a/src/modules/bluetooth/module-bluetooth-discover.c b/src/modules/bluetooth/module-bluetooth-discover.c
index 780135c..3e9763b 100644
--- a/src/modules/bluetooth/module-bluetooth-discover.c
+++ b/src/modules/bluetooth/module-bluetooth-discover.c
@@ -141,21 +141,21 @@ static void print_devices(struct device *device_list) {
     while (device_list_i != NULL) {
         struct uuid *uuid_list_i = device_list_i->uuid_list;
         if (strcmp(device_list_i->object_path, "/DEVICE_HEAD") != 0) {
-            pa_log("    [ %s ]", device_list_i->object_path);
-            pa_log("        Name = %s", device_list_i->name);
-            pa_log("        Paired = %d", device_list_i->paired);
-            pa_log("        Adapter = %s", device_list_i->adapter->object_path);
-            pa_log("        Alias = %s", device_list_i->alias);
-            pa_log("        Connected = %d", device_list_i->connected);
-            pa_log("        UUIDs = ");
+            pa_log_debug("    [ %s ]", device_list_i->object_path);
+            pa_log_debug("        Name = %s", device_list_i->name);
+            pa_log_debug("        Paired = %d", device_list_i->paired);
+            pa_log_debug("        Adapter = %s", device_list_i->adapter->object_path);
+            pa_log_debug("        Alias = %s", device_list_i->alias);
+            pa_log_debug("        Connected = %d", device_list_i->connected);
+            pa_log_debug("        UUIDs = ");
             while (uuid_list_i != NULL) {
                 if (strcmp(uuid_list_i->uuid, "UUID_HEAD") != 0)
                     pa_log("            %s", uuid_list_i->uuid);
                 uuid_list_i = uuid_list_i->next;
             }
-            pa_log("        Address = %s", device_list_i->address);
-            pa_log("        Class = 0x%x", device_list_i->class);
-            pa_log("        Trusted = %d", device_list_i->trusted);
+            pa_log_debug("        Address = %s", device_list_i->address);
+            pa_log_debug("        Class = 0x%x", device_list_i->class);
+            pa_log_debug("        Trusted = %d", device_list_i->trusted);
         }
         device_list_i = device_list_i->next;
     }
@@ -165,9 +165,9 @@ static void print_adapters(struct adapter *adapter_list) {
     struct adapter *adapter_list_i = adapter_list;
     while (adapter_list_i != NULL) {
         if (strcmp(adapter_list_i->object_path, "/ADAPTER_HEAD") != 0) {
-            pa_log("[ %s ]", adapter_list_i->object_path);
-            pa_log("    Mode = %s", adapter_list_i->mode);
-            pa_log("    Address = %s", adapter_list_i->address);
+            pa_log_debug("[ %s ]", adapter_list_i->object_path);
+            pa_log_debug("    Mode = %s", adapter_list_i->mode);
+            pa_log_debug("    Address = %s", adapter_list_i->address);
             print_devices(adapter_list_i->device_list);
         }
         adapter_list_i = adapter_list_i->next;
@@ -260,7 +260,7 @@ static void detect_devices(struct userdata *u) {
     struct adapter *adapter_list_i;
     struct device *device_list_i;
     const char *key, *value;
-    unsigned int uvalue;
+    int32_t ivalue;
 
     pa_assert(u);
     dbus_error_init(&e);
@@ -326,16 +326,16 @@ static void detect_devices(struct userdata *u) {
                         device_list_i->name = pa_xstrdup(value);
                     }
                     else if (strcmp(key, "Paired") == 0) {
-                        dbus_message_iter_get_basic(&variant_i, &uvalue);
-                        device_list_i->paired = uvalue;
+                        dbus_message_iter_get_basic(&variant_i, &ivalue);
+                        device_list_i->paired = ivalue;
                     }
                     else if (strcmp(key, "Alias") == 0) {
                         dbus_message_iter_get_basic(&variant_i, &value);
                         device_list_i->alias = pa_xstrdup(value);
                     }
                     else if (strcmp(key, "Connected") == 0) {
-                        dbus_message_iter_get_basic(&variant_i, &uvalue);
-                        device_list_i->connected = uvalue;
+                        dbus_message_iter_get_basic(&variant_i, &ivalue);
+                        device_list_i->connected = ivalue;
                     }
                     else if (strcmp(key, "UUIDs") == 0) {
                         DBusMessageIter uuid_i;
@@ -363,12 +363,12 @@ static void detect_devices(struct userdata *u) {
                         device_list_i->address = pa_xstrdup(value);
                     }
                     else if (strcmp(key, "Class") == 0) {
-                        dbus_message_iter_get_basic(&variant_i, &uvalue);
-                        device_list_i->class = uvalue;
+                        dbus_message_iter_get_basic(&variant_i, &ivalue);
+                        device_list_i->class = ivalue;
                     }
                     else if (strcmp(key, "Trusted") == 0) {
-                        dbus_message_iter_get_basic(&variant_i, &uvalue);
-                        device_list_i->trusted = uvalue;
+                        dbus_message_iter_get_basic(&variant_i, &ivalue);
+                        device_list_i->trusted = ivalue;
                     }
                 }
                 dbus_message_iter_next(&element_i);
@@ -465,7 +465,6 @@ void pa__done(pa_module* m) {
 
     pa_dbus_connection_unref(u->conn);
     pa_xfree(u);
-    pa_log("Unloading module-bt-discover");
     return;
 }
 
@@ -476,7 +475,6 @@ int pa__init(pa_module* m) {
     struct userdata *u;
 
     pa_assert(m);
-    pa_log("Loading module-bt-discover");
     dbus_error_init(&err);
     m->userdata = u = pa_xnew0(struct userdata, 1);
     u->module = m;
@@ -500,7 +498,7 @@ int pa__init(pa_module* m) {
     while (adapter_list_i != NULL) {
         device_list_i = adapter_list_i->device_list;
         while (device_list_i != NULL) {
-            pa_log("Loading module-bt-device for %s", device_list_i->name);
+            pa_log_debug("Loading module-bt-device for %s", device_list_i->name);
             /* TODO: call module */
             device_list_i = device_list_i->next;
         }

commit 3e16d2f40d5a9bcd3c64b291ee24c8be206f9f0a
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Sep 26 09:35:49 2008 -0700

    make pa_idxset_trivial_compare_func() do a full compare instea of just equakity check

diff --git a/src/pulsecore/idxset.c b/src/pulsecore/idxset.c
index 2de6406..24a28db 100644
--- a/src/pulsecore/idxset.c
+++ b/src/pulsecore/idxset.c
@@ -80,7 +80,7 @@ unsigned pa_idxset_trivial_hash_func(const void *p) {
 }
 
 int pa_idxset_trivial_compare_func(const void *a, const void *b) {
-    return a != b;
+    return a < b ? -1 : (a > b ? 1 : 0);
 }
 
 pa_idxset* pa_idxset_new(pa_hash_func_t hash_func, pa_compare_func_t compare_func) {

commit 3ad8c0456499248c496025ed02df81143baa783c
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Sep 26 09:49:52 2008 -0700

    add a generic priority queue implementation

diff --git a/src/.gitignore b/src/.gitignore
index 543f4e8..3b80bc1 100644
--- a/src/.gitignore
+++ b/src/.gitignore
@@ -1,3 +1,4 @@
+prioq-test
 lock-autospawn-test
 *.lo
 *.o
diff --git a/src/Makefile.am b/src/Makefile.am
index 4c92f91..14eb7f0 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -263,7 +263,8 @@ noinst_PROGRAMS = \
 		proplist-test \
 		rtstutter \
 		stripnul \
-		lock-autospawn-test
+		lock-autospawn-test \
+		prioq-test
 
 if HAVE_SIGXCPU
 noinst_PROGRAMS += \
@@ -458,6 +459,11 @@ lock_autospawn_test_LDADD = $(AM_LDADD) libpulsecore.la
 lock_autospawn_test_CFLAGS = $(AM_CFLAGS) $(LIBOIL_CFLAGS)
 lock_autospawn_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) $(LIBOIL_LIBS)
 
+prioq_test_SOURCES = tests/prioq-test.c
+prioq_test_LDADD = $(AM_LDADD) libpulsecore.la
+prioq_test_CFLAGS = $(AM_CFLAGS) $(LIBOIL_CFLAGS)
+prioq_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) $(LIBOIL_LIBS)
+
 ###################################
 #         Client library          #
 ###################################
@@ -757,6 +763,7 @@ libpulsecore_la_SOURCES += \
 		pulsecore/g711.c pulsecore/g711.h \
 		pulsecore/hashmap.c pulsecore/hashmap.h \
 		pulsecore/idxset.c pulsecore/idxset.h \
+		pulsecore/prioq.c pulsecore/prioq.h \
 		pulsecore/log.c pulsecore/log.h \
 		pulsecore/mcalign.c pulsecore/mcalign.h \
 		pulsecore/memblock.c pulsecore/memblock.h \
diff --git a/src/pulsecore/prioq.c b/src/pulsecore/prioq.c
new file mode 100644
index 0000000..18bed14
--- /dev/null
+++ b/src/pulsecore/prioq.c
@@ -0,0 +1,255 @@
+/***
+  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 <pulse/xmalloc.h>
+
+#include <pulsecore/flist.h>
+
+#include "prioq.h"
+
+struct pa_prioq_item {
+    void *value;
+    unsigned idx;
+};
+
+struct pa_prioq {
+    pa_prioq_item **items;
+    unsigned n_items;
+    unsigned n_allocated;
+    pa_compare_func_t compare_func;
+};
+
+PA_STATIC_FLIST_DECLARE(items, 0, pa_xfree);
+
+pa_prioq *pa_prioq_new(pa_compare_func_t compare_func) {
+
+    pa_prioq *q;
+
+    q = pa_xnew(pa_prioq, 1);
+    q->compare_func = compare_func;
+    q->n_items = 0;
+    q->n_allocated = 64;
+    q->items = pa_xnew(pa_prioq_item*, q->n_allocated);
+
+    return q;
+}
+
+void pa_prioq_free(pa_prioq *q, pa_free2_cb_t free_cb, void *userdata) {
+    pa_prioq_item **i, **e;
+
+    pa_assert(q);
+
+    for (i = q->items, e = q->items + q->n_items; i < e; i++) {
+
+        if (!*i)
+            continue;
+
+        if (free_cb)
+            free_cb((*i)->value, userdata);
+
+        pa_xfree(*i);
+    }
+
+    pa_xfree(q->items);
+    pa_xfree(q);
+}
+
+static void shuffle_up(pa_prioq *q, pa_prioq_item *i) {
+    pa_assert(q);
+    pa_assert(i);
+
+    j = i->idx;
+
+    while (j > 0) {
+        unsigned k;
+
+        k = (j-1)/2;
+
+        if (q->compare_func(q->items[k]->value, i->value) < 0)
+            break;
+
+        q->items[k]->idx = j;
+        q->items[j] = q->items[k];
+
+        j = k;
+    }
+
+    i->idx = j;
+    q->items[j] = i;
+
+}
+
+pa_prioq_item* pa_prioq_put(pa_prioq *q, void *p) {
+    pa_prioq_item *i;
+    unsigned j;
+
+    pa_assert(q);
+
+    if (q->n_items >= q->n_allocated) {
+        q->n_allocated = PA_MAX(q->n_items+1, q->n_allocated)*2;
+        q->items = pa_xrealloc(q->items, sizeof(pa_prioq_item*) * q->n_allocated);
+    }
+
+    if (!(i = pa_flist_pop(PA_STATIC_FLIST_GET(items))))
+        i = pa_xnew(pa_prioq_item, 1);
+
+    i->value = p;
+    i->idx = q->n_items++;
+
+    shuffle_up(q, i);
+
+    return i;
+}
+
+void* pa_prioq_peek(pa_prioq *q) {
+    pa_assert(q);
+
+    if (q->n_items <= 0)
+        return NULL;
+
+    return q->items[0]->value;
+}
+
+void* pa_prioq_pop(pa_prioq *q){
+    pa_assert(q);
+
+    if (q->n_items <= 0)
+        return NULL;
+
+    return pa_prioq_remove(q, q->items[0]);
+}
+
+static void swap(pa_prioq *q, unsigned j, unsigned k) {
+    pa_prioq_item *t;
+
+    pa_assert(q);
+    pa_assert(j < q->n_items);
+    pa_assert(k < q->n_items);
+
+    pa_assert(q->items[j]->idx == j);
+    pa_assert(q->items[k]->idx == k);
+
+    t = q->items[j];
+
+    q->items[j]->idx = k;
+    q->items[j] = q->items[k];
+
+    q->items[k]->idx = j;
+    q->items[k] = t;
+}
+
+static void shuffle_down(pa_prioq *q, unsigned idx) {
+
+    pa_assert(q);
+    pa_assert(idx < q->n_items);
+
+    for (;;) {
+        unsigned j, k, s;
+
+        k = (idx+1)*2; /* right child */
+        j = k-1;       /* left child */
+
+        if (j >= q->n_items)
+            break;
+
+        if (q->compare_func(q->items[j]->value, q->items[idx]->value) < 0)
+
+            /* So our left child is smaller than we are, let's
+             * remember this fact */
+            s = j;
+        else
+            s = idx;
+
+        if (k < q->n_items &&
+            q->compare_func(q->items[k]->value, q->items[s]->value) < 0)
+
+            /* So our right child is smaller than we are, let's
+             * remember this fact */
+            s = k;
+
+        /* s now points to the smallest of the three items */
+
+        if (s == idx)
+            /* No swap necessary, we're done */
+            break;
+
+        swap(q, idx, s);
+        idx = s;
+    }
+}
+
+void* pa_prioq_remove(pa_prioq *q, pa_prioq_item *i) {
+    void *p;
+
+    pa_assert(q);
+    pa_assert(i);
+    pa_assert(q->n_items >= 1);
+
+    p = i->value;
+
+    if (q->n_items-1 == i->idx) {
+        /* We are the last entry, so let's just remove us and good */
+        q->n_items--;
+
+    } else {
+
+        /* We are not the last entry, we need to replace ourselves
+         * with the last node and reshuffle */
+
+        q->items[i->idx] = q->items[q->n_items-1];
+        q->items[i->idx]->idx = i->idx;
+        q->n_items--;
+
+        shuffle_down(q, i->idx);
+    }
+
+    if (pa_flist_push(PA_STATIC_FLIST_GET(items), i) < 0)
+        pa_xfree(i);
+
+    return p;
+}
+
+unsigned pa_prioq_size(pa_prioq *q) {
+    pa_assert(q);
+
+    return q->n_items;
+}
+
+pa_bool_t pa_prioq_isempty(pa_prioq *q) {
+    pa_assert(q);
+
+    return q->n_items == 0;
+}
+
+void pa_prioq_reshuffle(pa_prioq *q, pa_prioq_item *i) {
+    pa_assert(q);
+    pa_assert(i);
+
+    /* This will move the entry down as far as necessary */
+    shuffle_down(q, i->idx);
+
+    /* And this will move the entry up as far as necessary */
+    shuffle_up(q, i->idx);
+}
diff --git a/src/pulsecore/prioq.h b/src/pulsecore/prioq.h
new file mode 100644
index 0000000..85a6627
--- /dev/null
+++ b/src/pulsecore/prioq.h
@@ -0,0 +1,64 @@
+#ifndef foopulsecoreprioqhfoo
+#define foopulsecoreprioqhfoo
+
+/***
+  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.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 <inttypes.h>
+
+#include <pulsecore/macro.h>
+#include <pulsecore/idxset.h>
+
+/* A heap-based priority queue. Removal and insertion is O(log
+ * n). Removal can happen a the top or at any position referenced by a
+ * pa_prioq_item.  */
+
+typedef struct pa_prioq pa_prioq;
+typedef struct pa_prioq_item pa_prioq_item;
+
+/* Instantiate a new prioq with the specified comparison functions */
+pa_prioq* pa_prioq_new(pa_compare_func_t compare_func);
+
+/* Free the prioq. When the prioq is not empty the specified function is called for every entry contained */
+void pa_prioq_free(pa_prioq *q, pa_free2_cb_t free_cb, void *userdata);
+
+/* Store a new item in the prioq. */
+pa_prioq_item* pa_prioq_put(pa_prioq *q, void* data);
+
+/* Get the item on the top of the queue, but don't remove it from the queue*/
+void* pa_prioq_peek(pa_prioq*q);
+
+/* Get the item on the top of the queue, and remove it from thq queue */
+void* pa_prioq_pop(pa_prioq*q);
+
+/* Remove an arbitrary from theq prioq, returning it's data */
+void* pa_prioq_remove(pa_prioq*q, pa_prioq_item *i);
+
+/* The priority of an item was modified. Adjustthe queue to that */
+void pa_prioq_reshuffle(pa_prioq *q, pa_prioq_item *i)
+
+/* Return the current number of items in the prioq */
+unsigned pa_prioq_size(pa_prioq*s);
+
+/* Return TRUE of the prioq is empty */
+pa_bool_t pa_prioq_isempty(pa_prioq *s);
+
+#endif
diff --git a/src/tests/prioq-test.c b/src/tests/prioq-test.c
new file mode 100644
index 0000000..120b512
--- /dev/null
+++ b/src/tests/prioq-test.c
@@ -0,0 +1,44 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <pulsecore/prioq.h>
+#include <pulsecore/macro.h>
+
+#define N 1024
+
+int main(int argc, char *argv[]) {
+    pa_prioq *q;
+    unsigned i;
+
+    srand(0);
+
+    q = pa_prioq_new(pa_idxset_trivial_compare_func);
+
+    /* Fill in 1024 */
+    for (i = 0; i < N; i++)
+        pa_prioq_put(q, PA_UINT_TO_PTR((unsigned) rand()));
+
+    /* Remove half of it again */
+    for (i = 0; i < N/2; i++){
+        unsigned u = PA_PTR_TO_UINT(pa_prioq_pop(q));
+        pa_log("%16u", u);
+    }
+
+    pa_log("Refilling");
+
+    /* Fill in another 1024 */
+    for (i = 0; i < N; i++)
+        pa_prioq_put(q, PA_UINT_TO_PTR((unsigned) rand()));
+
+
+    /* Remove everything */
+    while (!pa_prioq_isempty(q)) {
+        unsigned u = PA_PTR_TO_UINT(pa_prioq_pop(q));
+        pa_log("%16u", u);
+    }
+
+    pa_prioq_free(q, NULL, NULL);
+
+    return 0;
+}

commit 9adf7c56b8a17deed9bb980275226143f594099c
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Sep 26 09:51:25 2008 -0700

    ignore bt proximity helper

diff --git a/src/.gitignore b/src/.gitignore
index 3b80bc1..72c38cc 100644
--- a/src/.gitignore
+++ b/src/.gitignore
@@ -9,7 +9,7 @@ Makefile
 Makefile.in
 asyncmsgq-test
 asyncq-test
-bt-proximity-helper
+proximity-helper
 channelmap-test
 client.conf
 close-test

commit 87971c8707cf84e0f386b5fe5329c8aff155e629
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sat Sep 27 16:31:56 2008 +0200

    fix compilation errors in priority queue code

diff --git a/src/pulsecore/prioq.c b/src/pulsecore/prioq.c
index 18bed14..693dc51 100644
--- a/src/pulsecore/prioq.c
+++ b/src/pulsecore/prioq.c
@@ -77,6 +77,8 @@ void pa_prioq_free(pa_prioq *q, pa_free2_cb_t free_cb, void *userdata) {
 }
 
 static void shuffle_up(pa_prioq *q, pa_prioq_item *i) {
+    unsigned j;
+
     pa_assert(q);
     pa_assert(i);
 
@@ -103,7 +105,6 @@ static void shuffle_up(pa_prioq *q, pa_prioq_item *i) {
 
 pa_prioq_item* pa_prioq_put(pa_prioq *q, void *p) {
     pa_prioq_item *i;
-    unsigned j;
 
     pa_assert(q);
 
@@ -251,5 +252,5 @@ void pa_prioq_reshuffle(pa_prioq *q, pa_prioq_item *i) {
     shuffle_down(q, i->idx);
 
     /* And this will move the entry up as far as necessary */
-    shuffle_up(q, i->idx);
+    shuffle_up(q, i);
 }
diff --git a/src/pulsecore/prioq.h b/src/pulsecore/prioq.h
index 85a6627..fd3550b 100644
--- a/src/pulsecore/prioq.h
+++ b/src/pulsecore/prioq.h
@@ -53,7 +53,7 @@ void* pa_prioq_pop(pa_prioq*q);
 void* pa_prioq_remove(pa_prioq*q, pa_prioq_item *i);
 
 /* The priority of an item was modified. Adjustthe queue to that */
-void pa_prioq_reshuffle(pa_prioq *q, pa_prioq_item *i)
+void pa_prioq_reshuffle(pa_prioq *q, pa_prioq_item *i);
 
 /* Return the current number of items in the prioq */
 unsigned pa_prioq_size(pa_prioq*s);

commit 60e9744f281cde85790dd764cd4e52dc4b19f6b1
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Sep 29 21:34:18 2008 +0200

    remove a few compiler warnings in BlueZ code

diff --git a/src/modules/bluetooth/ipc.c b/src/modules/bluetooth/ipc.c
index e7b712d..9825699 100644
--- a/src/modules/bluetooth/ipc.c
+++ b/src/modules/bluetooth/ipc.c
@@ -40,7 +40,7 @@ static const char *strmsg[] = {
 	"BT_STREAMFD_IND",
 };
 
-int bt_audio_service_open()
+int bt_audio_service_open(void)
 {
 	int sk;
 	int err;
@@ -88,7 +88,7 @@ int bt_audio_service_get_data_fd(int sk)
 	msgh.msg_control = &cmsg_b;
 	msgh.msg_controllen = CMSG_LEN(sizeof(int));
 
-	ret = recvmsg(sk, &msgh, 0);
+	ret = (int) recvmsg(sk, &msgh, 0);
 	if (ret < 0) {
 		err = errno;
 		fprintf(stderr, "%s: Unable to receive fd: %s (%d)\n",
@@ -111,9 +111,8 @@ int bt_audio_service_get_data_fd(int sk)
 
 const char *bt_audio_strmsg(int type)
 {
-	if (type < 0 || type > (sizeof(strmsg) / sizeof(strmsg[0])))
+    if (type < 0 || (size_t) type > (sizeof(strmsg) / sizeof(strmsg[0])))
 		return NULL;
 
 	return strmsg[type];
 }
-
diff --git a/src/modules/bluetooth/ipc.h b/src/modules/bluetooth/ipc.h
index c900fcd..ae85e72 100644
--- a/src/modules/bluetooth/ipc.h
+++ b/src/modules/bluetooth/ipc.h
@@ -289,7 +289,7 @@ struct bt_control_ind {
 /* Function declaration */
 
 /* Opens a connection to the audio service: return a socket descriptor */
-int bt_audio_service_open();
+int bt_audio_service_open(void);
 
 /* Closes a connection to the audio service */
 int bt_audio_service_close(int sk);
diff --git a/src/modules/bluetooth/sbc.c b/src/modules/bluetooth/sbc.c
index 6303421..02a6143 100644
--- a/src/modules/bluetooth/sbc.c
+++ b/src/modules/bluetooth/sbc.c
@@ -145,7 +145,7 @@ static uint8_t sbc_crc8(const uint8_t *data, size_t len)
 
 	octet = data[i];
 	for (i = 0; i < len % 8; i++) {
-		char bit = ((octet ^ crc) & 0x80) >> 7;
+		unsigned char bit = ((octet ^ crc) & 0x80) >> 7;
 
 		crc = ((crc & 0x7f) << 1) ^ (bit ? 0x1d : 0);
 

commit 7923731e1820eddbbdfe01eab8d6ea6620e9286f
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Sep 29 21:36:42 2008 +0200

    use TRUE for pa_bool_t arguments

diff --git a/src/modules/module-alsa-sink.c b/src/modules/module-alsa-sink.c
index b8bef93..30d4d3a 100644
--- a/src/modules/module-alsa-sink.c
+++ b/src/modules/module-alsa-sink.c
@@ -1136,7 +1136,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-alsa-source.c b/src/modules/module-alsa-source.c
index cb77767..d0a22db 100644
--- a/src/modules/module-alsa-source.c
+++ b/src/modules/module-alsa-source.c
@@ -971,7 +971,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)

commit aa1974b7a022db6b3733ec8247c863ca3e9e6c5d
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Sep 29 21:40:52 2008 +0200

    Use the same module parameter names for module-bluetooth-device as for most other modules

diff --git a/src/modules/bluetooth/module-bluetooth-device.c b/src/modules/bluetooth/module-bluetooth-device.c
index e76264a..86109f7 100644
--- a/src/modules/bluetooth/module-bluetooth-device.c
+++ b/src/modules/bluetooth/module-bluetooth-device.c
@@ -63,8 +63,8 @@ PA_MODULE_DESCRIPTION("Bluetooth audio sink and source");
 PA_MODULE_VERSION(PACKAGE_VERSION);
 PA_MODULE_LOAD_ONCE(FALSE);
 PA_MODULE_USAGE(
-        "name=<name of the device> "
-        "addr=<address of the device> "
+        "sink_name=<name of the device> "
+        "address=<address of the device> "
         "profile=<a2dp|hsp>");
 
 struct bt_a2dp {
@@ -115,8 +115,8 @@ struct userdata {
 };
 
 static const char* const valid_modargs[] = {
-    "name",
-    "addr",
+    "sink_name",
+    "address",
     "profile",
     "rate",
     "channels",
@@ -789,29 +789,32 @@ int pa__init(pa_module* m) {
     u->rtpoll = pa_rtpoll_new();
     pa_thread_mq_init(&u->thread_mq, u->core->mainloop, u->rtpoll);
     u->rtpoll_item = NULL;
+    u->ss = m->core->default_sample_spec;
 
     if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
-        pa_log_error("failed to parse module arguments");
+        pa_log_error("Failed to parse module arguments");
         goto fail;
     }
-    if (!(u->name = pa_xstrdup(pa_modargs_get_value(ma, "name", DEFAULT_SINK_NAME)))) {
-        pa_log_error("failed to get device name from module arguments");
+    if (!(u->name = pa_xstrdup(pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME)))) {
+        pa_log_error("Failed to get device name from module arguments");
         goto fail;
     }
-    if (!(u->addr = pa_xstrdup(pa_modargs_get_value(ma, "addr", NULL)))) {
-        pa_log_error("failed to get device address from module arguments");
+    if (!(u->addr = pa_xstrdup(pa_modargs_get_value(ma, "address", NULL)))) {
+        pa_log_error("Failed to get device address from module arguments");
         goto fail;
     }
     if (!(u->profile = pa_xstrdup(pa_modargs_get_value(ma, "profile", NULL)))) {
-        pa_log_error("failed to get profile from module arguments");
+        pa_log_error("Failed to get profile from module arguments");
         goto fail;
     }
     if (pa_modargs_get_value_u32(ma, "rate", &u->ss.rate) < 0) {
-        pa_log_error("failed to get rate from module arguments");
+        pa_log_error("Failed to get rate from module arguments");
         goto fail;
     }
+
+    channels = u->ss.channels;
     if (pa_modargs_get_value_u32(ma, "channels", &channels) < 0) {
-        pa_log_error("failed to get channels from module arguments");
+        pa_log_error("Failed to get channels from module arguments");
         goto fail;
     }
     u->ss.channels = (uint8_t) channels;

commit a35f84a4f9844142d51490a231fe5638b936d4fc
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Sep 29 21:42:29 2008 +0200

    instead of failing when the requested sampling rate is not available find the next one that is higher

diff --git a/src/modules/bluetooth/module-bluetooth-device.c b/src/modules/bluetooth/module-bluetooth-device.c
index 86109f7..75d313c 100644
--- a/src/modules/bluetooth/module-bluetooth-device.c
+++ b/src/modules/bluetooth/module-bluetooth-device.c
@@ -252,33 +252,37 @@ static uint8_t default_bitpool(uint8_t freq, uint8_t mode) {
 
 static int bt_a2dp_init(struct userdata *u) {
     sbc_capabilities_t *cap = &u->a2dp.sbc_capabilities;
-    unsigned int max_bitpool, min_bitpool;
-
-    switch (u->ss.rate) {
-        case 48000:
-            cap->frequency = BT_SBC_SAMPLING_FREQ_48000;
-            break;
-        case 44100:
-            cap->frequency = BT_SBC_SAMPLING_FREQ_44100;
-            break;
-        case 32000:
-            cap->frequency = BT_SBC_SAMPLING_FREQ_32000;
+    uint8_t max_bitpool, min_bitpool;
+    unsigned i;
+
+    static const struct {
+        uint32_t rate;
+        uint8_t cap;
+    } freq_table[] = {
+        { 16000U, BT_SBC_SAMPLING_FREQ_16000 },
+        { 32000U, BT_SBC_SAMPLING_FREQ_32000 },
+        { 44100U, BT_SBC_SAMPLING_FREQ_44100 },
+        { 48000U, BT_SBC_SAMPLING_FREQ_48000 }
+    };
+
+    /* Find the lowest freq that is at least as high as the requested
+     * sampling rate */
+    for (i = 0; i < PA_ELEMENTSOF(freq_table); i++)
+        if (freq_table[i].rate >= u->ss.rate || i == PA_ELEMENTSOF(freq_table)-1 ) {
+            u->ss.rate = freq_table[i].rate;
+            cap->frequency = freq_table[i].cap;
             break;
-        case 16000:
-            cap->frequency = BT_SBC_SAMPLING_FREQ_16000;
-            break;
-        default:
-            pa_log_error("Rate %d not supported", u->ss.rate);
-            return -1;
-    }
+        }
 
-    if (u->ss.channels == 2) {
+    if (u->ss.channels >= 2) {
         if (cap->channel_mode & BT_A2DP_CHANNEL_MODE_JOINT_STEREO)
             cap->channel_mode = BT_A2DP_CHANNEL_MODE_JOINT_STEREO;
         else if (cap->channel_mode & BT_A2DP_CHANNEL_MODE_STEREO)
             cap->channel_mode = BT_A2DP_CHANNEL_MODE_STEREO;
         else if (cap->channel_mode & BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL)
             cap->channel_mode = BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL;
+
+        u->ss.channels = 2;
     } else {
         if (cap->channel_mode & BT_A2DP_CHANNEL_MODE_MONO)
             cap->channel_mode = BT_A2DP_CHANNEL_MODE_MONO;

commit 3f4bc0368da002b3159d4506560aeb0331f7dc17
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Sep 29 21:43:28 2008 +0200

    all kinds of minor type, memory leak, initializatio fixes

diff --git a/src/modules/bluetooth/module-bluetooth-device.c b/src/modules/bluetooth/module-bluetooth-device.c
index 75d313c..395d54f 100644
--- a/src/modules/bluetooth/module-bluetooth-device.c
+++ b/src/modules/bluetooth/module-bluetooth-device.c
@@ -53,7 +53,7 @@
 #define DEFAULT_SINK_NAME "bluetooth_sink"
 #define BUFFER_SIZE 2048
 #define MAX_BITPOOL 64
-#define MIN_BITPOOL 2
+#define MIN_BITPOOL 2U
 #define SOL_SCO 17
 #define SCO_TXBUFS 0x03
 #define SCO_RXBUFS 0x04
@@ -71,14 +71,14 @@ struct bt_a2dp {
     sbc_capabilities_t sbc_capabilities;
     sbc_t sbc;                           /* Codec data */
     pa_bool_t sbc_initialized;           /* Keep track if the encoder is initialized */
-    uint16_t codesize;                   /* SBC codesize */
-    uint8_t samples;                     /* Number of encoded samples */
+    size_t codesize;                     /* SBC codesize */
+    unsigned samples;                    /* Number of encoded samples */
     uint8_t buffer[BUFFER_SIZE];         /* Codec transfer buffer */
-    uint16_t count;                      /* Codec transfer buffer counter */
+    size_t count;                        /* Codec transfer buffer counter */
 
-    uint32_t nsamples;                   /* Cumulative number of codec samples */
+    unsigned total_samples;              /* Cumulative number of codec samples */
     uint16_t seq_num;                    /* Cumulative packet sequence */
-    uint8_t frame_count;                 /* Current frames in buffer*/
+    unsigned frame_count;                /* Current frames in buffer*/
 };
 
 struct userdata {
@@ -91,23 +91,20 @@ struct userdata {
     pa_rtpoll_item *rtpoll_item;
     pa_thread *thread;
 
-    int64_t offset;
+    uint64_t offset;
     pa_smoother *smoother;
 
-    pa_memchunk memchunk;
-    pa_mempool *mempool;
-
     char *name;
     char *addr;
     char *profile;
     pa_sample_spec ss;
 
-    uint8_t audioservice_fd;
-    uint8_t stream_fd;
+    int audioservice_fd;
+    int stream_fd;
 
     uint8_t transport;
     char *strtransport;
-    uint16_t link_mtu;
+    size_t link_mtu;
     size_t block_size;
     pa_usec_t latency;
 
@@ -188,20 +185,20 @@ static int bt_getcaps(struct userdata *u) {
     else if (strcasecmp(u->profile, "hsp") == 0)
         msg.getcaps_req.transport = BT_CAPABILITIES_TRANSPORT_SCO;
     else {
-        pa_log_error("invalid profile argument: %s", u->profile);
+        pa_log_error("Invalid profile argument: %s", u->profile);
         return -1;
     }
     msg.getcaps_req.flags = BT_FLAG_AUTOCONNECT;
 
     e = bt_audioservice_send(u->audioservice_fd, &msg.getcaps_req.h);
     if (e < 0) {
-        pa_log_error("failed to send GETCAPABILITIES_REQ");
+        pa_log_error("Failed to send GETCAPABILITIES_REQ");
         return e;
     }
 
     e = bt_audioservice_expect(u->audioservice_fd, &msg.rsp_hdr.msg_h, BT_GETCAPABILITIES_RSP);
     if (e < 0) {
-        pa_log_error("failed to expect for GETCAPABILITIES_RSP");
+        pa_log_error("Failed to expect for GETCAPABILITIES_RSP");
         return e;
     }
     if (msg.rsp_hdr.posix_errno != 0) {
@@ -320,11 +317,11 @@ static int bt_a2dp_init(struct userdata *u) {
     else if (cap->allocation_method & BT_A2DP_ALLOCATION_SNR)
         cap->allocation_method = BT_A2DP_ALLOCATION_SNR;
 
-    min_bitpool = PA_MAX(MIN_BITPOOL, cap->min_bitpool);
-    max_bitpool = PA_MIN(default_bitpool(cap->frequency, cap->channel_mode), cap->max_bitpool);
+    min_bitpool = (uint8_t) PA_MAX(MIN_BITPOOL, cap->min_bitpool);
+    max_bitpool = (uint8_t) PA_MIN(default_bitpool(cap->frequency, cap->channel_mode), cap->max_bitpool);
 
-    cap->min_bitpool = min_bitpool;
-    cap->max_bitpool = max_bitpool;
+    cap->min_bitpool = (uint8_t) min_bitpool;
+    cap->max_bitpool = (uint8_t) max_bitpool;
 
     return 0;
 }
@@ -362,7 +359,7 @@ static void bt_a2dp_setup(struct bt_a2dp *a2dp) {
     if (active_capabilities.channel_mode & BT_A2DP_CHANNEL_MODE_JOINT_STEREO)
         a2dp->sbc.mode = SBC_MODE_JOINT_STEREO;
 
-    a2dp->sbc.allocation = (active_capabilities.allocation_method == BT_A2DP_ALLOCATION_SNR ? SBC_AM_SNR : SBC_AM_LOUDNESS);
+    a2dp->sbc.allocation = (uint8_t) (active_capabilities.allocation_method == BT_A2DP_ALLOCATION_SNR ? SBC_AM_SNR : SBC_AM_LOUDNESS);
 
     switch (active_capabilities.subbands) {
         case BT_A2DP_SUBBANDS_4:
@@ -389,7 +386,7 @@ static void bt_a2dp_setup(struct bt_a2dp *a2dp) {
     }
 
     a2dp->sbc.bitpool = active_capabilities.max_bitpool;
-    a2dp->codesize = sbc_get_codesize(&a2dp->sbc);
+    a2dp->codesize = (uint16_t) sbc_get_codesize(&a2dp->sbc);
     a2dp->count = sizeof(struct rtp_header) + sizeof(struct rtp_payload);
 }
 
@@ -423,13 +420,13 @@ static int bt_setconf(struct userdata *u) {
 
     e = bt_audioservice_send(u->audioservice_fd, &msg.setconf_req.h);
     if (e < 0) {
-        pa_log_error("failed to send BT_SETCONFIGURATION_REQ");
+        pa_log_error("Failed to send BT_SETCONFIGURATION_REQ");
         return e;
     }
 
     e = bt_audioservice_expect(u->audioservice_fd, &msg.rsp_hdr.msg_h, BT_SETCONFIGURATION_RSP);
     if (e < 0) {
-        pa_log_error("failed to expect BT_SETCONFIGURATION_RSP");
+        pa_log_error("Failed to expect BT_SETCONFIGURATION_RSP");
         return e;
     }
 
@@ -470,13 +467,13 @@ static int bt_getstreamfd(struct userdata *u) {
 
     e = bt_audioservice_send(u->audioservice_fd, &msg.start_req.h);
     if (e < 0) {
-        pa_log_error("failed to send BT_STREAMSTART_REQ");
+        pa_log_error("Failed to send BT_STREAMSTART_REQ");
         return e;
     }
 
     e = bt_audioservice_expect(u->audioservice_fd, &msg.rsp_hdr.msg_h, BT_STREAMSTART_RSP);
     if (e < 0) {
-        pa_log_error("failed to expect BT_STREAMSTART_RSP");
+        pa_log_error("Failed to expect BT_STREAMSTART_RSP");
         return e;
     }
 
@@ -487,7 +484,7 @@ static int bt_getstreamfd(struct userdata *u) {
 
     e = bt_audioservice_expect(u->audioservice_fd, &msg.streamfd_ind.h, BT_STREAMFD_IND);
     if (e < 0) {
-        pa_log_error("failed to expect BT_STREAMFD_IND");
+        pa_log_error("Failed to expect BT_STREAMFD_IND");
         return e;
     }
 
@@ -496,13 +493,13 @@ static int bt_getstreamfd(struct userdata *u) {
 
     u->stream_fd = bt_audio_service_get_data_fd(u->audioservice_fd);
     if (u->stream_fd < 0) {
-        pa_log_error("failed to get data fd: %s (%d)",pa_cstrerror(errno), errno);
+        pa_log_error("Failed to get data fd: %s (%d)",pa_cstrerror(errno), errno);
         return -errno;
     }
 
     if (u->transport == BT_CAPABILITIES_TRANSPORT_A2DP) {
-        if (pa_socket_set_sndbuf(u->stream_fd, 10*u->link_mtu) < 0) {
-            pa_log_error("failed to set socket options for A2DP: %s (%d)",pa_cstrerror(errno), errno);
+        if (pa_socket_set_sndbuf(u->stream_fd, 10U*u->link_mtu) < 0) {
+            pa_log_error("Failed to set socket options for A2DP: %s (%d)",pa_cstrerror(errno), errno);
             return -errno;
         }
     }
@@ -543,9 +540,9 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
 
         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;
+/*             r = pa_smoother_get(u->smoother, pa_rtclock_usec()); */
+/* /\*             w = pa_bytes_to_usec(u->offset + (uint64_t) u->memchunk.length, &u->sink->sample_spec); *\/ */
+            *((pa_usec_t*) data) = /*w > r ? w - r :*/ 0;
             return 0;
         }
 
@@ -556,56 +553,46 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
 
 static int sco_process_render(struct userdata *u) {
     void *p;
-    ssize_t l;
-    int write_type = 0;
+    int ret = 0;
+    pa_memchunk memchunk;
 
-    u->memchunk.memblock = pa_memblock_new(u->mempool, u->block_size);
-    pa_log_debug("memblock asked size %d", u->block_size);
-    u->memchunk.length = pa_memblock_get_length(u->memchunk.memblock);
-    pa_log_debug("memchunk length %d", u->memchunk.length);
-    pa_sink_render_into_full(u->sink, &u->memchunk);
+    pa_sink_render_full(u->sink, u->block_size, &memchunk);
 
-    pa_assert(u->memchunk.length > 0);
+    p = pa_memblock_acquire(memchunk.memblock);
 
-    p = pa_memblock_acquire(u->memchunk.memblock);
+    for (;;) {
+        ssize_t l;
 
-sco_write:
-    l = pa_write(u->stream_fd, (uint8_t*) p, u->memchunk.length, &write_type);
-    pa_log_debug("memblock written to socket: %d bytes", l);
+        l = pa_loop_write(u->stream_fd, (uint8_t*) p, memchunk.length, NULL);
+        pa_log_debug("Memblock written to socket: %li bytes", (long) l);
 
-    pa_assert(l != 0);
+        pa_assert(l != 0);
 
-    if (l < 0) {
-        if (errno == EINTR) {
-            pa_log_debug("EINTR");
-            goto sco_write;
+        if (l > 0) {
+            u->offset += (uint64_t) l;
+            break;
         }
-        else if (errno == EAGAIN) {
+
+        if (errno == EINTR)
+            pa_log_debug("EINTR");
+        else if (errno == EAGAIN)
             pa_log_debug("EAGAIN");
-            goto sco_write;
-        }
         else {
-            pa_memblock_release(u->memchunk.memblock);
-            pa_memblock_unref(u->memchunk.memblock);
-            pa_memchunk_reset(&u->memchunk);
-            pa_log_debug("memchunk reseted");
             pa_log_error("Failed to write data to FIFO: %s", pa_cstrerror(errno));
-            return -1;
+            ret = -1;
+            break;
         }
-    } else {
-        pa_memblock_release(u->memchunk.memblock);
-        pa_memblock_unref(u->memchunk.memblock);
-        pa_memchunk_reset(&u->memchunk);
-        pa_log_debug("memchunk reseted");
-        u->offset += l;
-        return 0;
     }
+
+    pa_memblock_release(memchunk.memblock);
+    pa_memblock_unref(memchunk.memblock);
+
+    return ret;
 }
 
 static int a2dp_process_render(struct userdata *u) {
-    ssize_t l;
-    uint8_t write_type = 0;
-    uint16_t written;
+    int written;
+
     struct bt_a2dp *a2dp = &u->a2dp;
     struct rtp_header *header = (void *) a2dp->buffer;
     struct rtp_payload *payload = (void *) (a2dp->buffer + sizeof(*header));
@@ -614,39 +601,35 @@ static int a2dp_process_render(struct userdata *u) {
 
     do {
         /* Render some data */
-        uint16_t frame_size;
-        uint16_t encoded;
+        int frame_size, encoded;
         void *p;
+        pa_memchunk memchunk;
 
-        u->memchunk.memblock = pa_memblock_new(u->mempool, u->block_size);
-        pa_log_debug("memblock asked size %d", u->block_size);
-        u->memchunk.length = pa_memblock_get_length(u->memchunk.memblock);
-        pa_log_debug("memchunk length %d", u->memchunk.length);
-        pa_sink_render_into_full(u->sink, &u->memchunk);
+        pa_sink_render_full(u->sink, u->block_size, &memchunk);
 
-        pa_assert(u->memchunk.length > 0);
+        p = pa_memblock_acquire(memchunk.memblock);
 
-        p = pa_memblock_acquire(u->memchunk.memblock);
-        frame_size = sbc_get_frame_length(&a2dp->sbc);
+        frame_size = (uint16_t) sbc_get_frame_length(&a2dp->sbc);
         pa_log_debug("SBC frame_size: %d", frame_size);
 
-        encoded = sbc_encode(&a2dp->sbc, (uint8_t*) p, a2dp->codesize, a2dp->buffer + a2dp->count,
-                sizeof(a2dp->buffer) - a2dp->count, &written);
+        encoded = sbc_encode(&a2dp->sbc, p, (int) a2dp->codesize, a2dp->buffer + a2dp->count,
+                             (int) (sizeof(a2dp->buffer) - a2dp->count), &written);
         pa_log_debug("SBC: encoded: %d; written: %d", encoded, written);
+
+        pa_memblock_release(memchunk.memblock);
+        pa_memblock_unref(memchunk.memblock);
+
         if (encoded <= 0) {
             pa_log_error("SBC encoding error (%d)", encoded);
             return -1;
         }
-        pa_memblock_release(u->memchunk.memblock);
-        pa_memblock_unref(u->memchunk.memblock);
-        pa_memchunk_reset(&u->memchunk);
-        pa_log_debug("memchunk reseted");
 
-        a2dp->count += written;
+        a2dp->count += (size_t) written;
         a2dp->frame_count++;
-        a2dp->samples += encoded / frame_size;
-        a2dp->nsamples += encoded / frame_size;
-    } while (a2dp->count + written <= u->link_mtu);
+        a2dp->samples += (unsigned) encoded / frame_size;
+        a2dp->total_samples += (unsigned) encoded / frame_size;
+
+    } while (a2dp->count + (size_t) written <= u->link_mtu);
 
     /* write it to the fifo */
     memset(a2dp->buffer, 0, sizeof(*header) + sizeof(*payload));
@@ -654,24 +637,24 @@ static int a2dp_process_render(struct userdata *u) {
     header->v = 2;
     header->pt = 1;
     header->sequence_number = htons(a2dp->seq_num);
-    header->timestamp = htonl(a2dp->nsamples);
+    header->timestamp = htonl(a2dp->total_samples);
     header->ssrc = htonl(1);
 
-avdtp_write:
-    l = pa_write(u->stream_fd, a2dp->buffer, a2dp->count, &write_type);
-    pa_log_debug("avdtp_write: requested %d bytes; written %d bytes", a2dp->count, l);
+    for (;;) {
+        ssize_t l;
 
-    pa_assert(l != 0);
+        l = pa_loop_write(u->stream_fd, a2dp->buffer, a2dp->count, NULL);
+        pa_log_debug("avdtp_write: requested %lu bytes; written %li bytes", (unsigned long) a2dp->count, (long) l);
 
-    if (l < 0) {
-        if (errno == EINTR) {
+        pa_assert(l != 0);
+
+        if (l > 0)
+            break;
+
+        if (errno == EINTR)
             pa_log_debug("EINTR");
-            goto avdtp_write;
-        }
-        else if (errno == EAGAIN) {
+        else if (errno == EAGAIN)
             pa_log_debug("EAGAIN");
-            goto avdtp_write;
-        }
         else {
             pa_log_error("Failed to write data to FIFO: %s", pa_cstrerror(errno));
             return -1;
@@ -696,6 +679,9 @@ static void thread_func(void *userdata) {
 
     pa_log_debug("IO Thread starting up");
 
+    if (u->core->realtime_scheduling)
+        pa_make_realtime(u->core->realtime_priority);
+
     pa_thread_mq_install(&u->thread_mq);
     pa_rtpoll_install(u->rtpoll);
 
@@ -707,11 +693,9 @@ static void thread_func(void *userdata) {
         uint64_t n;
         pa_usec_t usec;
 
-        if (PA_SINK_IS_OPENED(u->sink->thread_info.state)) {
-            if (u->sink->thread_info.rewind_requested) {
+        if (PA_SINK_IS_OPENED(u->sink->thread_info.state))
+            if (u->sink->thread_info.rewind_requested)
                 pa_sink_process_rewind(u->sink, 0);
-            }
-        }
 
         pollfd = pa_rtpoll_item_get_pollfd(u->rtpoll_item, NULL);
 
@@ -719,8 +703,7 @@ static void thread_func(void *userdata) {
             if (u->transport == BT_CAPABILITIES_TRANSPORT_A2DP) {
                 if ((l = a2dp_process_render(u)) < 0)
                     goto fail;
-            }
-            else {
+            } else {
                 if ((l = sco_process_render(u)) < 0)
                     goto fail;
             }
@@ -729,7 +712,7 @@ static void thread_func(void *userdata) {
             /* feed the time smoother */
             n = u->offset;
             if (ioctl(u->stream_fd, SIOCOUTQ, &l) >= 0 && l > 0)
-                n -= l;
+                n -= (uint64_t) l;
             usec = pa_bytes_to_usec(n, &u->sink->sample_spec);
             if (usec > u->latency)
                 usec -= u->latency;
@@ -740,7 +723,7 @@ static void thread_func(void *userdata) {
 
         /* Hmm, nothing to do. Let's sleep */
         pa_log_debug("IO thread going to sleep");
-        pollfd->events = PA_SINK_IS_OPENED(u->sink->thread_info.state) ? POLLOUT : 0;
+        pollfd->events = (short) (PA_SINK_IS_OPENED(u->sink->thread_info.state) ? POLLOUT : 0);
         if ((ret = pa_rtpoll_run(u->rtpoll, TRUE)) < 0) {
             pa_log_error("rtpoll_run < 0");
             goto fail;
@@ -783,13 +766,11 @@ int pa__init(pa_module* m) {
     u->core = m->core;
     u->audioservice_fd = -1;
     u->stream_fd = -1;
-    u->transport = -1;
+    u->transport = (uint8_t) -1;
     u->offset = 0;
     u->latency = 0;
     u->a2dp.sbc_initialized = FALSE;
     u->smoother = pa_smoother_new(PA_USEC_PER_SEC, PA_USEC_PER_SEC*2, TRUE, 10);
-    u->mempool = pa_mempool_new(FALSE);
-    pa_memchunk_reset(&u->memchunk);
     u->rtpoll = pa_rtpoll_new();
     pa_thread_mq_init(&u->thread_mq, u->core->mainloop, u->rtpoll);
     u->rtpoll_item = NULL;
@@ -826,34 +807,34 @@ int pa__init(pa_module* m) {
     /* connect to the bluez audio service */
     u->audioservice_fd = bt_audio_service_open();
     if (u->audioservice_fd <= 0) {
-        pa_log_error("couldn't connect to bluetooth audio service");
+        pa_log_error("Couldn't connect to bluetooth audio service");
         goto fail;
     }
-    pa_log_debug("connected to the bluetooth audio service");
+    pa_log_debug("Connected to the bluetooth audio service");
 
     /* queries device capabilities */
     e = bt_getcaps(u);
     if (e < 0) {
-        pa_log_error("failed to get device capabilities");
+        pa_log_error("Failed to get device capabilities");
         goto fail;
     }
-    pa_log_debug("got device capabilities");
+    pa_log_debug("Got device capabilities");
 
     /* configures the connection */
     e = bt_setconf(u);
     if (e < 0) {
-        pa_log_error("failed to set config");
+        pa_log_error("Failed to set config");
         goto fail;
     }
-    pa_log_debug("connection to the device configured");
+    pa_log_debug("Connection to the device configured");
 
     /* gets the device socket */
     e = bt_getstreamfd(u);
     if (e < 0) {
-        pa_log_error("failed to get stream fd (%d)", e);
+        pa_log_error("Failed to get stream fd (%d)", e);
         goto fail;
     }
-    pa_log_debug("got the device socket");
+    pa_log_debug("Got the device socket");
 
     /* create sink */
     pa_sink_new_data_init(&data);
@@ -863,17 +844,17 @@ int pa__init(pa_module* m) {
     pa_sink_new_data_set_sample_spec(&data, &u->ss);
     pa_proplist_sets(data.proplist, PA_PROP_DEVICE_STRING, u->name);
     pa_proplist_setf(data.proplist, PA_PROP_DEVICE_DESCRIPTION, "Bluetooth %s '%s' (%s)", u->strtransport, u->name, u->addr);
-    pa_proplist_setf(data.proplist, "bluetooth.protocol", u->profile);
+    pa_proplist_sets(data.proplist, "bluetooth.protocol", u->profile);
     pa_proplist_setf(data.proplist, PA_PROP_DEVICE_API, "bluez");
     pa_proplist_setf(data.proplist, PA_PROP_DEVICE_CLASS, "sound");
     pa_proplist_setf(data.proplist, PA_PROP_DEVICE_CONNECTOR, "bluetooth");
-    pa_proplist_setf(data.proplist, PA_PROP_DEVICE_FORM_FACTOR, "headset"); /*FIXME*/
-    pa_proplist_setf(data.proplist, PA_PROP_DEVICE_VENDOR_PRODUCT_ID, "product_id"); /*FIXME*/
-    pa_proplist_setf(data.proplist, PA_PROP_DEVICE_SERIAL, "serial"); /*FIXME*/
+/*     pa_proplist_setf(data.proplist, PA_PROP_DEVICE_FORM_FACTOR, "headset"); /\*FIXME*\/ */
+/*     pa_proplist_setf(data.proplist, PA_PROP_DEVICE_VENDOR_PRODUCT_ID, "product_id"); /\*FIXME*\/ */
+/*     pa_proplist_setf(data.proplist, PA_PROP_DEVICE_SERIAL, "serial"); /\*FIXME*\/ */
     u->sink = pa_sink_new(m->core, &data, PA_SINK_HARDWARE|PA_SINK_LATENCY);
     pa_sink_new_data_done(&data);
     if (!u->sink) {
-        pa_log_error("failed to create sink");
+        pa_log_error("Failed to create sink");
         goto fail;
     }
     u->sink->userdata = u;
@@ -888,7 +869,7 @@ int pa__init(pa_module* m) {
 
     /* start rt thread */
     if (!(u->thread = pa_thread_new(thread_func, u))) {
-        pa_log_error("failed to create IO thread");
+        pa_log_error("Failed to create IO thread");
         goto fail;
     }
     pa_sink_put(u->sink);
@@ -899,6 +880,7 @@ int pa__init(pa_module* m) {
 fail:
     if (ma)
         pa_modargs_free(ma);
+
     pa__done(m);
     return -1;
 }
@@ -918,34 +900,24 @@ void pa__done(pa_module *m) {
         pa_thread_free(u->thread);
     }
 
-    pa_thread_mq_done(&u->thread_mq);
-
     if (u->sink)
         pa_sink_unref(u->sink);
 
+    pa_thread_mq_done(&u->thread_mq);
+
     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);
-
-    if (u->mempool)
-        pa_mempool_free(u->mempool);
-
     if (u->smoother)
         pa_smoother_free(u->smoother);
 
-    if (u->name)
-        pa_xfree(u->name);
-
-    if (u->addr)
-        pa_xfree(u->addr);
-
-    if (u->profile)
-        pa_xfree(u->profile);
+    pa_xfree(u->name);
+    pa_xfree(u->addr);
+    pa_xfree(u->profile);
+    pa_xfree(u->strtransport);
 
     if (u->stream_fd >= 0)
         pa_close(u->stream_fd);

commit f5c301d9f475ca62b32f48514d703266bf9b6445
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Sep 29 21:45:00 2008 +0200

    make module-bluetooth-discover actually load modules and smaller other fixes

diff --git a/src/modules/bluetooth/module-bluetooth-discover.c b/src/modules/bluetooth/module-bluetooth-discover.c
index 3e9763b..e0a760f 100644
--- a/src/modules/bluetooth/module-bluetooth-discover.c
+++ b/src/modules/bluetooth/module-bluetooth-discover.c
@@ -32,6 +32,7 @@
 #include <pulsecore/modargs.h>
 #include <pulsecore/macro.h>
 #include <pulsecore/llist.h>
+#include <pulsecore/core-util.h>
 
 #include "dbus-util.h"
 #include "module-bluetooth-discover-symdef.h"
@@ -62,11 +63,14 @@ struct device {
     char *address;
     int class;
     int trusted;
+    const char *audio_profile;
+    uint32_t module_index;
     PA_LLIST_FIELDS(struct device);
 };
 
 struct adapter {
     char *object_path;
+    char *name;
     char *mode;
     char *address;
     PA_LLIST_HEAD(struct device, device_list);
@@ -80,20 +84,28 @@ struct userdata {
 };
 
 static struct uuid *uuid_new(const char *uuid) {
-    struct uuid *node = pa_xnew(struct uuid, 1);
+    struct uuid *node;
+
+    node = pa_xnew(struct uuid, 1);
     node->uuid = pa_xstrdup(uuid);
     PA_LLIST_INIT(struct uuid, node);
+
     return node;
 }
 
 static void uuid_free(struct uuid *uuid) {
+    pa_assert(uuid);
+
+    pa_xfree(uuid->uuid);
     pa_xfree(uuid);
 }
 
-static struct device *device_new(const char *device, struct adapter *adapter) {
-    struct device *node = pa_xnew(struct device, 1);
+static struct device *device_new(struct adapter *adapter, const char *object_path) {
+    struct device *node;
+
+    node = pa_xnew(struct device, 1);
     node->name = NULL;
-    node->object_path = pa_xstrdup(device);
+    node->object_path = pa_xstrdup(object_path);
     node->paired = -1;
     node->adapter = adapter;
     node->alias = NULL;
@@ -102,84 +114,293 @@ static struct device *device_new(const char *device, struct adapter *adapter) {
     node->address = NULL;
     node->class = -1;
     node->trusted = -1;
+    node->audio_profile = NULL;
+    node->module_index = PA_INVALID_INDEX;
     PA_LLIST_INIT(struct device, node);
+
     return node;
 }
 
 static void device_free(struct device *device) {
-    struct uuid *uuid_list_i;
-    while (device->uuid_list) {
-        uuid_list_i = device->uuid_list;
-        PA_LLIST_REMOVE(struct uuid, device->uuid_list, uuid_list_i);
-        uuid_free(uuid_list_i);
+    struct uuid *i;
+
+    pa_assert(device);
+
+    while ((i = device->uuid_list)) {
+        PA_LLIST_REMOVE(struct uuid, device->uuid_list, i);
+        uuid_free(i);
     }
+
+    pa_xfree(device->name);
+    pa_xfree(device->object_path);
+    pa_xfree(device->alias);
+    pa_xfree(device->address);
     pa_xfree(device);
 }
 
-static struct adapter *adapter_new(const char *adapter) {
-    struct adapter *node = pa_xnew(struct adapter, 1);
-    node->object_path = pa_xstrdup(adapter);
+static struct adapter *adapter_new(const char *object_path) {
+    struct adapter *node;
+
+    node = pa_xnew(struct adapter, 1);
+    node->object_path = pa_xstrdup(object_path);
     node->mode = NULL;
     node->address = NULL;
+    node->name = NULL;
+
     PA_LLIST_HEAD_INIT(struct device, node->device_list);
     PA_LLIST_INIT(struct adapter, node);
+
     return node;
 }
 
 static void adapter_free(struct adapter *adapter) {
-    struct device *device_list_i;
-    while (adapter->device_list) {
-        device_list_i = adapter->device_list;
-        PA_LLIST_REMOVE(struct device, adapter->device_list, device_list_i);
-        device_free(device_list_i);
+    struct device *i;
+
+    pa_assert(adapter);
+
+    while ((i = adapter->device_list)) {
+        PA_LLIST_REMOVE(struct device, adapter->device_list, i);
+        device_free(i);
     }
+
+    pa_xfree(adapter->object_path);
+    pa_xfree(adapter->mode);
+    pa_xfree(adapter->address);
+    pa_xfree(adapter->name);
     pa_xfree(adapter);
 }
 
-static void print_devices(struct device *device_list) {
-    struct device *device_list_i = device_list;
-    while (device_list_i != NULL) {
-        struct uuid *uuid_list_i = device_list_i->uuid_list;
-        if (strcmp(device_list_i->object_path, "/DEVICE_HEAD") != 0) {
-            pa_log_debug("    [ %s ]", device_list_i->object_path);
-            pa_log_debug("        Name = %s", device_list_i->name);
-            pa_log_debug("        Paired = %d", device_list_i->paired);
-            pa_log_debug("        Adapter = %s", device_list_i->adapter->object_path);
-            pa_log_debug("        Alias = %s", device_list_i->alias);
-            pa_log_debug("        Connected = %d", device_list_i->connected);
-            pa_log_debug("        UUIDs = ");
-            while (uuid_list_i != NULL) {
-                if (strcmp(uuid_list_i->uuid, "UUID_HEAD") != 0)
-                    pa_log("            %s", uuid_list_i->uuid);
-                uuid_list_i = uuid_list_i->next;
-            }
-            pa_log_debug("        Address = %s", device_list_i->address);
-            pa_log_debug("        Class = 0x%x", device_list_i->class);
-            pa_log_debug("        Trusted = %d", device_list_i->trusted);
+static struct adapter* adapter_find(struct userdata *u, const char *path) {
+    struct adapter *i;
+
+    for (i = u->adapter_list; i; i = i->next)
+        if (pa_streq(i->object_path, path))
+            return i;
+
+    return NULL;
+}
+
+static struct device* device_find(struct userdata *u, const char *adapter, const char *path) {
+    struct adapter *a;
+    struct device *i;
+
+    if (!(a = adapter_find(u, adapter)))
+        return NULL;
+
+    for (i = a->device_list; i; i = i->next)
+        if (pa_streq(i->object_path, path))
+            return i;
+
+    return NULL;
+}
+
+static const char *yes_no_na(int b) {
+    if (b < 0)
+        return "n/a";
+
+    return pa_yes_no(b);
+}
+
+static void print_devices(struct adapter *a) {
+    struct device *i;
+
+    pa_assert(a);
+
+    for (i = a->device_list; i; i = i->next) {
+        struct uuid *j;
+
+        if (pa_streq(i->object_path, "/DEVICE_HEAD"))
+            continue;
+
+        pa_log_debug("\t[ %s ]\n"
+                     "\t\tName = %s\n"
+                     "\t\tPaired = %s\n"
+                     "\t\tAdapter = %s\n"
+                     "\t\tAlias = %s\n"
+                     "\t\tConnected = %s\n"
+                     "\t\tAudio = %s\n",
+                     i->object_path,
+                     pa_strnull(i->name),
+                     yes_no_na(i->paired),
+                     i->adapter->object_path,
+                     pa_strnull(i->alias),
+                     yes_no_na(i->connected),
+                     pa_strnull(i->audio_profile));
+
+        pa_log_debug("\t\tUUIDs = ");
+        for (j = i->uuid_list; j; j = j->next) {
+
+            if (pa_streq(j->uuid, "UUID_HEAD"))
+                continue;
+
+            pa_log_debug("\t\t         %s", j->uuid);
         }
-        device_list_i = device_list_i->next;
+
+        pa_log_debug("\t\tAddress = %s\n"
+                     "\t\tClass = 0x%x\n"
+                     "\t\tTrusted = %s",
+                     i->address,
+                     i->class,
+                     yes_no_na(i->trusted));
+    }
+}
+
+static void print_adapters(struct userdata *u) {
+    struct adapter *i;
+
+    pa_assert(u);
+
+    for (i = u->adapter_list; i; i = i->next) {
+
+        if (pa_streq(i->object_path, "/ADAPTER_HEAD"))
+            continue;
+
+        pa_log_debug(
+                "[ %s ]\n"
+                "\tName = %s\n"
+                "\tMode = %s\n"
+                "\tAddress = %s\n",
+                i->object_path,
+                pa_strnull(i->name),
+                pa_strnull(i->mode),
+                pa_strnull(i->address));
+
+        print_devices(i);
+    }
+}
+
+static const char *strip_object_path(const char *op) {
+    const char *slash;
+
+    if ((slash = strrchr(op, '/')))
+        return slash+1;
+
+    return op;
+}
+
+static void load_module_for_device(struct userdata *u, struct device *d) {
+    char *args;
+    pa_module *m;
+
+    pa_assert(u);
+    pa_assert(d);
+
+    if (!d->audio_profile) {
+        pa_log_debug("Ignoring %s since it is not an audio device.", d->object_path);
+        return;
     }
+
+    args = pa_sprintf_malloc("sink_name=%s address=%s profile=%s", strip_object_path(d->object_path), d->address, d->audio_profile);
+    m = pa_module_load(u->module->core, "module-bluetooth-device", args);
+    pa_xfree(args);
+
+    if (!m) {
+        pa_log_debug("Failed to load module for device %s", d->object_path);
+        return;
+    }
+
+    d->module_index = m->index;
 }
 
-static void print_adapters(struct adapter *adapter_list) {
-    struct adapter *adapter_list_i = adapter_list;
-    while (adapter_list_i != NULL) {
-        if (strcmp(adapter_list_i->object_path, "/ADAPTER_HEAD") != 0) {
-            pa_log_debug("[ %s ]", adapter_list_i->object_path);
-            pa_log_debug("    Mode = %s", adapter_list_i->mode);
-            pa_log_debug("    Address = %s", adapter_list_i->address);
-            print_devices(adapter_list_i->device_list);
+static void load_modules(struct userdata *u) {
+    struct device *d;
+    struct adapter *a;
+
+    pa_assert(u);
+
+    for (a = u->adapter_list; a; a = a->next)
+        for (d = a->device_list; d; d = d->next)
+            load_module_for_device(u, d);
+}
+
+static int get_adapter_properties(struct userdata *u, struct adapter *a) {
+    DBusError e;
+    DBusMessage *m = NULL, *r = NULL;
+    DBusMessageIter arg_i, element_i;
+    int ret = -1;
+
+    pa_assert(u);
+    pa_assert(a);
+    dbus_error_init(&e);
+
+    pa_assert_se(m = dbus_message_new_method_call("org.bluez", a->object_path, "org.bluez.Adapter", "GetProperties"));
+
+    r = dbus_connection_send_with_reply_and_block(pa_dbus_connection_get(u->conn), m, -1, &e);
+
+    if (!r) {
+        pa_log("org.bluez.Adapter.GetProperties failed: %s", e.message);
+        goto finish;
+    }
+
+    if (!dbus_message_iter_init(r, &arg_i)) {
+        pa_log("org.bluez.Adapter.GetProperties reply has no arguments");
+        goto finish;
+    }
+
+    if (dbus_message_iter_get_arg_type(&arg_i) != DBUS_TYPE_ARRAY) {
+        pa_log("org.bluez.Adapter.GetProperties argument is not an array");
+        goto finish;
+    }
+
+    dbus_message_iter_recurse(&arg_i, &element_i);
+    while (dbus_message_iter_get_arg_type(&element_i) != DBUS_TYPE_INVALID) {
+
+        if (dbus_message_iter_get_arg_type(&element_i) == DBUS_TYPE_DICT_ENTRY) {
+            const char *key;
+            DBusMessageIter dict_i, variant_i;
+
+            dbus_message_iter_recurse(&element_i, &dict_i);
+
+            if (dbus_message_iter_get_arg_type(&dict_i) != DBUS_TYPE_STRING) {
+                pa_log("Property name not a string.");
+                goto finish;
+            }
+
+            dbus_message_iter_get_basic(&dict_i, &key);
+
+            if (!dbus_message_iter_next(&dict_i)) {
+                pa_log("Dictionary item missing");
+                goto finish;
+            }
+
+            dbus_message_iter_recurse(&dict_i, &variant_i);
+
+            if (dbus_message_iter_get_arg_type(&variant_i) == DBUS_TYPE_STRING) {
+                const char *value;
+                dbus_message_iter_get_basic(&variant_i, &value);
+
+                if (pa_streq(key, "Mode"))
+                    a->mode = pa_xstrdup(value);
+                else if (pa_streq(key, "Address"))
+                    a->address = pa_xstrdup(value);
+                else if (pa_streq(key, "Name"))
+                    a->name = pa_xstrdup(value);
+            }
         }
-        adapter_list_i = adapter_list_i->next;
+
+        if (!dbus_message_iter_next(&element_i))
+            break;
     }
+
+    ret = 0;
+
+finish:
+    if (m)
+        dbus_message_unref(m);
+    if (r)
+        dbus_message_unref(r);
+
+    dbus_error_free(&e);
+
+    return ret;
 }
 
-static void detect_adapters(struct userdata *u) {
+static int detect_adapters(struct userdata *u) {
     DBusError e;
     DBusMessage *m = NULL, *r = NULL;
-    DBusMessageIter arg_i, element_i, dict_i, variant_i;
+    DBusMessageIter arg_i, element_i;
     struct adapter *adapter_list_i;
-    const char *key, *value;
+    int ret = -1;
 
     pa_assert(u);
     dbus_error_init(&e);
@@ -187,203 +408,222 @@ static void detect_adapters(struct userdata *u) {
     /* get adapters */
     pa_assert_se(m = dbus_message_new_method_call("org.bluez", "/", "org.bluez.Manager", "ListAdapters"));
     r = dbus_connection_send_with_reply_and_block(pa_dbus_connection_get(u->conn), m, -1, &e);
+
     if (!r) {
         pa_log("org.bluez.Manager.ListAdapters failed: %s", e.message);
-        goto fail;
+        goto finish;
     }
+
     if (!dbus_message_iter_init(r, &arg_i)) {
         pa_log("org.bluez.Manager.ListAdapters reply has no arguments");
-        goto fail;
+        goto finish;
     }
+
     if (dbus_message_iter_get_arg_type(&arg_i) != DBUS_TYPE_ARRAY) {
         pa_log("org.bluez.Manager.ListAdapters argument is not an array");
-        goto fail;
+        goto finish;
     }
+
     dbus_message_iter_recurse(&arg_i, &element_i);
     while (dbus_message_iter_get_arg_type(&element_i) != DBUS_TYPE_INVALID) {
         if (dbus_message_iter_get_arg_type(&element_i) == DBUS_TYPE_OBJECT_PATH) {
+
             struct adapter *node;
+            const char *value;
+
             dbus_message_iter_get_basic(&element_i, &value);
             node = adapter_new(value);
             PA_LLIST_PREPEND(struct adapter, u->adapter_list, node);
         }
-        dbus_message_iter_next(&element_i);
+
+        if (!dbus_message_iter_next(&element_i))
+            break;
     }
 
+    ret = 0;
+
     /* get adapter properties */
-    adapter_list_i = u->adapter_list;
-    while (adapter_list_i != NULL) {
-        pa_assert_se(m = dbus_message_new_method_call("org.bluez", adapter_list_i->object_path, "org.bluez.Adapter", "GetProperties"));
-        r = dbus_connection_send_with_reply_and_block(pa_dbus_connection_get(u->conn), m, -1, &e);
-        if (!r) {
-            pa_log("org.bluez.Adapter.GetProperties failed: %s", e.message);
-            goto fail;
-        }
-        if (!dbus_message_iter_init(r, &arg_i)) {
-            pa_log("org.bluez.Adapter.GetProperties reply has no arguments");
-            goto fail;
-        }
-        if (dbus_message_iter_get_arg_type(&arg_i) != DBUS_TYPE_ARRAY) {
-            pa_log("org.bluez.Adapter.GetProperties argument is not an array");
-            goto fail;
-        }
-        dbus_message_iter_recurse(&arg_i, &element_i);
-        while (dbus_message_iter_get_arg_type(&element_i) != DBUS_TYPE_INVALID) {
-            if (dbus_message_iter_get_arg_type(&element_i) == DBUS_TYPE_DICT_ENTRY) {
-                dbus_message_iter_recurse(&element_i, &dict_i);
-                dbus_message_iter_get_basic(&dict_i, &key);
-                dbus_message_iter_next(&dict_i);
-                dbus_message_iter_recurse(&dict_i, &variant_i);
+    for (adapter_list_i = u->adapter_list; adapter_list_i; adapter_list_i = adapter_list_i->next)
+        get_adapter_properties(u, adapter_list_i);
+
+finish:
+    if (m)
+        dbus_message_unref(m);
+    if (r)
+        dbus_message_unref(r);
+
+    dbus_error_free(&e);
+    return ret;
+}
+
+static int get_device_properties(struct userdata *u, struct device *d) {
+    DBusError e;
+    DBusMessage *m = NULL, *r = NULL;
+    DBusMessageIter arg_i, element_i, dict_i, variant_i;
+    int ret = -1;
+
+    pa_assert(u);
+    pa_assert(d);
+
+    dbus_error_init(&e);
+
+    pa_assert_se(m = dbus_message_new_method_call("org.bluez", d->object_path, "org.bluez.Device", "GetProperties"));
+
+    r = dbus_connection_send_with_reply_and_block(pa_dbus_connection_get(u->conn), m, -1, &e);
+
+    if (!r) {
+        pa_log("org.bluez.Device.GetProperties failed: %s", e.message);
+        goto finish;
+    }
+
+    if (!dbus_message_iter_init(r, &arg_i)) {
+        pa_log("org.bluez.Device.GetProperties reply has no arguments");
+        goto finish;
+    }
+
+    if (dbus_message_iter_get_arg_type(&arg_i) != DBUS_TYPE_ARRAY) {
+        pa_log("org.bluez.Device.GetProperties argument is not an array");
+        goto finish;
+    }
+
+    dbus_message_iter_recurse(&arg_i, &element_i);
+    while (dbus_message_iter_get_arg_type(&element_i) != DBUS_TYPE_INVALID) {
+        if (dbus_message_iter_get_arg_type(&element_i) == DBUS_TYPE_DICT_ENTRY) {
+            const char *value, *key;
+            int32_t ivalue;
+
+            dbus_message_iter_recurse(&element_i, &dict_i);
+            dbus_message_iter_get_basic(&dict_i, &key);
+            dbus_message_iter_next(&dict_i);
+
+            dbus_message_iter_recurse(&dict_i, &variant_i);
+            if (pa_streq(key, "Name")) {
+                dbus_message_iter_get_basic(&variant_i, &value);
+                d->name = pa_xstrdup(value);
+            } else if (pa_streq(key, "Paired")) {
+                dbus_message_iter_get_basic(&variant_i, &ivalue);
+                d->paired = ivalue;
+            } else if (pa_streq(key, "Alias")) {
+                dbus_message_iter_get_basic(&variant_i, &value);
+                d->alias = pa_xstrdup(value);
+            } else if (pa_streq(key, "Connected")) {
+                dbus_message_iter_get_basic(&variant_i, &ivalue);
+                d->connected = ivalue;
+            } else if (pa_streq(key, "UUIDs")) {
+                DBusMessageIter uuid_i;
+
+                dbus_message_iter_recurse(&variant_i, &uuid_i);
+                while (dbus_message_iter_get_arg_type(&uuid_i) != DBUS_TYPE_INVALID) {
+
+                    struct uuid *node;
+                    dbus_message_iter_get_basic(&uuid_i, &value);
+                    node = uuid_new(value);
+                    PA_LLIST_PREPEND(struct uuid, d->uuid_list, node);
+
+                    if ((strcasecmp(value, A2DP_SOURCE_UUID) == 0) ||
+                        (strcasecmp(value, A2DP_SINK_UUID) == 0))
+                        d->audio_profile = "a2dp";
+                    else if (((strcasecmp(value, HSP_HS_UUID) == 0) ||
+                              (strcasecmp(value, HFP_HS_UUID) == 0)) &&
+                             !d->audio_profile)
+                        d->audio_profile = "hsp";
+
+                    if (!dbus_message_iter_next(&uuid_i))
+                        break;
+                }
+
+            } else if (pa_streq(key, "Address")) {
                 dbus_message_iter_get_basic(&variant_i, &value);
-                if (strcmp(key, "Mode") == 0)
-                    adapter_list_i->mode = pa_xstrdup(value);
-                else if (strcmp(key, "Address") == 0)
-                    adapter_list_i->address = pa_xstrdup(value);
+                d->address = pa_xstrdup(value);
+            } else if (pa_streq(key, "Class")) {
+                dbus_message_iter_get_basic(&variant_i, &ivalue);
+                d->class = ivalue;
+            } else if (pa_streq(key, "Trusted")) {
+                dbus_message_iter_get_basic(&variant_i, &ivalue);
+                d->trusted = ivalue;
             }
-            dbus_message_iter_next(&element_i);
         }
-        adapter_list_i = adapter_list_i->next;
+
+        if (!dbus_message_iter_next(&element_i))
+            break;
     }
 
-fail:
+    ret = 0;
+
+finish:
     if (m)
         dbus_message_unref(m);
     if (r)
         dbus_message_unref(r);
+
     dbus_error_free(&e);
+    return ret;
 }
 
-static void detect_devices(struct userdata *u) {
+static int detect_devices(struct userdata *u) {
     DBusError e;
     DBusMessage *m = NULL, *r = NULL;
-    DBusMessageIter arg_i, element_i, dict_i, variant_i;
+    DBusMessageIter arg_i, element_i;
     struct adapter *adapter_list_i;
     struct device *device_list_i;
-    const char *key, *value;
-    int32_t ivalue;
+    const char *value;
+    int ret = -1;
 
     pa_assert(u);
     dbus_error_init(&e);
 
     /* get devices of each adapter */
-    adapter_list_i = u->adapter_list;
-    while (adapter_list_i != NULL) {
+    for (adapter_list_i = u->adapter_list; adapter_list_i; adapter_list_i = adapter_list_i->next) {
+
         pa_assert_se(m = dbus_message_new_method_call("org.bluez", adapter_list_i->object_path, "org.bluez.Adapter", "ListDevices"));
+
         r = dbus_connection_send_with_reply_and_block(pa_dbus_connection_get(u->conn), m, -1, &e);
+
         if (!r) {
             pa_log("org.bluez.Adapter.ListDevices failed: %s", e.message);
-            goto fail;
+            goto finish;
         }
+
         if (!dbus_message_iter_init(r, &arg_i)) {
             pa_log("org.bluez.Adapter.ListDevices reply has no arguments");
-            goto fail;
+            goto finish;
         }
+
         if (dbus_message_iter_get_arg_type(&arg_i) != DBUS_TYPE_ARRAY) {
             pa_log("org.bluez.Adapter.ListDevices argument is not an array");
-            goto fail;
+            goto finish;
         }
+
         dbus_message_iter_recurse(&arg_i, &element_i);
         while (dbus_message_iter_get_arg_type(&element_i) != DBUS_TYPE_INVALID) {
             if (dbus_message_iter_get_arg_type(&element_i) == DBUS_TYPE_OBJECT_PATH) {
                 struct device *node;
                 dbus_message_iter_get_basic(&element_i, &value);
-                node = device_new(value, adapter_list_i);
+                node = device_new(adapter_list_i, value);
                 PA_LLIST_PREPEND(struct device, adapter_list_i->device_list, node);
             }
-            dbus_message_iter_next(&element_i);
+
+            if (!dbus_message_iter_next(&element_i))
+                break;
         }
-        adapter_list_i = adapter_list_i->next;
     }
 
     /* get device properties */
-    adapter_list_i = u->adapter_list;
-    while (adapter_list_i != NULL) {
-        device_list_i = adapter_list_i->device_list;
-        while (device_list_i != NULL) {
-            pa_assert_se(m = dbus_message_new_method_call("org.bluez", device_list_i->object_path, "org.bluez.Device", "GetProperties"));
-            r = dbus_connection_send_with_reply_and_block(pa_dbus_connection_get(u->conn), m, -1, &e);
-            if (!r) {
-                pa_log("org.bluez.Device.GetProperties failed: %s", e.message);
-                goto fail;
-            }
-            if (!dbus_message_iter_init(r, &arg_i)) {
-                pa_log("org.bluez.Device.GetProperties reply has no arguments");
-                goto fail;
-            }
-            if (dbus_message_iter_get_arg_type(&arg_i) != DBUS_TYPE_ARRAY) {
-                pa_log("org.bluez.Device.GetProperties argument is not an array");
-                goto fail;
-            }
-            dbus_message_iter_recurse(&arg_i, &element_i);
-            while (dbus_message_iter_get_arg_type(&element_i) != DBUS_TYPE_INVALID) {
-                if (dbus_message_iter_get_arg_type(&element_i) == DBUS_TYPE_DICT_ENTRY) {
-                    dbus_message_iter_recurse(&element_i, &dict_i);
-                    dbus_message_iter_get_basic(&dict_i, &key);
-                    dbus_message_iter_next(&dict_i);
-                    dbus_message_iter_recurse(&dict_i, &variant_i);
-                    if (strcmp(key, "Name") == 0) {
-                        dbus_message_iter_get_basic(&variant_i, &value);
-                        device_list_i->name = pa_xstrdup(value);
-                    }
-                    else if (strcmp(key, "Paired") == 0) {
-                        dbus_message_iter_get_basic(&variant_i, &ivalue);
-                        device_list_i->paired = ivalue;
-                    }
-                    else if (strcmp(key, "Alias") == 0) {
-                        dbus_message_iter_get_basic(&variant_i, &value);
-                        device_list_i->alias = pa_xstrdup(value);
-                    }
-                    else if (strcmp(key, "Connected") == 0) {
-                        dbus_message_iter_get_basic(&variant_i, &ivalue);
-                        device_list_i->connected = ivalue;
-                    }
-                    else if (strcmp(key, "UUIDs") == 0) {
-                        DBusMessageIter uuid_i;
-                        pa_bool_t is_audio_device = FALSE;
-                        dbus_message_iter_recurse(&variant_i, &uuid_i);
-                        while (dbus_message_iter_get_arg_type(&uuid_i) != DBUS_TYPE_INVALID) {
-                            struct uuid *node;
-                            dbus_message_iter_get_basic(&uuid_i, &value);
-                            node = uuid_new(value);
-                            PA_LLIST_PREPEND(struct uuid, device_list_i->uuid_list, node);
-                            if ( (strcasecmp(value, HSP_HS_UUID) == 0) || (strcasecmp(value, HFP_HS_UUID) == 0) ||
-                                (strcasecmp(value, A2DP_SOURCE_UUID) == 0) || (strcasecmp(value, A2DP_SINK_UUID) == 0) )
-                                is_audio_device = TRUE;
-                            dbus_message_iter_next(&uuid_i);
-                        }
-                        if (!is_audio_device) {
-                            /* remove the current device from the list */
-                            PA_LLIST_REMOVE(struct device, adapter_list_i->device_list, device_list_i);
-                            pa_xfree(device_list_i);
-                            break;
-                        }
-                    }
-                    else if (strcmp(key, "Address") == 0) {
-                        dbus_message_iter_get_basic(&variant_i, &value);
-                        device_list_i->address = pa_xstrdup(value);
-                    }
-                    else if (strcmp(key, "Class") == 0) {
-                        dbus_message_iter_get_basic(&variant_i, &ivalue);
-                        device_list_i->class = ivalue;
-                    }
-                    else if (strcmp(key, "Trusted") == 0) {
-                        dbus_message_iter_get_basic(&variant_i, &ivalue);
-                        device_list_i->trusted = ivalue;
-                    }
-                }
-                dbus_message_iter_next(&element_i);
-            }
-            device_list_i = device_list_i->next;
-        }
-        adapter_list_i = adapter_list_i->next;
-    }
+    for (adapter_list_i = u->adapter_list; adapter_list_i; adapter_list_i = adapter_list_i->next)
+        for (device_list_i = adapter_list_i->device_list; device_list_i; device_list_i = device_list_i->next)
+            get_device_properties(u, device_list_i);
 
-fail:
+    ret = 0;
+
+finish:
     if (m)
         dbus_message_unref(m);
     if (r)
         dbus_message_unref(r);
+
     dbus_error_free(&e);
+
+    return ret;
 }
 
 static DBusHandlerResult filter_cb(DBusConnection *bus, DBusMessage *msg, void *userdata) {
@@ -404,43 +644,81 @@ static DBusHandlerResult filter_cb(DBusConnection *bus, DBusMessage *msg, void *
             dbus_message_get_member(msg));
 
     if (dbus_message_is_signal(msg, "org.bluez.Manager", "AdapterAdded")) {
+
         if (!dbus_message_iter_init(msg, &arg_i))
             pa_log("dbus: message has no parameters");
         else if (dbus_message_iter_get_arg_type(&arg_i) != DBUS_TYPE_OBJECT_PATH)
             pa_log("dbus: argument is not object path");
         else {
+            struct adapter *node;
+
             dbus_message_iter_get_basic(&arg_i, &value);
-            pa_log("hcid: adapter %s added", value);
+            pa_log_debug("hcid: adapter %s added", value);
+
+            node = adapter_new(value);
+            PA_LLIST_PREPEND(struct adapter, u->adapter_list, node);
+
+            get_adapter_properties(u, node);
         }
-    }
-    else if (dbus_message_is_signal(msg, "org.bluez.Manager", "AdapterRemoved")) {
+
+    } else if (dbus_message_is_signal(msg, "org.bluez.Manager", "AdapterRemoved")) {
         if (!dbus_message_iter_init(msg, &arg_i))
             pa_log("dbus: message has no parameters");
         else if (dbus_message_iter_get_arg_type(&arg_i) != DBUS_TYPE_OBJECT_PATH)
             pa_log("dbus: argument is not object path");
         else {
+            struct adapter *a;
+
             dbus_message_iter_get_basic(&arg_i, &value);
-            pa_log("hcid: adapter %s removed", value);
+            pa_log_debug("hcid: adapter %s removed", value);
+
+            if ((a = adapter_find(u, value))) {
+                PA_LLIST_REMOVE(struct adapter, u->adapter_list, a);
+                adapter_free(a);
+            }
         }
-    }
-    else if (dbus_message_is_signal(msg, "org.bluez.Adapter", "DeviceCreated")) {
+
+    } else if (dbus_message_is_signal(msg, "org.bluez.Adapter", "DeviceCreated")) {
+
         if (!dbus_message_iter_init(msg, &arg_i))
             pa_log("dbus: message has no parameters");
         else if (dbus_message_iter_get_arg_type(&arg_i) != DBUS_TYPE_OBJECT_PATH)
             pa_log("dbus: argument is not object path");
         else {
-            dbus_message_iter_get_basic(&arg_i, &value);
-            pa_log("hcid: device %s created", value);
+            struct adapter *adapter;
+
+            if (!(adapter = adapter_find(u, dbus_message_get_path(msg))))
+                pa_log("dbus: failed to find adapter for object path");
+            else {
+                struct device *node;
+
+                dbus_message_iter_get_basic(&arg_i, &value);
+                pa_log_debug("hcid: device %s created", value);
+
+                node = device_new(adapter, value);
+                PA_LLIST_PREPEND(struct device, adapter->device_list, node);
+
+                get_device_properties(u, node);
+                load_module_for_device(u, node);
+            }
         }
-    }
-    else if (dbus_message_is_signal(msg, "org.bluez.Adapter", "DeviceRemoved")) {
+
+    } else if (dbus_message_is_signal(msg, "org.bluez.Adapter", "DeviceRemoved")) {
+
         if (!dbus_message_iter_init(msg, &arg_i))
             pa_log("dbus: message has no parameters");
         else if (dbus_message_iter_get_arg_type(&arg_i) != DBUS_TYPE_OBJECT_PATH)
             pa_log("dbus: argument is not object path");
         else {
+            struct device *d;
+
             dbus_message_iter_get_basic(&arg_i, &value);
-            pa_log("hcid: device %s removed", value);
+            pa_log_debug("hcid: device %s removed", value);
+
+            if ((d = device_find(u, dbus_message_get_path(msg), value))) {
+                PA_LLIST_REMOVE(struct device, d->adapter->device_list, d);
+                device_free(d);
+            }
         }
     }
 
@@ -450,39 +728,38 @@ static DBusHandlerResult filter_cb(DBusConnection *bus, DBusMessage *msg, void *
 
 void pa__done(pa_module* m) {
     struct userdata *u;
-    struct adapter *adapter_list_i;
+    struct adapter *i;
 
     pa_assert(m);
 
     if (!(u = m->userdata))
         return;
 
-    while (u->adapter_list) {
-        adapter_list_i = u->adapter_list;
-        PA_LLIST_REMOVE(struct adapter, u->adapter_list, adapter_list_i);
-        adapter_free(adapter_list_i);
+    while ((i = u->adapter_list)) {
+        PA_LLIST_REMOVE(struct adapter, u->adapter_list, i);
+        adapter_free(i);
     }
 
-    pa_dbus_connection_unref(u->conn);
+    if (u->conn)
+        pa_dbus_connection_unref(u->conn);
+
     pa_xfree(u);
-    return;
 }
 
 int pa__init(pa_module* m) {
     DBusError err;
-    struct adapter *adapter_list_i;
-    struct device *device_list_i;
     struct userdata *u;
 
     pa_assert(m);
     dbus_error_init(&err);
-    m->userdata = u = pa_xnew0(struct userdata, 1);
+
+    m->userdata = u = pa_xnew(struct userdata, 1);
     u->module = m;
     PA_LLIST_HEAD_INIT(struct adapter, u->adapter_list);
 
     /* connect to the bus */
     u->conn = pa_dbus_bus_get(m->core, DBUS_BUS_SYSTEM, &err);
-    if ( dbus_error_is_set(&err) || (u->conn == NULL) ) {
+    if (dbus_error_is_set(&err) || (u->conn == NULL) ) {
         pa_log("Failed to get D-Bus connection: %s", err.message);
         goto fail;
     }
@@ -491,30 +768,21 @@ int pa__init(pa_module* m) {
     detect_adapters(u);
     detect_devices(u);
 
-    print_adapters(u->adapter_list);
-
-    /* load device modules */
-    adapter_list_i = u->adapter_list;
-    while (adapter_list_i != NULL) {
-        device_list_i = adapter_list_i->device_list;
-        while (device_list_i != NULL) {
-            pa_log_debug("Loading module-bt-device for %s", device_list_i->name);
-            /* TODO: call module */
-            device_list_i = device_list_i->next;
-        }
-        adapter_list_i = adapter_list_i->next;
-    }
+    print_adapters(u);
+    load_modules(u);
 
     /* dynamic detection of bluetooth audio devices */
     if (!dbus_connection_add_filter(pa_dbus_connection_get(u->conn), filter_cb, u, NULL)) {
         pa_log_error("Failed to add filter function");
         goto fail;
     }
+
     dbus_bus_add_match(pa_dbus_connection_get(u->conn), "type='signal',sender='org.bluez',interface='org.bluez.Manager'", &err);
     if (dbus_error_is_set(&err)) {
         pa_log_error("Unable to subscribe to org.bluez.Manager signals: %s: %s", err.name, err.message);
         goto fail;
     }
+
     dbus_bus_add_match(pa_dbus_connection_get(u->conn), "type='signal',sender='org.bluez',interface='org.bluez.Adapter'", &err);
     if (dbus_error_is_set(&err)) {
         pa_log_error("Unable to subscribe to org.bluez.Adapter signals: %s: %s", err.name, err.message);
@@ -526,5 +794,6 @@ int pa__init(pa_module* m) {
 fail:
     dbus_error_free(&err);
     pa__done(m);
+
     return -1;
 }

commit 564ef2b71fe67b58c5dfd6dd767467dad13f475e
Author: Stelian Ionescu <stelian.ionescu-zeus at poste.it>
Date:   Tue Sep 23 00:26:31 2008 +0200

    have make_random_dir respect $TMPDIR
    
    with the attached patch, make_random_dir first tries to use $TMPDIR,
    then $TMP finally defaulting to "/tmp"
    
    Signed-off-by: Lennart Poettering <lennart at poettering.net>

diff --git a/src/pulsecore/core-util.c b/src/pulsecore/core-util.c
index a9e2a70..d7c5caf 100644
--- a/src/pulsecore/core-util.c
+++ b/src/pulsecore/core-util.c
@@ -1315,31 +1315,43 @@ static char* make_random_dir(mode_t m) {
         "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
         "0123456789";
 
-    char fn[24] = "/tmp/pulse-";
+    const char *tmpdir;
+    char *fn;
+    size_t pathlen;
 
-    fn[sizeof(fn)-1] = 0;
+    if (!(tmpdir = getenv("TMPDIR")))
+        if (!(tmpdir = getenv("TMP")))
+            if (!(tmpdir = getenv("TEMP")))
+                tmpdir = getenv("TEMPDIR");
+
+    if (!tmpdir || !pa_is_path_absolute(tmpdir))
+        tmpdir = "/tmp";
+
+    fn = pa_sprintf_malloc("%s/pulse-XXXXXXXXXXXX", tmpdir);
+    pathlen = strlen(fn);
 
     for (;;) {
-        unsigned i;
+        size_t i;
         int r;
         mode_t u;
         int saved_errno;
 
-        for (i = 11; i < sizeof(fn)-1; i++)
+        for (i = pathlen - 12; i < pathlen; i++)
             fn[i] = table[rand() % (sizeof(table)-1)];
 
         u = umask((~m) & 0777);
         r = mkdir(fn, m);
+
         saved_errno = errno;
         umask(u);
+        errno = saved_errno;
 
         if (r >= 0)
-            return pa_xstrdup(fn);
-
-        errno = saved_errno;
+            return fn;
 
         if (errno != EEXIST) {
             pa_log_error("Failed to create random directory %s: %s", fn, pa_cstrerror(errno));
+            pa_xfree(fn);
             return NULL;
         }
     }

commit a84b72bf96745702ba59c678a973edc7504ee50e
Author: Nix <nix at esperi.org.uk>
Date:   Fri Sep 26 19:29:17 2008 +0100

    esound auth-ip-acl fix
    
    [...]
    
    iv) module-protocol-stub has a one-character typo that breaks
    auth-ip-acl for the esound TCP module, patch:
    
    Unbreak esound auth-ip-acl.
    
    Signed-off-by: Lennart Poettering <lennart at poettering.net>

diff --git a/src/modules/module-protocol-stub.c b/src/modules/module-protocol-stub.c
index 0e98b1c..aefd402 100644
--- a/src/modules/module-protocol-stub.c
+++ b/src/modules/module-protocol-stub.c
@@ -148,7 +148,7 @@
 #  include <pulsecore/esound.h>
 #  define TCPWRAP_SERVICE "esound"
 #  define IPV4_PORT ESD_DEFAULT_PORT
-#  define MODULE_ARGUMENTS_COMMON "sink", "source", "auth-anonymous", "cookie", "auth-cookie", "auth-cookie-enabled"
+#  define MODULE_ARGUMENTS_COMMON "sink", "source", "auth-anonymous", "cookie", "auth-cookie", "auth-cookie-enabled",
 
 #  ifdef USE_TCP_SOCKETS
 #    include "module-esound-protocol-tcp-symdef.h"

commit 79ad4e63f691d1280dde2eb6521a1572c78d03ce
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Oct 1 01:14:36 2008 +0200

    Make the shared memory segment size configurable
    
    This is useful only on systems where memory overcommit is not available
    or disabled.

diff --git a/man/pulse-client.conf.5.xml.in b/man/pulse-client.conf.5.xml.in
index ae8de1f..1d6f6fb 100644
--- a/man/pulse-client.conf.5.xml.in
+++ b/man/pulse-client.conf.5.xml.in
@@ -97,6 +97,15 @@ USA.
       <opt>no</opt>.</p>
     </option>
 
+    <option>
+      <p><opt>shm-size-bytes=</opt> Sets the shared memory segment
+      size for clients, in bytes. If left unspecified or is set to 0
+      it will default to some system-specific default, usually 64
+      MiB. Please note that usually there is no need to change this
+      value, unless you are running an OS kernel that does not do
+      memory overcommit.</p>
+    </option>
+
   </section>
 
   <section name="Authors">
diff --git a/man/pulse-daemon.conf.5.xml.in b/man/pulse-daemon.conf.5.xml.in
index ed158df..9d77abf 100644
--- a/man/pulse-daemon.conf.5.xml.in
+++ b/man/pulse-daemon.conf.5.xml.in
@@ -151,6 +151,15 @@ USA.
       argument takes precedence.</p>
     </option>
 
+    <option>
+      <p><opt>shm-size-bytes=</opt> Sets the shared memory segment
+      size for the daemon, in bytes. If left unspecified or is set to 0
+      it will default to some system-specific default, usually 64
+      MiB. Please note that usually there is no need to change this
+      value, unless you are running an OS kernel that does not do
+      memory overcommit.</p>
+    </option>
+
   </section>
 
   <section name="Scheduling">
diff --git a/src/daemon/daemon-conf.c b/src/daemon/daemon-conf.c
index 77da3f7..939b25d 100644
--- a/src/daemon/daemon-conf.c
+++ b/src/daemon/daemon-conf.c
@@ -84,7 +84,8 @@ static const pa_daemon_conf default_conf = {
     .disable_shm = FALSE,
     .default_n_fragments = 4,
     .default_fragment_size_msec = 25,
-    .default_sample_spec = { .format = PA_SAMPLE_S16NE, .rate = 44100, .channels = 2 }
+    .default_sample_spec = { .format = PA_SAMPLE_S16NE, .rate = 44100, .channels = 2 },
+    .shm_size = 0
 #ifdef HAVE_SYS_RESOURCE_H
    ,.rlimit_fsize = { .value = 0, .is_set = FALSE },
     .rlimit_data = { .value = 0, .is_set = FALSE },
@@ -429,6 +430,7 @@ int pa_daemon_conf_load(pa_daemon_conf *c, const char *filename) {
         { "disable-remixing",           pa_config_parse_bool,     NULL },
         { "disable-lfe-remixing",       pa_config_parse_bool,     NULL },
         { "load-default-script-file",   pa_config_parse_bool,     NULL },
+        { "shm-size-bytes",             pa_config_parse_size,     NULL },
 #ifdef HAVE_SYS_RESOURCE_H
         { "rlimit-fsize",               parse_rlimit,             NULL },
         { "rlimit-data",                parse_rlimit,             NULL },
@@ -494,65 +496,66 @@ int pa_daemon_conf_load(pa_daemon_conf *c, const char *filename) {
     table[26].data = &c->disable_remixing;
     table[27].data = &c->disable_lfe_remixing;
     table[28].data = &c->load_default_script_file;
+    table[29].data = &c->shm_size;
 #ifdef HAVE_SYS_RESOURCE_H
-    table[29].data = &c->rlimit_fsize;
-    table[30].data = &c->rlimit_data;
-    table[31].data = &c->rlimit_stack;
-    table[32].data = &c->rlimit_as;
-    table[33].data = &c->rlimit_core;
-    table[34].data = &c->rlimit_nofile;
-    table[35].data = &c->rlimit_as;
+    table[30].data = &c->rlimit_fsize;
+    table[31].data = &c->rlimit_data;
+    table[32].data = &c->rlimit_stack;
+    table[33].data = &c->rlimit_as;
+    table[34].data = &c->rlimit_core;
+    table[35].data = &c->rlimit_nofile;
+    table[36].data = &c->rlimit_as;
 #ifdef RLIMIT_NPROC
-    table[36].data = &c->rlimit_nproc;
+    table[37].data = &c->rlimit_nproc;
 #endif
 
 #ifdef RLIMIT_MEMLOCK
 #ifndef RLIMIT_NPROC
 #error "Houston, we have a numbering problem!"
 #endif
-    table[37].data = &c->rlimit_memlock;
+    table[38].data = &c->rlimit_memlock;
 #endif
 
 #ifdef RLIMIT_LOCKS
 #ifndef RLIMIT_MEMLOCK
 #error "Houston, we have a numbering problem!"
 #endif
-    table[38].data = &c->rlimit_locks;
+    table[39].data = &c->rlimit_locks;
 #endif
 
 #ifdef RLIMIT_SIGPENDING
 #ifndef RLIMIT_LOCKS
 #error "Houston, we have a numbering problem!"
 #endif
-    table[39].data = &c->rlimit_sigpending;
+    table[40].data = &c->rlimit_sigpending;
 #endif
 
 #ifdef RLIMIT_MSGQUEUE
 #ifndef RLIMIT_SIGPENDING
 #error "Houston, we have a numbering problem!"
 #endif
-    table[40].data = &c->rlimit_msgqueue;
+    table[41].data = &c->rlimit_msgqueue;
 #endif
 
 #ifdef RLIMIT_NICE
 #ifndef RLIMIT_MSGQUEUE
 #error "Houston, we have a numbering problem!"
 #endif
-    table[41].data = &c->rlimit_nice;
+    table[42].data = &c->rlimit_nice;
 #endif
 
 #ifdef RLIMIT_RTPRIO
 #ifndef RLIMIT_NICE
 #error "Houston, we have a numbering problem!"
 #endif
-    table[42].data = &c->rlimit_rtprio;
+    table[43].data = &c->rlimit_rtprio;
 #endif
 
 #ifdef RLIMIT_RTTIME
 #ifndef RLIMIT_RTTIME
 #error "Houston, we have a numbering problem!"
 #endif
-    table[43].data = &c->rlimit_rttime;
+    table[44].data = &c->rlimit_rttime;
 #endif
 #endif
 
@@ -670,6 +673,7 @@ char *pa_daemon_conf_dump(pa_daemon_conf *c) {
     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);
+    pa_strbuf_printf(s, "shm-size-bytes = %lu\n", (unsigned long) c->shm_size);
 #ifdef HAVE_SYS_RESOURCE_H
     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-data = %li\n", c->rlimit_data.is_set ? (long int) c->rlimit_data.value : -1);
diff --git a/src/daemon/daemon-conf.h b/src/daemon/daemon-conf.h
index 309a142..9032926 100644
--- a/src/daemon/daemon-conf.h
+++ b/src/daemon/daemon-conf.h
@@ -111,6 +111,7 @@ typedef struct pa_daemon_conf {
 
     unsigned default_n_fragments, default_fragment_size_msec;
     pa_sample_spec default_sample_spec;
+    size_t shm_size;
 } 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 ea09fe0..4362e1c 100644
--- a/src/daemon/daemon.conf.in
+++ b/src/daemon/daemon.conf.in
@@ -26,6 +26,7 @@
 ; use-pid-file = yes
 ; system-instance = no
 ; disable-shm = no
+; shm-size-bytes = 0 # setting this 0 will use the system-default, usually 64 MiB
 
 ; high-priority = yes
 ; nice-level = -11
diff --git a/src/daemon/main.c b/src/daemon/main.c
index a9e8ed4..53f5d19 100644
--- a/src/daemon/main.c
+++ b/src/daemon/main.c
@@ -854,7 +854,7 @@ int main(int argc, char *argv[]) {
 
     pa_assert_se(mainloop = pa_mainloop_new());
 
-    if (!(c = pa_core_new(pa_mainloop_get_api(mainloop), !conf->disable_shm))) {
+    if (!(c = pa_core_new(pa_mainloop_get_api(mainloop), !conf->disable_shm, conf->shm_size))) {
         pa_log(_("pa_core_new() failed."));
         goto finish;
     }
diff --git a/src/pulse/client-conf.c b/src/pulse/client-conf.c
index 739ef16..58d6464 100644
--- a/src/pulse/client-conf.c
+++ b/src/pulse/client-conf.c
@@ -61,6 +61,7 @@ static const pa_client_conf default_conf = {
     .disable_shm = FALSE,
     .cookie_file = NULL,
     .cookie_valid = FALSE,
+    .shm_size = 0
 };
 
 pa_client_conf *pa_client_conf_new(void) {
@@ -99,6 +100,7 @@ int pa_client_conf_load(pa_client_conf *c, const char *filename) {
         { "autospawn",              pa_config_parse_bool,    NULL },
         { "cookie-file",            pa_config_parse_string,  NULL },
         { "disable-shm",            pa_config_parse_bool,    NULL },
+        { "shm-size-bytes",         pa_config_parse_size,    NULL },
         { NULL,                     NULL,                    NULL },
     };
 
@@ -110,6 +112,7 @@ int pa_client_conf_load(pa_client_conf *c, const char *filename) {
     table[5].data = &c->autospawn;
     table[6].data = &c->cookie_file;
     table[7].data = &c->disable_shm;
+    table[8].data = &c->shm_size;
 
     if (filename) {
 
diff --git a/src/pulse/client-conf.h b/src/pulse/client-conf.h
index 699279a..4eac467 100644
--- a/src/pulse/client-conf.h
+++ b/src/pulse/client-conf.h
@@ -31,6 +31,7 @@ typedef struct pa_client_conf {
     pa_bool_t autospawn, disable_shm;
     uint8_t cookie[PA_NATIVE_COOKIE_LENGTH];
     pa_bool_t cookie_valid; /* non-zero, when cookie is valid */
+    size_t shm_size;
 } pa_client_conf;
 
 /* Create a new configuration data object and reset it to defaults */
diff --git a/src/pulse/client.conf.in b/src/pulse/client.conf.in
index 8339d65..579bcc2 100644
--- a/src/pulse/client.conf.in
+++ b/src/pulse/client.conf.in
@@ -30,3 +30,4 @@
 ; cookie-file =
 
 ; disable-shm = no
+; shm-size-bytes = 0 # setting this 0 will use the system-default, usually 64 MiB
diff --git a/src/pulse/context.c b/src/pulse/context.c
index 154e5fa..3145d9c 100644
--- a/src/pulse/context.c
+++ b/src/pulse/context.c
@@ -174,10 +174,10 @@ pa_context *pa_context_new_with_proplist(pa_mainloop_api *mainloop, const char *
     pa_client_conf_load(c->conf, NULL);
     pa_client_conf_env(c->conf);
 
-    if (!(c->mempool = pa_mempool_new(!c->conf->disable_shm))) {
+    if (!(c->mempool = pa_mempool_new(!c->conf->disable_shm, c->conf->shm_size))) {
 
         if (!c->conf->disable_shm)
-            c->mempool = pa_mempool_new(FALSE);
+            c->mempool = pa_mempool_new(FALSE, c->conf->shm_size);
 
         if (!c->mempool) {
             context_free(c);
diff --git a/src/pulsecore/conf-parser.c b/src/pulsecore/conf-parser.c
index 6b0e1d5..58ceab9 100644
--- a/src/pulsecore/conf-parser.c
+++ b/src/pulsecore/conf-parser.c
@@ -166,6 +166,24 @@ int pa_config_parse_int(const char *filename, unsigned line, const char *lvalue,
     return 0;
 }
 
+int pa_config_parse_size(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata) {
+    size_t *i = data;
+    uint32_t k;
+
+    pa_assert(filename);
+    pa_assert(lvalue);
+    pa_assert(rvalue);
+    pa_assert(data);
+
+    if (pa_atou(rvalue, &k) < 0) {
+        pa_log("[%s:%u] Failed to parse numeric value: %s", filename, line, rvalue);
+        return -1;
+    }
+
+    *i = (size_t) k;
+    return 0;
+}
+
 int pa_config_parse_bool(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata) {
     int k;
     pa_bool_t *b = data;
diff --git a/src/pulsecore/conf-parser.h b/src/pulsecore/conf-parser.h
index 7eb1fae..a5174fc 100644
--- a/src/pulsecore/conf-parser.h
+++ b/src/pulsecore/conf-parser.h
@@ -39,8 +39,9 @@ typedef struct pa_config_item {
  * NULL */
 int pa_config_parse(const char *filename, FILE *f, const pa_config_item *t, void *userdata);
 
-/* Generic parsers for integers, booleans and strings */
+/* Generic parsers for integers, size_t, booleans and strings */
 int pa_config_parse_int(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata);
+int pa_config_parse_size(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata);
 int pa_config_parse_bool(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata);
 int pa_config_parse_string(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, void *userdata);
 
diff --git a/src/pulsecore/core.c b/src/pulsecore/core.c
index bd956ae..5761bbc 100644
--- a/src/pulsecore/core.c
+++ b/src/pulsecore/core.c
@@ -66,7 +66,7 @@ static int core_process_msg(pa_msgobject *o, int code, void *userdata, int64_t o
 
 static void core_free(pa_object *o);
 
-pa_core* pa_core_new(pa_mainloop_api *m, int shared) {
+pa_core* pa_core_new(pa_mainloop_api *m, pa_bool_t shared, size_t shm_size) {
     pa_core* c;
     pa_mempool *pool;
     int j;
@@ -74,14 +74,14 @@ pa_core* pa_core_new(pa_mainloop_api *m, int shared) {
     pa_assert(m);
 
     if (shared) {
-        if (!(pool = pa_mempool_new(shared))) {
+        if (!(pool = pa_mempool_new(shared, shm_size))) {
             pa_log_warn("failed to allocate shared memory pool. Falling back to a normal memory pool.");
-            shared = 0;
+            shared = FALSE;
         }
     }
 
     if (!shared) {
-        if (!(pool = pa_mempool_new(shared))) {
+        if (!(pool = pa_mempool_new(shared, shm_size))) {
             pa_log("pa_mempool_new() failed.");
             return NULL;
         }
diff --git a/src/pulsecore/core.h b/src/pulsecore/core.h
index fb4490f..3955908 100644
--- a/src/pulsecore/core.h
+++ b/src/pulsecore/core.h
@@ -141,7 +141,7 @@ enum {
     PA_CORE_MESSAGE_MAX
 };
 
-pa_core* pa_core_new(pa_mainloop_api *m, int shared);
+pa_core* pa_core_new(pa_mainloop_api *m, pa_bool_t shared, size_t shm_size);
 
 /* Check whether noone is connected to this core */
 void pa_core_check_idle(pa_core *c);
diff --git a/src/pulsecore/memblock.c b/src/pulsecore/memblock.c
index 6d12acd..400a4e1 100644
--- a/src/pulsecore/memblock.c
+++ b/src/pulsecore/memblock.c
@@ -680,8 +680,9 @@ static void memblock_replace_import(pa_memblock *b) {
         pa_mutex_unlock(seg->import->mutex);
 }
 
-pa_mempool* pa_mempool_new(pa_bool_t shared) {
+pa_mempool* pa_mempool_new(pa_bool_t shared, size_t size) {
     pa_mempool *p;
+    char t1[64], t2[64];
 
     p = pa_xnew(pa_mempool, 1);
 
@@ -692,13 +693,26 @@ pa_mempool* pa_mempool_new(pa_bool_t shared) {
     if (p->block_size < PA_PAGE_SIZE)
         p->block_size = PA_PAGE_SIZE;
 
-    p->n_blocks = PA_MEMPOOL_SLOTS_MAX;
+    if (size <= 0)
+        p->n_blocks = PA_MEMPOOL_SLOTS_MAX;
+    else {
+        p->n_blocks = (unsigned) (size / p->block_size);
+
+        if (p->n_blocks < 2)
+            p->n_blocks = 2;
+    }
 
     if (pa_shm_create_rw(&p->memory, p->n_blocks * p->block_size, shared, 0700) < 0) {
         pa_xfree(p);
         return NULL;
     }
 
+    pa_log_debug("Using %s memory pool with %u slots of size %s each, total size is %s",
+                 p->memory.shared ? "shared" : "private",
+                 p->n_blocks,
+                 pa_bytes_snprint(t1, sizeof(t1), (unsigned) p->block_size),
+                 pa_bytes_snprint(t2, sizeof(t2), (unsigned) (p->n_blocks * p->block_size)));
+
     memset(&p->stat, 0, sizeof(p->stat));
     pa_atomic_store(&p->n_init, 0);
 
diff --git a/src/pulsecore/memblock.h b/src/pulsecore/memblock.h
index efe55b0..b1eab2a 100644
--- a/src/pulsecore/memblock.h
+++ b/src/pulsecore/memblock.h
@@ -117,7 +117,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(pa_bool_t shared);
+pa_mempool* pa_mempool_new(pa_bool_t shared, size_t size);
 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);
diff --git a/src/tests/envelope-test.c b/src/tests/envelope-test.c
index d71eff1..4a72f5a 100644
--- a/src/tests/envelope-test.c
+++ b/src/tests/envelope-test.c
@@ -205,7 +205,7 @@ int main(int argc, char *argv[]) {
     oil_init();
     pa_log_set_maximal_level(PA_LOG_DEBUG);
 
-    pa_assert_se(pool = pa_mempool_new(FALSE));
+    pa_assert_se(pool = pa_mempool_new(FALSE, 0));
     pa_assert_se(envelope = pa_envelope_new(&ss));
 
     block = generate_block(pool, &ss);
diff --git a/src/tests/mcalign-test.c b/src/tests/mcalign-test.c
index c066582..92e3e14 100644
--- a/src/tests/mcalign-test.c
+++ b/src/tests/mcalign-test.c
@@ -41,7 +41,7 @@ int main(int argc, char *argv[]) {
     pa_mcalign *a;
     pa_memchunk c;
 
-    p = pa_mempool_new(0);
+    p = pa_mempool_new(FALSE, 0);
 
     a = pa_mcalign_new(11);
 
diff --git a/src/tests/memblock-test.c b/src/tests/memblock-test.c
index 6da1b1e..37b5b40 100644
--- a/src/tests/memblock-test.c
+++ b/src/tests/memblock-test.c
@@ -78,9 +78,9 @@ int main(int argc, char *argv[]) {
 
     const char txt[] = "This is a test!";
 
-    pool_a = pa_mempool_new(1);
-    pool_b = pa_mempool_new(1);
-    pool_c = pa_mempool_new(1);
+    pool_a = pa_mempool_new(TRUE, 0);
+    pool_b = pa_mempool_new(TRUE, 0);
+    pool_c = pa_mempool_new(TRUE, 0);
 
     pa_mempool_get_shm_id(pool_a, &id_a);
     pa_mempool_get_shm_id(pool_b, &id_b);
diff --git a/src/tests/memblockq-test.c b/src/tests/memblockq-test.c
index 7bf992a..c53945b 100644
--- a/src/tests/memblockq-test.c
+++ b/src/tests/memblockq-test.c
@@ -63,7 +63,7 @@ int main(int argc, char *argv[]) {
 
     pa_log_set_maximal_level(PA_LOG_DEBUG);
 
-    p = pa_mempool_new(0);
+    p = pa_mempool_new(FALSE, 0);
 
     silence.memblock = pa_memblock_new_fixed(p, (char*)  "__", 2, 1);
     assert(silence.memblock);
diff --git a/src/tests/mix-test.c b/src/tests/mix-test.c
index 544121f..759d769 100644
--- a/src/tests/mix-test.c
+++ b/src/tests/mix-test.c
@@ -201,7 +201,7 @@ int main(int argc, char *argv[]) {
     oil_init();
     pa_log_set_maximal_level(PA_LOG_DEBUG);
 
-    pa_assert_se(pool = pa_mempool_new(FALSE));
+    pa_assert_se(pool = pa_mempool_new(FALSE, 0));
 
     a.channels = 1;
     a.rate = 44100;
diff --git a/src/tests/remix-test.c b/src/tests/remix-test.c
index 4777c15..3538d7d 100644
--- a/src/tests/remix-test.c
+++ b/src/tests/remix-test.c
@@ -58,7 +58,7 @@ int main(int argc, char *argv[]) {
     oil_init();
     pa_log_set_maximal_level(PA_LOG_DEBUG);
 
-    pa_assert_se(pool = pa_mempool_new(FALSE));
+    pa_assert_se(pool = pa_mempool_new(FALSE, 0));
 
     for (i = 0; maps[i].channels > 0; i++)
         for (j = 0; maps[j].channels > 0; j++) {
diff --git a/src/tests/resampler-test.c b/src/tests/resampler-test.c
index 6959127..2d59186 100644
--- a/src/tests/resampler-test.c
+++ b/src/tests/resampler-test.c
@@ -201,7 +201,7 @@ int main(int argc, char *argv[]) {
     oil_init();
     pa_log_set_maximal_level(PA_LOG_DEBUG);
 
-    pa_assert_se(pool = pa_mempool_new(FALSE));
+    pa_assert_se(pool = pa_mempool_new(FALSE, 0));
 
     a.channels = b.channels = 1;
     a.rate = b.rate = 44100;

commit d299ac5d934bb702061647018ef8cdced3c63bf6
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Oct 1 01:15:44 2008 +0200

    Some man page updates, add missing documentation, other fixes.

diff --git a/man/pulse-client.conf.5.xml.in b/man/pulse-client.conf.5.xml.in
index 1d6f6fb..26e3890 100644
--- a/man/pulse-client.conf.5.xml.in
+++ b/man/pulse-client.conf.5.xml.in
@@ -31,15 +31,15 @@ USA.
 
   <description>
     <p>The PulseAudio client library reads configuration directives from
-    a file <file>~/.pulse/client.conf</file> on startup, and when that
+    a file <file>~/.pulse/client.conf</file> on startup and when that
     file doesn't exist from
     <file>@pulseconfdir@/client.conf</file>.</p>
 
     <p>The configuration file is a simple collection of variable
     declarations. If the configuration file parser encounters either ;
-    or # for it ignores the rest of the line until its end.</p>
+    or # it ignores the rest of the line until its end.</p>
 
-    <p>For the settings that take a boolean argument, the values
+    <p>For the settings that take a boolean argument the values
     <opt>true</opt>, <opt>yes</opt>, <opt>on</opt> and <opt>1</opt>
     are equivalent, resp. <opt>false</opt>, <opt>no</opt>,
     <opt>off</opt>, <opt>0</opt>.</p>
@@ -69,7 +69,7 @@ USA.
 
     <option>
       <p><opt>autospawn=</opt> Autospawn a PulseAudio daemon when
-      needed. Takes a boolean value, defaults to "no".</p>
+      needed. Takes a boolean value, defaults to "yes".</p>
     </option>
 
     <option>
@@ -81,7 +81,7 @@ USA.
     <option>
       <p><opt>extra-arguments=</opt> Extra arguments to pass to the
       PulseAudio daemon when autospawning. Defaults to
-      <opt>--log-target=syslog --exit-idle-time=5</opt>
+      <opt>--log-target=syslog</opt>
       </p>
     </option>
 
diff --git a/man/pulse-daemon.conf.5.xml.in b/man/pulse-daemon.conf.5.xml.in
index 9d77abf..a516ee3 100644
--- a/man/pulse-daemon.conf.5.xml.in
+++ b/man/pulse-daemon.conf.5.xml.in
@@ -31,7 +31,7 @@ USA.
 
   <description>
     <p>The PulseAudio sound server reads configuration directives from
-    a file <file>~/.pulse/daemon.conf</file> on startup, and when that
+    a file <file>~/.pulse/daemon.conf</file> on startup and when that
     file doesn't exist from
     <file>@pulseconfdir@/daemon.conf</file>. Please note that the
     server also reads a configuration script on startup
@@ -40,9 +40,9 @@ USA.
 
     <p>The configuration file is a simple collection of variable
     declarations. If the configuration file parser encounters either ;
-    or # for it ignores the rest of the line until its end.</p>
+    or # it ignores the rest of the line until its end.</p>
 
-    <p>For the settings that take a boolean argument, the values
+    <p>For the settings that take a boolean argument the values
     <opt>true</opt>, <opt>yes</opt>, <opt>on</opt> and <opt>1</opt>
     are equivalent, resp. <opt>false</opt>, <opt>no</opt>,
     <opt>off</opt>, <opt>0</opt>.</p>
@@ -77,6 +77,11 @@ USA.
     </option>
 
     <option>
+      <p><opt>disallow-exit=</opt> Disallow exit on user
+      request. Defaults to <opt>no</opt>.</p>
+    </option>
+
+    <option>
       <p><opt>resample-method=</opt> The resampling algorithm to
       use. Use one of <opt>src-sinc-best-quality</opt>,
       <opt>src-sinc-medium-quality</opt>, <opt>src-sinc-fastest</opt>,
@@ -112,7 +117,7 @@ USA.
       available as well. If no input LFE channel is available the
       output LFE channel will always be 0. If no output LFE channel is
       available the signal on the input LFE channel will be
-      ignored.</p>
+      ignored. Defaults to "on".</p>
     </option>
 
     <option>
@@ -249,9 +254,17 @@ USA.
       default script file. The default behaviour is to load
       <file>~/.pulse/default.pa</file>, and if that file does not
       exist fall back to the system wide installed version
-      <file>@pulseconfdir@/default.pa</file>. If <opt>-n</opt> is
-      passed on the command line the default configuration script is
-      ignored.</p>
+      <file>@pulseconfdir@/default.pa</file>. If run in system-wide
+      mode the file <file>@pulseconfdir@/system.pa</file> is used
+      instead. If <opt>-n</opt> is passed on the command line
+      or <opt>default-script-file=</opt> is disabled the default
+      configuration script is ignored.</p>
+    </option>
+
+    <option>
+      <p><opt>default-script-file=</opt> Load the default
+      configuration script file as specified
+      in <opt>default-script-file=</opt>. Defaults to "yes".</p>
     </option>
 
   </section>
@@ -291,6 +304,9 @@ USA.
       <p><opt>rlimit-as</opt> Defaults to -1.</p>
     </option>
     <option>
+      <p><opt>rlimit-rss</opt> Defaults to -1.</p>
+    </option>
+    <option>
       <p><opt>rlimit-core</opt> Defaults to -1.</p>
     </option>
     <option>
@@ -309,6 +325,15 @@ USA.
       <p><opt>rlimit-nproc</opt> Defaults to -1.</p>
     </option>
     <option>
+      <p><opt>rlimit-locks</opt> Defaults to -1.</p>
+    </option>
+    <option>
+      <p><opt>rlimit-sigpending</opt> Defaults to -1.</p>
+    </option>
+    <option>
+      <p><opt>rlimit-msgqueue</opt> Defaults to -1.</p>
+    </option>
+    <option>
       <p><opt>rlimit-memlock</opt> Defaults to 16 KiB. Please note
       that the JACK client libraries may require more locked
       memory.</p>
@@ -326,6 +351,9 @@ USA.
       <opt>realtime-scheduling</opt> is enabled. The JACK client
       libraries require a real-time prority of 9 by default. </p>
     </option>
+    <option>
+      <p><opt>rlimit-rttime</opt> Defaults to 1000000.</p>
+    </option>
 
   </section>
 

commit 00b70a8bdbadeada75ee3fa0fadb79a8a5fddf95
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Oct 1 01:16:43 2008 +0200

    follow PropertyChanged signals from BlueZ

diff --git a/src/modules/bluetooth/module-bluetooth-discover.c b/src/modules/bluetooth/module-bluetooth-discover.c
index e0a760f..1494431 100644
--- a/src/modules/bluetooth/module-bluetooth-discover.c
+++ b/src/modules/bluetooth/module-bluetooth-discover.c
@@ -180,16 +180,14 @@ static struct adapter* adapter_find(struct userdata *u, const char *path) {
     return NULL;
 }
 
-static struct device* device_find(struct userdata *u, const char *adapter, const char *path) {
-    struct adapter *a;
+static struct device* device_find(struct userdata *u, const char *path) {
+    struct adapter *j;
     struct device *i;
 
-    if (!(a = adapter_find(u, adapter)))
-        return NULL;
-
-    for (i = a->device_list; i; i = i->next)
-        if (pa_streq(i->object_path, path))
-            return i;
+    for (j = u->adapter_list; j; j = j->next)
+        for (i = j->device_list; i; i = i->next)
+            if (pa_streq(i->object_path, path))
+                return i;
 
     return NULL;
 }
@@ -285,6 +283,12 @@ static void load_module_for_device(struct userdata *u, struct device *d) {
     pa_assert(u);
     pa_assert(d);
 
+    /* Check whether we already loaded a module for this device */
+    if (d->module_index != PA_INVALID_INDEX &&
+        pa_idxset_get_by_index(u->module->core->modules, d->module_index))
+        return;
+
+    /* Check whether this is an audio device */
     if (!d->audio_profile) {
         pa_log_debug("Ignoring %s since it is not an audio device.", d->object_path);
         return;
@@ -313,6 +317,52 @@ static void load_modules(struct userdata *u) {
             load_module_for_device(u, d);
 }
 
+static int parse_adapter_property(struct userdata *u, struct adapter *a, DBusMessageIter *i) {
+    const char *key;
+    DBusMessageIter variant_i;
+
+    pa_assert(u);
+    pa_assert(a);
+    pa_assert(i);
+
+    if (dbus_message_iter_get_arg_type(i) != DBUS_TYPE_STRING) {
+        pa_log("Property name not a string.");
+        return -1;
+    }
+
+    dbus_message_iter_get_basic(i, &key);
+
+    if (!dbus_message_iter_next(i)) {
+        pa_log("Property value missing");
+        return -1;
+    }
+
+    if (dbus_message_iter_get_arg_type(i) != DBUS_TYPE_VARIANT) {
+        pa_log("Property value not a variant.");
+        return -1;
+    }
+
+    dbus_message_iter_recurse(i, &variant_i);
+
+    if (dbus_message_iter_get_arg_type(&variant_i) == DBUS_TYPE_STRING) {
+        const char *value;
+        dbus_message_iter_get_basic(&variant_i, &value);
+
+        if (pa_streq(key, "Mode")) {
+            pa_xfree(a->mode);
+            a->mode = pa_xstrdup(value);
+        } else if (pa_streq(key, "Address")) {
+            pa_xstrdup(a->address);
+            a->address = pa_xstrdup(value);
+        } else if (pa_streq(key, "Name")) {
+            pa_xfree(a->name);
+            a->name = pa_xstrdup(value);
+        }
+    }
+
+    return 0;
+}
+
 static int get_adapter_properties(struct userdata *u, struct adapter *a) {
     DBusError e;
     DBusMessage *m = NULL, *r = NULL;
@@ -346,36 +396,12 @@ static int get_adapter_properties(struct userdata *u, struct adapter *a) {
     while (dbus_message_iter_get_arg_type(&element_i) != DBUS_TYPE_INVALID) {
 
         if (dbus_message_iter_get_arg_type(&element_i) == DBUS_TYPE_DICT_ENTRY) {
-            const char *key;
-            DBusMessageIter dict_i, variant_i;
+            DBusMessageIter dict_i;
 
             dbus_message_iter_recurse(&element_i, &dict_i);
 
-            if (dbus_message_iter_get_arg_type(&dict_i) != DBUS_TYPE_STRING) {
-                pa_log("Property name not a string.");
-                goto finish;
-            }
-
-            dbus_message_iter_get_basic(&dict_i, &key);
-
-            if (!dbus_message_iter_next(&dict_i)) {
-                pa_log("Dictionary item missing");
+            if (parse_adapter_property(u, a, &dict_i) < 0)
                 goto finish;
-            }
-
-            dbus_message_iter_recurse(&dict_i, &variant_i);
-
-            if (dbus_message_iter_get_arg_type(&variant_i) == DBUS_TYPE_STRING) {
-                const char *value;
-                dbus_message_iter_get_basic(&variant_i, &value);
-
-                if (pa_streq(key, "Mode"))
-                    a->mode = pa_xstrdup(value);
-                else if (pa_streq(key, "Address"))
-                    a->address = pa_xstrdup(value);
-                else if (pa_streq(key, "Name"))
-                    a->name = pa_xstrdup(value);
-            }
         }
 
         if (!dbus_message_iter_next(&element_i))
@@ -456,10 +482,124 @@ finish:
     return ret;
 }
 
+static int parse_device_property(struct userdata *u, struct device *d, DBusMessageIter *i) {
+    const char *key;
+    DBusMessageIter variant_i;
+
+    pa_assert(u);
+    pa_assert(d);
+    pa_assert(i);
+
+    if (dbus_message_iter_get_arg_type(i) != DBUS_TYPE_STRING) {
+        pa_log("Property name not a string.");
+        return -1;
+    }
+
+    dbus_message_iter_get_basic(i, &key);
+
+    if (!dbus_message_iter_next(i))  {
+        pa_log("Property value missing");
+        return -1;
+    }
+
+    if (dbus_message_iter_get_arg_type(i) != DBUS_TYPE_VARIANT) {
+        pa_log("Property value not a variant.");
+        return -1;
+    }
+
+    dbus_message_iter_recurse(i, &variant_i);
+
+    pa_log_debug("Parsing device property %s", key);
+
+    switch (dbus_message_iter_get_arg_type(&variant_i)) {
+
+        case DBUS_TYPE_STRING: {
+
+            const char *value;
+            dbus_message_iter_get_basic(&variant_i, &value);
+
+            if (pa_streq(key, "Name")) {
+                pa_xfree(d->name);
+                d->name = pa_xstrdup(value);
+            } else if (pa_streq(key, "Alias")) {
+                pa_xfree(d->alias);
+                d->alias = pa_xstrdup(value);
+            } else if (pa_streq(key, "Address")) {
+                pa_xfree(d->address);
+                d->address = pa_xstrdup(value);
+            }
+
+            break;
+        }
+
+        case DBUS_TYPE_BOOLEAN: {
+
+            dbus_bool_t value;
+            dbus_message_iter_get_basic(&variant_i, &value);
+
+            if (pa_streq(key, "Paired"))
+                d->paired = !!value;
+            else if (pa_streq(key, "Connected"))
+                d->connected = !!value;
+            else if (pa_streq(key, "Trusted"))
+                d->trusted = !!value;
+
+            break;
+        }
+
+        case DBUS_TYPE_UINT32: {
+
+            uint32_t value;
+            dbus_message_iter_get_basic(&variant_i, &value);
+
+            if (pa_streq(key, "Class"))
+                d->class = (int) value;
+
+            break;
+        }
+
+        case DBUS_TYPE_ARRAY: {
+
+            DBusMessageIter ai;
+            dbus_message_iter_recurse(&variant_i, &ai);
+
+            if (dbus_message_iter_get_arg_type(&ai) == DBUS_TYPE_STRING &&
+                pa_streq(key, "UUIDs")) {
+
+                d->audio_profile = NULL;
+
+                while (dbus_message_iter_get_arg_type(&ai) != DBUS_TYPE_INVALID) {
+                    struct uuid *node;
+                    const char *value;
+
+                    dbus_message_iter_get_basic(&ai, &value);
+                    node = uuid_new(value);
+                    PA_LLIST_PREPEND(struct uuid, d->uuid_list, node);
+
+                    if ((strcasecmp(value, A2DP_SOURCE_UUID) == 0) ||
+                        (strcasecmp(value, A2DP_SINK_UUID) == 0))
+                        d->audio_profile = "a2dp";
+                    else if (((strcasecmp(value, HSP_HS_UUID) == 0) ||
+                              (strcasecmp(value, HFP_HS_UUID) == 0)) &&
+                             !d->audio_profile)
+                        d->audio_profile = "hsp";
+
+                    if (!dbus_message_iter_next(&ai))
+                        break;
+                }
+            }
+
+            break;
+        }
+    }
+
+    return 0;
+}
+
 static int get_device_properties(struct userdata *u, struct device *d) {
     DBusError e;
     DBusMessage *m = NULL, *r = NULL;
-    DBusMessageIter arg_i, element_i, dict_i, variant_i;
+    DBusMessageIter arg_i, element_i;
     int ret = -1;
 
     pa_assert(u);
@@ -488,60 +628,14 @@ static int get_device_properties(struct userdata *u, struct device *d) {
 
     dbus_message_iter_recurse(&arg_i, &element_i);
     while (dbus_message_iter_get_arg_type(&element_i) != DBUS_TYPE_INVALID) {
+
         if (dbus_message_iter_get_arg_type(&element_i) == DBUS_TYPE_DICT_ENTRY) {
-            const char *value, *key;
-            int32_t ivalue;
+            DBusMessageIter dict_i;
 
             dbus_message_iter_recurse(&element_i, &dict_i);
-            dbus_message_iter_get_basic(&dict_i, &key);
-            dbus_message_iter_next(&dict_i);
 
-            dbus_message_iter_recurse(&dict_i, &variant_i);
-            if (pa_streq(key, "Name")) {
-                dbus_message_iter_get_basic(&variant_i, &value);
-                d->name = pa_xstrdup(value);
-            } else if (pa_streq(key, "Paired")) {
-                dbus_message_iter_get_basic(&variant_i, &ivalue);
-                d->paired = ivalue;
-            } else if (pa_streq(key, "Alias")) {
-                dbus_message_iter_get_basic(&variant_i, &value);
-                d->alias = pa_xstrdup(value);
-            } else if (pa_streq(key, "Connected")) {
-                dbus_message_iter_get_basic(&variant_i, &ivalue);
-                d->connected = ivalue;
-            } else if (pa_streq(key, "UUIDs")) {
-                DBusMessageIter uuid_i;
-
-                dbus_message_iter_recurse(&variant_i, &uuid_i);
-                while (dbus_message_iter_get_arg_type(&uuid_i) != DBUS_TYPE_INVALID) {
-
-                    struct uuid *node;
-                    dbus_message_iter_get_basic(&uuid_i, &value);
-                    node = uuid_new(value);
-                    PA_LLIST_PREPEND(struct uuid, d->uuid_list, node);
-
-                    if ((strcasecmp(value, A2DP_SOURCE_UUID) == 0) ||
-                        (strcasecmp(value, A2DP_SINK_UUID) == 0))
-                        d->audio_profile = "a2dp";
-                    else if (((strcasecmp(value, HSP_HS_UUID) == 0) ||
-                              (strcasecmp(value, HFP_HS_UUID) == 0)) &&
-                             !d->audio_profile)
-                        d->audio_profile = "hsp";
-
-                    if (!dbus_message_iter_next(&uuid_i))
-                        break;
-                }
-
-            } else if (pa_streq(key, "Address")) {
-                dbus_message_iter_get_basic(&variant_i, &value);
-                d->address = pa_xstrdup(value);
-            } else if (pa_streq(key, "Class")) {
-                dbus_message_iter_get_basic(&variant_i, &ivalue);
-                d->class = ivalue;
-            } else if (pa_streq(key, "Trusted")) {
-                dbus_message_iter_get_basic(&variant_i, &ivalue);
-                d->trusted = ivalue;
-            }
+            if (parse_device_property(u, d, &dict_i) < 0)
+                goto finish;
         }
 
         if (!dbus_message_iter_next(&element_i))
@@ -557,6 +651,7 @@ finish:
         dbus_message_unref(r);
 
     dbus_error_free(&e);
+
     return ret;
 }
 
@@ -636,6 +731,7 @@ static DBusHandlerResult filter_cb(DBusConnection *bus, DBusMessage *msg, void *
     pa_assert(msg);
     pa_assert(userdata);
     u = userdata;
+
     dbus_error_init(&err);
 
     pa_log_debug("dbus: interface=%s, path=%s, member=%s\n",
@@ -678,6 +774,17 @@ static DBusHandlerResult filter_cb(DBusConnection *bus, DBusMessage *msg, void *
             }
         }
 
+    } else if (dbus_message_is_signal(msg, "org.bluez.Adapter", "PropertyChanged")) {
+
+        if (!dbus_message_iter_init(msg, &arg_i))
+            pa_log("dbus: message has no parameters");
+        else {
+            struct adapter *a;
+
+            if ((a = adapter_find(u, dbus_message_get_path(msg))))
+                parse_adapter_property(u, a, &arg_i);
+        }
+
     } else if (dbus_message_is_signal(msg, "org.bluez.Adapter", "DeviceCreated")) {
 
         if (!dbus_message_iter_init(msg, &arg_i))
@@ -715,11 +822,27 @@ static DBusHandlerResult filter_cb(DBusConnection *bus, DBusMessage *msg, void *
             dbus_message_iter_get_basic(&arg_i, &value);
             pa_log_debug("hcid: device %s removed", value);
 
-            if ((d = device_find(u, dbus_message_get_path(msg), value))) {
+            if ((d = device_find(u, value))) {
                 PA_LLIST_REMOVE(struct device, d->adapter->device_list, d);
                 device_free(d);
             }
         }
+
+    } else if (dbus_message_is_signal(msg, "org.bluez.Device", "PropertyChanged")) {
+
+        if (!dbus_message_iter_init(msg, &arg_i))
+            pa_log("dbus: message has no parameters");
+        else {
+            struct device *d;
+
+            if ((d = device_find(u, dbus_message_get_path(msg)))) {
+                parse_device_property(u, d, &arg_i);
+
+                /* Hmm, something changed, let's try to reconnect if we
+                 * aren't connected yet */
+                load_module_for_device(u, d);
+            }
+        }
     }
 
     dbus_error_free(&err);
@@ -789,6 +912,12 @@ int pa__init(pa_module* m) {
         goto fail;
     }
 
+    dbus_bus_add_match(pa_dbus_connection_get(u->conn), "type='signal',sender='org.bluez',interface='org.bluez.Device'", &err);
+    if (dbus_error_is_set(&err)) {
+        pa_log_error("Unable to subscribe to org.bluez.Device signals: %s: %s", err.name, err.message);
+        goto fail;
+    }
+
     return 0;
 
 fail:

commit 0c3eb9f4786b0934e1bc48a52f25356307b55623
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Oct 1 01:19:01 2008 +0200

    fix typo in default.conf, closes bug #354

diff --git a/src/daemon/daemon.conf.in b/src/daemon/daemon.conf.in
index 4362e1c..c672d42 100644
--- a/src/daemon/daemon.conf.in
+++ b/src/daemon/daemon.conf.in
@@ -40,7 +40,7 @@
 
 ; dl-search-path = (depends on architecture)
 
-; load-defaul-script-file = yes
+; load-default-script-file = yes
 ; default-script-file = @PA_DEFAULT_CONFIG_FILE@
 
 ; log-target = auto

commit 6d7450462b8d33d099baa3ad7afb036291d76322
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Oct 1 01:23:35 2008 +0200

    it might be a bit too early to initialize bluetooth by default for now, since it's still very rough around the edges

diff --git a/src/daemon/default.pa.in b/src/daemon/default.pa.in
index 0af9931..7032038 100755
--- a/src/daemon/default.pa.in
+++ b/src/daemon/default.pa.in
@@ -49,9 +49,9 @@ load-module module-detect
 .endif
 
 ### Automatically load driver modules for Bluetooth hardware
-.ifexists module-bluetooth-discover at PA_SOEXT@
-load-module module-bluetooth-discover
-.endif
+#.ifexists module-bluetooth-discover at PA_SOEXT@
+#load-module module-bluetooth-discover
+#.endif
 
 ### Load several protocols
 .ifexists module-esound-protocol-unix at PA_SOEXT@

commit f04cfcd4f0ea1104c552a1712c5b98baf346e2ce
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Oct 1 01:24:47 2008 +0200

    replace module-volume-restore by module-stream-restore in system mode, too

diff --git a/src/daemon/system.pa.in b/src/daemon/system.pa.in
index f6052c4..27e4281 100755
--- a/src/daemon/system.pa.in
+++ b/src/daemon/system.pa.in
@@ -34,8 +34,9 @@ load-module module-esound-protocol-unix
 .endif
 load-module module-native-protocol-unix
 
-### Automatically restore the volume of playback streams
-load-module module-volume-restore
+### Automatically restore the volume of streams and devices
+load-module module-stream-restore
+load-module module-device-restore
 
 ### Automatically restore the default sink/source when changed by the user during runtime
 load-module module-default-device-restore

commit 644f39d261a4389a0ab19650eda7d8472074367b
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Oct 1 01:31:56 2008 +0200

    a few FreeBSD fixes, from alexis
    
    Signed-off-by: Lennart Poettering <lennart at poettering.net>

diff --git a/src/Makefile.am b/src/Makefile.am
index 14eb7f0..ff038a8 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -62,8 +62,8 @@ AM_CFLAGS += -DPA_MACHINE_ID=\"$(localstatedir)/lib/dbus/machine-id\"
 # This cool debug trap works on i386/gcc only
 AM_CFLAGS += '-DDEBUG_TRAP=__asm__("int $$3")'
 
-AM_LIBADD = $(PTHREAD_LIBS)
-AM_LDADD = $(PTHREAD_LIBS)
+AM_LIBADD = $(PTHREAD_LIBS) $(INTLLIBS)
+AM_LDADD = $(PTHREAD_LIBS) $(INTLLIBS)
 
 # Only required on some platforms but defined for all to avoid errors
 AM_LDFLAGS = -Wl,-no-undefined -Wl,--gc-sections
diff --git a/src/pulsecore/core-util.c b/src/pulsecore/core-util.c
index d7c5caf..0bc5cb4 100644
--- a/src/pulsecore/core-util.c
+++ b/src/pulsecore/core-util.c
@@ -2351,7 +2351,7 @@ int pa_reset_sigs(int except, ...) {
 int pa_reset_sigsv(const int except[]) {
     int sig;
 
-    for (sig = 1; sig < _NSIG; sig++) {
+    for (sig = 1; sig < NSIG; sig++) {
         pa_bool_t reset = TRUE;
 
         switch (sig) {
diff --git a/src/pulsecore/proplist-util.c b/src/pulsecore/proplist-util.c
index 6005775..4d505f5 100644
--- a/src/pulsecore/proplist-util.c
+++ b/src/pulsecore/proplist-util.c
@@ -37,7 +37,7 @@
 
 void pa_init_proplist(pa_proplist *p) {
     int a, b;
-#ifndef HAVE_DECL_ENVIRON
+#if !HAVE_DECL_ENVIRON
     extern char **environ;
 #endif
     char **e;
diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c
index 6ccee57..5c6dbf4 100644
--- a/src/pulsecore/protocol-native.c
+++ b/src/pulsecore/protocol-native.c
@@ -2192,6 +2192,7 @@ static void command_auth(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_ta
         if (c->version < 10 || (c->version >= 13 && !shm_on_remote))
             do_shm = FALSE;
 
+#ifdef HAVE_CREDS
     if (do_shm) {
         /* Only enable SHM if both sides are owned by the same
          * user. This is a security measure because otherwise data
@@ -2201,6 +2202,7 @@ static void command_auth(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_ta
         if (!(creds = pa_pdispatch_creds(pd)) || getuid() != creds->uid)
             do_shm = FALSE;
     }
+#endif
 
     pa_log_debug("Negotiated SHM: %s", pa_yes_no(do_shm));
     pa_pstream_enable_shm(c->pstream, do_shm);

commit 9e79c875a5629f64211dbf33dffb7a6c8abc3cc8
Merge: 644f39d... cd704f8...
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Oct 1 01:52:14 2008 +0200

    Merge commit 'coling/master'


commit c4bdc2fbbbd7bb03d71255052b77bad7b5a70fa8
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Oct 1 01:59:50 2008 +0200

    it's --daemonize, not --daemon

diff --git a/man/pulseaudio.1.xml.in b/man/pulseaudio.1.xml.in
index 0e008c3..df82824 100644
--- a/man/pulseaudio.1.xml.in
+++ b/man/pulseaudio.1.xml.in
@@ -127,7 +127,7 @@ USA.
     </option>
 
     <option>
-      <p><opt>-D | --daemon</opt><arg>[=BOOL]</arg></p>
+      <p><opt>-D | --daemonize</opt><arg>[=BOOL]</arg></p>
 
       <optdesc><p>Daemonize after startup, i.e. detach from the
       terminal.</p></optdesc>

commit 99acad7782b0f5be5b824bd69246cbbaa9ad199c
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Oct 1 03:26:45 2008 +0200

    fix support for ALSA devices which lack dB information

diff --git a/src/modules/module-alsa-sink.c b/src/modules/module-alsa-sink.c
index 30d4d3a..a4180d3 100644
--- a/src/modules/module-alsa-sink.c
+++ b/src/modules/module-alsa-sink.c
@@ -755,6 +755,21 @@ static int mixer_callback(snd_mixer_elem_t *elem, unsigned int mask) {
     return 0;
 }
 
+static pa_volume_t from_alsa_volume(struct userdata *u, long alsa_vol) {
+
+    return (pa_volume_t) round(((double) (alsa_vol - u->hw_volume_min) * PA_VOLUME_NORM) /
+                               (double) (u->hw_volume_max - u->hw_volume_min));
+}
+
+static long to_alsa_volume(struct userdata *u, pa_volume_t vol) {
+    long alsa_vol;
+
+    alsa_vol = (long) round(((double) vol * (double) (u->hw_volume_max - u->hw_volume_min))
+                            / PA_VOLUME_NORM) + u->hw_volume_min;
+
+    return PA_CLAMP_UNLIKELY(alsa_vol, u->hw_volume_min, u->hw_volume_max);
+}
+
 static int sink_get_volume_cb(pa_sink *s) {
     struct userdata *u = s->userdata;
     int err;
@@ -787,23 +802,31 @@ static int sink_get_volume_cb(pa_sink *s) {
                 if ((err = snd_mixer_selem_get_playback_volume(u->mixer_elem, u->mixer_map[i], &alsa_vol)) < 0)
                     goto fail;
 
-                r.values[i] = (pa_volume_t) round(((double) (alsa_vol - u->hw_volume_min) * PA_VOLUME_NORM) / (double) (u->hw_volume_max - u->hw_volume_min));
+                r.values[i] = from_alsa_volume(u, alsa_vol);
             }
         }
 
     } else {
         long alsa_vol;
 
-        pa_assert(u->hw_dB_supported);
+        if (u->hw_dB_supported) {
 
-        if ((err = snd_mixer_selem_get_playback_dB(u->mixer_elem, SND_MIXER_SCHN_MONO, &alsa_vol)) < 0)
-            goto fail;
+            if ((err = snd_mixer_selem_get_playback_dB(u->mixer_elem, SND_MIXER_SCHN_MONO, &alsa_vol)) < 0)
+                goto fail;
 
 #ifdef HAVE_VALGRIND_MEMCHECK_H
-                VALGRIND_MAKE_MEM_DEFINED(&alsa_vol, sizeof(alsa_vol));
+            VALGRIND_MAKE_MEM_DEFINED(&alsa_vol, sizeof(alsa_vol));
 #endif
 
-        pa_cvolume_set(&r, s->sample_spec.channels, pa_sw_volume_from_dB((double) alsa_vol / 100.0));
+            pa_cvolume_set(&r, s->sample_spec.channels, pa_sw_volume_from_dB((double) alsa_vol / 100.0));
+
+        } else {
+
+            if ((err = snd_mixer_selem_get_playback_volume(u->mixer_elem, SND_MIXER_SCHN_MONO, &alsa_vol)) < 0)
+                goto fail;
+
+            pa_cvolume_set(&r, s->sample_spec.channels, from_alsa_volume(u, alsa_vol));
+        }
     }
 
     pa_log_debug("Read hardware volume: %s", pa_cvolume_snprint(t, sizeof(t), &r));
@@ -861,10 +884,9 @@ static int sink_set_volume_cb(pa_sink *s) {
                     goto fail;
 
                 r.values[i] = pa_sw_volume_from_dB((double) alsa_vol / 100.0);
-            } else {
 
-                alsa_vol = (long) round(((double) vol * (double) (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);
+            } else {
+                alsa_vol = to_alsa_volume(u, vol);
 
                 if ((err = snd_mixer_selem_set_playback_volume(u->mixer_elem, u->mixer_map[i], alsa_vol)) < 0)
                     goto fail;
@@ -872,7 +894,7 @@ static int sink_set_volume_cb(pa_sink *s) {
                 if ((err = snd_mixer_selem_get_playback_volume(u->mixer_elem, u->mixer_map[i], &alsa_vol)) < 0)
                     goto fail;
 
-                r.values[i] = (pa_volume_t) round(((double) (alsa_vol - u->hw_volume_min) * PA_VOLUME_NORM) / (double) (u->hw_volume_max - u->hw_volume_min));
+                r.values[i] = from_alsa_volume(u, alsa_vol);
             }
         }
 
@@ -880,20 +902,31 @@ static int sink_set_volume_cb(pa_sink *s) {
         pa_volume_t vol;
         long alsa_vol;
 
-        pa_assert(u->hw_dB_supported);
-
         vol = pa_cvolume_max(&s->volume);
 
-        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 (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_all(u->mixer_elem, alsa_vol, 1)) < 0)
-            goto fail;
+            if ((err = snd_mixer_selem_set_playback_dB_all(u->mixer_elem, alsa_vol, 1)) < 0)
+                goto fail;
 
-        if ((err = snd_mixer_selem_get_playback_dB(u->mixer_elem, SND_MIXER_SCHN_MONO, &alsa_vol)) < 0)
-            goto fail;
+            if ((err = snd_mixer_selem_get_playback_dB(u->mixer_elem, SND_MIXER_SCHN_MONO, &alsa_vol)) < 0)
+                goto fail;
 
-        pa_cvolume_set(&r, s->volume.channels, pa_sw_volume_from_dB((double) alsa_vol / 100.0));
+            pa_cvolume_set(&r, s->volume.channels, pa_sw_volume_from_dB((double) alsa_vol / 100.0));
+
+        } else {
+            alsa_vol = to_alsa_volume(u, vol);
+
+            if ((err = snd_mixer_selem_set_playback_volume_all(u->mixer_elem, alsa_vol)) < 0)
+                goto fail;
+
+            if ((err = snd_mixer_selem_get_playback_volume(u->mixer_elem, SND_MIXER_SCHN_MONO, &alsa_vol)) < 0)
+                goto fail;
+
+            pa_cvolume_set(&r, s->sample_spec.channels, from_alsa_volume(u, alsa_vol));
+        }
     }
 
     u->hardware_volume = r;
diff --git a/src/modules/module-alsa-source.c b/src/modules/module-alsa-source.c
index d0a22db..6492839 100644
--- a/src/modules/module-alsa-source.c
+++ b/src/modules/module-alsa-source.c
@@ -700,6 +700,21 @@ static int mixer_callback(snd_mixer_elem_t *elem, unsigned int mask) {
     return 0;
 }
 
+static pa_volume_t from_alsa_volume(struct userdata *u, long alsa_vol) {
+
+    return (pa_volume_t) round(((double) (alsa_vol - u->hw_volume_min) * PA_VOLUME_NORM) /
+                               (double) (u->hw_volume_max - u->hw_volume_min));
+}
+
+static long to_alsa_volume(struct userdata *u, pa_volume_t vol) {
+    long alsa_vol;
+
+    alsa_vol = (long) round(((double) vol * (double) (u->hw_volume_max - u->hw_volume_min))
+                            / PA_VOLUME_NORM) + u->hw_volume_min;
+
+    return PA_CLAMP_UNLIKELY(alsa_vol, u->hw_volume_min, u->hw_volume_max);
+}
+
 static int source_get_volume_cb(pa_source *s) {
     struct userdata *u = s->userdata;
     int err;
@@ -732,23 +747,31 @@ static int source_get_volume_cb(pa_source *s) {
                 if ((err = snd_mixer_selem_get_capture_volume(u->mixer_elem, u->mixer_map[i], &alsa_vol)) < 0)
                     goto fail;
 
-                r.values[i] = (pa_volume_t) round(((double) (alsa_vol - u->hw_volume_min) * PA_VOLUME_NORM) / (double) (u->hw_volume_max - u->hw_volume_min));
+                r.values[i] = from_alsa_volume(u, alsa_vol);
             }
         }
 
     } else {
         long alsa_vol;
 
-        pa_assert(u->hw_dB_supported);
+        if (u->hw_dB_supported) {
 
-        if ((err = snd_mixer_selem_get_capture_dB(u->mixer_elem, SND_MIXER_SCHN_MONO, &alsa_vol)) < 0)
-            goto fail;
+            if ((err = snd_mixer_selem_get_capture_dB(u->mixer_elem, SND_MIXER_SCHN_MONO, &alsa_vol)) < 0)
+                goto fail;
 
 #ifdef HAVE_VALGRIND_MEMCHECK_H
-        VALGRIND_MAKE_MEM_DEFINED(&alsa_vol, sizeof(alsa_vol));
+            VALGRIND_MAKE_MEM_DEFINED(&alsa_vol, sizeof(alsa_vol));
 #endif
 
-        pa_cvolume_set(&r, s->sample_spec.channels, pa_sw_volume_from_dB((double) alsa_vol / 100.0));
+            pa_cvolume_set(&r, s->sample_spec.channels, pa_sw_volume_from_dB((double) alsa_vol / 100.0));
+
+        } else {
+
+            if ((err = snd_mixer_selem_get_capture_volume(u->mixer_elem, SND_MIXER_SCHN_MONO, &alsa_vol)) < 0)
+                goto fail;
+
+            pa_cvolume_set(&r, s->sample_spec.channels, from_alsa_volume(u, alsa_vol));
+        }
     }
 
     pa_log_debug("Read hardware volume: %s", pa_cvolume_snprint(t, sizeof(t), &r));
@@ -784,7 +807,7 @@ static int source_set_volume_cb(pa_source *s) {
     pa_assert(u);
     pa_assert(u->mixer_elem);
 
-        if (u->mixer_seperate_channels) {
+    if (u->mixer_seperate_channels) {
 
         r.channels = s->sample_spec.channels;
 
@@ -806,10 +829,9 @@ static int source_set_volume_cb(pa_source *s) {
                     goto fail;
 
                 r.values[i] = pa_sw_volume_from_dB((double) alsa_vol / 100.0);
-            } else {
 
-                alsa_vol = (long) round(((double) vol * (double) (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);
+            } else {
+                alsa_vol = to_alsa_volume(u, vol);
 
                 if ((err = snd_mixer_selem_set_capture_volume(u->mixer_elem, u->mixer_map[i], alsa_vol)) < 0)
                     goto fail;
@@ -817,7 +839,7 @@ static int source_set_volume_cb(pa_source *s) {
                 if ((err = snd_mixer_selem_get_capture_volume(u->mixer_elem, u->mixer_map[i], &alsa_vol)) < 0)
                     goto fail;
 
-                r.values[i] = (pa_volume_t) round(((double) (alsa_vol - u->hw_volume_min) * PA_VOLUME_NORM) / (double) (u->hw_volume_max - u->hw_volume_min));
+                r.values[i] = from_alsa_volume(u, alsa_vol);
             }
         }
 
@@ -825,20 +847,31 @@ static int source_set_volume_cb(pa_source *s) {
         pa_volume_t vol;
         long alsa_vol;
 
-        pa_assert(u->hw_dB_supported);
-
         vol = pa_cvolume_max(&s->volume);
 
-        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 (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_all(u->mixer_elem, alsa_vol, 1)) < 0)
-            goto fail;
+            if ((err = snd_mixer_selem_set_capture_dB_all(u->mixer_elem, alsa_vol, 1)) < 0)
+                goto fail;
 
-        if ((err = snd_mixer_selem_get_capture_dB(u->mixer_elem, SND_MIXER_SCHN_MONO, &alsa_vol)) < 0)
-            goto fail;
+            if ((err = snd_mixer_selem_get_capture_dB(u->mixer_elem, SND_MIXER_SCHN_MONO, &alsa_vol)) < 0)
+                goto fail;
 
-        pa_cvolume_set(&r, s->volume.channels, pa_sw_volume_from_dB((double) alsa_vol / 100.0));
+            pa_cvolume_set(&r, s->volume.channels, pa_sw_volume_from_dB((double) alsa_vol / 100.0));
+
+        } else {
+            alsa_vol = to_alsa_volume(u, vol);
+
+            if ((err = snd_mixer_selem_set_capture_volume_all(u->mixer_elem, alsa_vol)) < 0)
+                goto fail;
+
+            if ((err = snd_mixer_selem_get_capture_volume(u->mixer_elem, SND_MIXER_SCHN_MONO, &alsa_vol)) < 0)
+                goto fail;
+
+            pa_cvolume_set(&r, s->sample_spec.channels, from_alsa_volume(u, alsa_vol));
+        }
     }
 
     u->hardware_volume = r;

commit 4b67ea166ab9e95f2e483c23449a2fbc0af48f7e
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Oct 1 03:44:03 2008 +0200

    remove useless log message, re #367

diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c
index 6fa22dc..e04fc08 100644
--- a/src/pulsecore/sink.c
+++ b/src/pulsecore/sink.c
@@ -663,7 +663,6 @@ 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);

commit 5d18b6203350e061cad8ecb1da42102229f0e068
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Oct 1 03:54:01 2008 +0200

    remove useless log message

diff --git a/src/modules/rtp/module-rtp-recv.c b/src/modules/rtp/module-rtp-recv.c
index 0163789..e35773c 100644
--- a/src/modules/rtp/module-rtp-recv.c
+++ b/src/modules/rtp/module-rtp-recv.c
@@ -249,7 +249,7 @@ static int rtpoll_work_cb(pa_rtpoll_item *i) {
         pa_memblockq_seek(s->memblockq, (int64_t) chunk.length, PA_SEEK_RELATIVE);
     }
 
-    pa_log("blocks in q: %u", pa_memblockq_get_nblocks(s->memblockq));
+/*     pa_log("blocks in q: %u", pa_memblockq_get_nblocks(s->memblockq)); */
 
     pa_memblock_unref(chunk.memblock);
 

commit 3853070a21b1b71623c9f8f260bf46aeb6934716
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Oct 1 04:15:05 2008 +0200

    don't hit an assert if a kernel driver reports invalid dB information, instead just warn the user

diff --git a/src/modules/module-alsa-sink.c b/src/modules/module-alsa-sink.c
index a4180d3..8f90774 100644
--- a/src/modules/module-alsa-sink.c
+++ b/src/modules/module-alsa-sink.c
@@ -1474,14 +1474,15 @@ int pa__init(pa_module*m) {
         pa_assert(u->mixer_elem);
 
         if (snd_mixer_selem_has_playback_volume(u->mixer_elem)) {
-            pa_bool_t suitable = TRUE;
+            pa_bool_t suitable = FALSE;
 
-            if (snd_mixer_selem_get_playback_volume_range(u->mixer_elem, &u->hw_volume_min, &u->hw_volume_max) < 0) {
+            if (snd_mixer_selem_get_playback_volume_range(u->mixer_elem, &u->hw_volume_min, &u->hw_volume_max) < 0)
                 pa_log_info("Failed to get volume range. Falling back to software volume control.");
-                suitable = FALSE;
-            } else {
+            else if (u->hw_volume_min >= u->hw_volume_max)
+                pa_log_warn("Your kernel driver is broken: it reports a volume range from %li to %li which makes no sense.", u->hw_volume_min, u->hw_volume_max);
+            else {
                 pa_log_info("Volume ranges from %li to %li.", u->hw_volume_min, u->hw_volume_max);
-                pa_assert(u->hw_volume_min < u->hw_volume_max);
+                suitable = TRUE;
             }
 
             if (snd_mixer_selem_get_playback_dB_range(u->mixer_elem, &u->hw_dB_min, &u->hw_dB_max) < 0)
@@ -1492,9 +1493,12 @@ int pa__init(pa_module*m) {
                 VALGRIND_MAKE_MEM_DEFINED(&u->hw_dB_max, sizeof(u->hw_dB_max));
 #endif
 
-                pa_log_info("Volume ranges from %0.2f dB to %0.2f dB.", (double) u->hw_dB_min/100.0, (double) u->hw_dB_max/100.0);
-                pa_assert(u->hw_dB_min < u->hw_dB_max);
-                u->hw_dB_supported = TRUE;
+                if (u->hw_dB_min >= u->hw_dB_max)
+                    pa_log_warn("Your kernel driver is broken: it reports a volume range from %0.2f dB to %0.2f dB which makes no sense.", (double) u->hw_dB_min/100.0, (double) u->hw_dB_max/100.0);
+                else {
+                    pa_log_info("Volume ranges from %0.2f dB to %0.2f dB.", (double) u->hw_dB_min/100.0, (double) u->hw_dB_max/100.0);
+                    u->hw_dB_supported = TRUE;
+                }
             }
 
             if (suitable &&
diff --git a/src/modules/module-alsa-source.c b/src/modules/module-alsa-source.c
index 6492839..d5e2170 100644
--- a/src/modules/module-alsa-source.c
+++ b/src/modules/module-alsa-source.c
@@ -1295,14 +1295,15 @@ int pa__init(pa_module*m) {
         pa_assert(u->mixer_elem);
 
         if (snd_mixer_selem_has_capture_volume(u->mixer_elem)) {
-            pa_bool_t suitable = TRUE;
+            pa_bool_t suitable = FALSE;
 
-            if (snd_mixer_selem_get_capture_volume_range(u->mixer_elem, &u->hw_volume_min, &u->hw_volume_max) < 0) {
+            if (snd_mixer_selem_get_capture_volume_range(u->mixer_elem, &u->hw_volume_min, &u->hw_volume_max) < 0)
                 pa_log_info("Failed to get volume range. Falling back to software volume control.");
-                suitable = FALSE;
-            } else {
+            else if (u->hw_volume_min >= u->hw_volume_max)
+                pa_log_warn("Your kernel driver is broken: it reports a volume range from %li to %li which makes no sense.", u->hw_volume_min, u->hw_volume_max);
+            else {
                 pa_log_info("Volume ranges from %li to %li.", u->hw_volume_min, u->hw_volume_max);
-                pa_assert(u->hw_volume_min < u->hw_volume_max);
+                suitable = TRUE;
             }
 
             if (snd_mixer_selem_get_capture_dB_range(u->mixer_elem, &u->hw_dB_min, &u->hw_dB_max) < 0)
@@ -1313,9 +1314,12 @@ int pa__init(pa_module*m) {
                 VALGRIND_MAKE_MEM_DEFINED(&u->hw_dB_max, sizeof(u->hw_dB_max));
 #endif
 
-                pa_log_info("Volume ranges from %0.2f dB to %0.2f dB.", (double) u->hw_dB_min/100.0, (double) u->hw_dB_max/100.0);
-                pa_assert(u->hw_dB_min < u->hw_dB_max);
-                u->hw_dB_supported = TRUE;
+                if (u->hw_dB_min >= u->hw_dB_max)
+                    pa_log_warn("Your kernel driver is broken: it reports a volume range from %0.2f dB to %0.2f dB which makes no sense.", (double) u->hw_dB_min/100.0, (double) u->hw_dB_max/100.0);
+                else {
+                    pa_log_info("Volume ranges from %0.2f dB to %0.2f dB.", (double) u->hw_dB_min/100.0, (double) u->hw_dB_max/100.0);
+                    u->hw_dB_supported = TRUE;
+                }
             }
 
             if (suitable &&
@@ -1326,7 +1330,6 @@ int pa__init(pa_module*m) {
                 suitable = FALSE;
             }
 
-
             if (suitable) {
                 u->mixer_seperate_channels = pa_alsa_calc_mixer_map(u->mixer_elem, &map, u->mixer_map, FALSE) >= 0;
 

commit ea15ca98624ad308b68905bdb89b501b27fea81e
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Oct 1 14:49:00 2008 +0200

    PA_WARN_REFERENCE works only for ELF targets

diff --git a/src/pulsecore/macro.h b/src/pulsecore/macro.h
index fd33b7b..39e9b58 100644
--- a/src/pulsecore/macro.h
+++ b/src/pulsecore/macro.h
@@ -208,7 +208,7 @@ typedef int pa_bool_t;
 #define PA_PATH_SEP_CHAR '/'
 #endif
 
-#ifdef __GNUC__
+#if defined(__GNUC__) && defined(__ELF__)
 
 #define PA_WARN_REFERENCE(sym, msg)                  \
     __asm__(".section .gnu.warning." #sym);          \

commit cf3f80e8b41574a6f4c5def3537273356425b874
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Oct 1 23:42:32 2008 +0200

    when killing gconf helper, loop over EINTR

diff --git a/src/modules/gconf/module-gconf.c b/src/modules/gconf/module-gconf.c
index 6e8ab6e..845ede5 100644
--- a/src/modules/gconf/module-gconf.c
+++ b/src/modules/gconf/module-gconf.c
@@ -378,7 +378,16 @@ void pa__done(pa_module*m) {
 
     if (u->pid != (pid_t) -1) {
         kill(u->pid, SIGTERM);
-        waitpid(u->pid, NULL, 0);
+
+        for (;;) {
+            if (waitpid(u->pid, NULL, 0) >= 0)
+                break;
+
+            if (errno != EINTR) {
+                pa_log("waitpid() failed: %s", pa_cstrerror(errno));
+                break;
+            }
+        }
     }
 
     if (u->io_event)
@@ -387,7 +396,6 @@ void pa__done(pa_module*m) {
     if (u->fd >= 0)
         pa_close(u->fd);
 
-
     if (u->module_infos)
         pa_hashmap_free(u->module_infos, module_info_free, u);
 

commit 9f5d052d93a85bb8e4376732fe4473e87bf264f5
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Oct 2 00:04:02 2008 +0200

    make simple protocol not crash when allocating a memory block

diff --git a/src/pulsecore/protocol-simple.c b/src/pulsecore/protocol-simple.c
index 65e6773..743bf2e 100644
--- a/src/pulsecore/protocol-simple.c
+++ b/src/pulsecore/protocol-simple.c
@@ -173,7 +173,7 @@ static int do_read(connection *c) {
     }
 
     if (!c->playback.current_memblock) {
-        pa_assert_se(c->playback.current_memblock = pa_memblock_new(c->protocol->core->mempool, 0));
+        pa_assert_se(c->playback.current_memblock = pa_memblock_new(c->protocol->core->mempool, (size_t) -1));
         c->playback.memblock_index = 0;
 
         space = pa_memblock_get_length(c->playback.current_memblock);
@@ -492,6 +492,8 @@ void pa_simple_protocol_connect(pa_simple_protocol *p, pa_iochannel *io, pa_simp
     c->parent.parent.free = connection_free;
     c->parent.process_msg = connection_process_msg;
     c->io = io;
+    pa_iochannel_set_callback(c->io, io_callback, c);
+
     c->sink_input = NULL;
     c->source_output = NULL;
     c->input_memblockq = c->output_memblockq = NULL;
@@ -610,7 +612,6 @@ void pa_simple_protocol_connect(pa_simple_protocol *p, pa_iochannel *io, pa_simp
         pa_source_output_put(c->source_output);
     }
 
-    pa_iochannel_set_callback(c->io, io_callback, c);
     pa_idxset_put(p->connections, c, NULL);
 
     return;
@@ -689,6 +690,9 @@ pa_simple_options* pa_simple_options_new(void) {
     o = pa_xnew0(pa_simple_options, 1);
     PA_REFCNT_INIT(o);
 
+    o->record = FALSE;
+    o->playback = TRUE;
+
     return o;
 }
 
@@ -733,14 +737,14 @@ int pa_simple_options_parse(pa_simple_options *o, pa_core *c, pa_modargs *ma) {
     pa_xfree(o->default_sink);
     o->default_sink = pa_xstrdup(pa_modargs_get_value(ma, "sink", NULL));
 
-    enabled = FALSE;
+    enabled = o->record;
     if (pa_modargs_get_value_boolean(ma, "record", &enabled) < 0) {
         pa_log("record= expects a boolean argument.");
         return -1;
     }
     o->record = enabled;
 
-    enabled = TRUE;
+    enabled = o->playback;
     if (pa_modargs_get_value_boolean(ma, "playback", &enabled) < 0) {
         pa_log("playback= expects a boolean argument.");
         return -1;

commit 54afcf25980662d3033328705ec481c62b223e56
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Oct 2 01:02:31 2008 +0200

    inform dsp_empty_socket() *after* we emptied the dsp socket, that it is now empty

diff --git a/src/utils/padsp.c b/src/utils/padsp.c
index f2fdede..2e6e557 100644
--- a/src/utils/padsp.c
+++ b/src/utils/padsp.c
@@ -422,7 +422,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)
@@ -498,7 +498,6 @@ static void atfork_prepare(void) {
 
     pthread_mutex_lock(&func_mutex);
 
-
     debug(DEBUG_LEVEL_NORMAL, __FILE__": atfork_prepare() exit\n");
 }
 
@@ -550,12 +549,14 @@ static void atfork_child(void) {
         }
 
         if (i->app_fd >= 0) {
-            close(i->app_fd);
+            LOAD_CLOSE_FUNC();
+            _close(i->app_fd);
             i->app_fd = -1;
         }
 
         if (i->thread_fd >= 0) {
-            close(i->thread_fd);
+            LOAD_CLOSE_FUNC();
+            _close(i->thread_fd);
             i->thread_fd = -1;
         }
 
@@ -943,6 +944,10 @@ static int fd_info_copy_data(fd_info *i, int force) {
         api->io_enable(i->io_event, i->io_flags);
     }
 
+    /* So, we emptied the socket now, let's tell dsp_empty_socket()
+     * about this */
+    pa_threaded_mainloop_signal(i->mainloop, 0);
+
     return 0;
 }
 

commit 08cf9db0d17f8e2cfc68976fd96f0374721cdf22
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Oct 2 01:15:58 2008 +0200

    properly parse response to pa_stream_set_buffer_attr() calls. closes #370

diff --git a/src/pulse/stream.c b/src/pulse/stream.c
index ababe17..00aa1cf 100644
--- a/src/pulse/stream.c
+++ b/src/pulse/stream.c
@@ -2010,7 +2010,6 @@ static void stream_set_buffer_attr_callback(pa_pdispatch *pd, uint32_t command,
 
         success = 0;
     } else {
-
         if (o->stream->direction == PA_STREAM_PLAYBACK) {
             if (pa_tagstruct_getu32(t, &o->stream->buffer_attr.maxlength) < 0 ||
                 pa_tagstruct_getu32(t, &o->stream->buffer_attr.tlength) < 0 ||
@@ -2027,6 +2026,20 @@ static void stream_set_buffer_attr_callback(pa_pdispatch *pd, uint32_t command,
             }
         }
 
+        if (o->stream->context->version >= 13) {
+            pa_usec_t usec;
+
+            if (pa_tagstruct_get_usec(t, &usec) < 0) {
+                pa_context_fail(o->context, PA_ERR_PROTOCOL);
+                goto finish;
+            }
+
+            if (o->stream->direction == PA_STREAM_RECORD)
+                o->stream->timing_info.configured_source_usec = usec;
+            else
+                o->stream->timing_info.configured_sink_usec = usec;
+        }
+
         if (!pa_tagstruct_eof(t)) {
             pa_context_fail(o->context, PA_ERR_PROTOCOL);
             goto finish;

commit ea82dec294310b83be25b4e0c940fd2cd2c7eeb3
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Oct 2 02:29:56 2008 +0200

    when we mix into a 16bit accumulator make sure we clamp before we scale with a volume to avoid range faults when multiplying

diff --git a/src/pulsecore/sample-util.c b/src/pulsecore/sample-util.c
index b4234af..25178a8 100644
--- a/src/pulsecore/sample-util.c
+++ b/src/pulsecore/sample-util.c
@@ -214,8 +214,8 @@ size_t pa_mix(
                     m->ptr = (uint8_t*) m->ptr + sizeof(int16_t);
                 }
 
-                sum = (sum * linear[channel]) / 0x10000;
                 sum = PA_CLAMP_UNLIKELY(sum, -0x8000, 0x7FFF);
+                sum = (sum * linear[channel]) / 0x10000;
                 *((int16_t*) data) = (int16_t) sum;
 
                 data = (uint8_t*) data + sizeof(int16_t);
@@ -253,8 +253,8 @@ size_t pa_mix(
                     m->ptr = (uint8_t*) m->ptr + sizeof(int16_t);
                 }
 
-                sum = (sum * linear[channel]) / 0x10000;
                 sum = PA_CLAMP_UNLIKELY(sum, -0x8000, 0x7FFF);
+                sum = (sum * linear[channel]) / 0x10000;
                 *((int16_t*) data) = PA_INT16_SWAP((int16_t) sum);
 
                 data = (uint8_t*) data + sizeof(int16_t);
@@ -411,8 +411,8 @@ size_t pa_mix(
                     m->ptr = (uint8_t*) m->ptr + 1;
                 }
 
-                sum = (sum * linear[channel]) / 0x10000;
                 sum = PA_CLAMP_UNLIKELY(sum, -0x8000, 0x7FFF);
+                sum = (sum * linear[channel]) / 0x10000;
                 *((uint8_t*) data) = (uint8_t) st_14linear2ulaw((int16_t) sum >> 2);
 
                 data = (uint8_t*) data + 1;
@@ -450,8 +450,8 @@ size_t pa_mix(
                     m->ptr = (uint8_t*) m->ptr + 1;
                 }
 
-                sum = (sum * linear[channel]) / 0x10000;
                 sum = PA_CLAMP_UNLIKELY(sum, -0x8000, 0x7FFF);
+                sum = (sum * linear[channel]) / 0x10000;
                 *((uint8_t*) data) = (uint8_t) st_13linear2alaw((int16_t) sum >> 3);
 
                 data = (uint8_t*) data + 1;
diff --git a/src/tests/mix-test.c b/src/tests/mix-test.c
index 759d769..cc21ab0 100644
--- a/src/tests/mix-test.c
+++ b/src/tests/mix-test.c
@@ -221,6 +221,8 @@ int main(int argc, char *argv[]) {
         i.length = pa_memblock_get_length(i.memblock);
         i.index = 0;
 
+        dump_block(&a, &i);
+
         /* Make a copy */
         j = i;
         pa_memblock_ref(j.memblock);
@@ -229,6 +231,8 @@ int main(int argc, char *argv[]) {
         /* Adjust volume of the copy */
         pa_volume_memchunk(&j, &a, &v);
 
+        dump_block(&a, &j);
+
         m[0].chunk = i;
         m[0].volume.values[0] = PA_VOLUME_NORM;
         m[0].volume.channels = a.channels;
@@ -244,8 +248,6 @@ int main(int argc, char *argv[]) {
         pa_mix(m, 2, ptr, k.length, &a, NULL, FALSE);
         pa_memblock_release(k.memblock);
 
-        dump_block(&a, &i);
-        dump_block(&a, &j);
         dump_block(&a, &k);
 
         pa_memblock_unref(i.memblock);

commit a0f4ffd3e12c0274ca05a577d03914270370b724
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Oct 2 03:07:54 2008 +0200

    make sure we call pa_sink_process_rewind() if a rewind was requested under all circumstances

diff --git a/src/modules/module-null-sink.c b/src/modules/module-null-sink.c
index 9162960..470c622 100644
--- a/src/modules/module-null-sink.c
+++ b/src/modules/module-null-sink.c
@@ -137,13 +137,13 @@ static void process_rewind(struct userdata *u, pa_usec_t now) {
     pa_log_debug("Requested to rewind %lu bytes.", (unsigned long) rewind_nbytes);
 
     if (u->timestamp <= now)
-        return;
+        goto do_nothing;
 
     delay = u->timestamp - now;
     in_buffer = pa_usec_to_bytes(delay, &u->sink->sample_spec);
 
     if (in_buffer <= 0)
-        return;
+        goto do_nothing;
 
     if (rewind_nbytes > in_buffer)
         rewind_nbytes = in_buffer;
@@ -152,6 +152,11 @@ static void process_rewind(struct userdata *u, pa_usec_t now) {
     u->timestamp -= pa_bytes_to_usec(rewind_nbytes, &u->sink->sample_spec);
 
     pa_log_debug("Rewound %lu bytes.", (unsigned long) rewind_nbytes);
+    return;
+
+do_nothing:
+
+    pa_sink_process_rewind(u->sink, 0);
 }
 
 static void process_render(struct userdata *u, pa_usec_t now) {

commit 7d442e32769cfcf2e286f32be33821fbf8de2c7d
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Oct 3 01:53:34 2008 +0200

    optimize mixing routines a bit by pulling the multiplication with the global volume out of the inner loop by applying it first to the per-stream volumes

diff --git a/src/pulsecore/sample-util.c b/src/pulsecore/sample-util.c
index 25178a8..b4e8bf4 100644
--- a/src/pulsecore/sample-util.c
+++ b/src/pulsecore/sample-util.c
@@ -98,56 +98,62 @@ void* pa_silence_memory(void *p, size_t length, const pa_sample_spec *spec) {
     return p;
 }
 
-static void calc_linear_integer_stream_volumes(pa_mix_info streams[], unsigned nstreams, const pa_sample_spec *spec) {
-    unsigned k;
-
-    pa_assert(streams);
-    pa_assert(spec);
+static void calc_linear_integer_volume(int32_t linear[], const pa_cvolume *volume) {
+    unsigned channel;
 
-    for (k = 0; k < nstreams; k++) {
-        unsigned channel;
+    pa_assert(linear);
+    pa_assert(volume);
 
-        for (channel = 0; channel < spec->channels; channel++) {
-            pa_mix_info *m = streams + k;
-            m->linear[channel].i = (int32_t) (pa_sw_volume_to_linear(m->volume.values[channel]) * 0x10000);
-        }
-    }
+    for (channel = 0; channel < volume->channels; channel++)
+        linear[channel] = (int32_t) (pa_sw_volume_to_linear(volume->values[channel]) * 0x10000);
 }
 
-static void calc_linear_integer_volume(int32_t linear[], const pa_cvolume *volume) {
+static void calc_linear_float_volume(float linear[], const pa_cvolume *volume) {
     unsigned channel;
 
     pa_assert(linear);
     pa_assert(volume);
 
     for (channel = 0; channel < volume->channels; channel++)
-        linear[channel] = (int32_t) (pa_sw_volume_to_linear(volume->values[channel]) * 0x10000);
+        linear[channel] = (float) pa_sw_volume_to_linear(volume->values[channel]);
 }
 
-static void calc_linear_float_stream_volumes(pa_mix_info streams[], unsigned nstreams, const pa_sample_spec *spec) {
-    unsigned k;
+static void calc_linear_integer_stream_volumes(pa_mix_info streams[], unsigned nstreams, const pa_cvolume *volume, const pa_sample_spec *spec) {
+    unsigned k, channel;
+    float linear[PA_CHANNELS_MAX];
 
     pa_assert(streams);
     pa_assert(spec);
+    pa_assert(volume);
+
+    calc_linear_float_volume(linear, volume);
 
     for (k = 0; k < nstreams; k++) {
-        unsigned channel;
 
         for (channel = 0; channel < spec->channels; channel++) {
             pa_mix_info *m = streams + k;
-            m->linear[channel].f = (float) pa_sw_volume_to_linear(m->volume.values[channel]);
+            m->linear[channel].i = (int32_t) (pa_sw_volume_to_linear(m->volume.values[channel]) * linear[channel] * 0x10000);
         }
     }
 }
 
-static void calc_linear_float_volume(float linear[], const pa_cvolume *volume) {
-    unsigned channel;
+static void calc_linear_float_stream_volumes(pa_mix_info streams[], unsigned nstreams, const pa_cvolume *volume, const pa_sample_spec *spec) {
+    unsigned k, channel;
+    float linear[PA_CHANNELS_MAX];
 
-    pa_assert(linear);
+    pa_assert(streams);
+    pa_assert(spec);
     pa_assert(volume);
 
-    for (channel = 0; channel < volume->channels; channel++)
-        linear[channel] = (float) pa_sw_volume_to_linear(volume->values[channel]);
+    calc_linear_float_volume(linear, volume);
+
+    for (k = 0; k < nstreams; k++) {
+
+        for (channel = 0; channel < spec->channels; channel++) {
+            pa_mix_info *m = streams + k;
+            m->linear[channel].f = (float) (pa_sw_volume_to_linear(m->volume.values[channel]) * linear[channel]);
+        }
+    }
 }
 
 size_t pa_mix(
@@ -190,10 +196,8 @@ size_t pa_mix(
 
         case PA_SAMPLE_S16NE:{
             unsigned channel = 0;
-            int32_t linear[PA_CHANNELS_MAX];
 
-            calc_linear_integer_stream_volumes(streams, nstreams, spec);
-            calc_linear_integer_volume(linear, volume);
+            calc_linear_integer_stream_volumes(streams, nstreams, volume, spec);
 
             while (data < end) {
                 int32_t sum = 0;
@@ -203,19 +207,17 @@ size_t pa_mix(
                     pa_mix_info *m = streams + i;
                     int32_t v, cv = m->linear[channel].i;
 
-                    if (PA_UNLIKELY(cv <= 0) || PA_UNLIKELY(linear[channel] <= 0))
-                        v = 0;
-                    else {
-                        v = *((int16_t*) m->ptr);
-                        v = (v * cv) / 0x10000;
-                    }
+                    if (PA_UNLIKELY(cv <= 0))
+                        continue;
 
+                    v = *((int16_t*) m->ptr);
+                    v = (v * cv) / 0x10000;
                     sum += v;
+
                     m->ptr = (uint8_t*) m->ptr + sizeof(int16_t);
                 }
 
                 sum = PA_CLAMP_UNLIKELY(sum, -0x8000, 0x7FFF);
-                sum = (sum * linear[channel]) / 0x10000;
                 *((int16_t*) data) = (int16_t) sum;
 
                 data = (uint8_t*) data + sizeof(int16_t);
@@ -229,10 +231,8 @@ size_t pa_mix(
 
         case PA_SAMPLE_S16RE:{
             unsigned channel = 0;
-            int32_t linear[PA_CHANNELS_MAX];
 
-            calc_linear_integer_stream_volumes(streams, nstreams, spec);
-            calc_linear_integer_volume(linear, volume);
+            calc_linear_integer_stream_volumes(streams, nstreams, volume, spec);
 
             while (data < end) {
                 int32_t sum = 0;
@@ -242,19 +242,17 @@ size_t pa_mix(
                     pa_mix_info *m = streams + i;
                     int32_t v, cv = m->linear[channel].i;
 
-                    if (PA_UNLIKELY(cv <= 0) || PA_UNLIKELY(linear[channel] <= 0))
-                        v = 0;
-                    else {
-                        v = PA_INT16_SWAP(*((int16_t*) m->ptr));
-                        v = (v * cv) / 0x10000;
-                    }
+                    if (PA_UNLIKELY(cv <= 0))
+                        continue;
 
+                    v = PA_INT16_SWAP(*((int16_t*) m->ptr));
+                    v = (v * cv) / 0x10000;
                     sum += v;
+
                     m->ptr = (uint8_t*) m->ptr + sizeof(int16_t);
                 }
 
                 sum = PA_CLAMP_UNLIKELY(sum, -0x8000, 0x7FFF);
-                sum = (sum * linear[channel]) / 0x10000;
                 *((int16_t*) data) = PA_INT16_SWAP((int16_t) sum);
 
                 data = (uint8_t*) data + sizeof(int16_t);
@@ -268,10 +266,8 @@ size_t pa_mix(
 
         case PA_SAMPLE_S32NE:{
             unsigned channel = 0;
-            int32_t linear[PA_CHANNELS_MAX];
 
-            calc_linear_integer_stream_volumes(streams, nstreams, spec);
-            calc_linear_integer_volume(linear, volume);
+            calc_linear_integer_stream_volumes(streams, nstreams, volume, spec);
 
             while (data < end) {
                 int64_t sum = 0;
@@ -279,21 +275,19 @@ size_t pa_mix(
 
                 for (i = 0; i < nstreams; i++) {
                     pa_mix_info *m = streams + i;
-                    int64_t v;
                     int32_t cv = m->linear[channel].i;
+                    int64_t v;
 
-                    if (PA_UNLIKELY(cv <= 0) || PA_UNLIKELY(linear[channel] <= 0))
-                        v = 0;
-                    else {
-                        v = *((int32_t*) m->ptr);
-                        v = (v * cv) / 0x10000;
-                    }
+                    if (PA_UNLIKELY(cv <= 0))
+                        continue;
 
+                    v = *((int32_t*) m->ptr);
+                    v = (v * cv) / 0x10000;
                     sum += v;
+
                     m->ptr = (uint8_t*) m->ptr + sizeof(int32_t);
                 }
 
-                sum = (sum * linear[channel]) / 0x10000;
                 sum = PA_CLAMP_UNLIKELY(sum, -0x80000000LL, 0x7FFFFFFFLL);
                 *((int32_t*) data) = (int32_t) sum;
 
@@ -308,10 +302,8 @@ size_t pa_mix(
 
         case PA_SAMPLE_S32RE:{
             unsigned channel = 0;
-            int32_t linear[PA_CHANNELS_MAX];
 
-            calc_linear_integer_stream_volumes(streams, nstreams, spec);
-            calc_linear_integer_volume(linear, volume);
+            calc_linear_integer_stream_volumes(streams, nstreams, volume, spec);
 
             while (data < end) {
                 int64_t sum = 0;
@@ -319,21 +311,19 @@ size_t pa_mix(
 
                 for (i = 0; i < nstreams; i++) {
                     pa_mix_info *m = streams + i;
-                    int64_t v;
                     int32_t cv = m->linear[channel].i;
+                    int64_t v;
 
-                    if (PA_UNLIKELY(cv <= 0) || PA_UNLIKELY(linear[channel] <= 0))
-                        v = 0;
-                    else {
-                        v = PA_INT32_SWAP(*((int32_t*) m->ptr));
-                        v = (v * cv) / 0x10000;
-                    }
+                    if (PA_UNLIKELY(cv <= 0))
+                        continue;
 
+                    v = PA_INT32_SWAP(*((int32_t*) m->ptr));
+                    v = (v * cv) / 0x10000;
                     sum += v;
+
                     m->ptr = (uint8_t*) m->ptr + sizeof(int32_t);
                 }
 
-                sum = (sum * linear[channel]) / 0x10000;
                 sum = PA_CLAMP_UNLIKELY(sum, -0x80000000LL, 0x7FFFFFFFLL);
                 *((int32_t*) data) = PA_INT32_SWAP((int32_t) sum);
 
@@ -348,10 +338,8 @@ size_t pa_mix(
 
         case PA_SAMPLE_U8: {
             unsigned channel = 0;
-            int32_t linear[PA_CHANNELS_MAX];
 
-            calc_linear_integer_stream_volumes(streams, nstreams, spec);
-            calc_linear_integer_volume(linear, volume);
+            calc_linear_integer_stream_volumes(streams, nstreams, volume, spec);
 
             while (data < end) {
                 int32_t sum = 0;
@@ -361,18 +349,16 @@ size_t pa_mix(
                     pa_mix_info *m = streams + i;
                     int32_t v, cv = m->linear[channel].i;
 
-                    if (PA_UNLIKELY(cv <= 0) || PA_UNLIKELY(linear[channel] <= 0))
-                        v = 0;
-                    else {
-                        v = (int32_t) *((uint8_t*) m->ptr) - 0x80;
-                        v = (v * cv) / 0x10000;
-                    }
+                    if (PA_UNLIKELY(cv <= 0))
+                        continue;
 
+                    v = (int32_t) *((uint8_t*) m->ptr) - 0x80;
+                    v = (v * cv) / 0x10000;
                     sum += v;
+
                     m->ptr = (uint8_t*) m->ptr + 1;
                 }
 
-                sum = (sum * linear[channel]) / 0x10000;
                 sum = PA_CLAMP_UNLIKELY(sum, -0x80, 0x7F);
                 *((uint8_t*) data) = (uint8_t) (sum + 0x80);
 
@@ -387,10 +373,8 @@ size_t pa_mix(
 
         case PA_SAMPLE_ULAW: {
             unsigned channel = 0;
-            int32_t linear[PA_CHANNELS_MAX];
 
-            calc_linear_integer_stream_volumes(streams, nstreams, spec);
-            calc_linear_integer_volume(linear, volume);
+            calc_linear_integer_stream_volumes(streams, nstreams, volume, spec);
 
             while (data < end) {
                 int32_t sum = 0;
@@ -400,19 +384,17 @@ size_t pa_mix(
                     pa_mix_info *m = streams + i;
                     int32_t v, cv = m->linear[channel].i;
 
-                    if (PA_UNLIKELY(cv <= 0) || PA_UNLIKELY(linear[channel] <= 0))
-                        v = 0;
-                    else {
-                        v = (int32_t) st_ulaw2linear16(*((uint8_t*) m->ptr));
-                        v = (v * cv) / 0x10000;
-                    }
+                    if (PA_UNLIKELY(cv <= 0))
+                        continue;
 
+                    v = (int32_t) st_ulaw2linear16(*((uint8_t*) m->ptr));
+                    v = (v * cv) / 0x10000;
                     sum += v;
+
                     m->ptr = (uint8_t*) m->ptr + 1;
                 }
 
                 sum = PA_CLAMP_UNLIKELY(sum, -0x8000, 0x7FFF);
-                sum = (sum * linear[channel]) / 0x10000;
                 *((uint8_t*) data) = (uint8_t) st_14linear2ulaw((int16_t) sum >> 2);
 
                 data = (uint8_t*) data + 1;
@@ -426,10 +408,8 @@ size_t pa_mix(
 
         case PA_SAMPLE_ALAW: {
             unsigned channel = 0;
-            int32_t linear[PA_CHANNELS_MAX];
 
-            calc_linear_integer_stream_volumes(streams, nstreams, spec);
-            calc_linear_integer_volume(linear, volume);
+            calc_linear_integer_stream_volumes(streams, nstreams, volume, spec);
 
             while (data < end) {
                 int32_t sum = 0;
@@ -439,19 +419,17 @@ size_t pa_mix(
                     pa_mix_info *m = streams + i;
                     int32_t v, cv = m->linear[channel].i;
 
-                    if (PA_UNLIKELY(cv <= 0) || PA_UNLIKELY(linear[channel] <= 0))
-                        v = 0;
-                    else {
-                        v = (int32_t) st_alaw2linear16(*((uint8_t*) m->ptr));
-                        v = (v * cv) / 0x10000;
-                    }
+                    if (PA_UNLIKELY(cv <= 0))
+                        continue;
 
+                    v = (int32_t) st_alaw2linear16(*((uint8_t*) m->ptr));
+                    v = (v * cv) / 0x10000;
                     sum += v;
+
                     m->ptr = (uint8_t*) m->ptr + 1;
                 }
 
                 sum = PA_CLAMP_UNLIKELY(sum, -0x8000, 0x7FFF);
-                sum = (sum * linear[channel]) / 0x10000;
                 *((uint8_t*) data) = (uint8_t) st_13linear2alaw((int16_t) sum >> 3);
 
                 data = (uint8_t*) data + 1;
@@ -465,10 +443,8 @@ size_t pa_mix(
 
         case PA_SAMPLE_FLOAT32NE: {
             unsigned channel = 0;
-            float linear[PA_CHANNELS_MAX];
 
-            calc_linear_float_stream_volumes(streams, nstreams, spec);
-            calc_linear_float_volume(linear, volume);
+            calc_linear_float_stream_volumes(streams, nstreams, volume, spec);
 
             while (data < end) {
                 float sum = 0;
@@ -478,18 +454,16 @@ size_t pa_mix(
                     pa_mix_info *m = streams + i;
                     float v, cv = m->linear[channel].f;
 
-                    if (PA_UNLIKELY(cv <= 0) || PA_UNLIKELY(linear[channel] <= 0))
-                        v = 0;
-                    else {
-                        v = *((float*) m->ptr);
-                        v *= cv;
-                    }
+                    if (PA_UNLIKELY(cv <= 0))
+                        continue;
 
+                    v = *((float*) m->ptr);
+                    v *= cv;
                     sum += v;
+
                     m->ptr = (uint8_t*) m->ptr + sizeof(float);
                 }
 
-                sum *= linear[channel];
                 *((float*) data) = sum;
 
                 data = (uint8_t*) data + sizeof(float);
@@ -505,8 +479,7 @@ size_t pa_mix(
             unsigned channel = 0;
             float linear[PA_CHANNELS_MAX];
 
-            calc_linear_float_stream_volumes(streams, nstreams, spec);
-            calc_linear_float_volume(linear, volume);
+            calc_linear_float_stream_volumes(streams, nstreams, volume, spec);
 
             while (data < end) {
                 float sum = 0;
@@ -516,16 +489,16 @@ size_t pa_mix(
                     pa_mix_info *m = streams + i;
                     float v, cv = m->linear[channel].f;
 
-                    if (PA_UNLIKELY(cv <= 0) || PA_UNLIKELY(linear[channel] <= 0))
-                        v = 0;
-                    else
-                        v = PA_FLOAT32_SWAP(*(float*) m->ptr) *cv;
+                    if (PA_UNLIKELY(cv <= 0))
+                        continue;
 
+                    v = PA_FLOAT32_SWAP(*(float*) m->ptr);
+                    v *= cv;
                     sum += v;
+
                     m->ptr = (uint8_t*) m->ptr + sizeof(float);
                 }
 
-                sum *= linear[channel];
                 *((float*) data) = PA_FLOAT32_SWAP(sum);
 
                 data = (uint8_t*) data + sizeof(float);

commit 1bb5e58fb38f3cd4b2c389dd3da294b004eade56
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Oct 3 02:33:44 2008 +0200

    use PA_FLOAT32_SWAP where useful

diff --git a/src/pulsecore/sconv-s16le.c b/src/pulsecore/sconv-s16le.c
index 693d529..1a7448e 100644
--- a/src/pulsecore/sconv-s16le.c
+++ b/src/pulsecore/sconv-s16le.c
@@ -153,8 +153,7 @@ void pa_sconv_s16le_to_float32re(unsigned n, const int16_t *a, float *b) {
     for (; n > 0; n--) {
         int16_t s = *(a++);
         float k = ((float) INT16_FROM(s))/0x7FFF;
-        uint32_t *j = (uint32_t*) &k;
-        *j = PA_UINT32_SWAP(*j);
+        k = PA_FLOAT32_SWAP(k);
         *(b++) = k;
     }
 }
@@ -166,8 +165,7 @@ void pa_sconv_s32le_to_float32re(unsigned n, const int32_t *a, float *b) {
     for (; n > 0; n--) {
         int32_t s = *(a++);
         float k = (float) (((double) INT32_FROM(s))/0x7FFFFFFF);
-        uint32_t *j = (uint32_t*) &k;
-        *j = PA_UINT32_SWAP(*j);
+        k = PA_FLOAT32_SWAP(k);
         *(b++) = k;
     }
 }
@@ -179,8 +177,7 @@ void pa_sconv_s16le_from_float32re(unsigned n, const float *a, int16_t *b) {
     for (; n > 0; n--) {
         int16_t s;
         float v = *(a++);
-        uint32_t *j = (uint32_t*) &v;
-        *j = PA_UINT32_SWAP(*j);
+        v = PA_FLOAT32_SWAP(v);
         v = PA_CLAMP_UNLIKELY(v, -1.0f, 1.0f);
         s = (int16_t) (v * 0x7FFF);
         *(b++) = INT16_TO(s);
@@ -194,8 +191,7 @@ void pa_sconv_s32le_from_float32re(unsigned n, const float *a, int32_t *b) {
     for (; n > 0; n--) {
         int32_t s;
         float v = *(a++);
-        uint32_t *j = (uint32_t*) &v;
-        *j = PA_UINT32_SWAP(*j);
+        v = PA_FLOAT32_SWAP(v);
         v = PA_CLAMP_UNLIKELY(v, -1.0f, 1.0f);
         s = (int32_t) ((double) v * 0x7FFFFFFF);
         *(b++) = INT32_TO(s);

commit 33b186e74dc2de6fa363d10d3450c354ec99f864
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Oct 3 02:34:59 2008 +0200

    user lrint() and friends in inner loops instead of normal C casts to speed up a few things

diff --git a/src/pulse/volume.c b/src/pulse/volume.c
index 15938cb..6907dc8 100644
--- a/src/pulse/volume.c
+++ b/src/pulse/volume.c
@@ -96,7 +96,7 @@ pa_volume_t pa_sw_volume_from_dB(double dB) {
     if (isinf(dB) < 0 || dB <= -USER_DECIBEL_RANGE)
         return PA_VOLUME_MUTED;
 
-    return (pa_volume_t) ((dB/USER_DECIBEL_RANGE+1)*PA_VOLUME_NORM);
+    return (pa_volume_t) lrint((dB/USER_DECIBEL_RANGE+1)*PA_VOLUME_NORM);
 }
 
 double pa_sw_volume_to_dB(pa_volume_t v) {
diff --git a/src/pulsecore/sample-util.c b/src/pulsecore/sample-util.c
index b4e8bf4..5119ebd 100644
--- a/src/pulsecore/sample-util.c
+++ b/src/pulsecore/sample-util.c
@@ -105,7 +105,7 @@ static void calc_linear_integer_volume(int32_t linear[], const pa_cvolume *volum
     pa_assert(volume);
 
     for (channel = 0; channel < volume->channels; channel++)
-        linear[channel] = (int32_t) (pa_sw_volume_to_linear(volume->values[channel]) * 0x10000);
+        linear[channel] = lrint(pa_sw_volume_to_linear(volume->values[channel]) * 0x10000);
 }
 
 static void calc_linear_float_volume(float linear[], const pa_cvolume *volume) {
@@ -132,7 +132,7 @@ static void calc_linear_integer_stream_volumes(pa_mix_info streams[], unsigned n
 
         for (channel = 0; channel < spec->channels; channel++) {
             pa_mix_info *m = streams + k;
-            m->linear[channel].i = (int32_t) (pa_sw_volume_to_linear(m->volume.values[channel]) * linear[channel] * 0x10000);
+            m->linear[channel].i = lrint(pa_sw_volume_to_linear(m->volume.values[channel]) * linear[channel] * 0x10000);
         }
     }
 }
diff --git a/src/pulsecore/sconv-s16le.c b/src/pulsecore/sconv-s16le.c
index 1a7448e..159c465 100644
--- a/src/pulsecore/sconv-s16le.c
+++ b/src/pulsecore/sconv-s16le.c
@@ -111,7 +111,7 @@ void pa_sconv_s16le_from_float32ne(unsigned n, const float *a, int16_t *b) {
         float v = *(a++);
 
         v = PA_CLAMP_UNLIKELY(v, -1.0f, 1.f);
-        s = (int16_t) (v * 0x7FFF);
+        s = (int16_t) lrintf(v * 0x7FFF);
         *(b++) = INT16_TO(s);
     }
 
@@ -134,7 +134,7 @@ void pa_sconv_s32le_from_float32ne(unsigned n, const float *a, int32_t *b) {
         float v = *(a++);
 
         v = PA_CLAMP_UNLIKELY(v, -1.0f, 1.0f);
-        s = (int32_t) ((double) v * (double) 0x7FFFFFFF);
+        s = (int32_t) lrint((double) v * (double) 0x7FFFFFFF);
         *(b++) = INT32_TO(s);
     }
 
@@ -179,7 +179,7 @@ void pa_sconv_s16le_from_float32re(unsigned n, const float *a, int16_t *b) {
         float v = *(a++);
         v = PA_FLOAT32_SWAP(v);
         v = PA_CLAMP_UNLIKELY(v, -1.0f, 1.0f);
-        s = (int16_t) (v * 0x7FFF);
+        s = (int16_t) lrintf(v * 0x7FFF);
         *(b++) = INT16_TO(s);
     }
 }
@@ -193,7 +193,7 @@ void pa_sconv_s32le_from_float32re(unsigned n, const float *a, int32_t *b) {
         float v = *(a++);
         v = PA_FLOAT32_SWAP(v);
         v = PA_CLAMP_UNLIKELY(v, -1.0f, 1.0f);
-        s = (int32_t) ((double) v * 0x7FFFFFFF);
+        s = (int32_t) lrint((double) v * 0x7FFFFFFF);
         *(b++) = INT32_TO(s);
     }
 }
diff --git a/src/pulsecore/sconv.c b/src/pulsecore/sconv.c
index 733a46a..6c4d420 100644
--- a/src/pulsecore/sconv.c
+++ b/src/pulsecore/sconv.c
@@ -130,7 +130,7 @@ static void ulaw_from_float32ne(unsigned n, const float *a, uint8_t *b) {
         float v = *(a++);
         v = PA_CLAMP_UNLIKELY(v, -1.0f, 1.0f);
         v *= 0x1FFF;
-        *(b++) = st_14linear2ulaw((int16_t) v);
+        *(b++) = st_14linear2ulaw((int16_t) lrintf(v));
     }
 }
 
@@ -168,7 +168,7 @@ static void alaw_from_float32ne(unsigned n, const float *a, uint8_t *b) {
         float v = *a;
         v = PA_CLAMP_UNLIKELY(v, -1.0f, 1.0f);
         v *= 0xFFF;
-        *b = st_13linear2alaw((int16_t) v);
+        *b = st_13linear2alaw((int16_t) lrintf(v));
     }
 }
 
diff --git a/src/pulsecore/time-smoother.c b/src/pulsecore/time-smoother.c
index b165f4a..6a2ffaa 100644
--- a/src/pulsecore/time-smoother.c
+++ b/src/pulsecore/time-smoother.c
@@ -284,7 +284,7 @@ static void estimate(pa_smoother *s, pa_usec_t x, pa_usec_t *y, double *deriv) {
         /* 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 * (double) (x - s->px));
+        t = (int64_t) s->py + (int64_t) llrint(s->dp * (double) (x - s->px));
 
         if (t < 0)
             t = 0;
@@ -313,7 +313,7 @@ static void estimate(pa_smoother *s, pa_usec_t x, pa_usec_t *y, double *deriv) {
         /* Move back from origin */
         ty += (double) s->ey;
 
-        *y = ty >= 0 ? (pa_usec_t) ty : 0;
+        *y = ty >= 0 ? (pa_usec_t) lrint(ty) : 0;
 
         /* Horner scheme */
         if (deriv)
@@ -360,7 +360,7 @@ void pa_smoother_put(pa_smoother *s, pa_usec_t x, pa_usec_t y) {
 
     /* And calculate when we want to be on track again */
     s->px = s->ex + s->adjust_time;
-    s->py = s->ry + (pa_usec_t) (s->dp * (double) s->adjust_time);
+    s->py = s->ry + (pa_usec_t) lrint(s->dp * (double) s->adjust_time);
 
     s->abc_valid = FALSE;
 
@@ -456,7 +456,7 @@ pa_usec_t pa_smoother_translate(pa_smoother *s, pa_usec_t x, pa_usec_t y_delay)
 
 /*     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 / nde);
+    return (pa_usec_t) lrint((double) y_delay / nde);
 }
 
 void pa_smoother_reset(pa_smoother *s) {

commit 8a50105fe0568598ef5bc0f5360d60536a8bf5cd
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Oct 3 15:16:26 2008 +0200

    if a volume or channel map is invalid show so when printing it

diff --git a/src/pulse/channelmap.c b/src/pulse/channelmap.c
index 3730875..db6577e 100644
--- a/src/pulse/channelmap.c
+++ b/src/pulse/channelmap.c
@@ -466,6 +466,13 @@ char* pa_channel_map_snprint(char *s, size_t l, const pa_channel_map *map) {
     pa_assert(l > 0);
     pa_assert(map);
 
+    pa_init_i18n();
+
+    if (!pa_channel_map_valid(map)) {
+        pa_snprintf(s, l, _("(invalid)"));
+        return s;
+    }
+
     *(e = s) = 0;
 
     for (channel = 0; channel < map->channels && l > 1; channel++) {
diff --git a/src/pulse/sample.c b/src/pulse/sample.c
index 93da246..39891d2 100644
--- a/src/pulse/sample.c
+++ b/src/pulse/sample.c
@@ -131,7 +131,7 @@ char *pa_sample_spec_snprint(char *s, size_t l, const pa_sample_spec *spec) {
     pa_init_i18n();
 
     if (!pa_sample_spec_valid(spec))
-        pa_snprintf(s, l, _("Invalid"));
+        pa_snprintf(s, l, _("(invalid)"));
     else
         pa_snprintf(s, l, "%s %uch %uHz", pa_sample_format_to_string(spec->format), spec->channels, spec->rate);
 
diff --git a/src/pulse/volume.c b/src/pulse/volume.c
index 6907dc8..60a86be 100644
--- a/src/pulse/volume.c
+++ b/src/pulse/volume.c
@@ -26,6 +26,7 @@
 #include <stdio.h>
 #include <string.h>
 
+#include <pulse/i18n.h>
 #include <pulsecore/core-util.h>
 #include <pulsecore/macro.h>
 
@@ -134,6 +135,13 @@ char *pa_cvolume_snprint(char *s, size_t l, const pa_cvolume *c) {
     pa_assert(l > 0);
     pa_assert(c);
 
+    pa_init_i18n();
+
+    if (!pa_cvolume_valid(c)) {
+        pa_snprintf(s, l, _("(invalid)"));
+        return s;
+    }
+
     *(e = s) = 0;
 
     for (channel = 0; channel < c->channels && l > 1; channel++) {

commit 891989896d8c8c2d3645933c7ff93527d4eb4a9c
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Oct 3 17:13:17 2008 +0200

    add new API function pa_sample_spec_init()

diff --git a/src/pulse/sample.c b/src/pulse/sample.c
index 39891d2..2950159 100644
--- a/src/pulse/sample.c
+++ b/src/pulse/sample.c
@@ -80,6 +80,16 @@ size_t pa_usec_to_bytes(pa_usec_t t, const pa_sample_spec *spec) {
     return (size_t) (((t * spec->rate) / PA_USEC_PER_SEC)) * pa_frame_size(spec);
 }
 
+pa_sample_spec* pa_sample_spec_init(pa_sample_spec *spec) {
+    pa_assert(spec);
+
+    spec->format = PA_SAMPLE_INVALID;
+    spec->rate = 0;
+    spec->channels = 0;
+
+    return spec;
+}
+
 int pa_sample_spec_valid(const pa_sample_spec *spec) {
     pa_assert(spec);
 
diff --git a/src/pulse/sample.h b/src/pulse/sample.h
index 3f1b2fc..0053bf0 100644
--- a/src/pulse/sample.h
+++ b/src/pulse/sample.h
@@ -232,6 +232,11 @@ pa_usec_t pa_bytes_to_usec(uint64_t length, const pa_sample_spec *spec) PA_GCC_P
  * return values. \since 0.9 */
 size_t pa_usec_to_bytes(pa_usec_t t, const pa_sample_spec *spec) PA_GCC_PURE;
 
+/** Initialize the specified sample spec and return a pointer to
+ * it. The sample spec will have a defined state but
+ * pa_sample_spec_valid() will fail for it. \since 0.9.13 */
+pa_sample_spec* pa_sample_spec_init(pa_sample_spec *spec);
+
 /** Return non-zero when the sample type specification is valid */
 int pa_sample_spec_valid(const pa_sample_spec *spec) PA_GCC_PURE;
 

commit d56f3751fe234162ee71c573fd4be9086af35ea4
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Oct 3 17:14:02 2008 +0200

    treat a channel map only then as compatible with a sample spec if it is valid

diff --git a/src/pulse/channelmap.c b/src/pulse/channelmap.c
index db6577e..fd313bd 100644
--- a/src/pulse/channelmap.c
+++ b/src/pulse/channelmap.c
@@ -569,5 +569,11 @@ int pa_channel_map_compatible(const pa_channel_map *map, const pa_sample_spec *s
     pa_assert(map);
     pa_assert(ss);
 
+    if (!pa_channel_map_valid(map))
+        return 0;
+
+    if (!pa_sample_spec_valid(ss))
+        return 0;
+
     return map->channels == ss->channels;
 }

commit 7c2cb775836abc700a8b1e68831ff914ef726303
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Oct 3 17:14:35 2008 +0200

    a bit of late pa_bool_t'ization

diff --git a/src/pulsecore/namereg.c b/src/pulsecore/namereg.c
index ad697ed..ad702e4 100644
--- a/src/pulsecore/namereg.c
+++ b/src/pulsecore/namereg.c
@@ -97,7 +97,7 @@ void pa_namereg_free(pa_core *c) {
     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) {
+const char *pa_namereg_register(pa_core *c, const char *name, pa_namereg_type_t type, void *data, pa_bool_t fail) {
     struct namereg_entry *e;
     char *n = NULL;
 
diff --git a/src/pulsecore/namereg.h b/src/pulsecore/namereg.h
index 3c1de8e..f458100 100644
--- a/src/pulsecore/namereg.h
+++ b/src/pulsecore/namereg.h
@@ -35,7 +35,7 @@ typedef enum pa_namereg_type {
 
 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);
+const char *pa_namereg_register(pa_core *c, const char *name, pa_namereg_type_t type, void *data, pa_bool_t 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, pa_bool_t autoload);
 int pa_namereg_set_default(pa_core*c, const char *name, pa_namereg_type_t type);

commit 2367212ec3bf399fba070994619b4caa749f89b8
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Oct 3 17:14:58 2008 +0200

    make a few casts explicit to remove compiler warnings

diff --git a/src/pulsecore/sample-util.c b/src/pulsecore/sample-util.c
index 5119ebd..7b9ac7b 100644
--- a/src/pulsecore/sample-util.c
+++ b/src/pulsecore/sample-util.c
@@ -105,7 +105,7 @@ static void calc_linear_integer_volume(int32_t linear[], const pa_cvolume *volum
     pa_assert(volume);
 
     for (channel = 0; channel < volume->channels; channel++)
-        linear[channel] = lrint(pa_sw_volume_to_linear(volume->values[channel]) * 0x10000);
+        linear[channel] = (int32_t) lrint(pa_sw_volume_to_linear(volume->values[channel]) * 0x10000);
 }
 
 static void calc_linear_float_volume(float linear[], const pa_cvolume *volume) {
@@ -132,7 +132,7 @@ static void calc_linear_integer_stream_volumes(pa_mix_info streams[], unsigned n
 
         for (channel = 0; channel < spec->channels; channel++) {
             pa_mix_info *m = streams + k;
-            m->linear[channel].i = lrint(pa_sw_volume_to_linear(m->volume.values[channel]) * linear[channel] * 0x10000);
+            m->linear[channel].i = (int32_t) lrint(pa_sw_volume_to_linear(m->volume.values[channel]) * linear[channel] * 0x10000);
         }
     }
 }

commit db975c7127c15a527ef6277a695eba2870613637
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Oct 3 17:15:43 2008 +0200

    extend documentation for pa_channel_map_init()

diff --git a/src/pulse/channelmap.h b/src/pulse/channelmap.h
index d2dd6f8..8ea3dae 100644
--- a/src/pulse/channelmap.h
+++ b/src/pulse/channelmap.h
@@ -175,7 +175,9 @@ typedef struct pa_channel_map {
     /**< Channel labels */
 } pa_channel_map;
 
-/** Initialize the specified channel map and return a pointer to it */
+/** Initialize the specified channel map and return a pointer to
+ * it. The channel map will have a defined state but
+ * pa_channel_map_valid() will fail for it. */
 pa_channel_map* pa_channel_map_init(pa_channel_map *m);
 
 /** Initialize the specified channel map for monoaural audio and return a pointer to it */

commit be77bcd9ad7e51e51cb3c84d2aed9bd13ddd0a27
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Oct 3 17:16:55 2008 +0200

    add new API call pa_cvolume_init()

diff --git a/src/pulse/volume.c b/src/pulse/volume.c
index 60a86be..7c0522e 100644
--- a/src/pulse/volume.c
+++ b/src/pulse/volume.c
@@ -47,6 +47,19 @@ int pa_cvolume_equal(const pa_cvolume *a, const pa_cvolume *b) {
     return 1;
 }
 
+pa_cvolume* pa_cvolume_init(pa_cvolume *a) {
+    unsigned c;
+
+    pa_assert(a);
+
+    a->channels = 0;
+
+    for (c = 0; c < PA_CHANNELS_MAX; c++)
+        a->values[c] = (pa_volume_t) -1;
+
+    return a;
+}
+
 pa_cvolume* pa_cvolume_set(pa_cvolume *a, unsigned channels, pa_volume_t v) {
     int i;
 
@@ -88,7 +101,7 @@ pa_volume_t pa_cvolume_max(const pa_cvolume *a) {
 }
 
 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));
+    return pa_sw_volume_from_linear(pa_sw_volume_to_linear(a) * pa_sw_volume_to_linear(b));
 }
 
 #define USER_DECIBEL_RANGE 60
diff --git a/src/pulse/volume.h b/src/pulse/volume.h
index d612c7f..4b2f3a7 100644
--- a/src/pulse/volume.h
+++ b/src/pulse/volume.h
@@ -116,6 +116,11 @@ typedef struct pa_cvolume {
 /** Return non-zero when *a == *b */
 int pa_cvolume_equal(const pa_cvolume *a, const pa_cvolume *b) PA_GCC_PURE;
 
+/** Initialize the specified volume and return a pointer to
+ * it. The sample spec will have a defined state but
+ * pa_cvolume_valid() will fail for it. \since 0.9.13 */
+pa_cvolume* pa_cvolume_init(pa_cvolume *a);
+
 /** Set the volume of all channels to PA_VOLUME_NORM */
 #define pa_cvolume_reset(a, n) pa_cvolume_set((a), (n), PA_VOLUME_NORM)
 

commit 619ed8a82d05ec2c505600ed6937574739220400
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Oct 3 17:42:38 2008 +0200

    add new API call pa_cvolume_snprint_dB()

diff --git a/src/map-file b/src/map-file
index 67a5ee3..2ef2ad6 100644
--- a/src/map-file
+++ b/src/map-file
@@ -103,6 +103,7 @@ pa_cvolume_max;
 pa_cvolume_remap;
 pa_cvolume_set;
 pa_cvolume_snprint;
+pa_cvolume_snprint_dB;
 pa_cvolume_valid;
 pa_ext_stream_restore_delete;
 pa_ext_stream_restore_read;
diff --git a/src/pulse/volume.c b/src/pulse/volume.c
index 7c0522e..4d5fcf0 100644
--- a/src/pulse/volume.c
+++ b/src/pulse/volume.c
@@ -141,7 +141,7 @@ double pa_sw_volume_to_linear(pa_volume_t v) {
 
 char *pa_cvolume_snprint(char *s, size_t l, const pa_cvolume *c) {
     unsigned channel;
-    int first = 1;
+    pa_bool_t first = TRUE;
     char *e;
 
     pa_assert(s);
@@ -164,7 +164,38 @@ char *pa_cvolume_snprint(char *s, size_t l, const pa_cvolume *c) {
                       (c->values[channel]*100)/PA_VOLUME_NORM);
 
         e = strchr(e, 0);
-        first = 0;
+        first = FALSE;
+    }
+
+    return s;
+}
+
+char *pa_cvolume_snprint_dB(char *s, size_t l, const pa_cvolume *c) {
+    unsigned channel;
+    pa_bool_t first = TRUE;
+    char *e;
+
+    pa_assert(s);
+    pa_assert(l > 0);
+    pa_assert(c);
+
+    pa_init_i18n();
+
+    if (!pa_cvolume_valid(c)) {
+        pa_snprintf(s, l, _("(invalid)"));
+        return s;
+    }
+
+    *(e = s) = 0;
+
+    for (channel = 0; channel < c->channels && l > 1; channel++) {
+        l -= pa_snprintf(e, l, "%s%u: %0.2f dB",
+                      first ? "" : " ",
+                      channel,
+                      pa_sw_volume_to_dB(c->values[channel]));
+
+        e = strchr(e, 0);
+        first = FALSE;
     }
 
     return s;
diff --git a/src/pulse/volume.h b/src/pulse/volume.h
index 4b2f3a7..d6eb606 100644
--- a/src/pulse/volume.h
+++ b/src/pulse/volume.h
@@ -136,6 +136,16 @@ pa_cvolume* pa_cvolume_set(pa_cvolume *a, unsigned channels, pa_volume_t v);
 /** Pretty print a volume structure */
 char *pa_cvolume_snprint(char *s, size_t l, const pa_cvolume *c);
 
+/** Maximum length of the strings returned by
+ * pa_cvolume_snprint_dB(). Please note that this value can change with
+ * any release without warning and without being considered API or ABI
+ * breakage. You should not use this definition anywhere where it
+ * might become part of an ABI. \since 0.9.13 */
+#define PA_CVOLUME_SNPRINT_DB_MAX 448
+
+/** Pretty print a volume structure but show dB values. \since 0.9.13 */
+char *pa_cvolume_snprint_dB(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_GCC_PURE;
 
diff --git a/src/tests/voltest.c b/src/tests/voltest.c
index 5b26c0f..bbf3ea1 100644
--- a/src/tests/voltest.c
+++ b/src/tests/voltest.c
@@ -5,6 +5,7 @@
 
 int main(int argc, char *argv[]) {
     pa_volume_t v;
+    pa_cvolume cv;
 
     for (v = PA_VOLUME_MUTED; v <= PA_VOLUME_NORM*2; v += 256) {
 
@@ -13,6 +14,17 @@ int main(int argc, char *argv[]) {
 
         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));
+    }
+
+    for (v = PA_VOLUME_MUTED; v <= PA_VOLUME_NORM*2; v += 256) {
+        char s[PA_CVOLUME_SNPRINT_MAX], t[PA_CVOLUME_SNPRINT_DB_MAX];
+
+        pa_cvolume_set(&cv, 2, v);
+
+        printf("Volume: %3i [%s] [%s]\n",
+               v,
+               pa_cvolume_snprint(s, sizeof(s), &cv),
+               pa_cvolume_snprint_dB(t, sizeof(t), &cv));
 
     }
 

commit ebb2ecbe12b30ced855b6497d903e3250e356327
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Oct 3 17:43:40 2008 +0200

    add new API call pa_cvolume_compatible()

diff --git a/src/map-file b/src/map-file
index 2ef2ad6..7f38be1 100644
--- a/src/map-file
+++ b/src/map-file
@@ -98,6 +98,7 @@ pa_context_unload_module;
 pa_context_unref;
 pa_cvolume_avg;
 pa_cvolume_channels_equal_to;
+pa_cvolume_compatible;
 pa_cvolume_equal;
 pa_cvolume_max;
 pa_cvolume_remap;
diff --git a/src/pulse/volume.c b/src/pulse/volume.c
index 4d5fcf0..e809ef9 100644
--- a/src/pulse/volume.c
+++ b/src/pulse/volume.c
@@ -325,3 +325,17 @@ pa_cvolume *pa_cvolume_remap(pa_cvolume *v, pa_channel_map *from, pa_channel_map
     *v = result;
     return v;
 }
+
+int pa_cvolume_compatible(const pa_cvolume *v, const pa_sample_spec *ss) {
+
+    pa_assert(v);
+    pa_assert(ss);
+
+    if (!pa_cvolume_valid(v))
+        return 0;
+
+    if (!pa_sample_spec_valid(ss))
+        return 0;
+
+    return v->channels == ss->channels;
+}
diff --git a/src/pulse/volume.h b/src/pulse/volume.h
index d6eb606..90fb59e 100644
--- a/src/pulse/volume.h
+++ b/src/pulse/volume.h
@@ -192,6 +192,10 @@ double pa_sw_volume_to_linear(pa_volume_t v) PA_GCC_CONST;
 /** Remap a volume from one channel mapping to a different channel mapping. \since 0.9.12 */
 pa_cvolume *pa_cvolume_remap(pa_cvolume *v, pa_channel_map *from, pa_channel_map *to);
 
+/** Return non-zero if the specified volume is compatible with
+ * the specified sample spec. \since 0.9.13 */
+int pa_cvolume_compatible(const pa_cvolume *v, const pa_sample_spec *ss) PA_GCC_PURE;
+
 PA_C_DECL_END
 
 #endif

commit c0a9e8bfb77d5c8dbc8f788b14b3d2b02368d2e9
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Oct 3 17:44:17 2008 +0200

    add missing calls to map file

diff --git a/src/map-file b/src/map-file
index 7f38be1..50cb780 100644
--- a/src/map-file
+++ b/src/map-file
@@ -100,6 +100,7 @@ pa_cvolume_avg;
 pa_cvolume_channels_equal_to;
 pa_cvolume_compatible;
 pa_cvolume_equal;
+pa_cvolume_init;
 pa_cvolume_max;
 pa_cvolume_remap;
 pa_cvolume_set;
@@ -162,6 +163,7 @@ pa_proplist_update;
 pa_sample_format_to_string;
 pa_sample_size;
 pa_sample_spec_equal;
+pa_sample_spec_init;
 pa_sample_spec_snprint;
 pa_sample_spec_valid;
 pa_signal_done;

commit bde142c237924870e9b09d09d5d2a7186de2e249
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Oct 3 17:45:04 2008 +0200

    when checking the validity of a cvolume check whether all values are not -1

diff --git a/src/pulse/volume.c b/src/pulse/volume.c
index e809ef9..0ef02d9 100644
--- a/src/pulse/volume.c
+++ b/src/pulse/volume.c
@@ -233,11 +233,17 @@ pa_cvolume *pa_sw_cvolume_multiply(pa_cvolume *dest, const pa_cvolume *a, const
 }
 
 int pa_cvolume_valid(const pa_cvolume *v) {
+    unsigned c;
+
     pa_assert(v);
 
     if (v->channels <= 0 || v->channels > PA_CHANNELS_MAX)
         return 0;
 
+    for (c = 0; c < v->channels; c++)
+        if (v->values[c] == (pa_volume_t) -1)
+            return 0;
+
     return 1;
 }
 

commit 28af9944fe0560229efdcf9f0180568fd5a444c3
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Oct 3 17:45:55 2008 +0200

    increase PA_CVOLUME_SNPRINT_MAX to a proper value and document that it is not considered part of the ABI

diff --git a/src/pulse/channelmap.h b/src/pulse/channelmap.h
index 8ea3dae..d7d19d7 100644
--- a/src/pulse/channelmap.h
+++ b/src/pulse/channelmap.h
@@ -204,7 +204,11 @@ const char* pa_channel_position_to_string(pa_channel_position_t pos) PA_GCC_PURE
 /** Return a human readable text label for the specified channel position. \since 0.9.7 */
 const char* pa_channel_position_to_pretty_string(pa_channel_position_t pos);
 
-/** The maximum length of strings returned by pa_channel_map_snprint() */
+/** The maximum length of strings returned by
+ * pa_channel_map_snprint(). Please note that this value can change
+ * with any release without warning and without being considered API
+ * or ABI breakage. You should not use this definition anywhere where
+ * it might become part of an ABI. */
 #define PA_CHANNEL_MAP_SNPRINT_MAX 336
 
 /** Make a humand readable string from the specified channel map */
diff --git a/src/pulse/sample.h b/src/pulse/sample.h
index 0053bf0..3c7dd0e 100644
--- a/src/pulse/sample.h
+++ b/src/pulse/sample.h
@@ -249,7 +249,11 @@ 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_GCC_PURE;
 
-/** Maximum required string length for pa_sample_spec_snprint() */
+/** Maximum required string length for
+ * pa_sample_spec_snprint(). Please note that this value can change
+ * with any release without warning and without being considered API
+ * or ABI breakage. You should not use this definition anywhere where
+ * it might become part of an ABI. */
 #define PA_SAMPLE_SPEC_SNPRINT_MAX 32
 
 /** Pretty print a sample type specification to a string */
diff --git a/src/pulse/volume.h b/src/pulse/volume.h
index 90fb59e..9f6e5f0 100644
--- a/src/pulse/volume.h
+++ b/src/pulse/volume.h
@@ -130,8 +130,12 @@ pa_cvolume* pa_cvolume_init(pa_cvolume *a);
 /** Set the volume of all channels to the specified parameter */
 pa_cvolume* pa_cvolume_set(pa_cvolume *a, unsigned channels, pa_volume_t v);
 
-/** Maximum length of the strings returned by pa_cvolume_snprint() */
-#define PA_CVOLUME_SNPRINT_MAX 64
+/** Maximum length of the strings returned by
+ * pa_cvolume_snprint(). Please note that this value can change with
+ * any release without warning and without being considered API or ABI
+ * breakage. You should not use this definition anywhere where it
+ * might become part of an ABI.*/
+#define PA_CVOLUME_SNPRINT_MAX 320
 
 /** Pretty print a volume structure */
 char *pa_cvolume_snprint(char *s, size_t l, const pa_cvolume *c);

commit c0815deb4add5ae4598de7c2c0589d1f5dc1c641
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Oct 3 19:49:15 2008 +0200

    allow - in sample names

diff --git a/src/pulsecore/core-scache.c b/src/pulsecore/core-scache.c
index 814dff5..1d080e1 100644
--- a/src/pulsecore/core-scache.c
+++ b/src/pulsecore/core-scache.c
@@ -98,7 +98,7 @@ static pa_scache_entry* scache_add_item(pa_core *c, const char *name) {
     pa_assert(c);
     pa_assert(name);
 
-    if ((e = pa_namereg_get(c, name, PA_NAMEREG_SAMPLE, 0))) {
+    if ((e = pa_namereg_get(c, name, PA_NAMEREG_SAMPLE, FALSE))) {
         if (e->memchunk.memblock)
             pa_memblock_unref(e->memchunk.memblock);
 
@@ -111,7 +111,7 @@ static pa_scache_entry* scache_add_item(pa_core *c, const char *name) {
     } else {
         e = pa_xnew(pa_scache_entry, 1);
 
-        if (!pa_namereg_register(c, name, PA_NAMEREG_SAMPLE, e, 1)) {
+        if (!pa_namereg_register(c, name, PA_NAMEREG_SAMPLE, e, TRUE)) {
             pa_xfree(e);
             return NULL;
         }
@@ -134,9 +134,9 @@ static pa_scache_entry* scache_add_item(pa_core *c, const char *name) {
     e->lazy = FALSE;
     e->last_used_time = 0;
 
-    memset(&e->sample_spec, 0, sizeof(e->sample_spec));
+    pa_sample_spec_init(&e->sample_spec);
     pa_channel_map_init(&e->channel_map);
-    pa_cvolume_reset(&e->volume, PA_CHANNELS_MAX);
+    pa_cvolume_init(&e->volume);
 
     pa_proplist_sets(e->proplist, PA_PROP_MEDIA_ROLE, "event");
 
@@ -159,10 +159,12 @@ int pa_scache_add_item(
     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));
+    pa_assert(!map || (pa_channel_map_valid(map) && ss && pa_channel_map_compatible(map, ss)));
 
-    if (ss && !map)
+    if (ss && !map) {
         pa_channel_map_init_extend(&tmap, ss->channels, PA_CHANNEL_MAP_DEFAULT);
+        map = &tmap;
+    }
 
     if (chunk && chunk->length > PA_SCACHE_ENTRY_SIZE_MAX)
         return -1;
@@ -170,12 +172,13 @@ int pa_scache_add_item(
     if (!(e = scache_add_item(c, name)))
         return -1;
 
-    memset(&e->sample_spec, 0, sizeof(e->sample_spec));
+    pa_sample_spec_init(&e->sample_spec);
     pa_channel_map_init(&e->channel_map);
+    pa_cvolume_init(&e->volume);
 
     if (ss) {
         e->sample_spec = *ss;
-        e->volume.channels = e->sample_spec.channels;
+        pa_cvolume_reset(&e->volume, ss->channels);
     }
 
     if (map)
@@ -310,17 +313,21 @@ int pa_scache_play_item(pa_core *c, const char *name, pa_sink *sink, pa_volume_t
     pa_assert(name);
     pa_assert(sink);
 
-    if (!(e = pa_namereg_get(c, name, PA_NAMEREG_SAMPLE, 1)))
+    if (!(e = pa_namereg_get(c, name, PA_NAMEREG_SAMPLE, FALSE)))
         return -1;
 
     if (e->lazy && !e->memchunk.memblock) {
+        pa_channel_map old_channel_map = e->channel_map;
+
         if (pa_sound_file_load(c->mempool, e->filename, &e->sample_spec, &e->channel_map, &e->memchunk) < 0)
             return -1;
 
         pa_subscription_post(c, PA_SUBSCRIPTION_EVENT_SAMPLE_CACHE|PA_SUBSCRIPTION_EVENT_CHANGE, e->index);
 
-        if (e->volume.channels > e->sample_spec.channels)
-            e->volume.channels = e->sample_spec.channels;
+        if (pa_cvolume_valid(&e->volume))
+            pa_cvolume_remap(&e->volume, &old_channel_map, &e->channel_map);
+        else
+            pa_cvolume_reset(&e->volume, e->sample_spec.channels);
     }
 
     if (!e->memchunk.memblock)
@@ -383,7 +390,7 @@ uint32_t pa_scache_get_id_by_name(pa_core *c, const char *name) {
     pa_assert(c);
     pa_assert(name);
 
-    if (!(e = pa_namereg_get(c, name, PA_NAMEREG_SAMPLE, 0)))
+    if (!(e = pa_namereg_get(c, name, PA_NAMEREG_SAMPLE, FALSE)))
         return PA_IDXSET_INVALID;
 
     return e->index;
diff --git a/src/pulsecore/namereg.c b/src/pulsecore/namereg.c
index ad702e4..ecd8def 100644
--- a/src/pulsecore/namereg.c
+++ b/src/pulsecore/namereg.c
@@ -51,6 +51,7 @@ static pa_bool_t is_valid_char(char c) {
         (c >= 'A' && c <= 'Z') ||
         (c >= '0' && c <= '9') ||
         c == '.' ||
+        c == '-' ||
         c == '_';
 }
 

commit 7a1a1478819c0f4716f0612f1121a0429f455fa9
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Oct 3 22:21:27 2008 +0200

    rename pa_cvolume_snprint_dB to pa_sw_cvolume_snprint_dB since it is
    useful only for software volumes

diff --git a/src/map-file b/src/map-file
index 50cb780..7211914 100644
--- a/src/map-file
+++ b/src/map-file
@@ -105,7 +105,7 @@ pa_cvolume_max;
 pa_cvolume_remap;
 pa_cvolume_set;
 pa_cvolume_snprint;
-pa_cvolume_snprint_dB;
+pa_sw_cvolume_snprint_dB;
 pa_cvolume_valid;
 pa_ext_stream_restore_delete;
 pa_ext_stream_restore_read;
diff --git a/src/pulse/volume.c b/src/pulse/volume.c
index 0ef02d9..0412819 100644
--- a/src/pulse/volume.c
+++ b/src/pulse/volume.c
@@ -170,7 +170,7 @@ char *pa_cvolume_snprint(char *s, size_t l, const pa_cvolume *c) {
     return s;
 }
 
-char *pa_cvolume_snprint_dB(char *s, size_t l, const pa_cvolume *c) {
+char *pa_sw_cvolume_snprint_dB(char *s, size_t l, const pa_cvolume *c) {
     unsigned channel;
     pa_bool_t first = TRUE;
     char *e;
diff --git a/src/pulse/volume.h b/src/pulse/volume.h
index 9f6e5f0..bfd8ca5 100644
--- a/src/pulse/volume.h
+++ b/src/pulse/volume.h
@@ -145,10 +145,10 @@ char *pa_cvolume_snprint(char *s, size_t l, const pa_cvolume *c);
  * any release without warning and without being considered API or ABI
  * breakage. You should not use this definition anywhere where it
  * might become part of an ABI. \since 0.9.13 */
-#define PA_CVOLUME_SNPRINT_DB_MAX 448
+#define PA_SW_CVOLUME_SNPRINT_DB_MAX 448
 
 /** Pretty print a volume structure but show dB values. \since 0.9.13 */
-char *pa_cvolume_snprint_dB(char *s, size_t l, const pa_cvolume *c);
+char *pa_sw_cvolume_snprint_dB(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_GCC_PURE;
diff --git a/src/tests/voltest.c b/src/tests/voltest.c
index bbf3ea1..5bfc97e 100644
--- a/src/tests/voltest.c
+++ b/src/tests/voltest.c
@@ -17,14 +17,14 @@ int main(int argc, char *argv[]) {
     }
 
     for (v = PA_VOLUME_MUTED; v <= PA_VOLUME_NORM*2; v += 256) {
-        char s[PA_CVOLUME_SNPRINT_MAX], t[PA_CVOLUME_SNPRINT_DB_MAX];
+        char s[PA_CVOLUME_SNPRINT_MAX], t[PA_SW_CVOLUME_SNPRINT_DB_MAX];
 
         pa_cvolume_set(&cv, 2, v);
 
         printf("Volume: %3i [%s] [%s]\n",
                v,
                pa_cvolume_snprint(s, sizeof(s), &cv),
-               pa_cvolume_snprint_dB(t, sizeof(t), &cv));
+               pa_sw_cvolume_snprint_dB(t, sizeof(t), &cv));
 
     }
 

commit 443ea47ee07f990616f3a367842b16aa739c6283
Author: Luiz Augusto von Dentz <luiz.dentz at openbossa.org>
Date:   Wed Oct 1 11:29:50 2008 -0300

    Add match rules for org.bluez.Headset and org.bluez.AudioSink.

diff --git a/src/modules/bluetooth/module-bluetooth-discover.c b/src/modules/bluetooth/module-bluetooth-discover.c
index 1494431..cb5ee35 100644
--- a/src/modules/bluetooth/module-bluetooth-discover.c
+++ b/src/modules/bluetooth/module-bluetooth-discover.c
@@ -918,6 +918,18 @@ int pa__init(pa_module* m) {
         goto fail;
     }
 
+    dbus_bus_add_match(pa_dbus_connection_get(u->conn), "type='signal',sender='org.bluez',interface='org.bluez.Headset,member='Connected''", &err);
+    if (dbus_error_is_set(&err)) {
+        pa_log_error("Unable to subscribe to org.bluez.Headset signals: %s: %s", err.name, err.message);
+        goto fail;
+    }
+
+    dbus_bus_add_match(pa_dbus_connection_get(u->conn), "type='signal',sender='org.bluez',interface='org.bluez.AudioSink,member='Connected''", &err);
+    if (dbus_error_is_set(&err)) {
+        pa_log_error("Unable to subscribe to org.bluez.AudioSink signals: %s: %s", err.name, err.message);
+        goto fail;
+    }
+
     return 0;
 
 fail:

commit 3b427b7014ffe8d449a3a1336e483b4f949c9417
Author: Luiz Augusto von Dentz <luiz.dentz at openbossa.org>
Date:   Wed Oct 1 11:35:51 2008 -0300

    Add signal handlers for Connected signals.

diff --git a/src/modules/bluetooth/module-bluetooth-discover.c b/src/modules/bluetooth/module-bluetooth-discover.c
index cb5ee35..ae414a7 100644
--- a/src/modules/bluetooth/module-bluetooth-discover.c
+++ b/src/modules/bluetooth/module-bluetooth-discover.c
@@ -843,6 +843,18 @@ static DBusHandlerResult filter_cb(DBusConnection *bus, DBusMessage *msg, void *
                 load_module_for_device(u, d);
             }
         }
+
+    } else if (dbus_message_is_signal(msg, "org.bluez.Headset", "Connected") ||
+               dbus_message_is_signal(msg, "org.bluez.AudioSink", "Connected")) {
+
+        if (!dbus_message_iter_init(msg, &arg_i))
+            pa_log("dbus: message has no parameters");
+        else {
+            struct device *d;
+
+            if ((d = device_find(u, dbus_message_get_path(msg))))
+                load_module_for_device(u, d);
+        }
     }
 
     dbus_error_free(&err);

commit 0be845f3a94aaf271583629d395d298589def3fd
Author: Luiz Augusto von Dentz <luiz.dentz at openbossa.org>
Date:   Wed Oct 1 11:37:00 2008 -0300

    Remove PropertyChanged signal handler.

diff --git a/src/modules/bluetooth/module-bluetooth-discover.c b/src/modules/bluetooth/module-bluetooth-discover.c
index ae414a7..9c61ed2 100644
--- a/src/modules/bluetooth/module-bluetooth-discover.c
+++ b/src/modules/bluetooth/module-bluetooth-discover.c
@@ -828,22 +828,6 @@ static DBusHandlerResult filter_cb(DBusConnection *bus, DBusMessage *msg, void *
             }
         }
 
-    } else if (dbus_message_is_signal(msg, "org.bluez.Device", "PropertyChanged")) {
-
-        if (!dbus_message_iter_init(msg, &arg_i))
-            pa_log("dbus: message has no parameters");
-        else {
-            struct device *d;
-
-            if ((d = device_find(u, dbus_message_get_path(msg)))) {
-                parse_device_property(u, d, &arg_i);
-
-                /* Hmm, something changed, let's try to reconnect if we
-                 * aren't connected yet */
-                load_module_for_device(u, d);
-            }
-        }
-
     } else if (dbus_message_is_signal(msg, "org.bluez.Headset", "Connected") ||
                dbus_message_is_signal(msg, "org.bluez.AudioSink", "Connected")) {
 

commit 04677cb9259126ae3f63878963583b7af34daf69
Author: Luiz Augusto von Dentz <luiz.dentz at openbossa.org>
Date:   Wed Oct 1 12:04:55 2008 -0300

    Fix match rule problems.

diff --git a/src/modules/bluetooth/module-bluetooth-discover.c b/src/modules/bluetooth/module-bluetooth-discover.c
index 9c61ed2..90c50da 100644
--- a/src/modules/bluetooth/module-bluetooth-discover.c
+++ b/src/modules/bluetooth/module-bluetooth-discover.c
@@ -914,13 +914,13 @@ int pa__init(pa_module* m) {
         goto fail;
     }
 
-    dbus_bus_add_match(pa_dbus_connection_get(u->conn), "type='signal',sender='org.bluez',interface='org.bluez.Headset,member='Connected''", &err);
+    dbus_bus_add_match(pa_dbus_connection_get(u->conn), "type='signal',sender='org.bluez',interface='org.bluez.Headset',member='Connected'", &err);
     if (dbus_error_is_set(&err)) {
         pa_log_error("Unable to subscribe to org.bluez.Headset signals: %s: %s", err.name, err.message);
         goto fail;
     }
 
-    dbus_bus_add_match(pa_dbus_connection_get(u->conn), "type='signal',sender='org.bluez',interface='org.bluez.AudioSink,member='Connected''", &err);
+    dbus_bus_add_match(pa_dbus_connection_get(u->conn), "type='signal',sender='org.bluez',interface='org.bluez.AudioSink',member='Connected'", &err);
     if (dbus_error_is_set(&err)) {
         pa_log_error("Unable to subscribe to org.bluez.AudioSink signals: %s: %s", err.name, err.message);
         goto fail;

commit 20f68bcc461fd20926f8339c97217720f94d57df
Author: Luiz Augusto von Dentz <luiz.dentz at openbossa.org>
Date:   Wed Oct 1 12:16:16 2008 -0300

    Fix Connected signal handler.

diff --git a/src/modules/bluetooth/module-bluetooth-discover.c b/src/modules/bluetooth/module-bluetooth-discover.c
index 90c50da..985a1d2 100644
--- a/src/modules/bluetooth/module-bluetooth-discover.c
+++ b/src/modules/bluetooth/module-bluetooth-discover.c
@@ -831,14 +831,10 @@ static DBusHandlerResult filter_cb(DBusConnection *bus, DBusMessage *msg, void *
     } else if (dbus_message_is_signal(msg, "org.bluez.Headset", "Connected") ||
                dbus_message_is_signal(msg, "org.bluez.AudioSink", "Connected")) {
 
-        if (!dbus_message_iter_init(msg, &arg_i))
-            pa_log("dbus: message has no parameters");
-        else {
-            struct device *d;
+        struct device *d;
 
-            if ((d = device_find(u, dbus_message_get_path(msg))))
+        if ((d = device_find(u, dbus_message_get_path(msg))))
                 load_module_for_device(u, d);
-        }
     }
 
     dbus_error_free(&err);

commit b205fcc17c9958ece69d0038ad282a109c201686
Author: Luiz Augusto von Dentz <luiz.dentz at openbossa.org>
Date:   Wed Oct 1 20:15:09 2008 -0300

    Cleanup module-bluetooth-discover.

diff --git a/src/modules/bluetooth/module-bluetooth-device.c b/src/modules/bluetooth/module-bluetooth-device.c
index 395d54f..bf9bad6 100644
--- a/src/modules/bluetooth/module-bluetooth-device.c
+++ b/src/modules/bluetooth/module-bluetooth-device.c
@@ -497,13 +497,6 @@ static int bt_getstreamfd(struct userdata *u) {
         return -errno;
     }
 
-    if (u->transport == BT_CAPABILITIES_TRANSPORT_A2DP) {
-        if (pa_socket_set_sndbuf(u->stream_fd, 10U*u->link_mtu) < 0) {
-            pa_log_error("Failed to set socket options for A2DP: %s (%d)",pa_cstrerror(errno), errno);
-            return -errno;
-        }
-    }
-
 //   if (setsockopt(u->stream_fd, SOL_SCO, SCO_TXBUFS, &period_count, sizeof(period_count)) == 0)
 //       return 0;
 //   if (setsockopt(u->stream_fd, SOL_SCO, SO_SNDBUF, &period_count, sizeof(period_count)) == 0)
diff --git a/src/modules/bluetooth/module-bluetooth-discover.c b/src/modules/bluetooth/module-bluetooth-discover.c
index 985a1d2..88d4eef 100644
--- a/src/modules/bluetooth/module-bluetooth-discover.c
+++ b/src/modules/bluetooth/module-bluetooth-discover.c
@@ -42,10 +42,11 @@ PA_MODULE_DESCRIPTION("Detect available bluetooth audio devices and load bluetoo
 PA_MODULE_VERSION(PACKAGE_VERSION);
 PA_MODULE_USAGE("");
 
-#define HSP_HS_UUID             "00001108-0000-1000-8000-00805F9B34FB"
-#define HFP_HS_UUID             "0000111E-0000-1000-8000-00805F9B34FB"
-#define A2DP_SOURCE_UUID        "0000110A-0000-1000-8000-00805F9B34FB"
-#define A2DP_SINK_UUID          "0000110B-0000-1000-8000-00805F9B34FB"
+struct module {
+    char *profile;
+    pa_module *pa_m;
+    PA_LLIST_FIELDS(struct module);
+};
 
 struct uuid {
     char *uuid;
@@ -56,33 +57,40 @@ struct device {
     char *name;
     char *object_path;
     int paired;
-    struct adapter *adapter;
     char *alias;
     int connected;
     PA_LLIST_HEAD(struct uuid, uuid_list);
     char *address;
     int class;
     int trusted;
-    const char *audio_profile;
-    uint32_t module_index;
+    PA_LLIST_HEAD(struct module, module_list);
     PA_LLIST_FIELDS(struct device);
 };
 
-struct adapter {
-    char *object_path;
-    char *name;
-    char *mode;
-    char *address;
-    PA_LLIST_HEAD(struct device, device_list);
-    PA_LLIST_FIELDS(struct adapter);
-};
-
 struct userdata {
     pa_module *module;
     pa_dbus_connection *conn;
-    PA_LLIST_HEAD(struct adapter, adapter_list);
+    PA_LLIST_HEAD(struct device, device_list);
 };
 
+static struct module *module_new(const char *profile, pa_module *pa_m) {
+    struct module *m;
+
+    m = pa_xnew(struct module, 1);
+    m->profile = pa_xstrdup(profile);
+    m->pa_m = pa_m;
+    PA_LLIST_INIT(struct module, m);
+
+    return m;
+}
+
+static void module_free(struct module *m) {
+    pa_assert(m);
+
+    pa_xfree(m->profile);
+    pa_xfree(m);
+}
+
 static struct uuid *uuid_new(const char *uuid) {
     struct uuid *node;
 
@@ -100,32 +108,36 @@ static void uuid_free(struct uuid *uuid) {
     pa_xfree(uuid);
 }
 
-static struct device *device_new(struct adapter *adapter, const char *object_path) {
+static struct device *device_new(const char *object_path) {
     struct device *node;
 
     node = pa_xnew(struct device, 1);
     node->name = NULL;
     node->object_path = pa_xstrdup(object_path);
     node->paired = -1;
-    node->adapter = adapter;
     node->alias = NULL;
     node->connected = -1;
     PA_LLIST_HEAD_INIT(struct uuid, node->uuid_list);
     node->address = NULL;
     node->class = -1;
     node->trusted = -1;
-    node->audio_profile = NULL;
-    node->module_index = PA_INVALID_INDEX;
+    PA_LLIST_HEAD_INIT(struct module, node->module_list);
     PA_LLIST_INIT(struct device, node);
 
     return node;
 }
 
 static void device_free(struct device *device) {
+    struct module *m;
     struct uuid *i;
 
     pa_assert(device);
 
+    while ((m = device->module_list)) {
+        PA_LLIST_REMOVE(struct module, device->module_list, m);
+        module_free(m);
+    }
+
     while ((i = device->uuid_list)) {
         PA_LLIST_REMOVE(struct uuid, device->uuid_list, i);
         uuid_free(i);
@@ -138,350 +150,16 @@ static void device_free(struct device *device) {
     pa_xfree(device);
 }
 
-static struct adapter *adapter_new(const char *object_path) {
-    struct adapter *node;
-
-    node = pa_xnew(struct adapter, 1);
-    node->object_path = pa_xstrdup(object_path);
-    node->mode = NULL;
-    node->address = NULL;
-    node->name = NULL;
-
-    PA_LLIST_HEAD_INIT(struct device, node->device_list);
-    PA_LLIST_INIT(struct adapter, node);
-
-    return node;
-}
-
-static void adapter_free(struct adapter *adapter) {
+static struct device* device_find(struct userdata *u, const char *path) {
     struct device *i;
 
-    pa_assert(adapter);
-
-    while ((i = adapter->device_list)) {
-        PA_LLIST_REMOVE(struct device, adapter->device_list, i);
-        device_free(i);
-    }
-
-    pa_xfree(adapter->object_path);
-    pa_xfree(adapter->mode);
-    pa_xfree(adapter->address);
-    pa_xfree(adapter->name);
-    pa_xfree(adapter);
-}
-
-static struct adapter* adapter_find(struct userdata *u, const char *path) {
-    struct adapter *i;
-
-    for (i = u->adapter_list; i; i = i->next)
+    for (i = u->device_list; i; i = i->next)
         if (pa_streq(i->object_path, path))
             return i;
 
     return NULL;
 }
 
-static struct device* device_find(struct userdata *u, const char *path) {
-    struct adapter *j;
-    struct device *i;
-
-    for (j = u->adapter_list; j; j = j->next)
-        for (i = j->device_list; i; i = i->next)
-            if (pa_streq(i->object_path, path))
-                return i;
-
-    return NULL;
-}
-
-static const char *yes_no_na(int b) {
-    if (b < 0)
-        return "n/a";
-
-    return pa_yes_no(b);
-}
-
-static void print_devices(struct adapter *a) {
-    struct device *i;
-
-    pa_assert(a);
-
-    for (i = a->device_list; i; i = i->next) {
-        struct uuid *j;
-
-        if (pa_streq(i->object_path, "/DEVICE_HEAD"))
-            continue;
-
-        pa_log_debug("\t[ %s ]\n"
-                     "\t\tName = %s\n"
-                     "\t\tPaired = %s\n"
-                     "\t\tAdapter = %s\n"
-                     "\t\tAlias = %s\n"
-                     "\t\tConnected = %s\n"
-                     "\t\tAudio = %s\n",
-                     i->object_path,
-                     pa_strnull(i->name),
-                     yes_no_na(i->paired),
-                     i->adapter->object_path,
-                     pa_strnull(i->alias),
-                     yes_no_na(i->connected),
-                     pa_strnull(i->audio_profile));
-
-        pa_log_debug("\t\tUUIDs = ");
-        for (j = i->uuid_list; j; j = j->next) {
-
-            if (pa_streq(j->uuid, "UUID_HEAD"))
-                continue;
-
-            pa_log_debug("\t\t         %s", j->uuid);
-        }
-
-        pa_log_debug("\t\tAddress = %s\n"
-                     "\t\tClass = 0x%x\n"
-                     "\t\tTrusted = %s",
-                     i->address,
-                     i->class,
-                     yes_no_na(i->trusted));
-    }
-}
-
-static void print_adapters(struct userdata *u) {
-    struct adapter *i;
-
-    pa_assert(u);
-
-    for (i = u->adapter_list; i; i = i->next) {
-
-        if (pa_streq(i->object_path, "/ADAPTER_HEAD"))
-            continue;
-
-        pa_log_debug(
-                "[ %s ]\n"
-                "\tName = %s\n"
-                "\tMode = %s\n"
-                "\tAddress = %s\n",
-                i->object_path,
-                pa_strnull(i->name),
-                pa_strnull(i->mode),
-                pa_strnull(i->address));
-
-        print_devices(i);
-    }
-}
-
-static const char *strip_object_path(const char *op) {
-    const char *slash;
-
-    if ((slash = strrchr(op, '/')))
-        return slash+1;
-
-    return op;
-}
-
-static void load_module_for_device(struct userdata *u, struct device *d) {
-    char *args;
-    pa_module *m;
-
-    pa_assert(u);
-    pa_assert(d);
-
-    /* Check whether we already loaded a module for this device */
-    if (d->module_index != PA_INVALID_INDEX &&
-        pa_idxset_get_by_index(u->module->core->modules, d->module_index))
-        return;
-
-    /* Check whether this is an audio device */
-    if (!d->audio_profile) {
-        pa_log_debug("Ignoring %s since it is not an audio device.", d->object_path);
-        return;
-    }
-
-    args = pa_sprintf_malloc("sink_name=%s address=%s profile=%s", strip_object_path(d->object_path), d->address, d->audio_profile);
-    m = pa_module_load(u->module->core, "module-bluetooth-device", args);
-    pa_xfree(args);
-
-    if (!m) {
-        pa_log_debug("Failed to load module for device %s", d->object_path);
-        return;
-    }
-
-    d->module_index = m->index;
-}
-
-static void load_modules(struct userdata *u) {
-    struct device *d;
-    struct adapter *a;
-
-    pa_assert(u);
-
-    for (a = u->adapter_list; a; a = a->next)
-        for (d = a->device_list; d; d = d->next)
-            load_module_for_device(u, d);
-}
-
-static int parse_adapter_property(struct userdata *u, struct adapter *a, DBusMessageIter *i) {
-    const char *key;
-    DBusMessageIter variant_i;
-
-    pa_assert(u);
-    pa_assert(a);
-    pa_assert(i);
-
-    if (dbus_message_iter_get_arg_type(i) != DBUS_TYPE_STRING) {
-        pa_log("Property name not a string.");
-        return -1;
-    }
-
-    dbus_message_iter_get_basic(i, &key);
-
-    if (!dbus_message_iter_next(i)) {
-        pa_log("Property value missing");
-        return -1;
-    }
-
-    if (dbus_message_iter_get_arg_type(i) != DBUS_TYPE_VARIANT) {
-        pa_log("Property value not a variant.");
-        return -1;
-    }
-
-    dbus_message_iter_recurse(i, &variant_i);
-
-    if (dbus_message_iter_get_arg_type(&variant_i) == DBUS_TYPE_STRING) {
-        const char *value;
-        dbus_message_iter_get_basic(&variant_i, &value);
-
-        if (pa_streq(key, "Mode")) {
-            pa_xfree(a->mode);
-            a->mode = pa_xstrdup(value);
-        } else if (pa_streq(key, "Address")) {
-            pa_xstrdup(a->address);
-            a->address = pa_xstrdup(value);
-        } else if (pa_streq(key, "Name")) {
-            pa_xfree(a->name);
-            a->name = pa_xstrdup(value);
-        }
-    }
-
-    return 0;
-}
-
-static int get_adapter_properties(struct userdata *u, struct adapter *a) {
-    DBusError e;
-    DBusMessage *m = NULL, *r = NULL;
-    DBusMessageIter arg_i, element_i;
-    int ret = -1;
-
-    pa_assert(u);
-    pa_assert(a);
-    dbus_error_init(&e);
-
-    pa_assert_se(m = dbus_message_new_method_call("org.bluez", a->object_path, "org.bluez.Adapter", "GetProperties"));
-
-    r = dbus_connection_send_with_reply_and_block(pa_dbus_connection_get(u->conn), m, -1, &e);
-
-    if (!r) {
-        pa_log("org.bluez.Adapter.GetProperties failed: %s", e.message);
-        goto finish;
-    }
-
-    if (!dbus_message_iter_init(r, &arg_i)) {
-        pa_log("org.bluez.Adapter.GetProperties reply has no arguments");
-        goto finish;
-    }
-
-    if (dbus_message_iter_get_arg_type(&arg_i) != DBUS_TYPE_ARRAY) {
-        pa_log("org.bluez.Adapter.GetProperties argument is not an array");
-        goto finish;
-    }
-
-    dbus_message_iter_recurse(&arg_i, &element_i);
-    while (dbus_message_iter_get_arg_type(&element_i) != DBUS_TYPE_INVALID) {
-
-        if (dbus_message_iter_get_arg_type(&element_i) == DBUS_TYPE_DICT_ENTRY) {
-            DBusMessageIter dict_i;
-
-            dbus_message_iter_recurse(&element_i, &dict_i);
-
-            if (parse_adapter_property(u, a, &dict_i) < 0)
-                goto finish;
-        }
-
-        if (!dbus_message_iter_next(&element_i))
-            break;
-    }
-
-    ret = 0;
-
-finish:
-    if (m)
-        dbus_message_unref(m);
-    if (r)
-        dbus_message_unref(r);
-
-    dbus_error_free(&e);
-
-    return ret;
-}
-
-static int detect_adapters(struct userdata *u) {
-    DBusError e;
-    DBusMessage *m = NULL, *r = NULL;
-    DBusMessageIter arg_i, element_i;
-    struct adapter *adapter_list_i;
-    int ret = -1;
-
-    pa_assert(u);
-    dbus_error_init(&e);
-
-    /* get adapters */
-    pa_assert_se(m = dbus_message_new_method_call("org.bluez", "/", "org.bluez.Manager", "ListAdapters"));
-    r = dbus_connection_send_with_reply_and_block(pa_dbus_connection_get(u->conn), m, -1, &e);
-
-    if (!r) {
-        pa_log("org.bluez.Manager.ListAdapters failed: %s", e.message);
-        goto finish;
-    }
-
-    if (!dbus_message_iter_init(r, &arg_i)) {
-        pa_log("org.bluez.Manager.ListAdapters reply has no arguments");
-        goto finish;
-    }
-
-    if (dbus_message_iter_get_arg_type(&arg_i) != DBUS_TYPE_ARRAY) {
-        pa_log("org.bluez.Manager.ListAdapters argument is not an array");
-        goto finish;
-    }
-
-    dbus_message_iter_recurse(&arg_i, &element_i);
-    while (dbus_message_iter_get_arg_type(&element_i) != DBUS_TYPE_INVALID) {
-        if (dbus_message_iter_get_arg_type(&element_i) == DBUS_TYPE_OBJECT_PATH) {
-
-            struct adapter *node;
-            const char *value;
-
-            dbus_message_iter_get_basic(&element_i, &value);
-            node = adapter_new(value);
-            PA_LLIST_PREPEND(struct adapter, u->adapter_list, node);
-        }
-
-        if (!dbus_message_iter_next(&element_i))
-            break;
-    }
-
-    ret = 0;
-
-    /* get adapter properties */
-    for (adapter_list_i = u->adapter_list; adapter_list_i; adapter_list_i = adapter_list_i->next)
-        get_adapter_properties(u, adapter_list_i);
-
-finish:
-    if (m)
-        dbus_message_unref(m);
-    if (r)
-        dbus_message_unref(r);
-
-    dbus_error_free(&e);
-    return ret;
-}
-
 static int parse_device_property(struct userdata *u, struct device *d, DBusMessageIter *i) {
     const char *key;
     DBusMessageIter variant_i;
@@ -566,8 +244,6 @@ static int parse_device_property(struct userdata *u, struct device *d, DBusMessa
             if (dbus_message_iter_get_arg_type(&ai) == DBUS_TYPE_STRING &&
                 pa_streq(key, "UUIDs")) {
 
-                d->audio_profile = NULL;
-
                 while (dbus_message_iter_get_arg_type(&ai) != DBUS_TYPE_INVALID) {
                     struct uuid *node;
                     const char *value;
@@ -576,14 +252,6 @@ static int parse_device_property(struct userdata *u, struct device *d, DBusMessa
                     node = uuid_new(value);
                     PA_LLIST_PREPEND(struct uuid, d->uuid_list, node);
 
-                    if ((strcasecmp(value, A2DP_SOURCE_UUID) == 0) ||
-                        (strcasecmp(value, A2DP_SINK_UUID) == 0))
-                        d->audio_profile = "a2dp";
-                    else if (((strcasecmp(value, HSP_HS_UUID) == 0) ||
-                              (strcasecmp(value, HFP_HS_UUID) == 0)) &&
-                             !d->audio_profile)
-                        d->audio_profile = "hsp";
-
                     if (!dbus_message_iter_next(&ai))
                         break;
                 }
@@ -655,70 +323,26 @@ finish:
     return ret;
 }
 
-static int detect_devices(struct userdata *u) {
-    DBusError e;
-    DBusMessage *m = NULL, *r = NULL;
-    DBusMessageIter arg_i, element_i;
-    struct adapter *adapter_list_i;
-    struct device *device_list_i;
-    const char *value;
-    int ret = -1;
+static void load_module_for_device(struct userdata *u, struct device *d, const char *profile) {
+    char *args;
+    pa_module *pa_m;
+    struct module *m;
 
     pa_assert(u);
-    dbus_error_init(&e);
-
-    /* get devices of each adapter */
-    for (adapter_list_i = u->adapter_list; adapter_list_i; adapter_list_i = adapter_list_i->next) {
-
-        pa_assert_se(m = dbus_message_new_method_call("org.bluez", adapter_list_i->object_path, "org.bluez.Adapter", "ListDevices"));
-
-        r = dbus_connection_send_with_reply_and_block(pa_dbus_connection_get(u->conn), m, -1, &e);
-
-        if (!r) {
-            pa_log("org.bluez.Adapter.ListDevices failed: %s", e.message);
-            goto finish;
-        }
-
-        if (!dbus_message_iter_init(r, &arg_i)) {
-            pa_log("org.bluez.Adapter.ListDevices reply has no arguments");
-            goto finish;
-        }
-
-        if (dbus_message_iter_get_arg_type(&arg_i) != DBUS_TYPE_ARRAY) {
-            pa_log("org.bluez.Adapter.ListDevices argument is not an array");
-            goto finish;
-        }
+    pa_assert(d);
 
-        dbus_message_iter_recurse(&arg_i, &element_i);
-        while (dbus_message_iter_get_arg_type(&element_i) != DBUS_TYPE_INVALID) {
-            if (dbus_message_iter_get_arg_type(&element_i) == DBUS_TYPE_OBJECT_PATH) {
-                struct device *node;
-                dbus_message_iter_get_basic(&element_i, &value);
-                node = device_new(adapter_list_i, value);
-                PA_LLIST_PREPEND(struct device, adapter_list_i->device_list, node);
-            }
+    get_device_properties(u, d);
+    args = pa_sprintf_malloc("sink_name=%s address=%s profile=%s", d->name, d->address, profile);
+    pa_m = pa_module_load(u->module->core, "module-bluetooth-device", args);
+    pa_xfree(args);
 
-            if (!dbus_message_iter_next(&element_i))
-                break;
-        }
+    if (!m) {
+        pa_log_debug("Failed to load module for device %s", d->object_path);
+        return;
     }
 
-    /* get device properties */
-    for (adapter_list_i = u->adapter_list; adapter_list_i; adapter_list_i = adapter_list_i->next)
-        for (device_list_i = adapter_list_i->device_list; device_list_i; device_list_i = device_list_i->next)
-            get_device_properties(u, device_list_i);
-
-    ret = 0;
-
-finish:
-    if (m)
-        dbus_message_unref(m);
-    if (r)
-        dbus_message_unref(r);
-
-    dbus_error_free(&e);
-
-    return ret;
+    m = module_new(profile, pa_m);
+    PA_LLIST_PREPEND(struct module, d->module_list, m);
 }
 
 static DBusHandlerResult filter_cb(DBusConnection *bus, DBusMessage *msg, void *userdata) {
@@ -739,78 +363,7 @@ static DBusHandlerResult filter_cb(DBusConnection *bus, DBusMessage *msg, void *
             dbus_message_get_path(msg),
             dbus_message_get_member(msg));
 
-    if (dbus_message_is_signal(msg, "org.bluez.Manager", "AdapterAdded")) {
-
-        if (!dbus_message_iter_init(msg, &arg_i))
-            pa_log("dbus: message has no parameters");
-        else if (dbus_message_iter_get_arg_type(&arg_i) != DBUS_TYPE_OBJECT_PATH)
-            pa_log("dbus: argument is not object path");
-        else {
-            struct adapter *node;
-
-            dbus_message_iter_get_basic(&arg_i, &value);
-            pa_log_debug("hcid: adapter %s added", value);
-
-            node = adapter_new(value);
-            PA_LLIST_PREPEND(struct adapter, u->adapter_list, node);
-
-            get_adapter_properties(u, node);
-        }
-
-    } else if (dbus_message_is_signal(msg, "org.bluez.Manager", "AdapterRemoved")) {
-        if (!dbus_message_iter_init(msg, &arg_i))
-            pa_log("dbus: message has no parameters");
-        else if (dbus_message_iter_get_arg_type(&arg_i) != DBUS_TYPE_OBJECT_PATH)
-            pa_log("dbus: argument is not object path");
-        else {
-            struct adapter *a;
-
-            dbus_message_iter_get_basic(&arg_i, &value);
-            pa_log_debug("hcid: adapter %s removed", value);
-
-            if ((a = adapter_find(u, value))) {
-                PA_LLIST_REMOVE(struct adapter, u->adapter_list, a);
-                adapter_free(a);
-            }
-        }
-
-    } else if (dbus_message_is_signal(msg, "org.bluez.Adapter", "PropertyChanged")) {
-
-        if (!dbus_message_iter_init(msg, &arg_i))
-            pa_log("dbus: message has no parameters");
-        else {
-            struct adapter *a;
-
-            if ((a = adapter_find(u, dbus_message_get_path(msg))))
-                parse_adapter_property(u, a, &arg_i);
-        }
-
-    } else if (dbus_message_is_signal(msg, "org.bluez.Adapter", "DeviceCreated")) {
-
-        if (!dbus_message_iter_init(msg, &arg_i))
-            pa_log("dbus: message has no parameters");
-        else if (dbus_message_iter_get_arg_type(&arg_i) != DBUS_TYPE_OBJECT_PATH)
-            pa_log("dbus: argument is not object path");
-        else {
-            struct adapter *adapter;
-
-            if (!(adapter = adapter_find(u, dbus_message_get_path(msg))))
-                pa_log("dbus: failed to find adapter for object path");
-            else {
-                struct device *node;
-
-                dbus_message_iter_get_basic(&arg_i, &value);
-                pa_log_debug("hcid: device %s created", value);
-
-                node = device_new(adapter, value);
-                PA_LLIST_PREPEND(struct device, adapter->device_list, node);
-
-                get_device_properties(u, node);
-                load_module_for_device(u, node);
-            }
-        }
-
-    } else if (dbus_message_is_signal(msg, "org.bluez.Adapter", "DeviceRemoved")) {
+    if (dbus_message_is_signal(msg, "org.bluez.Adapter", "DeviceRemoved")) {
 
         if (!dbus_message_iter_init(msg, &arg_i))
             pa_log("dbus: message has no parameters");
@@ -823,7 +376,7 @@ static DBusHandlerResult filter_cb(DBusConnection *bus, DBusMessage *msg, void *
             pa_log_debug("hcid: device %s removed", value);
 
             if ((d = device_find(u, value))) {
-                PA_LLIST_REMOVE(struct device, d->adapter->device_list, d);
+                PA_LLIST_REMOVE(struct device, u->device_list, d);
                 device_free(d);
             }
         }
@@ -832,9 +385,19 @@ static DBusHandlerResult filter_cb(DBusConnection *bus, DBusMessage *msg, void *
                dbus_message_is_signal(msg, "org.bluez.AudioSink", "Connected")) {
 
         struct device *d;
+        const char *profile;
+
+        if (!(d = device_find(u, dbus_message_get_path(msg)))) {
+                d = device_new(dbus_message_get_path(msg));
+                PA_LLIST_PREPEND(struct device, u->device_list, d);
+        }
+
+        if (dbus_message_is_signal(msg, "org.bluez.Headset", "Connected"))
+            profile = "hsp";
+        else
+            profile = "a2dp";
 
-        if ((d = device_find(u, dbus_message_get_path(msg))))
-                load_module_for_device(u, d);
+        load_module_for_device(u, d, profile);
     }
 
     dbus_error_free(&err);
@@ -843,16 +406,16 @@ static DBusHandlerResult filter_cb(DBusConnection *bus, DBusMessage *msg, void *
 
 void pa__done(pa_module* m) {
     struct userdata *u;
-    struct adapter *i;
+    struct device *i;
 
     pa_assert(m);
 
     if (!(u = m->userdata))
         return;
 
-    while ((i = u->adapter_list)) {
-        PA_LLIST_REMOVE(struct adapter, u->adapter_list, i);
-        adapter_free(i);
+    while ((i = u->device_list)) {
+        PA_LLIST_REMOVE(struct device, u->device_list, i);
+        device_free(i);
     }
 
     if (u->conn)
@@ -870,7 +433,7 @@ int pa__init(pa_module* m) {
 
     m->userdata = u = pa_xnew(struct userdata, 1);
     u->module = m;
-    PA_LLIST_HEAD_INIT(struct adapter, u->adapter_list);
+    PA_LLIST_HEAD_INIT(struct device, u->device_list);
 
     /* connect to the bus */
     u->conn = pa_dbus_bus_get(m->core, DBUS_BUS_SYSTEM, &err);
@@ -879,37 +442,18 @@ int pa__init(pa_module* m) {
         goto fail;
     }
 
-    /* static detection of bluetooth audio devices */
-    detect_adapters(u);
-    detect_devices(u);
-
-    print_adapters(u);
-    load_modules(u);
-
     /* dynamic detection of bluetooth audio devices */
     if (!dbus_connection_add_filter(pa_dbus_connection_get(u->conn), filter_cb, u, NULL)) {
         pa_log_error("Failed to add filter function");
         goto fail;
     }
 
-    dbus_bus_add_match(pa_dbus_connection_get(u->conn), "type='signal',sender='org.bluez',interface='org.bluez.Manager'", &err);
-    if (dbus_error_is_set(&err)) {
-        pa_log_error("Unable to subscribe to org.bluez.Manager signals: %s: %s", err.name, err.message);
-        goto fail;
-    }
-
-    dbus_bus_add_match(pa_dbus_connection_get(u->conn), "type='signal',sender='org.bluez',interface='org.bluez.Adapter'", &err);
+    dbus_bus_add_match(pa_dbus_connection_get(u->conn), "type='signal',sender='org.bluez',interface='org.bluez.Adapter',member='DeviceRemoved'", &err);
     if (dbus_error_is_set(&err)) {
         pa_log_error("Unable to subscribe to org.bluez.Adapter signals: %s: %s", err.name, err.message);
         goto fail;
     }
 
-    dbus_bus_add_match(pa_dbus_connection_get(u->conn), "type='signal',sender='org.bluez',interface='org.bluez.Device'", &err);
-    if (dbus_error_is_set(&err)) {
-        pa_log_error("Unable to subscribe to org.bluez.Device signals: %s: %s", err.name, err.message);
-        goto fail;
-    }
-
     dbus_bus_add_match(pa_dbus_connection_get(u->conn), "type='signal',sender='org.bluez',interface='org.bluez.Headset',member='Connected'", &err);
     if (dbus_error_is_set(&err)) {
         pa_log_error("Unable to subscribe to org.bluez.Headset signals: %s: %s", err.name, err.message);

commit 0c998b089111ef1f1d9cc73dc0b05e22d049b4c7
Author: Luiz Augusto von Dentz <luiz.dentz at openbossa.org>
Date:   Fri Oct 3 12:15:26 2008 -0300

    Replace handlers of deprecated Connected signals with new PropertyChanged.

diff --git a/src/modules/bluetooth/module-bluetooth-discover.c b/src/modules/bluetooth/module-bluetooth-discover.c
index 88d4eef..dbbcb13 100644
--- a/src/modules/bluetooth/module-bluetooth-discover.c
+++ b/src/modules/bluetooth/module-bluetooth-discover.c
@@ -381,18 +381,51 @@ static DBusHandlerResult filter_cb(DBusConnection *bus, DBusMessage *msg, void *
             }
         }
 
-    } else if (dbus_message_is_signal(msg, "org.bluez.Headset", "Connected") ||
-               dbus_message_is_signal(msg, "org.bluez.AudioSink", "Connected")) {
+    } else if (dbus_message_is_signal(msg, "org.bluez.Headset", "PropertyChanged") ||
+               dbus_message_is_signal(msg, "org.bluez.AudioSink", "PropertyChanged")) {
 
         struct device *d;
         const char *profile;
+        DBusMessageIter variant_i;
+
+        if (!dbus_message_iter_init(msg, &arg_i)) {
+            pa_log("dbus: message has no parameters");
+            goto done;
+        }
+
+        if (dbus_message_iter_get_arg_type(&arg_i) != DBUS_TYPE_STRING) {
+            pa_log("Property name not a string.");
+            goto done;
+        }
+
+        dbus_message_iter_get_basic(&arg_i, &value);
+
+        if (!dbus_message_iter_next(&arg_i)) {
+            pa_log("Property value missing");
+            goto done;
+        }
+
+        if (dbus_message_iter_get_arg_type(&arg_i) != DBUS_TYPE_VARIANT) {
+            pa_log("Property value not a variant.");
+            goto done;
+        }
+
+        dbus_message_iter_recurse(&arg_i, &variant_i);
+
+        if (dbus_message_iter_get_arg_type(&variant_i) == DBUS_TYPE_BOOLEAN) {
+            dbus_bool_t connected;
+            dbus_message_iter_get_basic(&variant_i, &connected);
+
+            if (!pa_streq(value, "Connected") || !connected)
+                goto done;
+        }
 
         if (!(d = device_find(u, dbus_message_get_path(msg)))) {
                 d = device_new(dbus_message_get_path(msg));
                 PA_LLIST_PREPEND(struct device, u->device_list, d);
         }
 
-        if (dbus_message_is_signal(msg, "org.bluez.Headset", "Connected"))
+        if (dbus_message_is_signal(msg, "org.bluez.Headset", "PropertyChanged"))
             profile = "hsp";
         else
             profile = "a2dp";
@@ -400,6 +433,7 @@ static DBusHandlerResult filter_cb(DBusConnection *bus, DBusMessage *msg, void *
         load_module_for_device(u, d, profile);
     }
 
+done:
     dbus_error_free(&err);
     return DBUS_HANDLER_RESULT_HANDLED;
 }
@@ -454,13 +488,13 @@ int pa__init(pa_module* m) {
         goto fail;
     }
 
-    dbus_bus_add_match(pa_dbus_connection_get(u->conn), "type='signal',sender='org.bluez',interface='org.bluez.Headset',member='Connected'", &err);
+    dbus_bus_add_match(pa_dbus_connection_get(u->conn), "type='signal',sender='org.bluez',interface='org.bluez.Headset',member='PropertyChanged'", &err);
     if (dbus_error_is_set(&err)) {
         pa_log_error("Unable to subscribe to org.bluez.Headset signals: %s: %s", err.name, err.message);
         goto fail;
     }
 
-    dbus_bus_add_match(pa_dbus_connection_get(u->conn), "type='signal',sender='org.bluez',interface='org.bluez.AudioSink',member='Connected'", &err);
+    dbus_bus_add_match(pa_dbus_connection_get(u->conn), "type='signal',sender='org.bluez',interface='org.bluez.AudioSink',member='PropertyChanged'", &err);
     if (dbus_error_is_set(&err)) {
         pa_log_error("Unable to subscribe to org.bluez.AudioSink signals: %s: %s", err.name, err.message);
         goto fail;

commit fef63d77b4eed2562e94735399716cb99d8b22cc
Author: Luiz Augusto von Dentz <luiz.dentz at openbossa.org>
Date:   Fri Oct 3 18:04:53 2008 -0300

    Fix loading module-bluetooth-device with an invalid parameter.

diff --git a/src/modules/bluetooth/module-bluetooth-discover.c b/src/modules/bluetooth/module-bluetooth-discover.c
index dbbcb13..03abf26 100644
--- a/src/modules/bluetooth/module-bluetooth-discover.c
+++ b/src/modules/bluetooth/module-bluetooth-discover.c
@@ -332,7 +332,7 @@ static void load_module_for_device(struct userdata *u, struct device *d, const c
     pa_assert(d);
 
     get_device_properties(u, d);
-    args = pa_sprintf_malloc("sink_name=%s address=%s profile=%s", d->name, d->address, profile);
+    args = pa_sprintf_malloc("sink_name=\"%s\" address=\"%s\" profile=\"%s\"", d->name, d->address, profile);
     pa_m = pa_module_load(u->module->core, "module-bluetooth-device", args);
     pa_xfree(args);
 

commit 8222f1200fc2db90fdfde17f5f958f04272f9ade
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sat Oct 4 00:10:43 2008 +0200

    add new API function pa_in_valgrind() to check for

diff --git a/src/pulsecore/core-util.c b/src/pulsecore/core-util.c
index 0bc5cb4..dde34d7 100644
--- a/src/pulsecore/core-util.c
+++ b/src/pulsecore/core-util.c
@@ -2472,3 +2472,18 @@ char *pa_uname_string(void) {
 
     return pa_sprintf_malloc("%s %s %s %s", u.sysname, u.machine, u.release, u.version);
 }
+
+#ifdef HAVE_VALGRIND_MEMCHECK_H
+pa_bool_t pa_in_valgrind(void) {
+    static int b = 0;
+
+    /* To make heisenbugs a bit simpler to find we check for $VALGRIND
+     * here instead of really checking whether we run in valgrind or
+     * not. */
+
+    if (b < 1)
+        b = getenv("VALGRIND") ? 2 : 1;
+
+    return b > 1;
+}
+#endif
diff --git a/src/pulsecore/core-util.h b/src/pulsecore/core-util.h
index df8ce3f..fd6ee89 100644
--- a/src/pulsecore/core-util.h
+++ b/src/pulsecore/core-util.h
@@ -35,6 +35,10 @@
 #include <pulse/gccmacro.h>
 #include <pulsecore/macro.h>
 
+#ifndef PACKAGE
+#error "Please include config.h before including this file!"
+#endif
+
 struct timeval;
 
 /* These resource limits are pretty new on Linux, let's define them
@@ -193,4 +197,13 @@ pa_bool_t pa_in_system_mode(void);
 char *pa_machine_id(void);
 char *pa_uname_string(void);
 
+
+#ifdef HAVE_VALGRIND_MEMCHECK_H
+pa_bool_t pa_in_valgrind(void);
+#else
+static inline pa_bool_t pa_in_valgrind(void) {
+    return FALSE;
+}
+#endif
+
 #endif

commit 9b00664295d8dd1c4d1ee118fed3308af93723e0
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sat Oct 4 00:13:05 2008 +0200

    instead of checking for  directly use new function pa_in_valgrind()

diff --git a/src/daemon/caps.c b/src/daemon/caps.c
index f7b6658..25a09fd 100644
--- a/src/daemon/caps.c
+++ b/src/daemon/caps.c
@@ -112,9 +112,9 @@ void pa_drop_caps(void) {
 
 #ifndef __OPTIMIZE__
     /* Valgrind doesn't not know set_caps, so we bypass it here -- but
-     *  only in development builts.*/
+     * only in development builds.*/
 
-    if (getenv("VALGRIND") && !pa_have_caps())
+    if (pa_in_valgrind() && !pa_have_caps())
         return;
 #endif
 

commit 3c193520ee59703b9e4453db0bff8f9c6b8a06c2
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sat Oct 4 00:13:29 2008 +0200

    show valgrind status on startup

diff --git a/src/daemon/main.c b/src/daemon/main.c
index 53f5d19..fad635f 100644
--- a/src/daemon/main.c
+++ b/src/daemon/main.c
@@ -793,6 +793,8 @@ int main(int argc, char *argv[]) {
     pa_log_debug(_("Compiled with Valgrind support: no"));
 #endif
 
+    pa_log_debug(_("Running in valgrind mode: %s"), pa_yes_no(pa_in_valgrind()));
+
 #ifdef __OPTIMIZE__
     pa_log_debug(_("Optimized build: yes"));
 #else

commit 82c46f223823e8359ee2b788a83eac0ab82c912a
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sat Oct 4 00:14:02 2008 +0200

    do not cleanup staticly allocated memory unless we are in valgrind mode

diff --git a/src/pulsecore/flist.h b/src/pulsecore/flist.h
index 2d8422f..512dd35 100644
--- a/src/pulsecore/flist.h
+++ b/src/pulsecore/flist.h
@@ -26,6 +26,7 @@
 #include <pulse/gccmacro.h>
 
 #include <pulsecore/once.h>
+#include <pulsecore/core-util.h>
 
 /* A multiple-reader multipler-write lock-free free list implementation */
 
@@ -56,6 +57,8 @@ void* pa_flist_pop(pa_flist*l);
     }                                                                   \
     static void name##_flist_destructor(void) PA_GCC_DESTRUCTOR;        \
     static void name##_flist_destructor(void) {                         \
+        if (!pa_in_valgrind())                                          \
+            return;                                                     \
         if (name##_flist.flist)                                         \
             pa_flist_free(name##_flist.flist, (free_cb));               \
     }                                                                   \
diff --git a/src/pulsecore/log.c b/src/pulsecore/log.c
index d731808..b1de696 100644
--- a/src/pulsecore/log.c
+++ b/src/pulsecore/log.c
@@ -85,6 +85,9 @@ void pa_log_set_ident(const char *p) {
 /* To make valgrind shut up. */
 static void ident_destructor(void) PA_GCC_DESTRUCTOR;
 static void ident_destructor(void) {
+    if (!pa_in_valgrind())
+        return;
+
     pa_xfree(log_ident);
     pa_xfree(log_ident_local);
 }
diff --git a/src/pulsecore/thread.h b/src/pulsecore/thread.h
index 87e850d..eabe9ba 100644
--- a/src/pulsecore/thread.h
+++ b/src/pulsecore/thread.h
@@ -25,6 +25,7 @@
 
 #include <pulse/def.h>
 #include <pulsecore/once.h>
+#include <pulsecore/core-util.h>
 
 #ifndef PACKAGE
 #error "Please include config.h before including this file!"
@@ -69,6 +70,8 @@ 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 (!pa_in_valgrind())                                          \
+            return;                                                     \
         if (!name##_tls.tls)                                            \
             return;                                                     \
         if (_free_cb) {                                                 \

commit 88130eb9e64326810c486fee5a9cff3dd3903fb0
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sat Oct 4 01:06:35 2008 +0200

    add missing inclusion

diff --git a/src/daemon/caps.c b/src/daemon/caps.c
index 25a09fd..707b532 100644
--- a/src/daemon/caps.c
+++ b/src/daemon/caps.c
@@ -34,6 +34,7 @@
 #include <pulsecore/macro.h>
 #include <pulsecore/core-error.h>
 #include <pulsecore/log.h>
+#include <pulsecore/core-util.h>
 
 #ifdef HAVE_SYS_CAPABILITY_H
 #include <sys/capability.h>

commit 530b95fec50b6b7fb0ff1fd1a4eb9e4123bb32a0
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sat Oct 4 01:07:08 2008 +0200

    don't call snd_pcm_drain() when we suspend because that might take awfully long with our long buffer sizes these days

diff --git a/src/modules/module-alsa-sink.c b/src/modules/module-alsa-sink.c
index 8f90774..be463bb 100644
--- a/src/modules/module-alsa-sink.c
+++ b/src/modules/module-alsa-sink.c
@@ -539,8 +539,8 @@ static int suspend(struct userdata *u) {
 
     pa_smoother_pause(u->smoother, pa_rtclock_usec());
 
-    /* Let's suspend */
-    snd_pcm_drain(u->pcm_handle);
+    /* Let's suspend -- we don't call snd_pcm_drain() here since that might
+     * take awfully long with our long buffer sizes today. */
     snd_pcm_close(u->pcm_handle);
     u->pcm_handle = NULL;
 

commit 87c8132ce3f58eb65e742f085b364850c40fbf6a
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sat Oct 4 01:07:38 2008 +0200

    increase suspend timeout to 5s so that it is always longer then the default tsched buffer size of 2s

diff --git a/src/modules/module-suspend-on-idle.c b/src/modules/module-suspend-on-idle.c
index bc7c023..6cc28ec 100644
--- a/src/modules/module-suspend-on-idle.c
+++ b/src/modules/module-suspend-on-idle.c
@@ -337,7 +337,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 = 1;
+    uint32_t timeout = 5;
     uint32_t idx;
     pa_sink *sink;
     pa_source *source;

commit da4ad5ed01c02f6390c0e4e741734184707f655e
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sat Oct 4 01:40:41 2008 +0200

    implement pa_sw_volume_divide() and pa_sw_cvolume_divide()

diff --git a/src/pulse/volume.c b/src/pulse/volume.c
index 0412819..99a85f4 100644
--- a/src/pulse/volume.c
+++ b/src/pulse/volume.c
@@ -104,6 +104,15 @@ 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));
 }
 
+pa_volume_t pa_sw_volume_divide(pa_volume_t a, pa_volume_t b) {
+    double v = pa_sw_volume_to_linear(b);
+
+    if (v <= 0)
+        return 0;
+
+    return pa_sw_volume_from_linear(pa_sw_volume_to_linear(a) / v);
+}
+
 #define USER_DECIBEL_RANGE 60
 
 pa_volume_t pa_sw_volume_from_dB(double dB) {
@@ -220,12 +229,23 @@ pa_cvolume *pa_sw_cvolume_multiply(pa_cvolume *dest, const pa_cvolume *a, const
     pa_assert(a);
     pa_assert(b);
 
-    for (i = 0; i < a->channels && i < b->channels && i < PA_CHANNELS_MAX; i++) {
+    for (i = 0; i < a->channels && i < b->channels && i < PA_CHANNELS_MAX; i++)
+        dest->values[i] = pa_sw_volume_multiply(a->values[i], b->values[i]);
 
-        dest->values[i] = pa_sw_volume_multiply(
-            i < a->channels ? a->values[i] : PA_VOLUME_NORM,
-            i < b->channels ? b->values[i] : PA_VOLUME_NORM);
-    }
+    dest->channels = (uint8_t) i;
+
+    return dest;
+}
+
+pa_cvolume *pa_sw_cvolume_divide(pa_cvolume *dest, const pa_cvolume *a, const pa_cvolume *b) {
+    unsigned i;
+
+    pa_assert(dest);
+    pa_assert(a);
+    pa_assert(b);
+
+    for (i = 0; i < a->channels && i < b->channels && i < PA_CHANNELS_MAX; i++)
+        dest->values[i] = pa_sw_volume_divide(a->values[i], b->values[i]);
 
     dest->channels = (uint8_t) i;
 
diff --git a/src/pulse/volume.h b/src/pulse/volume.h
index bfd8ca5..75051af 100644
--- a/src/pulse/volume.h
+++ b/src/pulse/volume.h
@@ -168,12 +168,25 @@ 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 on normal level */
 #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! */
+/** Multiply two volume 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_GCC_CONST;
 
-/** Multiply to per-channel volumes and return the result in *dest. This is only valid for software volumes! */
+/** Multiply two 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);
 
+/** Divide two volume specifications, return the result. This uses
+ * PA_VOLUME_NORM as neutral element of division. This is only valid
+ * for software volumes! If a division by zero is tried the result
+ * will be 0. \since 0.9.13 */
+pa_volume_t pa_sw_volume_divide(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! \since 0.9.13 */
+pa_cvolume *pa_sw_cvolume_divide(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 83b1d7a305dfdf0a6958ba28a84cd1a074ca7aff
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sat Oct 4 01:48:13 2008 +0200

    get rid of pa_alsa_volume_divide() since we have pa_sw_volume_divide() now

diff --git a/src/modules/alsa-util.c b/src/modules/alsa-util.c
index c3eb72f..ffe7795 100644
--- a/src/modules/alsa-util.c
+++ b/src/modules/alsa-util.c
@@ -1109,27 +1109,3 @@ pa_rtpoll_item* pa_alsa_build_pollfd(snd_pcm_t *pcm, pa_rtpoll *rtpoll) {
 
     return item;
 }
-
-pa_cvolume *pa_alsa_volume_divide(pa_cvolume *r, const pa_cvolume *t) {
-    unsigned i;
-
-    pa_assert(r);
-    pa_assert(t);
-    pa_assert(r->channels == t->channels);
-
-    for (i = 0; i < r->channels; i++) {
-        double a, b, c;
-
-        a = pa_sw_volume_to_linear(r->values[i]); /* the hw volume */
-        b = pa_sw_volume_to_linear(t->values[i]); /* the intended volume */
-
-        if (a <= 0)
-            c = 0;
-        else
-            c = b / a;
-
-        r->values[i] = pa_sw_volume_from_linear(c);
-    }
-
-    return r;
-}
diff --git a/src/modules/alsa-util.h b/src/modules/alsa-util.h
index 7991a10..b66adc1 100644
--- a/src/modules/alsa-util.h
+++ b/src/modules/alsa-util.h
@@ -92,6 +92,4 @@ 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);
 
-pa_cvolume *pa_alsa_volume_divide(pa_cvolume *r, const pa_cvolume *t);
-
 #endif
diff --git a/src/modules/module-alsa-sink.c b/src/modules/module-alsa-sink.c
index be463bb..c42da36 100644
--- a/src/modules/module-alsa-sink.c
+++ b/src/modules/module-alsa-sink.c
@@ -936,7 +936,7 @@ static int sink_set_volume_cb(pa_sink *s) {
 
         /* Match exactly what the user requested by software */
 
-        pa_alsa_volume_divide(&r, &s->volume);
+        pa_sw_cvolume_divide(&r, &s->volume, &r);
         pa_sink_set_soft_volume(s, &r);
 
         pa_log_debug("Requested volume: %s", pa_cvolume_snprint(t, sizeof(t), &s->volume));
diff --git a/src/modules/module-alsa-source.c b/src/modules/module-alsa-source.c
index d5e2170..e1fe4d6 100644
--- a/src/modules/module-alsa-source.c
+++ b/src/modules/module-alsa-source.c
@@ -881,7 +881,7 @@ static int source_set_volume_cb(pa_source *s) {
 
         /* Match exactly what the user requested by software */
 
-        pa_alsa_volume_divide(&r, &s->volume);
+        pa_sw_cvolume_divide(&r, &s->volume, &r);
         pa_source_set_soft_volume(s, &r);
 
         pa_log_debug("Requested volume: %s", pa_cvolume_snprint(t, sizeof(t), &s->volume));

commit a9c1bb3e85b1a9776e9291ea24ef1847dc991e2a
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sat Oct 4 02:13:39 2008 +0200

    substract the unused record buffer size from the overall size before calculating the space still left for recording

diff --git a/src/modules/module-alsa-sink.c b/src/modules/module-alsa-sink.c
index c42da36..0e15da3 100644
--- a/src/modules/module-alsa-sink.c
+++ b/src/modules/module-alsa-sink.c
@@ -569,7 +569,7 @@ static int update_sw_params(struct userdata *u) {
         if ((latency = pa_sink_get_requested_latency_within_thread(u->sink)) != (pa_usec_t) -1) {
             size_t b;
 
-            pa_log_debug("latency set to %0.2f", (double) latency / PA_USEC_PER_MSEC);
+            pa_log_debug("latency set to %0.2fms", (double) latency / PA_USEC_PER_MSEC);
 
             b = pa_usec_to_bytes(latency, &u->sink->sample_spec);
 
diff --git a/src/modules/module-alsa-source.c b/src/modules/module-alsa-source.c
index e1fe4d6..2827ecf 100644
--- a/src/modules/module-alsa-source.c
+++ b/src/modules/module-alsa-source.c
@@ -211,9 +211,10 @@ static int try_recover(struct userdata *u, const char *call, int err) {
 
 static size_t check_left_to_record(struct userdata *u, snd_pcm_sframes_t n) {
     size_t left_to_record;
+    size_t rec_space = u->hwbuf_size - (size_t) u->hwbuf_unused_frames*u->frame_size;
 
-    if ((size_t) n*u->frame_size < u->hwbuf_size)
-        left_to_record = u->hwbuf_size - ((size_t) n*u->frame_size);
+    if ((size_t) n*u->frame_size < rec_space)
+        left_to_record = rec_space - ((size_t) n*u->frame_size);
     else
         left_to_record = 0;
 
@@ -514,7 +515,7 @@ static int update_sw_params(struct userdata *u) {
         if ((latency = pa_source_get_requested_latency_within_thread(u->source)) != (pa_usec_t) -1) {
             size_t b;
 
-            pa_log_debug("latency set to %0.2f", (double) latency / PA_USEC_PER_MSEC);
+            pa_log_debug("latency set to %0.2fms", (double) latency / PA_USEC_PER_MSEC);
 
             b = pa_usec_to_bytes(latency, &u->source->sample_spec);
 

commit 6d52a4130789e59b6c8d83e151230180cbd39493
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sun Oct 5 15:38:56 2008 +0200

    add missing include

diff --git a/src/pulse/introspect.c b/src/pulse/introspect.c
index 4e362fd..3809158 100644
--- a/src/pulse/introspect.c
+++ b/src/pulse/introspect.c
@@ -24,6 +24,8 @@
 #include <config.h>
 #endif
 
+#include <string.h>
+
 #include <pulse/context.h>
 #include <pulse/gccmacro.h>
 

commit f728e9cce060ded8db40b82e02683331252f6cc5
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sun Oct 5 22:51:25 2008 +0200

    disable valgrind macro usage for now since valgrind generates a lot of spurious warnings as it seems

diff --git a/src/pulsecore/memblock.c b/src/pulsecore/memblock.c
index 400a4e1..d9e1bf1 100644
--- a/src/pulsecore/memblock.c
+++ b/src/pulsecore/memblock.c
@@ -261,9 +261,11 @@ static struct mempool_slot* mempool_allocate_slot(pa_mempool *p) {
         }
     }
 
-#ifdef HAVE_VALGRIND_MEMCHECK_H
-    VALGRIND_MALLOCLIKE_BLOCK(slot, p->block_size, 0, 0);
-#endif
+/* #ifdef HAVE_VALGRIND_MEMCHECK_H */
+/*     if (PA_UNLIKELY(pa_in_valgrind())) { */
+/*         VALGRIND_MALLOCLIKE_BLOCK(slot, p->block_size, 0, 0); */
+/*     } */
+/* #endif */
 
     return slot;
 }
@@ -534,16 +536,18 @@ static void memblock_free(pa_memblock *b) {
 
             call_free = b->type == PA_MEMBLOCK_POOL_EXTERNAL;
 
+/* #ifdef HAVE_VALGRIND_MEMCHECK_H */
+/*             if (PA_UNLIKELY(pa_in_valgrind())) { */
+/*                 VALGRIND_FREELIKE_BLOCK(slot, b->pool->block_size); */
+/*             } */
+/* #endif */
+
             /* 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)
                 ;
 
-#ifdef HAVE_VALGRIND_MEMCHECK_H
-            VALGRIND_FREELIKE_BLOCK(slot, b->pool->block_size);
-#endif
-
             if (call_free)
                 if (pa_flist_push(PA_STATIC_FLIST_GET(unused_memblocks), b) < 0)
                     pa_xfree(b);

commit 5996f59dd5e13d10da9a2c95f0040e48f7a7696e
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sun Oct 5 23:02:25 2008 +0200

    update module-tunnel for recent protocol changes

diff --git a/src/modules/module-tunnel.c b/src/modules/module-tunnel.c
index de3c727..4bbb11a 100644
--- a/src/modules/module-tunnel.c
+++ b/src/modules/module-tunnel.c
@@ -159,7 +159,7 @@ static const pa_pdispatch_cb_t command_table[PA_COMMAND_MAX] = {
     [PA_COMMAND_PLAYBACK_STREAM_SUSPENDED] = command_suspended,
     [PA_COMMAND_RECORD_STREAM_SUSPENDED] = command_suspended,
     [PA_COMMAND_PLAYBACK_STREAM_MOVED] = command_moved,
-    [PA_COMMAND_RECORD_STREAM_MOVED] = command_moved,
+    [PA_COMMAND_RECORD_STREAM_MOVED] = command_moved
 };
 
 struct userdata {
@@ -1494,6 +1494,13 @@ static void setup_complete_callback(pa_pdispatch *pd, uint32_t command, uint32_t
 #endif
     }
 
+    if (u->version >= 14) {
+#ifdef TUNNEL_SINK
+        pa_tagstruct_put_boolean(reply, FALSE); /* volume_set */
+#endif
+        pa_tagstruct_put_boolean(reply, TRUE); /* early rquests */
+    }
+
     pa_pstream_send_tagstruct(u->pstream, reply);
     pa_pdispatch_register_reply(u->pdispatch, tag, DEFAULT_TIMEOUT, create_stream_callback, u, NULL);
 

commit aa4373962cef6c00b16e229ff6165c144d322ccb
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Oct 6 02:26:08 2008 +0200

    make sure we send a started messages when we are uncorking

diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c
index 5c6dbf4..778aab5 100644
--- a/src/pulsecore/protocol-native.c
+++ b/src/pulsecore/protocol-native.c
@@ -3168,6 +3168,10 @@ static void command_cork_playback_stream(pa_pdispatch *pd, uint32_t command, uin
     CHECK_VALIDITY(c->pstream, playback_stream_isinstance(s), tag, PA_ERR_NOENTITY);
 
     pa_sink_input_cork(s->sink_input, b);
+
+    if (b)
+        s->is_underrun = TRUE;
+
     pa_pstream_send_simple_ack(c->pstream, tag);
 }
 
diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c
index 326a7e2..4f70347 100644
--- a/src/pulsecore/sink-input.c
+++ b/src/pulsecore/sink-input.c
@@ -1030,6 +1030,9 @@ void pa_sink_input_set_state_within_thread(pa_sink_input *i, pa_sink_input_state
 
     } else if (uncorking) {
 
+        i->thread_info.underrun_for = (uint64_t) -1;
+        i->thread_info.playing_for = 0;
+
         pa_log_debug("Requesting rewind due to uncorking");
 
         /* OK, we're being uncorked. Make sure we're not rewound when

commit f64d6af0b70a85e2a825023956c893cc886b0042
Merge: aa43739... fef63d7...
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Oct 6 02:28:17 2008 +0200

    Merge commit 'vudentz/master'


commit 0274651f88adf704ba7afb6a46a35dd7921a4c7c
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Oct 6 02:37:59 2008 +0200

    bump version and sonames

diff --git a/configure.ac b/configure.ac
index 3c3550f..2b91a00 100644
--- a/configure.ac
+++ b/configure.ac
@@ -24,7 +24,7 @@ AC_PREREQ(2.62)
 
 m4_define(PA_MAJOR, [0])
 m4_define(PA_MINOR, [9])
-m4_define(PA_MICRO, [12])
+m4_define(PA_MICRO, [13])
 
 AC_INIT([pulseaudio],[PA_MAJOR.PA_MINOR.PA_MICRO],[mzchyfrnhqvb (at) 0pointer (dot) net])
 AC_CONFIG_SRCDIR([src/daemon/main.c])
@@ -40,7 +40,7 @@ AC_SUBST(PA_PROTOCOL_VERSION, 14)
 
 # The stable ABI for client applications, for the version info x:y:z
 # always will hold y=z
-AC_SUBST(LIBPULSE_VERSION_INFO, [6:0:6])
+AC_SUBST(LIBPULSE_VERSION_INFO, [7:0:7])
 
 # A simplified, synchronous, ABI-stable interface for client
 # applications, for the version info x:y:z always will hold y=z
@@ -57,7 +57,7 @@ AC_SUBST(LIBPULSE_MAINLOOP_GLIB_VERSION_INFO, [0:4: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, [7:0:0])
+AC_SUBST(LIBPULSECORE_VERSION_INFO, [8:0:0])
 
 AC_CANONICAL_HOST
 AC_DEFINE_UNQUOTED([CANONICAL_HOST], "$host", [Canonical host string.])

commit be667af03f37205faacc9a5ecd19928f9d2201f5
Merge: 0274651... aa43739...
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Oct 6 02:39:24 2008 +0200

    Merge branch 'master' of ssh://rootserver/home/lennart/git/public/pulseaudio


commit e26ffc9b507b6bee831a54d93bbd5cc18a4e2ae0
Merge: f64d6af... be667af...
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Oct 6 02:39:36 2008 +0200

    Merge branch 'master' of ssh://rootserver/home/lennart/git/public/pulseaudio


commit fa93cb71e83df6ee9e91d04687829a049ea18ec5
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Oct 6 03:35:46 2008 +0200

    make distcheck pass

diff --git a/po/POTFILES.in b/po/POTFILES.in
index 6efb1d0..c20340e 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -17,7 +17,7 @@ src/modules/module-solaris.c
 src/modules/module-default-device-restore.c
 src/modules/module-x11-xsmp.c
 src/modules/module-remap-sink.c
-src/modules/module-bt-proximity.c
+src/modules/bluetooth/module-bluetooth-proximity.c
 src/modules/module-detect.c
 src/modules/module-always-sink.c
 src/modules/module-lirc.c
@@ -39,7 +39,7 @@ src/modules/module-esound-compat-spawnfd.c
 src/modules/module-esound-compat-spawnpid.c
 #src/modules/module-waveout.c
 src/modules/module-combine.c
-src/modules/bt-proximity-helper.c
+src/modules/bluetooth/proximity-helper.c
 src/modules/module-x11-publish.c
 src/modules/rtp/module-rtp-recv.c
 src/modules/rtp/sdp.c
diff --git a/po/de.po b/po/de.po
index 0a80206..9643d04 100644
--- a/po/de.po
+++ b/po/de.po
@@ -7,7 +7,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: pulseaudio\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2008-08-29 11:33+0000\n"
+"POT-Creation-Date: 2008-10-06 03:21+0200\n"
 "PO-Revision-Date: 2008-08-31 12:22+0100\n"
 "Last-Translator: Fabian Affolter <fab at fedoraproject.org>\n"
 "Language-Team: German <fedora-trans-de at redhat.com>\n"
@@ -17,8 +17,7 @@ msgstr ""
 "Plural-Forms: nplurals=2; plural=(n != 1);\n"
 "X-Poedit-Language: German\n"
 
-#: ../src/daemon/ltdl-bind-now.c:177
-#: ../src/daemon/ltdl-bind-now.c:197
+#: ../src/daemon/ltdl-bind-now.c:177 ../src/daemon/ltdl-bind-now.c:197
 msgid "Failed to add bind-now-loader."
 msgstr "Hinzufügen von bind-now-loader fehlgeschlagen."
 
@@ -114,8 +113,7 @@ msgstr ""
 msgid "Home directory of user '%s' is not '%s', ignoring."
 msgstr "Benutzerverzeichnis von Benutzer '%s' ist nicht '%s', ignoriere."
 
-#: ../src/daemon/main.c:201
-#: ../src/daemon/main.c:206
+#: ../src/daemon/main.c:201 ../src/daemon/main.c:206
 #, c-format
 msgid "Failed to create '%s': %s"
 msgstr "Erzeugen von '%s' fehlgeschlagen: %s"
@@ -180,22 +178,14 @@ msgstr ""
 
 #: ../src/daemon/main.c:479
 msgid ""
-"Called SUID root and real-time/high-priority scheduling was requested in the configuration. However, we lack the necessary priviliges:\n"
+"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 '"
 msgstr ""
 
-#: ../src/daemon/main.c:480
-msgid ""
-"' 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 '"
-msgstr ""
-
-#: ../src/daemon/main.c:481
-msgid "', or increase the RLIMIT_NICE/RLIMIT_RTPRIO resource limits for this user."
-msgstr ""
-
 #: ../src/daemon/main.c:497
-msgid "High-priority scheduling enabled in configuration but not allowed by policy."
+msgid ""
+"High-priority scheduling enabled in configuration but not allowed by policy."
 msgstr ""
 
 #: ../src/daemon/main.c:522
@@ -212,7 +202,8 @@ msgid "Giving up CAP_NICE"
 msgstr ""
 
 #: ../src/daemon/main.c:539
-msgid "Real-time scheduling enabled in configuration but not allowed by policy."
+msgid ""
+"Real-time scheduling enabled in configuration but not allowed by policy."
 msgstr ""
 
 #: ../src/daemon/main.c:597
@@ -230,7 +221,9 @@ msgid "Failed to kill daemon: %s"
 msgstr ""
 
 #: ../src/daemon/main.c:627
-msgid "This program is not intended to be run as root (unless --system is specified)."
+msgid ""
+"This program is not intended to be run as root (unless --system is "
+"specified)."
 msgstr ""
 
 #: ../src/daemon/main.c:629
@@ -291,71 +284,109 @@ msgstr "Dies ist PulseAudio %s"
 
 #: ../src/daemon/main.c:781
 #, c-format
+msgid "Compilation host: %s"
+msgstr ""
+
+#: ../src/daemon/main.c:782
+#, c-format
+msgid "Compilation CFLAGS: %s"
+msgstr ""
+
+#: ../src/daemon/main.c:785
+#, c-format
+msgid "Running on host: %s"
+msgstr ""
+
+#: ../src/daemon/main.c:788
+#, c-format
 msgid "Page size is %lu bytes"
 msgstr "Seitengröße ist %lu Bytes."
 
-#: ../src/daemon/main.c:784
+#: ../src/daemon/main.c:791
+msgid "Compiled with Valgrind support: yes"
+msgstr ""
+
+#: ../src/daemon/main.c:793
+msgid "Compiled with Valgrind support: no"
+msgstr ""
+
+#: ../src/daemon/main.c:796
+#, c-format
+msgid "Running in valgrind mode: %s"
+msgstr ""
+
+#: ../src/daemon/main.c:799
+msgid "Optimized build: yes"
+msgstr ""
+
+#: ../src/daemon/main.c:801
+msgid "Optimized build: no"
+msgstr ""
+
+#: ../src/daemon/main.c:805
 msgid "Failed to get machine ID"
 msgstr ""
 
-#: ../src/daemon/main.c:787
+#: ../src/daemon/main.c:808
 #, c-format
 msgid "Machine ID is %s."
 msgstr "System- ID ist %s."
 
-#: ../src/daemon/main.c:792
+#: ../src/daemon/main.c:813
 #, c-format
 msgid "Using runtime directory %s."
 msgstr ""
 
-#: ../src/daemon/main.c:797
+#: ../src/daemon/main.c:818
 #, c-format
 msgid "Using state directory %s."
 msgstr ""
 
-#: ../src/daemon/main.c:800
+#: ../src/daemon/main.c:821
 #, c-format
 msgid "Running in system mode: %s"
 msgstr ""
 
-#: ../src/daemon/main.c:815
+#: ../src/daemon/main.c:836
 msgid "pa_pid_file_create() failed."
 msgstr "pa_pid_file_create() fehlgeschlagen."
 
-#: ../src/daemon/main.c:827
+#: ../src/daemon/main.c:848
 msgid "Fresh high-resolution timers available! Bon appetit!"
 msgstr ""
 
-#: ../src/daemon/main.c:829
-msgid "Dude, your kernel stinks! The chef's recommendation today is Linux with high-resolution timers enabled!"
+#: ../src/daemon/main.c:850
+msgid ""
+"Dude, your kernel stinks! The chef's recommendation today is Linux with high-"
+"resolution timers enabled!"
 msgstr ""
 
-#: ../src/daemon/main.c:839
+#: ../src/daemon/main.c:860
 msgid "pa_core_new() failed."
 msgstr "pa_core_new() fehlgeschlagen."
 
-#: ../src/daemon/main.c:899
+#: ../src/daemon/main.c:921
 msgid "Failed to initialize daemon."
 msgstr ""
 
-#: ../src/daemon/main.c:904
+#: ../src/daemon/main.c:926
 msgid "Daemon startup without any loaded modules, refusing to work."
 msgstr ""
 
-#: ../src/daemon/main.c:909
+#: ../src/daemon/main.c:931
 #, c-format
 msgid "Default sink name (%s) does not exist in name register."
 msgstr ""
 
-#: ../src/daemon/main.c:922
+#: ../src/daemon/main.c:944
 msgid "Daemon startup complete."
 msgstr "Start des Dämons abgeschlossen."
 
-#: ../src/daemon/main.c:928
+#: ../src/daemon/main.c:950
 msgid "Daemon shutdown initiated."
 msgstr ""
 
-#: ../src/daemon/main.c:949
+#: ../src/daemon/main.c:971
 msgid "Daemon terminated."
 msgstr "Dämon beendet."
 
@@ -370,8 +401,10 @@ msgid ""
 "      --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"
-"      --start                           Start the daemon if it is not running\n"
+"      --cleanup-shm                     Cleanup stale shared memory "
+"segments\n"
+"      --start                           Start the daemon if it is not "
+"running\n"
 "  -k  --kill                            Kill a running daemon\n"
 "      --check                           Check for a running daemon\n"
 "\n"
@@ -380,24 +413,31 @@ msgid ""
 "  -D, --daemonize[=BOOL]                Daemonize after startup\n"
 "      --fail[=BOOL]                     Quit when startup fails\n"
 "      --high-priority[=BOOL]            Try to set high nice level\n"
-"                                        (only available as root, when SUID or\n"
+"                                        (only available as root, when SUID "
+"or\n"
 "                                        with elevated RLIMIT_NICE)\n"
 "      --realtime[=BOOL]                 Try to enable realtime scheduling\n"
-"                                        (only available as root, when SUID or\n"
+"                                        (only available as root, when SUID "
+"or\n"
 "                                        with elevated RLIMIT_RTPRIO)\n"
-"      --disallow-module-loading[=BOOL]  Disallow module user requested module\n"
+"      --disallow-module-loading[=BOOL]  Disallow module user requested "
+"module\n"
 "                                        loading/unloading after startup\n"
 "      --disallow-exit[=BOOL]            Disallow user requested exit\n"
-"      --exit-idle-time=SECS             Terminate the daemon when idle and this\n"
+"      --exit-idle-time=SECS             Terminate the daemon when idle and "
+"this\n"
 "                                        time passed\n"
-"      --module-idle-time=SECS           Unload autoloaded modules when idle and\n"
+"      --module-idle-time=SECS           Unload autoloaded modules when idle "
+"and\n"
 "                                        this time passed\n"
-"      --scache-idle-time=SECS           Unload autoloaded samples when idle and\n"
+"      --scache-idle-time=SECS           Unload autoloaded samples when idle "
+"and\n"
 "                                        this time passed\n"
 "      --log-level[=LEVEL]               Increase or set verbosity level\n"
 "  -v                                    Increase the verbosity level\n"
 "      --log-target={auto,syslog,stderr} Specify the log target\n"
-"  -p, --dl-search-path=PATH             Set the search path for dynamic shared\n"
+"  -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"
 "                                        (See --dump-resample-methods for\n"
@@ -408,10 +448,12 @@ msgid ""
 "      --disable-shm[=BOOL]              Disable shared memory support.\n"
 "\n"
 "STARTUP SCRIPT:\n"
-"  -L, --load=\"MODULE ARGUMENTS\"         Load the specified plugin module with\n"
+"  -L, --load=\"MODULE ARGUMENTS\"         Load the specified plugin module "
+"with\n"
 "                                        the specified argument\n"
 "  -F, --file=FILENAME                   Run the specified script\n"
-"  -C                                    Open a command line on the running TTY\n"
+"  -C                                    Open a command line on the running "
+"TTY\n"
 "                                        after startup\n"
 "\n"
 "  -n                                    Don't load default script file\n"
@@ -426,7 +468,9 @@ msgid "--fail expects boolean argument"
 msgstr ""
 
 #: ../src/daemon/cmdline.c:262
-msgid "--log-level expects log level argument (either numeric in range 0..4 or one of debug, info, notice, warn, error)."
+msgid ""
+"--log-level expects log level argument (either numeric in range 0..4 or one "
+"of debug, info, notice, warn, error)."
 msgstr ""
 
 #: ../src/daemon/cmdline.c:274
@@ -510,76 +554,76 @@ msgstr "Lade einmalig: %s\n"
 msgid "Path: %s\n"
 msgstr "Pfad: %s\n"
 
-#: ../src/daemon/daemon-conf.c:203
+#: ../src/daemon/daemon-conf.c:205
 #, c-format
 msgid "[%s:%u] Invalid log target '%s'."
 msgstr ""
 
-#: ../src/daemon/daemon-conf.c:219
+#: ../src/daemon/daemon-conf.c:221
 #, c-format
 msgid "[%s:%u] Invalid log level '%s'."
 msgstr ""
 
-#: ../src/daemon/daemon-conf.c:235
+#: ../src/daemon/daemon-conf.c:237
 #, c-format
 msgid "[%s:%u] Invalid resample method '%s'."
 msgstr ""
 
-#: ../src/daemon/daemon-conf.c:258
+#: ../src/daemon/daemon-conf.c:260
 #, c-format
 msgid "[%s:%u] Invalid rlimit '%s'."
 msgstr ""
 
-#: ../src/daemon/daemon-conf.c:265
+#: ../src/daemon/daemon-conf.c:267
 #, c-format
 msgid "[%s:%u] rlimit not supported on this platform."
 msgstr ""
 
-#: ../src/daemon/daemon-conf.c:281
+#: ../src/daemon/daemon-conf.c:283
 #, c-format
 msgid "[%s:%u] Invalid sample format '%s'."
 msgstr ""
 
-#: ../src/daemon/daemon-conf.c:299
+#: ../src/daemon/daemon-conf.c:301
 #, c-format
 msgid "[%s:%u] Invalid sample rate '%s'."
 msgstr ""
 
-#: ../src/daemon/daemon-conf.c:317
+#: ../src/daemon/daemon-conf.c:319
 #, c-format
 msgid "[%s:%u] Invalid sample channels '%s'."
 msgstr ""
 
-#: ../src/daemon/daemon-conf.c:335
+#: ../src/daemon/daemon-conf.c:337
 #, c-format
 msgid "[%s:%u] Invalid number of fragments '%s'."
 msgstr ""
 
-#: ../src/daemon/daemon-conf.c:353
+#: ../src/daemon/daemon-conf.c:355
 #, c-format
 msgid "[%s:%u] Invalid fragment size '%s'."
 msgstr ""
 
-#: ../src/daemon/daemon-conf.c:371
+#: ../src/daemon/daemon-conf.c:373
 #, c-format
 msgid "[%s:%u] Invalid nice level '%s'."
 msgstr ""
 
-#: ../src/daemon/daemon-conf.c:564
+#: ../src/daemon/daemon-conf.c:570
 #, c-format
 msgid "Failed to open configuration file: %s"
 msgstr ""
 
-#: ../src/daemon/daemon-conf.c:638
+#: ../src/daemon/daemon-conf.c:644
 #, c-format
 msgid "### Read from configuration file: %s ###\n"
 msgstr ""
 
-#: ../src/daemon/caps.c:62
+#: ../src/daemon/caps.c:63
 msgid "Dropping root priviliges."
 msgstr "Verlasse Root-Berechtigungen."
 
-#: ../src/daemon/caps.c:102
+#: ../src/daemon/caps.c:103
 msgid "Limited capabilities successfully to CAP_SYS_NICE."
 msgstr ""
 
@@ -787,6 +831,12 @@ msgstr "Oben Hinten Links"
 msgid "Top Rear Right"
 msgstr "Oben Hinten Rechts"
 
+#: ../src/pulse/channelmap.c:472 ../src/pulse/sample.c:144
+#: ../src/pulse/volume.c:163 ../src/pulse/volume.c:194
+#, fuzzy
+msgid "(invalid)"
+msgstr "Ungültig"
+
 #: ../src/pulse/error.c:43
 msgid "OK"
 msgstr "OK"
@@ -875,12 +925,7 @@ msgstr "Unbekannter Fehlercode"
 msgid "No such extension"
 msgstr "Erweiterung nicht vorhanden"
 
-#: ../src/pulse/sample.c:134
-msgid "Invalid"
-msgstr "Ungültig"
-
-#: ../src/pulse/client-conf-x11.c:55
-#: ../src/utils/pax11publish.c:100
+#: ../src/pulse/client-conf-x11.c:55 ../src/utils/pax11publish.c:100
 msgid "XOpenDisplay() failed"
 msgstr "XOpenDisplay() fehlgeschlagen"
 
@@ -888,31 +933,26 @@ msgstr "XOpenDisplay() fehlgeschlagen"
 msgid "Failed to parse cookie data"
 msgstr ""
 
-#: ../src/pulse/client-conf.c:117
+#: ../src/pulse/client-conf.c:120
 #, c-format
 msgid "Failed to open configuration file '%s': %s"
 msgstr ""
 
-#: ../src/pulse/context.c:542
+#: ../src/pulse/context.c:516
 msgid "No cookie loaded. Attempting to connect without."
 msgstr ""
 
-#: ../src/pulse/context.c:596
-#, c-format
-msgid "socketpair(): %s"
-msgstr "socketpair(): %s"
-
-#: ../src/pulse/context.c:610
+#: ../src/pulse/context.c:642
 #, c-format
 msgid "fork(): %s"
 msgstr "fork(): %s"
 
-#: ../src/pulse/context.c:673
+#: ../src/pulse/context.c:695
 #, c-format
 msgid "waitpid(): %s"
 msgstr "waitpid(): %s"
 
-#: ../src/pulse/context.c:1354
+#: ../src/pulse/context.c:1256
 #, c-format
 msgid "Received message for unknown extension '%s'"
 msgstr ""
@@ -1026,28 +1066,23 @@ msgstr "pa_stream_connect_playback() fehlgeschlagen: %s\n"
 msgid "pa_stream_connect_record() failed: %s\n"
 msgstr "pa_stream_connect_record() fehlgeschlagen: %s\n"
 
-#: ../src/utils/pacat.c:307
-#: ../src/utils/pasuspender.c:159
-#: ../src/utils/pactl.c:666
-#: ../src/utils/paplay.c:183
+#: ../src/utils/pacat.c:307 ../src/utils/pasuspender.c:159
+#: ../src/utils/pactl.c:666 ../src/utils/paplay.c:183
 #, c-format
 msgid "Connection failure: %s\n"
 msgstr ""
 
-#: ../src/utils/pacat.c:328
-#: ../src/utils/paplay.c:75
+#: ../src/utils/pacat.c:328 ../src/utils/paplay.c:75
 #, c-format
 msgid "Failed to drain stream: %s\n"
 msgstr ""
 
-#: ../src/utils/pacat.c:333
-#: ../src/utils/paplay.c:80
+#: ../src/utils/pacat.c:333 ../src/utils/paplay.c:80
 #, c-format
 msgid "Playback stream drained.\n"
 msgstr ""
 
-#: ../src/utils/pacat.c:343
-#: ../src/utils/paplay.c:92
+#: ../src/utils/pacat.c:343 ../src/utils/paplay.c:92
 #, c-format
 msgid "Draining connection to server.\n"
 msgstr ""
@@ -1105,27 +1140,44 @@ msgid ""
 "\n"
 "  -v, --verbose                         Enable verbose operations\n"
 "\n"
-"  -s, --server=SERVER                   The name of the server to connect to\n"
-"  -d, --device=DEVICE                   The name of the sink/source to connect to\n"
-"  -n, --client-name=NAME                How to call this client on the server\n"
-"      --stream-name=NAME                How to call this stream on the server\n"
-"      --volume=VOLUME                   Specify the initial (linear) volume in range 0...65536\n"
-"      --rate=SAMPLERATE                 The sample rate in Hz (defaults to 44100)\n"
-"      --format=SAMPLEFORMAT             The sample type, one of s16le, s16be, u8, float32le,\n"
-"                                        float32be, ulaw, alaw (defaults to s16ne)\n"
-"      --channels=CHANNELS               The number of channels, 1 for mono, 2 for stereo\n"
+"  -s, --server=SERVER                   The name of the server to connect "
+"to\n"
+"  -d, --device=DEVICE                   The name of the sink/source to "
+"connect to\n"
+"  -n, --client-name=NAME                How to call this client on the "
+"server\n"
+"      --stream-name=NAME                How to call this stream on the "
+"server\n"
+"      --volume=VOLUME                   Specify the initial (linear) volume "
+"in range 0...65536\n"
+"      --rate=SAMPLERATE                 The sample rate in Hz (defaults to "
+"44100)\n"
+"      --format=SAMPLEFORMAT             The sample type, one of s16le, "
+"s16be, u8, float32le,\n"
+"                                        float32be, ulaw, alaw, s32le, s32be "
+"(defaults to s16ne)\n"
+"      --channels=CHANNELS               The number of channels, 1 for mono, "
+"2 for stereo\n"
 "                                        (defaults to 2)\n"
-"      --channel-map=CHANNELMAP          Channel map to use instead of the default\n"
-"      --fix-format                      Take the sample format from the sink the stream is\n"
+"      --channel-map=CHANNELMAP          Channel map to use instead of the "
+"default\n"
+"      --fix-format                      Take the sample format from the sink "
+"the stream is\n"
 "                                        being connected to.\n"
-"      --fix-rate                        Take the sampling rate from the sink the stream is\n"
+"      --fix-rate                        Take the sampling rate from the sink "
+"the stream is\n"
 "                                        being connected to.\n"
-"      --fix-channels                    Take the number of channels and the channel map\n"
-"                                        from the sink the stream is being connected to.\n"
+"      --fix-channels                    Take the number of channels and the "
+"channel map\n"
+"                                        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"
-"      --process-time=BYTES              Request the specified process time per request in bytes.\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"
 msgstr ""
 
 #: ../src/utils/pacat.c:591
@@ -1189,10 +1241,8 @@ msgstr "dup2(): %s\n"
 msgid "Too many arguments.\n"
 msgstr "Zu viele Argumente.\n"
 
-#: ../src/utils/pacat.c:742
-#: ../src/utils/pasuspender.c:280
-#: ../src/utils/pactl.c:909
-#: ../src/utils/paplay.c:381
+#: ../src/utils/pacat.c:742 ../src/utils/pasuspender.c:280
+#: ../src/utils/pactl.c:909 ../src/utils/paplay.c:381
 #, c-format
 msgid "pa_mainloop_new() failed.\n"
 msgstr "pa_mainloop_new() fehlgeschlagen.\n"
@@ -1202,23 +1252,24 @@ msgstr "pa_mainloop_new() fehlgeschlagen.\n"
 msgid "io_new() failed.\n"
 msgstr "io_new() fehlgeschlagen.\n"
 
-#: ../src/utils/pacat.c:769
-#: ../src/utils/pasuspender.c:293
-#: ../src/utils/pactl.c:923
-#: ../src/utils/paplay.c:396
+#: ../src/utils/pacat.c:769 ../src/utils/pasuspender.c:293
+#: ../src/utils/pactl.c:923 ../src/utils/paplay.c:396
 #, c-format
 msgid "pa_context_new() failed.\n"
 msgstr "pa_context_new() fehlgeschlagen.\n"
 
-#: ../src/utils/pacat.c:785
+#: ../src/utils/pacat.c:777
+#, fuzzy, c-format
+msgid "pa_context_connect() failed: %s"
+msgstr "pa_context_new() fehlgeschlagen.\n"
+
+#: ../src/utils/pacat.c:788
 #, c-format
 msgid "time_new() failed.\n"
 msgstr "time_new() fehlgeschlagen.\n"
 
-#: ../src/utils/pacat.c:792
-#: ../src/utils/pasuspender.c:301
-#: ../src/utils/pactl.c:931
-#: ../src/utils/paplay.c:407
+#: ../src/utils/pacat.c:795 ../src/utils/pasuspender.c:301
+#: ../src/utils/pactl.c:931 ../src/utils/paplay.c:407
 #, c-format
 msgid "pa_mainloop_run() failed.\n"
 msgstr "pa_mainloop_run() fehlgeschlagen.\n"
@@ -1248,8 +1299,7 @@ msgstr ""
 msgid "WARNING: Sound server is not local, not suspending.\n"
 msgstr ""
 
-#: ../src/utils/pasuspender.c:176
-#: ../src/utils/pactl.c:672
+#: ../src/utils/pasuspender.c:176 ../src/utils/pactl.c:672
 #: ../src/utils/paplay.c:191
 #, c-format
 msgid "Got SIGINT, exiting.\n"
@@ -1267,7 +1317,8 @@ msgid ""
 "\n"
 "  -h, --help                            Show this help\n"
 "      --version                         Show version\n"
-"  -s, --server=SERVER                   The name of the server to connect to\n"
+"  -s, --server=SERVER                   The name of the server to connect "
+"to\n"
 "\n"
 msgstr ""
 
@@ -1339,8 +1390,7 @@ msgid ""
 "%s"
 msgstr ""
 
-#: ../src/utils/pactl.c:193
-#: ../src/utils/pactl.c:371
+#: ../src/utils/pactl.c:193 ../src/utils/pactl.c:371
 msgid "muted"
 msgstr "stumm"
 
@@ -1366,18 +1416,10 @@ msgid ""
 "%s"
 msgstr ""
 
-#: ../src/utils/pactl.c:246
-#: ../src/utils/pactl.c:289
-#: ../src/utils/pactl.c:322
-#: ../src/utils/pactl.c:366
-#: ../src/utils/pactl.c:367
-#: ../src/utils/pactl.c:374
-#: ../src/utils/pactl.c:418
-#: ../src/utils/pactl.c:419
-#: ../src/utils/pactl.c:425
-#: ../src/utils/pactl.c:468
-#: ../src/utils/pactl.c:469
-#: ../src/utils/pactl.c:473
+#: ../src/utils/pactl.c:246 ../src/utils/pactl.c:289 ../src/utils/pactl.c:322
+#: ../src/utils/pactl.c:366 ../src/utils/pactl.c:367 ../src/utils/pactl.c:374
+#: ../src/utils/pactl.c:418 ../src/utils/pactl.c:419 ../src/utils/pactl.c:425
+#: ../src/utils/pactl.c:468 ../src/utils/pactl.c:469 ../src/utils/pactl.c:473
 msgid "n/a"
 msgstr "k.A."
 
@@ -1500,8 +1542,7 @@ msgstr ""
 msgid "source"
 msgstr "Quelle"
 
-#: ../src/utils/pactl.c:511
-#: ../src/utils/pactl.c:521
+#: ../src/utils/pactl.c:511 ../src/utils/pactl.c:521
 #, c-format
 msgid "Failure: %s\n"
 msgstr ""
@@ -1535,8 +1576,10 @@ msgid ""
 "  -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"
+"  -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"
 msgstr ""
 
 #: ../src/utils/pactl.c:729
@@ -1589,12 +1632,16 @@ msgstr ""
 
 #: ../src/utils/pactl.c:875
 #, c-format
-msgid "You may not specify more than one sink. You have to specify at least one boolean value.\n"
+msgid ""
+"You may not specify more than one sink. You have to specify at least one "
+"boolean value.\n"
 msgstr ""
 
 #: ../src/utils/pactl.c:888
 #, c-format
-msgid "You may not specify more than one source. You have to specify at least one boolean value.\n"
+msgid ""
+"You may not specify more than one source. You have to specify at least one "
+"boolean value.\n"
 msgstr ""
 
 #: ../src/utils/pactl.c:904
@@ -1609,7 +1656,8 @@ msgid ""
 "\n"
 " -d    Show current PulseAudio data attached to X11 display (default)\n"
 " -e    Export local PulseAudio data to X11 display\n"
-" -i    Import PulseAudio data from X11 display to local environment variables and cookie file.\n"
+" -i    Import PulseAudio data from X11 display to local environment "
+"variables and cookie file.\n"
 " -r    Remove PulseAudio data from X11 display\n"
 msgstr ""
 
@@ -1696,14 +1744,12 @@ msgstr ""
 msgid "select(): %s"
 msgstr "select(): %s"
 
-#: ../src/utils/pacmd.c:124
-#: ../src/utils/pacmd.c:140
+#: ../src/utils/pacmd.c:124 ../src/utils/pacmd.c:140
 #, c-format
 msgid "read(): %s"
 msgstr "read(): %s"
 
-#: ../src/utils/pacmd.c:153
-#: ../src/utils/pacmd.c:167
+#: ../src/utils/pacmd.c:153 ../src/utils/pacmd.c:167
 #, c-format
 msgid "write(): %s"
 msgstr "write(): %s"
@@ -1733,11 +1779,15 @@ msgid ""
 "\n"
 "  -v, --verbose                         Enable verbose operation\n"
 "\n"
-"  -s, --server=SERVER                   The name of the server to connect to\n"
+"  -s, --server=SERVER                   The name of the server to connect "
+"to\n"
 "  -d, --device=DEVICE                   The name of the sink to connect to\n"
-"  -n, --client-name=NAME                How to call this client on the server\n"
-"      --stream-name=NAME                How to call this stream on the server\n"
-"      --volume=VOLUME                   Specify the initial (linear) volume in range 0...65536\n"
+"  -n, --client-name=NAME                How to call this client on the "
+"server\n"
+"      --stream-name=NAME                How to call this stream on the "
+"server\n"
+"      --volume=VOLUME                   Specify the initial (linear) volume "
+"in range 0...65536\n"
 "      --channel-map=CHANNELMAP          Set the channel map to the use\n"
 msgstr ""
 
@@ -1769,3 +1819,9 @@ msgstr ""
 msgid "Using sample spec '%s'\n"
 msgstr ""
 
+#: ../src/pulsecore/lock-autospawn.c:126 ../src/pulsecore/lock-autospawn.c:207
+msgid "Cannot access autospawn lock."
+msgstr ""
+
+#~ msgid "socketpair(): %s"
+#~ msgstr "socketpair(): %s"
diff --git a/po/el.po b/po/el.po
index b664491..fed9ba9 100644
--- a/po/el.po
+++ b/po/el.po
@@ -6,7 +6,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: el\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2008-08-22 19:36+0300\n"
+"POT-Creation-Date: 2008-10-06 03:21+0200\n"
 "PO-Revision-Date: 2008-08-22 19:40+0300\n"
 "Last-Translator: Dimitris Glezos <dimitris at glezos.com>\n"
 "Language-Team: Greek <fedora-trans-el at redhat.com>\n"
@@ -283,42 +283,78 @@ msgstr "Αυτό είναι το PulseAudio %s"
 
 #: ../src/daemon/main.c:781
 #, c-format
+msgid "Compilation host: %s"
+msgstr ""
+
+#: ../src/daemon/main.c:782
+#, c-format
+msgid "Compilation CFLAGS: %s"
+msgstr ""
+
+#: ../src/daemon/main.c:785
+#, c-format
+msgid "Running on host: %s"
+msgstr ""
+
+#: ../src/daemon/main.c:788
+#, c-format
 msgid "Page size is %lu bytes"
 msgstr ""
 
-#: ../src/daemon/main.c:784
+#: ../src/daemon/main.c:791
+msgid "Compiled with Valgrind support: yes"
+msgstr ""
+
+#: ../src/daemon/main.c:793
+msgid "Compiled with Valgrind support: no"
+msgstr ""
+
+#: ../src/daemon/main.c:796
+#, c-format
+msgid "Running in valgrind mode: %s"
+msgstr ""
+
+#: ../src/daemon/main.c:799
+msgid "Optimized build: yes"
+msgstr ""
+
+#: ../src/daemon/main.c:801
+msgid "Optimized build: no"
+msgstr ""
+
+#: ../src/daemon/main.c:805
 msgid "Failed to get machine ID"
 msgstr ""
 
-#: ../src/daemon/main.c:787
+#: ../src/daemon/main.c:808
 #, c-format
 msgid "Machine ID is %s."
 msgstr ""
 
-#: ../src/daemon/main.c:792
+#: ../src/daemon/main.c:813
 #, c-format
 msgid "Using runtime directory %s."
 msgstr ""
 
-#: ../src/daemon/main.c:797
+#: ../src/daemon/main.c:818
 #, c-format
 msgid "Using state directory %s."
 msgstr ""
 
-#: ../src/daemon/main.c:800
+#: ../src/daemon/main.c:821
 #, c-format
 msgid "Running in system mode: %s"
 msgstr ""
 
-#: ../src/daemon/main.c:815
+#: ../src/daemon/main.c:836
 msgid "pa_pid_file_create() failed."
 msgstr ""
 
-#: ../src/daemon/main.c:827
+#: ../src/daemon/main.c:848
 msgid "Fresh high-resolution timers available! Bon appetit!"
 msgstr ""
 
-#: ../src/daemon/main.c:829
+#: ../src/daemon/main.c:850
 msgid ""
 "Dude, your kernel stinks! The chef's recommendation today is Linux with high-"
 "resolution timers enabled!"
@@ -326,32 +362,32 @@ msgstr ""
 "Δικέ μου, ο πυρήνας σου είναι για τα μπάζα! Η πρόταση του σεφ σήμερα είναι "
 "Linux με ενεργοποιημένα τα high-resolution timers!"
 
-#: ../src/daemon/main.c:839
+#: ../src/daemon/main.c:860
 msgid "pa_core_new() failed."
 msgstr ""
 
-#: ../src/daemon/main.c:899
+#: ../src/daemon/main.c:921
 msgid "Failed to initialize daemon."
 msgstr ""
 
-#: ../src/daemon/main.c:904
+#: ../src/daemon/main.c:926
 msgid "Daemon startup without any loaded modules, refusing to work."
 msgstr ""
 
-#: ../src/daemon/main.c:909
+#: ../src/daemon/main.c:931
 #, c-format
 msgid "Default sink name (%s) does not exist in name register."
 msgstr ""
 
-#: ../src/daemon/main.c:922
+#: ../src/daemon/main.c:944
 msgid "Daemon startup complete."
 msgstr ""
 
-#: ../src/daemon/main.c:928
+#: ../src/daemon/main.c:950
 msgid "Daemon shutdown initiated."
 msgstr ""
 
-#: ../src/daemon/main.c:949
+#: ../src/daemon/main.c:971
 msgid "Daemon terminated."
 msgstr ""
 
@@ -519,76 +555,76 @@ msgstr ""
 msgid "Path: %s\n"
 msgstr ""
 
-#: ../src/daemon/daemon-conf.c:203
+#: ../src/daemon/daemon-conf.c:205
 #, c-format
 msgid "[%s:%u] Invalid log target '%s'."
 msgstr ""
 
-#: ../src/daemon/daemon-conf.c:219
+#: ../src/daemon/daemon-conf.c:221
 #, c-format
 msgid "[%s:%u] Invalid log level '%s'."
 msgstr ""
 
-#: ../src/daemon/daemon-conf.c:235
+#: ../src/daemon/daemon-conf.c:237
 #, c-format
 msgid "[%s:%u] Invalid resample method '%s'."
 msgstr ""
 
-#: ../src/daemon/daemon-conf.c:258
+#: ../src/daemon/daemon-conf.c:260
 #, c-format
 msgid "[%s:%u] Invalid rlimit '%s'."
 msgstr ""
 
-#: ../src/daemon/daemon-conf.c:265
+#: ../src/daemon/daemon-conf.c:267
 #, c-format
 msgid "[%s:%u] rlimit not supported on this platform."
 msgstr ""
 
-#: ../src/daemon/daemon-conf.c:281
+#: ../src/daemon/daemon-conf.c:283
 #, c-format
 msgid "[%s:%u] Invalid sample format '%s'."
 msgstr ""
 
-#: ../src/daemon/daemon-conf.c:299
+#: ../src/daemon/daemon-conf.c:301
 #, c-format
 msgid "[%s:%u] Invalid sample rate '%s'."
 msgstr ""
 
-#: ../src/daemon/daemon-conf.c:317
+#: ../src/daemon/daemon-conf.c:319
 #, c-format
 msgid "[%s:%u] Invalid sample channels '%s'."
 msgstr ""
 
-#: ../src/daemon/daemon-conf.c:335
+#: ../src/daemon/daemon-conf.c:337
 #, c-format
 msgid "[%s:%u] Invalid number of fragments '%s'."
 msgstr ""
 
-#: ../src/daemon/daemon-conf.c:353
+#: ../src/daemon/daemon-conf.c:355
 #, c-format
 msgid "[%s:%u] Invalid fragment size '%s'."
 msgstr ""
 
-#: ../src/daemon/daemon-conf.c:371
+#: ../src/daemon/daemon-conf.c:373
 #, c-format
 msgid "[%s:%u] Invalid nice level '%s'."
 msgstr ""
 
-#: ../src/daemon/daemon-conf.c:564
+#: ../src/daemon/daemon-conf.c:570
 #, c-format
 msgid "Failed to open configuration file: %s"
 msgstr ""
 
-#: ../src/daemon/daemon-conf.c:638
+#: ../src/daemon/daemon-conf.c:644
 #, c-format
 msgid "### Read from configuration file: %s ###\n"
 msgstr ""
 
-#: ../src/daemon/caps.c:62
+#: ../src/daemon/caps.c:63
 msgid "Dropping root priviliges."
 msgstr ""
 
-#: ../src/daemon/caps.c:102
+#: ../src/daemon/caps.c:103
 msgid "Limited capabilities successfully to CAP_SYS_NICE."
 msgstr ""
 
@@ -796,6 +832,11 @@ msgstr ""
 msgid "Top Rear Right"
 msgstr ""
 
+#: ../src/pulse/channelmap.c:472 ../src/pulse/sample.c:144
+#: ../src/pulse/volume.c:163 ../src/pulse/volume.c:194
+msgid "(invalid)"
+msgstr ""
+
 #: ../src/pulse/error.c:43
 msgid "OK"
 msgstr ""
@@ -884,10 +925,6 @@ msgstr ""
 msgid "No such extension"
 msgstr ""
 
-#: ../src/pulse/sample.c:134
-msgid "Invalid"
-msgstr ""
-
 #: ../src/pulse/client-conf-x11.c:55 ../src/utils/pax11publish.c:100
 msgid "XOpenDisplay() failed"
 msgstr ""
@@ -896,31 +933,26 @@ msgstr ""
 msgid "Failed to parse cookie data"
 msgstr ""
 
-#: ../src/pulse/client-conf.c:117
+#: ../src/pulse/client-conf.c:120
 #, c-format
 msgid "Failed to open configuration file '%s': %s"
 msgstr ""
 
-#: ../src/pulse/context.c:542
+#: ../src/pulse/context.c:516
 msgid "No cookie loaded. Attempting to connect without."
 msgstr ""
 
-#: ../src/pulse/context.c:596
-#, c-format
-msgid "socketpair(): %s"
-msgstr ""
-
-#: ../src/pulse/context.c:610
+#: ../src/pulse/context.c:642
 #, c-format
 msgid "fork(): %s"
 msgstr ""
 
-#: ../src/pulse/context.c:673
+#: ../src/pulse/context.c:695
 #, c-format
 msgid "waitpid(): %s"
 msgstr ""
 
-#: ../src/pulse/context.c:1354
+#: ../src/pulse/context.c:1256
 #, c-format
 msgid "Received message for unknown extension '%s'"
 msgstr ""
@@ -1122,8 +1154,8 @@ msgid ""
 "44100)\n"
 "      --format=SAMPLEFORMAT             The sample type, one of s16le, "
 "s16be, u8, float32le,\n"
-"                                        float32be, ulaw, alaw (defaults to "
-"s16ne)\n"
+"                                        float32be, ulaw, alaw, s32le, s32be "
+"(defaults to s16ne)\n"
 "      --channels=CHANNELS               The number of channels, 1 for mono, "
 "2 for stereo\n"
 "                                        (defaults to 2)\n"
@@ -1226,12 +1258,17 @@ msgstr ""
 msgid "pa_context_new() failed.\n"
 msgstr ""
 
-#: ../src/utils/pacat.c:785
+#: ../src/utils/pacat.c:777
+#, c-format
+msgid "pa_context_connect() failed: %s"
+msgstr ""
+
+#: ../src/utils/pacat.c:788
 #, c-format
 msgid "time_new() failed.\n"
 msgstr ""
 
-#: ../src/utils/pacat.c:792 ../src/utils/pasuspender.c:301
+#: ../src/utils/pacat.c:795 ../src/utils/pasuspender.c:301
 #: ../src/utils/pactl.c:931 ../src/utils/paplay.c:407
 #, c-format
 msgid "pa_mainloop_run() failed.\n"
@@ -1782,3 +1819,6 @@ msgstr ""
 msgid "Using sample spec '%s'\n"
 msgstr ""
 
+#: ../src/pulsecore/lock-autospawn.c:126 ../src/pulsecore/lock-autospawn.c:207
+msgid "Cannot access autospawn lock."
+msgstr ""
diff --git a/po/fr.po b/po/fr.po
index 9cd91bf..4dc57d6 100644
--- a/po/fr.po
+++ b/po/fr.po
@@ -9,7 +9,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: pulseaudio trunk\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2008-09-06 06:06+0000\n"
+"POT-Creation-Date: 2008-10-06 03:21+0200\n"
 "PO-Revision-Date: 2008-09-06 10:49+0200\n"
 "Last-Translator: Robert-André Mauchin <zebob.m at pengzone.org>\n"
 "Language-Team: Fedora French <fedora-trans-fr at redhat.com>\n"
@@ -192,22 +192,6 @@ msgstr ""
 "nécessaires :\n"
 "nous ne somme pas dans le groupe "
 
-#: ../src/daemon/main.c:480
-msgid ""
-"' 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 '"
-msgstr ""
-" et PolicyKit refuse de nous accorder les permissions. Abandon du SUID à nouveau.\n"
-"Pour activer la planification en temps réel, veuillez aquérir les permissions "
-"PolicyKit appropriées, ou devenez membre de "
-
-#: ../src/daemon/main.c:481
-msgid ""
-"', or increase the RLIMIT_NICE/RLIMIT_RTPRIO resource limits for this user."
-msgstr ""
-", ou augmentez les limites de ressource RLIMIT_NICE/RLIMIT_RTPRIO pour cet utilisateur."
-
 #: ../src/daemon/main.c:497
 msgid ""
 "High-priority scheduling enabled in configuration but not allowed by policy."
@@ -319,65 +303,80 @@ msgid "This is PulseAudio %s"
 msgstr "Pulseaudio %s"
 
 #: ../src/daemon/main.c:781
+#, fuzzy, c-format
+msgid "Compilation host: %s"
+msgstr "CFLAGS de compilation : %s"
+
+#: ../src/daemon/main.c:782
 #, c-format
 msgid "Compilation CFLAGS: %s"
 msgstr "CFLAGS de compilation : %s"
 
-#: ../src/daemon/main.c:784
+#: ../src/daemon/main.c:785
+#, fuzzy, c-format
+msgid "Running on host: %s"
+msgstr "Exécution en mode système : %s"
+
+#: ../src/daemon/main.c:788
+#, c-format
+msgid "Page size is %lu bytes"
+msgstr "La taille de la page est de %lu octets"
+
+#: ../src/daemon/main.c:791
 msgid "Compiled with Valgrind support: yes"
 msgstr "Compilé avec la prise en charge Valgrind : oui"
 
-#: ../src/daemon/main.c:786
+#: ../src/daemon/main.c:793
 msgid "Compiled with Valgrind support: no"
 msgstr "Compilé avec la prise en charge Valgrind : non"
 
-#: ../src/daemon/main.c:790
+#: ../src/daemon/main.c:796
+#, fuzzy, c-format
+msgid "Running in valgrind mode: %s"
+msgstr "Exécution en mode système : %s"
+
+#: ../src/daemon/main.c:799
 msgid "Optimized build: yes"
 msgstr "Construction optimisée : oui"
 
-#: ../src/daemon/main.c:792
+#: ../src/daemon/main.c:801
 msgid "Optimized build: no"
 msgstr "Construction optimisée : non"
 
-#: ../src/daemon/main.c:795
-#, c-format
-msgid "Page size is %lu bytes"
-msgstr "La taille de la page est de %lu octets"
-
-#: ../src/daemon/main.c:798
+#: ../src/daemon/main.c:805
 msgid "Failed to get machine ID"
 msgstr "Échec lors de l'obtention de l'ID de la machine"
 
-#: ../src/daemon/main.c:801
+#: ../src/daemon/main.c:808
 #, c-format
 msgid "Machine ID is %s."
 msgstr "L'ID de la machine est %s."
 
-#: ../src/daemon/main.c:806
+#: ../src/daemon/main.c:813
 #, c-format
 msgid "Using runtime directory %s."
 msgstr "Utilisation du répertoire d'exécution %s."
 
-#: ../src/daemon/main.c:811
+#: ../src/daemon/main.c:818
 #, c-format
 msgid "Using state directory %s."
 msgstr "Utilisation du répertoire d'état %s."
 
-#: ../src/daemon/main.c:814
+#: ../src/daemon/main.c:821
 #, c-format
 msgid "Running in system mode: %s"
 msgstr "Exécution en mode système : %s"
 
-#: ../src/daemon/main.c:829
+#: ../src/daemon/main.c:836
 msgid "pa_pid_file_create() failed."
 msgstr "Échec de pa_pid_file_create()."
 
-#: ../src/daemon/main.c:841
+#: ../src/daemon/main.c:848
 msgid "Fresh high-resolution timers available! Bon appetit!"
 msgstr ""
 "De nouvelles horloges à haute résolution sont disponibles ! Bon appétit !"
 
-#: ../src/daemon/main.c:843
+#: ../src/daemon/main.c:850
 msgid ""
 "Dude, your kernel stinks! The chef's recommendation today is Linux with high-"
 "resolution timers enabled!"
@@ -385,34 +384,34 @@ msgstr ""
 "Eh mec, ton noyau il pue ! La recommandation d'aujourd'hui du patron est "
 "d'activer les horloges à haute résolution sur ton Linux."
 
-#: ../src/daemon/main.c:853
+#: ../src/daemon/main.c:860
 msgid "pa_core_new() failed."
 msgstr "Échec de pa_core_new()."
 
-#: ../src/daemon/main.c:913
+#: ../src/daemon/main.c:921
 msgid "Failed to initialize daemon."
 msgstr "Échec lors de l'initialisation du démon"
 
-#: ../src/daemon/main.c:918
+#: ../src/daemon/main.c:926
 msgid "Daemon startup without any loaded modules, refusing to work."
 msgstr "Démarrage du démon sans aucun module chargé : refus de fonctionner."
 
-#: ../src/daemon/main.c:923
+#: ../src/daemon/main.c:931
 #, c-format
 msgid "Default sink name (%s) does not exist in name register."
 msgstr ""
 "Le nom de la destination par défaut (%s) n'existe pas dans le registre des "
 "noms."
 
-#: ../src/daemon/main.c:936
+#: ../src/daemon/main.c:944
 msgid "Daemon startup complete."
 msgstr "Démarrage du démon effectué."
 
-#: ../src/daemon/main.c:942
+#: ../src/daemon/main.c:950
 msgid "Daemon shutdown initiated."
 msgstr "Fermeture du démon initiée."
 
-#: ../src/daemon/main.c:963
+#: ../src/daemon/main.c:971
 msgid "Daemon terminated."
 msgstr "Démon terminé."
 
@@ -664,76 +663,76 @@ msgid "Path: %s\n"
 msgstr "Chemin : %s\n"
 
 # dans les lignes suivantes [%s = nom de fichier: %u = ligne dans celui-ci]
-#: ../src/daemon/daemon-conf.c:203
+#: ../src/daemon/daemon-conf.c:205
 #, c-format
 msgid "[%s:%u] Invalid log target '%s'."
 msgstr "[%s:%u] Cible du journal « %s » invalide."
 
-#: ../src/daemon/daemon-conf.c:219
+#: ../src/daemon/daemon-conf.c:221
 #, c-format
 msgid "[%s:%u] Invalid log level '%s'."
 msgstr "[%s:%u] Niveau du journal « %s » invalide."
 
-#: ../src/daemon/daemon-conf.c:235
+#: ../src/daemon/daemon-conf.c:237
 #, c-format
 msgid "[%s:%u] Invalid resample method '%s'."
 msgstr "[%s:%u] Méthode de rééchantillonnage « %s » invalide."
 
-#: ../src/daemon/daemon-conf.c:258
+#: ../src/daemon/daemon-conf.c:260
 #, c-format
 msgid "[%s:%u] Invalid rlimit '%s'."
 msgstr "[%s:%u] rlimit « %s » invalide."
 
-#: ../src/daemon/daemon-conf.c:265
+#: ../src/daemon/daemon-conf.c:267
 #, c-format
 msgid "[%s:%u] rlimit not supported on this platform."
 msgstr "[%s:%u] rlimit n'est pas pris en charge sur cette plateforme."
 
-#: ../src/daemon/daemon-conf.c:281
+#: ../src/daemon/daemon-conf.c:283
 #, c-format
 msgid "[%s:%u] Invalid sample format '%s'."
 msgstr "[%s:%u] Format d'échantillon « %s » invalide."
 
-#: ../src/daemon/daemon-conf.c:299
+#: ../src/daemon/daemon-conf.c:301
 #, c-format
 msgid "[%s:%u] Invalid sample rate '%s'."
 msgstr "[%s:%u] Taux d'échantillonnage « %s » invalide."
 
-#: ../src/daemon/daemon-conf.c:317
+#: ../src/daemon/daemon-conf.c:319
 #, c-format
 msgid "[%s:%u] Invalid sample channels '%s'."
 msgstr "[%s:%u] Canaux d'échantillonnage « %s » invalide."
 
-#: ../src/daemon/daemon-conf.c:335
+#: ../src/daemon/daemon-conf.c:337
 #, c-format
 msgid "[%s:%u] Invalid number of fragments '%s'."
 msgstr "[%s:%u] Nombre de fragments « %s » invalide."
 
-#: ../src/daemon/daemon-conf.c:353
+#: ../src/daemon/daemon-conf.c:355
 #, c-format
 msgid "[%s:%u] Invalid fragment size '%s'."
 msgstr "[%s:%u] Taille du fragment « %s » invalide."
 
-#: ../src/daemon/daemon-conf.c:371
+#: ../src/daemon/daemon-conf.c:373
 #, c-format
 msgid "[%s:%u] Invalid nice level '%s'."
 msgstr "[%s:%u] Niveau de priorité (nice) « %s » invalide."
 
-#: ../src/daemon/daemon-conf.c:564
+#: ../src/daemon/daemon-conf.c:570
 #, c-format
 msgid "Failed to open configuration file: %s"
 msgstr "Échec lors de l'ouverture du fichier de configuration : %s"
 
-#: ../src/daemon/daemon-conf.c:638
+#: ../src/daemon/daemon-conf.c:644
 #, c-format
 msgid "### Read from configuration file: %s ###\n"
 msgstr "### Lecture à partir du fichier de configuration : %s ###\n"
 
-#: ../src/daemon/caps.c:62
+#: ../src/daemon/caps.c:63
 msgid "Dropping root priviliges."
 msgstr "Abandon des permissions root."
 
-#: ../src/daemon/caps.c:102
+#: ../src/daemon/caps.c:103
 msgid "Limited capabilities successfully to CAP_SYS_NICE."
 msgstr "Limitation des capacités à CAP_SYS_NICE réussie."
 
@@ -941,6 +940,12 @@ msgstr "Arrière gauche haut"
 msgid "Top Rear Right"
 msgstr "Arrière droit haut"
 
+#: ../src/pulse/channelmap.c:472 ../src/pulse/sample.c:144
+#: ../src/pulse/volume.c:163 ../src/pulse/volume.c:194
+#, fuzzy
+msgid "(invalid)"
+msgstr "Invalide"
+
 #: ../src/pulse/error.c:43
 msgid "OK"
 msgstr "OK"
@@ -1029,10 +1034,6 @@ msgstr "Code d'erreur inconnu"
 msgid "No such extension"
 msgstr "Aucune extension de ce type"
 
-#: ../src/pulse/sample.c:134
-msgid "Invalid"
-msgstr "Invalide"
-
 #: ../src/pulse/client-conf-x11.c:55 ../src/utils/pax11publish.c:100
 msgid "XOpenDisplay() failed"
 msgstr "Échec de XOpenDisplay()"
@@ -1041,31 +1042,26 @@ msgstr "Échec de XOpenDisplay()"
 msgid "Failed to parse cookie data"
 msgstr "Échec lors de l'analyse des données du cookie"
 
-#: ../src/pulse/client-conf.c:117
+#: ../src/pulse/client-conf.c:120
 #, c-format
 msgid "Failed to open configuration file '%s': %s"
 msgstr "Échec lors de l'ouverture du fichier de configuration « %s » :%s"
 
-#: ../src/pulse/context.c:542
+#: ../src/pulse/context.c:516
 msgid "No cookie loaded. Attempting to connect without."
 msgstr "Aucun cookie chargé. Tentative de connexion sans celui-ci."
 
-#: ../src/pulse/context.c:596
-#, c-format
-msgid "socketpair(): %s"
-msgstr "socketpair() : %s"
-
-#: ../src/pulse/context.c:610
+#: ../src/pulse/context.c:642
 #, c-format
 msgid "fork(): %s"
 msgstr "fork() : %s"
 
-#: ../src/pulse/context.c:673
+#: ../src/pulse/context.c:695
 #, c-format
 msgid "waitpid(): %s"
 msgstr "waitpid() : %s"
 
-#: ../src/pulse/context.c:1354
+#: ../src/pulse/context.c:1256
 #, c-format
 msgid "Received message for unknown extension '%s'"
 msgstr "Message reçu pour une extension inconnue « %s »"
@@ -1247,7 +1243,7 @@ msgstr "Échec de pa_stream_update_timing_info() : %s\n"
 # upmixer = par ex. convertir 2 canaux en 5 canaux
 # https://bugzilla.redhat.com/show_bug.cgi?id=460798
 #: ../src/utils/pacat.c:490
-#, c-format
+#, fuzzy, c-format
 msgid ""
 "%s [options]\n"
 "\n"
@@ -1273,8 +1269,8 @@ msgid ""
 "44100)\n"
 "      --format=SAMPLEFORMAT             The sample type, one of s16le, "
 "s16be, u8, float32le,\n"
-"                                        float32be, ulaw, alaw (defaults to "
-"s16ne)\n"
+"                                        float32be, ulaw, alaw, s32le, s32be "
+"(defaults to s16ne)\n"
 "      --channels=CHANNELS               The number of channels, 1 for mono, "
 "2 for stereo\n"
 "                                        (defaults to 2)\n"
@@ -1431,12 +1427,17 @@ msgstr "Échec de io_new().\n"
 msgid "pa_context_new() failed.\n"
 msgstr "Échec de pa_context_new().\n"
 
-#: ../src/utils/pacat.c:785
+#: ../src/utils/pacat.c:777
+#, fuzzy, c-format
+msgid "pa_context_connect() failed: %s"
+msgstr "Échec de pa_context_new().\n"
+
+#: ../src/utils/pacat.c:788
 #, c-format
 msgid "time_new() failed.\n"
 msgstr "Échec de time_new().\n"
 
-#: ../src/utils/pacat.c:792 ../src/utils/pasuspender.c:301
+#: ../src/utils/pacat.c:795 ../src/utils/pasuspender.c:301
 #: ../src/utils/pactl.c:931 ../src/utils/paplay.c:407
 #, c-format
 msgid "pa_mainloop_run() failed.\n"
@@ -2151,3 +2152,27 @@ msgstr "Le plan des canaux ne correspond pas au fichier.\n"
 #, c-format
 msgid "Using sample spec '%s'\n"
 msgstr "Utilisation de la spécification de l'échantillon « %s »\n"
+
+#: ../src/pulsecore/lock-autospawn.c:126 ../src/pulsecore/lock-autospawn.c:207
+msgid "Cannot access autospawn lock."
+msgstr ""
+
+#~ msgid ""
+#~ "' 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 '"
+#~ msgstr ""
+#~ " et PolicyKit refuse de nous accorder les permissions. Abandon du SUID à "
+#~ "nouveau.\n"
+#~ "Pour activer la planification en temps réel, veuillez aquérir les "
+#~ "permissions PolicyKit appropriées, ou devenez membre de "
+
+#~ msgid ""
+#~ "', or increase the RLIMIT_NICE/RLIMIT_RTPRIO resource limits for this "
+#~ "user."
+#~ msgstr ""
+#~ ", ou augmentez les limites de ressource RLIMIT_NICE/RLIMIT_RTPRIO pour "
+#~ "cet utilisateur."
+
+#~ msgid "socketpair(): %s"
+#~ msgstr "socketpair() : %s"
diff --git a/po/sv.po b/po/sv.po
index 11f6e13..269a225 100644
--- a/po/sv.po
+++ b/po/sv.po
@@ -7,7 +7,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: pulseaudio\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2008-09-04 19:30+0000\n"
+"POT-Creation-Date: 2008-10-06 03:21+0200\n"
 "PO-Revision-Date: 2008-09-05 18:24+0100\n"
 "Last-Translator: Daniel Nylander <po at danielnylander.se>\n"
 "Language-Team: Swedish <tp-sv at listor.tp-sv.se>\n"
@@ -15,8 +15,7 @@ msgstr ""
 "Content-Type: text/plain; charset=utf-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 
-#: ../src/daemon/ltdl-bind-now.c:177
-#: ../src/daemon/ltdl-bind-now.c:197
+#: ../src/daemon/ltdl-bind-now.c:177 ../src/daemon/ltdl-bind-now.c:197
 msgid "Failed to add bind-now-loader."
 msgstr ""
 
@@ -112,8 +111,7 @@ msgstr ""
 msgid "Home directory of user '%s' is not '%s', ignoring."
 msgstr "Hemkatalogen för användaren \"%s\" är inte \"%s\", ignorerar."
 
-#: ../src/daemon/main.c:201
-#: ../src/daemon/main.c:206
+#: ../src/daemon/main.c:201 ../src/daemon/main.c:206
 #, c-format
 msgid "Failed to create '%s': %s"
 msgstr "Misslyckades med att skapa \"%s\": %s"
@@ -178,22 +176,14 @@ msgstr ""
 
 #: ../src/daemon/main.c:479
 msgid ""
-"Called SUID root and real-time/high-priority scheduling was requested in the configuration. However, we lack the necessary priviliges:\n"
+"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 '"
 msgstr ""
 
-#: ../src/daemon/main.c:480
-msgid ""
-"' 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 '"
-msgstr ""
-
-#: ../src/daemon/main.c:481
-msgid "', or increase the RLIMIT_NICE/RLIMIT_RTPRIO resource limits for this user."
-msgstr ""
-
 #: ../src/daemon/main.c:497
-msgid "High-priority scheduling enabled in configuration but not allowed by policy."
+msgid ""
+"High-priority scheduling enabled in configuration but not allowed by policy."
 msgstr ""
 
 #: ../src/daemon/main.c:522
@@ -210,7 +200,8 @@ msgid "Giving up CAP_NICE"
 msgstr ""
 
 #: ../src/daemon/main.c:539
-msgid "Real-time scheduling enabled in configuration but not allowed by policy."
+msgid ""
+"Real-time scheduling enabled in configuration but not allowed by policy."
 msgstr ""
 
 #: ../src/daemon/main.c:597
@@ -228,8 +219,12 @@ msgid "Failed to kill daemon: %s"
 msgstr ""
 
 #: ../src/daemon/main.c:627
-msgid "This program is not intended to be run as root (unless --system is specified)."
-msgstr "Detta program är inte tänkt att köras som root (såvida inte --system har angivits)."
+msgid ""
+"This program is not intended to be run as root (unless --system is "
+"specified)."
+msgstr ""
+"Detta program är inte tänkt att köras som root (såvida inte --system har "
+"angivits)."
 
 #: ../src/daemon/main.c:629
 msgid "Root priviliges required."
@@ -289,92 +284,109 @@ msgstr "Detta är PulseAudio %s"
 
 #: ../src/daemon/main.c:781
 #, c-format
+msgid "Compilation host: %s"
+msgstr ""
+
+#: ../src/daemon/main.c:782
+#, c-format
 msgid "Compilation CFLAGS: %s"
 msgstr ""
 
-#: ../src/daemon/main.c:784
+#: ../src/daemon/main.c:785
+#, c-format
+msgid "Running on host: %s"
+msgstr ""
+
+#: ../src/daemon/main.c:788
+#, c-format
+msgid "Page size is %lu bytes"
+msgstr ""
+
+#: ../src/daemon/main.c:791
 msgid "Compiled with Valgrind support: yes"
 msgstr ""
 
-#: ../src/daemon/main.c:786
+#: ../src/daemon/main.c:793
 msgid "Compiled with Valgrind support: no"
 msgstr ""
 
-#: ../src/daemon/main.c:790
-msgid "Optimized build: yes"
+#: ../src/daemon/main.c:796
+#, c-format
+msgid "Running in valgrind mode: %s"
 msgstr ""
 
-#: ../src/daemon/main.c:792
-msgid "Optimized build: no"
+#: ../src/daemon/main.c:799
+msgid "Optimized build: yes"
 msgstr ""
 
-#: ../src/daemon/main.c:795
-#, c-format
-msgid "Page size is %lu bytes"
+#: ../src/daemon/main.c:801
+msgid "Optimized build: no"
 msgstr ""
 
-#: ../src/daemon/main.c:798
+#: ../src/daemon/main.c:805
 msgid "Failed to get machine ID"
 msgstr ""
 
-#: ../src/daemon/main.c:801
+#: ../src/daemon/main.c:808
 #, c-format
 msgid "Machine ID is %s."
 msgstr ""
 
-#: ../src/daemon/main.c:806
+#: ../src/daemon/main.c:813
 #, c-format
 msgid "Using runtime directory %s."
 msgstr ""
 
-#: ../src/daemon/main.c:811
+#: ../src/daemon/main.c:818
 #, c-format
 msgid "Using state directory %s."
 msgstr ""
 
-#: ../src/daemon/main.c:814
+#: ../src/daemon/main.c:821
 #, c-format
 msgid "Running in system mode: %s"
 msgstr ""
 
-#: ../src/daemon/main.c:829
+#: ../src/daemon/main.c:836
 msgid "pa_pid_file_create() failed."
 msgstr "pa_pid_file_create() misslyckades."
 
-#: ../src/daemon/main.c:841
+#: ../src/daemon/main.c:848
 msgid "Fresh high-resolution timers available! Bon appetit!"
 msgstr ""
 
-#: ../src/daemon/main.c:843
-msgid "Dude, your kernel stinks! The chef's recommendation today is Linux with high-resolution timers enabled!"
+#: ../src/daemon/main.c:850
+msgid ""
+"Dude, your kernel stinks! The chef's recommendation today is Linux with high-"
+"resolution timers enabled!"
 msgstr ""
 
-#: ../src/daemon/main.c:853
+#: ../src/daemon/main.c:860
 msgid "pa_core_new() failed."
 msgstr "pa_core_new() misslyckades."
 
-#: ../src/daemon/main.c:913
+#: ../src/daemon/main.c:921
 msgid "Failed to initialize daemon."
 msgstr ""
 
-#: ../src/daemon/main.c:918
+#: ../src/daemon/main.c:926
 msgid "Daemon startup without any loaded modules, refusing to work."
 msgstr ""
 
-#: ../src/daemon/main.c:923
+#: ../src/daemon/main.c:931
 #, c-format
 msgid "Default sink name (%s) does not exist in name register."
 msgstr ""
 
-#: ../src/daemon/main.c:936
+#: ../src/daemon/main.c:944
 msgid "Daemon startup complete."
 msgstr ""
 
-#: ../src/daemon/main.c:942
+#: ../src/daemon/main.c:950
 msgid "Daemon shutdown initiated."
 msgstr ""
 
-#: ../src/daemon/main.c:963
+#: ../src/daemon/main.c:971
 msgid "Daemon terminated."
 msgstr ""
 
@@ -389,8 +401,10 @@ msgid ""
 "      --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"
-"      --start                           Start the daemon if it is not running\n"
+"      --cleanup-shm                     Cleanup stale shared memory "
+"segments\n"
+"      --start                           Start the daemon if it is not "
+"running\n"
 "  -k  --kill                            Kill a running daemon\n"
 "      --check                           Check for a running daemon\n"
 "\n"
@@ -399,24 +413,31 @@ msgid ""
 "  -D, --daemonize[=BOOL]                Daemonize after startup\n"
 "      --fail[=BOOL]                     Quit when startup fails\n"
 "      --high-priority[=BOOL]            Try to set high nice level\n"
-"                                        (only available as root, when SUID or\n"
+"                                        (only available as root, when SUID "
+"or\n"
 "                                        with elevated RLIMIT_NICE)\n"
 "      --realtime[=BOOL]                 Try to enable realtime scheduling\n"
-"                                        (only available as root, when SUID or\n"
+"                                        (only available as root, when SUID "
+"or\n"
 "                                        with elevated RLIMIT_RTPRIO)\n"
-"      --disallow-module-loading[=BOOL]  Disallow module user requested module\n"
+"      --disallow-module-loading[=BOOL]  Disallow module user requested "
+"module\n"
 "                                        loading/unloading after startup\n"
 "      --disallow-exit[=BOOL]            Disallow user requested exit\n"
-"      --exit-idle-time=SECS             Terminate the daemon when idle and this\n"
+"      --exit-idle-time=SECS             Terminate the daemon when idle and "
+"this\n"
 "                                        time passed\n"
-"      --module-idle-time=SECS           Unload autoloaded modules when idle and\n"
+"      --module-idle-time=SECS           Unload autoloaded modules when idle "
+"and\n"
 "                                        this time passed\n"
-"      --scache-idle-time=SECS           Unload autoloaded samples when idle and\n"
+"      --scache-idle-time=SECS           Unload autoloaded samples when idle "
+"and\n"
 "                                        this time passed\n"
 "      --log-level[=LEVEL]               Increase or set verbosity level\n"
 "  -v                                    Increase the verbosity level\n"
 "      --log-target={auto,syslog,stderr} Specify the log target\n"
-"  -p, --dl-search-path=PATH             Set the search path for dynamic shared\n"
+"  -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"
 "                                        (See --dump-resample-methods for\n"
@@ -427,10 +448,12 @@ msgid ""
 "      --disable-shm[=BOOL]              Disable shared memory support.\n"
 "\n"
 "STARTUP SCRIPT:\n"
-"  -L, --load=\"MODULE ARGUMENTS\"         Load the specified plugin module with\n"
+"  -L, --load=\"MODULE ARGUMENTS\"         Load the specified plugin module "
+"with\n"
 "                                        the specified argument\n"
 "  -F, --file=FILENAME                   Run the specified script\n"
-"  -C                                    Open a command line on the running TTY\n"
+"  -C                                    Open a command line on the running "
+"TTY\n"
 "                                        after startup\n"
 "\n"
 "  -n                                    Don't load default script file\n"
@@ -445,7 +468,9 @@ msgid "--fail expects boolean argument"
 msgstr "--fail förväntar sig ett booleskt argument"
 
 #: ../src/daemon/cmdline.c:262
-msgid "--log-level expects log level argument (either numeric in range 0..4 or one of debug, info, notice, warn, error)."
+msgid ""
+"--log-level expects log level argument (either numeric in range 0..4 or one "
+"of debug, info, notice, warn, error)."
 msgstr ""
 
 #: ../src/daemon/cmdline.c:274
@@ -529,76 +554,76 @@ msgstr ""
 msgid "Path: %s\n"
 msgstr "Sökväg: %s\n"
 
-#: ../src/daemon/daemon-conf.c:203
+#: ../src/daemon/daemon-conf.c:205
 #, c-format
 msgid "[%s:%u] Invalid log target '%s'."
 msgstr ""
 
-#: ../src/daemon/daemon-conf.c:219
+#: ../src/daemon/daemon-conf.c:221
 #, c-format
 msgid "[%s:%u] Invalid log level '%s'."
 msgstr ""
 
-#: ../src/daemon/daemon-conf.c:235
+#: ../src/daemon/daemon-conf.c:237
 #, c-format
 msgid "[%s:%u] Invalid resample method '%s'."
 msgstr ""
 
-#: ../src/daemon/daemon-conf.c:258
+#: ../src/daemon/daemon-conf.c:260
 #, c-format
 msgid "[%s:%u] Invalid rlimit '%s'."
 msgstr ""
 
-#: ../src/daemon/daemon-conf.c:265
+#: ../src/daemon/daemon-conf.c:267
 #, c-format
 msgid "[%s:%u] rlimit not supported on this platform."
 msgstr ""
 
-#: ../src/daemon/daemon-conf.c:281
+#: ../src/daemon/daemon-conf.c:283
 #, c-format
 msgid "[%s:%u] Invalid sample format '%s'."
 msgstr ""
 
-#: ../src/daemon/daemon-conf.c:299
+#: ../src/daemon/daemon-conf.c:301
 #, c-format
 msgid "[%s:%u] Invalid sample rate '%s'."
 msgstr ""
 
-#: ../src/daemon/daemon-conf.c:317
+#: ../src/daemon/daemon-conf.c:319
 #, c-format
 msgid "[%s:%u] Invalid sample channels '%s'."
 msgstr ""
 
-#: ../src/daemon/daemon-conf.c:335
+#: ../src/daemon/daemon-conf.c:337
 #, c-format
 msgid "[%s:%u] Invalid number of fragments '%s'."
 msgstr ""
 
-#: ../src/daemon/daemon-conf.c:353
+#: ../src/daemon/daemon-conf.c:355
 #, c-format
 msgid "[%s:%u] Invalid fragment size '%s'."
 msgstr ""
 
-#: ../src/daemon/daemon-conf.c:371
+#: ../src/daemon/daemon-conf.c:373
 #, c-format
 msgid "[%s:%u] Invalid nice level '%s'."
 msgstr ""
 
-#: ../src/daemon/daemon-conf.c:564
+#: ../src/daemon/daemon-conf.c:570
 #, c-format
 msgid "Failed to open configuration file: %s"
 msgstr "Misslyckades med att öppna konfigurationsfil: %s"
 
-#: ../src/daemon/daemon-conf.c:638
+#: ../src/daemon/daemon-conf.c:644
 #, c-format
 msgid "### Read from configuration file: %s ###\n"
 msgstr ""
 
-#: ../src/daemon/caps.c:62
+#: ../src/daemon/caps.c:63
 msgid "Dropping root priviliges."
 msgstr "Släpper root-behörighet."
 
-#: ../src/daemon/caps.c:102
+#: ../src/daemon/caps.c:103
 msgid "Limited capabilities successfully to CAP_SYS_NICE."
 msgstr ""
 
@@ -806,6 +831,12 @@ msgstr ""
 msgid "Top Rear Right"
 msgstr ""
 
+#: ../src/pulse/channelmap.c:472 ../src/pulse/sample.c:144
+#: ../src/pulse/volume.c:163 ../src/pulse/volume.c:194
+#, fuzzy
+msgid "(invalid)"
+msgstr "Ogiltig"
+
 #: ../src/pulse/error.c:43
 msgid "OK"
 msgstr "OK"
@@ -894,12 +925,7 @@ msgstr "Okänd felkod"
 msgid "No such extension"
 msgstr ""
 
-#: ../src/pulse/sample.c:134
-msgid "Invalid"
-msgstr "Ogiltig"
-
-#: ../src/pulse/client-conf-x11.c:55
-#: ../src/utils/pax11publish.c:100
+#: ../src/pulse/client-conf-x11.c:55 ../src/utils/pax11publish.c:100
 msgid "XOpenDisplay() failed"
 msgstr "XOpenDisplay() misslyckades"
 
@@ -907,31 +933,26 @@ msgstr "XOpenDisplay() misslyckades"
 msgid "Failed to parse cookie data"
 msgstr ""
 
-#: ../src/pulse/client-conf.c:117
+#: ../src/pulse/client-conf.c:120
 #, c-format
 msgid "Failed to open configuration file '%s': %s"
 msgstr "Misslyckades med att öppna konfigurationsfilen \"%s\": %s"
 
-#: ../src/pulse/context.c:542
+#: ../src/pulse/context.c:516
 msgid "No cookie loaded. Attempting to connect without."
 msgstr ""
 
-#: ../src/pulse/context.c:596
-#, c-format
-msgid "socketpair(): %s"
-msgstr "socketpair(): %s"
-
-#: ../src/pulse/context.c:610
+#: ../src/pulse/context.c:642
 #, c-format
 msgid "fork(): %s"
 msgstr "fork(): %s"
 
-#: ../src/pulse/context.c:673
+#: ../src/pulse/context.c:695
 #, c-format
 msgid "waitpid(): %s"
 msgstr "waitpid(): %s"
 
-#: ../src/pulse/context.c:1354
+#: ../src/pulse/context.c:1256
 #, c-format
 msgid "Received message for unknown extension '%s'"
 msgstr ""
@@ -1045,28 +1066,23 @@ msgstr "pa_stream_connect_playback() misslyckades: %s\n"
 msgid "pa_stream_connect_record() failed: %s\n"
 msgstr "pa_stream_connect_record() misslyckades: %s\n"
 
-#: ../src/utils/pacat.c:307
-#: ../src/utils/pasuspender.c:159
-#: ../src/utils/pactl.c:666
-#: ../src/utils/paplay.c:183
+#: ../src/utils/pacat.c:307 ../src/utils/pasuspender.c:159
+#: ../src/utils/pactl.c:666 ../src/utils/paplay.c:183
 #, c-format
 msgid "Connection failure: %s\n"
 msgstr "Anslutningsfel: %s\n"
 
-#: ../src/utils/pacat.c:328
-#: ../src/utils/paplay.c:75
+#: ../src/utils/pacat.c:328 ../src/utils/paplay.c:75
 #, c-format
 msgid "Failed to drain stream: %s\n"
 msgstr ""
 
-#: ../src/utils/pacat.c:333
-#: ../src/utils/paplay.c:80
+#: ../src/utils/pacat.c:333 ../src/utils/paplay.c:80
 #, c-format
 msgid "Playback stream drained.\n"
 msgstr ""
 
-#: ../src/utils/pacat.c:343
-#: ../src/utils/paplay.c:92
+#: ../src/utils/pacat.c:343 ../src/utils/paplay.c:92
 #, c-format
 msgid "Draining connection to server.\n"
 msgstr ""
@@ -1124,27 +1140,44 @@ msgid ""
 "\n"
 "  -v, --verbose                         Enable verbose operations\n"
 "\n"
-"  -s, --server=SERVER                   The name of the server to connect to\n"
-"  -d, --device=DEVICE                   The name of the sink/source to connect to\n"
-"  -n, --client-name=NAME                How to call this client on the server\n"
-"      --stream-name=NAME                How to call this stream on the server\n"
-"      --volume=VOLUME                   Specify the initial (linear) volume in range 0...65536\n"
-"      --rate=SAMPLERATE                 The sample rate in Hz (defaults to 44100)\n"
-"      --format=SAMPLEFORMAT             The sample type, one of s16le, s16be, u8, float32le,\n"
-"                                        float32be, ulaw, alaw (defaults to s16ne)\n"
-"      --channels=CHANNELS               The number of channels, 1 for mono, 2 for stereo\n"
+"  -s, --server=SERVER                   The name of the server to connect "
+"to\n"
+"  -d, --device=DEVICE                   The name of the sink/source to "
+"connect to\n"
+"  -n, --client-name=NAME                How to call this client on the "
+"server\n"
+"      --stream-name=NAME                How to call this stream on the "
+"server\n"
+"      --volume=VOLUME                   Specify the initial (linear) volume "
+"in range 0...65536\n"
+"      --rate=SAMPLERATE                 The sample rate in Hz (defaults to "
+"44100)\n"
+"      --format=SAMPLEFORMAT             The sample type, one of s16le, "
+"s16be, u8, float32le,\n"
+"                                        float32be, ulaw, alaw, s32le, s32be "
+"(defaults to s16ne)\n"
+"      --channels=CHANNELS               The number of channels, 1 for mono, "
+"2 for stereo\n"
 "                                        (defaults to 2)\n"
-"      --channel-map=CHANNELMAP          Channel map to use instead of the default\n"
-"      --fix-format                      Take the sample format from the sink the stream is\n"
+"      --channel-map=CHANNELMAP          Channel map to use instead of the "
+"default\n"
+"      --fix-format                      Take the sample format from the sink "
+"the stream is\n"
 "                                        being connected to.\n"
-"      --fix-rate                        Take the sampling rate from the sink the stream is\n"
+"      --fix-rate                        Take the sampling rate from the sink "
+"the stream is\n"
 "                                        being connected to.\n"
-"      --fix-channels                    Take the number of channels and the channel map\n"
-"                                        from the sink the stream is being connected to.\n"
+"      --fix-channels                    Take the number of channels and the "
+"channel map\n"
+"                                        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"
-"      --process-time=BYTES              Request the specified process time per request in bytes.\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"
 msgstr ""
 
 #: ../src/utils/pacat.c:591
@@ -1208,10 +1241,8 @@ msgstr "dup2(): %s\n"
 msgid "Too many arguments.\n"
 msgstr "För många argument.\n"
 
-#: ../src/utils/pacat.c:742
-#: ../src/utils/pasuspender.c:280
-#: ../src/utils/pactl.c:909
-#: ../src/utils/paplay.c:381
+#: ../src/utils/pacat.c:742 ../src/utils/pasuspender.c:280
+#: ../src/utils/pactl.c:909 ../src/utils/paplay.c:381
 #, c-format
 msgid "pa_mainloop_new() failed.\n"
 msgstr "pa_mainloop_new() misslyckades.\n"
@@ -1221,23 +1252,24 @@ msgstr "pa_mainloop_new() misslyckades.\n"
 msgid "io_new() failed.\n"
 msgstr "io_new() misslyckades.\n"
 
-#: ../src/utils/pacat.c:769
-#: ../src/utils/pasuspender.c:293
-#: ../src/utils/pactl.c:923
-#: ../src/utils/paplay.c:396
+#: ../src/utils/pacat.c:769 ../src/utils/pasuspender.c:293
+#: ../src/utils/pactl.c:923 ../src/utils/paplay.c:396
 #, c-format
 msgid "pa_context_new() failed.\n"
 msgstr "pa_context_new() misslyckades.\n"
 
-#: ../src/utils/pacat.c:785
+#: ../src/utils/pacat.c:777
+#, fuzzy, c-format
+msgid "pa_context_connect() failed: %s"
+msgstr "pa_context_new() misslyckades.\n"
+
+#: ../src/utils/pacat.c:788
 #, c-format
 msgid "time_new() failed.\n"
 msgstr "time_new() misslyckades.\n"
 
-#: ../src/utils/pacat.c:792
-#: ../src/utils/pasuspender.c:301
-#: ../src/utils/pactl.c:931
-#: ../src/utils/paplay.c:407
+#: ../src/utils/pacat.c:795 ../src/utils/pasuspender.c:301
+#: ../src/utils/pactl.c:931 ../src/utils/paplay.c:407
 #, c-format
 msgid "pa_mainloop_run() failed.\n"
 msgstr "pa_mainloop_run() misslyckades.\n"
@@ -1267,8 +1299,7 @@ msgstr ""
 msgid "WARNING: Sound server is not local, not suspending.\n"
 msgstr ""
 
-#: ../src/utils/pasuspender.c:176
-#: ../src/utils/pactl.c:672
+#: ../src/utils/pasuspender.c:176 ../src/utils/pactl.c:672
 #: ../src/utils/paplay.c:191
 #, c-format
 msgid "Got SIGINT, exiting.\n"
@@ -1286,7 +1317,8 @@ msgid ""
 "\n"
 "  -h, --help                            Show this help\n"
 "      --version                         Show version\n"
-"  -s, --server=SERVER                   The name of the server to connect to\n"
+"  -s, --server=SERVER                   The name of the server to connect "
+"to\n"
 "\n"
 msgstr ""
 
@@ -1361,8 +1393,7 @@ msgid ""
 "%s"
 msgstr ""
 
-#: ../src/utils/pactl.c:193
-#: ../src/utils/pactl.c:371
+#: ../src/utils/pactl.c:193 ../src/utils/pactl.c:371
 msgid "muted"
 msgstr "tystad"
 
@@ -1388,18 +1419,10 @@ msgid ""
 "%s"
 msgstr ""
 
-#: ../src/utils/pactl.c:246
-#: ../src/utils/pactl.c:289
-#: ../src/utils/pactl.c:322
-#: ../src/utils/pactl.c:366
-#: ../src/utils/pactl.c:367
-#: ../src/utils/pactl.c:374
-#: ../src/utils/pactl.c:418
-#: ../src/utils/pactl.c:419
-#: ../src/utils/pactl.c:425
-#: ../src/utils/pactl.c:468
-#: ../src/utils/pactl.c:469
-#: ../src/utils/pactl.c:473
+#: ../src/utils/pactl.c:246 ../src/utils/pactl.c:289 ../src/utils/pactl.c:322
+#: ../src/utils/pactl.c:366 ../src/utils/pactl.c:367 ../src/utils/pactl.c:374
+#: ../src/utils/pactl.c:418 ../src/utils/pactl.c:419 ../src/utils/pactl.c:425
+#: ../src/utils/pactl.c:468 ../src/utils/pactl.c:469 ../src/utils/pactl.c:473
 msgid "n/a"
 msgstr ""
 
@@ -1522,8 +1545,7 @@ msgstr "sink"
 msgid "source"
 msgstr "källa"
 
-#: ../src/utils/pactl.c:511
-#: ../src/utils/pactl.c:521
+#: ../src/utils/pactl.c:511 ../src/utils/pactl.c:521
 #, c-format
 msgid "Failure: %s\n"
 msgstr "Fel: %s\n"
@@ -1557,8 +1579,10 @@ msgid ""
 "  -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"
+"  -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"
 msgstr ""
 
 #: ../src/utils/pactl.c:729
@@ -1614,12 +1638,16 @@ msgstr ""
 
 #: ../src/utils/pactl.c:875
 #, c-format
-msgid "You may not specify more than one sink. You have to specify at least one boolean value.\n"
+msgid ""
+"You may not specify more than one sink. You have to specify at least one "
+"boolean value.\n"
 msgstr ""
 
 #: ../src/utils/pactl.c:888
 #, c-format
-msgid "You may not specify more than one source. You have to specify at least one boolean value.\n"
+msgid ""
+"You may not specify more than one source. You have to specify at least one "
+"boolean value.\n"
 msgstr ""
 
 #: ../src/utils/pactl.c:904
@@ -1634,7 +1662,8 @@ msgid ""
 "\n"
 " -d    Show current PulseAudio data attached to X11 display (default)\n"
 " -e    Export local PulseAudio data to X11 display\n"
-" -i    Import PulseAudio data from X11 display to local environment variables and cookie file.\n"
+" -i    Import PulseAudio data from X11 display to local environment "
+"variables and cookie file.\n"
 " -r    Remove PulseAudio data from X11 display\n"
 msgstr ""
 
@@ -1721,14 +1750,12 @@ msgstr ""
 msgid "select(): %s"
 msgstr "select(): %s"
 
-#: ../src/utils/pacmd.c:124
-#: ../src/utils/pacmd.c:140
+#: ../src/utils/pacmd.c:124 ../src/utils/pacmd.c:140
 #, c-format
 msgid "read(): %s"
 msgstr "read(): %s"
 
-#: ../src/utils/pacmd.c:153
-#: ../src/utils/pacmd.c:167
+#: ../src/utils/pacmd.c:153 ../src/utils/pacmd.c:167
 #, c-format
 msgid "write(): %s"
 msgstr "write(): %s"
@@ -1758,11 +1785,15 @@ msgid ""
 "\n"
 "  -v, --verbose                         Enable verbose operation\n"
 "\n"
-"  -s, --server=SERVER                   The name of the server to connect to\n"
+"  -s, --server=SERVER                   The name of the server to connect "
+"to\n"
 "  -d, --device=DEVICE                   The name of the sink to connect to\n"
-"  -n, --client-name=NAME                How to call this client on the server\n"
-"      --stream-name=NAME                How to call this stream on the server\n"
-"      --volume=VOLUME                   Specify the initial (linear) volume in range 0...65536\n"
+"  -n, --client-name=NAME                How to call this client on the "
+"server\n"
+"      --stream-name=NAME                How to call this stream on the "
+"server\n"
+"      --volume=VOLUME                   Specify the initial (linear) volume "
+"in range 0...65536\n"
 "      --channel-map=CHANNELMAP          Set the channel map to the use\n"
 msgstr ""
 
@@ -1797,3 +1828,9 @@ msgstr ""
 msgid "Using sample spec '%s'\n"
 msgstr ""
 
+#: ../src/pulsecore/lock-autospawn.c:126 ../src/pulsecore/lock-autospawn.c:207
+msgid "Cannot access autospawn lock."
+msgstr ""
+
+#~ msgid "socketpair(): %s"
+#~ msgstr "socketpair(): %s"
diff --git a/src/Makefile.am b/src/Makefile.am
index 9cbb9c7..f277198 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1590,7 +1590,7 @@ libbluetooth_ipc_la_LDFLAGS = -avoid-version
 libbluetooth_ipc_la_LIBADD = $(AM_LIBADD)
 libbluetooth_ipc_la_CFLAGS = $(AM_CFLAGS)
 
-module_bluetooth_device_la_SOURCES = modules/bluetooth/module-bluetooth-device.c
+module_bluetooth_device_la_SOURCES = modules/bluetooth/module-bluetooth-device.c modules/bluetooth/rtp.h
 module_bluetooth_device_la_LDFLAGS = -module -avoid-version
 module_bluetooth_device_la_LIBADD = $(AM_LIBADD) $(DBUS_LIBS) libpulsecore.la libdbus-util.la libbluetooth-ipc.la libbluetooth-sbc.la libsocket-util.la
 module_bluetooth_device_la_CFLAGS = $(AM_CFLAGS) $(DBUS_CFLAGS)
diff --git a/src/modules/bluetooth/module-bluetooth-device.c b/src/modules/bluetooth/module-bluetooth-device.c
index bf9bad6..3460fe9 100644
--- a/src/modules/bluetooth/module-bluetooth-device.c
+++ b/src/modules/bluetooth/module-bluetooth-device.c
@@ -44,7 +44,7 @@
 #include <pulsecore/time-smoother.h>
 #include <pulsecore/rtclock.h>
 
-#include "dbus-util.h"
+#include "../dbus-util.h"
 #include "module-bluetooth-device-symdef.h"
 #include "ipc.h"
 #include "sbc.h"
diff --git a/src/modules/bluetooth/module-bluetooth-discover.c b/src/modules/bluetooth/module-bluetooth-discover.c
index 03abf26..0601e9a 100644
--- a/src/modules/bluetooth/module-bluetooth-discover.c
+++ b/src/modules/bluetooth/module-bluetooth-discover.c
@@ -34,7 +34,7 @@
 #include <pulsecore/llist.h>
 #include <pulsecore/core-util.h>
 
-#include "dbus-util.h"
+#include "../dbus-util.h"
 #include "module-bluetooth-discover-symdef.h"
 
 PA_MODULE_AUTHOR("Joao Paulo Rechi Vita");
diff --git a/src/modules/bluetooth/module-bluetooth-proximity.c b/src/modules/bluetooth/module-bluetooth-proximity.c
index 5cca36e..4cfaaf5 100644
--- a/src/modules/bluetooth/module-bluetooth-proximity.c
+++ b/src/modules/bluetooth/module-bluetooth-proximity.c
@@ -43,7 +43,7 @@
 #include <pulsecore/core-error.h>
 #include <pulsecore/start-child.h>
 
-#include "dbus-util.h"
+#include "../dbus-util.h"
 #include "module-bluetooth-proximity-symdef.h"
 
 PA_MODULE_AUTHOR("Lennart Poettering");

commit c8a963af0270c5fbc125ea34da6538198f524189
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Oct 7 02:00:07 2008 +0200

    Initialize exit_idle_time to -1 instead of 0  when in system mode.
    
    Spotted by Rafał Mużyło.

diff --git a/src/daemon/main.c b/src/daemon/main.c
index fad635f..bc8bc63 100644
--- a/src/daemon/main.c
+++ b/src/daemon/main.c
@@ -646,9 +646,9 @@ int main(int argc, char *argv[]) {
         conf->disable_shm = TRUE;
     }
 
-    if (conf->system_instance && conf->exit_idle_time > 0) {
+    if (conf->system_instance && conf->exit_idle_time >= 0) {
         pa_log_notice(_("Running in system mode, forcibly disabling exit idle time!"));
-        conf->exit_idle_time = 0;
+        conf->exit_idle_time = -1;
     }
 
     if (conf->cmd == PA_CMD_START) {

commit 3d7b76d159765a78e6e7288bd7aa5c276aa24e87
Author: Luiz Augusto von Dentz <luiz.dentz at openbossa.org>
Date:   Mon Oct 6 14:59:15 2008 -0300

    Unload module-bluetooth-device if the remote device disconnects.

diff --git a/src/modules/bluetooth/module-bluetooth-discover.c b/src/modules/bluetooth/module-bluetooth-discover.c
index 0601e9a..a33ca64 100644
--- a/src/modules/bluetooth/module-bluetooth-discover.c
+++ b/src/modules/bluetooth/module-bluetooth-discover.c
@@ -91,6 +91,16 @@ static void module_free(struct module *m) {
     pa_xfree(m);
 }
 
+static struct module* module_find(struct device *d, const char *profile) {
+    struct module *m;
+
+    for (m = d->module_list; d; d = d->next)
+        if (pa_streq(m->profile, profile))
+            return m;
+
+    return NULL;
+}
+
 static struct uuid *uuid_new(const char *uuid) {
     struct uuid *node;
 
@@ -345,6 +355,21 @@ static void load_module_for_device(struct userdata *u, struct device *d, const c
     PA_LLIST_PREPEND(struct module, d->module_list, m);
 }
 
+static void unload_module_for_device(struct userdata *u, struct device *d, const char *profile) {
+    struct module *m;
+
+    pa_assert(u);
+    pa_assert(d);
+
+    if (!(m = module_find(d, profile)))
+        return;
+
+    pa_module_unload_request(m->pa_m, TRUE);
+
+    PA_LLIST_REMOVE(struct module, d->module_list, m);
+    module_free(m);
+}
+
 static DBusHandlerResult filter_cb(DBusConnection *bus, DBusMessage *msg, void *userdata) {
     DBusMessageIter arg_i;
     DBusError err;
@@ -387,6 +412,7 @@ static DBusHandlerResult filter_cb(DBusConnection *bus, DBusMessage *msg, void *
         struct device *d;
         const char *profile;
         DBusMessageIter variant_i;
+        dbus_bool_t connected;
 
         if (!dbus_message_iter_init(msg, &arg_i)) {
             pa_log("dbus: message has no parameters");
@@ -400,6 +426,9 @@ static DBusHandlerResult filter_cb(DBusConnection *bus, DBusMessage *msg, void *
 
         dbus_message_iter_get_basic(&arg_i, &value);
 
+        if (!pa_streq(value, "Connected"))
+            goto done;
+
         if (!dbus_message_iter_next(&arg_i)) {
             pa_log("Property value missing");
             goto done;
@@ -412,25 +441,29 @@ static DBusHandlerResult filter_cb(DBusConnection *bus, DBusMessage *msg, void *
 
         dbus_message_iter_recurse(&arg_i, &variant_i);
 
-        if (dbus_message_iter_get_arg_type(&variant_i) == DBUS_TYPE_BOOLEAN) {
-            dbus_bool_t connected;
-            dbus_message_iter_get_basic(&variant_i, &connected);
-
-            if (!pa_streq(value, "Connected") || !connected)
-                goto done;
+        if (dbus_message_iter_get_arg_type(&variant_i) != DBUS_TYPE_BOOLEAN) {
+            pa_log("Property value not a boolean.");
+            goto done;
         }
 
-        if (!(d = device_find(u, dbus_message_get_path(msg)))) {
-                d = device_new(dbus_message_get_path(msg));
-                PA_LLIST_PREPEND(struct device, u->device_list, d);
-        }
+        dbus_message_iter_get_basic(&variant_i, &connected);
 
         if (dbus_message_is_signal(msg, "org.bluez.Headset", "PropertyChanged"))
             profile = "hsp";
         else
             profile = "a2dp";
 
-        load_module_for_device(u, d, profile);
+        d = device_find(u, dbus_message_get_path(msg));
+
+        if (connected) {
+            if (!d) {
+                    d = device_new(dbus_message_get_path(msg));
+                    PA_LLIST_PREPEND(struct device, u->device_list, d);
+            }
+
+            load_module_for_device(u, d, profile);
+        } else if (d)
+            unload_module_for_device(u, d, profile);
     }
 
 done:

commit 5925d44013e2d559d1755176af0e26f69fc46458
Merge: 3d7b76d... 8c2a7c8...
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Oct 7 21:38:06 2008 +0200

    Merge commit 'origin/master-tx' into master-tx
    
    Conflicts:
    	po/de.po

diff --cc po/de.po
index 9643d04,4fc8706..b587e21
--- a/po/de.po
+++ b/po/de.po
@@@ -7,9 -7,9 +7,9 @@@ msgid "
  msgstr ""
  "Project-Id-Version: pulseaudio\n"
  "Report-Msgid-Bugs-To: \n"
- "POT-Creation-Date: 2008-10-06 03:21+0200\n"
- "PO-Revision-Date: 2008-08-31 12:22+0100\n"
- "Last-Translator: Fabian Affolter <fab at fedoraproject.org>\n"
 -"POT-Creation-Date: 2008-09-11 19:30+0000\n"
 -"PO-Revision-Date: 2008-09-29 12:57+0100\n"
 -"Last-Translator: Fabian Affolter <fab at fedoraproject.org>\n"
++"POT-Creation-Date: 2008-10-07 21:03+0200\n"
++"PO-Revision-Date: 2008-10-07 21:36+0100\n"
++"Last-Translator: Lennart Poettering <lennart at poettering.net>\n"
  "Language-Team: German <fedora-trans-de at redhat.com>\n"
  "MIME-Version: 1.0\n"
  "Content-Type: text/plain; charset=utf-8\n"
@@@ -17,9 -17,10 +17,9 @@@
  "Plural-Forms: nplurals=2; plural=(n != 1);\n"
  "X-Poedit-Language: German\n"
  
 -#: ../src/daemon/ltdl-bind-now.c:177
 -#: ../src/daemon/ltdl-bind-now.c:197
 +#: ../src/daemon/ltdl-bind-now.c:177 ../src/daemon/ltdl-bind-now.c:197
  msgid "Failed to add bind-now-loader."
--msgstr "Hinzufügen von bind-now-loader fehlgeschlagen."
++msgstr "Hinzufügen von Bind-Now-Loader fehlgeschlagen."
  
  #: ../src/daemon/ltdl-bind-now.c:184
  msgid "Failed to find original dlopen loader."
@@@ -33,11 -34,11 +33,11 @@@ msgstr "Kann nicht mit dem System-Bus v
  #: ../src/daemon/polkit.c:65
  #, c-format
  msgid "Cannot get caller from PID: %s"
--msgstr "Kann caller von PID nicht benziehen: %s"
++msgstr "Kann Caller von PID nicht beziehen: %s"
  
  #: ../src/daemon/polkit.c:77
  msgid "Cannot set UID on caller object."
--msgstr "Kann caller-Ojekt für UID nicht setzen."
++msgstr "Kann Caller-Ojekt für UID nicht setzen."
  
  #: ../src/daemon/polkit.c:82
  msgid "Failed to get CK session."
@@@ -45,24 -46,26 +45,24 @@@ msgstr "Kann CK-Session nicht beziehen.
  
  #: ../src/daemon/polkit.c:90
  msgid "Cannot set UID on session object."
- msgstr ""
+ msgstr "Kann UID auf Session-Objekt nicht setzen."
  
  #: ../src/daemon/polkit.c:95
 -#, fuzzy
  msgid "Cannot allocate PolKitAction."
- msgstr ""
 -msgstr "Farbtabelleneinträge konnten nicht bereitgestellt werden"
++msgstr "Konnte PolKitAction nicht allozieren."
  
  #: ../src/daemon/polkit.c:100
  msgid "Cannot set action_id"
  msgstr "Kann action_id nicht setzen"
  
  #: ../src/daemon/polkit.c:105
 -#, fuzzy
  msgid "Cannot allocate PolKitContext."
- msgstr ""
 -msgstr "Farbtabelleneinträge konnten nicht bereitgestellt werden"
++msgstr "Konnte PolKitContext nicht allozieren"
  
  #: ../src/daemon/polkit.c:110
 -#, fuzzy, c-format
 +#, c-format
  msgid "Cannot initialize PolKitContext: %s"
- msgstr ""
 -msgstr "Kann OLE nicht initialisieren"
++msgstr "Konnte PolKitContect nicht initialisieren: %s"
  
  #: ../src/daemon/polkit.c:119
  #, c-format
@@@ -70,9 -73,9 +70,9 @@@ msgid "Could not determine whether call
  msgstr ""
  
  #: ../src/daemon/polkit.c:139
 -#, fuzzy, c-format
 +#, c-format
  msgid "Cannot obtain auth: %s"
- msgstr ""
 -msgstr "Kann die Datei nicht bearbeiten"
++msgstr "Erhalten der Authorisierung fehlgeschlagen: %s"
  
  #: ../src/daemon/polkit.c:148
  #, c-format
@@@ -126,7 -130,7 +126,7 @@@ msgstr "Wechseln der Gruppen-Liste fehl
  #: ../src/daemon/main.c:229
  #, c-format
  msgid "Failed to change GID: %s"
- msgstr ""
 -msgstr "WEchseln der GID fehlgeschlagen: %s"
++msgstr "Wechseln der GID fehlgeschlagen: %s"
  
  #: ../src/daemon/main.c:245
  #, c-format
@@@ -139,7 -143,7 +139,7 @@@ msgstr "Root-Berechtigungen erfolgreic
  
  #: ../src/daemon/main.c:267
  msgid "System wide mode unsupported on this platform."
- msgstr ""
 -msgstr "Systemweiter Modus auf dieser Plattform nicht unterstützt."
++msgstr "System-Modus auf dieser Plattform nicht unterstützt."
  
  #: ../src/daemon/main.c:285
  #, c-format
@@@ -147,8 -151,9 +147,8 @@@ msgid "setrlimit(%s, (%u, %u)) failed: 
  msgstr "setrlimit(%s, (%u, %u)) fehlgeschlagen: %s"
  
  #: ../src/daemon/main.c:425
 -#, fuzzy
  msgid "Failed to parse command line."
- msgstr ""
 -msgstr "Parsen der Port-Nummer fehlgeschlagen: %s\n"
++msgstr "Parsen der Kommandzeile fehlgeschlagen."
  
  #: ../src/daemon/main.c:441
  #, c-format
@@@ -199,11 -212,10 +199,11 @@@ msgstr "RLIMIT_RTPRIO fehlgeschlagen: %
  
  #: ../src/daemon/main.c:532
  msgid "Giving up CAP_NICE"
- msgstr ""
+ msgstr "Gebe CAP_NICE auf"
  
  #: ../src/daemon/main.c:539
 -msgid "Real-time scheduling enabled in configuration but not allowed by policy."
 +msgid ""
 +"Real-time scheduling enabled in configuration but not allowed by policy."
  msgstr ""
  
  #: ../src/daemon/main.c:597
@@@ -213,17 -225,15 +213,17 @@@ msgstr "Daemon läuft nicht
  #: ../src/daemon/main.c:599
  #, c-format
  msgid "Daemon running as PID %u"
- msgstr ""
 -msgstr "Lasse Daemon als PID %u laufen"
++msgstr "Daemon läuft als PID %u"
  
  #: ../src/daemon/main.c:609
 -#, fuzzy, c-format
 +#, c-format
  msgid "Failed to kill daemon: %s"
- msgstr ""
 -msgstr "Konnte Prozess %d nicht abbrechen"
++msgstr "Konnte Prozess nicht abbrechen: %s"
  
  #: ../src/daemon/main.c:627
 -msgid "This program is not intended to be run as root (unless --system is specified)."
 +msgid ""
 +"This program is not intended to be run as root (unless --system is "
 +"specified)."
  msgstr ""
  
  #: ../src/daemon/main.c:629
@@@ -231,8 -241,9 +231,8 @@@ msgid "Root priviliges required.
  msgstr "Root-Berechtigungen benötigt."
  
  #: ../src/daemon/main.c:634
 -#, fuzzy
  msgid "--start not supported for system instances."
- msgstr ""
+ msgstr "--start nicht unterstützt für System-Instanzen."
  
  #: ../src/daemon/main.c:639
  msgid "Running in system mode, but --disallow-exit not set!"
@@@ -251,8 -262,9 +251,8 @@@ msgid "Running in system mode, forcibl
  msgstr ""
  
  #: ../src/daemon/main.c:677
 -#, fuzzy
  msgid "Failed to acquire stdio."
- msgstr ""
 -msgstr "Verzeichnis konnte nicht gewechselt werden"
++msgstr "Reservieren von STDIO fehlgeschlagen."
  
  #: ../src/daemon/main.c:683
  #, c-format
@@@ -283,14 -295,14 +283,14 @@@ msgid "This is PulseAudio %s
  msgstr "Dies ist PulseAudio %s"
  
  #: ../src/daemon/main.c:781
 -#, fuzzy, c-format
 +#, c-format
  msgid "Compilation host: %s"
- msgstr ""
+ msgstr "Kompilations-Host: %s"
  
  #: ../src/daemon/main.c:782
  #, c-format
  msgid "Compilation CFLAGS: %s"
- msgstr ""
 -msgstr "Kompiliere CFLAGS: %s"
++msgstr "Kompilier-CFLAGS: %s"
  
  #: ../src/daemon/main.c:785
  #, c-format
@@@ -308,46 -320,41 +308,46 @@@ msgstr "Kompiliere mit Valgrind-Unterst
  
  #: ../src/daemon/main.c:793
  msgid "Compiled with Valgrind support: no"
- msgstr ""
+ msgstr "Kompiliere mit Valgrind-Unterstützung: nein"
  
 -#: ../src/daemon/main.c:797
 +#: ../src/daemon/main.c:796
 +#, c-format
 +msgid "Running in valgrind mode: %s"
- msgstr ""
++msgstr "Laufe im Valgrind-Modus: %s"
 +
 +#: ../src/daemon/main.c:799
  msgid "Optimized build: yes"
- msgstr ""
+ msgstr "Optimiertes Build: ja"
  
 -#: ../src/daemon/main.c:799
 +#: ../src/daemon/main.c:801
  msgid "Optimized build: no"
- msgstr ""
+ msgstr "Optimiertes Build: nein"
  
 -#: ../src/daemon/main.c:803
 +#: ../src/daemon/main.c:805
  msgid "Failed to get machine ID"
- msgstr ""
 -msgstr "Erhalten der Maschinen-ID fehlgeschlagen"
++msgstr "Beziehen der Maschinen-ID fehlgeschlagen"
  
 -#: ../src/daemon/main.c:806
 +#: ../src/daemon/main.c:808
  #, c-format
  msgid "Machine ID is %s."
  msgstr "System- ID ist %s."
  
 -#: ../src/daemon/main.c:811
 -#, fuzzy, c-format
 +#: ../src/daemon/main.c:813
 +#, c-format
  msgid "Using runtime directory %s."
- msgstr ""
 -msgstr "&Lokaler Verzeichnisbaum"
++msgstr "Nutze Laufzeit-Verzeichnis %s."
  
 -#: ../src/daemon/main.c:816
 -#, fuzzy, c-format
 +#: ../src/daemon/main.c:818
 +#, c-format
  msgid "Using state directory %s."
- msgstr ""
 -msgstr "&Lokaler Verzeichnisbaum"
++msgstr "Nutze Zustands-Verzeichnis %s."
  
 -#: ../src/daemon/main.c:819
 -#, fuzzy, c-format
 +#: ../src/daemon/main.c:821
 +#, c-format
  msgid "Running in system mode: %s"
- msgstr ""
 -msgstr "Standard-Enforcing-Modus des Systems"
++msgstr "Laufe im System-Modus: %s"
  
 -#: ../src/daemon/main.c:834
 +#: ../src/daemon/main.c:836
  msgid "pa_pid_file_create() failed."
  msgstr "pa_pid_file_create() fehlgeschlagen."
  
@@@ -365,11 -370,12 +365,11 @@@ msgstr "
  msgid "pa_core_new() failed."
  msgstr "pa_core_new() fehlgeschlagen."
  
 -#: ../src/daemon/main.c:919
 -#, fuzzy
 +#: ../src/daemon/main.c:921
  msgid "Failed to initialize daemon."
- msgstr ""
 -msgstr "TLS konnte nicht initialisiert werden."
++msgstr "Konnte Dämon nicht initialisieren"
  
 -#: ../src/daemon/main.c:924
 +#: ../src/daemon/main.c:926
  msgid "Daemon startup without any loaded modules, refusing to work."
  msgstr ""
  
@@@ -382,11 -388,11 +382,11 @@@ msgstr "
  msgid "Daemon startup complete."
  msgstr "Start des Dämons abgeschlossen."
  
 -#: ../src/daemon/main.c:948
 +#: ../src/daemon/main.c:950
  msgid "Daemon shutdown initiated."
- msgstr ""
+ msgstr "Herunterfahren des Daemon gestartet."
  
 -#: ../src/daemon/main.c:969
 +#: ../src/daemon/main.c:971
  msgid "Daemon terminated."
  msgstr "Dämon beendet."
  
@@@ -458,6 -453,59 +458,70 @@@ msgid "
  "\n"
  "  -n                                    Don't load default script file\n"
  msgstr ""
+ "%s [options]\n"
+ "\n"
+ "COMMANDS:\n"
+ "  -h, --help                            Show this help\n"
+ "      --version                         Show version\n"
+ "      --dump-conf                       Dump default configuration\n"
+ "      --dump-modules                    Dump list of available modules\n"
+ "      --dump-resample-methods           Dump available resample methods\n"
 -"      --cleanup-shm                     Cleanup stale shared memory segments\n"
 -"      --start                           Start the daemon if it is not running\n"
++"      --cleanup-shm                     Cleanup stale shared memory "
++"segments\n"
++"      --start                           Start the daemon if it is not "
++"running\n"
+ "  -k  --kill                            Kill a running daemon\n"
+ "      --check                           Check for a running daemon\n"
+ "\n"
+ "OPTIONS:\n"
+ "      --system[=BOOL]                   Run as system-wide instance\n"
+ "  -D, --daemonize[=BOOL]                Daemonize after startup\n"
+ "      --fail[=BOOL]                     Quit when startup fails\n"
+ "      --high-priority[=BOOL]            Try to set high nice level\n"
 -"                                        (only available as root, when SUID or\n"
++"                                        (only available as root, when SUID "
++"or\n"
+ "                                        with elevated RLIMIT_NICE)\n"
+ "      --realtime[=BOOL]                 Try to enable realtime scheduling\n"
 -"                                        (only available as root, when SUID or\n"
++"                                        (only available as root, when SUID "
++"or\n"
+ "                                        with elevated RLIMIT_RTPRIO)\n"
 -"      --disallow-module-loading[=BOOL]  Disallow module user requested module\n"
++"      --disallow-module-loading[=BOOL]  Disallow module user requested "
++"module\n"
+ "                                        loading/unloading after startup\n"
+ "      --disallow-exit[=BOOL]            Disallow user requested exit\n"
 -"      --exit-idle-time=SECS             Terminate the daemon when idle and this\n"
++"      --exit-idle-time=SECS             Terminate the daemon when idle and "
++"this\n"
+ "                                        time passed\n"
 -"      --module-idle-time=SECS           Unload autoloaded modules when idle and\n"
++"      --module-idle-time=SECS           Unload autoloaded modules when idle "
++"and\n"
+ "                                        this time passed\n"
 -"      --scache-idle-time=SECS           Unload autoloaded samples when idle and\n"
++"      --scache-idle-time=SECS           Unload autoloaded samples when idle "
++"and\n"
+ "                                        this time passed\n"
+ "      --log-level[=LEVEL]               Increase or set verbosity level\n"
+ "  -v                                    Increase the verbosity level\n"
+ "      --log-target={auto,syslog,stderr} Specify the log target\n"
 -"  -p, --dl-search-path=PATH             Set the search path for dynamic shared\n"
++"  -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"
+ "                                        (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"
+ "      --disable-shm[=BOOL]              Disable shared memory support.\n"
+ "\n"
+ "STARTUP SCRIPT:\n"
 -"  -L, --load=\"MODULE ARGUMENTS\"         Load the specified plugin module with\n"
++"  -L, --load=\"MODULE ARGUMENTS\"         Load the specified plugin module "
++"with\n"
+ "                                        the specified argument\n"
+ "  -F, --file=FILENAME                   Run the specified script\n"
 -"  -C                                    Open a command line on the running TTY\n"
++"  -C                                    Open a command line on the running "
++"TTY\n"
+ "                                        after startup\n"
+ "\n"
+ "  -n                                    Don't load default script file\n"
  
  #: ../src/daemon/cmdline.c:245
  msgid "--daemonize expects boolean argument"
@@@ -495,7 -541,7 +559,8 @@@ msgstr "
  
  #: ../src/daemon/cmdline.c:319
  msgid "Invalid log target: use either 'syslog', 'stderr' or 'auto'."
 -msgstr "Ungültiges Log-Ziel: Benutzen Sie entweder 'syslog', 'stderr' oder 'auto'."
 +msgstr ""
++"Ungültiges Log-Ziel: Benutzen Sie entweder 'syslog', 'stderr' oder 'auto'."
  
  #: ../src/daemon/cmdline.c:338
  #, c-format
@@@ -554,76 -600,76 +619,76 @@@ msgstr "Lade einmalig: %s\n
  msgid "Path: %s\n"
  msgstr "Pfad: %s\n"
  
 -#: ../src/daemon/daemon-conf.c:204
 +#: ../src/daemon/daemon-conf.c:205
  #, c-format
  msgid "[%s:%u] Invalid log target '%s'."
- msgstr ""
+ msgstr "[%s:%u] Ungültiges Log-Ziel '%s'."
  
 -#: ../src/daemon/daemon-conf.c:220
 +#: ../src/daemon/daemon-conf.c:221
  #, c-format
  msgid "[%s:%u] Invalid log level '%s'."
- msgstr ""
+ msgstr "[%s:%u] Ungültige Log-Stufe '%s'."
  
 -#: ../src/daemon/daemon-conf.c:236
 +#: ../src/daemon/daemon-conf.c:237
  #, c-format
  msgid "[%s:%u] Invalid resample method '%s'."
- msgstr ""
+ msgstr "[%s:%u] Ungültige Resample-Methode '%s'."
  
 -#: ../src/daemon/daemon-conf.c:259
 +#: ../src/daemon/daemon-conf.c:260
  #, c-format
  msgid "[%s:%u] Invalid rlimit '%s'."
- msgstr ""
+ msgstr "[%s:%u] Ungültiges rlimit '%s'."
  
 -#: ../src/daemon/daemon-conf.c:266
 +#: ../src/daemon/daemon-conf.c:267
  #, c-format
  msgid "[%s:%u] rlimit not supported on this platform."
- msgstr ""
+ msgstr "[%s:%u] rlimit nicht unterstützt auf dieser Plattform."
  
 -#: ../src/daemon/daemon-conf.c:282
 +#: ../src/daemon/daemon-conf.c:283
  #, c-format
  msgid "[%s:%u] Invalid sample format '%s'."
- msgstr ""
+ msgstr "[%s:%u] Ungültiges Sample-Format '%s'."
  
 -#: ../src/daemon/daemon-conf.c:300
 +#: ../src/daemon/daemon-conf.c:301
  #, c-format
  msgid "[%s:%u] Invalid sample rate '%s'."
- msgstr ""
+ msgstr "[%s:%u] Ungültige Sample-Rate '%s'."
  
 -#: ../src/daemon/daemon-conf.c:318
 +#: ../src/daemon/daemon-conf.c:319
  #, c-format
  msgid "[%s:%u] Invalid sample channels '%s'."
- msgstr ""
+ msgstr "[%s:%u] Ungültige Sample-Kanäle '%s'."
  
 -#: ../src/daemon/daemon-conf.c:336
 +#: ../src/daemon/daemon-conf.c:337
  #, c-format
  msgid "[%s:%u] Invalid number of fragments '%s'."
- msgstr ""
+ msgstr "[%s:%u] Ungültige Anzahl von Fragmenten '%s'."
  
 -#: ../src/daemon/daemon-conf.c:354
 +#: ../src/daemon/daemon-conf.c:355
  #, c-format
  msgid "[%s:%u] Invalid fragment size '%s'."
- msgstr ""
 -msgstr "[%s:%u] Ungültige Fragement-Grösse '%s'."
++msgstr "[%s:%u] Ungültige Fragment-Größe '%s'."
  
 -#: ../src/daemon/daemon-conf.c:372
 +#: ../src/daemon/daemon-conf.c:373
  #, c-format
  msgid "[%s:%u] Invalid nice level '%s'."
- msgstr ""
+ msgstr "[%s:%u] Ungültige Nice-Stufe '%s'."
  
 -#: ../src/daemon/daemon-conf.c:567
 +#: ../src/daemon/daemon-conf.c:570
  #, c-format
  msgid "Failed to open configuration file: %s"
- msgstr ""
+ msgstr "Öffnen der Konfigurationsdatei fehlgeschlagen : %s"
  
 -#: ../src/daemon/daemon-conf.c:641
 +#: ../src/daemon/daemon-conf.c:644
  #, c-format
  msgid "### Read from configuration file: %s ###\n"
- msgstr ""
+ msgstr "### Lesen von Konfigurationsdatei: %s ###\n"
  
 -#: ../src/daemon/caps.c:62
 +#: ../src/daemon/caps.c:63
  msgid "Dropping root priviliges."
--msgstr "Verlasse Root-Berechtigungen."
++msgstr "Gebe Root-Privilegien auf."
  
 -#: ../src/daemon/caps.c:102
 +#: ../src/daemon/caps.c:103
  msgid "Limited capabilities successfully to CAP_SYS_NICE."
  msgstr ""
  
@@@ -809,7 -855,7 +874,7 @@@ msgstr "Oben Mitte
  
  #: ../src/pulse/channelmap.c:155
  msgid "Top Front Center"
--msgstr "Oben Vorne Mitter"
++msgstr "Oben Vorne Mitte"
  
  #: ../src/pulse/channelmap.c:156
  msgid "Top Front Left"
@@@ -831,12 -877,6 +896,11 @@@ msgstr "Oben Hinten Links
  msgid "Top Rear Right"
  msgstr "Oben Hinten Rechts"
  
 +#: ../src/pulse/channelmap.c:472 ../src/pulse/sample.c:144
 +#: ../src/pulse/volume.c:163 ../src/pulse/volume.c:194
- #, fuzzy
 +msgid "(invalid)"
- msgstr "Ungültig"
++msgstr "(ungültig)"
 +
  #: ../src/pulse/error.c:43
  msgid "OK"
  msgstr "OK"
@@@ -859,7 -899,7 +923,7 @@@ msgstr "Entität existiert bereits
  
  #: ../src/pulse/error.c:48
  msgid "No such entity"
--msgstr "Keine Entität vorhanden"
++msgstr "Entität nicht vorhanden"
  
  #: ../src/pulse/error.c:49
  msgid "Connection refused"
@@@ -887,7 -927,7 +951,7 @@@ msgstr "Verbindung beendet
  
  #: ../src/pulse/error.c:55
  msgid "Entity killed"
--msgstr "Entität terminiert."
++msgstr "Entität terminiert"
  
  #: ../src/pulse/error.c:56
  msgid "Invalid server"
@@@ -930,13 -975,14 +994,13 @@@ msgid "XOpenDisplay() failed
  msgstr "XOpenDisplay() fehlgeschlagen"
  
  #: ../src/pulse/client-conf-x11.c:78
 -#, fuzzy
  msgid "Failed to parse cookie data"
- msgstr ""
 -msgstr "TIFF-Daten konnten nicht gespeichert werden"
++msgstr "Parsen der Cookie-Daten fehlgeschlagen"
  
 -#: ../src/pulse/client-conf.c:117
 -#, fuzzy, c-format
 +#: ../src/pulse/client-conf.c:120
 +#, c-format
  msgid "Failed to open configuration file '%s': %s"
- msgstr ""
 -msgstr "Datei »%s« konnte nicht geöffnet werden: fdopen() fehlgeschlagen: %s"
++msgstr "Konfigurationsdatei »%s« konnte nicht geöffnet werden: %s"
  
  #: ../src/pulse/context.c:516
  msgid "No cookie loaded. Attempting to connect without."
@@@ -978,9 -1024,9 +1042,9 @@@ msgid "pa_stream_drop() failed: %s\n
  msgstr "pa_stream_drop() fehlgeschlagen: %s\n"
  
  #: ../src/utils/pacat.c:169
 -#, fuzzy, c-format
 +#, c-format
  msgid "Stream successfully created.\n"
- msgstr ""
 -msgstr "Cache-Datei wurde erfolgreich erstellt.\n"
++msgstr "Stream wurde erfolgreich erstellt.\n"
  
  #: ../src/utils/pacat.c:172
  #, c-format
@@@ -1003,34 -1049,34 +1067,34 @@@ msgid "Using sample spec '%s', channel 
  msgstr ""
  
  #: ../src/utils/pacat.c:187
 -#, fuzzy, c-format
 +#, c-format
  msgid "Connected to device %s (%u, %ssuspended).\n"
- msgstr ""
 -msgstr "Zu benutzendes DVD-Device"
++msgstr "Connected to device %s (%u, %ssuspended).\n"
  
  #: ../src/utils/pacat.c:197
  #, c-format
  msgid "Stream error: %s\n"
- msgstr ""
+ msgstr "Stream-Fehler: %s\n"
  
  #: ../src/utils/pacat.c:207
 -#, fuzzy, c-format
 +#, c-format
  msgid "Stream device suspended.%s \n"
- msgstr ""
 -msgstr "ALSA Devicename"
++msgstr "Strom-Gerät eingeschlafen.%s\n"
  
  #: ../src/utils/pacat.c:209
 -#, fuzzy, c-format
 +#, c-format
  msgid "Stream device resumed.%s \n"
- msgstr ""
 -msgstr "ALSA Devicename"
++msgstr "Stream-Gerät aufgeweckt.%s\n"
  
  #: ../src/utils/pacat.c:217
 -#, fuzzy, c-format
 +#, c-format
  msgid "Stream underrun.%s \n"
- msgstr ""
 -msgstr "Stream underun.%s \n"
++msgstr "Stream underrun.%s \n"
  
  #: ../src/utils/pacat.c:224
- #, c-format
+ #, fuzzy, c-format
  msgid "Stream overrun.%s \n"
- msgstr ""
+ msgstr "Stream overrun.%s \n"
  
  #: ../src/utils/pacat.c:231
  #, c-format
@@@ -1066,31 -1112,36 +1130,31 @@@ msgstr "pa_stream_connect_playback() fe
  msgid "pa_stream_connect_record() failed: %s\n"
  msgstr "pa_stream_connect_record() fehlgeschlagen: %s\n"
  
 -#: ../src/utils/pacat.c:307
 -#: ../src/utils/pasuspender.c:159
 -#: ../src/utils/pactl.c:666
 -#: ../src/utils/paplay.c:183
 +#: ../src/utils/pacat.c:307 ../src/utils/pasuspender.c:159
 +#: ../src/utils/pactl.c:666 ../src/utils/paplay.c:183
  #, c-format
  msgid "Connection failure: %s\n"
- msgstr ""
+ msgstr "Verbindungsfehler: %s\n"
  
 -#: ../src/utils/pacat.c:328
 -#: ../src/utils/paplay.c:75
 -#, fuzzy, c-format
 +#: ../src/utils/pacat.c:328 ../src/utils/paplay.c:75
 +#, c-format
  msgid "Failed to drain stream: %s\n"
- msgstr ""
 -msgstr "Adresse des Computers, zu dem gestreamt wird."
++msgstr "Entleeren des Streams fehlgeschlagen: %s\n"
  
 -#: ../src/utils/pacat.c:333
 -#: ../src/utils/paplay.c:80
 -#, fuzzy, c-format
 +#: ../src/utils/pacat.c:333 ../src/utils/paplay.c:80
 +#, c-format
  msgid "Playback stream drained.\n"
- msgstr ""
 -msgstr "Bridge-Streamausgabe"
++msgstr "Wiedergabe-Stream entleert.\n"
  
 -#: ../src/utils/pacat.c:343
 -#: ../src/utils/paplay.c:92
 -#, fuzzy, c-format
 +#: ../src/utils/pacat.c:343 ../src/utils/paplay.c:92
 +#, c-format
  msgid "Draining connection to server.\n"
- msgstr ""
 -msgstr "Konnte keine Verbindung zum Server aufbauen"
++msgstr "Draining connection to server.\n"
  
  #: ../src/utils/pacat.c:369
  #, c-format
  msgid "Got EOF.\n"
--msgstr "Erhielt EOF.\n"
++msgstr "EOF empfangen.\n"
  
  #: ../src/utils/pacat.c:375
  #, c-format
@@@ -1110,7 -1161,7 +1174,7 @@@ msgstr "write() fehlgeschlagen: %s\n
  #: ../src/utils/pacat.c:438
  #, c-format
  msgid "Got signal, exiting.\n"
- msgstr ""
 -msgstr "Erhielt Signal, verlasse.\n"
++msgstr "Signal empfangen, beende.\n"
  
  #: ../src/utils/pacat.c:452
  #, c-format
@@@ -1303,7 -1347,7 +1370,7 @@@ msgstr "
  #: ../src/utils/paplay.c:191
  #, c-format
  msgid "Got SIGINT, exiting.\n"
- msgstr ""
 -msgstr "Erhielt SIGINT, verlasse.\n"
++msgstr "SIGINT empfangen, beende.\n"
  
  #: ../src/utils/pasuspender.c:194
  #, c-format
@@@ -1317,10 -1361,15 +1384,17 @@@ msgid "
  "\n"
  "  -h, --help                            Show this help\n"
  "      --version                         Show version\n"
 -"  -s, --server=SERVER                   The name of the server to connect to\n"
 +"  -s, --server=SERVER                   The name of the server to connect "
 +"to\n"
  "\n"
  msgstr ""
+ "%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"
++"  -s, --server=SERVER                   The name of the server to connect "
++"to\n"
+ "\n"
  
  #: ../src/utils/pasuspender.c:251
  #, c-format
@@@ -1348,12 -1397,12 +1422,12 @@@ msgstr "
  #: ../src/utils/pactl.c:119
  #, c-format
  msgid "Sample cache size: %s\n"
- msgstr ""
 -msgstr "Sample-Zwischenspeichergrösse: %s\n"
++msgstr "Sample-Pufferspeichergrösse: %s\n"
  
  #: ../src/utils/pactl.c:128
  #, c-format
  msgid "Failed to get server information: %s\n"
- msgstr ""
 -msgstr "Erhalten der Server-Information fehlgeschlagen: %s\n"
++msgstr "Beziehen der Server-Information fehlgeschlagen: %s\n"
  
  #: ../src/utils/pactl.c:135
  #, c-format
@@@ -1369,9 -1418,9 +1443,9 @@@ msgid "
  msgstr ""
  
  #: ../src/utils/pactl.c:160
 -#, fuzzy, c-format
 +#, c-format
  msgid "Failed to get sink information: %s\n"
- msgstr ""
+ msgstr "Erhalten der Sink-Information fehlgeschlagen: %s\n"
  
  #: ../src/utils/pactl.c:176
  #, c-format
@@@ -1397,7 -1447,7 +1471,7 @@@ msgstr "stumm
  #: ../src/utils/pactl.c:212
  #, c-format
  msgid "Failed to get source information: %s\n"
- msgstr ""
 -msgstr "Erhalten der Quellen-Information fehlgeschlagen: %s\n"
++msgstr "Beziehen der Quellen-Information fehlgeschlagen: %s\n"
  
  #: ../src/utils/pactl.c:228
  #, c-format
@@@ -1426,7 -1484,7 +1500,7 @@@ msgstr "k.A.
  #: ../src/utils/pactl.c:263
  #, c-format
  msgid "Failed to get module information: %s\n"
- msgstr ""
 -msgstr "Erhalten der Modul-Information fehlgeschlagen: %s\n"
++msgstr "Beziehen der Modul-Information fehlgeschlagen: %s\n"
  
  #: ../src/utils/pactl.c:281
  #, c-format
@@@ -1441,7 -1499,7 +1515,7 @@@ msgstr "
  #: ../src/utils/pactl.c:298
  #, c-format
  msgid "Failed to get client information: %s\n"
- msgstr ""
 -msgstr "Erhalten der Client-Information fehlgeschlagen: %s\n"
++msgstr "Beziehen der Client-Information fehlgeschlagen: %s\n"
  
  #: ../src/utils/pactl.c:316
  #, c-format
@@@ -1501,7 -1559,7 +1575,7 @@@ msgstr "
  #: ../src/utils/pactl.c:436
  #, c-format
  msgid "Failed to get sample information: %s\n"
- msgstr ""
 -msgstr "Erhalten der Sample-Information fehlgeschlagen: %s\n"
++msgstr "Beziehen der Sample-Information fehlgeschlagen: %s\n"
  
  #: ../src/utils/pactl.c:455
  #, c-format
@@@ -1522,7 -1580,7 +1596,7 @@@ msgstr "
  #: ../src/utils/pactl.c:481
  #, c-format
  msgid "Failed to get autoload information: %s\n"
- msgstr ""
 -msgstr "Erhalten der Autoload-Information fehlgeschlagen: %s\n"
++msgstr "Beziehen der Autoload-Information fehlgeschlagen: %s\n"
  
  #: ../src/utils/pactl.c:497
  #, c-format
@@@ -1542,23 -1600,24 +1616,23 @@@ msgstr "
  msgid "source"
  msgstr "Quelle"
  
 -#: ../src/utils/pactl.c:511
 -#: ../src/utils/pactl.c:521
 +#: ../src/utils/pactl.c:511 ../src/utils/pactl.c:521
  #, c-format
  msgid "Failure: %s\n"
- msgstr ""
 -msgstr "Fehlschlag: %s\n"
++msgstr "Fehlgeschlagen: %s\n"
  
  #: ../src/utils/pactl.c:545
  #, c-format
  msgid "Failed to upload sample: %s\n"
- msgstr ""
 -msgstr "Hinaufladen des Sample fehlgeschlagen: %s\n"
++msgstr "Hochladen des Sample fehlgeschlagen: %s\n"
  
  #: ../src/utils/pactl.c:562
 -#, fuzzy, c-format
 +#, c-format
  msgid "Premature end of file\n"
- msgstr ""
 -msgstr "Dateiende ist zu früh aufgetreten"
++msgstr "Dateiende ist zu früh aufgetreten\n"
  
  #: ../src/utils/pactl.c:678
- #, c-format
+ #, fuzzy, c-format
  msgid ""
  "%s [options] stat\n"
  "%s [options] list\n"
@@@ -1576,11 -1635,27 +1650,31 @@@
  "  -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"
 +"  -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"
  msgstr ""
+ "%s [options] stat\n"
+ "%s [options] list\n"
+ "%s [options] exit\n"
+ "%s [options] upload-sample FILENAME [NAME]\n"
+ "%s [options] play-sample NAME [SINK]\n"
+ "%s [options] remove-sample NAME\n"
+ "%s [options] move-sink-input ID SINK\n"
+ "%s [options] move-source-output ID SOURCE\n"
+ "%s [options] load-module NAME [ARGS ...]\n"
+ "%s [options] unload-module ID\n"
+ "%s [options] suspend-sink [SINK] 1|0\n"
+ "%s [options] suspend-source [SOURCE] 1|0\n"
+ "\n"
+ "  -h, --help                            Show this help\n"
+ "      --version                         Show version\n"
+ "\n"
 -"  -s, --server=SERVER                   The name of the server to connect to\n"
 -"  -n, --client-name=NAME                How to call this client on the server\n"
++"  -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"
  
  #: ../src/utils/pactl.c:729
  #, c-format
@@@ -1589,6 -1664,9 +1683,9 @@@ msgid "
  "Compiled with libpulse %s\n"
  "Linked with libpulse %s\n"
  msgstr ""
+ "pactl %s\n"
+ "Kompiliert mit libpulse %s\n"
 -"Verknüpft mit libpulse %s\n"
++"Gelinkt mit libpulse %s\n"
  
  #: ../src/utils/pactl.c:768
  #, c-format
@@@ -1598,17 -1676,17 +1695,17 @@@ msgstr "
  #: ../src/utils/pactl.c:790
  #, c-format
  msgid "Failed to open sound file.\n"
- msgstr ""
+ msgstr "Öffnen der Audio-Datei fehlgeschlagen.\n"
  
  #: ../src/utils/pactl.c:802
 -#, fuzzy, c-format
 +#, c-format
  msgid "You have to specify a sample name to play\n"
- msgstr ""
 -msgstr "Es muss ein Repository-Name angegeben werden"
++msgstr "You have to specify a sample name to play\n"
  
  #: ../src/utils/pactl.c:814
 -#, fuzzy, c-format
 +#, c-format
  msgid "You have to specify a sample name to remove\n"
- msgstr ""
 -msgstr "Es muss ein Paket zum Entfernen angegeben werden"
++msgstr "You have to specify a sample name to remove\n"
  
  #: ../src/utils/pactl.c:822
  #, c-format
@@@ -1621,14 -1699,14 +1718,14 @@@ msgid "You have to specify a source out
  msgstr ""
  
  #: ../src/utils/pactl.c:845
 -#, fuzzy, c-format
 +#, c-format
  msgid "You have to specify a module name and arguments.\n"
- msgstr ""
 -msgstr "Es muss ein Repository-Name/Argument und Wert angegeben werden"
++msgstr "You have to specify a module name and arguments.\n"
  
  #: ../src/utils/pactl.c:865
 -#, fuzzy, c-format
 +#, c-format
  msgid "You have to specify a module index\n"
- msgstr ""
 -msgstr "Geben Sie das zu benutzende Deinterlace-Modul an."
++msgstr "You have to specify a module index\n"
  
  #: ../src/utils/pactl.c:875
  #, c-format
@@@ -1656,15 -1730,20 +1753,22 @@@ msgid "
  "\n"
  " -d    Show current PulseAudio data attached to X11 display (default)\n"
  " -e    Export local PulseAudio data to X11 display\n"
 -" -i    Import PulseAudio data from X11 display to local environment variables and cookie file.\n"
 +" -i    Import PulseAudio data from X11 display to local environment "
 +"variables and cookie file.\n"
  " -r    Remove PulseAudio data from X11 display\n"
  msgstr ""
+ "%s [-D display] [-S server] [-O sink] [-I source] [-c file]  [-d|-e|-i|-r]\n"
+ "\n"
+ " -d    Show current PulseAudio data attached to X11 display (default)\n"
+ " -e    Export local PulseAudio data to X11 display\n"
 -" -i    Import PulseAudio data from X11 display to local environment variables and cookie file.\n"
++" -i    Import PulseAudio data from X11 display to local environment "
++"variables and cookie file.\n"
+ " -r    Remove PulseAudio data from X11 display\n"
  
  #: ../src/utils/pax11publish.c:94
 -#, fuzzy, c-format
 +#, c-format
  msgid "Failed to parse command line.\n"
- msgstr ""
 -msgstr "Parsen der Port-Nummer fehlgeschlagen: %s\n"
++msgstr "Parsen der Kommandozeile fehlgeschlagen.\n"
  
  #: ../src/utils/pax11publish.c:108
  #, c-format
@@@ -1687,9 -1766,9 +1791,9 @@@ msgid "Cookie: %s\n
  msgstr "Cookie: %s\n"
  
  #: ../src/utils/pax11publish.c:132
 -#, fuzzy, c-format
 +#, c-format
  msgid "Failed to parse cookie data\n"
- msgstr ""
 -msgstr "TIFF-Daten konnten nicht gespeichert werden"
++msgstr "Paresen der Cookie-Daten fehlgeschlagen.\n"
  
  #: ../src/utils/pax11publish.c:137
  #, c-format
@@@ -1699,12 -1778,12 +1803,12 @@@ msgstr "Speichern der Cookie-Daten fehl
  #: ../src/utils/pax11publish.c:152
  #, c-format
  msgid "Failed to load client configuration file.\n"
- msgstr ""
 -msgstr "Laden der Client-Konfigurationsdatei fehlgeschlagen\n"
++msgstr "Laden der Client-Konfigurationsdatei fehlgeschlagen.\n"
  
  #: ../src/utils/pax11publish.c:157
 -#, fuzzy, c-format
 +#, c-format
  msgid "Failed to read environment configuration data.\n"
- msgstr ""
 -msgstr "Daten konnten nicht vom Kindprozess gelesen werden"
++msgstr "Lesen the Umgebungsdaten fehlgeschlagen.\n"
  
  #: ../src/utils/pax11publish.c:174
  #, c-format
@@@ -1719,7 -1798,7 +1823,7 @@@ msgstr "Laden der Cookie-Daten fehlgesc
  #: ../src/utils/pax11publish.c:211
  #, c-format
  msgid "Not yet implemented.\n"
- msgstr ""
 -msgstr "Momentan nicht implementiert.\n"
++msgstr "Noch nicht implementiert.\n"
  
  #: ../src/utils/pacmd.c:64
  #, c-format
@@@ -1733,7 -1812,7 +1837,7 @@@ msgstr "connect(): %s
  
  #: ../src/utils/pacmd.c:89
  msgid "Failed to kill PulseAudio daemon."
- msgstr ""
 -msgstr "Abwürgen des PulseAudio-Daemon fehlgeschlagen."
++msgstr "Terminieren des PulseAudio-Daemon fehlgeschlagen."
  
  #: ../src/utils/pacmd.c:97
  msgid "Daemon not responding."
@@@ -1779,17 -1860,26 +1883,34 @@@ msgid "
  "\n"
  "  -v, --verbose                         Enable verbose operation\n"
  "\n"
 -"  -s, --server=SERVER                   The name of the server to connect to\n"
 +"  -s, --server=SERVER                   The name of the server to connect "
 +"to\n"
  "  -d, --device=DEVICE                   The name of the sink to connect to\n"
 -"  -n, --client-name=NAME                How to call this client on the server\n"
 -"      --stream-name=NAME                How to call this stream on the server\n"
 -"      --volume=VOLUME                   Specify the initial (linear) volume in range 0...65536\n"
 +"  -n, --client-name=NAME                How to call this client on the "
 +"server\n"
 +"      --stream-name=NAME                How to call this stream on the "
 +"server\n"
 +"      --volume=VOLUME                   Specify the initial (linear) volume "
 +"in range 0...65536\n"
  "      --channel-map=CHANNELMAP          Set the channel map to the use\n"
  msgstr ""
+ "%s [options] [FILE]\n"
+ "\n"
+ "  -h, --help                            Show this help\n"
+ "      --version                         Show version\n"
+ "\n"
+ "  -v, --verbose                         Enable verbose operation\n"
+ "\n"
 -"  -s, --server=SERVER                   The name of the server to connect to\n"
++"  -s, --server=SERVER                   The name of the server to connect "
++"to\n"
+ "  -d, --device=DEVICE                   The name of the sink to connect to\n"
 -"  -n, --client-name=NAME                How to call this client on the server\n"
 -"      --stream-name=NAME                How to call this stream on the server\n"
 -"      --volume=VOLUME                   Specify the initial (linear) volume in range 0...65536\n"
++"  -n, --client-name=NAME                How to call this client on the "
++"server\n"
++"      --stream-name=NAME                How to call this stream on the "
++"server\n"
++"      --volume=VOLUME                   Specify the initial (linear) volume "
++"in range 0...65536\n"
+ "      --channel-map=CHANNELMAP          Set the channel map to the use\n"
  
  #: ../src/utils/paplay.c:255
  #, c-format
@@@ -1798,6 -1888,9 +1919,9 @@@ msgid "
  "Compiled with libpulse %s\n"
  "Linked with libpulse %s\n"
  msgstr ""
+ "paplay %s\n"
+ "Kompliert mit libpulse %s\n"
 -"Verknüpft mit libpulse %s\n"
++"Gelinkt mit libpulse %s\n"
  
  #: ../src/utils/paplay.c:292
  #, c-format
@@@ -1812,16 -1905,18 +1936,16 @@@ msgstr "Öffnen der Datei '%s' fehlgesc
  #: ../src/utils/paplay.c:350
  #, c-format
  msgid "Channel map doesn't match file.\n"
- msgstr ""
 -msgstr "KAnal-Auflistung stimmt mit DAtei nicht überein.\n"
++msgstr "Kanal-Zuweisung stimmt mit Datei nicht überein.\n"
  
  #: ../src/utils/paplay.c:376
  #, c-format
  msgid "Using sample spec '%s'\n"
- msgstr ""
 -msgstr "Beispiel-Spec '%s' wird benutzt\n"
++msgstr "Sampling-Spezifikation '%s' wird benutzt\n"
  
 -#: ../src/pulsecore/lock-autospawn.c:126
 -#: ../src/pulsecore/lock-autospawn.c:207
 -#, fuzzy
 +#: ../src/pulsecore/lock-autospawn.c:126 ../src/pulsecore/lock-autospawn.c:207
  msgid "Cannot access autospawn lock."
- msgstr ""
 -msgstr "Fehler beim Zugriff auf automatische Sperre."
++msgstr "Fehler beim Zugriff auf Autostart -Sperre."
  
  #~ msgid "socketpair(): %s"
  #~ msgstr "socketpair(): %s"
diff --cc po/el.po
index fed9ba9,b664491..79ccda7
--- a/po/el.po
+++ b/po/el.po
@@@ -6,7 -6,7 +6,7 @@@ msgid "
  msgstr ""
  "Project-Id-Version: el\n"
  "Report-Msgid-Bugs-To: \n"
- "POT-Creation-Date: 2008-10-06 03:21+0200\n"
 -"POT-Creation-Date: 2008-08-22 19:36+0300\n"
++"POT-Creation-Date: 2008-10-07 21:03+0200\n"
  "PO-Revision-Date: 2008-08-22 19:40+0300\n"
  "Last-Translator: Dimitris Glezos <dimitris at glezos.com>\n"
  "Language-Team: Greek <fedora-trans-el at redhat.com>\n"
diff --cc po/fr.po
index 4dc57d6,9cd91bf..6d35390
--- a/po/fr.po
+++ b/po/fr.po
@@@ -9,7 -9,7 +9,7 @@@ msgid "
  msgstr ""
  "Project-Id-Version: pulseaudio trunk\n"
  "Report-Msgid-Bugs-To: \n"
- "POT-Creation-Date: 2008-10-06 03:21+0200\n"
 -"POT-Creation-Date: 2008-09-06 06:06+0000\n"
++"POT-Creation-Date: 2008-10-07 21:03+0200\n"
  "PO-Revision-Date: 2008-09-06 10:49+0200\n"
  "Last-Translator: Robert-André Mauchin <zebob.m at pengzone.org>\n"
  "Language-Team: Fedora French <fedora-trans-fr at redhat.com>\n"
diff --cc po/pl.po
index 269a225,4be8e06..5c5b3b4
--- a/po/pl.po
+++ b/po/pl.po
@@@ -5,14 -3,14 +3,14 @@@
  #
  msgid ""
  msgstr ""
- "Project-Id-Version: pulseaudio\n"
+ "Project-Id-Version: pl\n"
  "Report-Msgid-Bugs-To: \n"
- "POT-Creation-Date: 2008-10-06 03:21+0200\n"
- "PO-Revision-Date: 2008-09-05 18:24+0100\n"
- "Last-Translator: Daniel Nylander <po at danielnylander.se>\n"
- "Language-Team: Swedish <tp-sv at listor.tp-sv.se>\n"
 -"POT-Creation-Date: 2008-09-09 21:39+0200\n"
++"POT-Creation-Date: 2008-10-07 21:03+0200\n"
+ "PO-Revision-Date: 2008-09-10 22:41+0200\n"
+ "Last-Translator: Piotr DrÄ…g <piotrdrag at gmail.com>\n"
+ "Language-Team: Polish <pl at li.org>\n"
  "MIME-Version: 1.0\n"
- "Content-Type: text/plain; charset=utf-8\n"
+ "Content-Type: text/plain; charset=UTF-8\n"
  "Content-Transfer-Encoding: 8bit\n"
  
  #: ../src/daemon/ltdl-bind-now.c:177 ../src/daemon/ltdl-bind-now.c:197
@@@ -308,87 -322,84 +322,89 @@@ msgstr "Skompilowano z obsługą Valgri
  
  #: ../src/daemon/main.c:793
  msgid "Compiled with Valgrind support: no"
- msgstr ""
+ msgstr "Skompilowano z obsługą Valgrind: nie"
  
 -#: ../src/daemon/main.c:797
 +#: ../src/daemon/main.c:796
- #, c-format
++#, fuzzy, c-format
 +msgid "Running in valgrind mode: %s"
- msgstr ""
++msgstr "Uruchamianie w trybie systemowym: %s"
 +
 +#: ../src/daemon/main.c:799
  msgid "Optimized build: yes"
- msgstr ""
+ msgstr "Budowanie optymalizowane: tak"
  
 -#: ../src/daemon/main.c:799
 +#: ../src/daemon/main.c:801
  msgid "Optimized build: no"
- msgstr ""
+ msgstr "Budowanie optymalizowane: nie"
  
 -#: ../src/daemon/main.c:803
 +#: ../src/daemon/main.c:805
  msgid "Failed to get machine ID"
- msgstr ""
+ msgstr "Uzyskanie identyfikatora komputera nie powiodło się"
  
 -#: ../src/daemon/main.c:806
 +#: ../src/daemon/main.c:808
  #, c-format
  msgid "Machine ID is %s."
- msgstr ""
+ msgstr "Identyfikator komputera to %s."
  
 -#: ../src/daemon/main.c:811
 +#: ../src/daemon/main.c:813
  #, c-format
  msgid "Using runtime directory %s."
- msgstr ""
+ msgstr "Używanie folderu wykonywania %s."
  
 -#: ../src/daemon/main.c:816
 +#: ../src/daemon/main.c:818
  #, c-format
  msgid "Using state directory %s."
- msgstr ""
+ msgstr "Używanie folderu stanu %s."
  
 -#: ../src/daemon/main.c:819
 +#: ../src/daemon/main.c:821
  #, c-format
  msgid "Running in system mode: %s"
- msgstr ""
+ msgstr "Uruchamianie w trybie systemowym: %s"
  
 -#: ../src/daemon/main.c:834
 +#: ../src/daemon/main.c:836
  msgid "pa_pid_file_create() failed."
- msgstr "pa_pid_file_create() misslyckades."
+ msgstr "pa_pid_file_create() nie powiodło się."
  
 -#: ../src/daemon/main.c:846
 +#: ../src/daemon/main.c:848
  msgid "Fresh high-resolution timers available! Bon appetit!"
- msgstr ""
+ msgstr "Świeże zegary o wysokiej rozdzielczości! Smacznego!"
  
 -#: ../src/daemon/main.c:848
 +#: ../src/daemon/main.c:850
  msgid ""
  "Dude, your kernel stinks! The chef's recommendation today is Linux with high-"
  "resolution timers enabled!"
  msgstr ""
+ "Koleś, twoje jądro śmierdzi! Szef kuchni poleca dzisiaj Linuksa w włączonymi "
+ "zegarami o wysokiej rozdzielczości!"
  
 -#: ../src/daemon/main.c:858
 +#: ../src/daemon/main.c:860
  msgid "pa_core_new() failed."
- msgstr "pa_core_new() misslyckades."
+ msgstr "pa_core_new() nie powiodło się."
  
 -#: ../src/daemon/main.c:919
 +#: ../src/daemon/main.c:921
  msgid "Failed to initialize daemon."
- msgstr ""
+ msgstr "Zainicjowanie demona nie powiodło się."
  
 -#: ../src/daemon/main.c:924
 +#: ../src/daemon/main.c:926
  msgid "Daemon startup without any loaded modules, refusing to work."
- msgstr ""
+ msgstr "Uruchamianie demona bez żadnych wczytanych modułów, odmawianie pracy."
  
 -#: ../src/daemon/main.c:929
 +#: ../src/daemon/main.c:931
  #, c-format
  msgid "Default sink name (%s) does not exist in name register."
- msgstr ""
+ msgstr "Domyślna nazwa odpływu (%s) nie istnieje w rejestrze nazw."
  
 -#: ../src/daemon/main.c:942
 +#: ../src/daemon/main.c:944
  msgid "Daemon startup complete."
- msgstr ""
+ msgstr "Zakończono uruchamianie demona."
  
 -#: ../src/daemon/main.c:948
 +#: ../src/daemon/main.c:950
  msgid "Daemon shutdown initiated."
- msgstr ""
+ msgstr "Zainicjowano wyłączenie demona."
  
 -#: ../src/daemon/main.c:969
 +#: ../src/daemon/main.c:971
  msgid "Daemon terminated."
- msgstr ""
+ msgstr "Demon został zniszczony."
  
  #: ../src/daemon/cmdline.c:117
  #, c-format
@@@ -458,6 -469,79 +474,79 @@@ msgid "
  "\n"
  "  -n                                    Don't load default script file\n"
  msgstr ""
+ "%s [opcje]\n"
+ "\n"
+ "POLECENIA:\n"
+ "  -h, --help                            Wyświetla tę pomoc\n"
+ "      --version                         Wyświetla wersję\n"
+ "      --dump-conf                       Zrzuca domyślną konfigurację\n"
+ "      --dump-modules                    Zrzuca listę dostępnych modułów\n"
+ "      --dump-resample-methods           Zrzuca dostępne metody resamplingu\n"
+ "      --cleanup-shm                     Czyści stare fragmenty pamięci "
+ "współdzielonej\n"
+ "      --start                           Uruchamia demona, jeśli nie jest "
+ "uruchomiony\n"
+ "  -k  --kill                            Niszczy uruchomionego demona\n"
+ "      --check                           Sprawdza, czy demon jest "
+ "uruchomiony\n"
+ "\n"
+ "OPCJE:\n"
+ "      --system[=ZMIENNALOGICZNA]        Uruchamia w trybie systemowym\n"
+ "  -D, --daemonize[=ZMIENNALOGICZNA]     Tworzy demona po uruchomieniu\n"
+ "      --fail[=ZMIENNALOGICZNA]          Wyłącza, kiedy uruchomienie nie "
+ "powiedzie siÄ™\n"
+ "      --high-priority[=ZMIENNALOGICZNA] Próbuje ustawić wysoki poziom nice\n"
+ "                                        (dostępne tylko jako root, na SUID "
+ "lub\n"
+ "                                        z podniesionym RLIMIT_NICE)\n"
+ "      --realtime[=ZMIENNALOGICZNA]      Próbuje ustawić szeregowanie w "
+ "czasie rzeczywistym\n"
+ "                                        (dostępne tylko jako root, na SUID "
+ "lub\n"
+ "                                        z podniesionym RLIMIT_RTPRIO)\n"
+ "      --disallow-module-loading[=ZMIENNALOGICZNA] Nie zezwala użytkownikowi "
+ "modułu na\n"
 -"                                        żądanie wczytania/usunięcia modułu po "
 -"uruchomieniu\n"
++"                                        żądanie wczytania/usunięcia modułu "
++"po uruchomieniu\n"
+ "      --disallow-exit[=ZMIENNALOGICZNA] Nie zezwala użytkownikowi na żądanie "
+ "wyłączenia\n"
+ "      --exit-idle-time=SEKUNDY          Niszczy demona, kiedy jest zajęty i "
+ "upłynął\n"
+ "                                        ten czas\n"
+ "      --module-idle-time=SEKUNDY        Usuwa automatycznie wczytane moduły, "
+ "kiedy jest\n"
+ "                                        zajęty i upłynął ten czas\n"
+ "      --scache-idle-time=SEKUNDY        Usuwa automatycznie wczytane próbki, "
+ "kiedy jest\n"
+ "                                        zajęty i upłynął ten czas\n"
+ "      --log-level[=POZIOM]              Zwiększa lub ustaw poziom "
+ "wyświetlanych informacji\n"
+ "  -v                                    Zwiększa poziom wyświetlanych "
+ "informacji\n"
+ "      --log-target={auto,syslog,stderr} Określa dziennik docelowy\n"
+ "  -p, --dl-search-path=ŚCIEŻKA          Ustawia ścieżkę wyszukiwania dla "
+ "dynamicznie\n"
+ "                                        współdzielonych obiektów (wtyczek)\n"
+ "      --resample-method=METODA          Używa podanej metody resamplingu\n"
+ "                                        (zobacz --dump-resample-methods,\n"
+ "                                        aby poznać możliwe wartości)\n"
+ "      --use-pid-file[=ZMIENNALOGICZNA]  Tworzy plik PID\n"
+ "      --no-cpu-limit[=ZMIENNALOGICZNA]  Nie instaluje ograniczenia zasobów\n"
+ "                                        procesora na obsługujących je "
+ "platformach.\n"
+ "      --disable-shm[=ZMIENNALOGICZNA]   Wyłącza obsługę pamięci "
+ "współdzielonej.\n"
+ "\n"
+ "SKRYPT STARTOWY:\n"
+ "  -L, --load=\"PARAMETRY MODUŁU\"       Wczytuje podany moduł wtyczki z\n"
+ "                                        podanym parametrem\n"
+ "  -F, --file=NAZWAPLIKU                 Wykonuje podany skrypt\n"
+ "  -C                                    Otwiera wiersz poleceń na "
+ "uruchomionym TTY\n"
+ "                                        po uruchomieniu\n"
+ "\n"
+ "  -n                                    Nie wczytuje domyślnego pliku "
+ "skryptu\n"
  
  #: ../src/daemon/cmdline.c:245
  msgid "--daemonize expects boolean argument"
@@@ -552,80 -640,80 +645,80 @@@ msgstr "Wczytanie jednorazowe: %s\n
  #: ../src/daemon/dumpmodules.c:77
  #, c-format
  msgid "Path: %s\n"
- msgstr "Sökväg: %s\n"
+ msgstr "Ścieżka: %s\n"
  
 -#: ../src/daemon/daemon-conf.c:204
 +#: ../src/daemon/daemon-conf.c:205
  #, c-format
  msgid "[%s:%u] Invalid log target '%s'."
- msgstr ""
+ msgstr "[%s:%u] Nieprawidłowy dziennik docelowy \"%s\"."
  
 -#: ../src/daemon/daemon-conf.c:220
 +#: ../src/daemon/daemon-conf.c:221
  #, c-format
  msgid "[%s:%u] Invalid log level '%s'."
- msgstr ""
+ msgstr "[%s:%u] Nieprawidłowy poziom dziennika \"%s\"."
  
 -#: ../src/daemon/daemon-conf.c:236
 +#: ../src/daemon/daemon-conf.c:237
  #, c-format
  msgid "[%s:%u] Invalid resample method '%s'."
- msgstr ""
+ msgstr "[%s:%u] Nieprawidłowa metoda resamplingu \"%s\"."
  
 -#: ../src/daemon/daemon-conf.c:259
 +#: ../src/daemon/daemon-conf.c:260
  #, c-format
  msgid "[%s:%u] Invalid rlimit '%s'."
- msgstr ""
+ msgstr "[%s:%u] Nieprawidłowy rlimit \"%s\"."
  
 -#: ../src/daemon/daemon-conf.c:266
 +#: ../src/daemon/daemon-conf.c:267
  #, c-format
  msgid "[%s:%u] rlimit not supported on this platform."
- msgstr ""
+ msgstr "[%s:%u] rlimit nie jest obsługiwany na tej platformie."
  
 -#: ../src/daemon/daemon-conf.c:282
 +#: ../src/daemon/daemon-conf.c:283
  #, c-format
  msgid "[%s:%u] Invalid sample format '%s'."
- msgstr ""
+ msgstr "[%s:%u] Nieprawidłowy format próbki \"%s\"."
  
 -#: ../src/daemon/daemon-conf.c:300
 +#: ../src/daemon/daemon-conf.c:301
  #, c-format
  msgid "[%s:%u] Invalid sample rate '%s'."
- msgstr ""
+ msgstr "[%s:%u] Nieprawidłowa częstotliwość próbki \"%s\"."
  
 -#: ../src/daemon/daemon-conf.c:318
 +#: ../src/daemon/daemon-conf.c:319
  #, c-format
  msgid "[%s:%u] Invalid sample channels '%s'."
- msgstr ""
+ msgstr "[%s:%u] Nieprawidłowe kanały próbki \"%s\"."
  
 -#: ../src/daemon/daemon-conf.c:336
 +#: ../src/daemon/daemon-conf.c:337
  #, c-format
  msgid "[%s:%u] Invalid number of fragments '%s'."
- msgstr ""
+ msgstr "[%s:%u] Nieprawidłowa liczba fragmentów \"%s\"."
  
 -#: ../src/daemon/daemon-conf.c:354
 +#: ../src/daemon/daemon-conf.c:355
  #, c-format
  msgid "[%s:%u] Invalid fragment size '%s'."
- msgstr ""
+ msgstr "[%s:%u] Nieprawidłowy rozmiar fragmentu \"%s\"."
  
 -#: ../src/daemon/daemon-conf.c:372
 +#: ../src/daemon/daemon-conf.c:373
  #, c-format
  msgid "[%s:%u] Invalid nice level '%s'."
- msgstr ""
+ msgstr "[%s:%u] Nieprawidłowy poziom nice \"%s\"."
  
 -#: ../src/daemon/daemon-conf.c:567
 +#: ../src/daemon/daemon-conf.c:570
  #, c-format
  msgid "Failed to open configuration file: %s"
- msgstr "Misslyckades med att öppna konfigurationsfil: %s"
+ msgstr "Otwarcie pliku konfiguracji nie powiodło się: %s"
  
 -#: ../src/daemon/daemon-conf.c:641
 +#: ../src/daemon/daemon-conf.c:644
  #, c-format
  msgid "### Read from configuration file: %s ###\n"
- msgstr ""
+ msgstr "### Odczytano z pliku konfiguracji: %s ###\n"
  
 -#: ../src/daemon/caps.c:62
 +#: ../src/daemon/caps.c:63
  msgid "Dropping root priviliges."
- msgstr "Släpper root-behörighet."
+ msgstr "Porzucanie uprawnień roota."
  
 -#: ../src/daemon/caps.c:102
 +#: ../src/daemon/caps.c:103
  msgid "Limited capabilities successfully to CAP_SYS_NICE."
- msgstr ""
+ msgstr "Pomyślnie ograniczono możliwości do CAP_SYS_NICE."
  
  #: ../src/pulse/channelmap.c:102
  msgid "Mono"
@@@ -829,14 -917,8 +922,14 @@@ msgstr "Górny tylny lewy
  
  #: ../src/pulse/channelmap.c:161
  msgid "Top Rear Right"
- msgstr ""
+ msgstr "Górny tylny prawy"
  
 +#: ../src/pulse/channelmap.c:472 ../src/pulse/sample.c:144
 +#: ../src/pulse/volume.c:163 ../src/pulse/volume.c:194
 +#, fuzzy
 +msgid "(invalid)"
- msgstr "Ogiltig"
++msgstr "Nieprawidłowe"
 +
  #: ../src/pulse/error.c:43
  msgid "OK"
  msgstr "OK"
@@@ -923,20 -1005,24 +1016,20 @@@ msgstr "Nieznany kod błędu
  
  #: ../src/pulse/error.c:64
  msgid "No such extension"
- msgstr ""
+ msgstr "Nie ma takiego rozszerzenia"
  
 -#: ../src/pulse/sample.c:134
 -msgid "Invalid"
 -msgstr "Nieprawidłowe"
 -
  #: ../src/pulse/client-conf-x11.c:55 ../src/utils/pax11publish.c:100
  msgid "XOpenDisplay() failed"
- msgstr "XOpenDisplay() misslyckades"
+ msgstr "XOpenDisplay() nie powiodło się"
  
  #: ../src/pulse/client-conf-x11.c:78
  msgid "Failed to parse cookie data"
- msgstr ""
+ msgstr "Analiza danych ciasteczka nie powiodło się"
  
 -#: ../src/pulse/client-conf.c:117
 +#: ../src/pulse/client-conf.c:120
  #, c-format
  msgid "Failed to open configuration file '%s': %s"
- msgstr "Misslyckades med att öppna konfigurationsfilen \"%s\": %s"
+ msgstr "Otwarcie pliku konfiguracji \"%s\" nie powiodło się: %s"
  
  #: ../src/pulse/context.c:516
  msgid "No cookie loaded. Attempting to connect without."
@@@ -1525,7 -1748,7 +1755,8 @@@ msgstr "
  #: ../src/utils/pactl.c:481
  #, c-format
  msgid "Failed to get autoload information: %s\n"
 -msgstr "Uzyskanie informacji o automatycznym wczytywaniu nie powiodło się: %s\n"
 +msgstr ""
++"Uzyskanie informacji o automatycznym wczytywaniu nie powiodło się: %s\n"
  
  #: ../src/utils/pactl.c:497
  #, c-format
diff --cc po/pt_BR.po
index 9643d04,8bf905b..94494f7
--- a/po/pt_BR.po
+++ b/po/pt_BR.po
@@@ -7,19 -7,21 +7,20 @@@ msgid "
  msgstr ""
  "Project-Id-Version: pulseaudio\n"
  "Report-Msgid-Bugs-To: \n"
- "POT-Creation-Date: 2008-10-06 03:21+0200\n"
- "PO-Revision-Date: 2008-08-31 12:22+0100\n"
- "Last-Translator: Fabian Affolter <fab at fedoraproject.org>\n"
- "Language-Team: German <fedora-trans-de at redhat.com>\n"
 -"POT-Creation-Date: 2008-09-09 03:32+0000\n"
++"POT-Creation-Date: 2008-10-07 21:03+0200\n"
+ "PO-Revision-Date: 2008-09-21 17:05-0300\n"
+ "Last-Translator: Herli Menezes <herlimenezes at gmail.com>\n"
+ "Language-Team: Brazilian-Portuguese <fedora-trans-pt_br at redhat.com>\n"
  "MIME-Version: 1.0\n"
  "Content-Type: text/plain; charset=utf-8\n"
  "Content-Transfer-Encoding: 8bit\n"
  "Plural-Forms: nplurals=2; plural=(n != 1);\n"
- "X-Poedit-Language: German\n"
+ "X-Poedit-Language: Brazilian Portuguese\n"
+ "X-Poedit-Country: Brazil\n"
  
 -#: ../src/daemon/ltdl-bind-now.c:177
 -#: ../src/daemon/ltdl-bind-now.c:197
 +#: ../src/daemon/ltdl-bind-now.c:177 ../src/daemon/ltdl-bind-now.c:197
  msgid "Failed to add bind-now-loader."
- msgstr "Hinzufügen von bind-now-loader fehlgeschlagen."
+ msgstr "Falha em adicionar o bind-now-loader."
  
  #: ../src/daemon/ltdl-bind-now.c:184
  msgid "Failed to find original dlopen loader."
@@@ -111,12 -113,13 +112,12 @@@ msgstr "O GID do usuário'%s' e do grup
  #: ../src/daemon/main.c:198
  #, c-format
  msgid "Home directory of user '%s' is not '%s', ignoring."
- msgstr "Benutzerverzeichnis von Benutzer '%s' ist nicht '%s', ignoriere."
+ msgstr "O diretório Home do usuário '%s' não é '%s', ignorando."
  
 -#: ../src/daemon/main.c:201
 -#: ../src/daemon/main.c:206
 +#: ../src/daemon/main.c:201 ../src/daemon/main.c:206
  #, c-format
  msgid "Failed to create '%s': %s"
- msgstr "Erzeugen von '%s' fehlgeschlagen: %s"
+ msgstr "Falha em criar '%s': %s"
  
  #: ../src/daemon/main.c:213
  #, c-format
@@@ -178,15 -181,27 +179,21 @@@ msgstr "O PolicyKit recusa a aquisiçã
  
  #: ../src/daemon/main.c:479
  msgid ""
 -"Called SUID root and real-time/high-priority scheduling was requested in the configuration. However, we lack the necessary priviliges:\n"
 +"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 '"
  msgstr ""
 -"A chamada de SUID root e tempo real/alta prioridade no escalonamento foi requisitada pela configuração. Todavia, falta-nos os privilégios necessários:\n"
++"A chamada de SUID root e tempo real/alta prioridade no escalonamento foi "
++"requisitada pela configuração. Todavia, falta-nos os privilégios "
++"necessários:\n"
+ "Não estamos no grupo'"
  
 -#: ../src/daemon/main.c:480
 +#: ../src/daemon/main.c:497
  msgid ""
 -"' 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 '"
 +"High-priority scheduling enabled in configuration but not allowed by policy."
  msgstr ""
 -"' e o PolicyKit recusa-nos a garantia de privilégios. Retirando o SUID outra vez.\n"
 -" Para habilitar o escalonamento em tempo real, por favo, adquira os privilégios adequados pelo PolicyKit, ou torne-se membro do'"
 -
 -#: ../src/daemon/main.c:481
 -msgid "', or increase the RLIMIT_NICE/RLIMIT_RTPRIO resource limits for this user."
 -msgstr "', ou eleve o RLIMIT_NICE/RLIMIT_RTPRIO dos limites do recurso para este usuário."
 -
 -#: ../src/daemon/main.c:497
 -msgid "High-priority scheduling enabled in configuration but not allowed by policy."
 -msgstr "O escalonamento de alta prioridade foi habilitado para esta configuração, mas não é permitida pela política."
++"O escalonamento de alta prioridade foi habilitado para esta configuração, "
++"mas não é permitida pela política."
  
  #: ../src/daemon/main.c:522
  msgid "Successfully increased RLIMIT_RTPRIO"
@@@ -199,12 -214,11 +206,14 @@@ msgstr "RLIMIT_RTPRIO falhou: %s
  
  #: ../src/daemon/main.c:532
  msgid "Giving up CAP_NICE"
- msgstr ""
+ msgstr "Abandonando CAP_NICE"
  
  #: ../src/daemon/main.c:539
 -msgid "Real-time scheduling enabled in configuration but not allowed by policy."
 -msgstr "O escalonamento de tempo real foi habilitado pela configuração, mas não é permitido pela política."
 +msgid ""
 +"Real-time scheduling enabled in configuration but not allowed by policy."
 +msgstr ""
++"O escalonamento de tempo real foi habilitado pela configuração, mas não é "
++"permitido pela política."
  
  #: ../src/daemon/main.c:597
  msgid "Daemon not running"
@@@ -218,13 -232,11 +227,15 @@@ msgstr "Daemon executando como PID %u
  #: ../src/daemon/main.c:609
  #, c-format
  msgid "Failed to kill daemon: %s"
- msgstr ""
+ msgstr "Falha em encerrar o daemon: %s"
  
  #: ../src/daemon/main.c:627
 -msgid "This program is not intended to be run as root (unless --system is specified)."
 -msgstr "Este programa não é para ser executado como root (a não ser que --system seja especificado)."
 +msgid ""
 +"This program is not intended to be run as root (unless --system is "
 +"specified)."
 +msgstr ""
++"Este programa não é para ser executado como root (a não ser que --system "
++"seja especificado)."
  
  #: ../src/daemon/main.c:629
  msgid "Root priviliges required."
@@@ -240,7 -252,7 +251,8 @@@ msgstr "Executando em no modo system, m
  
  #: ../src/daemon/main.c:642
  msgid "Running in system mode, but --disallow-module-loading not set!"
 -msgstr "Executando no modo system, mas --disallow-module-loading não foi configurado!"
 +msgstr ""
++"Executando no modo system, mas --disallow-module-loading não foi configurado!"
  
  #: ../src/daemon/main.c:645
  msgid "Running in system mode, forcibly disabling SHM mode!"
@@@ -248,7 -260,7 +260,8 @@@ msgstr "Executando no modo system, desa
  
  #: ../src/daemon/main.c:650
  msgid "Running in system mode, forcibly disabling exit idle time!"
 -msgstr "Executando no modo system, desabilitando forçadamente o exit idle time!"
 +msgstr ""
++"Executando no modo system, desabilitando forçadamente o exit idle time!"
  
  #: ../src/daemon/main.c:677
  msgid "Failed to acquire stdio."
@@@ -308,87 -320,80 +321,90 @@@ msgstr "Compilado com suporte do Valgri
  
  #: ../src/daemon/main.c:793
  msgid "Compiled with Valgrind support: no"
- msgstr ""
+ msgstr "Compilado com suporte do Valgrind: não"
  
 -#: ../src/daemon/main.c:797
 +#: ../src/daemon/main.c:796
- #, c-format
++#, fuzzy, c-format
 +msgid "Running in valgrind mode: %s"
- msgstr ""
++msgstr "Executando em modo do sistema: %s"
 +
 +#: ../src/daemon/main.c:799
  msgid "Optimized build: yes"
- msgstr ""
+ msgstr "Build otimizado: sim"
  
 -#: ../src/daemon/main.c:799
 +#: ../src/daemon/main.c:801
  msgid "Optimized build: no"
- msgstr ""
+ msgstr "Build otimizado: não"
  
 -#: ../src/daemon/main.c:803
 +#: ../src/daemon/main.c:805
  msgid "Failed to get machine ID"
- msgstr ""
+ msgstr "Falha em obter o ID da máquina"
  
 -#: ../src/daemon/main.c:806
 +#: ../src/daemon/main.c:808
  #, c-format
  msgid "Machine ID is %s."
- msgstr "System- ID ist %s."
+ msgstr "A ID da máquina é %s."
  
 -#: ../src/daemon/main.c:811
 +#: ../src/daemon/main.c:813
  #, c-format
  msgid "Using runtime directory %s."
- msgstr ""
+ msgstr "Usando o diretório de runtime %s."
  
 -#: ../src/daemon/main.c:816
 +#: ../src/daemon/main.c:818
  #, c-format
  msgid "Using state directory %s."
- msgstr ""
+ msgstr "Usando o diretório de estado %s."
  
 -#: ../src/daemon/main.c:819
 +#: ../src/daemon/main.c:821
  #, c-format
  msgid "Running in system mode: %s"
- msgstr ""
+ msgstr "Executando em modo do sistema: %s"
  
 -#: ../src/daemon/main.c:834
 +#: ../src/daemon/main.c:836
  msgid "pa_pid_file_create() failed."
- msgstr "pa_pid_file_create() fehlgeschlagen."
+ msgstr "pa_pid_file_create() falhou."
  
 -#: ../src/daemon/main.c:846
 +#: ../src/daemon/main.c:848
  msgid "Fresh high-resolution timers available! Bon appetit!"
- msgstr ""
+ msgstr "Timers de alta resolução frequinhos disponíveis! Bon appetit!"
  
 -#: ../src/daemon/main.c:848
 -msgid "Dude, your kernel stinks! The chef's recommendation today is Linux with high-resolution timers enabled!"
 -msgstr "Cara, teu kernel fede! A recomendação do chef hoje é Linux com timers de alta resolução habilitados!"
 +#: ../src/daemon/main.c:850
 +msgid ""
 +"Dude, your kernel stinks! The chef's recommendation today is Linux with high-"
 +"resolution timers enabled!"
 +msgstr ""
++"Cara, teu kernel fede! A recomendação do chef hoje é Linux com timers de "
++"alta resolução habilitados!"
  
 -#: ../src/daemon/main.c:858
 +#: ../src/daemon/main.c:860
  msgid "pa_core_new() failed."
- msgstr "pa_core_new() fehlgeschlagen."
+ msgstr "pa_core_new() falhou."
  
 -#: ../src/daemon/main.c:919
 +#: ../src/daemon/main.c:921
  msgid "Failed to initialize daemon."
- msgstr ""
+ msgstr "Falha em iniciar o daemon."
  
 -#: ../src/daemon/main.c:924
 +#: ../src/daemon/main.c:926
  msgid "Daemon startup without any loaded modules, refusing to work."
 -msgstr "O Daemon iniciou sem qualquer módulo carregado, recusando-se a trabalhar."
 +msgstr ""
++"O Daemon iniciou sem qualquer módulo carregado, recusando-se a trabalhar."
  
 -#: ../src/daemon/main.c:929
 +#: ../src/daemon/main.c:931
  #, c-format
  msgid "Default sink name (%s) does not exist in name register."
- msgstr ""
+ msgstr "O nome padrão do destino (%s) não existe no registro de nomes."
  
 -#: ../src/daemon/main.c:942
 +#: ../src/daemon/main.c:944
  msgid "Daemon startup complete."
- msgstr "Start des Dämons abgeschlossen."
+ msgstr "A partida dos Daemon está completa."
  
 -#: ../src/daemon/main.c:948
 +#: ../src/daemon/main.c:950
  msgid "Daemon shutdown initiated."
- msgstr ""
+ msgstr "O encerramento do Daemon foi iniciado."
  
 -#: ../src/daemon/main.c:969
 +#: ../src/daemon/main.c:971
  msgid "Daemon terminated."
- msgstr "Dämon beendet."
+ msgstr "Daemon terminado."
  
  #: ../src/daemon/cmdline.c:117
  #, c-format
@@@ -458,6 -452,59 +474,80 @@@ msgid "
  "\n"
  "  -n                                    Don't load default script file\n"
  msgstr ""
+ "%s [opções]\n"
+ "\n"
+ "COMANDOS:\n"
+ "  -h, --help                            Mostra esta ajuda\n"
+ "      --version                        Mostra a versão\n"
+ "      --dump-conf                       Descarrega a configuração padrão\n"
 -"      --dump-modules                   Descarrega a lista de módulos disponíveis\n"
 -"      --dump-resample-methods           Descarrega os métodos de reamostragem (resample)\n"
 -"      --cleanup-shm                     Limpa os segmentos de memória compartilhados\n"
 -"      --start                           Inicia o daemon se ele não estiver em execução\n"
++"      --dump-modules                   Descarrega a lista de módulos "
++"disponíveis\n"
++"      --dump-resample-methods           Descarrega os métodos de "
++"reamostragem (resample)\n"
++"      --cleanup-shm                     Limpa os segmentos de memória "
++"compartilhados\n"
++"      --start                           Inicia o daemon se ele não estiver "
++"em execução\n"
+ "  -k  --kill                            Encerra um daemon em execução\n"
+ "      --check                           Verifica um daemon em execução\n"
+ "\n"
+ "OPÇÕES:\n"
 -"      --system[=BOOL]                   Executa como uma instância do sistema em escala ampla \n"
 -"  -D, --daemonize[=BOOL]                Torna um daemom (daemonize) depois da partida\n"
++"      --system[=BOOL]                   Executa como uma instância do "
++"sistema em escala ampla \n"
++"  -D, --daemonize[=BOOL]                Torna um daemom (daemonize) depois "
++"da partida\n"
+ "      --fail[=BOOL]                     Sai quando a partida falha\n"
+ "      --high-priority[=BOOL]            Tenta definir um nível alto de nice\n"
+ "                                        (disponível apenas, quando SUID ou\n"
+ "                                        com RLIMIT_NICE) elevado\n"
 -"      --realtime[=BOOL]                 Tenta habilidar o escalonamento em tempo real\n"
 -"                                        (disponível apenas como root, quando SUID ou\n"
++"      --realtime[=BOOL]                 Tenta habilidar o escalonamento em "
++"tempo real\n"
++"                                        (disponível apenas como root, quando "
++"SUID ou\n"
+ "                                        com  RLIMIT_RTPRIO) elevado\n"
 -"      --disallow-module-loading[=BOOL]  Não permite carga/descarga de módulo requerido pelo usuário\n"
++"      --disallow-module-loading[=BOOL]  Não permite carga/descarga de módulo "
++"requerido pelo usuário\n"
+ "                                        depois da partida\n"
 -"      --disallow-exit[=BOOL]            Não permite saída requisitada pelo usuário\n"
 -"      --exit-idle-time=SECS             Termina um daemon quando ocioso e este\n"
++"      --disallow-exit[=BOOL]            Não permite saída requisitada pelo "
++"usuário\n"
++"      --exit-idle-time=SECS             Termina um daemon quando ocioso e "
++"este\n"
+ "                                        tempo foi decorrido\n"
 -"      --module-idle-time=SECS           Descarrega os modulos autocarregáveis quando ociosos e\n"
++"      --module-idle-time=SECS           Descarrega os modulos "
++"autocarregáveis quando ociosos e\n"
+ "                                        tempo foi decorrido\n"
 -"      --scache-idle-time=SECS           Descarrega amostras quando ociosas e\n"
++"      --scache-idle-time=SECS           Descarrega amostras quando ociosas "
++"e\n"
+ "                                        este tempo tenha passado\n"
 -"      --log-level[=LEVEL]               Aumenta ou define o grau de verbosidade\n"
++"      --log-level[=LEVEL]               Aumenta ou define o grau de "
++"verbosidade\n"
+ "  -v                                    Aumenta o nível de verbosidade\n"
+ "      --log-target={auto,syslog,stderr} Especifica o alvo do log\n"
 -"  -p, --dl-search-path=PATH             Define o caminho de busca (search paht)para objetos (plugins)\n"
++"  -p, --dl-search-path=PATH             Define o caminho de busca (search "
++"paht)para objetos (plugins)\n"
+ "                                            dinamicamente commpartilhados\n"
 -"      --resample-method=METHOD         Usa o método de reamostragem especificado\n"
++"      --resample-method=METHOD         Usa o método de reamostragem "
++"especificado\n"
+ "                                        (Veja --dump-resample-methods para\n"
+ "                                        valores possíveis)\n"
+ "      --use-pid-file[=BOOL]             Cria um arquivo PID file\n"
 -"      --no-cpu-limit[=BOOL]            Não instala um limitador de carga de CPU load em\n"
++"      --no-cpu-limit[=BOOL]            Não instala um limitador de carga de "
++"CPU load em\n"
+ "                                        plataformas que o suportem.\n"
 -"      --disable-shm[=BOOL]              Desabilita o suporte a memória compartilhada.\n"
++"      --disable-shm[=BOOL]              Desabilita o suporte a memória "
++"compartilhada.\n"
+ "\n"
+ "STARTUP SCRIPT:\n"
 -"  -L, --load=\"MODULE ARGUMENTS\"         Carrega um plugin especificado com\n"
++"  -L, --load=\"MODULE ARGUMENTS\"         Carrega um plugin especificado "
++"com\n"
+ "                                        o argumento especificado\n"
+ "  -F, --file=FILENAME                  Executa o script especificado\n"
 -"  -C                                    Abre uma linha de comando no TTY em execução\n"
++"  -C                                    Abre uma linha de comando no TTY em "
++"execução\n"
+ "                                       depois da partida\n"
+ "\n"
 -"  -n                                    Não carrega o arquivo de script padrão\n"
++"  -n                                    Não carrega o arquivo de script "
++"padrão\n"
  
  #: ../src/daemon/cmdline.c:245
  msgid "--daemonize expects boolean argument"
@@@ -465,13 -512,11 +555,15 @@@ msgstr "--daemonize espera argumento bo
  
  #: ../src/daemon/cmdline.c:252
  msgid "--fail expects boolean argument"
- msgstr ""
+ msgstr "--fail espera argumento booleano"
  
  #: ../src/daemon/cmdline.c:262
 -msgid "--log-level expects log level argument (either numeric in range 0..4 or one of debug, info, notice, warn, error)."
 -msgstr "--log-level espera um argumento em nível de log  (seja numérico na faixa de 0..4 seja algum entre debug, info, notice, warn, error)."
 +msgid ""
 +"--log-level expects log level argument (either numeric in range 0..4 or one "
 +"of debug, info, notice, warn, error)."
 +msgstr ""
++"--log-level espera um argumento em nível de log  (seja numérico na faixa de "
++"0..4 seja algum entre debug, info, notice, warn, error)."
  
  #: ../src/daemon/cmdline.c:274
  msgid "--high-priority expects boolean argument"
@@@ -552,80 -597,80 +644,80 @@@ msgstr "Carrega uma vez: %s\n
  #: ../src/daemon/dumpmodules.c:77
  #, c-format
  msgid "Path: %s\n"
- msgstr "Pfad: %s\n"
+ msgstr "Caminho: %s\n"
  
 -#: ../src/daemon/daemon-conf.c:204
 +#: ../src/daemon/daemon-conf.c:205
  #, c-format
  msgid "[%s:%u] Invalid log target '%s'."
- msgstr ""
+ msgstr "[%s:%u] Alvo do log inválido '%s'."
  
 -#: ../src/daemon/daemon-conf.c:220
 +#: ../src/daemon/daemon-conf.c:221
  #, c-format
  msgid "[%s:%u] Invalid log level '%s'."
- msgstr ""
+ msgstr "[%s:%u] Nível de log inválido '%s'."
  
 -#: ../src/daemon/daemon-conf.c:236
 +#: ../src/daemon/daemon-conf.c:237
  #, c-format
  msgid "[%s:%u] Invalid resample method '%s'."
- msgstr ""
+ msgstr "[%s:%u] Método de reamostragem inválido '%s'."
  
 -#: ../src/daemon/daemon-conf.c:259
 +#: ../src/daemon/daemon-conf.c:260
  #, c-format
  msgid "[%s:%u] Invalid rlimit '%s'."
- msgstr ""
+ msgstr "[%s:%u] rlimit inválido '%s'."
  
 -#: ../src/daemon/daemon-conf.c:266
 +#: ../src/daemon/daemon-conf.c:267
  #, c-format
  msgid "[%s:%u] rlimit not supported on this platform."
- msgstr ""
+ msgstr "[%s:%u] rlimit não tem suporte nessa plataforma."
  
 -#: ../src/daemon/daemon-conf.c:282
 +#: ../src/daemon/daemon-conf.c:283
  #, c-format
  msgid "[%s:%u] Invalid sample format '%s'."
- msgstr ""
+ msgstr "[%s:%u] Formato de amostragem inválido '%s'."
  
 -#: ../src/daemon/daemon-conf.c:300
 +#: ../src/daemon/daemon-conf.c:301
  #, c-format
  msgid "[%s:%u] Invalid sample rate '%s'."
- msgstr ""
+ msgstr "[%s:%u] Taxa de amostragem inválida '%s'."
  
 -#: ../src/daemon/daemon-conf.c:318
 +#: ../src/daemon/daemon-conf.c:319
  #, c-format
  msgid "[%s:%u] Invalid sample channels '%s'."
- msgstr ""
+ msgstr "[%s:%u] Canais de amostragem inválidos'%s'."
  
 -#: ../src/daemon/daemon-conf.c:336
 +#: ../src/daemon/daemon-conf.c:337
  #, c-format
  msgid "[%s:%u] Invalid number of fragments '%s'."
- msgstr ""
+ msgstr "[%s:%u] Números de fragmentos inválidos '%s'."
  
 -#: ../src/daemon/daemon-conf.c:354
 +#: ../src/daemon/daemon-conf.c:355
  #, c-format
  msgid "[%s:%u] Invalid fragment size '%s'."
- msgstr ""
+ msgstr "[%s:%u] Tamanho de fragmentos inválido '%s'."
  
 -#: ../src/daemon/daemon-conf.c:372
 +#: ../src/daemon/daemon-conf.c:373
  #, c-format
  msgid "[%s:%u] Invalid nice level '%s'."
- msgstr ""
+ msgstr "[%s:%u] Número de nice inválido'%s'."
  
 -#: ../src/daemon/daemon-conf.c:567
 +#: ../src/daemon/daemon-conf.c:570
  #, c-format
  msgid "Failed to open configuration file: %s"
- msgstr ""
+ msgstr "Falha em abrir o arquivo de configuração: %s"
  
 -#: ../src/daemon/daemon-conf.c:641
 +#: ../src/daemon/daemon-conf.c:644
  #, c-format
  msgid "### Read from configuration file: %s ###\n"
- msgstr ""
+ msgstr "### Lido do arquivo de configuração: %s ###\n"
  
 -#: ../src/daemon/caps.c:62
 +#: ../src/daemon/caps.c:63
  msgid "Dropping root priviliges."
- msgstr "Verlasse Root-Berechtigungen."
+ msgstr "Descartando os privilégios de root."
  
 -#: ../src/daemon/caps.c:102
 +#: ../src/daemon/caps.c:103
  msgid "Limited capabilities successfully to CAP_SYS_NICE."
- msgstr ""
+ msgstr "As capacidades foram limitadas com sucesso para CAP_SYS_NICE."
  
  #: ../src/pulse/channelmap.c:102
  msgid "Mono"
@@@ -829,14 -874,8 +921,14 @@@ msgstr "Posterior Superior Esquerdo
  
  #: ../src/pulse/channelmap.c:161
  msgid "Top Rear Right"
- msgstr "Oben Hinten Rechts"
+ msgstr "Posterior Superior Direito"
  
 +#: ../src/pulse/channelmap.c:472 ../src/pulse/sample.c:144
 +#: ../src/pulse/volume.c:163 ../src/pulse/volume.c:194
 +#, fuzzy
 +msgid "(invalid)"
- msgstr "Ungültig"
++msgstr "Inválido"
 +
  #: ../src/pulse/error.c:43
  msgid "OK"
  msgstr "OK"
@@@ -923,20 -962,25 +1015,20 @@@ msgstr "Código de erro desconhecido
  
  #: ../src/pulse/error.c:64
  msgid "No such extension"
- msgstr "Erweiterung nicht vorhanden"
+ msgstr "Não existe tal extensão"
  
 -#: ../src/pulse/sample.c:134
 -msgid "Invalid"
 -msgstr "Inválido"
 -
 -#: ../src/pulse/client-conf-x11.c:55
 -#: ../src/utils/pax11publish.c:100
 +#: ../src/pulse/client-conf-x11.c:55 ../src/utils/pax11publish.c:100
  msgid "XOpenDisplay() failed"
- msgstr "XOpenDisplay() fehlgeschlagen"
+ msgstr "XOpenDisplay() falhou"
  
  #: ../src/pulse/client-conf-x11.c:78
  msgid "Failed to parse cookie data"
- msgstr ""
+ msgstr "Falhou ao analisar os dados do cookie"
  
 -#: ../src/pulse/client-conf.c:117
 +#: ../src/pulse/client-conf.c:120
  #, c-format
  msgid "Failed to open configuration file '%s': %s"
- msgstr ""
+ msgstr "Falha em abrir o arquivo de configuração '%s': %s"
  
  #: ../src/pulse/context.c:516
  msgid "No cookie loaded. Attempting to connect without."
@@@ -1064,28 -1108,33 +1156,28 @@@ msgstr "pa_stream_connect_playback() fa
  #: ../src/utils/pacat.c:293
  #, c-format
  msgid "pa_stream_connect_record() failed: %s\n"
- msgstr "pa_stream_connect_record() fehlgeschlagen: %s\n"
+ msgstr "pa_stream_connect_record() falhou: %s\n"
  
 -#: ../src/utils/pacat.c:307
 -#: ../src/utils/pasuspender.c:159
 -#: ../src/utils/pactl.c:666
 -#: ../src/utils/paplay.c:183
 +#: ../src/utils/pacat.c:307 ../src/utils/pasuspender.c:159
 +#: ../src/utils/pactl.c:666 ../src/utils/paplay.c:183
  #, c-format
  msgid "Connection failure: %s\n"
- msgstr ""
+ msgstr "Falha na conexão: %s\n"
  
 -#: ../src/utils/pacat.c:328
 -#: ../src/utils/paplay.c:75
 +#: ../src/utils/pacat.c:328 ../src/utils/paplay.c:75
  #, c-format
  msgid "Failed to drain stream: %s\n"
- msgstr ""
+ msgstr "Falha em drenar o fluxo: %s\n"
  
 -#: ../src/utils/pacat.c:333
 -#: ../src/utils/paplay.c:80
 +#: ../src/utils/pacat.c:333 ../src/utils/paplay.c:80
  #, c-format
  msgid "Playback stream drained.\n"
- msgstr ""
+ msgstr "Drenado o fluxo de playback.\n"
  
 -#: ../src/utils/pacat.c:343
 -#: ../src/utils/paplay.c:92
 +#: ../src/utils/pacat.c:343 ../src/utils/paplay.c:92
  #, c-format
  msgid "Draining connection to server.\n"
- msgstr ""
+ msgstr "Drenando a conexão par ao servidor.\n"
  
  #: ../src/utils/pacat.c:369
  #, c-format
@@@ -1140,45 -1189,58 +1232,89 @@@ msgid "
  "\n"
  "  -v, --verbose                         Enable verbose operations\n"
  "\n"
 -"  -s, --server=SERVER                   The name of the server to connect to\n"
 -"  -d, --device=DEVICE                   The name of the sink/source to connect to\n"
 -"  -n, --client-name=NAME                How to call this client on the server\n"
 -"      --stream-name=NAME                How to call this stream on the server\n"
 -"      --volume=VOLUME                   Specify the initial (linear) volume in range 0...65536\n"
 -"      --rate=SAMPLERATE                 The sample rate in Hz (defaults to 44100)\n"
 -"      --format=SAMPLEFORMAT             The sample type, one of s16le, s16be, u8, float32le,\n"
 -"                                        float32be, ulaw, alaw, s32le, s32be (defaults to s16ne)\n"
 -"      --channels=CHANNELS               The number of channels, 1 for mono, 2 for stereo\n"
 +"  -s, --server=SERVER                   The name of the server to connect "
 +"to\n"
 +"  -d, --device=DEVICE                   The name of the sink/source to "
 +"connect to\n"
 +"  -n, --client-name=NAME                How to call this client on the "
 +"server\n"
 +"      --stream-name=NAME                How to call this stream on the "
 +"server\n"
 +"      --volume=VOLUME                   Specify the initial (linear) volume "
 +"in range 0...65536\n"
 +"      --rate=SAMPLERATE                 The sample rate in Hz (defaults to "
 +"44100)\n"
 +"      --format=SAMPLEFORMAT             The sample type, one of s16le, "
 +"s16be, u8, float32le,\n"
 +"                                        float32be, ulaw, alaw, s32le, s32be "
 +"(defaults to s16ne)\n"
 +"      --channels=CHANNELS               The number of channels, 1 for mono, "
 +"2 for stereo\n"
  "                                        (defaults to 2)\n"
 -"      --channel-map=CHANNELMAP          Channel map to use instead of the default\n"
 -"      --fix-format                      Take the sample format from the sink the stream is\n"
 +"      --channel-map=CHANNELMAP          Channel map to use instead of the "
 +"default\n"
 +"      --fix-format                      Take the sample format from the sink "
 +"the stream is\n"
  "                                        being connected to.\n"
 -"      --fix-rate                        Take the sampling rate from the sink the stream is\n"
 +"      --fix-rate                        Take the sampling rate from the sink "
 +"the stream is\n"
  "                                        being connected to.\n"
 -"      --fix-channels                    Take the number of channels and the channel map\n"
 -"                                        from the sink the stream is being connected to.\n"
 +"      --fix-channels                    Take the number of channels and the "
 +"channel map\n"
 +"                                        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"
 -"      --process-time=BYTES              Request the specified process time per request in bytes.\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"
  msgstr ""
+ "%s [opções]\n"
+ "\n"
+ "  -h, --help                            Mostra essa ajuda\n"
+ "      --version                         Mostra a versão\n"
+ "\n"
+ "  -r, --record                          Cria uma conexão para gravação\n"
+ "  -p, --playback                        Cria uma conexão para playback\n"
+ "\n"
+ "  -v, --verbose                         Habilita operações no modo verboso\n"
+ "\n"
+ "  -s, --server=SERVER                   Nome do servidor a ser conectado\n"
+ "  -d, --device=DEVICE                   O nome do destino/fonte a conectar\n"
+ "  -n, --client-name=NAME                Como chamar o cliente no servidor\n"
 -"      --stream-name=NAME               Como chamar este fluxo no servidorn      --volume=VOLUME                   Especifica a faixa (linear) inicial de volume no intervalo 0...65536\n"
 -"      --rate=SAMPLERATE                 Taxa de amostragem em Hz (o padrão é 44100)\n"
 -"      --format=SAMPLEFORMAT             Tipo de amostragem, um de s16le, s16be, u8, float32le,\n"
 -"                                        float32be, ulaw, alaw, s32le, s32be (o padrão é s16ne)\n"
 -"      --channels=CHANNELS               O número de canais, 1 para mono, 2 para estéreo\n"
++"      --stream-name=NAME               Como chamar este fluxo no "
++"servidorn      --volume=VOLUME                   Especifica a faixa (linear) "
++"inicial de volume no intervalo 0...65536\n"
++"      --rate=SAMPLERATE                 Taxa de amostragem em Hz (o padrão é "
++"44100)\n"
++"      --format=SAMPLEFORMAT             Tipo de amostragem, um de s16le, "
++"s16be, u8, float32le,\n"
++"                                        float32be, ulaw, alaw, s32le, s32be "
++"(o padrão é s16ne)\n"
++"      --channels=CHANNELS               O número de canais, 1 para mono, 2 "
++"para estéreo\n"
+ "                                        (o padrão é 2)\n"
 -"      --channel-map=CHANNELMAP          Mapeamento de canais a ser usando em lugar do padrão\n"
 -"      --fix-format                      Obtém o formato da amostragem do destino onde o fluxo\n"
++"      --channel-map=CHANNELMAP          Mapeamento de canais a ser usando em "
++"lugar do padrão\n"
++"      --fix-format                      Obtém o formato da amostragem do "
++"destino onde o fluxo\n"
+ " está sendo conectado.\n"
 -"            --fix-rate                        Obtém o taxa de amostragem do destino onde o fluxo está\n"
++"            --fix-rate                        Obtém o taxa de amostragem do "
++"destino onde o fluxo está\n"
+ "                                        sendo conectado.\n"
 -"      --fix-channels                    Obtém o número de canais e o mapa de canais\n"
 -"                                      do destino onde o fluxo está sendo conectado.\n"
++"      --fix-channels                    Obtém o número de canais e o mapa de "
++"canais\n"
++"                                      do destino onde o fluxo está sendo "
++"conectado.\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"
 -"      --process-time=BYTES              Request the specified process time per request in bytes.\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"
  
  #: ../src/utils/pacat.c:591
  #, c-format
@@@ -1239,40 -1304,46 +1378,40 @@@ msgstr "dup2(): %s\n
  #: ../src/utils/pacat.c:729
  #, c-format
  msgid "Too many arguments.\n"
- msgstr "Zu viele Argumente.\n"
+ msgstr "Argumentos em excesso.\n"
  
 -#: ../src/utils/pacat.c:742
 -#: ../src/utils/pasuspender.c:280
 -#: ../src/utils/pactl.c:909
 -#: ../src/utils/paplay.c:381
 +#: ../src/utils/pacat.c:742 ../src/utils/pasuspender.c:280
 +#: ../src/utils/pactl.c:909 ../src/utils/paplay.c:381
  #, c-format
  msgid "pa_mainloop_new() failed.\n"
- msgstr "pa_mainloop_new() fehlgeschlagen.\n"
+ msgstr "pa_mainloop_new() falhou.\n"
  
  #: ../src/utils/pacat.c:763
  #, c-format
  msgid "io_new() failed.\n"
- msgstr "io_new() fehlgeschlagen.\n"
+ msgstr "io_new() falhou.\n"
  
 -#: ../src/utils/pacat.c:769
 -#: ../src/utils/pasuspender.c:293
 -#: ../src/utils/pactl.c:923
 -#: ../src/utils/paplay.c:396
 +#: ../src/utils/pacat.c:769 ../src/utils/pasuspender.c:293
 +#: ../src/utils/pactl.c:923 ../src/utils/paplay.c:396
  #, c-format
  msgid "pa_context_new() failed.\n"
- msgstr "pa_context_new() fehlgeschlagen.\n"
+ msgstr "pa_context_new() falhou.\n"
  
  #: ../src/utils/pacat.c:777
- #, fuzzy, c-format
+ #, c-format
  msgid "pa_context_connect() failed: %s"
- msgstr "pa_context_new() fehlgeschlagen.\n"
+ msgstr "pa_context_new() falhou: %s"
  
  #: ../src/utils/pacat.c:788
  #, c-format
  msgid "time_new() failed.\n"
- msgstr "time_new() fehlgeschlagen.\n"
+ msgstr "time_new() falhou.\n"
  
 -#: ../src/utils/pacat.c:795
 -#: ../src/utils/pasuspender.c:301
 -#: ../src/utils/pactl.c:931
 -#: ../src/utils/paplay.c:407
 +#: ../src/utils/pacat.c:795 ../src/utils/pasuspender.c:301
 +#: ../src/utils/pactl.c:931 ../src/utils/paplay.c:407
  #, c-format
  msgid "pa_mainloop_run() failed.\n"
- msgstr "pa_mainloop_run() fehlgeschlagen.\n"
+ msgstr "pa_mainloop_run() falhou.\n"
  
  #: ../src/utils/pasuspender.c:81
  #, c-format
@@@ -1297,9 -1368,10 +1436,11 @@@ msgstr "Falha ao prosseguir: %s\n
  #: ../src/utils/pasuspender.c:147
  #, c-format
  msgid "WARNING: Sound server is not local, not suspending.\n"
 -msgstr "AVISO: O servidor de som não é local, Sound server is not local, não está em suspenso.\n"
 +msgstr ""
++"AVISO: O servidor de som não é local, Sound server is not local, não está em "
++"suspenso.\n"
  
 -#: ../src/utils/pasuspender.c:176
 -#: ../src/utils/pactl.c:672
 +#: ../src/utils/pasuspender.c:176 ../src/utils/pactl.c:672
  #: ../src/utils/paplay.c:191
  #, c-format
  msgid "Got SIGINT, exiting.\n"
@@@ -1317,10 -1389,15 +1458,16 @@@ msgid "
  "\n"
  "  -h, --help                            Show this help\n"
  "      --version                         Show version\n"
 -"  -s, --server=SERVER                   The name of the server to connect to\n"
 +"  -s, --server=SERVER                   The name of the server to connect "
 +"to\n"
  "\n"
  msgstr ""
+ "%s [options] ... \n"
+ "\n"
+ "  -h, --help                          Mostra esta ajuda\n"
+ "      --version                         Mostra a versão\n"
+ "  -s, --server=SERVER                   Nome do servidor a ser conectado\n"
+ "\n"
  
  #: ../src/utils/pasuspender.c:251
  #, c-format
@@@ -1389,10 -1477,23 +1547,22 @@@ msgid "
  "Properties:\n"
  "%s"
  msgstr ""
+ "*** Destino #%u ***\n"
+ "Nome: %s\n"
+ "Driver: %s\n"
+ "Especificação de amostragem: %s\n"
+ "Mapa de canais: %s\n"
+ "Propretário do módulo: %u\n"
+ "Volume: %s\n"
+ "Fonte do monitor: %s\n"
+ "Latência: %0.0f us, configurado %0.0f us\n"
+ "Flags: %s%s%s%s%s%s\n"
+ "Propriedades:\n"
+ "%s"
  
 -#: ../src/utils/pactl.c:193
 -#: ../src/utils/pactl.c:371
 +#: ../src/utils/pactl.c:193 ../src/utils/pactl.c:371
  msgid "muted"
- msgstr "stumm"
+ msgstr "mudo"
  
  #: ../src/utils/pactl.c:212
  #, c-format
@@@ -1415,13 -1516,33 +1585,25 @@@ msgid "
  "Properties:\n"
  "%s"
  msgstr ""
+ "*** Fonte #%u ***\n"
+ "Nome: %s\n"
+ "Driver: %s\n"
+ "Especificação de amostragem: %s\n"
+ "Mapa do canal: %s\n"
+ "Proprietário do módulo: %u\n"
+ "Volume: %s\n"
+ "Monitor do destino: %s\n"
+ "Latência: %0.0f us, configurado %0.0f us:\n"
+ "Flags: %s%s%s%s%s%s\n"
+ "Propriedades:\n"
+ "%s"
  
 -#: ../src/utils/pactl.c:246
 -#: ../src/utils/pactl.c:289
 -#: ../src/utils/pactl.c:322
 -#: ../src/utils/pactl.c:366
 -#: ../src/utils/pactl.c:367
 -#: ../src/utils/pactl.c:374
 -#: ../src/utils/pactl.c:418
 -#: ../src/utils/pactl.c:419
 -#: ../src/utils/pactl.c:425
 -#: ../src/utils/pactl.c:468
 -#: ../src/utils/pactl.c:469
 -#: ../src/utils/pactl.c:473
 +#: ../src/utils/pactl.c:246 ../src/utils/pactl.c:289 ../src/utils/pactl.c:322
 +#: ../src/utils/pactl.c:366 ../src/utils/pactl.c:367 ../src/utils/pactl.c:374
 +#: ../src/utils/pactl.c:418 ../src/utils/pactl.c:419 ../src/utils/pactl.c:425
 +#: ../src/utils/pactl.c:468 ../src/utils/pactl.c:469 ../src/utils/pactl.c:473
  msgid "n/a"
- msgstr "k.A."
+ msgstr "n/a"
  
  #: ../src/utils/pactl.c:263
  #, c-format
@@@ -1540,12 -1712,13 +1773,12 @@@ msgstr "destino
  
  #: ../src/utils/pactl.c:504
  msgid "source"
- msgstr "Quelle"
+ msgstr "fonte"
  
 -#: ../src/utils/pactl.c:511
 -#: ../src/utils/pactl.c:521
 +#: ../src/utils/pactl.c:511 ../src/utils/pactl.c:521
  #, c-format
  msgid "Failure: %s\n"
- msgstr ""
+ msgstr "Falha: %s\n"
  
  #: ../src/utils/pactl.c:545
  #, c-format
@@@ -1576,11 -1749,27 +1809,30 @@@ msgid "
  "  -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"
 +"  -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"
  msgstr ""
+ "%s [options] stat\n"
+ "%s [options] list\n"
+ "%s [options] exit\n"
+ "%s [options] upload-sample FILENAME [NAME]\n"
+ "%s [options] play-sample NAME [SINK]\n"
+ "%s [options] remove-sample NAME\n"
+ "%s [options] move-sink-input ID SINK\n"
+ "%s [options] move-source-output ID SOURCE\n"
+ "%s [options] load-module NAME [ARGS ...]\n"
+ "%s [options] unload-module ID\n"
+ "%s [options] suspend-sink [SINK] 1|0\n"
+ "%s [options] suspend-source [SOURCE] 1|0\n"
+ "\n"
+ "  -h, --help                            Mostra essa ajuda\n"
+ "      --version                        Mostra a versão\n"
+ "\n"
+ "  -s, --server=SERVER                   O nome do servidor a ser conectado\n"
 -"  -n, --client-name=NAME                Como chamar este cliente no servidor \n"
++"  -n, --client-name=NAME                Como chamar este cliente no "
++"servidor \n"
  
  #: ../src/utils/pactl.c:729
  #, c-format
@@@ -1613,7 -1805,7 +1868,8 @@@ msgstr "Você deve especificar um nome 
  #: ../src/utils/pactl.c:822
  #, c-format
  msgid "You have to specify a sink input index and a sink\n"
 -msgstr "Você tem que especificar a entrada para o destino (sink) e um destino(sink)\n"
 +msgstr ""
++"Você tem que especificar a entrada para o destino (sink) e um destino(sink)\n"
  
  #: ../src/utils/pactl.c:831
  #, c-format
@@@ -1632,17 -1824,13 +1888,21 @@@ msgstr "Você deve especificar um índi
  
  #: ../src/utils/pactl.c:875
  #, c-format
 -msgid "You may not specify more than one sink. You have to specify at least one boolean value.\n"
 -msgstr "Você não pode especificar mais de um destino. Pelo menos um valor booleano deve ser especificado.\n"
 +msgid ""
 +"You may not specify more than one sink. You have to specify at least one "
 +"boolean value.\n"
 +msgstr ""
++"Você não pode especificar mais de um destino. Pelo menos um valor booleano "
++"deve ser especificado.\n"
  
  #: ../src/utils/pactl.c:888
  #, c-format
 -msgid "You may not specify more than one source. You have to specify at least one boolean value.\n"
 -msgstr "Você não pode especificar mais de uma fonte. Pelo menos um valor booleano deve ser especificado.\n"
 +msgid ""
 +"You may not specify more than one source. You have to specify at least one "
 +"boolean value.\n"
 +msgstr ""
++"Você não pode especificar mais de uma fonte. Pelo menos um valor booleano "
++"deve ser especificado.\n"
  
  #: ../src/utils/pactl.c:904
  #, c-format
@@@ -1656,10 -1844,15 +1916,18 @@@ msgid "
  "\n"
  " -d    Show current PulseAudio data attached to X11 display (default)\n"
  " -e    Export local PulseAudio data to X11 display\n"
 -" -i    Import PulseAudio data from X11 display to local environment variables and cookie file.\n"
 +" -i    Import PulseAudio data from X11 display to local environment "
 +"variables and cookie file.\n"
  " -r    Remove PulseAudio data from X11 display\n"
  msgstr ""
+ "%s [-D display] [-S server] [-O sink] [-I source] [-c file]  [-d|-e|-i|-r]\n"
+ "\n"
 -" -d    Mostra os dados atuais do PulseAudio associados ao display X11 (padrão)\n"
++" -d    Mostra os dados atuais do PulseAudio associados ao display X11 "
++"(padrão)\n"
+ " -e    Exporta os dados locais do PulseAudio para um display X11 \n"
 -" -i     Importa os dados do PulseAudio de um display X11 para as variáveis de ambiente locais e para o arquivo de cookie.\n"
++" -i     Importa os dados do PulseAudio de um display X11 para as variáveis "
++"de ambiente locais e para o arquivo de cookie.\n"
+ " -r    Remove os dados do PulseAudio do display X11\n"
  
  #: ../src/utils/pax11publish.c:94
  #, c-format
@@@ -1779,17 -1974,26 +2047,32 @@@ msgid "
  "\n"
  "  -v, --verbose                         Enable verbose operation\n"
  "\n"
 -"  -s, --server=SERVER                   The name of the server to connect to\n"
 +"  -s, --server=SERVER                   The name of the server to connect "
 +"to\n"
  "  -d, --device=DEVICE                   The name of the sink to connect to\n"
 -"  -n, --client-name=NAME                How to call this client on the server\n"
 -"      --stream-name=NAME                How to call this stream on the server\n"
 -"      --volume=VOLUME                   Specify the initial (linear) volume in range 0...65536\n"
 +"  -n, --client-name=NAME                How to call this client on the "
 +"server\n"
 +"      --stream-name=NAME                How to call this stream on the "
 +"server\n"
 +"      --volume=VOLUME                   Specify the initial (linear) volume "
 +"in range 0...65536\n"
  "      --channel-map=CHANNELMAP          Set the channel map to the use\n"
  msgstr ""
+ "%s [options] [FILE]\n"
+ "\n"
+ "  -h, --help                            Mostra essa ajuda\n"
+ "      --version                         Mostra a versão\n"
+ "\n"
+ "  -v, --verbose                         Habilida a operação detalhada\n"
+ "\n"
+ "  -s, --server=SERVER                   O nome do servidor a ser conectado\n"
+ "  -d, --device=DEVICE                   O nome do destino a ser conectado\n"
 -"  -n, --client-name=NAME                Como chamar este cliente no servidor\n"
++"  -n, --client-name=NAME                Como chamar este cliente no "
++"servidor\n"
+ "      --stream-name=NAME                Como chamar este fluxo no servidor\n"
 -"      --volume=VOLUME                   Especifica o volume inicial (linear) no intervalo 0...65536\n"
++"      --volume=VOLUME                   Especifica o volume inicial (linear) "
++"no intervalo 0...65536\n"
+ "      --channel-map=CHANNELMAP          Define o mapa do canal para uso\n"
  
  #: ../src/utils/paplay.c:255
  #, c-format
@@@ -1817,11 -2024,13 +2103,28 @@@ msgstr "O mapa dos canais não coincid
  #: ../src/utils/paplay.c:376
  #, c-format
  msgid "Using sample spec '%s'\n"
- msgstr ""
+ msgstr "Usando a especificação da amostragem '%s'\n"
  
 -#: ../src/pulsecore/lock-autospawn.c:126
 -#: ../src/pulsecore/lock-autospawn.c:207
 +#: ../src/pulsecore/lock-autospawn.c:126 ../src/pulsecore/lock-autospawn.c:207
  msgid "Cannot access autospawn lock."
- msgstr ""
+ msgstr "Não foi possível acessar a trava de autogeração."
+ 
++#~ msgid ""
++#~ "' 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 '"
++#~ msgstr ""
++#~ "' e o PolicyKit recusa-nos a garantia de privilégios. Retirando o SUID "
++#~ "outra vez.\n"
++#~ " Para habilitar o escalonamento em tempo real, por favo, adquira os "
++#~ "privilégios adequados pelo PolicyKit, ou torne-se membro do'"
++
++#~ msgid ""
++#~ "', or increase the RLIMIT_NICE/RLIMIT_RTPRIO resource limits for this "
++#~ "user."
++#~ msgstr ""
++#~ "', ou eleve o RLIMIT_NICE/RLIMIT_RTPRIO dos limites do recurso para este "
++#~ "usuário."
 +
  #~ msgid "socketpair(): %s"
  #~ msgstr "socketpair(): %s"
 -
diff --cc po/sv.po
index 269a225,11f6e13..772e155
--- a/po/sv.po
+++ b/po/sv.po
@@@ -7,7 -7,7 +7,7 @@@ msgid "
  msgstr ""
  "Project-Id-Version: pulseaudio\n"
  "Report-Msgid-Bugs-To: \n"
- "POT-Creation-Date: 2008-10-06 03:21+0200\n"
 -"POT-Creation-Date: 2008-09-04 19:30+0000\n"
++"POT-Creation-Date: 2008-10-07 21:03+0200\n"
  "PO-Revision-Date: 2008-09-05 18:24+0100\n"
  "Last-Translator: Daniel Nylander <po at danielnylander.se>\n"
  "Language-Team: Swedish <tp-sv at listor.tp-sv.se>\n"

-- 
hooks/post-receive
PulseAudio Sound Server



More information about the pulseaudio-commits mailing list