[pulseaudio-commits] [SCM] PulseAudio Sound Server branch, master, updated. v0.9.13-350-g3be4c31

Lennart Poettering gitmailer-noreply at 0pointer.de
Wed Jan 21 15:26:53 PST 2009


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

The master branch has been updated
      from  601293d346ef4bfc8f2ff80d6c13a0d66d9bdd57 (commit)

- Log -----------------------------------------------------------------
3be4c31... rework module-hal-detect and make it use module-alsa-card instead of module-alsa-sink/-source
b2ef19a... include PA_SINK_INVALID_STATE in all switch/case statements to make gcc shut up
4b2a682... fix minor memleak in prober
b606c09... rework logic how alsa sinks/sources/cards are named
7c11554... make gcc shut up
1c84251... fix segfault when in record-only mode
8519f54... only reread volume if we actually have a good mixer. Closes #466
40f2e21... make gcc shut up a bit more
a5c9546... fix copy'n'paste error
251f720... add new function pa_strna
36362f6... add new function pa_card_suspend()
bdfec1f... mark a few more ALSA dB values as 'valid' for valgrind
0f7954a... don't include full path in driver name.
bf7217b... require autoconf 2.63
-----------------------------------------------------------------------

Summary of changes:
 bootstrap.sh                          |    4 +-
 configure.ac                          |    2 +-
 src/modules/alsa/alsa-sink.c          |   52 ++-
 src/modules/alsa/alsa-source.c        |   52 ++-
 src/modules/alsa/alsa-util.c          |    2 +
 src/modules/alsa/module-alsa-card.c   |   36 ++-
 src/modules/alsa/module-alsa-sink.c   |    2 +
 src/modules/alsa/module-alsa-source.c |    2 +
 src/modules/module-combine.c          |    1 +
 src/modules/module-esound-sink.c      |    1 +
 src/modules/module-hal-detect.c       |  656 ++++++++++++++++-----------------
 src/modules/module-raop-sink.c        |    1 +
 src/modules/module-tunnel.c           |    2 +
 src/modules/oss/module-oss.c          |   19 +-
 src/modules/oss/oss-util.c            |    7 +-
 src/pulse/def.h                       |    4 +-
 src/pulsecore/card.c                  |   20 +-
 src/pulsecore/card.h                  |    2 +
 src/pulsecore/client.c                |    3 +-
 src/pulsecore/core-util.h             |    5 +-
 src/pulsecore/protocol-native.c       |    4 +-
 src/pulsecore/sink-input.c            |    3 +-
 src/pulsecore/sink.c                  |    3 +-
 src/pulsecore/source-output.c         |    3 +-
 src/pulsecore/source.c                |    3 +-
 25 files changed, 485 insertions(+), 404 deletions(-)

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

commit bf7217b6a5ef2cfd9c3399ba055f5643f89e0375
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Jan 22 00:11:58 2009 +0100

    require autoconf 2.63

diff --git a/bootstrap.sh b/bootstrap.sh
index 4eacc5a..6698f68 100755
--- a/bootstrap.sh
+++ b/bootstrap.sh
@@ -59,8 +59,8 @@ else
     intltoolize --copy --force --automake
     "$LIBTOOLIZE" -c --force --ltdl --recursive
     run_versioned aclocal "$VERSION" -I m4
-    run_versioned autoconf 2.62 -Wall
-    run_versioned autoheader 2.62
+    run_versioned autoconf 2.63 -Wall
+    run_versioned autoheader 2.63
     run_versioned automake "$VERSION" --copy --foreign --add-missing
 
     if test "x$NOCONFIGURE" = "x"; then

commit 0f7954a9f5291ba865ff87b6884c16a3014c1b76
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Jan 22 00:15:19 2009 +0100

    don't include full path in driver name.

diff --git a/src/pulsecore/card.c b/src/pulsecore/card.c
index 397c6d7..ac9e6d9 100644
--- a/src/pulsecore/card.c
+++ b/src/pulsecore/card.c
@@ -28,6 +28,7 @@
 #include <string.h>
 
 #include <pulse/xmalloc.h>
+#include <pulse/util.h>
 
 #include <pulsecore/log.h>
 #include <pulsecore/macro.h>
