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 MATTHIAS 24 * RINGWALD 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): Serve audio stream and handle remote playback control and queries. 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. 51 * 52 * @test To test with a remote device, e.g. a Bluetooth speaker, 53 * set the device_addr_string to the Bluetooth address of your 54 * remote device in the code, and use the UI to connect and start playback. 55 * Tap SPACE on the console to show the available commands. 56 * 57 * 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 <stdlib.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 // #undef HAVE_BTSTACK_STDIN 76 77 //#define AVRCP_BROWSING_ENABLED 78 79 #define NUM_CHANNELS 2 80 #define BYTES_PER_AUDIO_SAMPLE (2*NUM_CHANNELS) 81 #define AUDIO_TIMEOUT_MS 10 82 #define TABLE_SIZE_441HZ 100 83 84 #define SBC_STORAGE_SIZE 1030 85 86 typedef enum { 87 STREAM_SINE = 0, 88 STREAM_MOD, 89 STREAM_PTS_TEST 90 } stream_data_source_t; 91 92 typedef struct { 93 uint16_t a2dp_cid; 94 uint8_t local_seid; 95 uint8_t remote_seid; 96 uint8_t stream_opened; 97 uint16_t avrcp_cid; 98 99 uint32_t time_audio_data_sent; // ms 100 uint32_t acc_num_missed_samples; 101 uint32_t samples_ready; 102 btstack_timer_source_t audio_timer; 103 uint8_t streaming; 104 int max_media_payload_size; 105 106 uint8_t sbc_storage[SBC_STORAGE_SIZE]; 107 uint16_t sbc_storage_count; 108 uint8_t sbc_ready_to_send; 109 } a2dp_media_sending_context_t; 110 111 static uint8_t media_sbc_codec_capabilities[] = { 112 (AVDTP_SBC_44100 << 4) | AVDTP_SBC_STEREO, 113 0xFF,//(AVDTP_SBC_BLOCK_LENGTH_16 << 4) | (AVDTP_SBC_SUBBANDS_8 << 2) | AVDTP_SBC_ALLOCATION_METHOD_LOUDNESS, 114 2, 53 115 }; 116 117 // input signal: pre-computed int16 sine wave, 44100 Hz at 441 Hz 118 static const int16_t sine_int16_44100[] = { 119 0, 2057, 4107, 6140, 8149, 10126, 12062, 13952, 15786, 17557, 120 19260, 20886, 22431, 23886, 25247, 26509, 27666, 28714, 29648, 30466, 121 31163, 31738, 32187, 32509, 32702, 32767, 32702, 32509, 32187, 31738, 122 31163, 30466, 29648, 28714, 27666, 26509, 25247, 23886, 22431, 20886, 123 19260, 17557, 15786, 13952, 12062, 10126, 8149, 6140, 4107, 2057, 124 0, -2057, -4107, -6140, -8149, -10126, -12062, -13952, -15786, -17557, 125 -19260, -20886, -22431, -23886, -25247, -26509, -27666, -28714, -29648, -30466, 126 -31163, -31738, -32187, -32509, -32702, -32767, -32702, -32509, -32187, -31738, 127 -31163, -30466, -29648, -28714, -27666, -26509, -25247, -23886, -22431, -20886, 128 -19260, -17557, -15786, -13952, -12062, -10126, -8149, -6140, -4107, -2057, 129 }; 130 131 static const int num_samples_sine_int16_44100 = sizeof(sine_int16_44100) / 2; 132 133 // input signal: pre-computed int16 sine wave, 48000 Hz at 441 Hz 134 static const int16_t sine_int16_48000[] = { 135 0, 1905, 3804, 5690, 7557, 9398, 11207, 12978, 14706, 16383, 136 18006, 19567, 21062, 22486, 23834, 25101, 26283, 27376, 28377, 29282, 137 30087, 30791, 31390, 31884, 32269, 32545, 32712, 32767, 32712, 32545, 138 32269, 31884, 31390, 30791, 30087, 29282, 28377, 27376, 26283, 25101, 139 23834, 22486, 21062, 19567, 18006, 16383, 14706, 12978, 11207, 9398, 140 7557, 5690, 3804, 1905, 0, -1905, -3804, -5690, -7557, -9398, 141 -11207, -12978, -14706, -16384, -18006, -19567, -21062, -22486, -23834, -25101, 142 -26283, -27376, -28377, -29282, -30087, -30791, -31390, -31884, -32269, -32545, 143 -32712, -32767, -32712, -32545, -32269, -31884, -31390, -30791, -30087, -29282, 144 -28377, -27376, -26283, -25101, -23834, -22486, -21062, -19567, -18006, -16384, 145 -14706, -12978, -11207, -9398, -7557, -5690, -3804, -1905, }; 146 147 static const int num_samples_sine_int16_48000 = sizeof(sine_int16_48000) / 2; 148 149 typedef struct { 150 int reconfigure; 151 int num_channels; 152 int sampling_frequency; 153 int channel_mode; 154 int block_length; 155 int subbands; 156 int allocation_method; 157 int min_bitpool_value; 158 int max_bitpool_value; 159 int frames_per_buffer; 160 } avdtp_media_codec_configuration_sbc_t; 161 162 static btstack_packet_callback_registration_t hci_event_callback_registration; 163 164 // pts: static const char * device_addr_string = "00:1B:DC:08:0A:A5"; 165 // pts: static const char * device_addr_string = "00:1B:DC:08:E2:72"; 166 // mac 2013: static const char * device_addr_string = "84:38:35:65:d1:15"; 167 // phone 2013: static const char * device_addr_string = "D8:BB:2C:DF:F0:F2"; 168 // Minijambox: 169 static const char * device_addr_string = "00:21:3C:AC:F7:38"; 170 // Philips SHB9100: static const char * device_addr_string = "00:22:37:05:FD:E8"; 171 // RT-B6: static const char * device_addr_string = "00:75:58:FF:C9:7D"; 172 // BT dongle: static const char * device_addr_string = "00:1A:7D:DA:71:0A"; 173 // Sony MDR-ZX330BT static const char * device_addr_string = "00:18:09:28:50:18"; 174 // Panda (BM6) static const char * device_addr_string = "4F:3F:66:52:8B:E0"; 175 // BeatsX: static const char * device_addr_string = "DC:D3:A2:89:57:FB"; 176 177 static bd_addr_t device_addr; 178 static uint8_t sdp_a2dp_source_service_buffer[150]; 179 static uint8_t sdp_avrcp_target_service_buffer[200]; 180 static uint8_t sdp_avrcp_controller_service_buffer[200]; 181 182 static avdtp_media_codec_configuration_sbc_t sbc_configuration; 183 static btstack_sbc_encoder_state_t sbc_encoder_state; 184 185 static uint8_t media_sbc_codec_configuration[4]; 186 static a2dp_media_sending_context_t media_tracker; 187 188 static stream_data_source_t data_source; 189 190 static int sine_phase; 191 static int sample_rate = 44100; 192 193 static int hxcmod_initialized; 194 static modcontext mod_context; 195 static tracker_buffer_state trkbuf; 196 197 static uint16_t avrcp_controller_cid = 0; 198 199 /* AVRCP Target context START */ 200 static const uint8_t subunit_info[] = { 201 0,0,0,0, 202 1,1,1,1, 203 2,2,2,2, 204 3,3,3,3, 205 4,4,4,4, 206 5,5,5,5, 207 6,6,6,6, 208 7,7,7,7 209 }; 210 211 static uint32_t company_id = 0x112233; 212 static uint8_t companies_num = 1; 213 static uint8_t companies[] = { 214 0x00, 0x19, 0x58 //BT SIG registered CompanyID 215 }; 216 217 static uint8_t events_num = 13; 218 static uint8_t events[] = { 219 AVRCP_NOTIFICATION_EVENT_PLAYBACK_STATUS_CHANGED, 220 AVRCP_NOTIFICATION_EVENT_TRACK_CHANGED, 221 AVRCP_NOTIFICATION_EVENT_TRACK_REACHED_END, 222 AVRCP_NOTIFICATION_EVENT_TRACK_REACHED_START, 223 AVRCP_NOTIFICATION_EVENT_PLAYBACK_POS_CHANGED, 224 AVRCP_NOTIFICATION_EVENT_BATT_STATUS_CHANGED, 225 AVRCP_NOTIFICATION_EVENT_SYSTEM_STATUS_CHANGED, 226 AVRCP_NOTIFICATION_EVENT_PLAYER_APPLICATION_SETTING_CHANGED, 227 AVRCP_NOTIFICATION_EVENT_NOW_PLAYING_CONTENT_CHANGED, 228 AVRCP_NOTIFICATION_EVENT_AVAILABLE_PLAYERS_CHANGED, 229 AVRCP_NOTIFICATION_EVENT_ADDRESSED_PLAYER_CHANGED, 230 AVRCP_NOTIFICATION_EVENT_UIDS_CHANGED, 231 AVRCP_NOTIFICATION_EVENT_VOLUME_CHANGED 232 }; 233 234 typedef struct { 235 uint8_t track_id[8]; 236 uint32_t song_length_ms; 237 avrcp_playback_status_t status; 238 uint32_t song_position_ms; // 0xFFFFFFFF if not supported 239 } avrcp_play_status_info_t; 240 241 // python -c "print('a'*512)" 242 static const char title[] = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; 243 244 avrcp_track_t tracks[] = { 245 {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, 1, "Sine", "Generated", "A2DP Source Demo", "monotone", 12345}, 246 {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02}, 2, "Nao-deceased", "Decease", "A2DP Source Demo", "vivid", 12345}, 247 {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03}, 3, (char *)title, "Decease", "A2DP Source Demo", "vivid", 12345}, 248 }; 249 int current_track_index; 250 avrcp_play_status_info_t play_info; 251 252 /* AVRCP Target context END */ 253 254 /* @section Main Application Setup 255 * 256 * @text The Listing MainConfiguration shows how to setup AD2P Source and AVRCP Target services. 257 */ 258 259 /* LISTING_START(MainConfiguration): Setup Audio Source and AVRCP Target services */ 260 static void a2dp_source_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t * event, uint16_t event_size); 261 static void avrcp_target_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size); 262 static void avrcp_controller_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size); 263 #ifdef HAVE_BTSTACK_STDIN 264 static void stdin_process(char cmd); 265 #endif 266 267 static void a2dp_demo_reconfigure_sample_rate(int new_sample_rate){ 268 if (!hxcmod_initialized){ 269 hxcmod_initialized = hxcmod_init(&mod_context); 270 if (!hxcmod_initialized) { 271 printf("could not initialize hxcmod\n"); 272 return; 273 } 274 } 275 sample_rate = new_sample_rate; 276 media_tracker.sbc_storage_count = 0; 277 media_tracker.samples_ready = 0; 278 hxcmod_unload(&mod_context); 279 hxcmod_setcfg(&mod_context, sample_rate, 16, 1, 1, 1); 280 hxcmod_load(&mod_context, (void *) &mod_data, mod_len); 281 } 282 283 static int a2dp_source_and_avrcp_services_init(void){ 284 285 // request role change on reconnecting headset to always use them in slave mode 286 hci_set_master_slave_policy(0); 287 288 l2cap_init(); 289 // Initialize A2DP Source. 290 a2dp_source_init(); 291 a2dp_source_register_packet_handler(&a2dp_source_packet_handler); 292 293 // Create stream endpoint. 294 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)); 295 if (!local_stream_endpoint){ 296 printf("A2DP Source: not enough memory to create local stream endpoint\n"); 297 return 1; 298 } 299 media_tracker.local_seid = avdtp_local_seid(local_stream_endpoint); 300 avdtp_source_register_delay_reporting_category(media_tracker.local_seid); 301 302 // Initialize AVRCP Target. 303 avrcp_target_init(); 304 avrcp_target_register_packet_handler(&avrcp_target_packet_handler); 305 // Initialize AVRCP Controller 306 avrcp_controller_init(); 307 avrcp_controller_register_packet_handler(&avrcp_controller_packet_handler); 308 309 // Initialize SDP, 310 sdp_init(); 311 312 // Create A2DP Source service record and register it with SDP. 313 memset(sdp_a2dp_source_service_buffer, 0, sizeof(sdp_a2dp_source_service_buffer)); 314 a2dp_source_create_sdp_record(sdp_a2dp_source_service_buffer, 0x10002, 1, NULL, NULL); 315 sdp_register_service(sdp_a2dp_source_service_buffer); 316 317 // Create AVRCP target service record and register it with SDP. 318 memset(sdp_avrcp_target_service_buffer, 0, sizeof(sdp_avrcp_target_service_buffer)); 319 uint16_t supported_features = (1 << AVRCP_TARGET_SUPPORTED_FEATURE_CATEGORY_PLAYER_OR_RECORDER); 320 #ifdef AVRCP_BROWSING_ENABLED 321 supported_features |= (1 << AVRCP_TARGET_SUPPORTED_FEATURE_BROWSING); 322 #endif 323 avrcp_target_create_sdp_record(sdp_avrcp_target_service_buffer, 0x10001, supported_features, NULL, NULL); 324 sdp_register_service(sdp_avrcp_target_service_buffer); 325 326 // setup AVRCP Controller 327 memset(sdp_avrcp_controller_service_buffer, 0, sizeof(sdp_avrcp_controller_service_buffer)); 328 uint16_t controller_supported_features = (1 << AVRCP_CONTROLLER_SUPPORTED_FEATURE_CATEGORY_MONITOR_OR_AMPLIFIER); 329 avrcp_controller_create_sdp_record(sdp_avrcp_controller_service_buffer, 0x10002, controller_supported_features, NULL, NULL); 330 sdp_register_service(sdp_avrcp_controller_service_buffer); 331 332 // Set local name with a template Bluetooth address, that will be automatically 333 // replaced with a actual address once it is available, i.e. when BTstack boots 334 // up and starts talking to a Bluetooth module. 335 gap_set_local_name("A2DP Source 00:00:00:00:00:00"); 336 gap_discoverable_control(1); 337 gap_set_class_of_device(0x200408); 338 339 // Register for HCI events. 340 hci_event_callback_registration.callback = &a2dp_source_packet_handler; 341 hci_add_event_handler(&hci_event_callback_registration); 342 343 a2dp_demo_reconfigure_sample_rate(sample_rate); 344 345 // Parse human readable Bluetooth address. 346 sscanf_bd_addr(device_addr_string, device_addr); 347 348 #ifdef HAVE_BTSTACK_STDIN 349 btstack_stdin_setup(stdin_process); 350 #endif 351 return 0; 352 } 353 /* LISTING_END */ 354 355 static void a2dp_demo_send_media_packet(void){ 356 int num_bytes_in_frame = btstack_sbc_encoder_sbc_buffer_length(); 357 int bytes_in_storage = media_tracker.sbc_storage_count; 358 uint8_t num_frames = bytes_in_storage / num_bytes_in_frame; 359 a2dp_source_stream_send_media_payload(media_tracker.a2dp_cid, media_tracker.local_seid, media_tracker.sbc_storage, bytes_in_storage, num_frames, 0); 360 media_tracker.sbc_storage_count = 0; 361 media_tracker.sbc_ready_to_send = 0; 362 } 363 364 static void produce_sine_audio(int16_t * pcm_buffer, int num_samples_to_write){ 365 int count; 366 for (count = 0; count < num_samples_to_write ; count++){ 367 switch (sample_rate){ 368 case 44100: 369 pcm_buffer[count * 2] = sine_int16_44100[sine_phase]; 370 pcm_buffer[count * 2 + 1] = sine_int16_44100[sine_phase]; 371 sine_phase++; 372 if (sine_phase >= num_samples_sine_int16_44100){ 373 sine_phase -= num_samples_sine_int16_44100; 374 } 375 break; 376 case 48000: 377 pcm_buffer[count * 2] = sine_int16_48000[sine_phase]; 378 pcm_buffer[count * 2 + 1] = sine_int16_48000[sine_phase]; 379 sine_phase++; 380 if (sine_phase >= num_samples_sine_int16_48000){ 381 sine_phase -= num_samples_sine_int16_48000; 382 } 383 break; 384 default: 385 break; 386 } 387 388 389 } 390 } 391 392 static void produce_mod_audio(int16_t * pcm_buffer, int num_samples_to_write){ 393 hxcmod_fillbuffer(&mod_context, (unsigned short *) &pcm_buffer[0], num_samples_to_write, &trkbuf); 394 } 395 396 static void produce_audio(int16_t * pcm_buffer, int num_samples){ 397 switch (data_source){ 398 case STREAM_SINE: 399 produce_sine_audio(pcm_buffer, num_samples); 400 break; 401 case STREAM_MOD: 402 produce_mod_audio(pcm_buffer, num_samples); 403 break; 404 default: 405 break; 406 } 407 #ifdef VOLUME_REDUCTION 408 int i; 409 for (i=0;i<num_samples*2;i++){ 410 if (pcm_buffer[i] > 0){ 411 pcm_buffer[i] = pcm_buffer[i] >> VOLUME_REDUCTION; 412 } else { 413 pcm_buffer[i] = -((-pcm_buffer[i]) >> VOLUME_REDUCTION); 414 } 415 } 416 #endif 417 } 418 419 static int a2dp_demo_fill_sbc_audio_buffer(a2dp_media_sending_context_t * context){ 420 // perform sbc encodin 421 int total_num_bytes_read = 0; 422 unsigned int num_audio_samples_per_sbc_buffer = btstack_sbc_encoder_num_audio_frames(); 423 while (context->samples_ready >= num_audio_samples_per_sbc_buffer 424 && (context->max_media_payload_size - context->sbc_storage_count) >= btstack_sbc_encoder_sbc_buffer_length()){ 425 426 int16_t pcm_frame[256*NUM_CHANNELS]; 427 428 produce_audio(pcm_frame, num_audio_samples_per_sbc_buffer); 429 btstack_sbc_encoder_process_data(pcm_frame); 430 431 uint16_t sbc_frame_size = btstack_sbc_encoder_sbc_buffer_length(); 432 uint8_t * sbc_frame = btstack_sbc_encoder_sbc_buffer(); 433 434 total_num_bytes_read += num_audio_samples_per_sbc_buffer; 435 memcpy(&context->sbc_storage[context->sbc_storage_count], sbc_frame, sbc_frame_size); 436 context->sbc_storage_count += sbc_frame_size; 437 context->samples_ready -= num_audio_samples_per_sbc_buffer; 438 } 439 return total_num_bytes_read; 440 } 441 442 static void a2dp_demo_audio_timeout_handler(btstack_timer_source_t * timer){ 443 a2dp_media_sending_context_t * context = (a2dp_media_sending_context_t *) btstack_run_loop_get_timer_context(timer); 444 btstack_run_loop_set_timer(&context->audio_timer, AUDIO_TIMEOUT_MS); 445 btstack_run_loop_add_timer(&context->audio_timer); 446 uint32_t now = btstack_run_loop_get_time_ms(); 447 448 uint32_t update_period_ms = AUDIO_TIMEOUT_MS; 449 if (context->time_audio_data_sent > 0){ 450 update_period_ms = now - context->time_audio_data_sent; 451 } 452 453 uint32_t num_samples = (update_period_ms * sample_rate) / 1000; 454 context->acc_num_missed_samples += (update_period_ms * sample_rate) % 1000; 455 456 while (context->acc_num_missed_samples >= 1000){ 457 num_samples++; 458 context->acc_num_missed_samples -= 1000; 459 } 460 context->time_audio_data_sent = now; 461 context->samples_ready += num_samples; 462 463 if (context->sbc_ready_to_send) return; 464 465 a2dp_demo_fill_sbc_audio_buffer(context); 466 467 if ((context->sbc_storage_count + btstack_sbc_encoder_sbc_buffer_length()) > context->max_media_payload_size){ 468 // schedule sending 469 context->sbc_ready_to_send = 1; 470 a2dp_source_stream_endpoint_request_can_send_now(context->a2dp_cid, context->local_seid); 471 } 472 } 473 474 static void a2dp_demo_timer_start(a2dp_media_sending_context_t * context){ 475 context->max_media_payload_size = btstack_min(a2dp_max_media_payload_size(context->a2dp_cid, context->local_seid), SBC_STORAGE_SIZE); 476 context->sbc_storage_count = 0; 477 context->sbc_ready_to_send = 0; 478 context->streaming = 1; 479 btstack_run_loop_remove_timer(&context->audio_timer); 480 btstack_run_loop_set_timer_handler(&context->audio_timer, a2dp_demo_audio_timeout_handler); 481 btstack_run_loop_set_timer_context(&context->audio_timer, context); 482 btstack_run_loop_set_timer(&context->audio_timer, AUDIO_TIMEOUT_MS); 483 btstack_run_loop_add_timer(&context->audio_timer); 484 } 485 486 static void a2dp_demo_timer_stop(a2dp_media_sending_context_t * context){ 487 context->time_audio_data_sent = 0; 488 context->acc_num_missed_samples = 0; 489 context->samples_ready = 0; 490 context->streaming = 1; 491 context->sbc_storage_count = 0; 492 context->sbc_ready_to_send = 0; 493 btstack_run_loop_remove_timer(&context->audio_timer); 494 } 495 496 static void dump_sbc_configuration(avdtp_media_codec_configuration_sbc_t * configuration){ 497 printf("Received media codec configuration:\n"); 498 printf(" - num_channels: %d\n", configuration->num_channels); 499 printf(" - sampling_frequency: %d\n", configuration->sampling_frequency); 500 printf(" - channel_mode: %d\n", configuration->channel_mode); 501 printf(" - block_length: %d\n", configuration->block_length); 502 printf(" - subbands: %d\n", configuration->subbands); 503 printf(" - allocation_method: %d\n", configuration->allocation_method); 504 printf(" - bitpool_value [%d, %d] \n", configuration->min_bitpool_value, configuration->max_bitpool_value); 505 } 506 507 static void a2dp_source_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ 508 UNUSED(channel); 509 UNUSED(size); 510 uint8_t status; 511 uint8_t local_seid; 512 bd_addr_t address; 513 uint16_t cid; 514 515 if (packet_type != HCI_EVENT_PACKET) return; 516 517 #ifndef HAVE_BTSTACK_STDIN 518 if (hci_event_packet_get_type(packet) == BTSTACK_EVENT_STATE){ 519 if (btstack_event_state_get_state(packet) != HCI_STATE_WORKING) return; 520 printf("Create A2DP Source connection to addr %s.\n", bd_addr_to_str(device_addr)); 521 status = a2dp_source_establish_stream(device_addr, media_tracker.local_seid, &media_tracker.a2dp_cid); 522 if (status != ERROR_CODE_SUCCESS){ 523 printf("Could not perform command, status 0x%2x\n", status); 524 } 525 return; 526 } 527 #endif 528 if (hci_event_packet_get_type(packet) == HCI_EVENT_PIN_CODE_REQUEST) { 529 printf("Pin code request - using '0000'\n"); 530 hci_event_pin_code_request_get_bd_addr(packet, address); 531 gap_pin_code_response(address, "0000"); 532 return; 533 } 534 535 if (hci_event_packet_get_type(packet) != HCI_EVENT_A2DP_META) return; 536 537 switch (hci_event_a2dp_meta_get_subevent_code(packet)){ 538 case A2DP_SUBEVENT_SIGNALING_CONNECTION_ESTABLISHED: 539 a2dp_subevent_signaling_connection_established_get_bd_addr(packet, address); 540 cid = a2dp_subevent_signaling_connection_established_get_a2dp_cid(packet); 541 status = a2dp_subevent_signaling_connection_established_get_status(packet); 542 543 if (status != ERROR_CODE_SUCCESS){ 544 printf("A2DP Source: Connection failed, status 0x%02x, cid 0x%02x, a2dp_cid 0x%02x \n", status, cid, media_tracker.a2dp_cid); 545 media_tracker.a2dp_cid = 0; 546 break; 547 } 548 media_tracker.a2dp_cid = cid; 549 printf("A2DP Source: Connected to address %s, a2dp cid 0x%02x, local seid %d.\n", bd_addr_to_str(address), media_tracker.a2dp_cid, media_tracker.local_seid); 550 break; 551 552 case A2DP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CONFIGURATION:{ 553 cid = avdtp_subevent_signaling_media_codec_sbc_configuration_get_avdtp_cid(packet); 554 if (cid != media_tracker.a2dp_cid) return; 555 media_tracker.remote_seid = a2dp_subevent_signaling_media_codec_sbc_configuration_get_acp_seid(packet); 556 557 sbc_configuration.reconfigure = a2dp_subevent_signaling_media_codec_sbc_configuration_get_reconfigure(packet); 558 sbc_configuration.num_channels = a2dp_subevent_signaling_media_codec_sbc_configuration_get_num_channels(packet); 559 sbc_configuration.sampling_frequency = a2dp_subevent_signaling_media_codec_sbc_configuration_get_sampling_frequency(packet); 560 sbc_configuration.channel_mode = a2dp_subevent_signaling_media_codec_sbc_configuration_get_channel_mode(packet); 561 sbc_configuration.block_length = a2dp_subevent_signaling_media_codec_sbc_configuration_get_block_length(packet); 562 sbc_configuration.subbands = a2dp_subevent_signaling_media_codec_sbc_configuration_get_subbands(packet); 563 sbc_configuration.allocation_method = a2dp_subevent_signaling_media_codec_sbc_configuration_get_allocation_method(packet); 564 sbc_configuration.min_bitpool_value = a2dp_subevent_signaling_media_codec_sbc_configuration_get_min_bitpool_value(packet); 565 sbc_configuration.max_bitpool_value = a2dp_subevent_signaling_media_codec_sbc_configuration_get_max_bitpool_value(packet); 566 sbc_configuration.frames_per_buffer = sbc_configuration.subbands * sbc_configuration.block_length; 567 printf("A2DP Source: Received SBC codec configuration, sampling frequency %u, a2dp_cid 0x%02x, local seid %d (expected %d), remote seid %d .\n", 568 sbc_configuration.sampling_frequency, cid, 569 a2dp_subevent_signaling_media_codec_sbc_configuration_get_int_seid(packet), 570 media_tracker.local_seid, 571 media_tracker.remote_seid); 572 573 // Adapt Bluetooth spec definition to SBC Encoder expected input 574 sbc_configuration.allocation_method -= 1; 575 sbc_configuration.num_channels = 2; 576 switch (sbc_configuration.channel_mode){ 577 case AVDTP_SBC_JOINT_STEREO: 578 sbc_configuration.channel_mode = 3; 579 break; 580 case AVDTP_SBC_STEREO: 581 sbc_configuration.channel_mode = 2; 582 break; 583 case AVDTP_SBC_DUAL_CHANNEL: 584 sbc_configuration.channel_mode = 1; 585 break; 586 case AVDTP_SBC_MONO: 587 sbc_configuration.channel_mode = 0; 588 sbc_configuration.num_channels = 1; 589 break; 590 } 591 dump_sbc_configuration(&sbc_configuration); 592 593 btstack_sbc_encoder_init(&sbc_encoder_state, SBC_MODE_STANDARD, 594 sbc_configuration.block_length, sbc_configuration.subbands, 595 sbc_configuration.allocation_method, sbc_configuration.sampling_frequency, 596 sbc_configuration.max_bitpool_value, 597 sbc_configuration.channel_mode); 598 break; 599 } 600 601 case A2DP_SUBEVENT_SIGNALING_DELAY_REPORTING_CAPABILITY: 602 printf("A2DP Source: remote supports delay report, remote seid %d\n", 603 avdtp_subevent_signaling_delay_reporting_capability_get_remote_seid(packet)); 604 break; 605 case A2DP_SUBEVENT_SIGNALING_CAPABILITIES_DONE: 606 printf("A2DP Source: All capabilities reported, remote seid %d\n", 607 avdtp_subevent_signaling_capabilities_done_get_remote_seid(packet)); 608 break; 609 610 case A2DP_SUBEVENT_SIGNALING_DELAY_REPORT: 611 printf("A2DP Source: Received delay report of %d.%0d ms, local seid %d\n", 612 avdtp_subevent_signaling_delay_report_get_delay_100us(packet)/10, avdtp_subevent_signaling_delay_report_get_delay_100us(packet)%10, 613 avdtp_subevent_signaling_delay_report_get_local_seid(packet)); 614 break; 615 616 case A2DP_SUBEVENT_STREAM_ESTABLISHED: 617 a2dp_subevent_stream_established_get_bd_addr(packet, address); 618 status = a2dp_subevent_stream_established_get_status(packet); 619 if (status){ 620 printf("A2DP Source: Stream failed, status 0x%02x.\n", status); 621 break; 622 } 623 624 local_seid = a2dp_subevent_stream_established_get_local_seid(packet); 625 cid = a2dp_subevent_stream_established_get_a2dp_cid(packet); 626 printf("A2DP_SUBEVENT_STREAM_ESTABLISHED: a2dp_cid [expected 0x%02x, received 0x%02x], local_seid %d (expected %d), remote_seid %d (expected %d)\n", 627 media_tracker.a2dp_cid, cid, 628 local_seid, media_tracker.local_seid, 629 a2dp_subevent_stream_established_get_remote_seid(packet), media_tracker.remote_seid); 630 631 if (local_seid != media_tracker.local_seid){ 632 printf("A2DP Source: Stream failed, wrong local seid %d, expected %d.\n", local_seid, media_tracker.local_seid); 633 break; 634 } 635 printf("A2DP Source: Stream established, address %s, a2dp cid 0x%02x, local seid %d, remote seid %d.\n", bd_addr_to_str(address), 636 media_tracker.a2dp_cid, media_tracker.local_seid, a2dp_subevent_stream_established_get_remote_seid(packet)); 637 media_tracker.stream_opened = 1; 638 data_source = STREAM_MOD; 639 status = a2dp_source_start_stream(media_tracker.a2dp_cid, media_tracker.local_seid); 640 break; 641 642 case A2DP_SUBEVENT_STREAM_RECONFIGURED: 643 status = a2dp_subevent_stream_reconfigured_get_status(packet); 644 local_seid = a2dp_subevent_stream_reconfigured_get_local_seid(packet); 645 cid = a2dp_subevent_stream_reconfigured_get_a2dp_cid(packet); 646 647 printf("A2DP Source: Reconfigured: a2dp_cid [expected 0x%02x, received 0x%02x], local_seid [expected %d, received %d]\n", media_tracker.a2dp_cid, cid, media_tracker.local_seid, local_seid); 648 printf("Status 0x%02x\n", status); 649 break; 650 651 case A2DP_SUBEVENT_STREAM_STARTED: 652 local_seid = a2dp_subevent_stream_started_get_local_seid(packet); 653 cid = a2dp_subevent_stream_started_get_a2dp_cid(packet); 654 655 play_info.status = AVRCP_PLAYBACK_STATUS_PLAYING; 656 if (media_tracker.avrcp_cid){ 657 avrcp_target_set_now_playing_info(media_tracker.avrcp_cid, &tracks[data_source], sizeof(tracks)/sizeof(avrcp_track_t)); 658 avrcp_target_set_playback_status(media_tracker.avrcp_cid, AVRCP_PLAYBACK_STATUS_PLAYING); 659 } 660 a2dp_demo_timer_start(&media_tracker); 661 printf("A2DP Source: Stream started: a2dp_cid [expected 0x%02x, received 0x%02x], local_seid [expected %d, received %d]\n", media_tracker.a2dp_cid, cid, media_tracker.local_seid, local_seid); 662 break; 663 664 case A2DP_SUBEVENT_STREAMING_CAN_SEND_MEDIA_PACKET_NOW: 665 local_seid = a2dp_subevent_streaming_can_send_media_packet_now_get_local_seid(packet); 666 cid = a2dp_subevent_signaling_media_codec_sbc_configuration_get_a2dp_cid(packet); 667 // printf("A2DP Source: can send media packet: a2dp_cid [expected 0x%02x, received 0x%02x], local_seid [expected %d, received %d]\n", media_tracker.a2dp_cid, cid, media_tracker.local_seid, local_seid); 668 a2dp_demo_send_media_packet(); 669 break; 670 671 case A2DP_SUBEVENT_STREAM_SUSPENDED: 672 local_seid = a2dp_subevent_stream_suspended_get_local_seid(packet); 673 cid = a2dp_subevent_stream_suspended_get_a2dp_cid(packet); 674 675 play_info.status = AVRCP_PLAYBACK_STATUS_PAUSED; 676 if (media_tracker.avrcp_cid){ 677 avrcp_target_set_playback_status(media_tracker.avrcp_cid, AVRCP_PLAYBACK_STATUS_PAUSED); 678 } 679 printf("A2DP Source: Stream paused: a2dp_cid [expected 0x%02x, received 0x%02x], local_seid [expected %d, received %d]\n", media_tracker.a2dp_cid, cid, media_tracker.local_seid, local_seid); 680 681 a2dp_demo_timer_stop(&media_tracker); 682 break; 683 684 case A2DP_SUBEVENT_STREAM_RELEASED: 685 play_info.status = AVRCP_PLAYBACK_STATUS_STOPPED; 686 cid = a2dp_subevent_stream_released_get_a2dp_cid(packet); 687 local_seid = a2dp_subevent_stream_released_get_local_seid(packet); 688 689 printf("A2DP Source: Stream released: a2dp_cid [expected 0x%02x, received 0x%02x], local_seid [expected %d, received %d]\n", media_tracker.a2dp_cid, cid, media_tracker.local_seid, local_seid); 690 691 if (cid == media_tracker.a2dp_cid) { 692 media_tracker.stream_opened = 0; 693 printf("A2DP Source: Stream released.\n"); 694 } 695 if (media_tracker.avrcp_cid){ 696 avrcp_target_set_now_playing_info(media_tracker.avrcp_cid, NULL, sizeof(tracks)/sizeof(avrcp_track_t)); 697 avrcp_target_set_playback_status(media_tracker.avrcp_cid, AVRCP_PLAYBACK_STATUS_STOPPED); 698 } 699 700 a2dp_demo_timer_stop(&media_tracker); 701 break; 702 case A2DP_SUBEVENT_SIGNALING_CONNECTION_RELEASED: 703 cid = a2dp_subevent_signaling_connection_released_get_a2dp_cid(packet); 704 if (cid == media_tracker.a2dp_cid) { 705 media_tracker.avrcp_cid = 0; 706 media_tracker.a2dp_cid = 0; 707 printf("A2DP Source: Signaling released.\n\n"); 708 } 709 break; 710 default: 711 break; 712 } 713 } 714 715 static void avrcp_target_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ 716 UNUSED(channel); 717 UNUSED(size); 718 bd_addr_t event_addr; 719 uint16_t local_cid; 720 uint8_t status = ERROR_CODE_SUCCESS; 721 722 if (packet_type != HCI_EVENT_PACKET) return; 723 if (hci_event_packet_get_type(packet) != HCI_EVENT_AVRCP_META) return; 724 725 switch (packet[2]){ 726 case AVRCP_SUBEVENT_CONNECTION_ESTABLISHED: { 727 local_cid = avrcp_subevent_connection_established_get_avrcp_cid(packet); 728 // if (avrcp_cid != 0 && avrcp_cid != local_cid) { 729 // printf("AVRCP Target: Connection failed, expected 0x%02X l2cap cid, received 0x%02X\n", avrcp_cid, local_cid); 730 // return; 731 // } 732 // if (avrcp_cid != local_cid) break; 733 734 status = avrcp_subevent_connection_established_get_status(packet); 735 if (status != ERROR_CODE_SUCCESS){ 736 printf("AVRCP Target: Connection failed, status 0x%02x\n", status); 737 return; 738 } 739 media_tracker.avrcp_cid = local_cid; 740 avrcp_subevent_connection_established_get_bd_addr(packet, event_addr); 741 printf("AVRCP Target: Connected to %s, avrcp_cid 0x%02x\n", bd_addr_to_str(event_addr), local_cid); 742 743 avrcp_target_set_now_playing_info(media_tracker.avrcp_cid, NULL, sizeof(tracks)/sizeof(avrcp_track_t)); 744 avrcp_target_set_unit_info(media_tracker.avrcp_cid, AVRCP_SUBUNIT_TYPE_AUDIO, company_id); 745 avrcp_target_set_subunit_info(media_tracker.avrcp_cid, AVRCP_SUBUNIT_TYPE_AUDIO, (uint8_t *)subunit_info, sizeof(subunit_info)); 746 return; 747 } 748 case AVRCP_SUBEVENT_NOTIFICATION_VOLUME_CHANGED: 749 printf("AVRCP Target: new volume %d\n", avrcp_subevent_notification_volume_changed_get_absolute_volume(packet)); 750 break; 751 case AVRCP_SUBEVENT_EVENT_IDS_QUERY: 752 status = avrcp_target_supported_events(media_tracker.avrcp_cid, events_num, events, sizeof(events)); 753 break; 754 case AVRCP_SUBEVENT_COMPANY_IDS_QUERY: 755 status = avrcp_target_supported_companies(media_tracker.avrcp_cid, companies_num, companies, sizeof(companies)); 756 break; 757 case AVRCP_SUBEVENT_PLAY_STATUS_QUERY: 758 status = avrcp_target_play_status(media_tracker.avrcp_cid, play_info.song_length_ms, play_info.song_position_ms, play_info.status); 759 break; 760 // case AVRCP_SUBEVENT_NOW_PLAYING_INFO_QUERY: 761 // status = avrcp_target_now_playing_info(avrcp_cid); 762 // break; 763 case AVRCP_SUBEVENT_OPERATION:{ 764 avrcp_operation_id_t operation_id = avrcp_subevent_operation_get_operation_id(packet); 765 switch (operation_id){ 766 case AVRCP_OPERATION_ID_PLAY: 767 printf("AVRCP Target: PLAY\n"); 768 status = a2dp_source_start_stream(media_tracker.a2dp_cid, media_tracker.local_seid); 769 break; 770 case AVRCP_OPERATION_ID_PAUSE: 771 printf("AVRCP Target: PAUSE\n"); 772 status = a2dp_source_pause_stream(media_tracker.a2dp_cid, media_tracker.local_seid); 773 break; 774 case AVRCP_OPERATION_ID_STOP: 775 printf("AVRCP Target: STOP\n"); 776 status = a2dp_source_disconnect(media_tracker.a2dp_cid); 777 break; 778 default: 779 printf("AVRCP Target: operation 0x%2x is not handled\n", operation_id); 780 return; 781 } 782 break; 783 } 784 case AVRCP_SUBEVENT_CONNECTION_RELEASED: 785 printf("AVRCP Target: Disconnected, avrcp_cid 0x%02x\n", avrcp_subevent_connection_released_get_avrcp_cid(packet)); 786 media_tracker.avrcp_cid = 0; 787 return; 788 default: 789 break; 790 } 791 792 if (status != ERROR_CODE_SUCCESS){ 793 printf("Responding to event 0x%02x failed with status 0x%02x\n", packet[2], status); 794 } 795 } 796 797 static void avrcp_controller_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ 798 UNUSED(channel); 799 UNUSED(size); 800 uint16_t local_cid; 801 uint8_t status = 0xFF; 802 bd_addr_t adress; 803 804 if (packet_type != HCI_EVENT_PACKET) return; 805 if (hci_event_packet_get_type(packet) != HCI_EVENT_AVRCP_META) return; 806 switch (packet[2]){ 807 case AVRCP_SUBEVENT_CONNECTION_ESTABLISHED: { 808 local_cid = avrcp_subevent_connection_established_get_avrcp_cid(packet); 809 if (avrcp_controller_cid != 0 && avrcp_controller_cid != local_cid) { 810 printf("AVRCP Controller: Connection failed, expected 0x%02X l2cap cid, received 0x%02X\n", avrcp_controller_cid, local_cid); 811 return; 812 } 813 814 status = avrcp_subevent_connection_established_get_status(packet); 815 if (status != ERROR_CODE_SUCCESS){ 816 printf("AVRCP Controller: Connection failed: status 0x%02x\n", status); 817 avrcp_controller_cid = 0; 818 return; 819 } 820 821 avrcp_controller_cid = local_cid; 822 avrcp_subevent_connection_established_get_bd_addr(packet, adress); 823 printf("AVRCP Controller: Channel successfully opened: %s, avrcp_controller_cid 0x%02x\n", bd_addr_to_str(adress), avrcp_controller_cid); 824 825 // automatically enable notifications 826 avrcp_controller_enable_notification(avrcp_controller_cid, AVRCP_NOTIFICATION_EVENT_VOLUME_CHANGED); 827 return; 828 } 829 case AVRCP_SUBEVENT_CONNECTION_RELEASED: 830 printf("AVRCP Controller: Channel released: avrcp_controller_cid 0x%02x\n", avrcp_subevent_connection_released_get_avrcp_cid(packet)); 831 avrcp_controller_cid = 0; 832 return; 833 default: 834 break; 835 } 836 837 status = packet[5]; 838 if (!avrcp_controller_cid) return; 839 840 // ignore INTERIM status 841 if (status == AVRCP_CTYPE_RESPONSE_INTERIM) return; 842 843 switch (packet[2]){ 844 case AVRCP_SUBEVENT_NOTIFICATION_VOLUME_CHANGED:{ 845 int volume_percentage = avrcp_subevent_notification_volume_changed_get_absolute_volume(packet) * 100 / 127; 846 printf("AVRCP Controller: notification absolute volume changed %d %%\n", volume_percentage); 847 return; 848 } 849 default: 850 break; 851 } 852 } 853 854 #ifdef HAVE_BTSTACK_STDIN 855 static void show_usage(void){ 856 bd_addr_t iut_address; 857 gap_local_bd_addr(iut_address); 858 printf("\n--- Bluetooth A2DP Source/AVRCP Target Demo %s ---\n", bd_addr_to_str(iut_address)); 859 printf("b - A2DP Source create connection to addr %s\n", device_addr_string); 860 printf("B - A2DP Source disconnect\n"); 861 printf("c - AVRCP Target create connection to addr %s\n", device_addr_string); 862 printf("C - AVRCP Target disconnect\n"); 863 864 printf("x - start streaming sine\n"); 865 if (hxcmod_initialized){ 866 printf("z - start streaming '%s'\n", mod_name); 867 } 868 printf("p - pause streaming\n"); 869 printf("w - reconfigure stream for 44100 Hz\n"); 870 printf("e - reconfigure stream for 48000 Hz\n"); 871 printf("t - volume up\n"); 872 printf("T - volume down\n"); 873 printf("v - absolute volume of 50 percent\n"); 874 875 printf("\n--- Bluetooth AVRCP Target Commands %s ---\n", bd_addr_to_str(iut_address)); 876 printf("---\n"); 877 } 878 879 static void stdin_process(char cmd){ 880 uint8_t status = ERROR_CODE_SUCCESS; 881 switch (cmd){ 882 case 'b': 883 status = a2dp_source_establish_stream(device_addr, media_tracker.local_seid, &media_tracker.a2dp_cid); 884 printf("%c - Create A2DP Source connection to addr %s, cid 0x%02x.\n", cmd, bd_addr_to_str(device_addr), media_tracker.a2dp_cid); 885 break; 886 case 'B': 887 printf("%c - A2DP Source Disconnect from cid 0x%2x\n", cmd, media_tracker.a2dp_cid); 888 status = a2dp_source_disconnect(media_tracker.a2dp_cid); 889 break; 890 case 'c': 891 printf("%c - Create AVRCP Target connection to addr %s.\n", cmd, bd_addr_to_str(device_addr)); 892 status = avrcp_target_connect(device_addr, &media_tracker.avrcp_cid); 893 break; 894 case 'C': 895 printf("%c - AVRCP Target disconnect\n", cmd); 896 status = avrcp_target_disconnect(media_tracker.avrcp_cid); 897 break; 898 899 case '\n': 900 case '\r': 901 break; 902 903 case 't': 904 printf(" - volume up\n"); 905 status = avrcp_controller_volume_up(avrcp_controller_cid); 906 break; 907 case 'T': 908 printf(" - volume down\n"); 909 status = avrcp_controller_volume_down(avrcp_controller_cid); 910 break; 911 case 'v': 912 printf(" - absolute volume of 50%% (64)\n"); 913 status = avrcp_controller_set_absolute_volume(avrcp_controller_cid, 64); 914 break; 915 916 case 'x': 917 if (media_tracker.avrcp_cid){ 918 avrcp_target_set_now_playing_info(media_tracker.avrcp_cid, &tracks[data_source], sizeof(tracks)/sizeof(avrcp_track_t)); 919 } 920 printf("%c - Play sine.\n", cmd); 921 data_source = STREAM_SINE; 922 if (!media_tracker.stream_opened) break; 923 status = a2dp_source_start_stream(media_tracker.a2dp_cid, media_tracker.local_seid); 924 break; 925 case 'z': 926 if (media_tracker.avrcp_cid){ 927 avrcp_target_set_now_playing_info(media_tracker.avrcp_cid, &tracks[data_source], sizeof(tracks)/sizeof(avrcp_track_t)); 928 } 929 printf("%c - Play mod.\n", cmd); 930 data_source = STREAM_MOD; 931 if (!media_tracker.stream_opened) break; 932 status = a2dp_source_start_stream(media_tracker.a2dp_cid, media_tracker.local_seid); 933 if (status == ERROR_CODE_SUCCESS){ 934 a2dp_demo_reconfigure_sample_rate(sample_rate); 935 } 936 break; 937 938 case 'p': 939 if (!media_tracker.stream_opened) break; 940 printf("%c - Pause stream.\n", cmd); 941 status = a2dp_source_pause_stream(media_tracker.a2dp_cid, media_tracker.local_seid); 942 break; 943 944 case 'w': 945 if (!media_tracker.stream_opened) break; 946 if (play_info.status == AVRCP_PLAYBACK_STATUS_PLAYING){ 947 printf("Stream cannot be reconfigured while playing, please pause stream first\n"); 948 break; 949 } 950 printf("%c - Reconfigure for %d Hz.\n", cmd, sample_rate); 951 status = a2dp_source_reconfigure_stream_sampling_frequency(media_tracker.a2dp_cid, 44100); 952 if (status == ERROR_CODE_SUCCESS){ 953 a2dp_demo_reconfigure_sample_rate(44100); 954 } 955 break; 956 957 case 'e': 958 if (!media_tracker.stream_opened) break; 959 if (play_info.status == AVRCP_PLAYBACK_STATUS_PLAYING){ 960 printf("Stream cannot be reconfigured while playing, please pause stream first\n"); 961 break; 962 } 963 printf("%c - Reconfigure for %d Hz.\n", cmd, sample_rate); 964 status = a2dp_source_reconfigure_stream_sampling_frequency(media_tracker.a2dp_cid, 48000); 965 if (status == ERROR_CODE_SUCCESS){ 966 a2dp_demo_reconfigure_sample_rate(48000); 967 } 968 break; 969 970 default: 971 show_usage(); 972 return; 973 } 974 if (status != ERROR_CODE_SUCCESS){ 975 printf("Could not perform command \'%c\', status 0x%2x\n", cmd, status); 976 } 977 } 978 #endif 979 980 981 int btstack_main(int argc, const char * argv[]); 982 int btstack_main(int argc, const char * argv[]){ 983 (void)argc; 984 (void)argv; 985 986 int err = a2dp_source_and_avrcp_services_init(); 987 if (err) return err; 988 // turn on! 989 hci_power_control(HCI_POWER_ON); 990 return 0; 991 } 992 /* EXAMPLE_END */ 993