diff --git a/spa/plugins/bluez5/bluez5-dbus.c b/spa/plugins/bluez5/bluez5-dbus.c index 852519487..a0badc999 100644 --- a/spa/plugins/bluez5/bluez5-dbus.c +++ b/spa/plugins/bluez5/bluez5-dbus.c @@ -133,6 +133,7 @@ struct spa_bt_monitor { struct media_codec_audio_info default_audio_info; bool le_audio_supported; + bool bap_initiator; }; /* Stream endpoints owned by BlueZ for each device */ @@ -641,6 +642,14 @@ static DBusHandlerResult endpoint_select_properties(DBusConnection *conn, DBusMe else res = -ENOTSUP; + /* FIXME: We can't determine which remote endpoint or device the + * SelectConfiguration() call is associated with. For LE Audio BAP, + * as this method is called only for the Initiator we set the whole + * instance as a Central/Initiator. + */ + if (codec->bap) + monitor->bap_initiator = true; + if (res < 0 || res != size) { spa_log_error(monitor->log, "can't select config: %d (%s)", res, spa_strerror(res)); @@ -2004,6 +2013,7 @@ struct spa_bt_transport *spa_bt_transport_create(struct spa_bt_monitor *monitor, t->fd = -1; t->sco_io = NULL; t->delay = SPA_BT_UNKNOWN_DELAY; + t->bap_initiator = monitor->bap_initiator; t->user_data = SPA_PTROFF(t, sizeof(struct spa_bt_transport), void); spa_hook_list_init(&t->listener_list); @@ -4133,6 +4143,17 @@ static void interfaces_removed(struct spa_bt_monitor *monitor, DBusMessageIter * ep = remote_endpoint_find(monitor, object_path); if (ep != NULL) { struct spa_bt_device *d = ep->device; + /* FIXME: As we had been unabe to determine which remote endpoint or + * device the SelectConfiguration() has been associated with, this + * removes the general Central/Initiator flag on LE Audio BAP media + * endpoint removal. + */ + int i; + for (i = 0; monitor->media_codecs[i]; i++) { + const struct media_codec *codec = monitor->media_codecs[i]; + if (codec->codec_id == ep->codec && codec->bap) + monitor->bap_initiator = false; + } remote_endpoint_free(ep); if (d) spa_bt_device_emit_profiles_changed(d, d->profiles, d->connected_profiles); @@ -4446,7 +4467,7 @@ static DBusHandlerResult filter_cb(DBusConnection *bus, DBusMessage *m, void *us transport_update_props(transport, &it[1], NULL); } - } + } fail: dbus_error_free(&err); diff --git a/spa/plugins/bluez5/bluez5-device.c b/spa/plugins/bluez5/bluez5-device.c index 775b96e38..eb002b1ce 100644 --- a/spa/plugins/bluez5/bluez5-device.c +++ b/spa/plugins/bluez5/bluez5-device.c @@ -678,11 +678,8 @@ static int emit_nodes(struct impl *this) 1, SPA_NAME_API_BLUEZ5_SCO_SINK, false); } } - if (this->bt_dev->connected_profiles & (SPA_BT_PROFILE_MEDIA_SOURCE)) { - if (this->bt_dev->connected_profiles & SPA_BT_PROFILE_BAP_SOURCE) - t = find_transport(this, SPA_BT_PROFILE_BAP_SOURCE, 0); - else - t = find_transport(this, SPA_BT_PROFILE_A2DP_SOURCE, 0); + if (this->bt_dev->connected_profiles & (SPA_BT_PROFILE_A2DP_SOURCE)) { + t = find_transport(this, SPA_BT_PROFILE_A2DP_SOURCE, 0); if (t) { this->props.codec = t->media_codec->id; emit_dynamic_node(&this->dyn_media_source, this, t, @@ -731,8 +728,11 @@ static int emit_nodes(struct impl *this) t = find_transport(this, SPA_BT_PROFILE_BAP_SOURCE, 0); if (t) { this->props.codec = t->media_codec->id; - emit_dynamic_node(&this->dyn_media_source, this, t, - DEVICE_ID_SOURCE, SPA_NAME_API_BLUEZ5_MEDIA_SOURCE, false); + if (t->bap_initiator) + emit_node(this, t, DEVICE_ID_SOURCE, SPA_NAME_API_BLUEZ5_MEDIA_SOURCE, false); + else + emit_dynamic_node(&this->dyn_media_source, this, t, + DEVICE_ID_SOURCE, SPA_NAME_API_BLUEZ5_MEDIA_SOURCE, false); } } @@ -740,7 +740,11 @@ static int emit_nodes(struct impl *this) t = find_transport(this, SPA_BT_PROFILE_BAP_SINK, this->props.codec); if (t) { this->props.codec = t->media_codec->id; - emit_node(this, t, DEVICE_ID_SINK, SPA_NAME_API_BLUEZ5_MEDIA_SINK, false); + if (t->bap_initiator) + emit_node(this, t, DEVICE_ID_SINK, SPA_NAME_API_BLUEZ5_MEDIA_SINK, false); + else + emit_dynamic_node(&this->dyn_media_sink, this, t, + DEVICE_ID_SINK, SPA_NAME_API_BLUEZ5_MEDIA_SINK, false); } } diff --git a/spa/plugins/bluez5/defs.h b/spa/plugins/bluez5/defs.h index 4c4437dbc..15732dbba 100644 --- a/spa/plugins/bluez5/defs.h +++ b/spa/plugins/bluez5/defs.h @@ -602,6 +602,7 @@ struct spa_bt_transport { void *configuration; int configuration_len; char *endpoint_path; + bool bap_initiator; uint32_t n_channels; uint32_t channels[64]; diff --git a/spa/plugins/bluez5/media-sink.c b/spa/plugins/bluez5/media-sink.c index d0104e157..902b988f3 100644 --- a/spa/plugins/bluez5/media-sink.c +++ b/spa/plugins/bluez5/media-sink.c @@ -136,6 +136,7 @@ struct impl { unsigned int started:1; unsigned int following:1; + unsigned int is_output:1; unsigned int is_duplex:1; @@ -1123,8 +1124,10 @@ static void emit_node_info(struct impl *this, bool full) { struct spa_dict_item node_info_items[] = { { SPA_KEY_DEVICE_API, "bluez5" }, - { SPA_KEY_MEDIA_CLASS, "Audio/Sink" }, - { SPA_KEY_NODE_DRIVER, "true" }, + { SPA_KEY_MEDIA_CLASS, this->is_output ? "Audio/Sink" : "Stream/Input/Audio" }, + { "media.name", ((this->transport && this->transport->device->name) ? + this->transport->device->name : this->codec->bap ? "BAP" : "A2DP" ) }, + { SPA_KEY_NODE_DRIVER, this->is_output ? "true" : "false" }, }; uint64_t old = full ? this->info.change_mask : 0; if (full) @@ -1775,6 +1778,9 @@ impl_init(const struct spa_handle_factory *factory, this->is_duplex ? MEDIA_CODEC_FLAG_SINK : 0, this->transport->device->settings); + if (this->codec->bap) + this->is_output = this->transport->bap_initiator; + reset_props(this, &this->props); spa_bt_transport_add_listener(this->transport, diff --git a/spa/plugins/bluez5/media-source.c b/spa/plugins/bluez5/media-source.c index 8586238b3..f9e06e38a 100644 --- a/spa/plugins/bluez5/media-source.c +++ b/spa/plugins/bluez5/media-source.c @@ -1582,6 +1582,9 @@ impl_init(const struct spa_handle_factory *factory, } this->use_duplex_source = this->is_duplex || (this->codec->duplex_codec != NULL); + if (this->codec->bap) + this->is_input = this->transport->bap_initiator; + if (this->codec->init_props != NULL) this->codec_props = this->codec->init_props(this->codec, this->is_duplex ? 0 : MEDIA_CODEC_FLAG_SINK,