@@ -128,7 +129,7 @@ pa_card *pa_card_new(pa_core *core, pa_card_new_data *data) {
     c->core = core;
     c->name = pa_xstrdup(data->name);
     c->proplist = pa_proplist_copy(data->proplist);
-    c->driver = pa_xstrdup(data->driver);
+    c->driver = pa_xstrdup(pa_path_get_filename(data->driver));
     c->module = data->module;
 
     c->sinks = pa_idxset_new(NULL, NULL);
diff --git a/src/pulsecore/client.c b/src/pulsecore/client.c
index 1e65fcd..1800441 100644
--- a/src/pulsecore/client.c
+++ b/src/pulsecore/client.c
@@ -29,6 +29,7 @@
 #include <string.h>
 
 #include <pulse/xmalloc.h>
+#include <pulse/util.h>
 
 #include <pulsecore/core-subscribe.h>
 #include <pulsecore/log.h>
@@ -64,7 +65,7 @@ pa_client *pa_client_new(pa_core *core, pa_client_new_data *data) {
     c = pa_xnew(pa_client, 1);
     c->core = core;
     c->proplist = pa_proplist_copy(data->proplist);
-    c->driver = pa_xstrdup(data->driver);
+    c->driver = pa_xstrdup(pa_path_get_filename(data->driver));
     c->module = data->module;
 
     c->sink_inputs = pa_idxset_new(NULL, NULL);
diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c
index 8f18266..5667114 100644
--- a/src/pulsecore/sink-input.c
+++ b/src/pulsecore/sink-input.c
@@ -30,6 +30,7 @@
 
 #include <pulse/utf8.h>
 #include <pulse/xmalloc.h>
+#include <pulse/util.h>
 
 #include <pulsecore/sample-util.h>
 #include <pulsecore/core-subscribe.h>
@@ -229,7 +230,7 @@ pa_sink_input* pa_sink_input_new(
     i->state = PA_SINK_INPUT_INIT;
     i->flags = flags;
     i->proplist = pa_proplist_copy(data->proplist);
-    i->driver = pa_xstrdup(data->driver);
+    i->driver = pa_xstrdup(pa_path_get_filename(data->driver));
     i->module = data->module;
     i->sink = data->sink;
     i->client = data->client;
diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c
index bd90cf5..df46a2c 100644
--- a/src/pulsecore/sink.c
+++ b/src/pulsecore/sink.c
@@ -32,6 +32,7 @@
 #include <pulse/utf8.h>
 #include <pulse/xmalloc.h>
 #include <pulse/timeval.h>
+#include <pulse/util.h>
 
 #include <pulsecore/sink-input.h>
 #include <pulsecore/namereg.h>
@@ -184,7 +185,7 @@ pa_sink* pa_sink_new(
     s->flags = flags;
     s->name = pa_xstrdup(name);
     s->proplist = pa_proplist_copy(data->proplist);
-    s->driver = pa_xstrdup(data->driver);
+    s->driver = pa_xstrdup(pa_path_get_filename(data->driver));
     s->module = data->module;
     s->card = data->card;
 
diff --git a/src/pulsecore/source-output.c b/src/pulsecore/source-output.c
index e314656..cb8ba28 100644
--- a/src/pulsecore/source-output.c
+++ b/src/pulsecore/source-output.c
@@ -29,6 +29,7 @@
 
 #include <pulse/utf8.h>
 #include <pulse/xmalloc.h>
+#include <pulse/util.h>
 
 #include <pulsecore/sample-util.h>
 #include <pulsecore/core-subscribe.h>
@@ -192,7 +193,7 @@ pa_source_output* pa_source_output_new(
     o->state = PA_SOURCE_OUTPUT_INIT;
     o->flags = flags;
     o->proplist = pa_proplist_copy(data->proplist);
-    o->driver = pa_xstrdup(data->driver);
+    o->driver = pa_xstrdup(pa_path_get_filename(data->driver));
     o->module = data->module;
     o->source = data->source;
     o->client = data->client;
diff --git a/src/pulsecore/source.c b/src/pulsecore/source.c
index a30ef95..fea66b7 100644
--- a/src/pulsecore/source.c
+++ b/src/pulsecore/source.c
@@ -31,6 +31,7 @@
 #include <pulse/utf8.h>
 #include <pulse/xmalloc.h>
 #include <pulse/timeval.h>
+#include <pulse/util.h>
 
 #include <pulsecore/source-output.h>
 #include <pulsecore/namereg.h>
@@ -175,7 +176,7 @@ pa_source* pa_source_new(
     s->flags = flags;
     s->name = pa_xstrdup(name);
     s->proplist = pa_proplist_copy(data->proplist);
-    s->driver = pa_xstrdup(data->driver);
+    s->driver = pa_xstrdup(pa_path_get_filename(data->driver));
     s->module = data->module;
     s->card = data->card;
 

commit bdfec1feba2585aaa5ad88a2760da5c38f3466e9
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Jan 22 00:16:28 2009 +0100

    mark a few more ALSA dB values as 'valid' for valgrind

diff --git a/src/modules/alsa/alsa-sink.c b/src/modules/alsa/alsa-sink.c
index e6b3e0e..61fb408 100644
--- a/src/modules/alsa/alsa-sink.c
+++ b/src/modules/alsa/alsa-sink.c
@@ -870,6 +870,10 @@ static int sink_set_volume_cb(pa_sink *s) {
                 if ((err = snd_mixer_selem_get_playback_dB(u->mixer_elem, u->mixer_map[i], &alsa_vol)) < 0)
                     goto fail;
 
+#ifdef HAVE_VALGRIND_MEMCHECK_H
+                VALGRIND_MAKE_MEM_DEFINED(&alsa_vol, sizeof(alsa_vol));
+#endif
+
                 r.values[i] = pa_sw_volume_from_dB((double) (alsa_vol - u->hw_dB_max) / 100.0);
 
             } else {
@@ -902,6 +906,10 @@ static int sink_set_volume_cb(pa_sink *s) {
             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));
+#endif
+
             pa_cvolume_set(&r, s->volume.channels, pa_sw_volume_from_dB((double) (alsa_vol - u->hw_dB_max) / 100.0));
 
         } else {
diff --git a/src/modules/alsa/alsa-source.c b/src/modules/alsa/alsa-source.c
index 29145f6..3a7b308 100644
--- a/src/modules/alsa/alsa-source.c
+++ b/src/modules/alsa/alsa-source.c
@@ -816,6 +816,10 @@ static int source_set_volume_cb(pa_source *s) {
                 if ((err = snd_mixer_selem_get_capture_dB(u->mixer_elem, u->mixer_map[i], &alsa_vol)) < 0)
                     goto fail;
 
+#ifdef HAVE_VALGRIND_MEMCHECK_H
+                VALGRIND_MAKE_MEM_DEFINED(&alsa_vol, sizeof(alsa_vol));
+#endif
+
                 r.values[i] = pa_sw_volume_from_dB((double) (alsa_vol - u->hw_dB_max) / 100.0);
 
             } else {
@@ -848,6 +852,10 @@ static int source_set_volume_cb(pa_source *s) {
             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));
+#endif
+
             pa_cvolume_set(&r, s->volume.channels, pa_sw_volume_from_dB((double) (alsa_vol - u->hw_dB_max) / 100.0));
 
         } else {

commit 36362f624f985c14f757884c6d4fd6a079a4701b
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Jan 22 00:17:11 2009 +0100

    add new function pa_card_suspend()

diff --git a/src/pulsecore/card.c b/src/pulsecore/card.c
index ac9e6d9..8e1ba53 100644
--- a/src/pulsecore/card.c
+++ b/src/pulsecore/card.c
@@ -235,3 +235,20 @@ int pa_card_set_profile(pa_card *c, const char *name) {
 
     return 0;
 }
+
+int pa_card_suspend(pa_card *c, pa_bool_t suspend) {
+    pa_sink *sink;
+    pa_source *source;
+    uint32_t idx;
+    int ret = 0;
+
+    pa_assert(c);
+
+    for (sink = pa_idxset_first(c->sinks, &idx); sink; sink = pa_idxset_next(c->sinks, &idx))
+        ret -= pa_sink_suspend(sink, suspend) < 0;
+
+    for (source = pa_idxset_first(c->sources, &idx); source; source = pa_idxset_next(c->sources, &idx))
+        ret -= pa_source_suspend(source, suspend) < 0;
+
+    return ret;
+}
diff --git a/src/pulsecore/card.h b/src/pulsecore/card.h
index 9aa8f37..b179831 100644
--- a/src/pulsecore/card.h
+++ b/src/pulsecore/card.h
@@ -95,4 +95,6 @@ void pa_card_free(pa_card *c);
 
 int pa_card_set_profile(pa_card *c, const char *name);
 
+int pa_card_suspend(pa_card *c, pa_bool_t suspend);
+
 #endif

commit 251f720b05a92294f96347b5da1a3f2ca9b55d29
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Jan 22 00:17:31 2009 +0100

    add new function pa_strna

diff --git a/src/pulsecore/core-util.h b/src/pulsecore/core-util.h
index 167d073..44b3af3 100644
--- a/src/pulsecore/core-util.h
+++ b/src/pulsecore/core-util.h
@@ -97,6 +97,10 @@ static inline const char *pa_strempty(const char *x) {
     return x ? x : "";
 }
 
+static inline const char *pa_strna(const char *x) {
+    return x ? x : "n/a";
+}
+
 char *pa_split(const char *c, const char*delimiters, const char **state);
 char *pa_split_spaces(const char *c, const char **state);
 
@@ -198,7 +202,6 @@ 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

commit a5c9546fc7e20cb1ea26fbe80b0ec26aab11b76e
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Jan 22 00:17:55 2009 +0100

    fix copy'n'paste error

diff --git a/src/pulse/def.h b/src/pulse/def.h
index fb1bd27..be5cc23 100644
--- a/src/pulse/def.h
+++ b/src/pulse/def.h
@@ -609,7 +609,7 @@ typedef enum pa_sink_flags {
 #define PA_SINK_LATENCY PA_SINK_LATENCY
 #define PA_SINK_HARDWARE PA_SINK_HARDWARE
 #define PA_SINK_NETWORK PA_SINK_NETWORK
-#define PA_SINK_HW_VOLUME_CTRL PA_SINK_HW_VOLUME_CTRL
+#define PA_SINK_HW_MUTE_CTRL PA_SINK_HW_MUTE_CTRL
 #define PA_SINK_DECIBEL_VOLUME PA_SINK_DECIBEL_VOLUME
 /** \endcond */
 
@@ -684,7 +684,7 @@ typedef enum pa_source_flags {
 #define PA_SOURCE_LATENCY PA_SOURCE_LATENCY
 #define PA_SOURCE_HARDWARE PA_SOURCE_HARDWARE
 #define PA_SOURCE_NETWORK PA_SOURCE_NETWORK
-#define PA_SOURCE_HW_VOLUME_CTRL PA_SOURCE_HW_VOLUME_CTRL
+#define PA_SOURCE_HW_MUTE_CTRL PA_SOURCE_HW_MUTE_CTRL
 #define PA_SOURCE_DECIBEL_VOLUME PA_SOURCE_DECIBEL_VOLUME
 /** \endcond */
 

commit 40f2e21aa731c56353dc75a4ad4effcb88b41916
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Jan 22 00:19:04 2009 +0100

    make gcc shut up a bit more

diff --git a/src/modules/oss/oss-util.c b/src/modules/oss/oss-util.c
index f8e11fd..ea8d811 100644
--- a/src/modules/oss/oss-util.c
+++ b/src/modules/oss/oss-util.c
@@ -45,6 +45,7 @@
 int pa_oss_open(const char *device, int *mode, int* pcaps) {
     int fd = -1;
     int caps;
+    char *t;
 
     pa_assert(device);
     pa_assert(mode);
@@ -92,7 +93,8 @@ int pa_oss_open(const char *device, int *mode, int* pcaps) {
 
 success:
 
-    pa_log_debug("capabilities:%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
+    t = pa_sprintf_malloc(
+            "%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
                  *pcaps & DSP_CAP_BATCH ? " BATCH" : "",
 #ifdef DSP_CAP_BIND
                  *pcaps & DSP_CAP_BIND ? " BIND" : "",
@@ -140,6 +142,9 @@ success:
 #endif
                  *pcaps & DSP_CAP_TRIGGER ? " TRIGGER" : "");
 
+    pa_log_debug("capabilities:%s", t);
+    pa_xfree(t);
+
     pa_make_fd_cloexec(fd);
 
     return fd;

commit 8519f54a0eaefb0e84586b354c260a999a595e22
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Jan 22 00:20:15 2009 +0100

    only reread volume if we actually have a good mixer. Closes #466

diff --git a/src/modules/oss/module-oss.c b/src/modules/oss/module-oss.c
index 23a3254..79cbf67 100644
--- a/src/modules/oss/module-oss.c
+++ b/src/modules/oss/module-oss.c
@@ -601,10 +601,10 @@ static int unsuspend(struct userdata *u) {
 
     build_pollfd(u);
 
-    if (u->sink)
-        sink_get_volume(u->sink);
-    if (u->source)
-        source_get_volume(u->source);
+    if (u->sink && u->sink->get_volume)
+        u->sink->get_volume(u->sink);
+    if (u->source && u->source->get_volume)
+        u->source->get_volume(u->source);
 
     pa_log_info("Resumed successfully...");
 
@@ -1201,12 +1201,12 @@ int pa__init(pa_module*m) {
 
     if (use_mmap && (!(caps & DSP_CAP_MMAP) || !(caps & DSP_CAP_TRIGGER))) {
         pa_log_info("OSS device not mmap capable, falling back to UNIX read/write mode.");
-        use_mmap = 0;
+        use_mmap = FALSE;
     }
 
     if (use_mmap && mode == O_WRONLY) {
         pa_log_info("Device opened for playback only, cannot do memory mapping, falling back to UNIX write() mode.");
-        use_mmap = 0;
+        use_mmap = FALSE;
     }
 
     if (pa_oss_get_hw_description(dev, hwdesc, sizeof(hwdesc)) >= 0)
@@ -1235,6 +1235,7 @@ int pa__init(pa_module*m) {
     m->userdata = u;
     u->fd = fd;
     u->mixer_fd = -1;
+    u->mixer_devmask = 0;
     u->use_getospace = u->use_getispace = TRUE;
     u->use_getodelay = TRUE;
     u->mode = mode;
@@ -1383,7 +1384,6 @@ int pa__init(pa_module*m) {
 
     if ((u->mixer_fd = pa_oss_open_mixer_for_device(u->device_name)) >= 0) {
         pa_bool_t do_close = TRUE;
-        u->mixer_devmask = 0;
 
         if (ioctl(fd, SOUND_MIXER_READ_DEVMASK, &u->mixer_devmask) < 0)
             pa_log_warn("SOUND_MIXER_READ_DEVMASK failed: %s", pa_cstrerror(errno));
@@ -1409,6 +1409,7 @@ int pa__init(pa_module*m) {
         if (do_close) {
             pa_close(u->mixer_fd);
             u->mixer_fd = -1;
+            u->mixer_devmask = 0;
         }
     }
 

commit 1c84251ec5c0f7b60d12e2cca73871d779e4e0d3
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Jan 22 00:22:29 2009 +0100

    fix segfault when in record-only mode

diff --git a/src/modules/oss/module-oss.c b/src/modules/oss/module-oss.c
index 79cbf67..da9245a 100644
--- a/src/modules/oss/module-oss.c
+++ b/src/modules/oss/module-oss.c
@@ -877,7 +877,7 @@ static void thread_func(void *userdata) {
 
 /*        pa_log("loop");    */
 
-        if (PA_SINK_IS_OPENED(u->sink->thread_info.state))
+        if (u->sink && PA_SINK_IS_OPENED(u->sink->thread_info.state))
             if (u->sink->thread_info.rewind_requested)
                 pa_sink_process_rewind(u->sink, 0);
 

commit 7c11554daaf273a04fded3e06f75c7668182a135
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Jan 22 00:22:46 2009 +0100

    make gcc shut up

diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c
index af9c05b..7ddc010 100644
--- a/src/pulsecore/protocol-native.c
+++ b/src/pulsecore/protocol-native.c
@@ -3985,7 +3985,7 @@ static void command_extension(pa_pdispatch *pd, uint32_t command, uint32_t tag,
     CHECK_VALIDITY(c->pstream, m, tag, PA_ERR_NOEXTENSION);
     CHECK_VALIDITY(c->pstream, m->load_once || idx != PA_INVALID_INDEX, tag, PA_ERR_INVALID);
 
-    cb = (pa_native_protocol_ext_cb_t) pa_hashmap_get(c->protocol->extensions, m);
+    cb = (pa_native_protocol_ext_cb_t) (unsigned long) pa_hashmap_get(c->protocol->extensions, m);
     CHECK_VALIDITY(c->pstream, m, tag, PA_ERR_NOEXTENSION);
 
     if (cb(c->protocol, m, c, tag, t) < 0)
@@ -4380,7 +4380,7 @@ int pa_native_protocol_install_ext(pa_native_protocol *p, pa_module *m, pa_nativ
     pa_assert(cb);
     pa_assert(!pa_hashmap_get(p->extensions, m));
 
-    pa_assert_se(pa_hashmap_put(p->extensions, m, (void*) cb) == 0);
+    pa_assert_se(pa_hashmap_put(p->extensions, m, (void*) (unsigned long) cb) == 0);
     return 0;
 }
 

commit b606c0940a1309a7034d5c479e8601965075985d
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Jan 22 00:24:13 2009 +0100

    rework logic how alsa sinks/sources/cards are named

diff --git a/src/modules/alsa/alsa-sink.c b/src/modules/alsa/alsa-sink.c
index 61fb408..749396f 100644
--- a/src/modules/alsa/alsa-sink.c
+++ b/src/modules/alsa/alsa-sink.c
@@ -1209,6 +1209,32 @@ finish:
     pa_log_debug("Thread shutting down");
 }
 
+static void set_sink_name(pa_sink_new_data *data, pa_modargs *ma, const char *device_id, const char *device_name) {
+    const char *n;
+    char *t;
+
+    pa_assert(data);
+    pa_assert(ma);
+    pa_assert(device_name);
+
+    if ((n = pa_modargs_get_value(ma, "sink_name", NULL))) {
+        pa_sink_new_data_set_name(data, n);
+        data->namereg_fail = TRUE;
+        return;
+    }
+
+    if ((n = pa_modargs_get_value(ma, "name", NULL)))
+        data->namereg_fail = TRUE;
+    else {
+        n = device_id ? device_id : device_name;
+        data->namereg_fail = FALSE;
+    }
+
+    t = pa_sprintf_malloc("alsa_output.%s", n);
+    pa_sink_new_data_set_name(data, t);
+    pa_xfree(t);
+}
+
 pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_card *card, const pa_alsa_profile_info *profile) {
 
     struct userdata *u = NULL;
@@ -1220,9 +1246,6 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca
     size_t frame_size;
     snd_pcm_info_t *pcm_info = NULL;
     int err;
-    const char *name;
-    char *name_buf = NULL;
-    pa_bool_t namereg_fail;
     pa_bool_t use_mmap = TRUE, b, use_tsched = TRUE, d;
     pa_usec_t usec;
     pa_sink_new_data data;
@@ -1404,22 +1427,11 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca
         }
     }
 
-    if ((name = pa_modargs_get_value(ma, "sink_name", NULL)))
-        namereg_fail = TRUE;
-    else if ((name = pa_modargs_get_value(ma, "name", NULL))) {
-        name = name_buf = pa_sprintf_malloc("alsa_output.%s", name);
-        namereg_fail = TRUE;
-    } else {
-        name = name_buf = pa_sprintf_malloc("alsa_output.%s", u->device_name);
-        namereg_fail = FALSE;
-    }
-
     pa_sink_new_data_init(&data);
     data.driver = driver;
     data.module = m;
     data.card = card;
-    pa_sink_new_data_set_name(&data, name);
-    data.namereg_fail = namereg_fail;
+    set_sink_name(&data, ma, dev_id, u->device_name);
     pa_sink_new_data_set_sample_spec(&data, &ss);
     pa_sink_new_data_set_channel_map(&data, &map);
 
@@ -1436,7 +1448,6 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca
 
     u->sink = pa_sink_new(m->core, &data, PA_SINK_HARDWARE|PA_SINK_LATENCY);
     pa_sink_new_data_done(&data);
-    pa_xfree(name_buf);
 
     if (!u->sink) {
         pa_log("Failed to create sink object");
diff --git a/src/modules/alsa/alsa-source.c b/src/modules/alsa/alsa-source.c
index 3a7b308..fe4eddb 100644
--- a/src/modules/alsa/alsa-source.c
+++ b/src/modules/alsa/alsa-source.c
@@ -1044,6 +1044,32 @@ finish:
     pa_log_debug("Thread shutting down");
 }
 
+static void set_source_name(pa_source_new_data *data, pa_modargs *ma, const char *device_id, const char *device_name) {
+    const char *n;
+    char *t;
+
+    pa_assert(data);
+    pa_assert(ma);
+    pa_assert(device_name);
+
+    if ((n = pa_modargs_get_value(ma, "source_name", NULL))) {
+        pa_source_new_data_set_name(data, n);
+        data->namereg_fail = TRUE;
+        return;
+    }
+
+    if ((n = pa_modargs_get_value(ma, "name", NULL)))
+        data->namereg_fail = TRUE;
+    else {
+        n = device_id ? device_id : device_name;
+        data->namereg_fail = FALSE;
+    }
+
+    t = pa_sprintf_malloc("alsa_input.%s", n);
+    pa_source_new_data_set_name(data, t);
+    pa_xfree(t);
+}
+
 pa_source *pa_alsa_source_new(pa_module *m, pa_modargs *ma, const char*driver, pa_card *card, const pa_alsa_profile_info *profile) {
 
     struct userdata *u = NULL;
@@ -1055,9 +1081,6 @@ pa_source *pa_alsa_source_new(pa_module *m, pa_modargs *ma, const char*driver, p
     size_t frame_size;
     snd_pcm_info_t *pcm_info = NULL;
     int err;
-    const char *name;
-    char *name_buf = NULL;
-    pa_bool_t namereg_fail;
     pa_bool_t use_mmap = TRUE, b, use_tsched = TRUE, d;
     pa_source_new_data data;
 
@@ -1229,22 +1252,11 @@ pa_source *pa_alsa_source_new(pa_module *m, pa_modargs *ma, const char*driver, p
         }
     }
 
-    if ((name = pa_modargs_get_value(ma, "source_name", NULL)))
-        namereg_fail = TRUE;
-    else if ((name = pa_modargs_get_value(ma, "name", NULL))) {
-        name = name_buf = pa_sprintf_malloc("alsa_input.%s", name);
-        namereg_fail = TRUE;
-    } else {
-        name = name_buf = pa_sprintf_malloc("alsa_input.%s", u->device_name);
-        namereg_fail = FALSE;
-    }
-
     pa_source_new_data_init(&data);
     data.driver = driver;
     data.module = m;
     data.card = card;
-    pa_source_new_data_set_name(&data, name);
-    data.namereg_fail = namereg_fail;
+    set_source_name(&data, ma, dev_id, u->device_name);
     pa_source_new_data_set_sample_spec(&data, &ss);
     pa_source_new_data_set_channel_map(&data, &map);
 
@@ -1261,7 +1273,6 @@ pa_source *pa_alsa_source_new(pa_module *m, pa_modargs *ma, const char*driver, p
 
     u->source = pa_source_new(m->core, &data, PA_SOURCE_HARDWARE|PA_SOURCE_LATENCY);
     pa_source_new_data_done(&data);
-    pa_xfree(name_buf);
 
     if (!u->source) {
         pa_log("Failed to create source object");
diff --git a/src/modules/alsa/module-alsa-card.c b/src/modules/alsa/module-alsa-card.c
index f250602..9a00edd 100644
--- a/src/modules/alsa/module-alsa-card.c
+++ b/src/modules/alsa/module-alsa-card.c
@@ -37,7 +37,10 @@ PA_MODULE_DESCRIPTION("ALSA Card");
 PA_MODULE_VERSION(PACKAGE_VERSION);
 PA_MODULE_LOAD_ONCE(FALSE);
 PA_MODULE_USAGE(
-        "name=<name for the sink/source> "
+        "name=<name for the card/sink/source, to be prefixed> "
+        "card_name=<name for card> "
+        "sink_name=<name for sink> "
+        "source_name=<name for source> "
         "device_id=<ALSA card index> "
         "format=<sample format> "
         "rate=<sample rate> "
@@ -51,6 +54,9 @@ PA_MODULE_USAGE(
 
 static const char* const valid_modargs[] = {
     "name",
+    "card_name",
+    "sink_name",
+    "source_name",
     "device_id",
     "format",
     "rate",
@@ -189,6 +195,32 @@ static void init_profile(struct userdata *u) {
         u->source = pa_alsa_source_new(u->module, u->modargs, __FILE__, u->card, d->source_profile);
 }
 
+static void set_card_name(pa_card_new_data *data, pa_modargs *ma, const char *device_id) {
+    char *t;
+    const char *n;
+
+    pa_assert(data);
+    pa_assert(ma);
+    pa_assert(device_id);
+
+    if ((n = pa_modargs_get_value(ma, "card_name", NULL))) {
+        pa_card_new_data_set_name(data, n);
+        data->namereg_fail = TRUE;
+        return;
+    }
+
+    if ((n = pa_modargs_get_value(ma, "name", NULL)))
+        data->namereg_fail = TRUE;
+    else {
+        n = device_id;
+        data->namereg_fail = FALSE;
+    }
+
+    t = pa_sprintf_malloc("alsa_card.%s", n);
+    pa_card_new_data_set_name(data, t);
+    pa_xfree(t);
+}
+
 int pa__init(pa_module*m) {
     pa_card_new_data data;
     pa_modargs *ma;
@@ -224,7 +256,7 @@ int pa__init(pa_module*m) {
     data.module = m;
     pa_alsa_init_proplist_card(data.proplist, alsa_card_index);
     pa_proplist_sets(data.proplist, PA_PROP_DEVICE_STRING, u->device_id);
-    pa_card_new_data_set_name(&data, pa_modargs_get_value(ma, "name", u->device_id));
+    set_card_name(&data, ma, u->device_id);
 
     data.profiles = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func);
     if (pa_alsa_probe_profiles(u->device_id, &m->core->default_sample_spec, enumerate_cb, data.profiles) < 0) {
diff --git a/src/modules/alsa/module-alsa-sink.c b/src/modules/alsa/module-alsa-sink.c
index 6a66ad3..6cf48b5 100644
--- a/src/modules/alsa/module-alsa-sink.c
+++ b/src/modules/alsa/module-alsa-sink.c
@@ -38,6 +38,7 @@ PA_MODULE_DESCRIPTION("ALSA Sink");
 PA_MODULE_VERSION(PACKAGE_VERSION);
 PA_MODULE_LOAD_ONCE(FALSE);
 PA_MODULE_USAGE(
+        "name=<name of the sink, to be prefixed> "
         "sink_name=<name for the sink> "
         "device=<ALSA device> "
         "device_id=<ALSA card index> "
@@ -53,6 +54,7 @@ PA_MODULE_USAGE(
         "tsched_buffer_watermark=<lower fill watermark>");
 
 static const char* const valid_modargs[] = {
+    "name",
     "sink_name",
     "device",
     "device_id",
diff --git a/src/modules/alsa/module-alsa-source.c b/src/modules/alsa/module-alsa-source.c
index 7dc22fe..1e7c387 100644
--- a/src/modules/alsa/module-alsa-source.c
+++ b/src/modules/alsa/module-alsa-source.c
@@ -62,6 +62,7 @@ PA_MODULE_DESCRIPTION("ALSA Source");
 PA_MODULE_VERSION(PACKAGE_VERSION);
 PA_MODULE_LOAD_ONCE(FALSE);
 PA_MODULE_USAGE(
+        "name=<name for the source, to be prefixed> "
         "source_name=<name for the source> "
         "device=<ALSA device> "
         "device_id=<ALSA card index> "
@@ -77,6 +78,7 @@ PA_MODULE_USAGE(
         "tsched_buffer_watermark=<upper fill watermark>");
 
 static const char* const valid_modargs[] = {
+    "name",
     "source_name",
     "device",
     "device_id",

commit 4b2a6827419d8c45878c53eb6fa8f1424836d774
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Jan 22 00:24:28 2009 +0100

    fix minor memleak in prober

diff --git a/src/modules/alsa/alsa-util.c b/src/modules/alsa/alsa-util.c
index e154f6e..599079c 100644
--- a/src/modules/alsa/alsa-util.c
+++ b/src/modules/alsa/alsa-util.c
@@ -836,6 +836,8 @@ snd_pcm_t *pa_alsa_open_by_device_string(
 
         if (dev)
             *dev = d;
+        else
+            pa_xfree(d);
 
         if (ss->channels != map->channels)
             pa_channel_map_init_extend(map, ss->channels, PA_CHANNEL_MAP_ALSA);

commit b2ef19acc550dbfbd9e9a215fbda4cd9f8b0c977
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Jan 22 00:25:36 2009 +0100

    include PA_SINK_INVALID_STATE in all switch/case statements to make gcc shut up

diff --git a/src/modules/alsa/alsa-sink.c b/src/modules/alsa/alsa-sink.c
index 749396f..f092b5d 100644
--- a/src/modules/alsa/alsa-sink.c
+++ b/src/modules/alsa/alsa-sink.c
@@ -715,6 +715,7 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
 
                 case PA_SINK_UNLINKED:
                 case PA_SINK_INIT:
+                case PA_SINK_INVALID_STATE:
                     ;
             }
 
diff --git a/src/modules/alsa/alsa-source.c b/src/modules/alsa/alsa-source.c
index fe4eddb..0c4e5bc 100644
--- a/src/modules/alsa/alsa-source.c
+++ b/src/modules/alsa/alsa-source.c
@@ -661,6 +661,7 @@ static int source_process_msg(pa_msgobject *o, int code, void *data, int64_t off
 
                 case PA_SOURCE_UNLINKED:
                 case PA_SOURCE_INIT:
+                case PA_SOURCE_INVALID_STATE:
                     ;
             }
 
diff --git a/src/modules/module-combine.c b/src/modules/module-combine.c
index b1dc820..82c8871 100644
--- a/src/modules/module-combine.c
+++ b/src/modules/module-combine.c
@@ -627,6 +627,7 @@ static int sink_set_state(pa_sink *sink, pa_sink_state_t state) {
 
         case PA_SINK_UNLINKED:
         case PA_SINK_INIT:
+        case PA_SINK_INVALID_STATE:
             ;
     }
 
diff --git a/src/modules/module-esound-sink.c b/src/modules/module-esound-sink.c
index 7c7f828..f6b90a4 100644
--- a/src/modules/module-esound-sink.c
+++ b/src/modules/module-esound-sink.c
@@ -156,6 +156,7 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
 
                 case PA_SINK_UNLINKED:
                 case PA_SINK_INIT:
+                case PA_SINK_INVALID_STATE:
                     ;
             }
 
diff --git a/src/modules/module-raop-sink.c b/src/modules/module-raop-sink.c
index c324437..bb93ca8 100644
--- a/src/modules/module-raop-sink.c
+++ b/src/modules/module-raop-sink.c
@@ -195,6 +195,7 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
 
                 case PA_SINK_UNLINKED:
                 case PA_SINK_INIT:
+                case PA_SINK_INVALID_STATE:
                     ;
             }
 
diff --git a/src/modules/module-tunnel.c b/src/modules/module-tunnel.c
index a46d6e5..61b9516 100644
--- a/src/modules/module-tunnel.c
+++ b/src/modules/module-tunnel.c
@@ -494,6 +494,7 @@ static int sink_set_state(pa_sink *s, pa_sink_state_t state) {
 
         case PA_SINK_UNLINKED:
         case PA_SINK_INIT:
+        case PA_SINK_INVALID_STATE:
             ;
     }
 
@@ -581,6 +582,7 @@ static int source_set_state(pa_source *s, pa_source_state_t state) {
 
         case PA_SOURCE_UNLINKED:
         case PA_SOURCE_INIT:
+        case PA_SINK_INVALID_STATE:
             ;
     }
 
diff --git a/src/modules/oss/module-oss.c b/src/modules/oss/module-oss.c
index da9245a..b5b9e2a 100644
--- a/src/modules/oss/module-oss.c
+++ b/src/modules/oss/module-oss.c
@@ -681,6 +681,7 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
 
                     break;
 
+                case PA_SINK_INVALID_STATE:
                 case PA_SINK_UNLINKED:
                 case PA_SINK_INIT:
                     ;
@@ -762,6 +763,7 @@ static int source_process_msg(pa_msgobject *o, int code, void *data, int64_t off
 
                 case PA_SOURCE_UNLINKED:
                 case PA_SOURCE_INIT:
+                case PA_SOURCE_INVALID_STATE:
                     ;
 
             }

commit 3be4c31ee0f8bac99cec69ae97668333882fc1f8
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Jan 22 00:26:16 2009 +0100

    rework module-hal-detect and make it use module-alsa-card instead of module-alsa-sink/-source

diff --git a/configure.ac b/configure.ac
index 411a14d..1d891b7 100644
--- a/configure.ac
+++ b/configure.ac
@@ -876,7 +876,7 @@ AC_ARG_ENABLE([hal],
         ],
         [hal=auto])
 if test "x${hal}" != xno -a \( "x$HAVE_OSS" = "x1" -o "x$HAVE_ALSA" = "x1" \) ; then
-    PKG_CHECK_MODULES(HAL, [ hal >= 0.5.7 ],
+    PKG_CHECK_MODULES(HAL, [ hal >= 0.5.11 ],
         HAVE_HAL=1,
         [
             HAVE_HAL=0
diff --git a/src/modules/module-hal-detect.c b/src/modules/module-hal-detect.c
index e287a5d..309b006 100644
--- a/src/modules/module-hal-detect.c
+++ b/src/modules/module-hal-detect.c
@@ -66,9 +66,9 @@ PA_MODULE_USAGE("api=<oss>");
 #endif
 
 struct device {
-    uint32_t index;
-    char *udi;
-    char *sink_name, *source_name;
+    char *udi, *originating_udi;
+    char *card_name, *sink_name, *source_name;
+    uint32_t module;
     pa_bool_t acl_race_fix;
 };
 
@@ -76,18 +76,13 @@ struct userdata {
     pa_core *core;
     LibHalContext *context;
     pa_dbus_connection *connection;
-    pa_hashmap *devices;
+    pa_hashmap *devices; /* Every entry is indexed twice in this table: by the udi we found the device with and by the originating device's udi */
     const char *capability;
 #ifdef HAVE_ALSA
     pa_bool_t use_tsched;
 #endif
 };
 
-struct timerdata {
-    struct userdata *u;
-    char *udi;
-};
-
 #define CAPABILITY_ALSA "alsa"
 #define CAPABILITY_OSS "oss"
 
@@ -99,22 +94,22 @@ static const char* const valid_modargs[] = {
     NULL
 };
 
-static void hal_device_free(struct device* d) {
+static void device_free(struct device* d) {
     pa_assert(d);
 
     pa_xfree(d->udi);
+    pa_xfree(d->originating_udi);
     pa_xfree(d->sink_name);
     pa_xfree(d->source_name);
+    pa_xfree(d->card_name);
     pa_xfree(d);
 }
 
-static void hal_device_free_cb(void *d, void *data) {
-    hal_device_free(d);
-}
-
 static const char *strip_udi(const char *udi) {
     const char *slash;
 
+    pa_assert(udi);
+
     if ((slash = strrchr(udi, '/')))
         return slash+1;
 
@@ -123,405 +118,380 @@ static const char *strip_udi(const char *udi) {
 
 #ifdef HAVE_ALSA
 
-typedef enum {
-    ALSA_TYPE_SINK,
-    ALSA_TYPE_SOURCE,
-    ALSA_TYPE_OTHER,
-    ALSA_TYPE_MAX
-} alsa_type_t;
+enum alsa_type {
+    ALSA_TYPE_PLAYBACK,
+    ALSA_TYPE_CAPTURE,
+    ALSA_TYPE_OTHER
+};
 
-static alsa_type_t hal_alsa_device_get_type(LibHalContext *context, const char *udi, DBusError *error) {
+static enum alsa_type hal_alsa_device_get_type(LibHalContext *context, const char *udi) {
     char *type;
-    alsa_type_t t;
+    enum alsa_type t = ALSA_TYPE_OTHER;
+    DBusError error;
+
+    dbus_error_init(&error);
 
-    if (!(type = libhal_device_get_property_string(context, udi, "alsa.type", error)))
-        return ALSA_TYPE_OTHER;
+    pa_assert(context);
+    pa_assert(udi);
 
-    if (!strcmp(type, "playback"))
-        t = ALSA_TYPE_SINK;
-    else if (!strcmp(type, "capture"))
-        t = ALSA_TYPE_SOURCE;
-    else
-        t = ALSA_TYPE_OTHER;
+    if (!(type = libhal_device_get_property_string(context, udi, "alsa.type", &error)))
+        goto finish;
+
+    if (pa_streq(type, "playback"))
+        t = ALSA_TYPE_PLAYBACK;
+    else if (pa_streq(type, "capture"))
+        t = ALSA_TYPE_CAPTURE;
 
     libhal_free_string(type);
 
+finish:
+    if (dbus_error_is_set(&error)) {
+        pa_log_error("D-Bus error while parsing HAL ALSA data: %s: %s", error.name, error.message);
+        dbus_error_free(&error);
+    }
+
     return t;
 }
 
-static int hal_alsa_device_is_modem(LibHalContext *context, const char *udi, DBusError *error) {
+static pa_bool_t hal_alsa_device_is_modem(LibHalContext *context, const char *udi) {
     char *class;
-    int r;
+    pa_bool_t r = FALSE;
+    DBusError error;
 
-    if (!(class = libhal_device_get_property_string(context, udi, "alsa.pcm_class", error)))
-        return 0;
+    dbus_error_init(&error);
+
+    pa_assert(context);
+    pa_assert(udi);
+
+    if (!(class = libhal_device_get_property_string(context, udi, "alsa.pcm_class", &error)))
+        goto finish;
+
+    r = pa_streq(class, "modem");
+    libhal_free_string(class);
 
-    r = strcmp(class, "modem") == 0;
-    pa_xfree(class);
+finish:
+    if (dbus_error_is_set(&error)) {
+        pa_log_error("D-Bus error while parsing HAL ALSA data: %s: %s", error.name, error.message);
+        dbus_error_free(&error);
+    }
 
     return r;
 }
 
-static pa_module* hal_device_load_alsa(struct userdata *u, const char *udi, char **sink_name, char **source_name) {
-    char *args;
-    alsa_type_t type;
+static int hal_device_load_alsa(struct userdata *u, const char *udi, struct device *d) {
+    enum alsa_type type;
     int device, card;
-    const char *module_name;
     DBusError error;
     pa_module *m;
+    char *args, *originating_udi = NULL, *card_name = NULL;
 
     dbus_error_init(&error);
 
     pa_assert(u);
-    pa_assert(sink_name);
-    pa_assert(source_name);
+    pa_assert(udi);
+    pa_assert(d);
 
-    *sink_name = *source_name = NULL;
+    /* We only care for PCM devices */
+    type = hal_alsa_device_get_type(u->context, udi);
+    if (type == ALSA_TYPE_OTHER)
+        goto fail;
 
-    type = hal_alsa_device_get_type(u->context, udi, &error);
-    if (dbus_error_is_set(&error) || type == ALSA_TYPE_OTHER)
+    /* We don't care for modems */
+    if (hal_alsa_device_is_modem(u->context, udi))
         goto fail;
 
+    /* We only care for the main device */
     device = libhal_device_get_property_int(u->context, udi, "alsa.device", &error);
     if (dbus_error_is_set(&error) || device != 0)
         goto fail;
 
-    card = libhal_device_get_property_int(u->context, udi, "alsa.card", &error);
-    if (dbus_error_is_set(&error))
+    /* We store only one entry per card, hence we look for the originating device */
+    originating_udi = libhal_device_get_property_string(u->context, udi, "alsa.originating_device", &error);
+    if (dbus_error_is_set(&error) || !originating_udi)
         goto fail;
 
-    if (hal_alsa_device_is_modem(u->context, udi, &error))
+    /* Make sure we only load one module per card */
+    if (pa_hashmap_get(u->devices, originating_udi))
         goto fail;
 
-    if (type == ALSA_TYPE_SINK) {
-        *sink_name = pa_sprintf_malloc("alsa_output.%s", strip_udi(udi));
-
-        module_name = "module-alsa-sink";
-        args = pa_sprintf_malloc("device_id=%u sink_name=%s tsched=%i", card, *sink_name, (int) u->use_tsched);
-    } else {
-        *source_name = pa_sprintf_malloc("alsa_input.%s", strip_udi(udi));
-
-        module_name = "module-alsa-source";
-        args = pa_sprintf_malloc("device_id=%u source_name=%s tsched=%i", card, *source_name, (int) u->use_tsched);
-    }
-
-    pa_log_debug("Loading %s with arguments '%s'", module_name, args);
+    /* We need the identifier */
+    card = libhal_device_get_property_int(u->context, udi, "alsa.card", &error);
+    if (dbus_error_is_set(&error))
+        goto fail;
 
-    m = pa_module_load(u->core, module_name, args);
+    card_name = pa_sprintf_malloc("alsa_card.%s", strip_udi(originating_udi));
+    args = pa_sprintf_malloc("device_id=%u name=%s card_name=%s tsched=%i", card, strip_udi(originating_udi), card_name, (int) u->use_tsched);
 
+    pa_log_debug("Loading module-alsa-card with arguments '%s'", args);
+    m = pa_module_load(u->core, "module-alsa-card", args);
     pa_xfree(args);
 
-    if (!m) {
-        pa_xfree(*sink_name);
-        pa_xfree(*source_name);
-        *sink_name = *source_name = NULL;
-    }
+    if (!m)
+        goto fail;
+
+    d->originating_udi = originating_udi;
+    d->module = m->index;
+    d->card_name = card_name;
 
-    return m;
+    return 0;
 
 fail:
     if (dbus_error_is_set(&error)) {
-        pa_log_error("D-Bus error while parsing ALSA data: %s: %s", error.name, error.message);
+        pa_log_error("D-Bus error while parsing HAL ALSA data: %s: %s", error.name, error.message);
         dbus_error_free(&error);
     }
 
-    return NULL;
+    pa_xfree(originating_udi);
+    pa_xfree(card_name);
+
+    return -1;
 }
 
 #endif
 
 #ifdef HAVE_OSS
 
-static int hal_oss_device_is_pcm(LibHalContext *context, const char *udi, DBusError *error) {
+static pa_bool_t hal_oss_device_is_pcm(LibHalContext *context, const char *udi) {
     char *class = NULL, *dev = NULL, *e;
     int device;
-    int r = 0;
+    pa_bool_t r = FALSE;
+    DBusError error;
+
+    dbus_error_init(&error);
+
+    pa_assert(context);
+    pa_assert(udi);
 
-    class = libhal_device_get_property_string(context, udi, "oss.type", error);
-    if (dbus_error_is_set(error) || !class)
+    /* We only care for PCM devices */
+    class = libhal_device_get_property_string(context, udi, "oss.type", &error);
+    if (dbus_error_is_set(&error) || !class)
         goto finish;
 
-    if (strcmp(class, "pcm"))
+    if (!pa_streq(class, "pcm"))
         goto finish;
 
-    dev = libhal_device_get_property_string(context, udi, "oss.device_file", error);
-    if (dbus_error_is_set(error) || !dev)
+    /* We don't like /dev/audio */
+    dev = libhal_device_get_property_string(context, udi, "oss.device_file", &error);
+    if (dbus_error_is_set(&error) || !dev)
         goto finish;
 
     if ((e = strrchr(dev, '/')))
         if (pa_startswith(e + 1, "audio"))
             goto finish;
 
-    device = libhal_device_get_property_int(context, udi, "oss.device", error);
-    if (dbus_error_is_set(error) || device != 0)
+    /* We only care for the main device */
+    device = libhal_device_get_property_int(context, udi, "oss.device", &error);
+    if (dbus_error_is_set(&error) || device != 0)
         goto finish;
 
-    r = 1;
+    r = TRUE;
 
 finish:
 
+    if (dbus_error_is_set(&error)) {
+        pa_log_error("D-Bus error while parsing HAL OSS data: %s: %s", error.name, error.message);
+        dbus_error_free(&error);
+    }
+
     libhal_free_string(class);
     libhal_free_string(dev);
 
     return r;
 }
 
-static pa_module* hal_device_load_oss(struct userdata *u, const char *udi, char **sink_name, char **source_name) {
-    char* args;
-    char* device;
+static int hal_device_load_oss(struct userdata *u, const char *udi, struct device *d) {
     DBusError error;
     pa_module *m;
+    char *args, *originating_udi = NULL, *device, *sink_name = NULL, *source_name = NULL;
 
     dbus_error_init(&error);
 
     pa_assert(u);
-    pa_assert(sink_name);
-    pa_assert(source_name);
+    pa_assert(udi);
+    pa_assert(d);
+
+    /* We only care for OSS PCM devices */
+    if (!hal_oss_device_is_pcm(u->context, udi))
+        goto fail;
 
-    *sink_name = *source_name = NULL;
+    /* We store only one entry per card, hence we look for the originating device */
+    originating_udi = libhal_device_get_property_string(u->context, udi, "oss.originating_device", &error);
+    if (dbus_error_is_set(&error) || !originating_udi)
+        goto fail;
 
-    if (!hal_oss_device_is_pcm(u->context, udi, &error) || dbus_error_is_set(&error))
+    /* Make sure we only load one module per card */
+    if (pa_hashmap_get(u->devices, originating_udi))
         goto fail;
 
+    /* We need the device file */
     device = libhal_device_get_property_string(u->context, udi, "oss.device_file", &error);
     if (!device || dbus_error_is_set(&error))
         goto fail;
 
-    *sink_name = pa_sprintf_malloc("oss_output.%s", strip_udi(udi));
-    *source_name = pa_sprintf_malloc("oss_input.%s", strip_udi(udi));
+    sink_name = pa_sprintf_malloc("oss_output.%s", strip_udi(udi));
+    source_name = pa_sprintf_malloc("oss_input.%s", strip_udi(udi));
+    args = pa_sprintf_malloc("device=%s sink_name=%s source_name=%s", device, sink_name, source_name);
 
-    args = pa_sprintf_malloc("device=%s sink_name=%s source_name=%s", device, *sink_name, *source_name);
     libhal_free_string(device);
 
     pa_log_debug("Loading module-oss with arguments '%s'", args);
     m = pa_module_load(u->core, "module-oss", args);
     pa_xfree(args);
 
-    if (!m) {
-        pa_xfree(*sink_name);
-        pa_xfree(*source_name);
-        *sink_name = *source_name = NULL;
-    }
+    if (!m)
+        goto fail;
+
+    d->originating_udi = originating_udi;
+    d->module = m->index;
+    d->sink_name = sink_name;
+    d->source_name = source_name;
 
-    return m;
+    return 0;
 
 fail:
     if (dbus_error_is_set(&error)) {
-        pa_log_error("D-Bus error while parsing OSS data: %s: %s", error.name, error.message);
+        pa_log_error("D-Bus error while parsing OSS HAL data: %s: %s", error.name, error.message);
         dbus_error_free(&error);
     }
 
-    return NULL;
+    pa_xfree(originating_udi);
+    pa_xfree(source_name);
+    pa_xfree(sink_name);
+
+    return -1;
 }
 #endif
 
 static struct device* hal_device_add(struct userdata *u, const char *udi) {
-    pa_module* m = NULL;
     struct device *d;
-    char *sink_name = NULL, *source_name = NULL;
+    int r;
 
     pa_assert(u);
     pa_assert(u->capability);
-    pa_assert(!pa_hashmap_get(u->devices, udi));
+
+    d = pa_xnew(struct device, 1);
+    d->acl_race_fix = FALSE;
+    d->udi = pa_xstrdup(udi);
+    d->originating_udi = NULL;
+    d->module = PA_INVALID_INDEX;
+    d->sink_name = d->source_name = d->card_name = NULL;
 
 #ifdef HAVE_ALSA
-    if (strcmp(u->capability, CAPABILITY_ALSA) == 0)
-        m = hal_device_load_alsa(u, udi, &sink_name, &source_name);
+    if (pa_streq(u->capability, CAPABILITY_ALSA))
+        r = hal_device_load_alsa(u, udi,  d);
 #endif
 #ifdef HAVE_OSS
-    if (strcmp(u->capability, CAPABILITY_OSS) == 0)
-        m = hal_device_load_oss(u, udi, &sink_name, &source_name);
+    if (pa_streq(u->capability, CAPABILITY_OSS))
+        r = hal_device_load_oss(u, udi, d);
 #endif
 
-    if (!m)
+    if (r < 0) {
+        device_free(d);
         return NULL;
+    }
 
-    d = pa_xnew(struct device, 1);
-    d->acl_race_fix = FALSE;
-    d->udi = pa_xstrdup(udi);
-    d->index = m->index;
-    d->sink_name = sink_name;
-    d->source_name = source_name;
     pa_hashmap_put(u->devices, d->udi, d);
+    pa_hashmap_put(u->devices, d->originating_udi, d);
 
     return d;
 }
 
-static int hal_device_add_all(struct userdata *u, const char *capability) {
-    DBusError error;
-    int i, n, count = 0;
+static int hal_device_add_all(struct userdata *u) {
+    int n, count = 0;
     char** udis;
-
-    pa_assert(u);
+    DBusError error;
 
     dbus_error_init(&error);
 
-    if (u->capability && strcmp(u->capability, capability) != 0)
-        return 0;
-
-    pa_log_info("Trying capability %s", capability);
+    pa_assert(u);
 
-    udis = libhal_find_device_by_capability(u->context, capability, &n, &error);
-    if (dbus_error_is_set(&error)) {
-        pa_log_error("Error finding devices: %s: %s", error.name, error.message);
-        dbus_error_free(&error);
-        return -1;
-    }
+    udis = libhal_find_device_by_capability(u->context, u->capability, &n, &error);
+    if (dbus_error_is_set(&error) || !udis)
+        goto fail;
 
     if (n > 0) {
-        u->capability = capability;
+        int i;
 
         for (i = 0; i < n; i++) {
             struct device *d;
 
-            if (!(d = hal_device_add(u, udis[i])))
-                pa_log_debug("Not loaded device %s", udis[i]);
-            else {
-                if (d->sink_name)
-                    pa_scache_play_item_by_name(u->core, "pulse-coldplug", d->sink_name, PA_VOLUME_NORM, NULL, NULL);
+            if ((d = hal_device_add(u, udis[i])))
                 count++;
-            }
+            else
+                pa_log_debug("Not loaded device %s", udis[i]);
         }
     }
 
     libhal_free_string_array(udis);
-    return count;
-}
-
-static dbus_bool_t device_has_capability(LibHalContext *context, const char *udi, const char* cap, DBusError *error){
-    dbus_bool_t has_prop;
-
-    has_prop = libhal_device_property_exists(context, udi, "info.capabilities", error);
-    if (!has_prop || dbus_error_is_set(error))
-        return FALSE;
 
-    return libhal_device_query_capability(context, udi, cap, error);
-}
-
-static void device_added_time_cb(pa_mainloop_api *ea, pa_time_event *ev, const struct timeval *tv, void *userdata) {
-    DBusError error;
-    struct timerdata *td = userdata;
-
-    dbus_error_init(&error);
-
-    if (!pa_hashmap_get(td->u->devices, td->udi)) {
-        dbus_bool_t b;
-        struct device *d;
+    return count;
 
-        b = libhal_device_exists(td->u->context, td->udi, &error);
-
-        if (dbus_error_is_set(&error)) {
-            pa_log_error("Error adding device: %s: %s", error.name, error.message);
-            dbus_error_free(&error);
-        } else if (b) {
-            if (!(d = hal_device_add(td->u, td->udi)))
-                pa_log_debug("Not loaded device %s", td->udi);
-            else {
-                if (d->sink_name)
-                    pa_scache_play_item_by_name(td->u->core, "pulse-hotplug", d->sink_name, PA_VOLUME_NORM, NULL, NULL);
-            }
-        }
+fail:
+    if (dbus_error_is_set(&error)) {
+        pa_log_error("D-Bus error while parsing HAL data: %s: %s", error.name, error.message);
+        dbus_error_free(&error);
     }
 
-    pa_xfree(td->udi);
-    pa_xfree(td);
-    ea->time_free(ev);
+    return -1;
 }
 
 static void device_added_cb(LibHalContext *context, const char *udi) {
     DBusError error;
-    struct timeval tv;
-    struct timerdata *t;
     struct userdata *u;
     pa_bool_t good = FALSE;
 
-    pa_assert_se(u = libhal_ctx_get_user_data(context));
-
-    if (pa_hashmap_get(u->devices, udi))
-        return;
-
-    pa_log_debug("HAL Device added: %s", udi);
-
     dbus_error_init(&error);
 
-    if (u->capability) {
-
-        good = device_has_capability(context, udi, u->capability, &error);
-
-        if (dbus_error_is_set(&error)) {
-            pa_log_error("Error getting capability: %s: %s", error.name, error.message);
-            dbus_error_free(&error);
-            return;
-        }
-
-    } else {
-
-#ifdef HAVE_ALSA
-        good = device_has_capability(context, udi, CAPABILITY_ALSA, &error);
-
-        if (dbus_error_is_set(&error)) {
-            pa_log_error("Error getting capability: %s: %s", error.name, error.message);
-            dbus_error_free(&error);
-            return;
-        }
+    pa_assert(context);
+    pa_assert(udi);
 
-        if (good)
-            u->capability = CAPABILITY_ALSA;
-#endif
-#if defined(HAVE_OSS) && defined(HAVE_ALSA)
-        if (!good) {
-#endif
-#ifdef HAS_OSS
-            good = device_has_capability(context, udi, CAPABILITY_OSS, &error);
+    pa_assert_se(u = libhal_ctx_get_user_data(context));
 
-            if (dbus_error_is_set(&error)) {
-                pa_log_error("Error getting capability: %s: %s", error.name, error.message);
-                dbus_error_free(&error);
-                return;
-            }
+    good = libhal_device_query_capability(context, udi, u->capability, &error);
+    if (dbus_error_is_set(&error) || !good)
+        goto finish;
 
-            if (good)
-                u->capability = CAPABILITY_OSS;
+    if (!hal_device_add(u, udi))
+        pa_log_debug("Not loaded device %s", udi);
 
-#endif
-#if defined(HAVE_OSS) && defined(HAVE_ALSA)
-        }
-#endif
+finish:
+    if (dbus_error_is_set(&error)) {
+        pa_log_error("D-Bus error while parsing HAL data: %s: %s", error.name, error.message);
+        dbus_error_free(&error);
     }
-
-    if (!good)
-        return;
-
-    /* actually add the device 1/2 second later */
-    t = pa_xnew(struct timerdata, 1);
-    t->u = u;
-    t->udi = pa_xstrdup(udi);
-
-    pa_gettimeofday(&tv);
-    pa_timeval_add(&tv, 500000);
-    u->core->mainloop->time_new(u->core->mainloop, &tv, device_added_time_cb, t);
 }
 
 static void device_removed_cb(LibHalContext* context, const char *udi) {
     struct device *d;
     struct userdata *u;
 
+    pa_assert(context);
+    pa_assert(udi);
+
     pa_assert_se(u = libhal_ctx_get_user_data(context));
 
-    pa_log_debug("Device removed: %s", udi);
+    if (!(d = pa_hashmap_get(u->devices, udi)))
+        return;
+
+    pa_hashmap_remove(u->devices, d->originating_udi);
+    pa_hashmap_remove(u->devices, d->udi);
 
-    if ((d = pa_hashmap_remove(u->devices, udi))) {
-        pa_module_unload_request_by_index(u->core, d->index, TRUE);
-        hal_device_free(d);
-    }
+    pa_log_debug("Removing HAL device: %s", d->originating_udi);
+
+    pa_module_unload_request_by_index(u->core, d->module, TRUE);
+    device_free(d);
 }
 
 static void new_capability_cb(LibHalContext *context, const char *udi, const char* capability) {
     struct userdata *u;
 
+    pa_assert(context);
+    pa_assert(udi);
+    pa_assert(capability);
+
     pa_assert_se(u = libhal_ctx_get_user_data(context));
 
-    if (!u->capability || strcmp(u->capability, capability) == 0)
+    if (pa_streq(u->capability, capability))
         /* capability we care about, pretend it's a new device */
         device_added_cb(context, udi);
 }
@@ -529,20 +499,24 @@ static void new_capability_cb(LibHalContext *context, const char *udi, const cha
 static void lost_capability_cb(LibHalContext *context, const char *udi, const char* capability) {
     struct userdata *u;
 
+    pa_assert(context);
+    pa_assert(udi);
+    pa_assert(capability);
+
     pa_assert_se(u = libhal_ctx_get_user_data(context));
 
-    if (u->capability && strcmp(u->capability, capability) == 0)
+    if (pa_streq(u->capability, capability))
         /* capability we care about, pretend it was removed */
         device_removed_cb(context, udi);
 }
 
 static DBusHandlerResult filter_cb(DBusConnection *bus, DBusMessage *message, void *userdata) {
-    struct userdata*u = userdata;
+    struct userdata*u;
     DBusError error;
 
     pa_assert(bus);
     pa_assert(message);
-    pa_assert(u);
+    pa_assert_se(u = userdata);
 
     dbus_error_init(&error);
 
@@ -554,13 +528,14 @@ static DBusHandlerResult filter_cb(DBusConnection *bus, DBusMessage *message, vo
     if (dbus_message_is_signal(message, "org.freedesktop.Hal.Device.AccessControl", "ACLAdded") ||
         dbus_message_is_signal(message, "org.freedesktop.Hal.Device.AccessControl", "ACLRemoved")) {
         uint32_t uid;
-        int suspend = strcmp(dbus_message_get_member(message), "ACLRemoved") == 0;
+        pa_bool_t suspend = strcmp(dbus_message_get_member(message), "ACLRemoved") == 0;
 
         if (!dbus_message_get_args(message, &error, DBUS_TYPE_UINT32, &uid, DBUS_TYPE_INVALID) || dbus_error_is_set(&error)) {
             pa_log_error("Failed to parse ACL message: %s: %s", error.name, error.message);
             goto finish;
         }
 
+        /* Check if this is about us? */
         if (uid == getuid() || uid == geteuid()) {
             struct device *d;
             const char *udi;
@@ -569,27 +544,18 @@ static DBusHandlerResult filter_cb(DBusConnection *bus, DBusMessage *message, vo
 
             if ((d = pa_hashmap_get(u->devices, udi))) {
                 pa_bool_t send_acl_race_fix_message = FALSE;
-
                 d->acl_race_fix = FALSE;
 
                 if (d->sink_name) {
                     pa_sink *sink;
 
                     if ((sink = pa_namereg_get(u->core, d->sink_name, PA_NAMEREG_SINK))) {
-                        int prev_suspended = pa_sink_get_state(sink) == PA_SINK_SUSPENDED;
-
-                        if (prev_suspended && !suspend) {
-                            /* resume */
-                            if (pa_sink_suspend(sink, 0) >= 0)
-                                pa_scache_play_item_by_name(u->core, "pulse-access", d->sink_name, PA_VOLUME_NORM, NULL, NULL);
-                            else
-                                d->acl_race_fix = TRUE;
-
-                        } else if (!prev_suspended && suspend) {
-                            /* suspend */
-                            if (pa_sink_suspend(sink, 1) >= 0)
-                                send_acl_race_fix_message = TRUE;
-                        }
+                        pa_bool_t success = pa_sink_suspend(sink, suspend) >= 0;
+
+                        if (!success && !suspend)
+                            d->acl_race_fix = TRUE; /* resume failed, let's try again */
+                        else if (suspend)
+                            send_acl_race_fix_message = TRUE; /* suspend finished, let's tell everyone to try again */
                     }
                 }
 
@@ -597,18 +563,25 @@ static DBusHandlerResult filter_cb(DBusConnection *bus, DBusMessage *message, vo
                     pa_source *source;
 
                     if ((source = pa_namereg_get(u->core, d->source_name, PA_NAMEREG_SOURCE))) {
-                        int prev_suspended = pa_source_get_state(source) == PA_SOURCE_SUSPENDED;
-
-                        if (prev_suspended && !suspend) {
-                            /* resume */
-                            if (pa_source_suspend(source, 0) < 0)
-                                d->acl_race_fix = TRUE;
-
-                        } else if (!prev_suspended && suspend) {
-                            /* suspend */
-                            if (pa_source_suspend(source, 0) >= 0)
-                                send_acl_race_fix_message = TRUE;
-                        }
+                        pa_bool_t success = pa_source_suspend(source, suspend) >= 0;
+
+                        if (!success && !suspend)
+                            d->acl_race_fix = TRUE; /* resume failed, let's try again */
+                        else if (suspend)
+                            send_acl_race_fix_message = TRUE; /* suspend finished, let's tell everyone to try again */
+                    }
+                }
+
+                if (d->card_name) {
+                    pa_card *card;
+
+                    if ((card = pa_namereg_get(u->core, d->card_name, PA_NAMEREG_CARD))) {
+                        pa_bool_t success = pa_card_suspend(card, suspend) >= 0;
+
+                        if (!success && !suspend)
+                            d->acl_race_fix = TRUE; /* resume failed, let's try again */
+                        else if (suspend)
+                            send_acl_race_fix_message = TRUE; /* suspend finished, let's tell everyone to try again */
                     }
                 }
 
@@ -621,6 +594,7 @@ static DBusHandlerResult filter_cb(DBusConnection *bus, DBusMessage *message, vo
 
             } else if (!suspend)
                 device_added_cb(u->context, udi);
+
         }
 
         return DBUS_HANDLER_RESULT_HANDLED;
@@ -631,40 +605,36 @@ static DBusHandlerResult filter_cb(DBusConnection *bus, DBusMessage *message, vo
            sever has closed the device. We can remove this as
            soon as HAL learns frevoke() */
 
-        const char *udi;
         struct device *d;
+        const char *udi;
 
         udi = dbus_message_get_path(message);
 
-        if ((d = pa_hashmap_get(u->devices, udi)) && d->acl_race_fix) {
-            pa_log_debug("Got dirty give up message for '%s', trying resume ...", udi);
-
-            d->acl_race_fix = FALSE;
-
-            if (d->sink_name) {
-                pa_sink *sink;
+        if ((d = pa_hashmap_get(u->devices, udi))) {
 
-                if ((sink = pa_namereg_get(u->core, d->sink_name, PA_NAMEREG_SINK))) {
+            if (d->acl_race_fix) {
+                d->acl_race_fix = FALSE;
+                pa_log_debug("Got dirty give up message for '%s', trying resume ...", udi);
 
-                    int prev_suspended = pa_sink_get_state(sink) == PA_SINK_SUSPENDED;
+                if (d->sink_name) {
+                    pa_sink *sink;
 
-                    if (prev_suspended) {
-                        /* resume */
-                        if (pa_sink_suspend(sink, 0) >= 0)
-                            pa_scache_play_item_by_name(u->core, "pulse-access", d->sink_name, PA_VOLUME_NORM, NULL, NULL);
-                    }
+                    if ((sink = pa_namereg_get(u->core, d->sink_name, PA_NAMEREG_SINK)))
+                        pa_sink_suspend(sink, FALSE);
                 }
-            }
 
-            if (d->source_name) {
-                pa_source *source;
+                if (d->source_name) {
+                    pa_source *source;
 
-                if ((source = pa_namereg_get(u->core, d->source_name, PA_NAMEREG_SOURCE))) {
+                    if ((source = pa_namereg_get(u->core, d->source_name, PA_NAMEREG_SOURCE)))
+                        pa_source_suspend(source, FALSE);
+                }
 
-                    int prev_suspended = pa_source_get_state(source) == PA_SOURCE_SUSPENDED;
+                if (d->card_name) {
+                    pa_card *card;
 
-                    if (prev_suspended)
-                        pa_source_suspend(source, 0);
+                    if ((card = pa_namereg_get(u->core, d->source_name, PA_NAMEREG_CARD)))
+                        pa_card_suspend(card, FALSE);
                 }
             }
 
@@ -692,18 +662,20 @@ static void hal_context_free(LibHalContext* hal_context) {
     dbus_error_free(&error);
 }
 
-static LibHalContext* hal_context_new(pa_core* c, DBusConnection *conn) {
+static LibHalContext* hal_context_new(DBusConnection *connection) {
     DBusError error;
     LibHalContext *hal_context = NULL;
 
     dbus_error_init(&error);
 
+    pa_assert(connection);
+
     if (!(hal_context = libhal_ctx_new())) {
         pa_log_error("libhal_ctx_new() failed");
         goto fail;
     }
 
-    if (!libhal_ctx_set_dbus_connection(hal_context, conn)) {
+    if (!libhal_ctx_set_dbus_connection(hal_context, connection)) {
         pa_log_error("Error establishing DBUS connection: %s: %s", error.name, error.message);
         goto fail;
     }
@@ -726,13 +698,10 @@ fail:
 
 int pa__init(pa_module*m) {
     DBusError error;
-    pa_dbus_connection *conn;
     struct userdata *u = NULL;
-    LibHalContext *hal_context = NULL;
     int n = 0;
     pa_modargs *ma;
     const char *api;
-    pa_bool_t use_tsched = TRUE;
 
     pa_assert(m);
 
@@ -743,90 +712,74 @@ int pa__init(pa_module*m) {
         goto fail;
     }
 
-    if (pa_modargs_get_value_boolean(ma, "tsched", &use_tsched) < 0) {
+    m->userdata = u = pa_xnew(struct userdata, 1);
+    u->core = m->core;
+    u->context = NULL;
+    u->connection = NULL;
+    u->devices = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func);
+    u->capability = NULL;
+
+#ifdef HAVE_ALSA
+    u->use_tsched = TRUE;
+
+    if (pa_modargs_get_value_boolean(ma, "tsched", &u->use_tsched) < 0) {
         pa_log("Failed to parse tsched argument.");
         goto fail;
     }
 
-    if ((api = pa_modargs_get_value(ma, "api", NULL))) {
-        pa_bool_t good = FALSE;
+    api = pa_modargs_get_value(ma, "api", "alsa");
 
-#ifdef HAVE_ALSA
-        if (strcmp(api, CAPABILITY_ALSA) == 0) {
-            good = TRUE;
-            api = CAPABILITY_ALSA;
-        }
+    if (pa_streq(api, "alsa"))
+        u->capability = CAPABILITY_ALSA;
+#else
+    api = pa_modargs_get_value(ma, "api", "oss");
 #endif
+
 #ifdef HAVE_OSS
-        if (strcmp(api, CAPABILITY_OSS) == 0) {
-            good = TRUE;
-            api = CAPABILITY_OSS;
-        }
+    if (pa_streq(api, "oss"))
+        u->capability = CAPABILITY_OSS;
 #endif
 
-        if (!good) {
-            pa_log_error("Invalid API specification.");
-            goto fail;
-        }
+    if (!u->capability) {
+        pa_log_error("Invalid API specification.");
+        goto fail;
     }
 
-    if (!(conn = pa_dbus_bus_get(m->core, DBUS_BUS_SYSTEM, &error)) || dbus_error_is_set(&error)) {
-        if (conn)
-            pa_dbus_connection_unref(conn);
+    if (!(u->connection = pa_dbus_bus_get(m->core, DBUS_BUS_SYSTEM, &error)) || dbus_error_is_set(&error)) {
         pa_log_error("Unable to contact DBUS system bus: %s: %s", error.name, error.message);
         goto fail;
     }
 
-    if (!(hal_context = hal_context_new(m->core, pa_dbus_connection_get(conn)))) {
+    if (!(u->context = hal_context_new(pa_dbus_connection_get(u->connection)))) {
         /* pa_hal_context_new() logs appropriate errors */
-        pa_dbus_connection_unref(conn);
         goto fail;
     }
 
-    u = pa_xnew(struct userdata, 1);
-    u->core = m->core;
-    u->context = hal_context;
-    u->connection = conn;
-    u->devices = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func);
-    u->capability = api;
-#ifdef HAVE_ALSA
-    u->use_tsched = use_tsched;
-#endif
-    m->userdata = u;
+    n = hal_device_add_all(u);
 
-#ifdef HAVE_ALSA
-    n = hal_device_add_all(u, CAPABILITY_ALSA);
-#endif
-#if defined(HAVE_ALSA) && defined(HAVE_OSS)
-    if (n <= 0)
-#endif
-#ifdef HAVE_OSS
-        n += hal_device_add_all(u, CAPABILITY_OSS);
-#endif
+    libhal_ctx_set_user_data(u->context, u);
+    libhal_ctx_set_device_added(u->context, device_added_cb);
+    libhal_ctx_set_device_removed(u->context, device_removed_cb);
+    libhal_ctx_set_device_new_capability(u->context, new_capability_cb);
+    libhal_ctx_set_device_lost_capability(u->context, lost_capability_cb);
 
-    libhal_ctx_set_user_data(hal_context, u);
-    libhal_ctx_set_device_added(hal_context, device_added_cb);
-    libhal_ctx_set_device_removed(hal_context, device_removed_cb);
-    libhal_ctx_set_device_new_capability(hal_context, new_capability_cb);
-    libhal_ctx_set_device_lost_capability(hal_context, lost_capability_cb);
-
-    if (!libhal_device_property_watch_all(hal_context, &error)) {
+    if (!libhal_device_property_watch_all(u->context, &error)) {
         pa_log_error("Error monitoring device list: %s: %s", error.name, error.message);
         goto fail;
     }
 
-    if (!dbus_connection_add_filter(pa_dbus_connection_get(conn), filter_cb, u, NULL)) {
+    if (!dbus_connection_add_filter(pa_dbus_connection_get(u->connection), filter_cb, u, NULL)) {
         pa_log_error("Failed to add filter function");
         goto fail;
     }
 
-    dbus_bus_add_match(pa_dbus_connection_get(conn), "type='signal',sender='org.freedesktop.Hal', interface='org.freedesktop.Hal.Device.AccessControl'", &error);
+    dbus_bus_add_match(pa_dbus_connection_get(u->connection), "type='signal',sender='org.freedesktop.Hal', interface='org.freedesktop.Hal.Device.AccessControl'", &error);
     if (dbus_error_is_set(&error)) {
         pa_log_error("Unable to subscribe to HAL ACL signals: %s: %s", error.name, error.message);
         goto fail;
     }
 
-    dbus_bus_add_match(pa_dbus_connection_get(conn), "type='signal',interface='org.pulseaudio.Server'", &error);
+    dbus_bus_add_match(pa_dbus_connection_get(u->connection), "type='signal',interface='org.pulseaudio.Server'", &error);
     if (dbus_error_is_set(&error)) {
         pa_log_error("Unable to subscribe to PulseAudio signals: %s: %s", error.name, error.message);
         goto fail;
@@ -860,8 +813,17 @@ void pa__done(pa_module *m) {
     if (u->context)
         hal_context_free(u->context);
 
-    if (u->devices)
-        pa_hashmap_free(u->devices, hal_device_free_cb, NULL);
+    if (u->devices) {
+        struct device *d;
+
+        while ((d = pa_hashmap_first(u->devices))) {
+            pa_hashmap_remove(u->devices, d->udi);
+            pa_hashmap_remove(u->devices, d->originating_udi);
+            device_free(d);
+        }
+
+        pa_hashmap_free(u->devices, NULL, NULL);
+    }
 
     if (u->connection) {
         DBusError error;

-- 
hooks/post-receive
PulseAudio Sound Server



More information about the pulseaudio-commits mailing list