[pulseaudio-discuss] [PATCH v4 36/41] bluetooth: Handle changes to BlueZ 5 transports state
jprvita at gmail.com
jprvita at gmail.com
Wed Sep 18 14:17:30 PDT 2013
From: João Paulo Rechi Vita <jprvita at openbossa.org>
---
src/modules/bluetooth/module-bluez5-device.c | 78 ++++++++++++++++++++++++++++
1 file changed, 78 insertions(+)
diff --git a/src/modules/bluetooth/module-bluez5-device.c b/src/modules/bluetooth/module-bluez5-device.c
index d9e1fc6..2eaeb77 100644
--- a/src/modules/bluetooth/module-bluez5-device.c
+++ b/src/modules/bluetooth/module-bluez5-device.c
@@ -97,6 +97,7 @@ struct userdata {
pa_core *core;
pa_hook_slot *device_connection_changed_slot;
+ pa_hook_slot *transport_state_changed_slot;
pa_bluetooth_discovery *discovery;
pa_bluetooth_device *device;
@@ -1670,6 +1671,62 @@ static int add_card(struct userdata *u) {
}
/* Run from main thread */
+static void handle_transport_state_change(struct userdata *u, struct pa_bluetooth_transport *t) {
+ bool acquire = false;
+ bool release = false;
+ pa_card_profile *cp;
+ pa_device_port *port;
+
+ pa_assert(u);
+ pa_assert(t);
+
+ /* Update profile availability */
+ if (!(cp = pa_hashmap_get(u->card->profiles, pa_bluetooth_profile_to_string(t->profile))))
+ return;
+ pa_card_profile_set_available(cp, transport_state_to_availability(t->state));
+
+ /* Update port availability */
+ pa_assert_se(port = pa_hashmap_get(u->card->ports, u->output_port_name));
+ pa_device_port_set_available(port, get_port_availability(u, PA_DIRECTION_OUTPUT));
+ pa_assert_se(port = pa_hashmap_get(u->card->ports, u->input_port_name));
+ pa_device_port_set_available(port, get_port_availability(u, PA_DIRECTION_INPUT));
+
+ /* Acquire or release transport as needed */
+ acquire = (t->state == PA_BLUETOOTH_TRANSPORT_STATE_PLAYING && u->profile == t->profile);
+ release = (t->state != PA_BLUETOOTH_TRANSPORT_STATE_PLAYING && u->profile == t->profile);
+
+ if (acquire && transport_acquire(u, true) >= 0) {
+ if (u->source) {
+ pa_log_debug("Resuming source %s because its transport state changed to playing", u->source->name);
+ pa_source_suspend(u->source, false, PA_SUSPEND_IDLE|PA_SUSPEND_USER);
+ }
+
+ if (u->sink) {
+ pa_log_debug("Resuming sink %s because its transport state changed to playing", u->sink->name);
+ pa_sink_suspend(u->sink, false, PA_SUSPEND_IDLE|PA_SUSPEND_USER);
+ }
+ }
+
+ if (release && u->transport_acquired) {
+ /* FIXME: this release is racy, since the audio stream might have
+ * been set up again in the meantime (but not processed yet by PA).
+ * BlueZ should probably release the transport automatically, and in
+ * that case we would just mark the transport as released */
+
+ /* Remote side closed the stream so we consider it PA_SUSPEND_USER */
+ if (u->source) {
+ pa_log_debug("Suspending source %s because the remote end closed the stream", u->source->name);
+ pa_source_suspend(u->source, true, PA_SUSPEND_USER);
+ }
+
+ if (u->sink) {
+ pa_log_debug("Suspending sink %s because the remote end closed the stream", u->sink->name);
+ pa_sink_suspend(u->sink, true, PA_SUSPEND_USER);
+ }
+ }
+}
+
+/* Run from main thread */
static pa_hook_result_t device_connection_changed_cb(pa_bluetooth_discovery *y, const pa_bluetooth_device *d, struct userdata *u) {
pa_assert(d);
pa_assert(u);
@@ -1683,6 +1740,20 @@ static pa_hook_result_t device_connection_changed_cb(pa_bluetooth_discovery *y,
return PA_HOOK_OK;
}
+/* Run from main thread */
+static pa_hook_result_t transport_state_changed_cb(pa_bluetooth_discovery *y, pa_bluetooth_transport *t, struct userdata *u) {
+ pa_assert(t);
+ pa_assert(u);
+
+ if (t == u->transport && t->state <= PA_BLUETOOTH_TRANSPORT_STATE_DISCONNECTED)
+ pa_assert_se(pa_card_set_profile(u->card, "off", false) >= 0);
+
+ if (t->device == u->device)
+ handle_transport_state_change(u, t);
+
+ return PA_HOOK_OK;
+}
+
/* Run from main thread context */
static int device_process_msg(pa_msgobject *obj, int code, void *data, int64_t offset, pa_memchunk *chunk) {
struct bluetooth_msg *u = BLUETOOTH_MSG(obj);
@@ -1735,6 +1806,10 @@ int pa__init(pa_module* m) {
pa_hook_connect(pa_bluetooth_discovery_hook(u->discovery, PA_BLUETOOTH_HOOK_DEVICE_CONNECTION_CHANGED),
PA_HOOK_NORMAL, (pa_hook_cb_t) device_connection_changed_cb, u);
+ u->transport_state_changed_slot =
+ pa_hook_connect(pa_bluetooth_discovery_hook(u->discovery, PA_BLUETOOTH_HOOK_TRANSPORT_STATE_CHANGED),
+ PA_HOOK_NORMAL, (pa_hook_cb_t) transport_state_changed_cb, u);
+
if (add_card(u) < 0)
goto fail;
@@ -1784,6 +1859,9 @@ void pa__done(pa_module *m) {
if (u->device_connection_changed_slot)
pa_hook_slot_free(u->device_connection_changed_slot);
+ if (u->transport_state_changed_slot)
+ pa_hook_slot_free(u->transport_state_changed_slot);
+
if (u->sbc_info.buffer)
pa_xfree(u->sbc_info.buffer);
--
1.8.3.1
More information about the pulseaudio-discuss
mailing list