[pulseaudio-discuss] [PATCH next v0 04/11] bluetooth: Use array to store profile states

Mikel Astiz mikel.astiz.oss at gmail.com
Thu Dec 6 06:55:29 PST 2012


From: Mikel Astiz <mikel.astiz at bmw-carit.de>

Refactor the code to use an array of states instead of independent
member fields, avoiding duplicated code and improving readability.
---
 src/modules/bluetooth/bluetooth-util.c          | 81 ++++++++++++++-----------
 src/modules/bluetooth/bluetooth-util.h          | 13 +---
 src/modules/bluetooth/module-bluetooth-device.c | 59 +++++-------------
 3 files changed, 62 insertions(+), 91 deletions(-)

diff --git a/src/modules/bluetooth/bluetooth-util.c b/src/modules/bluetooth/bluetooth-util.c
index 6f784d1..4986501 100644
--- a/src/modules/bluetooth/bluetooth-util.c
+++ b/src/modules/bluetooth/bluetooth-util.c
@@ -93,6 +93,24 @@ pa_bt_audio_state_t pa_bt_audio_state_from_string(const char* value) {
     return PA_BT_AUDIO_STATE_INVALID;
 }
 
+static bool pa_bt_audio_profile_from_interface(const char *interface, enum profile *p) {
+    if (pa_streq(interface, "org.bluez.AudioSink")) {
+        *p = PROFILE_A2DP;
+        return true;
+    } else if (pa_streq(interface, "org.bluez.AudioSource")) {
+        *p = PROFILE_A2DP_SOURCE;
+        return true;
+    } else if (pa_streq(interface, "org.bluez.Headset")) {
+        *p = PROFILE_HSP;
+        return true;
+    } else if (pa_streq(interface, "org.bluez.HandsfreeGateway")) {
+        *p = PROFILE_HFGW;
+        return true;
+    }
+
+    return false;
+}
+
 static pa_bluetooth_uuid *uuid_new(const char *uuid) {
     pa_bluetooth_uuid *u;
 
@@ -112,6 +130,7 @@ static void uuid_free(pa_bluetooth_uuid *u) {
 
 static pa_bluetooth_device* device_new(pa_bluetooth_discovery *discovery, const char *path) {
     pa_bluetooth_device *d;
+    unsigned i;
 
     pa_assert(discovery);
     pa_assert(path);
@@ -133,10 +152,9 @@ static pa_bluetooth_device* device_new(pa_bluetooth_discovery *discovery, const
     d->trusted = -1;
 
     d->audio_state = PA_BT_AUDIO_STATE_INVALID;
-    d->audio_sink_state = PA_BT_AUDIO_STATE_INVALID;
-    d->audio_source_state = PA_BT_AUDIO_STATE_INVALID;
-    d->headset_state = PA_BT_AUDIO_STATE_INVALID;
-    d->hfgw_state = PA_BT_AUDIO_STATE_INVALID;
+
+    for (i = 0; i < PA_BLUETOOTH_PROFILE_COUNT; i++)
+        d->profile_state[i] = PA_BT_AUDIO_STATE_INVALID;
 
     return d;
 }
@@ -185,14 +203,18 @@ static void device_free(pa_bluetooth_device *d) {
 }
 
 static pa_bool_t device_is_audio_ready(const pa_bluetooth_device *d) {
+    unsigned i;
+
     pa_assert(d);
 
-    return
-        d->device_info_valid && d->audio_state != PA_BT_AUDIO_STATE_INVALID &&
-        (d->audio_sink_state != PA_BT_AUDIO_STATE_INVALID ||
-         d->audio_source_state != PA_BT_AUDIO_STATE_INVALID ||
-         d->headset_state != PA_BT_AUDIO_STATE_INVALID ||
-         d->hfgw_state != PA_BT_AUDIO_STATE_INVALID);
+    if (!d->device_info_valid || d->audio_state == PA_BT_AUDIO_STATE_INVALID)
+        return FALSE;
+
+    for (i = 0; i < PA_BLUETOOTH_PROFILE_COUNT; i++)
+        if (d->profile_state[i] != PA_BT_AUDIO_STATE_INVALID)
+            return TRUE;
+
+    return FALSE;
 }
 
 static const char *check_variant_property(DBusMessageIter *i) {
@@ -570,6 +592,7 @@ static void get_properties_reply(DBusPendingCall *pending, void *userdata) {
 
         if (dbus_message_iter_get_arg_type(&element_i) == DBUS_TYPE_DICT_ENTRY) {
             DBusMessageIter dict_i;
+            enum profile profile;
 
             dbus_message_iter_recurse(&element_i, &dict_i);
 
@@ -589,22 +612,13 @@ static void get_properties_reply(DBusPendingCall *pending, void *userdata) {
                 if (parse_audio_property(y, &d->audio_state, &dict_i) < 0)
                     goto finish;
 
-            } else if (dbus_message_has_interface(p->message, "org.bluez.Headset")) {
-                if (parse_audio_property(y, &d->headset_state, &dict_i) < 0)
-                    goto finish;
-
-            }  else if (dbus_message_has_interface(p->message, "org.bluez.AudioSink")) {
-                if (parse_audio_property(y, &d->audio_sink_state, &dict_i) < 0)
-                    goto finish;
+            } else if (pa_bt_audio_profile_from_interface(dbus_message_get_interface(p->message), &profile)) {
+                pa_bt_audio_state_t state;
 
-            }  else if (dbus_message_has_interface(p->message, "org.bluez.AudioSource")) {
-                if (parse_audio_property(y, &d->audio_source_state, &dict_i) < 0)
-                    goto finish;
-
-            }  else if (dbus_message_has_interface(p->message, "org.bluez.HandsfreeGateway")) {
-                if (parse_audio_property(y, &d->hfgw_state, &dict_i) < 0)
+                if (parse_audio_property(y, &state, &dict_i) < 0)
                     goto finish;
 
+                d->profile_state[profile] = state;
             }
         }
 
@@ -846,6 +860,7 @@ static DBusHandlerResult filter_cb(DBusConnection *bus, DBusMessage *m, void *us
 
         if ((d = pa_hashmap_get(y->devices, dbus_message_get_path(m)))) {
             DBusMessageIter arg_i;
+            enum profile profile;
             bool old_any_connected = pa_bluetooth_device_any_audio_connected(d);
 
             if (!dbus_message_iter_init(m, &arg_i)) {
@@ -861,21 +876,13 @@ static DBusHandlerResult filter_cb(DBusConnection *bus, DBusMessage *m, void *us
                 if (parse_audio_property(y, &d->audio_state, &arg_i) < 0)
                     goto fail;
 
-            } else if (dbus_message_has_interface(m, "org.bluez.Headset")) {
-                if (parse_audio_property(y, &d->headset_state, &arg_i) < 0)
-                    goto fail;
+            } else if (pa_bt_audio_profile_from_interface(dbus_message_get_interface(m), &profile)) {
+                pa_bt_audio_state_t state;
 
-            }  else if (dbus_message_has_interface(m, "org.bluez.AudioSink")) {
-                if (parse_audio_property(y, &d->audio_sink_state, &arg_i) < 0)
+                if (parse_audio_property(y, &state, &arg_i) < 0)
                     goto fail;
 
-            }  else if (dbus_message_has_interface(m, "org.bluez.AudioSource")) {
-                if (parse_audio_property(y, &d->audio_source_state, &arg_i) < 0)
-                    goto fail;
-
-            }  else if (dbus_message_has_interface(m, "org.bluez.HandsfreeGateway")) {
-                if (parse_audio_property(y, &d->hfgw_state, &arg_i) < 0)
-                    goto fail;
+                d->profile_state[profile] = state;
             }
 
             if (old_any_connected != pa_bluetooth_device_any_audio_connected(d))
@@ -989,8 +996,8 @@ bool pa_bluetooth_device_any_audio_connected(const pa_bluetooth_device *d) {
      * loaded. */
     return
         d->audio_state >= PA_BT_AUDIO_STATE_CONNECTED ||
-        d->audio_source_state >= PA_BT_AUDIO_STATE_CONNECTED ||
-        d->hfgw_state >= PA_BT_AUDIO_STATE_CONNECTED;
+        d->profile_state[PROFILE_A2DP_SOURCE] >= PA_BT_AUDIO_STATE_CONNECTED ||
+        d->profile_state[PROFILE_HFGW] >= PA_BT_AUDIO_STATE_CONNECTED;
 }
 
 int pa_bluetooth_transport_acquire(pa_bluetooth_transport *t, const char *accesstype, size_t *imtu, size_t *omtu) {
diff --git a/src/modules/bluetooth/bluetooth-util.h b/src/modules/bluetooth/bluetooth-util.h
index ecc663c..35f91df 100644
--- a/src/modules/bluetooth/bluetooth-util.h
+++ b/src/modules/bluetooth/bluetooth-util.h
@@ -126,17 +126,8 @@ struct pa_bluetooth_device {
     /* Audio state */
     pa_bt_audio_state_t audio_state;
 
-    /* AudioSink state */
-    pa_bt_audio_state_t audio_sink_state;
-
-    /* AudioSource state */
-    pa_bt_audio_state_t audio_source_state;
-
-    /* Headset state */
-    pa_bt_audio_state_t headset_state;
-
-    /* HandsfreeGateway state */
-    pa_bt_audio_state_t hfgw_state;
+    /* AudioSink, AudioSource, Headset and HandsfreeGateway states */
+    pa_bt_audio_state_t profile_state[PA_BLUETOOTH_PROFILE_COUNT];
 };
 
 pa_bluetooth_discovery* pa_bluetooth_discovery_get(pa_core *core);
diff --git a/src/modules/bluetooth/module-bluetooth-device.c b/src/modules/bluetooth/module-bluetooth-device.c
index 649e73f..83b18f3 100644
--- a/src/modules/bluetooth/module-bluetooth-device.c
+++ b/src/modules/bluetooth/module-bluetooth-device.c
@@ -366,23 +366,6 @@ static void bt_transport_release(struct userdata *u) {
     teardown_stream(u);
 }
 
-static pa_bt_audio_state_t get_profile_audio_state(const struct userdata *u, const pa_bluetooth_device *d) {
-    switch(u->profile) {
-        case PROFILE_HSP:
-            return d->headset_state;
-        case PROFILE_A2DP:
-            return d->audio_sink_state;
-        case PROFILE_A2DP_SOURCE:
-            return d->audio_source_state;
-        case PROFILE_HFGW:
-            return d->hfgw_state;
-        case PROFILE_OFF:
-            break;
-    }
-
-    pa_assert_not_reached();
-}
-
 static int bt_transport_acquire(struct userdata *u, pa_bool_t start) {
     const char *accesstype = "rw";
 
@@ -404,7 +387,7 @@ static int bt_transport_acquire(struct userdata *u, pa_bool_t start) {
            suspended in the meantime, so we can't really guarantee that the
            stream will not be requested until BlueZ's API supports this
            atomically. */
-        if (get_profile_audio_state(u, u->device) < PA_BT_AUDIO_STATE_PLAYING) {
+        if (u->device->profile_state[u->profile] < PA_BT_AUDIO_STATE_PLAYING) {
             pa_log_info("Failed optional acquire of transport %s", u->transport->path);
             return -1;
         }
@@ -1368,7 +1351,7 @@ static DBusHandlerResult filter_cb(DBusConnection *bus, DBusMessage *m, void *us
             if (pa_hashmap_get(u->card->profiles, "a2dp") == NULL)
                 available = audio_state_to_availability(state);
             else
-                available = audio_state_to_availability_merged(state, u->device->audio_sink_state);
+                available = audio_state_to_availability_merged(state, u->device->profile_state[PROFILE_A2DP]);
 
             pa_assert_se(port = pa_hashmap_get(u->card->ports, "bluetooth-output"));
             pa_device_port_set_available(port, available);
@@ -1402,7 +1385,7 @@ static DBusHandlerResult filter_cb(DBusConnection *bus, DBusMessage *m, void *us
             if (pa_hashmap_get(u->card->profiles, "hsp") == NULL)
                 available = audio_state_to_availability(state);
             else
-                available = audio_state_to_availability_merged(state, u->device->headset_state);
+                available = audio_state_to_availability_merged(state, u->device->profile_state[PROFILE_HSP]);
 
             pa_assert_se(port = pa_hashmap_get(u->card->ports, "bluetooth-output"));
             pa_device_port_set_available(port, available);
@@ -2207,17 +2190,8 @@ static int card_set_profile(pa_card *c, pa_card_profile *new_profile) {
     if (*d != PROFILE_OFF) {
         const pa_bluetooth_device *device = u->device;
 
-        if (device->headset_state < PA_BT_AUDIO_STATE_CONNECTED && *d == PROFILE_HSP) {
-            pa_log_warn("HSP is not connected, refused to switch profile");
-            return -PA_ERR_IO;
-        } else if (device->audio_sink_state < PA_BT_AUDIO_STATE_CONNECTED && *d == PROFILE_A2DP) {
-            pa_log_warn("A2DP Sink is not connected, refused to switch profile");
-            return -PA_ERR_IO;
-        } else if (device->audio_source_state < PA_BT_AUDIO_STATE_CONNECTED && *d == PROFILE_A2DP_SOURCE) {
-            pa_log_warn("A2DP Source is not connected, refused to switch profile");
-            return -PA_ERR_IO;
-        } else if (device->hfgw_state < PA_BT_AUDIO_STATE_CONNECTED && *d == PROFILE_HFGW) {
-            pa_log_warn("HandsfreeGateway is not connected, refused to switch profile");
+        if (device->profile_state[*d] < PA_BT_AUDIO_STATE_CONNECTED) {
+            pa_log_warn("Profile not connected, refused to switch profile to %s", new_profile->name);
             return -PA_ERR_IO;
         }
     }
@@ -2262,7 +2236,8 @@ static void create_ports_for_profile(struct userdata *u, pa_hashmap *ports, pa_c
         case PROFILE_A2DP:
             if ((port = pa_hashmap_get(ports, "bluetooth-output")) != NULL) {
                 port->priority = PA_MAX(port->priority, profile->priority * 100);
-                port->available = audio_state_to_availability_merged(device->headset_state, device->audio_sink_state);
+                port->available = audio_state_to_availability_merged(device->profile_state[PROFILE_HSP],
+                                                                     device->profile_state[PROFILE_A2DP]);
                 pa_hashmap_put(port->profiles, profile->name, profile);
             } else {
                 pa_assert_se(port = pa_device_port_new(u->core, "bluetooth-output", _("Bluetooth Output"), 0));
@@ -2270,7 +2245,7 @@ static void create_ports_for_profile(struct userdata *u, pa_hashmap *ports, pa_c
                 port->is_output = 1;
                 port->is_input = 0;
                 port->priority = profile->priority * 100;
-                port->available = audio_state_to_availability(device->audio_sink_state);
+                port->available = audio_state_to_availability(device->profile_state[*d]);
                 pa_hashmap_put(port->profiles, profile->name, profile);
             }
 
@@ -2282,14 +2257,15 @@ static void create_ports_for_profile(struct userdata *u, pa_hashmap *ports, pa_c
             port->is_output = 0;
             port->is_input = 1;
             port->priority = profile->priority * 100;
-            port->available = audio_state_to_availability(device->audio_source_state);
+            port->available = audio_state_to_availability(device->profile_state[*d]);
             pa_hashmap_put(port->profiles, profile->name, profile);
             break;
 
         case PROFILE_HSP:
             if ((port = pa_hashmap_get(ports, "bluetooth-output")) != NULL) {
                 port->priority = PA_MAX(port->priority, profile->priority * 100);
-                port->available = audio_state_to_availability_merged(device->headset_state, device->audio_sink_state);
+                port->available = audio_state_to_availability_merged(device->profile_state[PROFILE_HSP],
+                                                                     device->profile_state[PROFILE_A2DP]);
                 pa_hashmap_put(port->profiles, profile->name, profile);
             } else {
                 pa_assert_se(port = pa_device_port_new(u->core, "bluetooth-output", _("Bluetooth Output"), 0));
@@ -2297,7 +2273,7 @@ static void create_ports_for_profile(struct userdata *u, pa_hashmap *ports, pa_c
                 port->is_output = 1;
                 port->is_input = 0;
                 port->priority = profile->priority * 100;
-                port->available = audio_state_to_availability(device->headset_state);
+                port->available = audio_state_to_availability(device->profile_state[*d]);
                 pa_hashmap_put(port->profiles, profile->name, profile);
             }
 
@@ -2306,7 +2282,7 @@ static void create_ports_for_profile(struct userdata *u, pa_hashmap *ports, pa_c
             port->is_output = 0;
             port->is_input = 1;
             port->priority = profile->priority * 100;
-            port->available = audio_state_to_availability(device->headset_state);
+            port->available = audio_state_to_availability(device->profile_state[*d]);
             pa_hashmap_put(port->profiles, profile->name, profile);
             break;
 
@@ -2316,7 +2292,7 @@ static void create_ports_for_profile(struct userdata *u, pa_hashmap *ports, pa_c
             port->is_output = 1;
             port->is_input = 0;
             port->priority = profile->priority * 100;
-            port->available = audio_state_to_availability(device->hfgw_state);
+            port->available = audio_state_to_availability(device->profile_state[*d]);
             pa_hashmap_put(port->profiles, profile->name, profile);
 
             pa_assert_se(port = pa_device_port_new(u->core, "hfgw-input", _("Bluetooth Handsfree Gateway"), 0));
@@ -2324,7 +2300,7 @@ static void create_ports_for_profile(struct userdata *u, pa_hashmap *ports, pa_c
             port->is_output = 0;
             port->is_input = 1;
             port->priority = profile->priority * 100;
-            port->available = audio_state_to_availability(device->hfgw_state);
+            port->available = audio_state_to_availability(device->profile_state[*d]);
             pa_hashmap_put(port->profiles, profile->name, profile);
             break;
 
@@ -2466,10 +2442,7 @@ static int add_card(struct userdata *u) {
 
     d = PA_CARD_PROFILE_DATA(u->card->active_profile);
 
-    if ((device->headset_state < PA_BT_AUDIO_STATE_CONNECTED && *d == PROFILE_HSP) ||
-        (device->audio_sink_state < PA_BT_AUDIO_STATE_CONNECTED && *d == PROFILE_A2DP) ||
-        (device->audio_source_state < PA_BT_AUDIO_STATE_CONNECTED && *d == PROFILE_A2DP_SOURCE) ||
-        (device->hfgw_state < PA_BT_AUDIO_STATE_CONNECTED && *d == PROFILE_HFGW)) {
+    if (*d != PROFILE_OFF && (device->profile_state[*d] < PA_BT_AUDIO_STATE_CONNECTED)) {
         pa_log_warn("Default profile not connected, selecting off profile");
         u->card->active_profile = pa_hashmap_get(u->card->profiles, "off");
         u->card->save_profile = FALSE;
-- 
1.7.11.7



More information about the pulseaudio-discuss mailing list