[pulseaudio-commits] [SCM] PulseAudio Sound Server branch, master, updated. v0.9.15-test1-38-g84666db

Lennart Poettering gitmailer-noreply at 0pointer.de
Wed Feb 11 19:00:50 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  5d154255cbab0726ab30ec1f9e0b745face778fa (commit)

- Log -----------------------------------------------------------------
84666db... properly free modargs object when init fails; don't abbreviate modargs in struct
a371306... tabs are evil
a7b992f... some minor fixups
6ada8d1... instead of reparsing the rate module argument when changing profile, simply restore the originally requested sample_spec, this also makes sure the channel count is properly reset
752f815... addendum to f56da9893: don't crash when s->sink is NULL
1837a96... call _kill functions instead of _unlink since the latter should only be called be the stream implementor
f0cc23d... Merge commit 'elmarco/bt-wip'
86bec09... pulsecore: add PA_CORE_HOOK_*_MOVE_FAIL
f56da98... suspend-on-idle: don't crash when so->source is NULL
cce4359... bluetooth: reinitialize the sample spec when switching profile
cac0f9e... bluetooth: export nrec
452e2b9... bluetooth: suspend SCO state when over PCM
c8a240c... bluetooth: SCO over PCM
b35ae7f... bluetooth: reconnect to audio service when switching profile
539abc3... bluetooth: typo
-----------------------------------------------------------------------

Summary of changes:
 src/modules/bluetooth/module-bluetooth-device.c   |  294 ++++++++++++++++-----
 src/modules/bluetooth/module-bluetooth-discover.c |   31 ++-
 src/modules/module-suspend-on-idle.c              |    6 +
 src/pulsecore/core.h                              |    2 +
 src/pulsecore/sink.c                              |    8 +-
 src/pulsecore/source.c                            |    8 +-
 6 files changed, 271 insertions(+), 78 deletions(-)

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

commit 539abc365f8e12a5241694920a2e09e0bfe05710
Author: Marc-André Lureau <marcandre.lureau at gmail.com>
Date:   Mon Feb 2 11:06:31 2009 +0200

    bluetooth: typo

diff --git a/src/modules/bluetooth/module-bluetooth-discover.c b/src/modules/bluetooth/module-bluetooth-discover.c
index f9540b3..0523648 100644
--- a/src/modules/bluetooth/module-bluetooth-discover.c
+++ b/src/modules/bluetooth/module-bluetooth-discover.c
@@ -123,7 +123,7 @@ int pa__init(pa_module* m) {
     }
 
     if (pa_modargs_get_value_boolean(ma, "async", &async) < 0) {
-        pa_log("Failed to parse tsched argument.");
+        pa_log("Failed to parse async argument.");
         goto fail;
     }
 

commit b35ae7f53116949d0cf5d991883e3b54f2c48aa5
Author: Marc-André Lureau <marcandre.lureau at gmail.com>
Date:   Mon Feb 9 22:11:46 2009 +0200

    bluetooth: reconnect to audio service when switching profile
    
    Currently, Bluez audio service crash when reusing the same control
    socket to switch to different profiles. This typically happen when
    first switching from HSP to A2DP on dual headsets.

