[pulseaudio-commits] 8 commits - src/modules
Tanu Kaskinen
tanuk at kemper.freedesktop.org
Fri Oct 19 08:55:52 PDT 2012
src/modules/bluetooth/bluetooth-util.c | 11 +-
src/modules/bluetooth/bluetooth-util.h | 7 -
src/modules/bluetooth/module-bluetooth-device.c | 106 ++++++++++++++----------
3 files changed, 75 insertions(+), 49 deletions(-)
New commits:
commit 1b83e3fe5fa5da3de564d802c77aebba9692b1cb
Author: Mikel Astiz <mikel.astiz at bmw-carit.de>
Date: Fri Oct 19 10:11:28 2012 +0200
bluetooth: Hold transport pointer while profile set
Instead of repeatedly asking the discovery API to find a transport given
our transport path, let's hold a pointer to the transport and make sure
we remove the reference when the hook is fired reporting that the
transport has been removed. This makes the code easier to follow and
slightly more efficient.
diff --git a/src/modules/bluetooth/module-bluetooth-device.c b/src/modules/bluetooth/module-bluetooth-device.c
index a907e4b..4bf5f03 100644
--- a/src/modules/bluetooth/module-bluetooth-device.c
+++ b/src/modules/bluetooth/module-bluetooth-device.c
@@ -141,7 +141,7 @@ struct userdata {
char *address;
char *path;
- char *transport;
+ pa_bluetooth_transport *transport;
char *accesstype;
pa_hook_slot *transport_removed_slot;
@@ -344,18 +344,15 @@ static void teardown_stream(struct userdata *u) {
}
static void bt_transport_release(struct userdata *u) {
- const char *accesstype = "rw";
- pa_bluetooth_transport *t;
+ pa_assert(u->transport);
/* Ignore if already released */
if (!bt_transport_is_acquired(u))
return;
- pa_log_debug("Releasing transport %s", u->transport);
+ pa_log_debug("Releasing transport %s", u->transport->path);
- t = pa_bluetooth_discovery_get_transport(u->discovery, u->transport);
- if (t)
- pa_bluetooth_transport_release(t, accesstype);
+ pa_bluetooth_transport_release(u->transport, u->accesstype);
pa_xfree(u->accesstype);
u->accesstype = NULL;
@@ -383,12 +380,8 @@ static pa_bt_audio_state_t get_profile_audio_state(const struct userdata *u, con
static int bt_transport_acquire(struct userdata *u, pa_bool_t start) {
const char *accesstype = "rw";
const pa_bluetooth_device *d;
- pa_bluetooth_transport *t;
- if (u->transport == NULL) {
- pa_log("Transport no longer available.");
- return -1;
- }
+ pa_assert(u->transport);
if (bt_transport_is_acquired(u)) {
if (start)
@@ -396,7 +389,7 @@ static int bt_transport_acquire(struct userdata *u, pa_bool_t start) {
return 0;
}
- pa_log_debug("Acquiring transport %s", u->transport);
+ pa_log_debug("Acquiring transport %s", u->transport->path);
d = pa_bluetooth_discovery_get_by_path(u->discovery, u->path);
if (!d) {
@@ -404,14 +397,6 @@ static int bt_transport_acquire(struct userdata *u, pa_bool_t start) {
return -1;
}
- t = pa_bluetooth_discovery_get_transport(u->discovery, u->transport);
- if (!t) {
- pa_log("Transport %s no longer available", u->transport);
- pa_xfree(u->transport);
- u->transport = NULL;
- return -1;
- }
-
if (!start) {
/* FIXME: we are trying to acquire the transport only if the stream is
playing, without actually initiating the stream request from our side
@@ -421,29 +406,29 @@ static int bt_transport_acquire(struct userdata *u, pa_bool_t start) {
stream will not be requested until BlueZ's API supports this
atomically. */
if (get_profile_audio_state(u, d) < PA_BT_AUDIO_STATE_PLAYING) {
- pa_log_info("Failed optional acquire of transport %s", u->transport);
+ pa_log_info("Failed optional acquire of transport %s", u->transport->path);
return -1;
}
}
- u->stream_fd = pa_bluetooth_transport_acquire(t, accesstype, &u->read_link_mtu, &u->write_link_mtu);
+ u->stream_fd = pa_bluetooth_transport_acquire(u->transport, accesstype, &u->read_link_mtu, &u->write_link_mtu);
if (u->stream_fd < 0) {
if (start)
- pa_log("Failed to acquire transport %s", u->transport);
+ pa_log("Failed to acquire transport %s", u->transport->path);
else
- pa_log_info("Failed optional acquire of transport %s", u->transport);
+ pa_log_info("Failed optional acquire of transport %s", u->transport->path);
return -1;
}
u->accesstype = pa_xstrdup(accesstype);
- pa_log_info("Transport %s acquired: fd %d", u->transport, u->stream_fd);
+ pa_log_info("Transport %s acquired: fd %d", u->transport->path, u->stream_fd);
if (!start)
return 0;
done:
- pa_log_info("Transport %s resuming", u->transport);
+ pa_log_info("Transport %s resuming", u->transport->path);
setup_stream(u);
return 0;
@@ -1318,7 +1303,7 @@ static DBusHandlerResult filter_cb(DBusConnection *bus, DBusMessage *m, void *us
dbus_message_get_path(m),
dbus_message_get_member(m));
- if (!dbus_message_has_path(m, u->path) && !dbus_message_has_path(m, u->transport))
+ if (!dbus_message_has_path(m, u->path) && (!u->transport || !dbus_message_has_path(m, u->transport->path)))
goto fail;
if (dbus_message_is_signal(m, "org.bluez.Headset", "SpeakerGainChanged") ||
@@ -1698,6 +1683,8 @@ static int source_set_port_cb(pa_source *s, pa_device_port *p) {
static int add_sink(struct userdata *u) {
char *k;
+ pa_assert(u->transport);
+
if (USE_SCO_OVER_PCM(u)) {
pa_proplist *p;
@@ -1775,6 +1762,8 @@ static int add_sink(struct userdata *u) {
static int add_source(struct userdata *u) {
char *k;
+ pa_assert(u->transport);
+
if (USE_SCO_OVER_PCM(u)) {
u->source = u->hsp.sco_source;
pa_proplist_sets(u->source->proplist, "bluetooth.protocol", profile_to_string(u->profile));
@@ -1834,9 +1823,7 @@ static int add_source(struct userdata *u) {
}
if ((u->profile == PROFILE_HSP) || (u->profile == PROFILE_HFGW)) {
- pa_bluetooth_transport *t;
- t = pa_bluetooth_discovery_get_transport(u->discovery, u->transport);
- pa_assert(t);
+ pa_bluetooth_transport *t = u->transport;
pa_proplist_sets(u->source->proplist, "bluetooth.nrec", t->nrec ? "1" : "0");
if (!u->hsp.nrec_changed_slot)
@@ -1860,7 +1847,7 @@ static void bt_transport_config_a2dp(struct userdata *u) {
struct a2dp_info *a2dp = &u->a2dp;
a2dp_sbc_t *config;
- t = pa_bluetooth_discovery_get_transport(u->discovery, u->transport);
+ t = u->transport;
pa_assert(t);
config = (a2dp_sbc_t *) t->config;
@@ -1991,6 +1978,7 @@ static int setup_transport(struct userdata *u) {
pa_bluetooth_transport *t;
pa_assert(u);
+ pa_assert(!u->transport);
if (!(d = pa_bluetooth_discovery_get_by_path(u->discovery, u->path))) {
pa_log_error("Failed to get device object.");
@@ -2004,7 +1992,7 @@ static int setup_transport(struct userdata *u) {
return -1;
}
- u->transport = pa_xstrdup(t->path);
+ u->transport = t;
u->transport_removed_slot = pa_hook_connect(&t->hooks[PA_BLUETOOTH_TRANSPORT_HOOK_REMOVED], PA_HOOK_NORMAL,
(pa_hook_cb_t) transport_removed_cb, u);
@@ -2025,6 +2013,8 @@ static int init_profile(struct userdata *u) {
if (setup_transport(u) < 0)
return -1;
+ pa_assert(u->transport);
+
if (u->profile == PROFILE_A2DP ||
u->profile == PROFILE_HSP ||
u->profile == PROFILE_HFGW)
@@ -2085,7 +2075,6 @@ static void stop_thread(struct userdata *u) {
if (u->transport) {
bt_transport_release(u);
- pa_xfree(u->transport);
u->transport = NULL;
}
commit 3ddff2f3e5e876d606d1180e3c957270fdc98625
Author: Mikel Astiz <mikel.astiz at bmw-carit.de>
Date: Fri Oct 19 10:11:27 2012 +0200
bluetooth: Set to off instead of failing module load
If the profile setup fails during module load, the fallback should be
setting the profile to off, exactly as it is done in card_set_profile().
diff --git a/src/modules/bluetooth/module-bluetooth-device.c b/src/modules/bluetooth/module-bluetooth-device.c
index 8b14c61..a907e4b 100644
--- a/src/modules/bluetooth/module-bluetooth-device.c
+++ b/src/modules/bluetooth/module-bluetooth-device.c
@@ -2647,11 +2647,18 @@ int pa__init(pa_module* m) {
if (u->profile != PROFILE_OFF)
if (init_profile(u) < 0)
- goto fail;
+ goto off;
if (u->sink || u->source)
if (start_thread(u) < 0)
- goto fail;
+ goto off;
+
+ return 0;
+
+off:
+ stop_thread(u);
+
+ pa_assert_se(pa_card_set_profile(u->card, "off", false) >= 0);
return 0;
commit 9b9e53d144e35a227f994c65f7c2ed98800229df
Author: Mikel Astiz <mikel.astiz at bmw-carit.de>
Date: Fri Oct 19 10:11:26 2012 +0200
bluetooth: Set to off if transport removed
The recently added hook can be used to detect that the transport being
used has been removed. In this case, the profile needs to be set to off.
Additionally, the change fixes a significant problem: without this
transition, the transport could be destroyed while the hook slots (i.e.
nrec_changed_slot) were still set. This led to a double free of these
objects in stop_thread().
diff --git a/src/modules/bluetooth/module-bluetooth-device.c b/src/modules/bluetooth/module-bluetooth-device.c
index b56cb77..8b14c61 100644
--- a/src/modules/bluetooth/module-bluetooth-device.c
+++ b/src/modules/bluetooth/module-bluetooth-device.c
@@ -143,6 +143,7 @@ struct userdata {
char *path;
char *transport;
char *accesstype;
+ pa_hook_slot *transport_removed_slot;
pa_bluetooth_discovery *discovery;
pa_bool_t auto_connect;
@@ -1975,6 +1976,16 @@ static void bt_transport_config(struct userdata *u) {
}
/* Run from main thread */
+static pa_hook_result_t transport_removed_cb(pa_bluetooth_transport *t, void *call_data, struct userdata *u) {
+ pa_assert(t);
+ pa_assert(u);
+
+ pa_assert_se(pa_card_set_profile(u->card, "off", false) >= 0);
+
+ return PA_HOOK_OK;
+}
+
+/* Run from main thread */
static int setup_transport(struct userdata *u) {
const pa_bluetooth_device *d;
pa_bluetooth_transport *t;
@@ -1995,6 +2006,9 @@ static int setup_transport(struct userdata *u) {
u->transport = pa_xstrdup(t->path);
+ u->transport_removed_slot = pa_hook_connect(&t->hooks[PA_BLUETOOTH_TRANSPORT_HOOK_REMOVED], PA_HOOK_NORMAL,
+ (pa_hook_cb_t) transport_removed_cb, u);
+
bt_transport_acquire(u, FALSE);
bt_transport_config(u);
@@ -2064,6 +2078,11 @@ static void stop_thread(struct userdata *u) {
u->hsp.nrec_changed_slot = NULL;
}
+ if (u->transport_removed_slot) {
+ pa_hook_slot_free(u->transport_removed_slot);
+ u->transport_removed_slot = NULL;
+ }
+
if (u->transport) {
bt_transport_release(u);
pa_xfree(u->transport);
commit 6e5f78e0af1bf4aff4afe942f57c7d801a233366
Author: Mikel Astiz <mikel.astiz at bmw-carit.de>
Date: Fri Oct 19 10:11:25 2012 +0200
bluetooth: Add hook to tell transport was removed
Add a hook to report that the transport was removed from D-Bus, and thus
references to it should be released.
diff --git a/src/modules/bluetooth/bluetooth-util.c b/src/modules/bluetooth/bluetooth-util.c
index 0482c16..f4f60c4 100644
--- a/src/modules/bluetooth/bluetooth-util.c
+++ b/src/modules/bluetooth/bluetooth-util.c
@@ -157,8 +157,10 @@ static void device_free(pa_bluetooth_device *d) {
pa_assert(d);
- while ((t = pa_hashmap_steal_first(d->transports)))
+ while ((t = pa_hashmap_steal_first(d->transports))) {
+ pa_hook_fire(&t->hooks[PA_BLUETOOTH_TRANSPORT_HOOK_REMOVED], NULL);
transport_free(t);
+ }
pa_hashmap_free(d->transports, NULL, NULL);
@@ -1188,6 +1190,7 @@ static DBusMessage *endpoint_clear_configuration(DBusConnection *c, DBusMessage
if ((t = pa_hashmap_get(d->transports, path))) {
pa_log_debug("Clearing transport %s profile %d", t->path, t->profile);
pa_hashmap_remove(d->transports, t->path);
+ pa_hook_fire(&t->hooks[PA_BLUETOOTH_TRANSPORT_HOOK_REMOVED], NULL);
transport_free(t);
break;
}
diff --git a/src/modules/bluetooth/bluetooth-util.h b/src/modules/bluetooth/bluetooth-util.h
index 879b3a3..e529891 100644
--- a/src/modules/bluetooth/bluetooth-util.h
+++ b/src/modules/bluetooth/bluetooth-util.h
@@ -66,6 +66,7 @@ enum profile {
/* Hook data: pa_bluetooth_transport pointer. */
typedef enum pa_bluetooth_transport_hook {
PA_BLUETOOTH_TRANSPORT_HOOK_NREC_CHANGED, /* Call data: NULL. */
+ PA_BLUETOOTH_TRANSPORT_HOOK_REMOVED, /* Call data: NULL. */
PA_BLUETOOTH_TRANSPORT_HOOK_MAX
} pa_bluetooth_transport_hook_t;
commit 640038cc28ae3e9a88d2e2902dd8ec1c32be0ed7
Author: Mikel Astiz <mikel.astiz at bmw-carit.de>
Date: Fri Oct 19 10:11:24 2012 +0200
bluetooth: Remove const qualifier for transports
The internal API in bluetooth-util should not use the const qualifier
for operations modifying the transport object. This is specially useful
in order to use the available hooks.
diff --git a/src/modules/bluetooth/bluetooth-util.c b/src/modules/bluetooth/bluetooth-util.c
index e14c8c8..0482c16 100644
--- a/src/modules/bluetooth/bluetooth-util.c
+++ b/src/modules/bluetooth/bluetooth-util.c
@@ -968,7 +968,7 @@ pa_bluetooth_transport* pa_bluetooth_discovery_get_transport(pa_bluetooth_discov
return NULL;
}
-const pa_bluetooth_transport* pa_bluetooth_device_get_transport(const pa_bluetooth_device *d, enum profile profile) {
+pa_bluetooth_transport* pa_bluetooth_device_get_transport(const pa_bluetooth_device *d, enum profile profile) {
pa_bluetooth_transport *t;
void *state = NULL;
@@ -981,7 +981,7 @@ const pa_bluetooth_transport* pa_bluetooth_device_get_transport(const pa_bluetoo
return NULL;
}
-int pa_bluetooth_transport_acquire(const pa_bluetooth_transport *t, const char *accesstype, size_t *imtu, size_t *omtu) {
+int pa_bluetooth_transport_acquire(pa_bluetooth_transport *t, const char *accesstype, size_t *imtu, size_t *omtu) {
DBusMessage *m, *r;
DBusError err;
int ret;
@@ -1019,7 +1019,7 @@ fail:
return ret;
}
-void pa_bluetooth_transport_release(const pa_bluetooth_transport *t, const char *accesstype) {
+void pa_bluetooth_transport_release(pa_bluetooth_transport *t, const char *accesstype) {
DBusMessage *m;
DBusError err;
diff --git a/src/modules/bluetooth/bluetooth-util.h b/src/modules/bluetooth/bluetooth-util.h
index a2ad9aa..879b3a3 100644
--- a/src/modules/bluetooth/bluetooth-util.h
+++ b/src/modules/bluetooth/bluetooth-util.h
@@ -133,10 +133,10 @@ const pa_bluetooth_device* pa_bluetooth_discovery_get_by_path(pa_bluetooth_disco
const pa_bluetooth_device* pa_bluetooth_discovery_get_by_address(pa_bluetooth_discovery *d, const char* address);
pa_bluetooth_transport* pa_bluetooth_discovery_get_transport(pa_bluetooth_discovery *y, const char *path);
-const pa_bluetooth_transport* pa_bluetooth_device_get_transport(const pa_bluetooth_device *d, enum profile profile);
+pa_bluetooth_transport* pa_bluetooth_device_get_transport(const pa_bluetooth_device *d, enum profile profile);
-int pa_bluetooth_transport_acquire(const pa_bluetooth_transport *t, const char *accesstype, size_t *imtu, size_t *omtu);
-void pa_bluetooth_transport_release(const pa_bluetooth_transport *t, const char *accesstype);
+int pa_bluetooth_transport_acquire(pa_bluetooth_transport *t, const char *accesstype, size_t *imtu, size_t *omtu);
+void pa_bluetooth_transport_release(pa_bluetooth_transport *t, const char *accesstype);
int pa_bluetooth_transport_parse_property(pa_bluetooth_transport *t, DBusMessageIter *i);
pa_hook* pa_bluetooth_discovery_hook(pa_bluetooth_discovery *d);
diff --git a/src/modules/bluetooth/module-bluetooth-device.c b/src/modules/bluetooth/module-bluetooth-device.c
index 4b98108..b56cb77 100644
--- a/src/modules/bluetooth/module-bluetooth-device.c
+++ b/src/modules/bluetooth/module-bluetooth-device.c
@@ -344,7 +344,7 @@ static void teardown_stream(struct userdata *u) {
static void bt_transport_release(struct userdata *u) {
const char *accesstype = "rw";
- const pa_bluetooth_transport *t;
+ pa_bluetooth_transport *t;
/* Ignore if already released */
if (!bt_transport_is_acquired(u))
@@ -382,7 +382,7 @@ static pa_bt_audio_state_t get_profile_audio_state(const struct userdata *u, con
static int bt_transport_acquire(struct userdata *u, pa_bool_t start) {
const char *accesstype = "rw";
const pa_bluetooth_device *d;
- const pa_bluetooth_transport *t;
+ pa_bluetooth_transport *t;
if (u->transport == NULL) {
pa_log("Transport no longer available.");
@@ -1977,7 +1977,7 @@ static void bt_transport_config(struct userdata *u) {
/* Run from main thread */
static int setup_transport(struct userdata *u) {
const pa_bluetooth_device *d;
- const pa_bluetooth_transport *t;
+ pa_bluetooth_transport *t;
pa_assert(u);
commit e68712acb41c6bd1b5af88829253c7253129417a
Author: Mikel Astiz <mikel.astiz at bmw-carit.de>
Date: Fri Oct 19 10:11:23 2012 +0200
bluetooth: Check return value of start_thread()
The function can return an error, so in that case the profile change
should fail.
diff --git a/src/modules/bluetooth/module-bluetooth-device.c b/src/modules/bluetooth/module-bluetooth-device.c
index 33d42fe..4b98108 100644
--- a/src/modules/bluetooth/module-bluetooth-device.c
+++ b/src/modules/bluetooth/module-bluetooth-device.c
@@ -2142,7 +2142,6 @@ static int start_thread(struct userdata *u) {
if (!(u->thread = pa_thread_new("bluetooth", thread_func, u))) {
pa_log_error("Failed to create IO thread");
- stop_thread(u);
return -1;
}
@@ -2233,7 +2232,8 @@ static int card_set_profile(pa_card *c, pa_card_profile *new_profile) {
goto off;
if (u->sink || u->source)
- start_thread(u);
+ if (start_thread(u) < 0)
+ goto off;
return 0;
commit fcfc0e536ae7a5a2a2a8d53c164409db5f2187f7
Author: Mikel Astiz <mikel.astiz at bmw-carit.de>
Date: Fri Oct 19 10:11:22 2012 +0200
bluetooth: Check return value of init_profile()
If profile could not be successfully initialized, the card should be
set to PROFILE_OFF automatically. If sinks or sources exist, they need
to be destroyed, therefore stop_thread() is called.
diff --git a/src/modules/bluetooth/module-bluetooth-device.c b/src/modules/bluetooth/module-bluetooth-device.c
index ee17fde..33d42fe 100644
--- a/src/modules/bluetooth/module-bluetooth-device.c
+++ b/src/modules/bluetooth/module-bluetooth-device.c
@@ -2229,12 +2229,20 @@ static int card_set_profile(pa_card *c, pa_card_profile *new_profile) {
save_sco_volume_callbacks(u);
if (u->profile != PROFILE_OFF)
- init_profile(u);
+ if (init_profile(u) < 0)
+ goto off;
if (u->sink || u->source)
start_thread(u);
return 0;
+
+off:
+ stop_thread(u);
+
+ pa_assert_se(pa_card_set_profile(u->card, "off", false) >= 0);
+
+ return -PA_ERR_IO;
}
static void create_ports_for_profile(struct userdata *u, const pa_bluetooth_device *device, pa_card_new_data *card_new_data, pa_card_profile *profile) {
commit 8b1236531efb7a485c6386888468db920cae6d99
Author: Mikel Astiz <mikel.astiz at bmw-carit.de>
Date: Fri Oct 19 10:11:21 2012 +0200
bluetooth: Use assertions when setting off profile
Setting the card profile to off cannot fail, therefore assertions can be
used when calling pa_card_set_profile().
diff --git a/src/modules/bluetooth/module-bluetooth-device.c b/src/modules/bluetooth/module-bluetooth-device.c
index d78ce8c..ee17fde 100644
--- a/src/modules/bluetooth/module-bluetooth-device.c
+++ b/src/modules/bluetooth/module-bluetooth-device.c
@@ -605,8 +605,7 @@ static int device_process_msg(pa_msgobject *obj, int code, void *data, int64_t o
pa_log_debug("Switching the profile to off due to IO thread failure.");
- if (pa_card_set_profile(u->card, "off", FALSE) < 0)
- pa_log_debug("Failed to switch profile to off");
+ pa_assert_se(pa_card_set_profile(u->card, "off", false) >= 0);
break;
}
}
More information about the pulseaudio-commits
mailing list