1 /* 2 * Copyright 2019 HIMSA II K/S - www.himsa.com. Represented by EHIMA - 3 * www.ehima.com 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 #pragma once 19 20 #include <bluetooth/log.h> 21 22 #include <array> 23 #include <bitset> 24 #include <map> 25 #include <optional> 26 #include <ostream> 27 #include <vector> 28 29 #include "types/raw_address.h" 30 31 namespace bluetooth { 32 namespace le_audio { 33 34 enum class LeAudioHealthBasedAction { 35 NONE = 0, 36 DISABLE, 37 CONSIDER_DISABLING, 38 INACTIVATE_GROUP, 39 }; 40 41 inline std::ostream& operator<<(std::ostream& os, const LeAudioHealthBasedAction action) { 42 switch (action) { 43 case LeAudioHealthBasedAction::NONE: 44 os << "NONE"; 45 break; 46 case LeAudioHealthBasedAction::DISABLE: 47 os << "DISABLE"; 48 break; 49 case LeAudioHealthBasedAction::CONSIDER_DISABLING: 50 os << "CONSIDER_DISABLING"; 51 break; 52 case LeAudioHealthBasedAction::INACTIVATE_GROUP: 53 os << "INACTIVATE_GROUP"; 54 break; 55 default: 56 os << "UNKNOWN"; 57 break; 58 } 59 return os; 60 } 61 62 enum class ConnectionState { DISCONNECTED = 0, CONNECTING, CONNECTED, DISCONNECTING }; 63 64 enum class GroupStatus { 65 INACTIVE = 0, 66 ACTIVE, 67 TURNED_IDLE_DURING_CALL, 68 }; 69 70 enum class GroupStreamStatus { 71 IDLE = 0, 72 STREAMING, 73 RELEASING, 74 RELEASING_AUTONOMOUS, 75 SUSPENDING, 76 SUSPENDED, 77 CONFIGURED_AUTONOMOUS, 78 CONFIGURED_BY_USER, 79 DESTROYED, 80 }; 81 82 inline std::ostream& operator<<(std::ostream& os, const GroupStreamStatus& state) { 83 switch (state) { 84 case GroupStreamStatus::IDLE: 85 os << "IDLE"; 86 break; 87 case GroupStreamStatus::STREAMING: 88 os << "STREAMING"; 89 break; 90 case GroupStreamStatus::RELEASING: 91 os << "RELEASING"; 92 break; 93 case GroupStreamStatus::RELEASING_AUTONOMOUS: 94 os << "RELEASING_AUTONOMOUS"; 95 break; 96 case GroupStreamStatus::SUSPENDING: 97 os << "SUSPENDING"; 98 break; 99 case GroupStreamStatus::SUSPENDED: 100 os << "SUSPENDED"; 101 break; 102 case GroupStreamStatus::CONFIGURED_AUTONOMOUS: 103 os << "CONFIGURED_AUTONOMOUS"; 104 break; 105 case GroupStreamStatus::CONFIGURED_BY_USER: 106 os << "CONFIGURED_BY_USER"; 107 break; 108 case GroupStreamStatus::DESTROYED: 109 os << "DESTROYED"; 110 break; 111 default: 112 os << "UNKNOWN"; 113 break; 114 } 115 return os; 116 } 117 118 enum class GroupNodeStatus { 119 ADDED = 1, 120 REMOVED, 121 }; 122 123 enum class UnicastMonitorModeStatus { 124 STREAMING_REQUESTED = 0, 125 STREAMING, 126 STREAMING_SUSPENDED, 127 STREAMING_REQUESTED_NO_CONTEXT_VALIDATE, 128 }; 129 130 typedef enum { 131 LE_AUDIO_CODEC_INDEX_SOURCE_LC3 = 0, 132 LE_AUDIO_CODEC_INDEX_SOURCE_INVALID = 1000 * 1000, 133 } btle_audio_codec_index_t; 134 135 typedef enum { QUALITY_STANDARD = 0, QUALITY_HIGH } btle_audio_quality_t; 136 137 typedef enum { 138 LE_AUDIO_SAMPLE_RATE_INDEX_NONE = 0, 139 LE_AUDIO_SAMPLE_RATE_INDEX_8000HZ = 0x01 << 0, 140 LE_AUDIO_SAMPLE_RATE_INDEX_11025HZ = 0x01 << 1, 141 LE_AUDIO_SAMPLE_RATE_INDEX_16000HZ = 0x01 << 2, 142 LE_AUDIO_SAMPLE_RATE_INDEX_22050HZ = 0x01 << 3, 143 LE_AUDIO_SAMPLE_RATE_INDEX_24000HZ = 0x01 << 4, 144 LE_AUDIO_SAMPLE_RATE_INDEX_32000HZ = 0x01 << 5, 145 LE_AUDIO_SAMPLE_RATE_INDEX_44100HZ = 0x01 << 6, 146 LE_AUDIO_SAMPLE_RATE_INDEX_48000HZ = 0x01 << 7, 147 LE_AUDIO_SAMPLE_RATE_INDEX_88200HZ = 0x01 << 8, 148 LE_AUDIO_SAMPLE_RATE_INDEX_96000HZ = 0x01 << 9, 149 LE_AUDIO_SAMPLE_RATE_INDEX_176400HZ = 0x01 << 10, 150 LE_AUDIO_SAMPLE_RATE_INDEX_192000HZ = 0x01 << 11, 151 LE_AUDIO_SAMPLE_RATE_INDEX_384000HZ = 0x01 << 12 152 } btle_audio_sample_rate_index_t; 153 154 typedef enum { 155 LE_AUDIO_BITS_PER_SAMPLE_INDEX_NONE = 0, 156 LE_AUDIO_BITS_PER_SAMPLE_INDEX_16 = 0x01 << 0, 157 LE_AUDIO_BITS_PER_SAMPLE_INDEX_24 = 0x01 << 1, 158 LE_AUDIO_BITS_PER_SAMPLE_INDEX_32 = 0x01 << 3 159 } btle_audio_bits_per_sample_index_t; 160 161 typedef enum { 162 LE_AUDIO_CHANNEL_COUNT_INDEX_NONE = 0, 163 LE_AUDIO_CHANNEL_COUNT_INDEX_1 = 0x01 << 0, 164 LE_AUDIO_CHANNEL_COUNT_INDEX_2 = 0x01 << 1 165 } btle_audio_channel_count_index_t; 166 167 typedef enum { 168 LE_AUDIO_FRAME_DURATION_INDEX_NONE = 0, 169 LE_AUDIO_FRAME_DURATION_INDEX_7500US = 0x01 << 0, 170 LE_AUDIO_FRAME_DURATION_INDEX_10000US = 0x01 << 1 171 } btle_audio_frame_duration_index_t; 172 173 typedef struct btle_audio_codec_config { 174 btle_audio_codec_index_t codec_type = LE_AUDIO_CODEC_INDEX_SOURCE_INVALID; 175 btle_audio_sample_rate_index_t sample_rate = LE_AUDIO_SAMPLE_RATE_INDEX_NONE; 176 btle_audio_bits_per_sample_index_t bits_per_sample = LE_AUDIO_BITS_PER_SAMPLE_INDEX_NONE; 177 btle_audio_channel_count_index_t channel_count = LE_AUDIO_CHANNEL_COUNT_INDEX_NONE; 178 btle_audio_frame_duration_index_t frame_duration = LE_AUDIO_FRAME_DURATION_INDEX_NONE; 179 uint8_t codec_frame_blocks_per_sdu = 0; 180 uint16_t octets_per_frame = 0; 181 int32_t codec_priority = 0; 182 183 bool operator!=(const btle_audio_codec_config& other) const { 184 if (codec_type != other.codec_type) { 185 return true; 186 } 187 if (sample_rate != other.sample_rate) { 188 return true; 189 } 190 if (bits_per_sample != other.bits_per_sample) { 191 return true; 192 } 193 if (channel_count != other.channel_count) { 194 return true; 195 } 196 if (frame_duration != other.frame_duration) { 197 return true; 198 } 199 if (octets_per_frame != other.octets_per_frame) { 200 return true; 201 } 202 if (codec_priority != other.codec_priority) { 203 return true; 204 } 205 return false; 206 } 207 bool operator==(const btle_audio_codec_config& other) const { return !(*this != other); } 208 ToStringbtle_audio_codec_config209 std::string ToString() const { 210 std::string codec_name_str; 211 std::string sample_rate_str; 212 std::string bits_per_sample_str; 213 std::string channel_count_str; 214 std::string frame_duration_str; 215 std::string octets_per_frame_str; 216 std::string codec_priority_str; 217 218 switch (codec_type) { 219 case LE_AUDIO_CODEC_INDEX_SOURCE_LC3: 220 codec_name_str = "LC3"; 221 break; 222 default: 223 codec_name_str = "Unknown LE codec " + std::to_string(codec_type); 224 break; 225 } 226 227 switch (sample_rate) { 228 case LE_AUDIO_SAMPLE_RATE_INDEX_NONE: 229 sample_rate_str = "none"; 230 break; 231 case LE_AUDIO_SAMPLE_RATE_INDEX_8000HZ: 232 sample_rate_str = "8000 hz"; 233 break; 234 case LE_AUDIO_SAMPLE_RATE_INDEX_11025HZ: 235 sample_rate_str = "11025 hz"; 236 break; 237 case LE_AUDIO_SAMPLE_RATE_INDEX_16000HZ: 238 sample_rate_str = "16000 hz"; 239 break; 240 case LE_AUDIO_SAMPLE_RATE_INDEX_22050HZ: 241 sample_rate_str = "22050 hz"; 242 break; 243 case LE_AUDIO_SAMPLE_RATE_INDEX_24000HZ: 244 sample_rate_str = "24000 hz"; 245 break; 246 case LE_AUDIO_SAMPLE_RATE_INDEX_32000HZ: 247 sample_rate_str = "32000 hz"; 248 break; 249 case LE_AUDIO_SAMPLE_RATE_INDEX_44100HZ: 250 sample_rate_str = "44100 hz"; 251 break; 252 case LE_AUDIO_SAMPLE_RATE_INDEX_48000HZ: 253 sample_rate_str = "48000 hz"; 254 break; 255 case LE_AUDIO_SAMPLE_RATE_INDEX_88200HZ: 256 sample_rate_str = "88200 hz"; 257 break; 258 case LE_AUDIO_SAMPLE_RATE_INDEX_96000HZ: 259 sample_rate_str = "96000 hz"; 260 break; 261 case LE_AUDIO_SAMPLE_RATE_INDEX_176400HZ: 262 sample_rate_str = "176400 hz"; 263 break; 264 case LE_AUDIO_SAMPLE_RATE_INDEX_192000HZ: 265 sample_rate_str = "192000 hz"; 266 break; 267 case LE_AUDIO_SAMPLE_RATE_INDEX_384000HZ: 268 sample_rate_str = "384000 hz"; 269 break; 270 default: 271 sample_rate_str = "Unknown LE sample rate " + std::to_string(sample_rate); 272 break; 273 } 274 275 switch (bits_per_sample) { 276 case LE_AUDIO_BITS_PER_SAMPLE_INDEX_NONE: 277 bits_per_sample_str = "none"; 278 break; 279 case LE_AUDIO_BITS_PER_SAMPLE_INDEX_16: 280 bits_per_sample_str = "16"; 281 break; 282 case LE_AUDIO_BITS_PER_SAMPLE_INDEX_24: 283 bits_per_sample_str = "24"; 284 break; 285 case LE_AUDIO_BITS_PER_SAMPLE_INDEX_32: 286 bits_per_sample_str = "32"; 287 break; 288 default: 289 bits_per_sample_str = "Unknown LE bits per sample " + std::to_string(bits_per_sample); 290 break; 291 } 292 293 switch (channel_count) { 294 case LE_AUDIO_CHANNEL_COUNT_INDEX_NONE: 295 channel_count_str = "none"; 296 break; 297 case LE_AUDIO_CHANNEL_COUNT_INDEX_1: 298 channel_count_str = "1"; 299 break; 300 case LE_AUDIO_CHANNEL_COUNT_INDEX_2: 301 channel_count_str = "2"; 302 break; 303 default: 304 channel_count_str = "Unknown LE channel count " + std::to_string(channel_count); 305 break; 306 } 307 308 switch (frame_duration) { 309 case LE_AUDIO_FRAME_DURATION_INDEX_NONE: 310 frame_duration_str = "none"; 311 break; 312 case LE_AUDIO_FRAME_DURATION_INDEX_7500US: 313 frame_duration_str = "7500 us"; 314 break; 315 case LE_AUDIO_FRAME_DURATION_INDEX_10000US: 316 frame_duration_str = "10000 us"; 317 break; 318 default: 319 frame_duration_str = "Unknown LE frame duration " + std::to_string(frame_duration); 320 break; 321 } 322 323 if (octets_per_frame < 0) { 324 octets_per_frame_str = "Unknown LE octets per frame " + std::to_string(octets_per_frame); 325 } else { 326 octets_per_frame_str = std::to_string(octets_per_frame); 327 } 328 329 if (codec_priority < -1) { 330 codec_priority_str = "Unknown LE codec priority " + std::to_string(codec_priority); 331 } else { 332 codec_priority_str = std::to_string(codec_priority); 333 } 334 335 return "codec: " + codec_name_str + ", sample rate: " + sample_rate_str + 336 ", bits per sample: " + bits_per_sample_str + ", channel count: " + channel_count_str + 337 ", frame duration: " + frame_duration_str + 338 ", octets per frame: " + octets_per_frame_str + ", codec priroty: " + codec_priority_str; 339 } 340 } btle_audio_codec_config_t; 341 342 class LeAudioClientCallbacks { 343 public: 344 virtual ~LeAudioClientCallbacks() = default; 345 346 /* Callback to notify Java that stack is ready */ 347 virtual void OnInitialized(void) = 0; 348 349 /** Callback for profile connection state change */ 350 virtual void OnConnectionState(ConnectionState state, const RawAddress& address) = 0; 351 352 /* Callback with group status update */ 353 virtual void OnGroupStatus(int group_id, GroupStatus group_status) = 0; 354 355 /* Callback with node status update */ 356 virtual void OnGroupNodeStatus(const RawAddress& bd_addr, int group_id, 357 GroupNodeStatus node_status) = 0; 358 /* Callback for newly recognized or reconfigured existing le audio group */ 359 virtual void OnAudioConf(uint8_t direction, int group_id, 360 std::optional<std::bitset<32>> snk_audio_location, 361 std::optional<std::bitset<32>> src_audio_location, 362 uint16_t avail_cont) = 0; 363 /* Callback for sink audio location recognized */ 364 virtual void OnSinkAudioLocationAvailable(const RawAddress& address, 365 std::optional<std::bitset<32>> snk_audio_location) = 0; 366 /* Callback with local codec capabilities */ 367 virtual void OnAudioLocalCodecCapabilities( 368 std::vector<btle_audio_codec_config_t> local_input_capa_codec_conf, 369 std::vector<btle_audio_codec_config_t> local_output_capa_codec_conf) = 0; 370 /* Callback with current group codec configurations. Should change when PACs 371 * changes */ 372 virtual void OnAudioGroupCurrentCodecConf(int group_id, 373 btle_audio_codec_config_t input_codec_conf, 374 btle_audio_codec_config_t output_codec_conf) = 0; 375 /* Callback with selectable group codec configurations. Should change when 376 * context changes */ 377 virtual void OnAudioGroupSelectableCodecConf( 378 int group_id, std::vector<btle_audio_codec_config_t> input_selectable_codec_conf, 379 std::vector<btle_audio_codec_config_t> output_selectable_codec_conf) = 0; 380 virtual void OnHealthBasedRecommendationAction(const RawAddress& address, 381 LeAudioHealthBasedAction action) = 0; 382 virtual void OnHealthBasedGroupRecommendationAction(int group_id, 383 LeAudioHealthBasedAction action) = 0; 384 385 virtual void OnUnicastMonitorModeStatus(uint8_t direction, UnicastMonitorModeStatus status) = 0; 386 387 /* Callback with group stream status update */ 388 virtual void OnGroupStreamStatus(int group_id, GroupStreamStatus group_stream_status) = 0; 389 }; 390 391 class LeAudioClientInterface { 392 public: 393 virtual ~LeAudioClientInterface() = default; 394 395 /* Register the LeAudio callbacks */ 396 virtual void Initialize(LeAudioClientCallbacks* callbacks, 397 const std::vector<btle_audio_codec_config_t>& offloading_preference) = 0; 398 399 /** Connect to LEAudio */ 400 virtual void Connect(const RawAddress& address) = 0; 401 402 /** Disconnect from LEAudio */ 403 virtual void Disconnect(const RawAddress& address) = 0; 404 405 /* Set enable/disable State for the LeAudio device */ 406 virtual void SetEnableState(const RawAddress& address, bool enabled) = 0; 407 408 /* Cleanup the LeAudio */ 409 virtual void Cleanup(void) = 0; 410 411 /* Called when LeAudio is unbonded. */ 412 virtual void RemoveDevice(const RawAddress& address) = 0; 413 414 /* Attach le audio node to group */ 415 virtual void GroupAddNode(int group_id, const RawAddress& addr) = 0; 416 417 /* Detach le audio node from a group */ 418 virtual void GroupRemoveNode(int group_id, const RawAddress& addr) = 0; 419 420 /* Set active le audio group */ 421 virtual void GroupSetActive(int group_id) = 0; 422 423 /* Set codec config preference */ 424 virtual void SetCodecConfigPreference(int group_id, btle_audio_codec_config_t input_codec_config, 425 btle_audio_codec_config_t output_codec_config) = 0; 426 427 /* Set Ccid for context type */ 428 virtual void SetCcidInformation(int ccid, int context_type) = 0; 429 430 /* Set In call flag */ 431 virtual void SetInCall(bool in_call) = 0; 432 433 /* Set Sink listening mode flag */ 434 virtual void SetUnicastMonitorMode(uint8_t direction, bool enable) = 0; 435 436 /* Sends a preferred audio profiles change */ 437 virtual void SendAudioProfilePreferences(int group_id, bool is_output_preference_le_audio, 438 bool is_duplex_preference_le_audio) = 0; 439 440 /* Set allowed to stream context */ 441 virtual void SetGroupAllowedContextMask(int group_id, int sink_context_types, 442 int source_context_types) = 0; 443 }; 444 445 /* Represents the broadcast source state. */ 446 enum class BroadcastState { 447 STOPPED = 0, 448 CONFIGURING, 449 CONFIGURED, 450 ENABLING, 451 DISABLING, 452 STOPPING, 453 STREAMING, 454 }; 455 456 using BroadcastId = uint32_t; 457 static constexpr BroadcastId kBroadcastIdInvalid = 0x00000000; 458 using BroadcastCode = std::array<uint8_t, 16>; 459 460 /* Content Metadata LTV Types */ 461 constexpr uint8_t kLeAudioMetadataTypePreferredAudioContext = 0x01; 462 constexpr uint8_t kLeAudioMetadataTypeStreamingAudioContext = 0x02; 463 constexpr uint8_t kLeAudioMetadataTypeProgramInfo = 0x03; 464 constexpr uint8_t kLeAudioMetadataTypeLanguage = 0x04; 465 constexpr uint8_t kLeAudioMetadataTypeCcidList = 0x05; 466 467 /* Codec specific LTV Types */ 468 constexpr uint8_t kLeAudioLtvTypeSamplingFreq = 0x01; 469 constexpr uint8_t kLeAudioLtvTypeFrameDuration = 0x02; 470 constexpr uint8_t kLeAudioLtvTypeAudioChannelAllocation = 0x03; 471 constexpr uint8_t kLeAudioLtvTypeOctetsPerCodecFrame = 0x04; 472 constexpr uint8_t kLeAudioLtvTypeCodecFrameBlocksPerSdu = 0x05; 473 474 /* Audio quality configuration in public broadcast announcement */ 475 constexpr uint8_t kLeAudioQualityStandard = 0x1 << 1; 476 constexpr uint8_t kLeAudioQualityHigh = 0x1 << 2; 477 478 /* Unknown RSSI value 0x7F - 127 */ 479 constexpr uint8_t kLeAudioSourceRssiUnknown = 0x7F; 480 481 struct BasicAudioAnnouncementCodecConfig { 482 /* 5 octets for the Codec ID */ 483 uint8_t codec_id; 484 uint16_t vendor_company_id; 485 uint16_t vendor_codec_id; 486 487 /* Codec params - series of LTV formatted triplets */ 488 std::map<uint8_t, std::vector<uint8_t>> codec_specific_params; 489 std::optional<std::vector<uint8_t>> vendor_codec_specific_params; 490 }; 491 492 struct BasicAudioAnnouncementBisConfig { 493 std::map<uint8_t, std::vector<uint8_t>> codec_specific_params; 494 std::optional<std::vector<uint8_t>> vendor_codec_specific_params; 495 496 uint8_t bis_index; 497 }; 498 499 struct BasicAudioAnnouncementSubgroup { 500 /* Subgroup specific codec configuration and metadata */ 501 BasicAudioAnnouncementCodecConfig codec_config; 502 // Content metadata 503 std::map<uint8_t, std::vector<uint8_t>> metadata; 504 // Broadcast channel configuration 505 std::vector<BasicAudioAnnouncementBisConfig> bis_configs; 506 }; 507 508 struct BasicAudioAnnouncementData { 509 /* Announcement Header fields */ 510 uint32_t presentation_delay_us; 511 512 /* Subgroup specific configurations */ 513 std::vector<BasicAudioAnnouncementSubgroup> subgroup_configs; 514 }; 515 516 struct PublicBroadcastAnnouncementData { 517 // Public Broadcast Announcement features bitmap 518 uint8_t features; 519 // Metadata 520 std::map<uint8_t, std::vector<uint8_t>> metadata; 521 }; 522 523 struct BroadcastMetadata { 524 bool is_public; 525 uint16_t pa_interval; 526 RawAddress addr; 527 uint8_t addr_type; 528 uint8_t adv_sid; 529 530 BroadcastId broadcast_id; 531 std::string broadcast_name; 532 std::optional<BroadcastCode> broadcast_code; 533 534 PublicBroadcastAnnouncementData public_announcement; 535 /* Presentation delay and subgroup configurations */ 536 BasicAudioAnnouncementData basic_audio_announcement; 537 }; 538 539 class LeAudioBroadcasterCallbacks { 540 public: 541 virtual ~LeAudioBroadcasterCallbacks() = default; 542 /* Callback for the newly created broadcast event. */ 543 virtual void OnBroadcastCreated(uint32_t broadcast_id, bool success) = 0; 544 545 /* Callback for the destroyed broadcast event. */ 546 virtual void OnBroadcastDestroyed(uint32_t broadcast_id) = 0; 547 /* Callback for the broadcast source state event. */ 548 virtual void OnBroadcastStateChanged(uint32_t broadcast_id, BroadcastState state) = 0; 549 /* Callback for the broadcast metadata change. */ 550 virtual void OnBroadcastMetadataChanged(uint32_t broadcast_id, 551 const BroadcastMetadata& broadcast_metadata) = 0; 552 /* Callback for broadcast audio session create event. */ 553 virtual void OnBroadcastAudioSessionCreated(bool success) = 0; 554 }; 555 556 class LeAudioBroadcasterInterface { 557 public: 558 virtual ~LeAudioBroadcasterInterface() = default; 559 /* Register the LeAudio Broadcaster callbacks */ 560 virtual void Initialize(LeAudioBroadcasterCallbacks* callbacks) = 0; 561 /* Stop the LeAudio Broadcaster and all active broadcasts */ 562 virtual void Stop(void) = 0; 563 /* Cleanup the LeAudio Broadcaster */ 564 virtual void Cleanup(void) = 0; 565 /* Create Broadcast instance */ 566 virtual void CreateBroadcast(bool is_public, std::string broadcast_name, 567 std::optional<BroadcastCode> broadcast_code, 568 std::vector<uint8_t> public_metadata, 569 std::vector<uint8_t> subgroup_quality, 570 std::vector<std::vector<uint8_t>> subgroup_metadata) = 0; 571 /* Update the ongoing Broadcast metadata */ 572 virtual void UpdateMetadata(uint32_t broadcast_id, std::string broadcast_name, 573 std::vector<uint8_t> public_metadata, 574 std::vector<std::vector<uint8_t>> subgroup_metadata) = 0; 575 576 /* Start the existing Broadcast stream */ 577 virtual void StartBroadcast(uint32_t broadcast_id) = 0; 578 /* Pause the ongoing Broadcast stream */ 579 virtual void PauseBroadcast(uint32_t broadcast_id) = 0; 580 /* Stop the Broadcast (no stream, no periodic advertisements */ 581 virtual void StopBroadcast(uint32_t broadcast_id) = 0; 582 /* Destroy the existing Broadcast instance */ 583 virtual void DestroyBroadcast(uint32_t broadcast_id) = 0; 584 /* Get Broadcast Metadata */ 585 virtual void GetBroadcastMetadata(uint32_t broadcast_id) = 0; 586 }; 587 588 } /* namespace le_audio */ 589 } /* namespace bluetooth */ 590 591 namespace std { 592 template <> 593 struct formatter<bluetooth::le_audio::btle_audio_codec_index_t> 594 : enum_formatter<bluetooth::le_audio::btle_audio_codec_index_t> {}; 595 template <> 596 struct formatter<bluetooth::le_audio::btle_audio_sample_rate_index_t> 597 : enum_formatter<bluetooth::le_audio::btle_audio_sample_rate_index_t> {}; 598 template <> 599 struct formatter<bluetooth::le_audio::btle_audio_bits_per_sample_index_t> 600 : enum_formatter<bluetooth::le_audio::btle_audio_bits_per_sample_index_t> {}; 601 template <> 602 struct formatter<bluetooth::le_audio::btle_audio_channel_count_index_t> 603 : enum_formatter<bluetooth::le_audio::btle_audio_channel_count_index_t> {}; 604 template <> 605 struct formatter<bluetooth::le_audio::btle_audio_frame_duration_index_t> 606 : enum_formatter<bluetooth::le_audio::btle_audio_frame_duration_index_t> {}; 607 template <> 608 struct formatter<bluetooth::le_audio::GroupStreamStatus> 609 : enum_formatter<bluetooth::le_audio::GroupStreamStatus> {}; 610 } // namespace std 611