From: Jo?o Paulo Rechi Vita <jprvita@xxxxxxxxxxxxx> --- src/modules/bluetooth/bluez5-util.c | 84 +++++++++++++++++++++++++++++++++++++ src/modules/bluetooth/bluez5-util.h | 1 + 2 files changed, 85 insertions(+) diff --git a/src/modules/bluetooth/bluez5-util.c b/src/modules/bluetooth/bluez5-util.c index e29a19a..45052a2 100644 --- a/src/modules/bluetooth/bluez5-util.c +++ b/src/modules/bluetooth/bluez5-util.c @@ -253,6 +253,79 @@ bool pa_bluetooth_device_any_transport_connected(const pa_bluetooth_device *d) { return false; } +static pa_bluetooth_transport_state_t transport_state_from_string(const char* value, pa_bluetooth_transport_state_t *state) { + pa_assert(value); + pa_assert(state); + + if (pa_streq(value, "idle")) + *state = PA_BLUETOOTH_TRANSPORT_STATE_IDLE; + else if (pa_streq(value, "pending") || pa_streq(value, "active")) + *state = PA_BLUETOOTH_TRANSPORT_STATE_PLAYING; + else + return PA_BLUETOOTH_TRANSPORT_STATE_INVALID; + + return 0; +} + +static void parse_transport_property(pa_bluetooth_transport *t, DBusMessageIter *i) { + const char *key; + DBusMessageIter variant_i; + + key = pa_bluetooth_dbus_check_variant_property(i); + if (key == NULL) + return; + + dbus_message_iter_recurse(i, &variant_i); + + 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")) { + bool old_any_connected = pa_bluetooth_device_any_transport_connected(t->device); + + if (transport_state_from_string(value, &t->state) == PA_BLUETOOTH_TRANSPORT_STATE_INVALID) { + pa_log_error("Transport %s has an invalid state: '%s'", t->path, value); + return; + } + + pa_log_debug("Transport %s state changed to '%s'", t->path, value); + pa_hook_fire(&t->device->discovery->hooks[PA_BLUETOOTH_HOOK_TRANSPORT_STATE_CHANGED], t); + + if (old_any_connected != pa_bluetooth_device_any_transport_connected(t->device)) { + t->device->dead = old_any_connected; + pa_hook_fire(&t->device->discovery->hooks[PA_BLUETOOTH_HOOK_DEVICE_CONNECTION_CHANGED], t->device); + } + } + + break; + } + } + + return; +} + +static int parse_transport_properties(pa_bluetooth_transport *t, DBusMessageIter *i) { + DBusMessageIter element_i; + + dbus_message_iter_recurse(i, &element_i); + + while (dbus_message_iter_get_arg_type(&element_i) == DBUS_TYPE_DICT_ENTRY) { + DBusMessageIter dict_i; + + dbus_message_iter_recurse(&element_i, &dict_i); + + parse_transport_property(t, &dict_i); + + dbus_message_iter_next(&element_i); + } + + return 0; +} + static pa_bluetooth_uuid *pa_bluetooth_uuid_new(const char *uuid) { pa_bluetooth_uuid *u; @@ -793,6 +866,13 @@ static DBusHandlerResult filter_cb(DBusConnection *bus, DBusMessage *m, void *us } parse_device_properties(d, &arg_i, true); + } else if (pa_streq(iface, BLUEZ_MEDIA_TRANSPORT_INTERFACE)) { + pa_bluetooth_transport *t; + + if (!(t = pa_hashmap_get(y->transports, dbus_message_get_path(m)))) + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + + parse_transport_properties(t, &arg_i); } return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; @@ -1238,6 +1318,8 @@ pa_bluetooth_discovery* pa_bluetooth_discovery_get(pa_core *c) { "type='signal',sender='" BLUEZ_SERVICE "',interface='org.freedesktop.DBus.ObjectManager',member='InterfacesRemoved'", "type='signal',sender='" BLUEZ_SERVICE "',interface='org.freedesktop.DBus.Properties',member='PropertiesChanged'" ",arg0='" BLUEZ_DEVICE_INTERFACE "'", + "type='signal',sender='" BLUEZ_SERVICE "',interface='org.freedesktop.DBus.Properties',member='PropertiesChanged'" + ",arg0='" BLUEZ_MEDIA_TRANSPORT_INTERFACE "'", NULL) < 0) { pa_log_error("Failed to add D-Bus matches: %s", err.message); goto fail; @@ -1293,6 +1375,8 @@ void pa_bluetooth_discovery_unref(pa_bluetooth_discovery *y) { "type='signal',sender='" BLUEZ_SERVICE "',interface='org.freedesktop.DBus.ObjectManager',member='InterfacesRemoved'", "type='signal',sender='" BLUEZ_SERVICE "',interface='org.freedesktop.DBus.Properties',member='PropertiesChanged'" ",arg0='" BLUEZ_DEVICE_INTERFACE "'", + "type='signal',sender='" BLUEZ_SERVICE "',interface='org.freedesktop.DBus.Properties',member='PropertiesChanged'" + ",arg0='" BLUEZ_MEDIA_TRANSPORT_INTERFACE "'", NULL); if (y->filter_added) diff --git a/src/modules/bluetooth/bluez5-util.h b/src/modules/bluetooth/bluez5-util.h index b1a112f..cf90003 100644 --- a/src/modules/bluetooth/bluez5-util.h +++ b/src/modules/bluetooth/bluez5-util.h @@ -46,6 +46,7 @@ typedef enum profile { #define PA_BLUETOOTH_PROFILE_COUNT PROFILE_OFF typedef enum pa_bluetooth_transport_state { + PA_BLUETOOTH_TRANSPORT_STATE_INVALID = -1, PA_BLUETOOTH_TRANSPORT_STATE_DISCONNECTED, PA_BLUETOOTH_TRANSPORT_STATE_IDLE, PA_BLUETOOTH_TRANSPORT_STATE_PLAYING -- 1.7.11.7