diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/modules/bluetooth/bluetooth-util.c | 72 | ||||
-rw-r--r-- | src/modules/bluetooth/bluetooth-util.h | 2 | ||||
-rw-r--r-- | src/modules/bluetooth/module-bluetooth-device.c | 86 |
3 files changed, 112 insertions, 48 deletions
diff --git a/src/modules/bluetooth/bluetooth-util.c b/src/modules/bluetooth/bluetooth-util.c index 17ba1302..9c679687 100644 --- a/src/modules/bluetooth/bluetooth-util.c +++ b/src/modules/bluetooth/bluetooth-util.c @@ -714,6 +714,47 @@ static void list_adapters(pa_bluetooth_discovery *y) { send_and_add_to_pending(y, NULL, m, list_adapters_reply); } +int pa_bluetooth_transport_parse_property(pa_bluetooth_transport *t, DBusMessageIter *i) +{ + const char *key; + DBusMessageIter variant_i; + + if (dbus_message_iter_get_arg_type(i) != DBUS_TYPE_STRING) { + pa_log("Property name not a string."); + return -1; + } + + dbus_message_iter_get_basic(i, &key); + + if (!dbus_message_iter_next(i)) { + pa_log("Property value missing"); + return -1; + } + + if (dbus_message_iter_get_arg_type(i) != DBUS_TYPE_VARIANT) { + pa_log("Property value not a variant."); + return -1; + } + + dbus_message_iter_recurse(i, &variant_i); + + switch (dbus_message_iter_get_arg_type(&variant_i)) { + + case DBUS_TYPE_BOOLEAN: { + + pa_bool_t *value; + dbus_message_iter_get_basic(&variant_i, &value); + + if (pa_streq(key, "NREC")) + t->nrec = value; + + break; + } + } + + return 0; +} + static DBusHandlerResult filter_cb(DBusConnection *bus, DBusMessage *m, void *userdata) { DBusError err; pa_bluetooth_discovery *y; @@ -862,6 +903,28 @@ static DBusHandlerResult filter_cb(DBusConnection *bus, DBusMessage *m, void *us } return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + } else if (dbus_message_is_signal(m, "org.bluez.MediaTransport", "PropertyChanged")) { + pa_bluetooth_device *d; + pa_bluetooth_transport *t; + void *state = NULL; + DBusMessageIter arg_i; + + while ((d = pa_hashmap_iterate(y->devices, &state, NULL))) + if ((t = pa_hashmap_get(d->transports, dbus_message_get_path(m)))) + break; + + if (!t) + goto fail; + + if (!dbus_message_iter_init(m, &arg_i)) { + pa_log("Failed to parse PropertyChanged: %s", err.message); + goto fail; + } + + if (pa_bluetooth_transport_parse_property(t, &arg_i) < 0) + goto fail; + + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; } fail: @@ -1035,6 +1098,7 @@ static DBusMessage *endpoint_set_configuration(DBusConnection *conn, DBusMessage const char *path, *dev_path = NULL, *uuid = NULL; uint8_t *config = NULL; int size = 0; + pa_bool_t nrec; enum profile p; DBusMessageIter args, props; DBusMessage *r; @@ -1070,6 +1134,10 @@ static DBusMessage *endpoint_set_configuration(DBusConnection *conn, DBusMessage if (var != DBUS_TYPE_OBJECT_PATH) goto fail; dbus_message_iter_get_basic(&value, &dev_path); + } else if (strcasecmp(key, "NREC") == 0) { + if (var != DBUS_TYPE_BOOLEAN) + goto fail; + dbus_message_iter_get_basic(&value, &nrec); } else if (strcasecmp(key, "Configuration") == 0) { DBusMessageIter array; if (var != DBUS_TYPE_ARRAY) @@ -1093,6 +1161,8 @@ static DBusMessage *endpoint_set_configuration(DBusConnection *conn, DBusMessage p = PROFILE_A2DP_SOURCE; t = transport_new(y, path, p, config, size); + if (nrec) + t->nrec = nrec; pa_hashmap_put(d->transports, t->path, t); pa_log_debug("Transport %s profile %d available", t->path, t->profile); @@ -1402,6 +1472,7 @@ pa_bluetooth_discovery* pa_bluetooth_discovery_get(pa_core *c) { "type='signal',sender='org.bluez',interface='org.bluez.AudioSink',member='PropertyChanged'", "type='signal',sender='org.bluez',interface='org.bluez.AudioSource',member='PropertyChanged'", "type='signal',sender='org.bluez',interface='org.bluez.HandsfreeGateway',member='PropertyChanged'", + "type='signal',sender='org.bluez',interface='org.bluez.MediaTransport',member='PropertyChanged'", NULL) < 0) { pa_log("Failed to add D-Bus matches: %s", err.message); goto fail; @@ -1469,6 +1540,7 @@ void pa_bluetooth_discovery_unref(pa_bluetooth_discovery *y) { "type='signal',sender='org.bluez',interface='org.bluez.AudioSink',member='PropertyChanged'", "type='signal',sender='org.bluez',interface='org.bluez.AudioSource',member='PropertyChanged'", "type='signal',sender='org.bluez',interface='org.bluez.HandsfreeGateway',member='PropertyChanged'", + "type='signal',sender='org.bluez',interface='org.bluez.MediaTransport',member='PropertyChanged'", NULL); if (y->filter_added) diff --git a/src/modules/bluetooth/bluetooth-util.h b/src/modules/bluetooth/bluetooth-util.h index b471c34d..bb0cb24a 100644 --- a/src/modules/bluetooth/bluetooth-util.h +++ b/src/modules/bluetooth/bluetooth-util.h @@ -70,6 +70,7 @@ struct pa_bluetooth_transport { uint8_t codec; uint8_t *config; int config_size; + pa_bool_t nrec; }; /* This enum is shared among Audio, Headset, AudioSink, and AudioSource, although not all values are acceptable in all profiles */ @@ -128,6 +129,7 @@ const pa_bluetooth_transport* pa_bluetooth_device_get_transport(const pa_bluetoo int pa_bluetooth_transport_acquire(const pa_bluetooth_transport *t, const char *accesstype, size_t *imtu, size_t *omtu); void pa_bluetooth_transport_release(const pa_bluetooth_transport *t, const char *accesstype); +int pa_bluetooth_transport_parse_property(pa_bluetooth_transport *t, DBusMessageIter *i); pa_hook* pa_bluetooth_discovery_hook(pa_bluetooth_discovery *d); diff --git a/src/modules/bluetooth/module-bluetooth-device.c b/src/modules/bluetooth/module-bluetooth-device.c index 75cf498f..86aaa461 100644 --- a/src/modules/bluetooth/module-bluetooth-device.c +++ b/src/modules/bluetooth/module-bluetooth-device.c @@ -1751,7 +1751,7 @@ static DBusHandlerResult filter_cb(DBusConnection *bus, DBusMessage *m, void *us dbus_message_get_path(m), dbus_message_get_member(m)); - if (!dbus_message_has_path(m, u->path)) + if (!dbus_message_has_path(m, u->path) && !dbus_message_has_path(m, u->transport)) goto fail; if (dbus_message_is_signal(m, "org.bluez.Headset", "SpeakerGainChanged") || @@ -1777,6 +1777,28 @@ static DBusHandlerResult filter_cb(DBusConnection *bus, DBusMessage *m, void *us pa_source_volume_changed(u->source, &v); } } + } else if (dbus_message_is_signal(m, "org.bluez.MediaTransport", "PropertyChanged")) { + DBusMessageIter arg_i; + pa_bluetooth_transport *t; + pa_bool_t nrec; + + t = (pa_bluetooth_transport *) pa_bluetooth_discovery_get_transport(u->discovery, u->transport); + pa_assert(t); + + if (!dbus_message_iter_init(m, &arg_i)) { + pa_log("Failed to parse PropertyChanged: %s", err.message); + goto fail; + } + + nrec = t->nrec; + + if (pa_bluetooth_transport_parse_property(t, &arg_i) < 0) + goto fail; + + if (nrec != t->nrec) { + pa_log_debug("dbus: property 'NREC' changed to value '%s'", t->nrec ? "True" : "False"); + pa_proplist_sets(u->source->proplist, "bluetooth.nrec", t->nrec ? "1" : "0"); + } } fail: @@ -2018,6 +2040,7 @@ static int add_source(struct userdata *u) { pa_proplist_sets(data.proplist, "bluetooth.protocol", u->profile == PROFILE_A2DP_SOURCE ? "a2dp_source" : "hsp"); if ((u->profile == PROFILE_HSP) || (u->profile == PROFILE_HFGW)) pa_proplist_sets(data.proplist, PA_PROP_DEVICE_INTENDED_ROLES, "phone"); + data.card = u->card; data.name = get_name("source", u->modargs, u->address, &b); data.namereg_fail = b; @@ -2044,8 +2067,15 @@ static int add_source(struct userdata *u) { pa_bytes_to_usec(u->block_size, &u->sample_spec)); } - if (u->profile == PROFILE_HSP || u->profile == PROFILE_HFGW) - pa_proplist_sets(u->source->proplist, "bluetooth.nrec", (u->hsp.pcm_capabilities.flags & BT_PCM_FLAG_NREC) ? "1" : "0"); + if ((u->profile == PROFILE_HSP) || (u->profile == PROFILE_HFGW)) { + if (u->transport) { + const pa_bluetooth_transport *t; + t = pa_bluetooth_discovery_get_transport(u->discovery, u->transport); + pa_assert(t); + pa_proplist_sets(u->source->proplist, "bluetooth.nrec", t->nrec ? "1" : "0"); + } else + pa_proplist_sets(u->source->proplist, "bluetooth.nrec", (u->hsp.pcm_capabilities.flags & BT_PCM_FLAG_NREC) ? "1" : "0"); + } if (u->profile == PROFILE_HSP) { u->source->set_volume = source_set_volume_cb; @@ -2196,50 +2226,6 @@ static int bt_transport_config(struct userdata *u) { return bt_transport_config_a2dp(u); } -static int parse_transport_property(struct userdata *u, DBusMessageIter *i) { - const char *key; - DBusMessageIter variant_i; - - pa_assert(u); - pa_assert(i); - - if (dbus_message_iter_get_arg_type(i) != DBUS_TYPE_STRING) { - pa_log("Property name not a string."); - return -1; - } - - dbus_message_iter_get_basic(i, &key); - - if (!dbus_message_iter_next(i)) { - pa_log("Property value missing"); - return -1; - } - - if (dbus_message_iter_get_arg_type(i) != DBUS_TYPE_VARIANT) { - pa_log("Property value not a variant."); - return -1; - } - - dbus_message_iter_recurse(i, &variant_i); - - switch (dbus_message_iter_get_arg_type(&variant_i)) { - - case DBUS_TYPE_UINT16: { - - uint16_t value; - dbus_message_iter_get_basic(&variant_i, &value); - - if (pa_streq(key, "OMTU")) - u->link_mtu = value; - - break; - } - - } - - return 0; -} - /* Run from main thread */ static int bt_transport_open(struct userdata *u) { if (bt_transport_acquire(u, FALSE) < 0) @@ -2725,7 +2711,7 @@ int pa__init(pa_module* m) { struct userdata *u; const char *address, *path; DBusError err; - char *mike, *speaker; + char *mike, *speaker, *transport; const pa_bluetooth_device *device; pa_assert(m); @@ -2804,15 +2790,18 @@ int pa__init(pa_module* m) { speaker = pa_sprintf_malloc("type='signal',sender='org.bluez',interface='org.bluez.Headset',member='SpeakerGainChanged',path='%s'", u->path); mike = pa_sprintf_malloc("type='signal',sender='org.bluez',interface='org.bluez.Headset',member='MicrophoneGainChanged',path='%s'", u->path); + transport = pa_sprintf_malloc("type='signal',sender='org.bluez',interface='org.bluez.MediaTransport',member='PropertyChanged'"); if (pa_dbus_add_matches( pa_dbus_connection_get(u->connection), &err, speaker, mike, + transport, NULL) < 0) { pa_xfree(speaker); pa_xfree(mike); + pa_xfree(transport); pa_log("Failed to add D-Bus matches: %s", err.message); goto fail; @@ -2820,6 +2809,7 @@ int pa__init(pa_module* m) { pa_xfree(speaker); pa_xfree(mike); + pa_xfree(transport); /* Connect to the BT service */ init_bt(u); |