From 8660066af66b1a5d2310027aab4075e506f69ef4 Mon Sep 17 00:00:00 2001 From: Silviu Florian Barbulescu Date: Thu, 17 Aug 2023 18:52:48 +0300 Subject: [PATCH] Add suport for braodcast sink --- spa/plugins/bluez5/bluez5-dbus.c | 61 +++++++++++++++++++++--------- spa/plugins/bluez5/bluez5-device.c | 12 ++++++ spa/plugins/bluez5/defs.h | 6 +-- 3 files changed, 59 insertions(+), 20 deletions(-) diff --git a/spa/plugins/bluez5/bluez5-dbus.c b/spa/plugins/bluez5/bluez5-dbus.c index f9d0a2440..edc1ac617 100644 --- a/spa/plugins/bluez5/bluez5-dbus.c +++ b/spa/plugins/bluez5/bluez5-dbus.c @@ -502,6 +502,7 @@ static bool codec_has_direction(const struct media_codec *codec, enum spa_bt_med case SPA_BT_MEDIA_SOURCE_BROADCAST: return codec->encode; case SPA_BT_MEDIA_SINK: + case SPA_BT_MEDIA_SINK_BROADCAST: return codec->decode; default: spa_assert_not_reached(); @@ -518,6 +519,8 @@ static enum spa_bt_profile get_codec_profile(const struct media_codec *codec, return codec->bap ? SPA_BT_PROFILE_BAP_SINK : SPA_BT_PROFILE_A2DP_SINK; case SPA_BT_MEDIA_SOURCE_BROADCAST: return SPA_BT_PROFILE_BAP_BROADCAST_SOURCE; + case SPA_BT_MEDIA_SINK_BROADCAST: + return SPA_BT_PROFILE_BAP_BROADCAST_SINK; default: spa_assert_not_reached(); } @@ -1033,7 +1036,8 @@ static int adapter_media_update_props(struct spa_bt_adapter *adapter, adapter->path); } - if (spa_streq(uuid, SPA_BT_UUID_BAP_BROADCAST_SOURCE)) { + if (spa_streq(uuid, SPA_BT_UUID_BAP_BROADCAST_SOURCE) || + spa_streq(uuid, SPA_BT_UUID_BAP_BROADCAST_SINK)) { adapter->le_audio_bcast_supported = true; spa_log_info(monitor->log, "Adapter %s: LE Broadcast Audio supported", adapter->path); @@ -1659,7 +1663,7 @@ static int reconnect_device_profiles(struct spa_bt_device *device) if (reconnect & SPA_BT_PROFILE_BAP_SOURCE) device_try_connect_profile(device, SPA_BT_UUID_BAP_SOURCE); if (reconnect & SPA_BT_PROFILE_BAP_BROADCAST_SINK) - device_try_connect_profile(device, SPA_BT_UUID_BAP_SINK); + device_try_connect_profile(device, SPA_BT_UUID_BAP_BROADCAST_SINK); if (reconnect & SPA_BT_PROFILE_BAP_BROADCAST_SOURCE) device_try_connect_profile(device, SPA_BT_UUID_BAP_BROADCAST_SOURCE); @@ -2269,7 +2273,7 @@ bool spa_bt_device_supports_media_codec(struct spa_bt_device *device, const stru spa_list_for_each(ep, &device->remote_endpoint_list, device_link) { enum spa_bt_profile profile = spa_bt_profile_from_uuid(ep->uuid); if (codec->bap) { - if(profile == SPA_BT_PROFILE_BAP_BROADCAST_SINK) + if((profile == SPA_BT_PROFILE_BAP_BROADCAST_SINK) || (profile == SPA_BT_PROFILE_BAP_BROADCAST_SOURCE)) codec_profile = sink ? SPA_BT_PROFILE_BAP_BROADCAST_SINK : SPA_BT_PROFILE_BAP_BROADCAST_SOURCE; else codec_profile = sink ? SPA_BT_PROFILE_BAP_SINK : SPA_BT_PROFILE_BAP_SOURCE; @@ -2293,7 +2297,7 @@ bool spa_bt_device_supports_media_codec(struct spa_bt_device *device, const stru */ spa_list_for_each(t, &device->transport_list, device_link) { if (codec->bap) { - if(t->profile == SPA_BT_PROFILE_BAP_BROADCAST_SINK) + if((t->profile == SPA_BT_PROFILE_BAP_BROADCAST_SINK) || (t->profile == SPA_BT_PROFILE_BAP_BROADCAST_SOURCE)) codec_profile = sink ? SPA_BT_PROFILE_BAP_BROADCAST_SINK : SPA_BT_PROFILE_BAP_BROADCAST_SOURCE; else codec_profile = sink ? SPA_BT_PROFILE_BAP_SINK : SPA_BT_PROFILE_BAP_SOURCE; @@ -3384,11 +3388,12 @@ static int transport_create_iso_io(struct spa_bt_transport *transport) struct spa_bt_monitor *monitor = transport->monitor; struct spa_bt_transport *t; - if (!(transport->profile & (SPA_BT_PROFILE_BAP_SINK | SPA_BT_PROFILE_BAP_SOURCE - | SPA_BT_PROFILE_BAP_BROADCAST_SINK))) + if (!(transport->profile & (SPA_BT_PROFILE_BAP_SINK | SPA_BT_PROFILE_BAP_SOURCE | + SPA_BT_PROFILE_BAP_BROADCAST_SINK || SPA_BT_PROFILE_BAP_BROADCAST_SOURCE))) return 0; - if (transport->profile == SPA_BT_PROFILE_BAP_BROADCAST_SINK) { + if ((transport->profile == SPA_BT_PROFILE_BAP_BROADCAST_SINK) || + (transport->profile == SPA_BT_PROFILE_BAP_BROADCAST_SOURCE)) { if (transport->bap_big == 0xff || transport->bap_bis == 0xff) return -EINVAL; } else { @@ -3404,11 +3409,12 @@ static int transport_create_iso_io(struct spa_bt_transport *transport) /* Transports in same connected iso group share the same i/o */ spa_list_for_each(t, &monitor->transport_list, link) { - if (!(t->profile & (SPA_BT_PROFILE_BAP_SINK | SPA_BT_PROFILE_BAP_SOURCE - | SPA_BT_PROFILE_BAP_BROADCAST_SINK))) + if (!(t->profile & (SPA_BT_PROFILE_BAP_SINK | SPA_BT_PROFILE_BAP_SOURCE | + SPA_BT_PROFILE_BAP_BROADCAST_SINK | SPA_BT_PROFILE_BAP_BROADCAST_SOURCE))) continue; - - if (transport->profile == SPA_BT_PROFILE_BAP_BROADCAST_SINK) { + + if ((transport->profile == SPA_BT_PROFILE_BAP_BROADCAST_SINK) || + (transport->profile == SPA_BT_PROFILE_BAP_BROADCAST_SOURCE)) { if (t->bap_big != transport->bap_big) continue; } else { @@ -3494,9 +3500,10 @@ finish: if (transport_create_iso_io(transport) < 0) spa_log_error(monitor->log, "transport %p: transport_create_iso_io failed", transport); - /* For broadcast there initiator moves the transport state to SPA_BT_TRANSPORT_STATE_ACTIVE */ + /* For broadcast the initiator moves the transport state to SPA_BT_TRANSPORT_STATE_ACTIVE */ /* TODO: handeling multiple BIGs support */ - if(transport->profile == SPA_BT_PROFILE_BAP_BROADCAST_SINK) { + if ((transport->profile == SPA_BT_PROFILE_BAP_BROADCAST_SINK) || + (transport->profile == SPA_BT_PROFILE_BAP_BROADCAST_SOURCE)) { spa_bt_transport_set_state(transport, SPA_BT_TRANSPORT_STATE_ACTIVE); } else { if (!transport->bap_initiator) @@ -3526,7 +3533,8 @@ finish: t_linked); /* For broadcast there initiator moves the transport state to SPA_BT_TRANSPORT_STATE_ACTIVE */ - if(transport->profile == SPA_BT_PROFILE_BAP_BROADCAST_SINK) { + if ((transport->profile == SPA_BT_PROFILE_BAP_BROADCAST_SINK) || + (transport->profile == SPA_BT_PROFILE_BAP_BROADCAST_SOURCE)) { spa_bt_transport_set_state(transport, SPA_BT_TRANSPORT_STATE_ACTIVE); } else { if (!transport->bap_initiator) @@ -4733,7 +4741,7 @@ static DBusHandlerResult object_manager_handler(DBusConnection *c, DBusMessage * } } - if((codec->bap) && register_bcast) + if(codec->bap && register_bcast) { if (endpoint_should_be_registered(monitor, codec, SPA_BT_MEDIA_SOURCE_BROADCAST)) { caps_size = codec->fill_caps(codec, 0, caps); @@ -4749,6 +4757,21 @@ static DBusHandlerResult object_manager_handler(DBusConnection *c, DBusMessage * codec_id, caps, caps_size); } } + + if (endpoint_should_be_registered(monitor, codec, SPA_BT_MEDIA_SINK_BROADCAST)) { + caps_size = codec->fill_caps(codec, MEDIA_CODEC_FLAG_SINK, caps); + if (caps_size < 0) + continue; + + spa_autofree char *endpoint = NULL; + ret = media_codec_to_endpoint(codec, SPA_BT_MEDIA_SINK_BROADCAST, &endpoint); + if (ret == 0) { + spa_log_info(monitor->log, "register broadcast media sink codec %s: %s", media_codecs[i]->name, endpoint); + append_media_object(&array, endpoint, + SPA_BT_UUID_BAP_BROADCAST_SINK, + codec_id, caps, caps_size); + } + } } } @@ -4880,8 +4903,8 @@ static int register_media_application(struct spa_bt_monitor * monitor) if(codec->bap) { register_media_endpoint(monitor, codec, SPA_BT_MEDIA_SOURCE_BROADCAST); + register_media_endpoint(monitor, codec, SPA_BT_MEDIA_SINK_BROADCAST); } - } return 0; @@ -4917,6 +4940,7 @@ static void unregister_media_application(struct spa_bt_monitor * monitor) if(codec->bap) { unregister_media_endpoint(monitor, codec, SPA_BT_MEDIA_SOURCE_BROADCAST); + unregister_media_endpoint(monitor, codec, SPA_BT_MEDIA_SINK_BROADCAST); } } @@ -4936,7 +4960,8 @@ static bool have_codec_endpoints(struct spa_bt_monitor *monitor, bool bap) continue; if (endpoint_should_be_registered(monitor, codec, SPA_BT_MEDIA_SINK) || endpoint_should_be_registered(monitor, codec, SPA_BT_MEDIA_SOURCE) || - endpoint_should_be_registered(monitor, codec, SPA_BT_MEDIA_SOURCE_BROADCAST)) + endpoint_should_be_registered(monitor, codec, SPA_BT_MEDIA_SOURCE_BROADCAST) || + endpoint_should_be_registered(monitor, codec, SPA_BT_MEDIA_SINK_BROADCAST)) return true; } return false; @@ -5674,6 +5699,8 @@ int spa_bt_profiles_from_json_array(const char *str) profiles |= SPA_BT_PROFILE_BAP_SOURCE; } else if (spa_streq(role_name, "bap_bcast_source")) { profiles |= SPA_BT_PROFILE_BAP_BROADCAST_SOURCE; + } else if (spa_streq(role_name, "bap_bcast_sink")) { + profiles |= SPA_BT_PROFILE_BAP_BROADCAST_SINK; } } diff --git a/spa/plugins/bluez5/bluez5-device.c b/spa/plugins/bluez5/bluez5-device.c index 00296bc0f..23918b054 100644 --- a/spa/plugins/bluez5/bluez5-device.c +++ b/spa/plugins/bluez5/bluez5-device.c @@ -1062,6 +1062,18 @@ static int emit_nodes(struct impl *this) emit_device_set_node(this, DEVICE_ID_SINK_SET); } + if (this->bt_dev->connected_profiles & (SPA_BT_PROFILE_BAP_BROADCAST_SOURCE)) { + t = find_transport(this, SPA_BT_PROFILE_BAP_BROADCAST_SOURCE, this->props.codec); + 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 (this->device_set.leader && this->device_set.sources > 0) + emit_device_set_node(this, DEVICE_ID_SOURCE_SET); + } + if (get_supported_media_codec(this, this->props.codec, NULL) == NULL) this->props.codec = 0; break; diff --git a/spa/plugins/bluez5/defs.h b/spa/plugins/bluez5/defs.h index ca33551bf..0651ee1cb 100644 --- a/spa/plugins/bluez5/defs.h +++ b/spa/plugins/bluez5/defs.h @@ -321,10 +321,10 @@ static inline const char *spa_bt_profile_name (enum spa_bt_profile profile) { case SPA_BT_PROFILE_HEADSET_AUDIO: return "headset-audio"; case SPA_BT_PROFILE_BAP_SOURCE: - case SPA_BT_PROFILE_BAP_BROADCAST_SOURCE: + case SPA_BT_PROFILE_BAP_BROADCAST_SOURCE: return "bap-source"; case SPA_BT_PROFILE_BAP_SINK: - case SPA_BT_PROFILE_BAP_BROADCAST_SINK: + case SPA_BT_PROFILE_BAP_BROADCAST_SINK: return "bap-sink"; case SPA_BT_PROFILE_BAP_DUPLEX: return "bap-duplex"; @@ -365,7 +365,7 @@ struct spa_bt_adapter { unsigned int le_audio_supported:1; unsigned int has_adapter1_interface:1; unsigned int has_media1_interface:1; - unsigned int le_audio_bcast_supported :1; + unsigned int le_audio_bcast_supported:1; }; enum spa_bt_form_factor {