From 87fcb3d5925cc030e957f55399f8c3e96c66cbb5 Mon Sep 17 00:00:00 2001 From: Marc-André Lureau Date: Fri, 27 Mar 2009 21:48:04 +0200 Subject: bluetooth: use new audio State properties --- src/modules/bluetooth/bluetooth-util.c | 109 ++++++++++++++++++++++----------- 1 file changed, 73 insertions(+), 36 deletions(-) (limited to 'src/modules/bluetooth/bluetooth-util.c') diff --git a/src/modules/bluetooth/bluetooth-util.c b/src/modules/bluetooth/bluetooth-util.c index dfebf663..771afff5 100644 --- a/src/modules/bluetooth/bluetooth-util.c +++ b/src/modules/bluetooth/bluetooth-util.c @@ -42,6 +42,22 @@ struct pa_bluetooth_discovery { static void get_properties_reply(DBusPendingCall *pending, void *userdata); static pa_dbus_pending* send_and_add_to_pending(pa_bluetooth_discovery *y, pa_bluetooth_device *d, DBusMessage *m, DBusPendingCallNotifyFunction func); +static enum pa_bt_audio_state pa_bt_audio_state_from_string(const char* value) { + pa_assert(value); + + if (pa_streq(value, "disconnected")) { + return PA_BT_AUDIO_STATE_DISCONNECTED; + } else if (pa_streq(value, "connecting")) { + return PA_BT_AUDIO_STATE_CONNECTING; + } else if (pa_streq(value, "connected")) { + return PA_BT_AUDIO_STATE_CONNECTED; + } else if (pa_streq(value, "playing")) { + return PA_BT_AUDIO_STATE_PLAYING; + } + + return PA_BT_AUDIO_STATE_INVALID; +} + static pa_bluetooth_uuid *uuid_new(const char *uuid) { pa_bluetooth_uuid *u; @@ -66,7 +82,7 @@ static pa_bluetooth_device* device_new(const char *path) { d->dead = FALSE; - d->device_info_valid = d->audio_sink_info_valid = d->headset_info_valid = 0; + d->device_info_valid = 0; d->name = NULL; d->path = pa_xstrdup(path); @@ -78,9 +94,9 @@ static pa_bluetooth_device* device_new(const char *path) { d->class = -1; d->trusted = -1; - d->audio_sink_connected = -1; - - d->headset_connected = -1; + d->audio_state = PA_BT_AUDIO_STATE_INVALID; + d->audio_sink_state = PA_BT_AUDIO_STATE_INVALID; + d->headset_state = PA_BT_AUDIO_STATE_INVALID; return d; } @@ -102,25 +118,14 @@ static void device_free(pa_bluetooth_device *d) { pa_xfree(d); } -static pa_bool_t device_is_loaded(pa_bluetooth_device *d) { - pa_assert(d); - - return - d->device_info_valid && - d->audio_sink_info_valid && - d->headset_info_valid; -} - static pa_bool_t device_is_audio(pa_bluetooth_device *d) { pa_assert(d); - pa_assert(d->device_info_valid); - pa_assert(d->audio_sink_info_valid); - pa_assert(d->headset_info_valid); - return - d->device_info_valid > 0 && - (d->audio_sink_info_valid > 0 || d->headset_info_valid > 0); + d->device_info_valid && + (d->audio_state != PA_BT_AUDIO_STATE_INVALID || + d->audio_sink_state != PA_BT_AUDIO_STATE_INVALID || + d->headset_state != PA_BT_AUDIO_STATE_INVALID); } static int parse_device_property(pa_bluetooth_discovery *y, pa_bluetooth_device *d, DBusMessageIter *i) { @@ -222,6 +227,11 @@ static int parse_device_property(pa_bluetooth_discovery *y, pa_bluetooth_device node = uuid_new(value); PA_LLIST_PREPEND(pa_bluetooth_uuid, d->uuids, node); + /* this might eventually be racy if .Audio is not there yet, but the State change will come anyway later, so this call is for cold-detection mostly */ + pa_assert_se(m = dbus_message_new_method_call("org.bluez", d->path, "org.bluez.Audio", "GetProperties")); + send_and_add_to_pending(y, d, m, get_properties_reply); + + /* Vudentz said the interfaces are here when the UUIDs are announced */ if (strcasecmp(HSP_HS_UUID, value) == 0 || strcasecmp(HFP_HS_UUID, value) == 0) { pa_assert_se(m = dbus_message_new_method_call("org.bluez", d->path, "org.bluez.Headset", "GetProperties")); send_and_add_to_pending(y, d, m, get_properties_reply); @@ -242,12 +252,12 @@ static int parse_device_property(pa_bluetooth_discovery *y, pa_bluetooth_device return 0; } -static int parse_audio_property(pa_bluetooth_discovery *u, int *connected, DBusMessageIter *i) { +static int parse_audio_property(pa_bluetooth_discovery *u, int *state, DBusMessageIter *i) { const char *key; DBusMessageIter variant_i; pa_assert(u); - pa_assert(connected); + pa_assert(state); pa_assert(i); if (dbus_message_iter_get_arg_type(i) != DBUS_TYPE_STRING) { @@ -269,17 +279,27 @@ static int parse_audio_property(pa_bluetooth_discovery *u, int *connected, DBusM dbus_message_iter_recurse(i, &variant_i); -/* pa_log_debug("Parsing property org.bluez.{AudioSink|Headset}.%s", key); */ +/* pa_log_debug("Parsing property org.bluez.{Audio|AudioSink|Headset}.%s", key); */ switch (dbus_message_iter_get_arg_type(&variant_i)) { + case DBUS_TYPE_STRING: { + + const char *value; + dbus_message_iter_get_basic(&variant_i, &value); + + if (pa_streq(key, "State")) + *state = pa_bt_audio_state_from_string(value); +/* pa_log_debug("Value %s", value); */ + } + case DBUS_TYPE_BOOLEAN: { dbus_bool_t value; dbus_message_iter_get_basic(&variant_i, &value); - if (pa_streq(key, "Connected")) - *connected = !!value; + /* if (pa_streq(key, "Connected")) */ + /* *connected = !!value; */ /* pa_log_debug("Value %s", pa_yes_no(value)); */ @@ -294,9 +314,6 @@ static void run_callback(pa_bluetooth_discovery *y, pa_bluetooth_device *d, pa_b pa_assert(y); pa_assert(d); - if (!device_is_loaded(d)) - return; - if (!device_is_audio(d)) return; @@ -326,10 +343,6 @@ static void get_properties_reply(DBusPendingCall *pending, void *userdata) { if (dbus_message_is_method_call(p->message, "org.bluez.Device", "GetProperties")) d->device_info_valid = valid; - else if (dbus_message_is_method_call(p->message, "org.bluez.Headset", "GetProperties")) - d->headset_info_valid = valid; - else if (dbus_message_is_method_call(p->message, "org.bluez.AudioSink", "GetProperties")) - d->audio_sink_info_valid = valid; if (dbus_message_get_type(r) == DBUS_MESSAGE_TYPE_ERROR) { @@ -361,12 +374,16 @@ static void get_properties_reply(DBusPendingCall *pending, void *userdata) { if (parse_device_property(y, d, &dict_i) < 0) goto finish; + } else if (dbus_message_has_interface(p->message, "org.bluez.Audio")) { + 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_connected, &dict_i) < 0) + 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_connected, &dict_i) < 0) + if (parse_audio_property(y, &d->audio_sink_state, &dict_i) < 0) goto finish; } } @@ -572,7 +589,8 @@ static DBusHandlerResult filter_cb(DBusConnection *bus, DBusMessage *m, void *us found_adapter(y, path); return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - } else if (dbus_message_is_signal(m, "org.bluez.Headset", "PropertyChanged") || + } else if (dbus_message_is_signal(m, "org.bluez.Audio", "PropertyChanged") || + dbus_message_is_signal(m, "org.bluez.Headset", "PropertyChanged") || dbus_message_is_signal(m, "org.bluez.AudioSink", "PropertyChanged") || dbus_message_is_signal(m, "org.bluez.Device", "PropertyChanged")) { @@ -590,12 +608,16 @@ static DBusHandlerResult filter_cb(DBusConnection *bus, DBusMessage *m, void *us if (parse_device_property(y, d, &arg_i) < 0) goto fail; + } else if (dbus_message_has_interface(m, "org.bluez.Audio")) { + 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_connected, &arg_i) < 0) + if (parse_audio_property(y, &d->headset_state, &arg_i) < 0) goto fail; } else if (dbus_message_has_interface(m, "org.bluez.AudioSink")) { - if (parse_audio_property(y, &d->audio_sink_connected, &arg_i) < 0) + if (parse_audio_property(y, &d->audio_sink_state, &arg_i) < 0) goto fail; } @@ -690,6 +712,7 @@ pa_bluetooth_discovery* pa_bluetooth_discovery_get(pa_core *c) { "type='signal',sender='org.bluez',interface='org.bluez.Adapter',member='DeviceRemoved'", "type='signal',sender='org.bluez',interface='org.bluez.Adapter',member='DeviceCreated'", "type='signal',sender='org.bluez',interface='org.bluez.Device',member='PropertyChanged'", + "type='signal',sender='org.bluez',interface='org.bluez.Audio',member='PropertyChanged'", "type='signal',sender='org.bluez',interface='org.bluez.Headset',member='PropertyChanged'", "type='signal',sender='org.bluez',interface='org.bluez.AudioSink',member='PropertyChanged'", NULL) < 0) { pa_log("Failed to add D-Bus matches: %s", err.message); @@ -746,6 +769,7 @@ void pa_bluetooth_discovery_unref(pa_bluetooth_discovery *y) { "type='signal',sender='org.bluez',interface='org.bluez.Adapter',member='DeviceRemoved'", "type='signal',sender='org.bluez',interface='org.bluez.Adapter',member='DeviceCreated'", "type='signal',sender='org.bluez',interface='org.bluez.Device',member='PropertyChanged'", + "type='signal',sender='org.bluez',interface='org.bluez.Audio',member='PropertyChanged'", "type='signal',sender='org.bluez',interface='org.bluez.Headset',member='PropertyChanged'", "type='signal',sender='org.bluez',interface='org.bluez.AudioSink',member='PropertyChanged'", NULL); @@ -833,3 +857,16 @@ char *pa_bluetooth_cleanup_name(const char *name) { return t; } + +pa_bool_t pa_bluetooth_uuid_has(pa_bluetooth_uuid *uuids, const char *uuid) { + pa_assert(uuid); + + while (uuids) { + if (strcasecmp(uuids->uuid, uuid) == 0) + return TRUE; + + uuids = uuids->next; + } + + return FALSE; +} -- cgit