[pulseaudio-discuss] [RFC next v0 06/11] bluetooth: Split BlueZ backend data to separate structs
Mikel Astiz
mikel.astiz.oss at gmail.com
Wed May 15 01:46:51 PDT 2013
From: Mikel Astiz <mikel.astiz at bmw-carit.de>
bluetooth-util internally implements a backend for BlueZ Media API
but it's nevertheless convenient to have the backend-specific data split
into separated data structures.
---
src/modules/bluetooth/bluetooth-util.c | 108 +++++++++++++++++++++++----------
src/modules/bluetooth/bluetooth-util.h | 4 +-
2 files changed, 79 insertions(+), 33 deletions(-)
diff --git a/src/modules/bluetooth/bluetooth-util.c b/src/modules/bluetooth/bluetooth-util.c
index 34db2ac..be82331 100644
--- a/src/modules/bluetooth/bluetooth-util.c
+++ b/src/modules/bluetooth/bluetooth-util.c
@@ -97,8 +97,14 @@ struct profile_data {
};
typedef struct bluez_backend_private {
+ pa_hashmap *transports;
} bluez_backend_private;
+typedef struct bluez_transport_private {
+ char *owner;
+ char *path;
+} bluez_transport_private;
+
struct pa_bluetooth_discovery {
PA_REFCNT_DECLARE;
@@ -108,7 +114,6 @@ struct pa_bluetooth_discovery {
pa_bluez_version_t version;
bool adapters_listed;
pa_hashmap *devices;
- pa_hashmap *transports;
struct profile_data profiles[PA_BLUETOOTH_PROFILE_COUNT];
pa_hook hooks[PA_BLUETOOTH_HOOK_MAX];
bool filter_added;
@@ -252,15 +257,32 @@ static pa_bluetooth_device* device_new(pa_bluetooth_discovery *discovery, const
return d;
}
+static void bluez_transport_free(bluez_transport_private *p) {
+ pa_assert(p);
+
+ pa_xfree(p->owner);
+ pa_xfree(p->path);
+ pa_xfree(p);
+}
+
static void transport_free(pa_bluetooth_transport *t) {
pa_assert(t);
- pa_xfree(t->owner);
- pa_xfree(t->path);
+ bluez_transport_free(t->backend_private);
+
pa_xfree(t->config);
pa_xfree(t);
}
+static void bluez_backend_transport_removed(bluez_backend_private *bbp, pa_bluetooth_transport *t) {
+ bluez_transport_private *p;
+
+ pa_assert(t);
+ pa_assert_se(p = t->backend_private);
+
+ pa_hashmap_remove(bbp->transports, p->path);
+}
+
static void device_free(pa_bluetooth_device *d) {
pa_bluetooth_uuid *u;
pa_bluetooth_transport *t;
@@ -273,7 +295,7 @@ static void device_free(pa_bluetooth_device *d) {
continue;
d->transports[i] = NULL;
- pa_hashmap_remove(d->discovery->transports, t->path);
+ bluez_backend_transport_removed(&d->discovery->backend_private, t);
t->state = PA_BLUETOOTH_TRANSPORT_STATE_DISCONNECTED;
pa_hook_fire(&d->discovery->hooks[PA_BLUETOOTH_HOOK_TRANSPORT_STATE_CHANGED], t);
transport_free(t);
@@ -1070,6 +1092,10 @@ static void init_bluez(pa_bluetooth_discovery *y) {
static int transport_parse_property(pa_bluetooth_transport *t, DBusMessageIter *i) {
const char *key;
DBusMessageIter variant_i;
+ bluez_transport_private *p;
+
+ pa_assert(t);
+ pa_assert_se(p = t->backend_private);
key = check_variant_property(i);
if (key == NULL)
@@ -1099,11 +1125,11 @@ static int transport_parse_property(pa_bluetooth_transport *t, DBusMessageIter *
bool old_any_connected = pa_bluetooth_device_any_audio_connected(t->device);
if (transport_state_from_string(value, &t->state) < 0) {
- pa_log("Transport %s has an invalid state: '%s'", t->path, value);
+ pa_log("Transport %s has an invalid state: '%s'", p->path, value);
return -1;
}
- pa_log_debug("dbus: transport %s set to state '%s'", t->path, value);
+ pa_log_debug("dbus: transport %s set to state '%s'", p->path, value);
pa_hook_fire(&t->device->discovery->hooks[PA_BLUETOOTH_HOOK_TRANSPORT_STATE_CHANGED], t);
if (old_any_connected != pa_bluetooth_device_any_audio_connected(t->device))
@@ -1138,12 +1164,15 @@ static int parse_transport_properties(pa_bluetooth_transport *t, DBusMessageIter
static DBusHandlerResult filter_cb(DBusConnection *bus, DBusMessage *m, void *userdata) {
DBusError err;
pa_bluetooth_discovery *y;
+ bluez_backend_private *bbp;
pa_assert(bus);
pa_assert(m);
pa_assert_se(y = userdata);
+ bbp = &y->backend_private;
+
dbus_error_init(&err);
pa_log_debug("dbus: interface=%s, path=%s, member=%s\n",
@@ -1262,7 +1291,7 @@ static DBusHandlerResult filter_cb(DBusConnection *bus, DBusMessage *m, void *us
pa_bluetooth_transport *t;
DBusMessageIter arg_i;
- if (!(t = pa_hashmap_get(y->transports, dbus_message_get_path(m))))
+ if (!(t = pa_hashmap_get(bbp->transports, dbus_message_get_path(m))))
goto fail;
if (!dbus_message_iter_init(m, &arg_i)) {
@@ -1359,7 +1388,7 @@ static DBusHandlerResult filter_cb(DBusConnection *bus, DBusMessage *m, void *us
} else if (pa_streq(interface, "org.bluez.MediaTransport1")) {
pa_bluetooth_transport *t;
- if (!(t = pa_hashmap_get(y->transports, dbus_message_get_path(m))))
+ if (!(t = pa_hashmap_get(bbp->transports, dbus_message_get_path(m))))
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
parse_transport_properties(t, &arg_i);
@@ -1443,10 +1472,12 @@ int pa_bluetooth_transport_acquire(pa_bluetooth_transport *t, bool optional, siz
int ret;
uint16_t i, o;
const char *method;
+ bluez_transport_private *p;
pa_assert(t);
pa_assert(t->device);
pa_assert(t->device->discovery);
+ pa_assert_se(p = t->backend_private);
dbus_error_init(&err);
@@ -1461,28 +1492,28 @@ int pa_bluetooth_transport_acquire(pa_bluetooth_transport *t, bool optional, siz
suspended in the meantime, so we can't really guarantee that the
stream will not be requested with the API in BlueZ 4.x */
if (t->state < PA_BLUETOOTH_TRANSPORT_STATE_PLAYING) {
- pa_log_info("Failed optional acquire of unavailable transport %s", t->path);
+ pa_log_info("Failed optional acquire of unavailable transport %s", p->path);
return -1;
}
}
method = "Acquire";
- pa_assert_se(m = dbus_message_new_method_call(t->owner, t->path, "org.bluez.MediaTransport", method));
+ pa_assert_se(m = dbus_message_new_method_call(p->owner, p->path, "org.bluez.MediaTransport", method));
pa_assert_se(dbus_message_append_args(m, DBUS_TYPE_STRING, &accesstype, DBUS_TYPE_INVALID));
} else {
pa_assert(t->device->discovery->version == BLUEZ_VERSION_5);
method = optional ? "TryAcquire" : "Acquire";
- pa_assert_se(m = dbus_message_new_method_call(t->owner, t->path, "org.bluez.MediaTransport1", method));
+ pa_assert_se(m = dbus_message_new_method_call(p->owner, p->path, "org.bluez.MediaTransport1", method));
}
r = dbus_connection_send_with_reply_and_block(pa_dbus_connection_get(t->device->discovery->connection), m, -1, &err);
if (!r) {
if (optional && pa_streq(err.name, "org.bluez.Error.NotAvailable"))
- pa_log_info("Failed optional acquire of unavailable transport %s", t->path);
+ pa_log_info("Failed optional acquire of unavailable transport %s", p->path);
else
- pa_log("Transport %s() failed for transport %s (%s)", method, t->path, err.message);
+ pa_log("Transport %s() failed for transport %s (%s)", method, p->path, err.message);
dbus_error_free(&err);
return -1;
@@ -1510,36 +1541,38 @@ fail:
void pa_bluetooth_transport_release(pa_bluetooth_transport *t) {
DBusMessage *m;
DBusError err;
+ bluez_transport_private *p;
pa_assert(t);
pa_assert(t->device);
pa_assert(t->device->discovery);
+ pa_assert_se(p = t->backend_private);
dbus_error_init(&err);
if (t->device->discovery->version == BLUEZ_VERSION_4) {
const char *accesstype = "rw";
- pa_assert_se(m = dbus_message_new_method_call(t->owner, t->path, "org.bluez.MediaTransport", "Release"));
+ pa_assert_se(m = dbus_message_new_method_call(p->owner, p->path, "org.bluez.MediaTransport", "Release"));
pa_assert_se(dbus_message_append_args(m, DBUS_TYPE_STRING, &accesstype, DBUS_TYPE_INVALID));
} else {
pa_assert(t->device->discovery->version == BLUEZ_VERSION_5);
if (t->state <= PA_BLUETOOTH_TRANSPORT_STATE_IDLE) {
- pa_log_info("Transport %s auto-released by BlueZ or already released", t->path);
+ pa_log_info("Transport %s auto-released by BlueZ or already released", p->path);
return;
}
- pa_assert_se(m = dbus_message_new_method_call(t->owner, t->path, "org.bluez.MediaTransport1", "Release"));
+ pa_assert_se(m = dbus_message_new_method_call(p->owner, p->path, "org.bluez.MediaTransport1", "Release"));
}
dbus_connection_send_with_reply_and_block(pa_dbus_connection_get(t->device->discovery->connection), m, -1, &err);
if (dbus_error_is_set(&err)) {
- pa_log("Failed to release transport %s: %s", t->path, err.message);
+ pa_log("Failed to release transport %s: %s", p->path, err.message);
dbus_error_free(&err);
} else
- pa_log_info("Transport %s released", t->path);
+ pa_log_info("Transport %s released", p->path);
}
static void set_property(pa_bluetooth_discovery *y, const char *bus, const char *path, const char *interface,
@@ -1600,6 +1633,7 @@ static pa_bluetooth_transport *transport_new(pa_bluetooth_device *d, const char
const uint8_t *config, int size) {
pa_bluetooth_transport *t;
pa_bluetooth_transport_new_data data;
+ bluez_transport_private *private;
data.device = d;
data.profile = p;
@@ -1613,8 +1647,10 @@ static pa_bluetooth_transport *transport_new(pa_bluetooth_device *d, const char
t = pa_bt_backend_notify_transport_added(&data);
- t->owner = pa_xstrdup(owner);
- t->path = pa_xstrdup(path);
+ private = pa_xnew0(bluez_transport_private, 1);
+ private->owner = pa_xstrdup(owner);
+ private->path = pa_xstrdup(path);
+ t->backend_private = private;
return t;
}
@@ -1623,6 +1659,7 @@ static DBusMessage *endpoint_set_configuration(DBusConnection *conn, DBusMessage
pa_bluetooth_discovery *y = userdata;
pa_bluetooth_device *d;
pa_bluetooth_transport *t;
+ bluez_backend_private *bbp;
const char *sender, *path, *dev_path = NULL, *uuid = NULL;
uint8_t *config = NULL;
int size = 0;
@@ -1632,6 +1669,8 @@ static DBusMessage *endpoint_set_configuration(DBusConnection *conn, DBusMessage
DBusMessage *r;
bool old_any_connected;
+ bbp = &y->backend_private;
+
if (!dbus_message_iter_init(m, &args) || !pa_streq(dbus_message_get_signature(m), "oa{sv}")) {
pa_log("Invalid signature for method SetConfiguration");
goto fail2;
@@ -1639,7 +1678,7 @@ static DBusMessage *endpoint_set_configuration(DBusConnection *conn, DBusMessage
dbus_message_iter_get_basic(&args, &path);
- if (pa_hashmap_get(y->transports, path)) {
+ if (pa_hashmap_get(bbp->transports, path)) {
pa_log("Endpoint SetConfiguration: Transport %s is already configured.", path);
goto fail2;
}
@@ -1720,9 +1759,9 @@ static DBusMessage *endpoint_set_configuration(DBusConnection *conn, DBusMessage
t->nrec = nrec;
d->transports[p] = t;
- pa_assert_se(pa_hashmap_put(y->transports, t->path, t) >= 0);
+ pa_assert_se(pa_hashmap_put(bbp->transports, path, t) >= 0);
- pa_log_debug("Transport %s profile %d available", t->path, t->profile);
+ pa_log_debug("Transport %s profile %d available", path, p);
pa_assert_se(r = dbus_message_new_method_return(m));
pa_assert_se(dbus_connection_send(pa_dbus_connection_get(y->connection), r, NULL));
@@ -1744,10 +1783,15 @@ fail2:
static DBusMessage *endpoint_clear_configuration(DBusConnection *c, DBusMessage *m, void *userdata) {
pa_bluetooth_discovery *y = userdata;
pa_bluetooth_transport *t;
+ bluez_backend_private *bbp;
DBusMessage *r;
DBusError e;
const char *path;
+ pa_assert(y);
+
+ bbp = &y->backend_private;
+
dbus_error_init(&e);
if (!dbus_message_get_args(m, &e, DBUS_TYPE_OBJECT_PATH, &path, DBUS_TYPE_INVALID)) {
@@ -1756,7 +1800,7 @@ static DBusMessage *endpoint_clear_configuration(DBusConnection *c, DBusMessage
goto fail;
}
- if ((t = pa_hashmap_get(y->transports, path)))
+ if ((t = pa_hashmap_remove(bbp->transports, path)))
pa_bt_backend_notify_transport_removed(t);
pa_assert_se(r = dbus_message_new_method_return(m));
@@ -1986,6 +2030,8 @@ pa_bluetooth_backend bluez_backend = {
static void bluez_backend_init(pa_bluetooth_discovery *y) {
bluez_backend_private *bbp = &y->backend_private;
+ bbp->transports = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func);
+
pa_bt_backend_register(y, &bluez_backend, PROFILE_A2DP, bbp);
pa_bt_backend_register(y, &bluez_backend, PROFILE_A2DP_SOURCE, bbp);
@@ -1997,6 +2043,8 @@ static void bluez_backend_init(pa_bluetooth_discovery *y) {
}
static void bluez_backend_done(pa_bluetooth_discovery *y) {
+ bluez_backend_private *bbp = &y->backend_private;
+
pa_bt_backend_unregister(y, &bluez_backend, PROFILE_A2DP);
pa_bt_backend_unregister(y, &bluez_backend, PROFILE_A2DP_SOURCE);
@@ -2005,6 +2053,11 @@ static void bluez_backend_done(pa_bluetooth_discovery *y) {
pa_bt_backend_unregister(y, &bluez_backend, PROFILE_HSP);
pa_bt_backend_unregister(y, &bluez_backend, PROFILE_HFGW);
+
+ if (bbp->transports) {
+ pa_assert(pa_hashmap_isempty(bbp->transports));
+ pa_hashmap_free(bbp->transports, NULL);
+ }
}
pa_bluetooth_discovery* pa_bluetooth_discovery_get(pa_core *c) {
@@ -2027,7 +2080,6 @@ pa_bluetooth_discovery* pa_bluetooth_discovery_get(pa_core *c) {
PA_REFCNT_INIT(y);
y->core = c;
y->devices = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func);
- y->transports = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func);
PA_LLIST_HEAD_INIT(pa_dbus_pending, y->pending);
for (i = 0; i < PA_BLUETOOTH_HOOK_MAX; i++)
@@ -2120,11 +2172,6 @@ void pa_bluetooth_discovery_unref(pa_bluetooth_discovery *y) {
pa_hashmap_free(y->devices, NULL);
}
- if (y->transports) {
- pa_assert(pa_hashmap_isempty(y->transports));
- pa_hashmap_free(y->transports, NULL);
- }
-
if (y->connection) {
dbus_connection_unregister_object_path(pa_dbus_connection_get(y->connection), HFP_AG_ENDPOINT);
dbus_connection_unregister_object_path(pa_dbus_connection_get(y->connection), HFP_HS_ENDPOINT);
@@ -2346,7 +2393,6 @@ void pa_bt_backend_notify_transport_removed(pa_bluetooth_transport *t) {
pa_log_debug("Removing transport for device %s profile %s", d->path, pa_bt_profile_to_string(t->profile));
d->transports[t->profile] = NULL;
- pa_hashmap_remove(y->transports, t->path);
t->state = PA_BLUETOOTH_TRANSPORT_STATE_DISCONNECTED;
pa_hook_fire(&y->hooks[PA_BLUETOOTH_HOOK_TRANSPORT_STATE_CHANGED], t);
diff --git a/src/modules/bluetooth/bluetooth-util.h b/src/modules/bluetooth/bluetooth-util.h
index 1a72ca6..a4d365e 100644
--- a/src/modules/bluetooth/bluetooth-util.h
+++ b/src/modules/bluetooth/bluetooth-util.h
@@ -91,8 +91,6 @@ typedef enum pa_bluetooth_transport_state {
struct pa_bluetooth_transport {
pa_bluetooth_device *device;
- char *owner;
- char *path;
enum profile profile;
uint8_t codec;
uint8_t *config;
@@ -102,6 +100,8 @@ struct pa_bluetooth_transport {
bool nrec;
uint16_t microphone_gain; /* Used for HSP/HFP */
uint16_t speaker_gain; /* Used for HSP/HFP */
+
+ void *backend_private;
};
/* This enum is shared among Audio, Headset, AudioSink, and AudioSource, although not all values are acceptable in all profiles */
--
1.8.1.4
More information about the pulseaudio-discuss
mailing list