1 /* 2 * Copyright (C) 2016 BlueKitchen GmbH 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. Neither the name of the copyright holders nor the names of 14 * contributors may be used to endorse or promote products derived 15 * from this software without specific prior written permission. 16 * 4. Any redistribution, use, or modification is done solely for 17 * personal benefit and not for any commercial purpose or for 18 * monetary gain. 19 * 20 * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS 21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BLUEKITCHEN 24 * GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 26 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 27 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 28 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 29 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 30 * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 * 33 * Please inquire about commercial licensing options at 34 * [email protected] 35 * 36 */ 37 38 #define BTSTACK_FILE__ "a2dp_source_demo.c" 39 40 /* 41 * a2dp_source_demo.c 42 */ 43 44 // ***************************************************************************** 45 /* EXAMPLE_START(a2dp_source_demo): A2DP Source - Stream Audio and Control Volume 46 * 47 * @text This A2DP Source example demonstrates how to send an audio data stream 48 * to a remote A2DP Sink device and how to switch between two audio data sources. 49 * In addition, the AVRCP Target is used to answer queries on currently played media, 50 * as well as to handle remote playback control, i.e. play, stop, repeat, etc. If HAVE_BTSTACK_STDIN 51 * is set, press SPACE on the console to show the available AVDTP and AVRCP commands. 52 * 53 * @text To test with a remote device, e.g. a Bluetooth speaker, 54 * set the device_addr_string to the Bluetooth address of your 55 * remote device in the code, and use the UI to connect and start playback. 56 * 57 * @text For more info on BTstack audio, see our blog post 58 * [A2DP Sink and Source on STM32 F4 Discovery Board](http://bluekitchen-gmbh.com/a2dp-sink-and-source-on-stm32-f4-discovery-board/). 59 * 60 */ 61 // ***************************************************************************** 62 63 64 #include <stdint.h> 65 #include <stdio.h> 66 #include <inttypes.h> 67 #include <string.h> 68 69 #include "btstack.h" 70 #include "hxcmod.h" 71 #include "mods/mod.h" 72 73 // logarithmic volume reduction, samples are divided by 2^x 74 // #define VOLUME_REDUCTION 3 75 76 //#define AVRCP_BROWSING_ENABLED 77 78 #define NUM_CHANNELS 2 79 #define BYTES_PER_AUDIO_SAMPLE (2*NUM_CHANNELS) 80 #define AUDIO_TIMEOUT_MS 10 81 #define TABLE_SIZE_441HZ 100 82 83 #define SBC_STORAGE_SIZE 1030 84 85 typedef enum { 86 STREAM_SINE = 0, 87 STREAM_MOD, 88 STREAM_PTS_TEST 89 } stream_data_source_t; 90 91 typedef struct { 92 uint16_t a2dp_cid; 93 uint8_t local_seid; 94 uint8_t remote_seid; 95 uint8_t stream_opened; 96 uint16_t avrcp_cid; 97 98 uint32_t time_audio_data_sent; // ms 99 uint32_t acc_num_missed_samples; 100 uint32_t samples_ready; 101 btstack_timer_source_t audio_timer; 102 uint8_t streaming; 103 int max_media_payload_size; 104 uint32_t rtp_timestamp; 105 106 uint8_t sbc_storage[SBC_STORAGE_SIZE]; 107 uint16_t sbc_storage_count; 108 uint8_t sbc_ready_to_send; 109 110 uint8_t volume; 111 } a2dp_media_sending_context_t; 112 113 static uint8_t media_sbc_codec_capabilities[] = { 114 (AVDTP_SBC_44100 << 4) | (AVDTP_SBC_48000 << 4) | AVDTP_SBC_STEREO, 115 0xFF,//(AVDTP_SBC_BLOCK_LENGTH_16 << 4) | (AVDTP_SBC_SUBBANDS_8 << 2) | AVDTP_SBC_ALLOCATION_METHOD_LOUDNESS, 116 2, 53 117 }; 118 119 // input signal: pre-computed int16 sine wave, 44100 Hz at 441 Hz 120 static const int16_t sine_int16_44100[] = { 121 0, 2057, 4107, 6140, 8149, 10126, 12062, 13952, 15786, 17557, 122 19260, 20886, 22431, 23886, 25247, 26509, 27666, 28714, 29648, 30466, 123 31163, 31738, 32187, 32509, 32702, 32767, 32702, 32509, 32187, 31738, 124 31163, 30466, 29648, 28714, 27666, 26509, 25247, 23886, 22431, 20886, 125 19260, 17557, 15786, 13952, 12062, 10126, 8149, 6140, 4107, 2057, 126 0, -2057, -4107, -6140, -8149, -10126, -12062, -13952, -15786, -17557, 127 -19260, -20886, -22431, -23886, -25247, -26509, -27666, -28714, -29648, -30466, 128 -31163, -31738, -32187, -32509, -32702, -32767, -32702, -32509, -32187, -31738, 129 -31163, -30466, -29648, -28714, -27666, -26509, -25247, -23886, -22431, -20886, 130 -19260, -17557, -15786, -13952, -12062, -10126, -8149, -6140, -4107, -2057, 131 }; 132 133 static const int num_samples_sine_int16_44100 = sizeof(sine_int16_44100) / 2; 134 135 // input signal: pre-computed int16 sine wave, 48000 Hz at 441 Hz 136 static const int16_t sine_int16_48000[] = { 137 0, 1905, 3804, 5690, 7557, 9398, 11207, 12978, 14706, 16383, 138 18006, 19567, 21062, 22486, 23834, 25101, 26283, 27376, 28377, 29282, 139 30087, 30791, 31390, 31884, 32269, 32545, 32712, 32767, 32712, 32545, 140 32269, 31884, 31390, 30791, 30087, 29282, 28377, 27376, 26283, 25101, 141 23834, 22486, 21062, 19567, 18006, 16383, 14706, 12978, 11207, 9398, 142 7557, 5690, 3804, 1905, 0, -1905, -3804, -5690, -7557, -9398, 143 -11207, -12978, -14706, -16384, -18006, -19567, -21062, -22486, -23834, -25101, 144 -26283, -27376, -28377, -29282, -30087, -30791, -31390, -31884, -32269, -32545, 145 -32712, -32767, -32712, -32545, -32269, -31884, -31390, -30791, -30087, -29282, 146 -28377, -27376, -26283, -25101, -23834, -22486, -21062, -19567, -18006, -16384, 147 -14706, -12978, -11207, -9398, -7557, -5690, -3804, -1905, }; 148 149 static const int num_samples_sine_int16_48000 = sizeof(sine_int16_48000) / 2; 150 151 static const int A2DP_SOURCE_DEMO_INQUIRY_DURATION_1280MS = 12; 152 153 typedef struct { 154 int reconfigure; 155 156 int num_channels; 157 int sampling_frequency; 158 int block_length; 159 int subbands; 160 int min_bitpool_value; 161 int max_bitpool_value; 162 btstack_sbc_channel_mode_t channel_mode; 163 btstack_sbc_allocation_method_t allocation_method; 164 } media_codec_configuration_sbc_t; 165 166 static btstack_packet_callback_registration_t hci_event_callback_registration; 167 168 // Minijambox: 169 static const char * device_addr_string = "00:21:3C:AC:F7:38"; 170 171 static bd_addr_t device_addr; 172 static bool scan_active; 173 174 static uint8_t sdp_a2dp_source_service_buffer[150]; 175 static uint8_t sdp_avrcp_target_service_buffer[200]; 176 static uint8_t sdp_avrcp_controller_service_buffer[200]; 177 static uint8_t device_id_sdp_service_buffer[100]; 178 179 static media_codec_configuration_sbc_t sbc_configuration; 180 static btstack_sbc_encoder_state_t sbc_encoder_state; 181 182 static uint8_t media_sbc_codec_configuration[4]; 183 static a2dp_media_sending_context_t media_tracker; 184 185 static stream_data_source_t data_source; 186 187 static int sine_phase; 188 static int current_sample_rate = 44100; 189 static int new_sample_rate = 44100; 190 191 static int hxcmod_initialized; 192 static modcontext mod_context; 193 static tracker_buffer_state trkbuf; 194 195 /* AVRCP Target context START */ 196 197 typedef struct { 198 uint8_t track_id[8]; 199 uint32_t song_length_ms; 200 avrcp_playback_status_t status; 201 uint32_t song_position_ms; // 0xFFFFFFFF if not supported 202 } avrcp_play_status_info_t; 203 204 // python -c "print('a'*512)" 205 static const char title[] = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; 206 207 avrcp_track_t tracks[] = { 208 {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, 1, "Sine", "Generated", "A2DP Source Demo", "monotone", 12345}, 209 {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02}, 2, "Nao-deceased", "Decease", "A2DP Source Demo", "vivid", 12345}, 210 {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03}, 3, (char *)title, "Decease", "A2DP Source Demo", "vivid", 12345}, 211 }; 212 int current_track_index; 213 avrcp_play_status_info_t play_info; 214 215 /* AVRCP Target context END */ 216 217 /* @section Main Application Setup 218 * 219 * @text The Listing MainConfiguration shows how to setup AD2P Source and AVRCP services. 220 * Besides calling init() method for each service, you'll also need to register several packet handlers: 221 * - hci_packet_handler - handles legacy pairing, here by using fixed '0000' pin code. 222 * - a2dp_source_packet_handler - handles events on stream connection status (established, released), the media codec configuration, and, the commands on stream itself (open, pause, stopp). 223 * - avrcp_packet_handler - receives connect/disconnect event. 224 * - avrcp_controller_packet_handler - receives answers for sent AVRCP commands. 225 * - avrcp_target_packet_handler - receives AVRCP commands, and registered notifications. 226 * - stdin_process - used to trigger AVRCP commands to the A2DP Source device, such are get now playing info, start, stop, volume control. Requires HAVE_BTSTACK_STDIN. 227 * 228 * @text To announce A2DP Source and AVRCP services, you need to create corresponding 229 * SDP records and register them with the SDP service. 230 */ 231 232 /* LISTING_START(MainConfiguration): Setup Audio Source and AVRCP Target services */ 233 static void hci_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size); 234 static void a2dp_source_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t * event, uint16_t event_size); 235 static void avrcp_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size); 236 static void avrcp_target_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size); 237 static void avrcp_controller_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size); 238 #ifdef HAVE_BTSTACK_STDIN 239 static void stdin_process(char cmd); 240 #endif 241 242 static void a2dp_demo_hexcmod_configure_sample_rate(int sample_rate); 243 244 static int a2dp_source_and_avrcp_services_init(void){ 245 246 // Request role change on reconnecting headset to always use them in slave mode 247 hci_set_master_slave_policy(0); 248 // enabled EIR 249 hci_set_inquiry_mode(INQUIRY_MODE_RSSI_AND_EIR); 250 251 l2cap_init(); 252 253 #ifdef ENABLE_BLE 254 // Initialize LE Security Manager. Needed for cross-transport key derivation 255 sm_init(); 256 #endif 257 258 // Initialize A2DP Source 259 a2dp_source_init(); 260 a2dp_source_register_packet_handler(&a2dp_source_packet_handler); 261 262 // Create stream endpoint 263 avdtp_stream_endpoint_t * local_stream_endpoint = a2dp_source_create_stream_endpoint(AVDTP_AUDIO, AVDTP_CODEC_SBC, media_sbc_codec_capabilities, sizeof(media_sbc_codec_capabilities), media_sbc_codec_configuration, sizeof(media_sbc_codec_configuration)); 264 if (!local_stream_endpoint){ 265 printf("A2DP Source: not enough memory to create local stream endpoint\n"); 266 return 1; 267 } 268 269 avdtp_set_preferred_sampling_frequency(local_stream_endpoint, 44100); 270 271 // Store stream enpoint's SEP ID, as it is used by A2DP API to indentify the stream endpoint 272 media_tracker.local_seid = avdtp_local_seid(local_stream_endpoint); 273 avdtp_source_register_delay_reporting_category(media_tracker.local_seid); 274 275 // Initialize AVRCP Service 276 avrcp_init(); 277 avrcp_register_packet_handler(&avrcp_packet_handler); 278 // Initialize AVRCP Target 279 avrcp_target_init(); 280 avrcp_target_register_packet_handler(&avrcp_target_packet_handler); 281 282 // Initialize AVRCP Controller 283 avrcp_controller_init(); 284 avrcp_controller_register_packet_handler(&avrcp_controller_packet_handler); 285 286 // Initialize SDP, 287 sdp_init(); 288 289 // Create A2DP Source service record and register it with SDP 290 memset(sdp_a2dp_source_service_buffer, 0, sizeof(sdp_a2dp_source_service_buffer)); 291 a2dp_source_create_sdp_record(sdp_a2dp_source_service_buffer, sdp_create_service_record_handle(), AVDTP_SOURCE_FEATURE_MASK_PLAYER, NULL, NULL); 292 btstack_assert(de_get_len( sdp_a2dp_source_service_buffer) <= sizeof(sdp_a2dp_source_service_buffer)); 293 sdp_register_service(sdp_a2dp_source_service_buffer); 294 295 // Create AVRCP Target service record and register it with SDP. We receive Category 1 commands from the headphone, e.g. play/pause 296 memset(sdp_avrcp_target_service_buffer, 0, sizeof(sdp_avrcp_target_service_buffer)); 297 uint16_t supported_features = AVRCP_FEATURE_MASK_CATEGORY_PLAYER_OR_RECORDER; 298 #ifdef AVRCP_BROWSING_ENABLED 299 supported_features |= AVRCP_FEATURE_MASK_BROWSING; 300 #endif 301 avrcp_target_create_sdp_record(sdp_avrcp_target_service_buffer, sdp_create_service_record_handle(), supported_features, NULL, NULL); 302 btstack_assert(de_get_len( sdp_avrcp_target_service_buffer) <= sizeof(sdp_avrcp_target_service_buffer)); 303 sdp_register_service(sdp_avrcp_target_service_buffer); 304 305 // Create AVRCP Controller service record and register it with SDP. We send Category 2 commands to the headphone, e.g. volume up/down 306 memset(sdp_avrcp_controller_service_buffer, 0, sizeof(sdp_avrcp_controller_service_buffer)); 307 uint16_t controller_supported_features = AVRCP_FEATURE_MASK_CATEGORY_MONITOR_OR_AMPLIFIER; 308 avrcp_controller_create_sdp_record(sdp_avrcp_controller_service_buffer, sdp_create_service_record_handle(), controller_supported_features, NULL, NULL); 309 btstack_assert(de_get_len( sdp_avrcp_controller_service_buffer) <= sizeof(sdp_avrcp_controller_service_buffer)); 310 sdp_register_service(sdp_avrcp_controller_service_buffer); 311 312 // Register Device ID (PnP) service SDP record 313 memset(device_id_sdp_service_buffer, 0, sizeof(device_id_sdp_service_buffer)); 314 device_id_create_sdp_record(device_id_sdp_service_buffer, sdp_create_service_record_handle(), DEVICE_ID_VENDOR_ID_SOURCE_BLUETOOTH, BLUETOOTH_COMPANY_ID_BLUEKITCHEN_GMBH, 1, 1); 315 btstack_assert(de_get_len( device_id_sdp_service_buffer) <= sizeof(device_id_sdp_service_buffer)); 316 sdp_register_service(device_id_sdp_service_buffer); 317 318 // Set local name with a template Bluetooth address, that will be automatically 319 // replaced with a actual address once it is available, i.e. when BTstack boots 320 // up and starts talking to a Bluetooth module. 321 gap_set_local_name("A2DP Source 00:00:00:00:00:00"); 322 gap_discoverable_control(1); 323 gap_set_class_of_device(0x200408); 324 325 // Register for HCI events. 326 hci_event_callback_registration.callback = &hci_packet_handler; 327 hci_add_event_handler(&hci_event_callback_registration); 328 329 data_source = STREAM_MOD; 330 331 // Parse human readable Bluetooth address. 332 sscanf_bd_addr(device_addr_string, device_addr); 333 334 #ifdef HAVE_BTSTACK_STDIN 335 btstack_stdin_setup(stdin_process); 336 #endif 337 return 0; 338 } 339 /* LISTING_END */ 340 341 static void a2dp_demo_hexcmod_configure_sample_rate(int sample_rate){ 342 if (!hxcmod_initialized){ 343 hxcmod_initialized = hxcmod_init(&mod_context); 344 if (!hxcmod_initialized) { 345 printf("could not initialize hxcmod\n"); 346 return; 347 } 348 } 349 current_sample_rate = sample_rate; 350 media_tracker.sbc_storage_count = 0; 351 media_tracker.samples_ready = 0; 352 hxcmod_unload(&mod_context); 353 hxcmod_setcfg(&mod_context, current_sample_rate, 16, 1, 1, 1); 354 hxcmod_load(&mod_context, (void *) &mod_data, mod_len); 355 } 356 357 static void a2dp_demo_send_media_packet(void){ 358 int num_bytes_in_frame = btstack_sbc_encoder_sbc_buffer_length(); 359 int bytes_in_storage = media_tracker.sbc_storage_count; 360 uint8_t num_sbc_frames = bytes_in_storage / num_bytes_in_frame; 361 // Prepend SBC Header 362 media_tracker.sbc_storage[0] = num_sbc_frames; // (fragmentation << 7) | (starting_packet << 6) | (last_packet << 5) | num_frames; 363 a2dp_source_stream_send_media_payload_rtp(media_tracker.a2dp_cid, media_tracker.local_seid, 0, 364 media_tracker.rtp_timestamp, 365 media_tracker.sbc_storage, bytes_in_storage + 1); 366 367 // update rtp_timestamp 368 unsigned int num_audio_samples_per_sbc_buffer = btstack_sbc_encoder_num_audio_frames(); 369 media_tracker.rtp_timestamp += num_sbc_frames * num_audio_samples_per_sbc_buffer; 370 371 media_tracker.sbc_storage_count = 0; 372 media_tracker.sbc_ready_to_send = 0; 373 } 374 375 static void produce_sine_audio(int16_t * pcm_buffer, int num_samples_to_write){ 376 int count; 377 for (count = 0; count < num_samples_to_write ; count++){ 378 switch (current_sample_rate){ 379 case 44100: 380 pcm_buffer[count * 2] = sine_int16_44100[sine_phase]; 381 pcm_buffer[count * 2 + 1] = sine_int16_44100[sine_phase]; 382 sine_phase++; 383 if (sine_phase >= num_samples_sine_int16_44100){ 384 sine_phase -= num_samples_sine_int16_44100; 385 } 386 break; 387 case 48000: 388 pcm_buffer[count * 2] = sine_int16_48000[sine_phase]; 389 pcm_buffer[count * 2 + 1] = sine_int16_48000[sine_phase]; 390 sine_phase++; 391 if (sine_phase >= num_samples_sine_int16_48000){ 392 sine_phase -= num_samples_sine_int16_48000; 393 } 394 break; 395 default: 396 break; 397 } 398 } 399 } 400 401 static void produce_mod_audio(int16_t * pcm_buffer, int num_samples_to_write){ 402 hxcmod_fillbuffer(&mod_context, (unsigned short *) &pcm_buffer[0], num_samples_to_write, &trkbuf); 403 } 404 405 static void produce_audio(int16_t * pcm_buffer, int num_samples){ 406 switch (data_source){ 407 case STREAM_SINE: 408 produce_sine_audio(pcm_buffer, num_samples); 409 break; 410 case STREAM_MOD: 411 produce_mod_audio(pcm_buffer, num_samples); 412 break; 413 default: 414 break; 415 } 416 #ifdef VOLUME_REDUCTION 417 int i; 418 for (i=0;i<num_samples*2;i++){ 419 if (pcm_buffer[i] > 0){ 420 pcm_buffer[i] = pcm_buffer[i] >> VOLUME_REDUCTION; 421 } else { 422 pcm_buffer[i] = -((-pcm_buffer[i]) >> VOLUME_REDUCTION); 423 } 424 } 425 #endif 426 } 427 428 static int a2dp_demo_fill_sbc_audio_buffer(a2dp_media_sending_context_t * context){ 429 // perform sbc encoding 430 int total_num_bytes_read = 0; 431 unsigned int num_audio_samples_per_sbc_buffer = btstack_sbc_encoder_num_audio_frames(); 432 while (context->samples_ready >= num_audio_samples_per_sbc_buffer 433 && (context->max_media_payload_size - context->sbc_storage_count) >= btstack_sbc_encoder_sbc_buffer_length()){ 434 435 int16_t pcm_frame[256*NUM_CHANNELS]; 436 437 produce_audio(pcm_frame, num_audio_samples_per_sbc_buffer); 438 btstack_sbc_encoder_process_data(pcm_frame); 439 440 uint16_t sbc_frame_size = btstack_sbc_encoder_sbc_buffer_length(); 441 uint8_t * sbc_frame = btstack_sbc_encoder_sbc_buffer(); 442 443 total_num_bytes_read += num_audio_samples_per_sbc_buffer; 444 // first byte in sbc storage contains sbc media header 445 memcpy(&context->sbc_storage[1 + context->sbc_storage_count], sbc_frame, sbc_frame_size); 446 context->sbc_storage_count += sbc_frame_size; 447 context->samples_ready -= num_audio_samples_per_sbc_buffer; 448 } 449 return total_num_bytes_read; 450 } 451 452 static void a2dp_demo_audio_timeout_handler(btstack_timer_source_t * timer){ 453 a2dp_media_sending_context_t * context = (a2dp_media_sending_context_t *) btstack_run_loop_get_timer_context(timer); 454 btstack_run_loop_set_timer(&context->audio_timer, AUDIO_TIMEOUT_MS); 455 btstack_run_loop_add_timer(&context->audio_timer); 456 uint32_t now = btstack_run_loop_get_time_ms(); 457 458 uint32_t update_period_ms = AUDIO_TIMEOUT_MS; 459 if (context->time_audio_data_sent > 0){ 460 update_period_ms = now - context->time_audio_data_sent; 461 } 462 463 uint32_t num_samples = (update_period_ms * current_sample_rate) / 1000; 464 context->acc_num_missed_samples += (update_period_ms * current_sample_rate) % 1000; 465 466 while (context->acc_num_missed_samples >= 1000){ 467 num_samples++; 468 context->acc_num_missed_samples -= 1000; 469 } 470 context->time_audio_data_sent = now; 471 context->samples_ready += num_samples; 472 473 if (context->sbc_ready_to_send) return; 474 475 a2dp_demo_fill_sbc_audio_buffer(context); 476 477 if ((context->sbc_storage_count + btstack_sbc_encoder_sbc_buffer_length()) > context->max_media_payload_size){ 478 // schedule sending 479 context->sbc_ready_to_send = 1; 480 a2dp_source_stream_endpoint_request_can_send_now(context->a2dp_cid, context->local_seid); 481 } 482 } 483 484 static void a2dp_demo_timer_start(a2dp_media_sending_context_t * context){ 485 context->max_media_payload_size = btstack_min(a2dp_max_media_payload_size(context->a2dp_cid, context->local_seid), SBC_STORAGE_SIZE); 486 context->sbc_storage_count = 0; 487 context->sbc_ready_to_send = 0; 488 context->streaming = 1; 489 btstack_run_loop_remove_timer(&context->audio_timer); 490 btstack_run_loop_set_timer_handler(&context->audio_timer, a2dp_demo_audio_timeout_handler); 491 btstack_run_loop_set_timer_context(&context->audio_timer, context); 492 btstack_run_loop_set_timer(&context->audio_timer, AUDIO_TIMEOUT_MS); 493 btstack_run_loop_add_timer(&context->audio_timer); 494 } 495 496 static void a2dp_demo_timer_stop(a2dp_media_sending_context_t * context){ 497 context->time_audio_data_sent = 0; 498 context->acc_num_missed_samples = 0; 499 context->samples_ready = 0; 500 context->streaming = 1; 501 context->sbc_storage_count = 0; 502 context->sbc_ready_to_send = 0; 503 btstack_run_loop_remove_timer(&context->audio_timer); 504 } 505 506 static void dump_sbc_configuration(media_codec_configuration_sbc_t * configuration){ 507 printf("Received media codec configuration:\n"); 508 printf(" - num_channels: %d\n", configuration->num_channels); 509 printf(" - sampling_frequency: %d\n", configuration->sampling_frequency); 510 printf(" - channel_mode: %d\n", configuration->channel_mode); 511 printf(" - block_length: %d\n", configuration->block_length); 512 printf(" - subbands: %d\n", configuration->subbands); 513 printf(" - allocation_method: %d\n", configuration->allocation_method); 514 printf(" - bitpool_value [%d, %d] \n", configuration->min_bitpool_value, configuration->max_bitpool_value); 515 } 516 517 static void a2dp_source_demo_start_scanning(void){ 518 printf("Start scanning...\n"); 519 gap_inquiry_start(A2DP_SOURCE_DEMO_INQUIRY_DURATION_1280MS); 520 scan_active = true; 521 } 522 523 static void hci_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ 524 UNUSED(channel); 525 UNUSED(size); 526 if (packet_type != HCI_EVENT_PACKET) return; 527 uint8_t status; 528 UNUSED(status); 529 530 bd_addr_t address; 531 uint32_t cod; 532 533 // Service Class: Rendering | Audio, Major Device Class: Audio 534 const uint32_t bluetooth_speaker_cod = 0x200000 | 0x040000 | 0x000400; 535 536 switch (hci_event_packet_get_type(packet)){ 537 #ifndef HAVE_BTSTACK_STDIN 538 case BTSTACK_EVENT_STATE: 539 if (btstack_event_state_get_state(packet) != HCI_STATE_WORKING) return; 540 a2dp_source_demo_start_scanning(); 541 break; 542 #endif 543 case HCI_EVENT_PIN_CODE_REQUEST: 544 printf("Pin code request - using '0000'\n"); 545 hci_event_pin_code_request_get_bd_addr(packet, address); 546 gap_pin_code_response(address, "0000"); 547 break; 548 case GAP_EVENT_INQUIRY_RESULT: 549 gap_event_inquiry_result_get_bd_addr(packet, address); 550 // print info 551 printf("Device found: %s ", bd_addr_to_str(address)); 552 cod = gap_event_inquiry_result_get_class_of_device(packet); 553 printf("with COD: %06" PRIx32, cod); 554 if (gap_event_inquiry_result_get_rssi_available(packet)){ 555 printf(", rssi %d dBm", (int8_t) gap_event_inquiry_result_get_rssi(packet)); 556 } 557 if (gap_event_inquiry_result_get_name_available(packet)){ 558 char name_buffer[240]; 559 int name_len = gap_event_inquiry_result_get_name_len(packet); 560 memcpy(name_buffer, gap_event_inquiry_result_get_name(packet), name_len); 561 name_buffer[name_len] = 0; 562 printf(", name '%s'", name_buffer); 563 } 564 printf("\n"); 565 if ((cod & bluetooth_speaker_cod) == bluetooth_speaker_cod){ 566 memcpy(device_addr, address, 6); 567 printf("Bluetooth speaker detected, trying to connect to %s...\n", bd_addr_to_str(device_addr)); 568 scan_active = false; 569 gap_inquiry_stop(); 570 a2dp_source_establish_stream(device_addr, &media_tracker.a2dp_cid); 571 } 572 break; 573 case GAP_EVENT_INQUIRY_COMPLETE: 574 if (scan_active){ 575 printf("No Bluetooth speakers found, scanning again...\n"); 576 gap_inquiry_start(A2DP_SOURCE_DEMO_INQUIRY_DURATION_1280MS); 577 } 578 break; 579 default: 580 break; 581 } 582 } 583 584 static void a2dp_source_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ 585 UNUSED(channel); 586 UNUSED(size); 587 uint8_t status; 588 uint8_t local_seid; 589 bd_addr_t address; 590 uint16_t cid; 591 592 avdtp_channel_mode_t channel_mode; 593 uint8_t allocation_method; 594 595 if (packet_type != HCI_EVENT_PACKET) return; 596 if (hci_event_packet_get_type(packet) != HCI_EVENT_A2DP_META) return; 597 598 switch (hci_event_a2dp_meta_get_subevent_code(packet)){ 599 case A2DP_SUBEVENT_SIGNALING_CONNECTION_ESTABLISHED: 600 a2dp_subevent_signaling_connection_established_get_bd_addr(packet, address); 601 cid = a2dp_subevent_signaling_connection_established_get_a2dp_cid(packet); 602 status = a2dp_subevent_signaling_connection_established_get_status(packet); 603 604 if (status != ERROR_CODE_SUCCESS){ 605 printf("A2DP Source: Connection failed, status 0x%02x, cid 0x%02x, a2dp_cid 0x%02x \n", status, cid, media_tracker.a2dp_cid); 606 media_tracker.a2dp_cid = 0; 607 break; 608 } 609 media_tracker.a2dp_cid = cid; 610 media_tracker.volume = 32; 611 612 printf("A2DP Source: Connected to address %s, a2dp cid 0x%02x, local seid 0x%02x.\n", bd_addr_to_str(address), media_tracker.a2dp_cid, media_tracker.local_seid); 613 break; 614 615 case A2DP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CONFIGURATION:{ 616 cid = avdtp_subevent_signaling_media_codec_sbc_configuration_get_avdtp_cid(packet); 617 if (cid != media_tracker.a2dp_cid) return; 618 619 media_tracker.remote_seid = a2dp_subevent_signaling_media_codec_sbc_configuration_get_remote_seid(packet); 620 621 sbc_configuration.reconfigure = a2dp_subevent_signaling_media_codec_sbc_configuration_get_reconfigure(packet); 622 sbc_configuration.num_channels = a2dp_subevent_signaling_media_codec_sbc_configuration_get_num_channels(packet); 623 sbc_configuration.sampling_frequency = a2dp_subevent_signaling_media_codec_sbc_configuration_get_sampling_frequency(packet); 624 sbc_configuration.block_length = a2dp_subevent_signaling_media_codec_sbc_configuration_get_block_length(packet); 625 sbc_configuration.subbands = a2dp_subevent_signaling_media_codec_sbc_configuration_get_subbands(packet); 626 sbc_configuration.min_bitpool_value = a2dp_subevent_signaling_media_codec_sbc_configuration_get_min_bitpool_value(packet); 627 sbc_configuration.max_bitpool_value = a2dp_subevent_signaling_media_codec_sbc_configuration_get_max_bitpool_value(packet); 628 629 channel_mode = (avdtp_channel_mode_t) a2dp_subevent_signaling_media_codec_sbc_configuration_get_channel_mode(packet); 630 allocation_method = a2dp_subevent_signaling_media_codec_sbc_configuration_get_allocation_method(packet); 631 632 printf("A2DP Source: Received SBC codec configuration, sampling frequency %u, a2dp_cid 0x%02x, local seid 0x%02x, remote seid 0x%02x.\n", 633 sbc_configuration.sampling_frequency, cid, 634 a2dp_subevent_signaling_media_codec_sbc_configuration_get_local_seid(packet), 635 a2dp_subevent_signaling_media_codec_sbc_configuration_get_remote_seid(packet)); 636 637 // Adapt Bluetooth spec definition to SBC Encoder expected input 638 sbc_configuration.allocation_method = (btstack_sbc_allocation_method_t)(allocation_method - 1); 639 switch (channel_mode){ 640 case AVDTP_CHANNEL_MODE_JOINT_STEREO: 641 sbc_configuration.channel_mode = SBC_CHANNEL_MODE_JOINT_STEREO; 642 break; 643 case AVDTP_CHANNEL_MODE_STEREO: 644 sbc_configuration.channel_mode = SBC_CHANNEL_MODE_STEREO; 645 break; 646 case AVDTP_CHANNEL_MODE_DUAL_CHANNEL: 647 sbc_configuration.channel_mode = SBC_CHANNEL_MODE_DUAL_CHANNEL; 648 break; 649 case AVDTP_CHANNEL_MODE_MONO: 650 sbc_configuration.channel_mode = SBC_CHANNEL_MODE_MONO; 651 break; 652 default: 653 btstack_assert(false); 654 break; 655 } 656 dump_sbc_configuration(&sbc_configuration); 657 658 current_sample_rate = sbc_configuration.sampling_frequency; 659 a2dp_demo_hexcmod_configure_sample_rate(current_sample_rate); 660 661 btstack_sbc_encoder_init(&sbc_encoder_state, SBC_MODE_STANDARD, 662 sbc_configuration.block_length, sbc_configuration.subbands, 663 sbc_configuration.allocation_method, sbc_configuration.sampling_frequency, 664 sbc_configuration.max_bitpool_value, 665 sbc_configuration.channel_mode); 666 break; 667 } 668 669 case A2DP_SUBEVENT_SIGNALING_DELAY_REPORTING_CAPABILITY: 670 printf("A2DP Source: remote supports delay report, remote seid %d\n", 671 avdtp_subevent_signaling_delay_reporting_capability_get_remote_seid(packet)); 672 break; 673 case A2DP_SUBEVENT_SIGNALING_CAPABILITIES_DONE: 674 printf("A2DP Source: All capabilities reported, remote seid %d\n", 675 avdtp_subevent_signaling_capabilities_done_get_remote_seid(packet)); 676 break; 677 678 case A2DP_SUBEVENT_SIGNALING_DELAY_REPORT: 679 printf("A2DP Source: Received delay report of %d.%0d ms, local seid %d\n", 680 avdtp_subevent_signaling_delay_report_get_delay_100us(packet)/10, avdtp_subevent_signaling_delay_report_get_delay_100us(packet)%10, 681 avdtp_subevent_signaling_delay_report_get_local_seid(packet)); 682 break; 683 684 case A2DP_SUBEVENT_STREAM_ESTABLISHED: 685 a2dp_subevent_stream_established_get_bd_addr(packet, address); 686 status = a2dp_subevent_stream_established_get_status(packet); 687 if (status != ERROR_CODE_SUCCESS){ 688 printf("A2DP Source: Stream failed, status 0x%02x.\n", status); 689 break; 690 } 691 692 local_seid = a2dp_subevent_stream_established_get_local_seid(packet); 693 cid = a2dp_subevent_stream_established_get_a2dp_cid(packet); 694 695 printf("A2DP Source: Stream established a2dp_cid 0x%02x, local_seid 0x%02x, remote_seid 0x%02x\n", cid, local_seid, a2dp_subevent_stream_established_get_remote_seid(packet)); 696 697 a2dp_demo_hexcmod_configure_sample_rate(current_sample_rate); 698 media_tracker.stream_opened = 1; 699 status = a2dp_source_start_stream(media_tracker.a2dp_cid, media_tracker.local_seid); 700 break; 701 702 case A2DP_SUBEVENT_STREAM_RECONFIGURED: 703 status = a2dp_subevent_stream_reconfigured_get_status(packet); 704 local_seid = a2dp_subevent_stream_reconfigured_get_local_seid(packet); 705 cid = a2dp_subevent_stream_reconfigured_get_a2dp_cid(packet); 706 707 if (status != ERROR_CODE_SUCCESS){ 708 printf("A2DP Source: Stream reconfiguration failed, status 0x%02x\n", status); 709 break; 710 } 711 712 printf("A2DP Source: Stream reconfigured a2dp_cid 0x%02x, local_seid 0x%02x\n", cid, local_seid); 713 a2dp_demo_hexcmod_configure_sample_rate(new_sample_rate); 714 status = a2dp_source_start_stream(media_tracker.a2dp_cid, media_tracker.local_seid); 715 break; 716 717 case A2DP_SUBEVENT_STREAM_STARTED: 718 local_seid = a2dp_subevent_stream_started_get_local_seid(packet); 719 cid = a2dp_subevent_stream_started_get_a2dp_cid(packet); 720 721 play_info.status = AVRCP_PLAYBACK_STATUS_PLAYING; 722 if (media_tracker.avrcp_cid){ 723 avrcp_target_set_now_playing_info(media_tracker.avrcp_cid, &tracks[data_source], sizeof(tracks)/sizeof(avrcp_track_t)); 724 avrcp_target_set_playback_status(media_tracker.avrcp_cid, AVRCP_PLAYBACK_STATUS_PLAYING); 725 } 726 a2dp_demo_timer_start(&media_tracker); 727 printf("A2DP Source: Stream started, a2dp_cid 0x%02x, local_seid 0x%02x\n", cid, local_seid); 728 break; 729 730 case A2DP_SUBEVENT_STREAMING_CAN_SEND_MEDIA_PACKET_NOW: 731 local_seid = a2dp_subevent_streaming_can_send_media_packet_now_get_local_seid(packet); 732 cid = a2dp_subevent_signaling_media_codec_sbc_configuration_get_a2dp_cid(packet); 733 a2dp_demo_send_media_packet(); 734 break; 735 736 case A2DP_SUBEVENT_STREAM_SUSPENDED: 737 local_seid = a2dp_subevent_stream_suspended_get_local_seid(packet); 738 cid = a2dp_subevent_stream_suspended_get_a2dp_cid(packet); 739 740 play_info.status = AVRCP_PLAYBACK_STATUS_PAUSED; 741 if (media_tracker.avrcp_cid){ 742 avrcp_target_set_playback_status(media_tracker.avrcp_cid, AVRCP_PLAYBACK_STATUS_PAUSED); 743 } 744 printf("A2DP Source: Stream paused, a2dp_cid 0x%02x, local_seid 0x%02x\n", cid, local_seid); 745 746 a2dp_demo_timer_stop(&media_tracker); 747 break; 748 749 case A2DP_SUBEVENT_STREAM_RELEASED: 750 play_info.status = AVRCP_PLAYBACK_STATUS_STOPPED; 751 cid = a2dp_subevent_stream_released_get_a2dp_cid(packet); 752 local_seid = a2dp_subevent_stream_released_get_local_seid(packet); 753 754 printf("A2DP Source: Stream released, a2dp_cid 0x%02x, local_seid 0x%02x\n", cid, local_seid); 755 756 if (cid == media_tracker.a2dp_cid) { 757 media_tracker.stream_opened = 0; 758 printf("A2DP Source: Stream released.\n"); 759 } 760 if (media_tracker.avrcp_cid){ 761 avrcp_target_set_now_playing_info(media_tracker.avrcp_cid, NULL, sizeof(tracks)/sizeof(avrcp_track_t)); 762 avrcp_target_set_playback_status(media_tracker.avrcp_cid, AVRCP_PLAYBACK_STATUS_STOPPED); 763 } 764 a2dp_demo_timer_stop(&media_tracker); 765 break; 766 case A2DP_SUBEVENT_SIGNALING_CONNECTION_RELEASED: 767 cid = a2dp_subevent_signaling_connection_released_get_a2dp_cid(packet); 768 if (cid == media_tracker.a2dp_cid) { 769 media_tracker.avrcp_cid = 0; 770 media_tracker.a2dp_cid = 0; 771 printf("A2DP Source: Signaling released.\n\n"); 772 } 773 break; 774 default: 775 break; 776 } 777 } 778 779 static void avrcp_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ 780 UNUSED(channel); 781 UNUSED(size); 782 bd_addr_t event_addr; 783 uint16_t local_cid; 784 uint8_t status = ERROR_CODE_SUCCESS; 785 786 if (packet_type != HCI_EVENT_PACKET) return; 787 if (hci_event_packet_get_type(packet) != HCI_EVENT_AVRCP_META) return; 788 789 switch (packet[2]){ 790 case AVRCP_SUBEVENT_CONNECTION_ESTABLISHED: 791 local_cid = avrcp_subevent_connection_established_get_avrcp_cid(packet); 792 status = avrcp_subevent_connection_established_get_status(packet); 793 if (status != ERROR_CODE_SUCCESS){ 794 printf("AVRCP: Connection failed, local cid 0x%02x, status 0x%02x\n", local_cid, status); 795 return; 796 } 797 media_tracker.avrcp_cid = local_cid; 798 avrcp_subevent_connection_established_get_bd_addr(packet, event_addr); 799 800 printf("AVRCP: Channel to %s successfully opened, avrcp_cid 0x%02x\n", bd_addr_to_str(event_addr), media_tracker.avrcp_cid); 801 802 avrcp_target_support_event(media_tracker.avrcp_cid, AVRCP_NOTIFICATION_EVENT_PLAYBACK_STATUS_CHANGED); 803 avrcp_target_support_event(media_tracker.avrcp_cid, AVRCP_NOTIFICATION_EVENT_TRACK_CHANGED); 804 avrcp_target_support_event(media_tracker.avrcp_cid, AVRCP_NOTIFICATION_EVENT_NOW_PLAYING_CONTENT_CHANGED); 805 avrcp_target_set_now_playing_info(media_tracker.avrcp_cid, NULL, sizeof(tracks)/sizeof(avrcp_track_t)); 806 807 printf("Enable Volume Change notification\n"); 808 avrcp_controller_enable_notification(media_tracker.avrcp_cid, AVRCP_NOTIFICATION_EVENT_VOLUME_CHANGED); 809 printf("Enable Battery Status Change notification\n"); 810 avrcp_controller_enable_notification(media_tracker.avrcp_cid, AVRCP_NOTIFICATION_EVENT_BATT_STATUS_CHANGED); 811 return; 812 813 case AVRCP_SUBEVENT_CONNECTION_RELEASED: 814 printf("AVRCP Target: Disconnected, avrcp_cid 0x%02x\n", avrcp_subevent_connection_released_get_avrcp_cid(packet)); 815 media_tracker.avrcp_cid = 0; 816 return; 817 default: 818 break; 819 } 820 821 if (status != ERROR_CODE_SUCCESS){ 822 printf("Responding to event 0x%02x failed, status 0x%02x\n", packet[2], status); 823 } 824 } 825 826 static void avrcp_target_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ 827 UNUSED(channel); 828 UNUSED(size); 829 uint8_t status = ERROR_CODE_SUCCESS; 830 831 if (packet_type != HCI_EVENT_PACKET) return; 832 if (hci_event_packet_get_type(packet) != HCI_EVENT_AVRCP_META) return; 833 834 bool button_pressed; 835 char const * button_state; 836 avrcp_operation_id_t operation_id; 837 838 switch (packet[2]){ 839 case AVRCP_SUBEVENT_PLAY_STATUS_QUERY: 840 status = avrcp_target_play_status(media_tracker.avrcp_cid, play_info.song_length_ms, play_info.song_position_ms, play_info.status); 841 break; 842 // case AVRCP_SUBEVENT_NOW_PLAYING_INFO_QUERY: 843 // status = avrcp_target_now_playing_info(avrcp_cid); 844 // break; 845 case AVRCP_SUBEVENT_OPERATION: 846 operation_id = avrcp_subevent_operation_get_operation_id(packet); 847 button_pressed = avrcp_subevent_operation_get_button_pressed(packet) > 0; 848 button_state = button_pressed ? "PRESS" : "RELEASE"; 849 850 printf("AVRCP Target: operation %s (%s)\n", avrcp_operation2str(operation_id), button_state); 851 852 if (!button_pressed){ 853 break; 854 } 855 switch (operation_id) { 856 case AVRCP_OPERATION_ID_PLAY: 857 status = a2dp_source_start_stream(media_tracker.a2dp_cid, media_tracker.local_seid); 858 break; 859 case AVRCP_OPERATION_ID_PAUSE: 860 status = a2dp_source_pause_stream(media_tracker.a2dp_cid, media_tracker.local_seid); 861 break; 862 case AVRCP_OPERATION_ID_STOP: 863 status = a2dp_source_disconnect(media_tracker.a2dp_cid); 864 break; 865 default: 866 break; 867 } 868 break; 869 default: 870 break; 871 } 872 873 if (status != ERROR_CODE_SUCCESS){ 874 printf("Responding to event 0x%02x failed, status 0x%02x\n", packet[2], status); 875 } 876 } 877 878 static void avrcp_controller_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ 879 UNUSED(channel); 880 UNUSED(size); 881 882 if (packet_type != HCI_EVENT_PACKET) return; 883 if (hci_event_packet_get_type(packet) != HCI_EVENT_AVRCP_META) return; 884 if (!media_tracker.avrcp_cid) return; 885 886 switch (packet[2]){ 887 case AVRCP_SUBEVENT_NOTIFICATION_VOLUME_CHANGED: 888 printf("AVRCP Controller: Notification Absolute Volume %d %%\n", avrcp_subevent_notification_volume_changed_get_absolute_volume(packet) * 100 / 127); 889 break; 890 case AVRCP_SUBEVENT_NOTIFICATION_EVENT_BATT_STATUS_CHANGED: 891 // see avrcp_battery_status_t 892 printf("AVRCP Controller: Notification Battery Status 0x%02x\n", avrcp_subevent_notification_event_batt_status_changed_get_battery_status(packet)); 893 break; 894 case AVRCP_SUBEVENT_NOTIFICATION_STATE: 895 printf("AVRCP Controller: Notification %s - %s\n", 896 avrcp_event2str(avrcp_subevent_notification_state_get_event_id(packet)), 897 avrcp_subevent_notification_state_get_enabled(packet) != 0 ? "enabled" : "disabled"); 898 break; 899 default: 900 break; 901 } 902 } 903 904 #ifdef HAVE_BTSTACK_STDIN 905 static void show_usage(void){ 906 bd_addr_t iut_address; 907 gap_local_bd_addr(iut_address); 908 printf("\n--- Bluetooth A2DP Source/AVRCP Demo %s ---\n", bd_addr_to_str(iut_address)); 909 printf("a - Scan for Bluetooth speaker and connect\n"); 910 printf("b - A2DP Source create connection to addr %s\n", device_addr_string); 911 printf("B - A2DP Source disconnect\n"); 912 printf("c - AVRCP create connection to addr %s\n", device_addr_string); 913 printf("C - AVRCP disconnect\n"); 914 printf("D - delete all link keys\n"); 915 916 printf("x - start streaming sine\n"); 917 if (hxcmod_initialized){ 918 printf("z - start streaming '%s'\n", mod_name); 919 } 920 printf("p - pause streaming\n"); 921 printf("w - reconfigure stream for 44100 Hz\n"); 922 printf("e - reconfigure stream for 48000 Hz\n"); 923 printf("t - volume up\n"); 924 printf("T - volume down\n"); 925 printf("v - volume up (via set absolute volume)\n"); 926 printf("V - volume down (via set absolute volume)\n"); 927 928 printf("---\n"); 929 } 930 931 static void stdin_process(char cmd){ 932 uint8_t status = ERROR_CODE_SUCCESS; 933 switch (cmd){ 934 case 'a': 935 a2dp_source_demo_start_scanning(); 936 break; 937 case 'b': 938 status = a2dp_source_establish_stream(device_addr, &media_tracker.a2dp_cid); 939 printf("%c - Create A2DP Source connection to addr %s, cid 0x%02x.\n", cmd, bd_addr_to_str(device_addr), media_tracker.a2dp_cid); 940 break; 941 case 'B': 942 printf("%c - A2DP Source Disconnect from cid 0x%2x\n", cmd, media_tracker.a2dp_cid); 943 status = a2dp_source_disconnect(media_tracker.a2dp_cid); 944 break; 945 case 'c': 946 printf("%c - Create AVRCP connection to addr %s.\n", cmd, bd_addr_to_str(device_addr)); 947 status = avrcp_connect(device_addr, &media_tracker.avrcp_cid); 948 break; 949 case 'C': 950 printf("%c - AVRCP disconnect\n", cmd); 951 status = avrcp_disconnect(media_tracker.avrcp_cid); 952 break; 953 case 'D': 954 printf("Deleting all link keys\n"); 955 gap_delete_all_link_keys(); 956 break; 957 case '\n': 958 case '\r': 959 break; 960 961 case 't': 962 printf(" - volume up\n"); 963 status = avrcp_controller_volume_up(media_tracker.avrcp_cid); 964 break; 965 case 'T': 966 printf(" - volume down\n"); 967 status = avrcp_controller_volume_down(media_tracker.avrcp_cid); 968 break; 969 970 case 'v': 971 if (media_tracker.volume > 117){ 972 media_tracker.volume = 127; 973 } else { 974 media_tracker.volume += 10; 975 } 976 printf(" - volume up (via set absolute volume) %d%% (%d)\n", media_tracker.volume * 100 / 127, media_tracker.volume); 977 status = avrcp_controller_set_absolute_volume(media_tracker.avrcp_cid, media_tracker.volume); 978 break; 979 case 'V': 980 if (media_tracker.volume < 10){ 981 media_tracker.volume = 0; 982 } else { 983 media_tracker.volume -= 10; 984 } 985 printf(" - volume down (via set absolute volume) %d%% (%d)\n", media_tracker.volume * 100 / 127, media_tracker.volume); 986 status = avrcp_controller_set_absolute_volume(media_tracker.avrcp_cid, media_tracker.volume); 987 break; 988 989 case 'x': 990 if (media_tracker.avrcp_cid){ 991 avrcp_target_set_now_playing_info(media_tracker.avrcp_cid, &tracks[data_source], sizeof(tracks)/sizeof(avrcp_track_t)); 992 } 993 printf("%c - Play sine.\n", cmd); 994 data_source = STREAM_SINE; 995 if (!media_tracker.stream_opened) break; 996 status = a2dp_source_start_stream(media_tracker.a2dp_cid, media_tracker.local_seid); 997 break; 998 case 'z': 999 if (media_tracker.avrcp_cid){ 1000 avrcp_target_set_now_playing_info(media_tracker.avrcp_cid, &tracks[data_source], sizeof(tracks)/sizeof(avrcp_track_t)); 1001 } 1002 printf("%c - Play mod.\n", cmd); 1003 data_source = STREAM_MOD; 1004 if (!media_tracker.stream_opened) break; 1005 status = a2dp_source_start_stream(media_tracker.a2dp_cid, media_tracker.local_seid); 1006 break; 1007 1008 case 'p': 1009 if (!media_tracker.stream_opened) break; 1010 printf("%c - Pause stream.\n", cmd); 1011 status = a2dp_source_pause_stream(media_tracker.a2dp_cid, media_tracker.local_seid); 1012 break; 1013 1014 case 'w': 1015 if (!media_tracker.stream_opened) break; 1016 if (play_info.status == AVRCP_PLAYBACK_STATUS_PLAYING){ 1017 printf("Stream cannot be reconfigured while playing, please pause stream first\n"); 1018 break; 1019 } 1020 new_sample_rate = 44100; 1021 if (current_sample_rate == new_sample_rate){ 1022 printf("%c - Stream already configured for %d Hz.\n", cmd, new_sample_rate); 1023 } else { 1024 printf("%c - Reconfigure for %d Hz.\n", cmd, new_sample_rate); 1025 status = a2dp_source_reconfigure_stream_sampling_frequency(media_tracker.a2dp_cid, new_sample_rate); 1026 } 1027 break; 1028 1029 case 'e': 1030 if (!media_tracker.stream_opened) break; 1031 if (play_info.status == AVRCP_PLAYBACK_STATUS_PLAYING){ 1032 printf("Stream cannot be reconfigured while playing, please pause stream first\n"); 1033 break; 1034 } 1035 new_sample_rate = 48000; 1036 if (current_sample_rate == new_sample_rate){ 1037 printf("%c - Stream already configured for %d Hz.\n", cmd, new_sample_rate); 1038 } else { 1039 printf("%c - Reconfigure for %d Hz.\n", cmd, new_sample_rate); 1040 status = a2dp_source_reconfigure_stream_sampling_frequency(media_tracker.a2dp_cid, new_sample_rate); 1041 } 1042 break; 1043 1044 default: 1045 show_usage(); 1046 return; 1047 } 1048 if (status != ERROR_CODE_SUCCESS){ 1049 printf("Could not perform command \'%c\', status 0x%02x\n", cmd, status); 1050 } 1051 } 1052 #endif 1053 1054 1055 int btstack_main(int argc, const char * argv[]); 1056 int btstack_main(int argc, const char * argv[]){ 1057 (void)argc; 1058 (void)argv; 1059 1060 int err = a2dp_source_and_avrcp_services_init(); 1061 if (err) return err; 1062 // turn on! 1063 hci_power_control(HCI_POWER_ON); 1064 return 0; 1065 } 1066 /* EXAMPLE_END */ 1067