bluetooth: Use array to store profile states

Refactor the code to use an array of states instead of independent
member fields, avoiding duplicated code and improving readability.
This commit is contained in:
Mikel Astiz 2012-12-06 15:55:29 +01:00 committed by Tanu Kaskinen
parent 689f9413ad
commit 726435045e
3 changed files with 67 additions and 93 deletions

View file

@ -93,6 +93,27 @@ pa_bt_audio_state_t pa_bt_audio_state_from_string(const char* value) {
return PA_BT_AUDIO_STATE_INVALID; return PA_BT_AUDIO_STATE_INVALID;
} }
static int profile_from_interface(const char *interface, enum profile *p) {
pa_assert(interface);
pa_assert(p);
if (pa_streq(interface, "org.bluez.AudioSink")) {
*p = PROFILE_A2DP;
return 0;
} else if (pa_streq(interface, "org.bluez.AudioSource")) {
*p = PROFILE_A2DP_SOURCE;
return 0;
} else if (pa_streq(interface, "org.bluez.Headset")) {
*p = PROFILE_HSP;
return 0;
} else if (pa_streq(interface, "org.bluez.HandsfreeGateway")) {
*p = PROFILE_HFGW;
return 0;
}
return -1;
}
static pa_bluetooth_uuid *uuid_new(const char *uuid) { static pa_bluetooth_uuid *uuid_new(const char *uuid) {
pa_bluetooth_uuid *u; pa_bluetooth_uuid *u;
@ -112,6 +133,7 @@ static void uuid_free(pa_bluetooth_uuid *u) {
static pa_bluetooth_device* device_new(pa_bluetooth_discovery *discovery, const char *path) { static pa_bluetooth_device* device_new(pa_bluetooth_discovery *discovery, const char *path) {
pa_bluetooth_device *d; pa_bluetooth_device *d;
unsigned i;
pa_assert(discovery); pa_assert(discovery);
pa_assert(path); pa_assert(path);
@ -133,10 +155,9 @@ static pa_bluetooth_device* device_new(pa_bluetooth_discovery *discovery, const
d->trusted = -1; d->trusted = -1;
d->audio_state = PA_BT_AUDIO_STATE_INVALID; 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; for (i = 0; i < PA_BLUETOOTH_PROFILE_COUNT; i++)
d->headset_state = PA_BT_AUDIO_STATE_INVALID; d->profile_state[i] = PA_BT_AUDIO_STATE_INVALID;
d->hfgw_state = PA_BT_AUDIO_STATE_INVALID;
return d; return d;
} }
@ -185,14 +206,18 @@ static void device_free(pa_bluetooth_device *d) {
} }
static pa_bool_t device_is_audio_ready(const pa_bluetooth_device *d) { static pa_bool_t device_is_audio_ready(const pa_bluetooth_device *d) {
unsigned i;
pa_assert(d); pa_assert(d);
return if (!d->device_info_valid || d->audio_state == PA_BT_AUDIO_STATE_INVALID)
d->device_info_valid && d->audio_state != PA_BT_AUDIO_STATE_INVALID && return FALSE;
(d->audio_sink_state != PA_BT_AUDIO_STATE_INVALID ||
d->audio_source_state != PA_BT_AUDIO_STATE_INVALID || for (i = 0; i < PA_BLUETOOTH_PROFILE_COUNT; i++)
d->headset_state != PA_BT_AUDIO_STATE_INVALID || if (d->profile_state[i] != PA_BT_AUDIO_STATE_INVALID)
d->hfgw_state != PA_BT_AUDIO_STATE_INVALID); return TRUE;
return FALSE;
} }
static const char *check_variant_property(DBusMessageIter *i) { static const char *check_variant_property(DBusMessageIter *i) {
@ -570,6 +595,7 @@ static void get_properties_reply(DBusPendingCall *pending, void *userdata) {
if (dbus_message_iter_get_arg_type(&element_i) == DBUS_TYPE_DICT_ENTRY) { if (dbus_message_iter_get_arg_type(&element_i) == DBUS_TYPE_DICT_ENTRY) {
DBusMessageIter dict_i; DBusMessageIter dict_i;
enum profile profile;
dbus_message_iter_recurse(&element_i, &dict_i); dbus_message_iter_recurse(&element_i, &dict_i);
@ -589,22 +615,13 @@ static void get_properties_reply(DBusPendingCall *pending, void *userdata) {
if (parse_audio_property(y, &d->audio_state, &dict_i) < 0) if (parse_audio_property(y, &d->audio_state, &dict_i) < 0)
goto finish; goto finish;
} else if (dbus_message_has_interface(p->message, "org.bluez.Headset")) { } else if (profile_from_interface(dbus_message_get_interface(p->message), &profile) >= 0) {
if (parse_audio_property(y, &d->headset_state, &dict_i) < 0) pa_bt_audio_state_t state;
goto finish;
if (parse_audio_property(y, &state, &dict_i) < 0)
} 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 (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)
goto finish; goto finish;
d->profile_state[profile] = state;
} }
} }
@ -846,6 +863,7 @@ static DBusHandlerResult filter_cb(DBusConnection *bus, DBusMessage *m, void *us
if ((d = pa_hashmap_get(y->devices, dbus_message_get_path(m)))) { if ((d = pa_hashmap_get(y->devices, dbus_message_get_path(m)))) {
DBusMessageIter arg_i; DBusMessageIter arg_i;
enum profile profile;
bool old_any_connected = pa_bluetooth_device_any_audio_connected(d); bool old_any_connected = pa_bluetooth_device_any_audio_connected(d);
if (!dbus_message_iter_init(m, &arg_i)) { if (!dbus_message_iter_init(m, &arg_i)) {
@ -861,21 +879,13 @@ static DBusHandlerResult filter_cb(DBusConnection *bus, DBusMessage *m, void *us
if (parse_audio_property(y, &d->audio_state, &arg_i) < 0) if (parse_audio_property(y, &d->audio_state, &arg_i) < 0)
goto fail; goto fail;
} else if (dbus_message_has_interface(m, "org.bluez.Headset")) { } else if (profile_from_interface(dbus_message_get_interface(m), &profile) >= 0) {
if (parse_audio_property(y, &d->headset_state, &arg_i) < 0) pa_bt_audio_state_t state;
if (parse_audio_property(y, &state, &arg_i) < 0)
goto fail; goto fail;
} else if (dbus_message_has_interface(m, "org.bluez.AudioSink")) { d->profile_state[profile] = state;
if (parse_audio_property(y, &d->audio_sink_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;
} }
if (old_any_connected != pa_bluetooth_device_any_audio_connected(d)) if (old_any_connected != pa_bluetooth_device_any_audio_connected(d))
@ -989,8 +999,8 @@ bool pa_bluetooth_device_any_audio_connected(const pa_bluetooth_device *d) {
* loaded. */ * loaded. */
return return
d->audio_state >= PA_BT_AUDIO_STATE_CONNECTED || d->audio_state >= PA_BT_AUDIO_STATE_CONNECTED ||
d->audio_source_state >= PA_BT_AUDIO_STATE_CONNECTED || d->profile_state[PROFILE_A2DP_SOURCE] >= PA_BT_AUDIO_STATE_CONNECTED ||
d->hfgw_state >= 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) { int pa_bluetooth_transport_acquire(pa_bluetooth_transport *t, const char *accesstype, size_t *imtu, size_t *omtu) {

View file

@ -126,17 +126,8 @@ struct pa_bluetooth_device {
/* Audio state */ /* Audio state */
pa_bt_audio_state_t audio_state; pa_bt_audio_state_t audio_state;
/* AudioSink state */ /* AudioSink, AudioSource, Headset and HandsfreeGateway states */
pa_bt_audio_state_t audio_sink_state; pa_bt_audio_state_t profile_state[PA_BLUETOOTH_PROFILE_COUNT];
/* 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;
}; };
pa_bluetooth_discovery* pa_bluetooth_discovery_get(pa_core *core); pa_bluetooth_discovery* pa_bluetooth_discovery_get(pa_core *core);

View file

@ -366,23 +366,6 @@ static void bt_transport_release(struct userdata *u) {
teardown_stream(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) { static int bt_transport_acquire(struct userdata *u, pa_bool_t start) {
const char *accesstype = "rw"; 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 suspended in the meantime, so we can't really guarantee that the
stream will not be requested until BlueZ's API supports this stream will not be requested until BlueZ's API supports this
atomically. */ 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); pa_log_info("Failed optional acquire of transport %s", u->transport->path);
return -1; 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) if (pa_hashmap_get(u->card->profiles, "a2dp") == NULL)
available = audio_state_to_availability(state); available = audio_state_to_availability(state);
else 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_assert_se(port = pa_hashmap_get(u->card->ports, "bluetooth-output"));
pa_device_port_set_available(port, available); 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) if (pa_hashmap_get(u->card->profiles, "hsp") == NULL)
available = audio_state_to_availability(state); available = audio_state_to_availability(state);
else 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_assert_se(port = pa_hashmap_get(u->card->ports, "bluetooth-output"));
pa_device_port_set_available(port, available); 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) { if (*d != PROFILE_OFF) {
const pa_bluetooth_device *device = u->device; const pa_bluetooth_device *device = u->device;
if (device->headset_state < PA_BT_AUDIO_STATE_CONNECTED && *d == PROFILE_HSP) { if (device->profile_state[*d] < PA_BT_AUDIO_STATE_CONNECTED) {
pa_log_warn("HSP is not connected, refused to switch profile"); pa_log_warn("Profile not connected, refused to switch profile to %s", new_profile->name);
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");
return -PA_ERR_IO; 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: case PROFILE_A2DP:
if ((port = pa_hashmap_get(ports, "bluetooth-output")) != NULL) { if ((port = pa_hashmap_get(ports, "bluetooth-output")) != NULL) {
port->priority = PA_MAX(port->priority, profile->priority * 100); 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); pa_hashmap_put(port->profiles, profile->name, profile);
} else { } else {
pa_assert_se(port = pa_device_port_new(u->core, "bluetooth-output", _("Bluetooth Output"), 0)); 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_output = 1;
port->is_input = 0; port->is_input = 0;
port->priority = profile->priority * 100; 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); 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_output = 0;
port->is_input = 1; port->is_input = 1;
port->priority = profile->priority * 100; 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); pa_hashmap_put(port->profiles, profile->name, profile);
break; break;
case PROFILE_HSP: case PROFILE_HSP:
if ((port = pa_hashmap_get(ports, "bluetooth-output")) != NULL) { if ((port = pa_hashmap_get(ports, "bluetooth-output")) != NULL) {
port->priority = PA_MAX(port->priority, profile->priority * 100); 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); pa_hashmap_put(port->profiles, profile->name, profile);
} else { } else {
pa_assert_se(port = pa_device_port_new(u->core, "bluetooth-output", _("Bluetooth Output"), 0)); 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_output = 1;
port->is_input = 0; port->is_input = 0;
port->priority = profile->priority * 100; 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); 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_output = 0;
port->is_input = 1; port->is_input = 1;
port->priority = profile->priority * 100; 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); pa_hashmap_put(port->profiles, profile->name, profile);
break; 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_output = 1;
port->is_input = 0; port->is_input = 0;
port->priority = profile->priority * 100; 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_hashmap_put(port->profiles, profile->name, profile);
pa_assert_se(port = pa_device_port_new(u->core, "hfgw-input", _("Bluetooth Handsfree Gateway"), 0)); 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_output = 0;
port->is_input = 1; port->is_input = 1;
port->priority = profile->priority * 100; 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_hashmap_put(port->profiles, profile->name, profile);
break; break;
@ -2466,10 +2442,7 @@ static int add_card(struct userdata *u) {
d = PA_CARD_PROFILE_DATA(u->card->active_profile); d = PA_CARD_PROFILE_DATA(u->card->active_profile);
if ((device->headset_state < PA_BT_AUDIO_STATE_CONNECTED && *d == PROFILE_HSP) || if (*d != PROFILE_OFF && (device->profile_state[*d] < PA_BT_AUDIO_STATE_CONNECTED)) {
(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)) {
pa_log_warn("Default profile not connected, selecting off profile"); pa_log_warn("Default profile not connected, selecting off profile");
u->card->active_profile = pa_hashmap_get(u->card->profiles, "off"); u->card->active_profile = pa_hashmap_get(u->card->profiles, "off");
u->card->save_profile = FALSE; u->card->save_profile = FALSE;