diff --git a/src/modules/bluetooth/module-bluetooth-device.c b/src/modules/bluetooth/module-bluetooth-device.c
index de6bded..0067d91 100644
--- a/src/modules/bluetooth/module-bluetooth-device.c
+++ b/src/modules/bluetooth/module-bluetooth-device.c
@@ -1282,6 +1282,19 @@ static int add_source(struct userdata *u) {
 static int init_bt(struct userdata *u) {
     pa_assert(u);
 
+    /* shutdown bt */
+    if (u->stream_fd >= 0) {
+        pa_close(u->stream_fd);
+        u->stream_fd = -1;
+    }
+
+    if (u->service_fd >= 0) {
+        pa_close(u->service_fd);
+        u->service_fd = -1;
+    }
+
+    u->write_type = u->read_type = 0;
+
     /* connect to the bluez audio service */
     if ((u->service_fd = bt_audio_service_open()) < 0) {
         pa_log_error("Couldn't connect to bluetooth audio service");
@@ -1292,17 +1305,6 @@ static int init_bt(struct userdata *u) {
     return 0;
 }
 
-static void shutdown_bt(struct userdata *u) {
-    pa_assert(u);
-
-    if (u->stream_fd <= 0) {
-        pa_close(u->stream_fd);
-        u->stream_fd = -1;
-    }
-
-    u->write_type = u->read_type = 0;
-}
-
 static int setup_bt(struct userdata *u) {
     pa_assert(u);
 
@@ -1417,7 +1419,7 @@ static int card_set_profile(pa_card *c, pa_card_profile *new_profile) {
     }
 
     stop_thread(u);
-    shutdown_bt(u);
+    init_bt(u);
 
     if (u->write_memchunk.memblock) {
         pa_memblock_unref(u->write_memchunk.memblock);

commit c8a240cddd23eba83c4d3fc901fe2e42a871823f
Author: Marc-André Lureau <marcandre.lureau at gmail.com>
Date:   Tue Feb 3 17:15:41 2009 +0200

    bluetooth: SCO over PCM

diff --git a/src/modules/bluetooth/module-bluetooth-device.c b/src/modules/bluetooth/module-bluetooth-device.c
index 0067d91..2302b1d 100644
--- a/src/modules/bluetooth/module-bluetooth-device.c
+++ b/src/modules/bluetooth/module-bluetooth-device.c
@@ -43,6 +43,7 @@
 #include <pulsecore/rtpoll.h>
 #include <pulsecore/time-smoother.h>
 #include <pulsecore/rtclock.h>
+#include <pulsecore/namereg.h>
 
 #include <modules/dbus-util.h>
 
@@ -71,7 +72,9 @@ PA_MODULE_USAGE(
         "profile=<a2dp|hsp> "
         "rate=<sample rate> "
         "channels=<number of channels> "
-        "path=<device object path>");
+        "path=<device object path> "
+	"sco_sink=<SCO over PCM sink name> "
+	"sco_source=<SCO over PCM source name>");
 
 static const char* const valid_modargs[] = {
     "name",
@@ -83,6 +86,8 @@ static const char* const valid_modargs[] = {
     "rate",
     "channels",
     "path",
+    "sco_sink",
+    "sco_source",
     NULL
 };
 
@@ -98,6 +103,11 @@ struct a2dp_info {
     uint16_t seq_num;                    /* Cumulative packet sequence */
 };
 
+struct hsp_info {
+    pa_sink *sco_sink;
+    pa_source *sco_source;
+};
+
 enum profile {
     PROFILE_A2DP,
     PROFILE_HSP,
@@ -132,6 +142,7 @@ struct userdata {
     size_t block_size;
 
     struct a2dp_info a2dp;
+    struct hsp_info hsp;
     pa_dbus_connection *connection;
 
     enum profile profile;
@@ -1215,67 +1226,97 @@ static char *get_name(const char *type, pa_modargs *ma, const char *device_id, p
     return pa_sprintf_malloc("bluez_%s.%s", type, n);
 }
 
+#define USE_SCO_OVER_PCM(u) (u->profile == PROFILE_HSP && (u->hsp.sco_sink && u->hsp.sco_source))
+
 static int add_sink(struct userdata *u) {
-    pa_sink_new_data data;
-    pa_bool_t b;
 
-    pa_sink_new_data_init(&data);
-    data.driver = __FILE__;
-    data.module = u->module;
-    pa_sink_new_data_set_sample_spec(&data, &u->sample_spec);
-    pa_proplist_sets(data.proplist, "bluetooth.protocol", u->profile == PROFILE_A2DP ? "a2dp" : "sco");
-    data.card = u->card;
-    data.name = get_name("sink", u->modargs, u->device->address, &b);
-    data.namereg_fail = b;
+    if (USE_SCO_OVER_PCM(u)) {
+        pa_proplist *p;
 
-    u->sink = pa_sink_new(u->core, &data, PA_SINK_HARDWARE|PA_SINK_LATENCY);
-    pa_sink_new_data_done(&data);
+        u->sink = u->hsp.sco_sink;
+        u->sink->card = u->card; /* FIXME! */
+        p = pa_proplist_new();
+        pa_proplist_sets(p, "bluetooth.protocol", "sco");
+        pa_proplist_update(u->sink->proplist, PA_UPDATE_MERGE, p);
+        pa_proplist_free(p);
 
-    if (!u->sink) {
-        pa_log_error("Failed to create sink");
-        return -1;
+    } else {
+        pa_sink_new_data data;
+        pa_bool_t b;
+
+        pa_sink_new_data_init(&data);
+        data.driver = __FILE__;
+        data.module = u->module;
+        pa_sink_new_data_set_sample_spec(&data, &u->sample_spec);
+        pa_proplist_sets(data.proplist, "bluetooth.protocol", u->profile == PROFILE_A2DP ? "a2dp" : "sco");
+        data.card = u->card;
+        data.name = get_name("sink", u->modargs, u->device->address, &b);
+        data.namereg_fail = b;
+
+        u->sink = pa_sink_new(u->core, &data, PA_SINK_HARDWARE|PA_SINK_LATENCY);
+        pa_sink_new_data_done(&data);
+
+        if (!u->sink) {
+            pa_log_error("Failed to create sink");
+            return -1;
+        }
+
+        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);
     }
 
-    u->sink->userdata = u;
-    u->sink->parent.process_msg = sink_process_msg;
 /*     u->sink->get_volume = sink_get_volume_cb; */
 /*     u->sink->set_volume = sink_set_volume_cb; */
 
-    pa_sink_set_asyncmsgq(u->sink, u->thread_mq.inq);
-    pa_sink_set_rtpoll(u->sink, u->rtpoll);
-
     return 0;
 }
 
 static int add_source(struct userdata *u) {
-    pa_source_new_data data;
-    pa_bool_t b;
 
-    pa_source_new_data_init(&data);
-    data.driver = __FILE__;
-    data.module = u->module;
-    pa_source_new_data_set_sample_spec(&data, &u->sample_spec);
-    pa_proplist_sets(data.proplist, "bluetooth.protocol", u->profile == PROFILE_A2DP ? "a2dp" : "sco");
-    data.card = u->card;
-    data.name = get_name("source", u->modargs, u->device->address, &b);
-    data.namereg_fail = b;
+    if (USE_SCO_OVER_PCM(u)) {
+        pa_proplist *p;
 
-    u->source = pa_source_new(u->core, &data, PA_SOURCE_HARDWARE|PA_SOURCE_LATENCY);
-    pa_source_new_data_done(&data);
+        u->source = u->hsp.sco_source;
+        u->source->card = u->card; /* FIXME! */
+        p = pa_proplist_new();
+        pa_proplist_sets(p, "bluetooth.protocol", "sco");
+        pa_proplist_update(u->source->proplist, PA_UPDATE_MERGE, p);
+        pa_proplist_free(p);
 
-    if (!u->source) {
-        pa_log_error("Failed to create source");
-        return -1;
+    } else {
+        pa_source_new_data data;
+        pa_bool_t b;
+
+        pa_source_new_data_init(&data);
+        data.driver = __FILE__;
+        data.module = u->module;
+        pa_source_new_data_set_sample_spec(&data, &u->sample_spec);
+        pa_proplist_sets(data.proplist, "bluetooth.protocol", u->profile == PROFILE_A2DP ? "a2dp" : "sco");
+        data.card = u->card;
+        data.name = get_name("source", u->modargs, u->device->address, &b);
+        data.namereg_fail = b;
+
+        u->source = pa_source_new(u->core, &data, PA_SOURCE_HARDWARE|PA_SOURCE_LATENCY);
+        pa_source_new_data_done(&data);
+
+        if (!u->source) {
+            pa_log_error("Failed to create source");
+            return -1;
+        }
+
+        u->source->userdata = u;
+        u->source->parent.process_msg = source_process_msg;
+
+        pa_source_set_asyncmsgq(u->source, u->thread_mq.inq);
+        pa_source_set_rtpoll(u->source, u->rtpoll);
     }
 
-    u->source->userdata = u;
-    u->source->parent.process_msg = source_process_msg;
 /*     u->source->get_volume = source_get_volume_cb; */
 /*     u->source->set_volume = source_set_volume_cb; */
 
-    pa_source_set_asyncmsgq(u->source, u->thread_mq.inq);
-    pa_source_set_rtpoll(u->source, u->rtpoll);
-
     return 0;
 }
 
@@ -1318,6 +1359,11 @@ static int setup_bt(struct userdata *u) {
 
     pa_log_debug("Connection to the device configured");
 
+    if (USE_SCO_OVER_PCM(u)) {
+        pa_log_debug("Configured to use SCO over PCM");
+        return 0;
+    }
+
     if (setup_stream_fd(u) < 0)
         return -1;
 
@@ -1377,6 +1423,12 @@ static int start_thread(struct userdata *u) {
     pa_assert(!u->thread);
     pa_assert(!u->rtpoll_item);
 
+    if (USE_SCO_OVER_PCM(u)) {
+        pa_sink_ref(u->sink);
+        pa_source_ref(u->source);
+        return 0;
+    }
+
     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;
@@ -1410,12 +1462,14 @@ static int card_set_profile(pa_card *c, pa_card_profile *new_profile) {
 
     if (u->sink) {
         inputs = pa_sink_move_all_start(u->sink);
-        pa_sink_unlink(u->sink);
+	if (!USE_SCO_OVER_PCM(u))
+            pa_sink_unlink(u->sink);
     }
 
     if (u->source) {
         outputs = pa_source_move_all_start(u->source);
-        pa_source_unlink(u->source);
+	if (!USE_SCO_OVER_PCM(u))
+            pa_source_unlink(u->source);
     }
 
     stop_thread(u);
@@ -1604,6 +1658,18 @@ int pa__init(pa_module* m) {
     u->sample_spec = m->core->default_sample_spec;
     u->modargs = ma;
 
+    if (pa_modargs_get_value(ma, "sco_sink", NULL) &&
+        !(u->hsp.sco_sink = pa_namereg_get(m->core, pa_modargs_get_value(ma, "sco_sink", NULL), PA_NAMEREG_SINK))) {
+        pa_log("SCO sink not found");
+        goto fail;
+    }
+
+    if (pa_modargs_get_value(ma, "sco_source", NULL) &&
+        !(u->hsp.sco_source = pa_namereg_get(m->core, pa_modargs_get_value(ma, "sco_source", NULL), PA_NAMEREG_SOURCE))) {
+        pa_log("SCO source not found");
+        goto fail;
+    }
+
     if (pa_modargs_get_value_u32(ma, "rate", &u->sample_spec.rate) < 0 ||
         u->sample_spec.rate <= 0 || u->sample_spec.rate > PA_RATE_MAX) {
         pa_log_error("Failed to get rate from module arguments");
@@ -1704,10 +1770,10 @@ void pa__done(pa_module *m) {
     if (!(u = m->userdata))
         return;
 
-    if (u->sink)
+    if (u->sink && !USE_SCO_OVER_PCM(u))
         pa_sink_unlink(u->sink);
 
-    if (u->source)
+    if (u->source && !USE_SCO_OVER_PCM(u))
         pa_source_unlink(u->source);
 
     stop_thread(u);
diff --git a/src/modules/bluetooth/module-bluetooth-discover.c b/src/modules/bluetooth/module-bluetooth-discover.c
index 0523648..3f8a751 100644
--- a/src/modules/bluetooth/module-bluetooth-discover.c
+++ b/src/modules/bluetooth/module-bluetooth-discover.c
@@ -42,15 +42,20 @@
 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("async=<Asynchronous initialization?>");
+PA_MODULE_USAGE("sco_sink=<name of sink> "
+		"sco_source=<name of source>"
+		"async=<Asynchronous initialization?>");
 
 static const char* const valid_modargs[] = {
+    "sco_sink",
+    "sco_source",
     "async",
     NULL
 };
 
 struct userdata {
     pa_module *module;
+    pa_modargs *ma;
     pa_core *core;
     pa_dbus_connection *connection;
     pa_bluetooth_discovery *discovery;
@@ -71,6 +76,16 @@ static void load_module_for_device(struct userdata *u, pa_bluetooth_device *d, p
             /* Oh, awesome, a new device has shown up and been connected! */
 
             args = pa_sprintf_malloc("address=\"%s\" path=\"%s\"", d->address, d->path);
+
+            if (pa_modargs_get_value(u->ma, "sco_sink", NULL) &&
+                pa_modargs_get_value(u->ma, "sco_source", NULL)) {
+                char *tmp;
+
+                tmp = pa_sprintf_malloc("%s sco_sink=\"%s\" sco_source=\"%s\"", args, pa_modargs_get_value(u->ma, "sco_sink", NULL), pa_modargs_get_value(u->ma, "sco_source", NULL));
+                pa_xfree(args);
+                args = tmp;
+            }
+
             pa_log_debug("Loading module-bluetooth-device %s", args);
             m = pa_module_load(u->module->core, "module-bluetooth-device", args);
             pa_xfree(args);
@@ -130,6 +145,7 @@ int pa__init(pa_module* m) {
     m->userdata = u = pa_xnew0(struct userdata, 1);
     u->module = m;
     u->core = m->core;
+    u->ma = ma;
 
     if (setup_dbus(u) < 0)
         goto fail;
@@ -162,5 +178,8 @@ void pa__done(pa_module* m) {
     if (u->connection)
         pa_dbus_connection_unref(u->connection);
 
+    if (u->ma)
+        pa_modargs_free(u->ma);
+
     pa_xfree(u);
 }

commit 452e2b9fa073299e2f047dd4dda51a3d7032a7ff
Author: Marc-André Lureau <marcandre.lureau at gmail.com>
Date:   Tue Feb 3 18:17:20 2009 +0200

    bluetooth: suspend SCO state when over PCM

diff --git a/src/modules/bluetooth/module-bluetooth-device.c b/src/modules/bluetooth/module-bluetooth-device.c
index 2302b1d..c70a79d 100644
--- a/src/modules/bluetooth/module-bluetooth-device.c
+++ b/src/modules/bluetooth/module-bluetooth-device.c
@@ -106,6 +106,8 @@ struct a2dp_info {
 struct hsp_info {
     pa_sink *sco_sink;
     pa_source *sco_source;
+    pa_hook_slot *sink_state_changed_slot;
+    pa_hook_slot *source_state_changed_slot;
 };
 
 enum profile {
@@ -154,6 +156,9 @@ struct userdata {
     int write_type, read_type;
 };
 
+static int init_bt(struct userdata *u);
+static int init_profile(struct userdata *u);
+
 static int service_send(int fd, const bt_audio_msg_header_t *msg) {
     size_t length;
     ssize_t r;
@@ -1228,6 +1233,57 @@ static char *get_name(const char *type, pa_modargs *ma, const char *device_id, p
 
 #define USE_SCO_OVER_PCM(u) (u->profile == PROFILE_HSP && (u->hsp.sco_sink && u->hsp.sco_source))
 
+static void sco_over_pcm_state_update(struct userdata *u) {
+    pa_assert(u);
+
+    if (PA_SINK_IS_OPENED(pa_sink_get_state(u->hsp.sco_sink)) ||
+        PA_SOURCE_IS_OPENED(pa_source_get_state(u->hsp.sco_source))) {
+
+        if (u->service_fd > 0)
+            return;
+
+        pa_log_debug("Resuming SCO over PCM");
+        if ((init_bt(u) < 0) || (init_profile(u) < 0))
+            pa_log("Can't resume SCO over PCM");
+
+    } else {
+
+        if (u->service_fd <= 0)
+            return;
+
+        pa_log_debug("Closing SCO over PCM");
+        pa_close(u->service_fd);
+        u->service_fd = 0;
+
+    }
+}
+
+static pa_hook_result_t sink_state_changed_cb(pa_core *c, pa_sink *s, struct userdata *u) {
+    pa_assert(c);
+    pa_sink_assert_ref(s);
+    pa_assert(u);
+
+    if (s != u->hsp.sco_sink)
+        return PA_HOOK_OK;
+
+    sco_over_pcm_state_update(u);
+
+    return PA_HOOK_OK;
+}
+
+static pa_hook_result_t source_state_changed_cb(pa_core *c, pa_source *s, struct userdata *u) {
+    pa_assert(c);
+    pa_source_assert_ref(s);
+    pa_assert(u);
+
+    if (s != u->hsp.sco_source)
+        return PA_HOOK_OK;
+
+    sco_over_pcm_state_update(u);
+
+    return PA_HOOK_OK;
+}
+
 static int add_sink(struct userdata *u) {
 
     if (USE_SCO_OVER_PCM(u)) {
@@ -1240,6 +1296,9 @@ static int add_sink(struct userdata *u) {
         pa_proplist_update(u->sink->proplist, PA_UPDATE_MERGE, p);
         pa_proplist_free(p);
 
+	if (!u->hsp.sink_state_changed_slot)
+            u->hsp.sink_state_changed_slot = pa_hook_connect(&u->core->hooks[PA_CORE_HOOK_SINK_STATE_CHANGED], PA_HOOK_NORMAL, (pa_hook_cb_t) sink_state_changed_cb, u);
+
     } else {
         pa_sink_new_data data;
         pa_bool_t b;
@@ -1286,6 +1345,9 @@ static int add_source(struct userdata *u) {
         pa_proplist_update(u->source->proplist, PA_UPDATE_MERGE, p);
         pa_proplist_free(p);
 
+        if (!u->hsp.source_state_changed_slot)
+            u->hsp.source_state_changed_slot = pa_hook_connect(&u->core->hooks[PA_CORE_HOOK_SOURCE_STATE_CHANGED], PA_HOOK_NORMAL, (pa_hook_cb_t) source_state_changed_cb, u);
+
     } else {
         pa_source_new_data data;
         pa_bool_t b;
@@ -1405,6 +1467,16 @@ static void stop_thread(struct userdata *u) {
         u->rtpoll_item = NULL;
     }
 
+    if (u->hsp.sink_state_changed_slot) {
+        pa_hook_slot_free(u->hsp.sink_state_changed_slot);
+        u->hsp.sink_state_changed_slot = NULL;
+    }
+
+    if (u->hsp.source_state_changed_slot) {
+        pa_hook_slot_free(u->hsp.source_state_changed_slot);
+        u->hsp.source_state_changed_slot = NULL;
+    }
+
     if (u->sink) {
         pa_sink_unref(u->sink);
         u->sink = NULL;

commit cac0f9ef2b91462778600821f456248efffb2517
Author: Marc-André Lureau <marcandre.lureau at gmail.com>
Date:   Tue Feb 3 18:43:54 2009 +0200

    bluetooth: export nrec

diff --git a/src/modules/bluetooth/module-bluetooth-device.c b/src/modules/bluetooth/module-bluetooth-device.c
index c70a79d..fa9d6bf 100644
--- a/src/modules/bluetooth/module-bluetooth-device.c
+++ b/src/modules/bluetooth/module-bluetooth-device.c
@@ -104,6 +104,7 @@ struct a2dp_info {
 };
 
 struct hsp_info {
+    pcm_capabilities_t pcm_capabilities;
     pa_sink *sco_sink;
     pa_source *sco_source;
     pa_hook_slot *sink_state_changed_slot;
@@ -271,23 +272,33 @@ static int parse_caps(struct userdata *u, const struct bt_get_capabilities_rsp *
         return -1;
     }
 
-    if (u->profile != PROFILE_A2DP)
-        return 0;
+    if (u->profile == PROFILE_HSP) {
+        if (bytes_left <= 0 || codec->length != sizeof(u->hsp.pcm_capabilities))
+            return -1;
 
-    while (bytes_left > 0) {
-        if (codec->type == BT_A2DP_CODEC_SBC)
-            break;
+        pa_assert(codec->type == BT_HFP_CODEC_PCM);
 
-        bytes_left -= codec->length;
-        codec = (const codec_capabilities_t*) ((const uint8_t*) codec + codec->length);
+        memcpy(&u->hsp.pcm_capabilities, codec, sizeof(u->hsp.pcm_capabilities));
     }
 
-    if (bytes_left <= 0 || codec->length != sizeof(u->a2dp.sbc_capabilities))
-        return -1;
+    if (u->profile == PROFILE_A2DP) {
+
+        while (bytes_left > 0) {
+            if (codec->type == BT_A2DP_CODEC_SBC)
+                break;
+
+            bytes_left -= codec->length;
+            codec = (const codec_capabilities_t*) ((const uint8_t*) codec + codec->length);
+        }
+
+        if (bytes_left <= 0 || codec->length != sizeof(u->a2dp.sbc_capabilities))
+            return -1;
+
+        pa_assert(codec->type == BT_A2DP_CODEC_SBC);
 
-    pa_assert(codec->type == BT_A2DP_CODEC_SBC);
+        memcpy(&u->a2dp.sbc_capabilities, codec, sizeof(u->a2dp.sbc_capabilities));
+    }
 
-    memcpy(&u->a2dp.sbc_capabilities, codec, sizeof(u->a2dp.sbc_capabilities));
     return 0;
 }
 
@@ -1334,10 +1345,9 @@ static int add_sink(struct userdata *u) {
 }
 
 static int add_source(struct userdata *u) {
+    pa_proplist *p;
 
     if (USE_SCO_OVER_PCM(u)) {
-        pa_proplist *p;
-
         u->source = u->hsp.sco_source;
         u->source->card = u->card; /* FIXME! */
         p = pa_proplist_new();
@@ -1379,6 +1389,11 @@ static int add_source(struct userdata *u) {
 /*     u->source->get_volume = source_get_volume_cb; */
 /*     u->source->set_volume = source_set_volume_cb; */
 
+    p = pa_proplist_new();
+    pa_proplist_sets(p, "bluetooth.nrec", pa_yes_no(u->hsp.pcm_capabilities.flags & BT_PCM_FLAG_NREC));
+    pa_proplist_update(u->source->proplist, PA_UPDATE_MERGE, p);
+    pa_proplist_free(p);
+
     return 0;
 }
 

commit cce4359831b5ff02f63e9748671fa744d500d27f
Author: Marc-André Lureau <marcandre.lureau at gmail.com>
Date:   Tue Feb 10 23:48:37 2009 +0200

    bluetooth: reinitialize the sample spec when switching profile
    
    When doing init_profile(), the value u->sample_spec is modified to the
    one which has been last configured. In case of HSP, it will be 8kHz.
    
    Later on, when setting the profile to A2DP, it picks up the lower rate
    available which match with current u->sample_spec.
    
    In my case, it would be 16kHz. To circunvent the issue, I decided to
    reinitialize the u->sample_spec to default value with user module
    argument requested rate.

diff --git a/src/modules/bluetooth/module-bluetooth-device.c b/src/modules/bluetooth/module-bluetooth-device.c
index fa9d6bf..666dc6a 100644
--- a/src/modules/bluetooth/module-bluetooth-device.c
+++ b/src/modules/bluetooth/module-bluetooth-device.c
@@ -1568,6 +1568,14 @@ static int card_set_profile(pa_card *c, pa_card_profile *new_profile) {
     }
 
     u->profile = *d;
+
+    /* Reinitialize the sample spec to default with module argument rate */
+    u->sample_spec = u->module->core->default_sample_spec;
+    if (pa_modargs_get_value_u32(u->modargs, "rate", &u->sample_spec.rate) < 0 ||
+        u->sample_spec.rate <= 0 || u->sample_spec.rate > PA_RATE_MAX) {
+        u->sample_spec = u->module->core->default_sample_spec;
+    }
+
     init_profile(u);
 
     if (u->sink || u->source)

commit f56da989372bedc4817f8b37b78ad8f2daf5429d
Author: Marc-André Lureau <marcandre.lureau at gmail.com>
Date:   Wed Feb 11 16:06:54 2009 +0200

    suspend-on-idle: don't crash when so->source is NULL

diff --git a/src/modules/module-suspend-on-idle.c b/src/modules/module-suspend-on-idle.c
index 5e5e53e..22d49f7 100644
--- a/src/modules/module-suspend-on-idle.c
+++ b/src/modules/module-suspend-on-idle.c
@@ -174,6 +174,9 @@ static pa_hook_result_t source_output_unlink_hook_cb(pa_core *c, pa_source_outpu
     pa_source_output_assert_ref(s);
     pa_assert(u);
 
+    if (!s->source)
+        return PA_HOOK_OK;
+
     if (pa_source_check_suspend(s->source) <= 0) {
         struct device_info *d;
         if ((d = pa_hashmap_get(u->device_infos, s->source)))

commit 86bec09fa843160dd671cf53a32c13fafa0cb932
Author: Marc-André Lureau <marcandre.lureau at gmail.com>
Date:   Wed Feb 11 19:16:42 2009 +0200

    pulsecore: add PA_CORE_HOOK_*_MOVE_FAIL
    
    In case pa_*_move_all_fail(), it is nicer to let a module override the
    default behavior to fallback on a different sink/source. (instead of
    unlinking the sink_input/source_output)

diff --git a/src/pulsecore/core.h b/src/pulsecore/core.h
index 2b8f819..8fa9761 100644
--- a/src/pulsecore/core.h
+++ b/src/pulsecore/core.h
@@ -70,6 +70,7 @@ typedef enum pa_core_hook {
     PA_CORE_HOOK_SINK_INPUT_UNLINK_POST,
     PA_CORE_HOOK_SINK_INPUT_MOVE_START,
     PA_CORE_HOOK_SINK_INPUT_MOVE_FINISH,
+    PA_CORE_HOOK_SINK_INPUT_MOVE_FAIL,
     PA_CORE_HOOK_SINK_INPUT_STATE_CHANGED,
     PA_CORE_HOOK_SINK_INPUT_PROPLIST_CHANGED,
     PA_CORE_HOOK_SINK_INPUT_SET_VOLUME,
@@ -80,6 +81,7 @@ typedef enum pa_core_hook {
     PA_CORE_HOOK_SOURCE_OUTPUT_UNLINK_POST,
     PA_CORE_HOOK_SOURCE_OUTPUT_MOVE_START,
     PA_CORE_HOOK_SOURCE_OUTPUT_MOVE_FINISH,
+    PA_CORE_HOOK_SOURCE_OUTPUT_MOVE_FAIL,
     PA_CORE_HOOK_SOURCE_OUTPUT_STATE_CHANGED,
     PA_CORE_HOOK_SOURCE_OUTPUT_PROPLIST_CHANGED,
     PA_CORE_HOOK_CLIENT_NEW,
diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c
index 0c297ec..558da8c 100644
--- a/src/pulsecore/sink.c
+++ b/src/pulsecore/sink.c
@@ -533,8 +533,10 @@ void pa_sink_move_all_fail(pa_queue *q) {
     pa_assert(q);
 
     while ((i = PA_SINK_INPUT(pa_queue_pop(q)))) {
-        pa_sink_input_unlink(i);
-        pa_sink_input_unref(i);
+        if (pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_MOVE_FAIL], i) == PA_HOOK_OK) {
+            pa_sink_input_unlink(i);
+            pa_sink_input_unref(i);
+        }
     }
 
     pa_queue_free(q, NULL, NULL);
diff --git a/src/pulsecore/source.c b/src/pulsecore/source.c
index 04c7f8b..c31c89c 100644
--- a/src/pulsecore/source.c
+++ b/src/pulsecore/source.c
@@ -472,8 +472,10 @@ void pa_source_move_all_fail(pa_queue *q) {
     pa_assert(q);
 
     while ((o = PA_SOURCE_OUTPUT(pa_queue_pop(q)))) {
-        pa_source_output_unlink(o);
-        pa_source_output_unref(o);
+        if (pa_hook_fire(&o->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_MOVE_FAIL], o) == PA_HOOK_OK) {
+            pa_source_output_unlink(o);
+            pa_source_output_unref(o);
+        }
     }
 
     pa_queue_free(q, NULL, NULL);

commit f0cc23d6e5dd9ce718e66978d7de2dbc94ded537
Merge: 5d15425... 86bec09...
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Feb 12 03:35:57 2009 +0100

    Merge commit 'elmarco/bt-wip'

diff --cc src/pulsecore/core.h
index aca96bb,8fa9761..53e2d2c
--- a/src/pulsecore/core.h
+++ b/src/pulsecore/core.h
@@@ -81,9 -81,9 +82,10 @@@ typedef enum pa_core_hook 
      PA_CORE_HOOK_SOURCE_OUTPUT_UNLINK_POST,
      PA_CORE_HOOK_SOURCE_OUTPUT_MOVE_START,
      PA_CORE_HOOK_SOURCE_OUTPUT_MOVE_FINISH,
+     PA_CORE_HOOK_SOURCE_OUTPUT_MOVE_FAIL,
      PA_CORE_HOOK_SOURCE_OUTPUT_STATE_CHANGED,
      PA_CORE_HOOK_SOURCE_OUTPUT_PROPLIST_CHANGED,
 +    PA_CORE_HOOK_SOURCE_OUTPUT_SEND_EVENT,
      PA_CORE_HOOK_CLIENT_NEW,
      PA_CORE_HOOK_CLIENT_PUT,
      PA_CORE_HOOK_CLIENT_UNLINK,

commit 1837a96e645149bf09ed09aa2f1d276ad608e749
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Feb 12 03:39:56 2009 +0100

    call _kill functions instead of _unlink since the latter should only be called be the stream implementor

diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c
index eadef80..4f39d67 100644
--- a/src/pulsecore/sink.c
+++ b/src/pulsecore/sink.c
@@ -519,7 +519,7 @@ void pa_sink_move_all_finish(pa_sink *s, pa_queue *q, pa_bool_t save) {
 
     while ((i = PA_SINK_INPUT(pa_queue_pop(q)))) {
         if (pa_sink_input_finish_move(i, s, save) < 0)
-            pa_sink_input_unlink(i);
+            pa_sink_input_kill(i);
 
         pa_sink_input_unref(i);
     }
@@ -534,7 +534,7 @@ void pa_sink_move_all_fail(pa_queue *q) {
 
     while ((i = PA_SINK_INPUT(pa_queue_pop(q)))) {
         if (pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_MOVE_FAIL], i) == PA_HOOK_OK) {
-            pa_sink_input_unlink(i);
+            pa_sink_input_kill(i);
             pa_sink_input_unref(i);
         }
     }
diff --git a/src/pulsecore/source.c b/src/pulsecore/source.c
index c31c89c..0009d85 100644
--- a/src/pulsecore/source.c
+++ b/src/pulsecore/source.c
@@ -458,7 +458,7 @@ void pa_source_move_all_finish(pa_source *s, pa_queue *q, pa_bool_t save) {
 
     while ((o = PA_SOURCE_OUTPUT(pa_queue_pop(q)))) {
         if (pa_source_output_finish_move(o, s, save) < 0)
-            pa_source_output_unlink(o);
+            pa_source_output_kill(o);
 
         pa_source_output_unref(o);
     }
@@ -473,7 +473,7 @@ void pa_source_move_all_fail(pa_queue *q) {
 
     while ((o = PA_SOURCE_OUTPUT(pa_queue_pop(q)))) {
         if (pa_hook_fire(&o->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_MOVE_FAIL], o) == PA_HOOK_OK) {
-            pa_source_output_unlink(o);
+            pa_source_output_kill(o);
             pa_source_output_unref(o);
         }
     }

commit 752f8151833506975fe96e0d4ca2fe9cf3555126
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Feb 12 03:42:28 2009 +0100

    addendum to f56da9893: don't crash when s->sink is NULL

diff --git a/src/modules/module-suspend-on-idle.c b/src/modules/module-suspend-on-idle.c
index 22d49f7..a5a3571 100644
--- a/src/modules/module-suspend-on-idle.c
+++ b/src/modules/module-suspend-on-idle.c
@@ -160,6 +160,9 @@ static pa_hook_result_t sink_input_unlink_hook_cb(pa_core *c, pa_sink_input *s,
     pa_sink_input_assert_ref(s);
     pa_assert(u);
 
+    if (!s->sink)
+        return PA_HOOK_OK;
+
     if (pa_sink_check_suspend(s->sink) <= 0) {
         struct device_info *d;
         if ((d = pa_hashmap_get(u->device_infos, s->sink)))

commit 6ada8d1fea43aa7ee8c45663d52e58e8611c9e1f
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Feb 12 03:47:27 2009 +0100

    instead of reparsing the rate module argument when changing profile, simply restore the originally requested sample_spec, this also makes sure the channel count is properly reset

diff --git a/src/modules/bluetooth/module-bluetooth-device.c b/src/modules/bluetooth/module-bluetooth-device.c
index 9419595..bf288f4 100644
--- a/src/modules/bluetooth/module-bluetooth-device.c
+++ b/src/modules/bluetooth/module-bluetooth-device.c
@@ -136,7 +136,7 @@ struct userdata {
 
     pa_memchunk write_memchunk;
 
-    pa_sample_spec sample_spec;
+    pa_sample_spec sample_spec, requested_sample_spec;
 
     int service_fd;
     int stream_fd;
@@ -1571,13 +1571,7 @@ static int card_set_profile(pa_card *c, pa_card_profile *new_profile) {
     }
 
     u->profile = *d;
-
-    /* Reinitialize the sample spec to default with module argument rate */
-    u->sample_spec = u->module->core->default_sample_spec;
-    if (pa_modargs_get_value_u32(u->modargs, "rate", &u->sample_spec.rate) < 0 ||
-        u->sample_spec.rate <= 0 || u->sample_spec.rate > PA_RATE_MAX) {
-        u->sample_spec = u->module->core->default_sample_spec;
-    }
+    u->sample_spec = u->requested_sample_spec;
 
     init_profile(u);
 
@@ -1781,6 +1775,7 @@ int pa__init(pa_module* m) {
         goto fail;
     }
     u->sample_spec.channels = (uint8_t) channels;
+    u->requested_sample_spec = u->sample_spec;
 
     if (setup_dbus(u) < 0)
         goto fail;

commit a7b992faceb1dbb0ac0c39f81987d78c31eb9e5a
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Feb 12 03:56:01 2009 +0100

    some minor fixups

diff --git a/src/modules/bluetooth/module-bluetooth-device.c b/src/modules/bluetooth/module-bluetooth-device.c
index bf288f4..0e0542e 100644
--- a/src/modules/bluetooth/module-bluetooth-device.c
+++ b/src/modules/bluetooth/module-bluetooth-device.c
@@ -273,15 +273,15 @@ static int parse_caps(struct userdata *u, const struct bt_get_capabilities_rsp *
     }
 
     if (u->profile == PROFILE_HSP) {
+
         if (bytes_left <= 0 || codec->length != sizeof(u->hsp.pcm_capabilities))
             return -1;
 
         pa_assert(codec->type == BT_HFP_CODEC_PCM);
 
         memcpy(&u->hsp.pcm_capabilities, codec, sizeof(u->hsp.pcm_capabilities));
-    }
 
-    if (u->profile == PROFILE_A2DP) {
+    } else if (u->profile == PROFILE_A2DP) {
 
         while (bytes_left > 0) {
             if (codec->type == BT_A2DP_CODEC_SBC)
@@ -1249,6 +1249,7 @@ static char *get_name(const char *type, pa_modargs *ma, const char *device_id, p
 
 static void sco_over_pcm_state_update(struct userdata *u) {
     pa_assert(u);
+    pa_assert(USE_SCO_OVER_PCM(u));
 
     if (PA_SINK_IS_OPENED(pa_sink_get_state(u->hsp.sco_sink)) ||
         PA_SOURCE_IS_OPENED(pa_source_get_state(u->hsp.sco_source))) {
@@ -1267,8 +1268,7 @@ static void sco_over_pcm_state_update(struct userdata *u) {
 
         pa_log_debug("Closing SCO over PCM");
         pa_close(u->service_fd);
-        u->service_fd = 0;
-
+        u->service_fd = -1;
     }
 }
 
@@ -1304,7 +1304,6 @@ static int add_sink(struct userdata *u) {
         pa_proplist *p;
 
         u->sink = u->hsp.sco_sink;
-        u->sink->card = u->card; /* FIXME! */
         p = pa_proplist_new();
         pa_proplist_sets(p, "bluetooth.protocol", "sco");
         pa_proplist_update(u->sink->proplist, PA_UPDATE_MERGE, p);
@@ -1352,7 +1351,6 @@ static int add_source(struct userdata *u) {
 
     if (USE_SCO_OVER_PCM(u)) {
         u->source = u->hsp.sco_source;
-        u->source->card = u->card; /* FIXME! */
         p = pa_proplist_new();
         pa_proplist_sets(p, "bluetooth.protocol", "sco");
         pa_proplist_update(u->source->proplist, PA_UPDATE_MERGE, p);

commit a371306710b7267a2c9fa6ebece90e17ee7bff2e
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Feb 12 03:57:59 2009 +0100

    tabs are evil

diff --git a/src/modules/bluetooth/module-bluetooth-device.c b/src/modules/bluetooth/module-bluetooth-device.c
index 0e0542e..7011220 100644
--- a/src/modules/bluetooth/module-bluetooth-device.c
+++ b/src/modules/bluetooth/module-bluetooth-device.c
@@ -73,8 +73,8 @@ PA_MODULE_USAGE(
         "rate=<sample rate> "
         "channels=<number of channels> "
         "path=<device object path> "
-	"sco_sink=<SCO over PCM sink name> "
-	"sco_source=<SCO over PCM source name>");
+        "sco_sink=<SCO over PCM sink name> "
+        "sco_source=<SCO over PCM source name>");
 
 static const char* const valid_modargs[] = {
     "name",
@@ -1309,7 +1309,7 @@ static int add_sink(struct userdata *u) {
         pa_proplist_update(u->sink->proplist, PA_UPDATE_MERGE, p);
         pa_proplist_free(p);
 
-	if (!u->hsp.sink_state_changed_slot)
+        if (!u->hsp.sink_state_changed_slot)
             u->hsp.sink_state_changed_slot = pa_hook_connect(&u->core->hooks[PA_CORE_HOOK_SINK_STATE_CHANGED], PA_HOOK_NORMAL, (pa_hook_cb_t) sink_state_changed_cb, u);
 
     } else {
@@ -1550,13 +1550,13 @@ static int card_set_profile(pa_card *c, pa_card_profile *new_profile) {
 
     if (u->sink) {
         inputs = pa_sink_move_all_start(u->sink);
-	if (!USE_SCO_OVER_PCM(u))
+        if (!USE_SCO_OVER_PCM(u))
             pa_sink_unlink(u->sink);
     }
 
     if (u->source) {
         outputs = pa_source_move_all_start(u->source);
-	if (!USE_SCO_OVER_PCM(u))
+        if (!USE_SCO_OVER_PCM(u))
             pa_source_unlink(u->source);
     }
 
diff --git a/src/modules/bluetooth/module-bluetooth-discover.c b/src/modules/bluetooth/module-bluetooth-discover.c
index 3f8a751..01340e1 100644
--- a/src/modules/bluetooth/module-bluetooth-discover.c
+++ b/src/modules/bluetooth/module-bluetooth-discover.c
@@ -43,8 +43,8 @@ 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("sco_sink=<name of sink> "
-		"sco_source=<name of source>"
-		"async=<Asynchronous initialization?>");
+                "sco_source=<name of source>"
+                "async=<Asynchronous initialization?>");
 
 static const char* const valid_modargs[] = {
     "sco_sink",

commit 84666dbc88d6ace253bd4c5839dcde127ca02100
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Feb 12 04:00:40 2009 +0100

    properly free modargs object when init fails; don't abbreviate modargs in struct

diff --git a/src/modules/bluetooth/module-bluetooth-discover.c b/src/modules/bluetooth/module-bluetooth-discover.c
index 01340e1..e974074 100644
--- a/src/modules/bluetooth/module-bluetooth-discover.c
+++ b/src/modules/bluetooth/module-bluetooth-discover.c
@@ -55,7 +55,7 @@ static const char* const valid_modargs[] = {
 
 struct userdata {
     pa_module *module;
-    pa_modargs *ma;
+    pa_modargs *modargs;
     pa_core *core;
     pa_dbus_connection *connection;
     pa_bluetooth_discovery *discovery;
@@ -77,11 +77,13 @@ static void load_module_for_device(struct userdata *u, pa_bluetooth_device *d, p
 
             args = pa_sprintf_malloc("address=\"%s\" path=\"%s\"", d->address, d->path);
 
-            if (pa_modargs_get_value(u->ma, "sco_sink", NULL) &&
-                pa_modargs_get_value(u->ma, "sco_source", NULL)) {
+            if (pa_modargs_get_value(u->modargs, "sco_sink", NULL) &&
+                pa_modargs_get_value(u->modargs, "sco_source", NULL)) {
                 char *tmp;
 
-                tmp = pa_sprintf_malloc("%s sco_sink=\"%s\" sco_source=\"%s\"", args, pa_modargs_get_value(u->ma, "sco_sink", NULL), pa_modargs_get_value(u->ma, "sco_source", NULL));
+                tmp = pa_sprintf_malloc("%s sco_sink=\"%s\" sco_source=\"%s\"", args,
+                                        pa_modargs_get_value(u->modargs, "sco_sink", NULL),
+                                        pa_modargs_get_value(u->modargs, "sco_source", NULL));
                 pa_xfree(args);
                 args = tmp;
             }
@@ -127,7 +129,7 @@ static int setup_dbus(struct userdata *u) {
 
 int pa__init(pa_module* m) {
     struct userdata *u;
-    pa_modargs *ma;
+    pa_modargs *ma = NULL;
     pa_bool_t async = FALSE;
 
     pa_assert(m);
@@ -145,7 +147,8 @@ int pa__init(pa_module* m) {
     m->userdata = u = pa_xnew0(struct userdata, 1);
     u->module = m;
     u->core = m->core;
-    u->ma = ma;
+    u->modargs = ma;
+    ma = NULL;
 
     if (setup_dbus(u) < 0)
         goto fail;
@@ -161,6 +164,9 @@ int pa__init(pa_module* m) {
 fail:
     pa__done(m);
 
+    if (ma)
+        pa_modargs_free(ma);
+
     return -1;
 }
 
@@ -178,8 +184,8 @@ void pa__done(pa_module* m) {
     if (u->connection)
         pa_dbus_connection_unref(u->connection);
 
-    if (u->ma)
-        pa_modargs_free(u->ma);
+    if (u->modargs)
+        pa_modargs_free(u->modargs);
 
     pa_xfree(u);
 }

-- 
hooks/post-receive
PulseAudio Sound Server



More information about the pulseaudio-commits mailing list