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_sink_demo.c" 39 40 /* 41 * a2dp_sink_demo.c 42 */ 43 44 // ***************************************************************************** 45 /* EXAMPLE_START(a2dp_sink_demo): Receive audio stream and control its playback. 46 * 47 * @text This A2DP Sink example demonstrates how to use the A2DP Sink service to 48 * receive an audio data stream from a remote A2DP Source device. In addition, 49 * the AVRCP Controller is used to get information on currently played media, 50 * such are title, artist and album, as well as to control the playback, 51 * i.e. to play, stop, repeat, etc. 52 * 53 * @test To test with a remote device, e.g. a mobile phone, 54 * pair from the remote device with the demo, then start playing music on the remote device. 55 * Alternatively, set the device_addr_string to the Bluetooth address of your 56 * remote device in the code, and call connect from the UI. 57 * 58 * @test To controll the playback, tap SPACE on the console to show the available 59 * AVRCP commands. 60 */ 61 // ***************************************************************************** 62 63 #include <stdint.h> 64 #include <stdio.h> 65 #include <stdlib.h> 66 #include <string.h> 67 68 #include "btstack.h" 69 #include "classic/btstack_sbc.h" 70 71 #define AVRCP_BROWSING_ENABLED 0 72 73 #ifdef HAVE_BTSTACK_STDIN 74 #include "btstack_stdin.h" 75 #endif 76 77 #ifdef HAVE_AUDIO_DMA 78 #include "btstack_ring_buffer.h" 79 #include "hal_audio_dma.h" 80 #endif 81 82 #ifdef HAVE_PORTAUDIO 83 #include "btstack_ring_buffer.h" 84 #include <portaudio.h> 85 #endif 86 87 #ifdef HAVE_POSIX_FILE_IO 88 #include "wav_util.h" 89 #define STORE_SBC_TO_SBC_FILE 90 #define STORE_SBC_TO_WAV_FILE 91 #endif 92 93 #if defined(HAVE_PORTAUDIO) || defined(STORE_SBC_TO_WAV_FILE) || defined(HAVE_AUDIO_DMA) 94 #define DECODE_SBC 95 #endif 96 97 #define NUM_CHANNELS 2 98 #define BYTES_PER_FRAME (2*NUM_CHANNELS) 99 #define MAX_SBC_FRAME_SIZE 120 100 101 // SBC Decoder for WAV file or PortAudio 102 #ifdef DECODE_SBC 103 static btstack_sbc_decoder_state_t state; 104 static btstack_sbc_mode_t mode = SBC_MODE_STANDARD; 105 #endif 106 107 #if defined(HAVE_PORTAUDIO) || defined (HAVE_AUDIO_DMA) 108 #define PREBUFFER_MS 200 109 static int audio_stream_started = 0; 110 static int audio_stream_paused = 0; 111 static btstack_ring_buffer_t ring_buffer; 112 #endif 113 114 #ifdef HAVE_AUDIO_DMA 115 // below 30: add samples, 30-40: fine, above 40: drop samples 116 #define OPTIMAL_FRAMES_MIN 30 117 #define OPTIMAL_FRAMES_MAX 40 118 #define ADDITIONAL_FRAMES 10 119 #define DMA_AUDIO_FRAMES 128 120 #define DMA_MAX_FILL_FRAMES 1 121 #define NUM_AUDIO_BUFFERS 2 122 123 static uint16_t audio_samples[(DMA_AUDIO_FRAMES + DMA_MAX_FILL_FRAMES)*2*NUM_AUDIO_BUFFERS]; 124 static uint16_t audio_samples_len[NUM_AUDIO_BUFFERS]; 125 static uint8_t ring_buffer_storage[(OPTIMAL_FRAMES_MAX + ADDITIONAL_FRAMES) * MAX_SBC_FRAME_SIZE]; 126 static const uint16_t silent_buffer[DMA_AUDIO_FRAMES*2]; 127 static volatile int playback_buffer; 128 static int write_buffer; 129 static uint8_t sbc_frame_size; 130 static int sbc_samples_fix; 131 #endif 132 133 // PortAdudio - live playback 134 #ifdef HAVE_PORTAUDIO 135 #define PA_SAMPLE_TYPE paInt16 136 #define SAMPLE_RATE 48000 137 #define FRAMES_PER_BUFFER 128 138 #define PREBUFFER_BYTES (PREBUFFER_MS*SAMPLE_RATE/1000*BYTES_PER_FRAME) 139 static PaStream * stream; 140 static uint8_t ring_buffer_storage[2*PREBUFFER_BYTES]; 141 #endif 142 143 // WAV File 144 #ifdef STORE_SBC_TO_WAV_FILE 145 static int frame_count = 0; 146 static char * wav_filename = "avdtp_sink.wav"; 147 #endif 148 149 #ifdef STORE_SBC_TO_SBC_FILE 150 static FILE * sbc_file; 151 static char * sbc_filename = "avdtp_sink.sbc"; 152 #endif 153 154 typedef struct { 155 // bitmaps 156 uint8_t sampling_frequency_bitmap; 157 uint8_t channel_mode_bitmap; 158 uint8_t block_length_bitmap; 159 uint8_t subbands_bitmap; 160 uint8_t allocation_method_bitmap; 161 uint8_t min_bitpool_value; 162 uint8_t max_bitpool_value; 163 } adtvp_media_codec_information_sbc_t; 164 165 typedef struct { 166 int reconfigure; 167 int num_channels; 168 int sampling_frequency; 169 int channel_mode; 170 int block_length; 171 int subbands; 172 int allocation_method; 173 int min_bitpool_value; 174 int max_bitpool_value; 175 int frames_per_buffer; 176 } avdtp_media_codec_configuration_sbc_t; 177 178 #ifdef HAVE_BTSTACK_STDIN 179 // mac 2011: static bd_addr_t remote = {0x04, 0x0C, 0xCE, 0xE4, 0x85, 0xD3}; 180 // pts: static bd_addr_t remote = {0x00, 0x1B, 0xDC, 0x08, 0x0A, 0xA5}; 181 // mac 2013: 182 // mac 2013: static const char * device_addr_string = "84:38:35:65:d1:15"; 183 // iPhone 5S: static const char * device_addr_string = "54:E4:3A:26:A2:39"; 184 // BT dongle: 185 static const char * device_addr_string = "00:02:72:DC:31:C1"; 186 #endif 187 188 // bt dongle: -u 02-02 static bd_addr_t remote = {0x00, 0x02, 0x72, 0xDC, 0x31, 0xC1}; 189 190 static uint8_t sdp_avdtp_sink_service_buffer[150]; 191 static avdtp_media_codec_configuration_sbc_t sbc_configuration; 192 static uint16_t a2dp_cid = 0; 193 static uint8_t local_seid = 0; 194 static uint8_t value[100]; 195 196 static btstack_packet_callback_registration_t hci_event_callback_registration; 197 198 static int media_initialized = 0; 199 200 #ifdef HAVE_BTSTACK_STDIN 201 static bd_addr_t device_addr; 202 #endif 203 204 static uint16_t a2dp_sink_connected = 0; 205 static uint16_t avrcp_cid = 0; 206 static uint8_t avrcp_connected = 0; 207 static uint8_t sdp_avrcp_controller_service_buffer[200]; 208 209 static uint8_t media_sbc_codec_capabilities[] = { 210 0xFF,//(AVDTP_SBC_44100 << 4) | AVDTP_SBC_STEREO, 211 0xFF,//(AVDTP_SBC_BLOCK_LENGTH_16 << 4) | (AVDTP_SBC_SUBBANDS_8 << 2) | AVDTP_SBC_ALLOCATION_METHOD_LOUDNESS, 212 2, 53 213 }; 214 215 static uint8_t media_sbc_codec_configuration[] = { 216 (AVDTP_SBC_44100 << 4) | AVDTP_SBC_STEREO, 217 (AVDTP_SBC_BLOCK_LENGTH_16 << 4) | (AVDTP_SBC_SUBBANDS_8 << 2) | AVDTP_SBC_ALLOCATION_METHOD_LOUDNESS, 218 2, 53 219 }; 220 221 222 /* @section Main Application Setup 223 * 224 * @text The Listing MainConfiguration shows how to setup AD2P Sink and AVRCP controller services. 225 * To announce A2DP Sink and AVRCP Controller services, you need to create corresponding 226 * SDP records and register them with the SDP service. 227 * You'll also need to register several packet handlers: 228 * - a2dp_sink_packet_handler - handles events on stream connection status (established, released), the media codec configuration, and, the status of the stream itself (opened, paused, stopped). 229 * - handle_l2cap_media_data_packet - used to receive streaming data. If HAVE_PORTAUDIO or STORE_SBC_TO_WAV_FILE directives (check btstack_config.h) are used, the SBC decoder will be used to decode the SBC data into PCM frames. The resulting PCM frames are then processed in the SBC Decoder callback. 230 * - stdin_process callback - used to trigger AVRCP commands to the A2DP Source device, such are get now playing info, start, stop, volume control. Requires HAVE_BTSTACK_STDIN. 231 * - avrcp_controller_packet_handler - used to receive answers for AVRCP commands, 232 * 233 * @text Note, currently only the SBC codec is supported. 234 * If you want to store the audio data in a file, you'll need to define STORE_SBC_TO_WAV_FILE. The HAVE_PORTAUDIO directive indicates if the audio is played back via PortAudio. 235 * If HAVE_PORTAUDIO or STORE_SBC_TO_WAV_FILE directives is defined, the SBC decoder needs to get initialized when a2dp_sink_packet_handler receives event A2DP_SUBEVENT_STREAM_STARTED. 236 * The initialization of the SBC decoder requires a callback that handles PCM data: 237 * - handle_pcm_data - handles PCM audio frames. Here, they are stored a in wav file if STORE_SBC_TO_WAV_FILE is defined, and/or played using the PortAudio library if HAVE_PORTAUDIO is defined. 238 */ 239 240 /* LISTING_START(MainConfiguration): Setup Audio Sink and AVRCP Controller services */ 241 static void a2dp_sink_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t * event, uint16_t event_size); 242 static void avrcp_controller_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size); 243 static void handle_l2cap_media_data_packet(uint8_t seid, uint8_t *packet, uint16_t size); 244 #ifdef HAVE_BTSTACK_STDIN 245 static void stdin_process(char cmd); 246 #endif 247 #if defined(HAVE_PORTAUDIO) || defined(STORE_SBC_TO_WAV_FILE) 248 static void handle_pcm_data(int16_t * data, int num_samples, int num_channels, int sample_rate, void * context); 249 #endif 250 251 static int a2dp_sink_and_avrcp_services_init(void){ 252 // Register for HCI events. 253 hci_event_callback_registration.callback = &a2dp_sink_packet_handler; 254 hci_add_event_handler(&hci_event_callback_registration); 255 256 // Initialize L2CAP. 257 l2cap_init(); 258 259 // Initialize A2DP Sink. 260 a2dp_sink_init(); 261 // Register A2DP Sink for HCI events. 262 a2dp_sink_register_packet_handler(&a2dp_sink_packet_handler); 263 // Register A2DP Sink for receiving media data. 264 a2dp_sink_register_media_handler(&handle_l2cap_media_data_packet); 265 // Create a stream endpoint to which the streaming channel will be opened. 266 uint8_t status = a2dp_sink_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), &local_seid); 267 if (status != ERROR_CODE_SUCCESS){ 268 printf("A2DP Sink: not enough memory to create local stream endpoint\n"); 269 return 1; 270 } 271 272 // Initialize AVRCP Controller. 273 avrcp_controller_init(); 274 // Register AVRCP for HCI events. 275 avrcp_controller_register_packet_handler(&avrcp_controller_packet_handler); 276 277 // Initialize SDP. 278 sdp_init(); 279 280 // Create A2DP sink service record and register it with SDP. 281 memset(sdp_avdtp_sink_service_buffer, 0, sizeof(sdp_avdtp_sink_service_buffer)); 282 a2dp_sink_create_sdp_record(sdp_avdtp_sink_service_buffer, 0x10001, 1, NULL, NULL); 283 sdp_register_service(sdp_avdtp_sink_service_buffer); 284 285 // Create AVRCP service record and register it with SDP. 286 memset(sdp_avrcp_controller_service_buffer, 0, sizeof(sdp_avrcp_controller_service_buffer)); 287 avrcp_controller_create_sdp_record(sdp_avrcp_controller_service_buffer, 0x10001, AVRCP_BROWSING_ENABLED, 1, NULL, NULL); 288 sdp_register_service(sdp_avrcp_controller_service_buffer); 289 290 // Set local name with a template Bluetooth address, that will be automatically 291 // replaced with a actual address once it is available, i.e. when BTstack boots 292 // up and starts talking to a Bluetooth module. 293 gap_set_local_name("A2DP Sink Demo 00:00:00:00:00:00"); 294 gap_discoverable_control(1); 295 gap_set_class_of_device(0x200408); 296 297 #ifdef HAVE_AUDIO_DMA 298 static btstack_data_source_t hal_audio_dma_data_source; 299 // Set up polling data source. 300 btstack_run_loop_set_data_source_handler(&hal_audio_dma_data_source, &hal_audio_dma_process); 301 btstack_run_loop_enable_data_source_callbacks(&hal_audio_dma_data_source, DATA_SOURCE_CALLBACK_POLL); 302 btstack_run_loop_add_data_source(&hal_audio_dma_data_source); 303 #endif 304 305 #ifdef HAVE_BTSTACK_STDIN 306 // Parse human readable Bluetooth address. 307 sscanf_bd_addr(device_addr_string, device_addr); 308 btstack_stdin_setup(stdin_process); 309 #endif 310 return 0; 311 } 312 /* LISTING_END */ 313 314 #ifdef HAVE_PORTAUDIO 315 static int portaudio_callback( const void *inputBuffer, void *outputBuffer, 316 unsigned long framesPerBuffer, 317 const PaStreamCallbackTimeInfo* timeInfo, 318 PaStreamCallbackFlags statusFlags, 319 void *userData ) { 320 321 /** portaudio_callback is called from different thread, don't use hci_dump / log_info here without additional checks */ 322 323 // Prevent unused variable warnings. 324 (void) timeInfo; 325 (void) statusFlags; 326 (void) inputBuffer; 327 (void) userData; 328 329 int bytes_to_copy = framesPerBuffer * BYTES_PER_FRAME; 330 331 // fill ring buffer with silence while stream is paused 332 if (audio_stream_paused){ 333 if (btstack_ring_buffer_bytes_available(&ring_buffer) < PREBUFFER_BYTES){ 334 memset(outputBuffer, 0, bytes_to_copy); 335 return 0; 336 } else { 337 // resume playback 338 audio_stream_paused = 0; 339 } 340 } 341 342 // get data from ring buffer 343 uint32_t bytes_read = 0; 344 btstack_ring_buffer_read(&ring_buffer, outputBuffer, bytes_to_copy, &bytes_read); 345 bytes_to_copy -= bytes_read; 346 347 // fill ring buffer with silence if there are not enough bytes to copy 348 if (bytes_to_copy){ 349 memset(outputBuffer + bytes_read, 0, bytes_to_copy); 350 audio_stream_paused = 1; 351 } 352 return 0; 353 } 354 #endif 355 356 #ifdef HAVE_AUDIO_DMA 357 static int next_buffer(int current){ 358 if (current == NUM_AUDIO_BUFFERS-1) return 0; 359 return current + 1; 360 } 361 static uint8_t * start_of_buffer(int num){ 362 return (uint8_t *) &audio_samples[num * DMA_AUDIO_FRAMES * 2]; 363 } 364 void hal_audio_dma_done(void){ 365 if (audio_stream_paused){ 366 hal_audio_dma_play((const uint8_t *) silent_buffer, DMA_AUDIO_FRAMES*4); 367 return; 368 } 369 // next buffer 370 int next_playback_buffer = next_buffer(playback_buffer); 371 uint8_t * playback_data; 372 if (next_playback_buffer == write_buffer){ 373 374 // TODO: stop codec while playing silence when getting 'stream paused' 375 376 // start playing silence 377 audio_stream_paused = 1; 378 hal_audio_dma_play((const uint8_t *) silent_buffer, DMA_AUDIO_FRAMES*4); 379 printf("%6u - paused - bytes in buffer %u\n", (int) btstack_run_loop_get_time_ms(), btstack_ring_buffer_bytes_available(&ring_buffer)); 380 return; 381 } 382 playback_buffer = next_playback_buffer; 383 playback_data = start_of_buffer(playback_buffer); 384 hal_audio_dma_play(playback_data, audio_samples_len[playback_buffer]); 385 // btstack_run_loop_embedded_trigger(); 386 } 387 #endif 388 389 390 #ifdef HAVE_AUDIO_DMA 391 static void hal_audio_dma_process(btstack_data_source_t * ds, btstack_data_source_callback_type_t callback_type){ 392 UNUSED(ds); 393 UNUSED(callback_type); 394 395 if (!media_initialized) return; 396 397 int trigger_resume = 0; 398 if (audio_stream_paused) { 399 if (sbc_frame_size && btstack_ring_buffer_bytes_available(&ring_buffer) >= OPTIMAL_FRAMES_MIN * sbc_frame_size){ 400 trigger_resume = 1; 401 // reset buffers 402 playback_buffer = NUM_AUDIO_BUFFERS - 1; 403 write_buffer = 0; 404 } else { 405 return; 406 } 407 } 408 409 while (playback_buffer != write_buffer && btstack_ring_buffer_bytes_available(&ring_buffer) >= sbc_frame_size ){ 410 uint8_t frame[MAX_SBC_FRAME_SIZE]; 411 uint32_t bytes_read = 0; 412 btstack_ring_buffer_read(&ring_buffer, frame, sbc_frame_size, &bytes_read); 413 btstack_sbc_decoder_process_data(&state, 0, frame, sbc_frame_size); 414 } 415 416 if (trigger_resume){ 417 printf("%6u - resume\n", (int) btstack_run_loop_get_time_ms()); 418 audio_stream_paused = 0; 419 } 420 } 421 #endif 422 423 static int media_processing_init(avdtp_media_codec_configuration_sbc_t configuration){ 424 if (media_initialized) return 0; 425 #ifdef DECODE_SBC 426 btstack_sbc_decoder_init(&state, mode, handle_pcm_data, NULL); 427 #endif 428 429 #ifdef STORE_SBC_TO_WAV_FILE 430 wav_writer_open(wav_filename, configuration.num_channels, configuration.sampling_frequency); 431 #endif 432 433 #ifdef STORE_SBC_TO_SBC_FILE 434 sbc_file = fopen(sbc_filename, "wb"); 435 #endif 436 437 #ifdef HAVE_PORTAUDIO 438 // int frames_per_buffer = configuration.frames_per_buffer; 439 PaError err; 440 PaStreamParameters outputParameters; 441 const PaDeviceInfo *deviceInfo; 442 443 /* -- initialize PortAudio -- */ 444 err = Pa_Initialize(); 445 if (err != paNoError){ 446 printf("Error initializing portaudio: \"%s\"\n", Pa_GetErrorText(err)); 447 return err; 448 } 449 /* -- setup input and output -- */ 450 outputParameters.device = Pa_GetDefaultOutputDevice(); /* default output device */ 451 outputParameters.channelCount = configuration.num_channels; 452 outputParameters.sampleFormat = PA_SAMPLE_TYPE; 453 outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultHighOutputLatency; 454 outputParameters.hostApiSpecificStreamInfo = NULL; 455 deviceInfo = Pa_GetDeviceInfo( outputParameters.device ); 456 printf("PortAudio: Output device: %s\n", deviceInfo->name); 457 log_info("PortAudio: Output device: %s", deviceInfo->name); 458 /* -- setup stream -- */ 459 err = Pa_OpenStream( 460 &stream, 461 NULL, /* &inputParameters */ 462 &outputParameters, 463 configuration.sampling_frequency, 464 0, 465 paClipOff, /* we won't output out of range samples so don't bother clipping them */ 466 portaudio_callback, /* use callback */ 467 NULL ); 468 469 if (err != paNoError){ 470 printf("Error initializing portaudio: \"%s\"\n", Pa_GetErrorText(err)); 471 return err; 472 } 473 log_info("PortAudio: stream opened"); 474 printf("PortAudio: stream opened\n"); 475 #endif 476 #ifdef HAVE_AUDIO_DMA 477 audio_stream_paused = 1; 478 hal_audio_dma_init(configuration.sampling_frequency); 479 hal_audio_dma_set_audio_played(&hal_audio_dma_done); 480 // start playing silence 481 hal_audio_dma_done(); 482 #endif 483 484 #if defined(HAVE_PORTAUDIO) || defined (HAVE_AUDIO_DMA) 485 memset(ring_buffer_storage, 0, sizeof(ring_buffer_storage)); 486 btstack_ring_buffer_init(&ring_buffer, ring_buffer_storage, sizeof(ring_buffer_storage)); 487 audio_stream_started = 0; 488 audio_stream_paused = 0; 489 #endif 490 media_initialized = 1; 491 return 0; 492 } 493 494 static void media_processing_close(void){ 495 if (!media_initialized) return; 496 media_initialized = 0; 497 498 #ifdef STORE_SBC_TO_WAV_FILE 499 wav_writer_close(); 500 int total_frames_nr = state.good_frames_nr + state.bad_frames_nr + state.zero_frames_nr; 501 502 printf("WAV Writer: Decoding done. Processed totaly %d frames:\n - %d good\n - %d bad\n - %d zero frames\n", total_frames_nr, state.good_frames_nr, state.bad_frames_nr, state.zero_frames_nr); 503 printf("WAV Writer: Written %d frames to wav file: %s\n", frame_count, wav_filename); 504 #endif 505 506 #ifdef STORE_SBC_TO_SBC_FILE 507 fclose(sbc_file); 508 #endif 509 510 #if defined(HAVE_PORTAUDIO) || defined (HAVE_AUDIO_DMA) 511 audio_stream_started = 0; 512 #endif 513 514 #ifdef HAVE_PORTAUDIO 515 printf("PortAudio: Stream closed\n"); 516 log_info("PortAudio: Stream closed"); 517 518 PaError err = Pa_StopStream(stream); 519 if (err != paNoError){ 520 printf("Error stopping the stream: \"%s\"\n", Pa_GetErrorText(err)); 521 log_error("Error stopping the stream: \"%s\"", Pa_GetErrorText(err)); 522 return; 523 } 524 err = Pa_CloseStream(stream); 525 if (err != paNoError){ 526 printf("Error closing the stream: \"%s\"\n", Pa_GetErrorText(err)); 527 log_error("Error closing the stream: \"%s\"", Pa_GetErrorText(err)); 528 return; 529 } 530 err = Pa_Terminate(); 531 if (err != paNoError){ 532 printf("Error terminating portaudio: \"%s\"\n", Pa_GetErrorText(err)); 533 log_error("Error terminating portaudio: \"%s\"", Pa_GetErrorText(err)); 534 return; 535 } 536 #endif 537 538 #ifdef HAVE_AUDIO_DMA 539 hal_audio_dma_close(); 540 #endif 541 } 542 543 544 /* @section Handle Media Data Packet 545 * 546 * @text Media data packets, in this case the audio data, are received through the handle_l2cap_media_data_packet callback. 547 * Currently, only the SBC media codec is supported. Hence, the media data consists of the media packet header and the SBC packet. 548 * The SBC data will be decoded using an SBC decoder if either HAVE_PORTAUDIO or STORE_SBC_TO_WAV_FILE directive is defined. 549 * The resulting PCM frames can be then captured through a PCM data callback registered during SBC decoder setup, i.e. the 550 * handle_pcm_data callback. 551 */ 552 553 static int read_media_data_header(uint8_t * packet, int size, int * offset, avdtp_media_packet_header_t * media_header); 554 static int read_sbc_header(uint8_t * packet, int size, int * offset, avdtp_sbc_codec_header_t * sbc_header); 555 556 static void handle_l2cap_media_data_packet(uint8_t seid, uint8_t *packet, uint16_t size){ 557 UNUSED(seid); 558 int pos = 0; 559 560 avdtp_media_packet_header_t media_header; 561 if (!read_media_data_header(packet, size, &pos, &media_header)) return; 562 563 avdtp_sbc_codec_header_t sbc_header; 564 if (!read_sbc_header(packet, size, &pos, &sbc_header)) return; 565 566 #ifdef HAVE_AUDIO_DMA 567 // store sbc frame size for buffer management 568 sbc_frame_size = (size-pos)/ sbc_header.num_frames; 569 #endif 570 571 #if defined(HAVE_PORTAUDIO) || defined(STORE_SBC_TO_WAV_FILE) 572 btstack_sbc_decoder_process_data(&state, 0, packet+pos, size-pos); 573 #endif 574 575 #ifdef HAVE_AUDIO_DMA 576 btstack_ring_buffer_write(&ring_buffer, packet+pos, size-pos); 577 578 // decide on audio sync drift based on number of sbc frames in queue 579 int sbc_frames_in_buffer = btstack_ring_buffer_bytes_available(&ring_buffer) / sbc_frame_size; 580 if (sbc_frames_in_buffer < OPTIMAL_FRAMES_MIN){ 581 sbc_samples_fix = 1; // duplicate last sample 582 } else if (sbc_frames_in_buffer <= OPTIMAL_FRAMES_MAX){ 583 sbc_samples_fix = 0; // nothing to do 584 } else { 585 sbc_samples_fix = -1; // drop last sample 586 } 587 588 // dump 589 printf("%6u %03u %d\n", (int) btstack_run_loop_get_time_ms(), sbc_frames_in_buffer, sbc_samples_fix); 590 #endif 591 592 #ifdef STORE_SBC_TO_SBC_FILE 593 fwrite(packet+pos, size-pos, 1, sbc_file); 594 #endif 595 } 596 597 /* @section Handle PCM Data 598 * 599 * @text In this example, we use the [PortAudio library](http://www.portaudio.com) to play the audio stream. 600 * The PCM data are bufferd in a ring buffer. 601 * Aditionally, tha audio data can be stored in the avdtp_sink.wav file. 602 */ 603 #if defined(HAVE_PORTAUDIO) || defined(STORE_SBC_TO_WAV_FILE) || defined(HAVE_AUDIO_DMA) 604 static void handle_pcm_data(int16_t * data, int num_samples, int num_channels, int sample_rate, void * context){ 605 UNUSED(sample_rate); 606 UNUSED(context); 607 608 #ifdef STORE_SBC_TO_WAV_FILE 609 wav_writer_write_int16(num_samples*num_channels, data); 610 frame_count++; 611 #endif 612 613 #ifdef HAVE_PORTAUDIO 614 // store pcm samples in ring buffer 615 btstack_ring_buffer_write(&ring_buffer, (uint8_t *)data, num_samples*num_channels*2); 616 617 if (!audio_stream_started){ 618 audio_stream_paused = 1; 619 /* -- start stream -- */ 620 PaError err = Pa_StartStream(stream); 621 if (err != paNoError){ 622 printf("Error starting the stream: \"%s\"\n", Pa_GetErrorText(err)); 623 return; 624 } 625 audio_stream_started = 1; 626 } 627 #endif 628 629 #ifdef HAVE_AUDIO_DMA 630 // store in ring buffer 631 uint8_t * write_data = start_of_buffer(write_buffer); 632 uint16_t len = num_samples*num_channels*2; 633 memcpy(write_data, data, len); 634 audio_samples_len[write_buffer] = len; 635 636 // add/drop audio frame to fix drift 637 if (sbc_samples_fix > 0){ 638 memcpy(write_data + len, write_data + len - 4, 4); 639 audio_samples_len[write_buffer] += 4; 640 } 641 if (sbc_samples_fix < 0){ 642 audio_samples_len[write_buffer] -= 4; 643 } 644 645 write_buffer = next_buffer(write_buffer); 646 #endif 647 } 648 #endif 649 650 static int read_sbc_header(uint8_t * packet, int size, int * offset, avdtp_sbc_codec_header_t * sbc_header){ 651 int sbc_header_len = 12; // without crc 652 int pos = *offset; 653 654 if (size - pos < sbc_header_len){ 655 printf("Not enough data to read SBC header, expected %d, received %d\n", sbc_header_len, size-pos); 656 return 0; 657 } 658 659 sbc_header->fragmentation = get_bit16(packet[pos], 7); 660 sbc_header->starting_packet = get_bit16(packet[pos], 6); 661 sbc_header->last_packet = get_bit16(packet[pos], 5); 662 sbc_header->num_frames = packet[pos] & 0x0f; 663 pos++; 664 // printf("SBC HEADER: num_frames %u, fragmented %u, start %u, stop %u\n", sbc_header.num_frames, sbc_header.fragmentation, sbc_header.starting_packet, sbc_header.last_packet); 665 *offset = pos; 666 return 1; 667 } 668 669 static int read_media_data_header(uint8_t *packet, int size, int *offset, avdtp_media_packet_header_t *media_header){ 670 int media_header_len = 12; // without crc 671 int pos = *offset; 672 673 if (size - pos < media_header_len){ 674 printf("Not enough data to read media packet header, expected %d, received %d\n", media_header_len, size-pos); 675 return 0; 676 } 677 678 media_header->version = packet[pos] & 0x03; 679 media_header->padding = get_bit16(packet[pos],2); 680 media_header->extension = get_bit16(packet[pos],3); 681 media_header->csrc_count = (packet[pos] >> 4) & 0x0F; 682 pos++; 683 684 media_header->marker = get_bit16(packet[pos],0); 685 media_header->payload_type = (packet[pos] >> 1) & 0x7F; 686 pos++; 687 688 media_header->sequence_number = big_endian_read_16(packet, pos); 689 pos+=2; 690 691 media_header->timestamp = big_endian_read_32(packet, pos); 692 pos+=4; 693 694 media_header->synchronization_source = big_endian_read_32(packet, pos); 695 pos+=4; 696 *offset = pos; 697 // TODO: read csrc list 698 699 // printf_hexdump( packet, pos ); 700 // printf("MEDIA HEADER: %u timestamp, version %u, padding %u, extension %u, csrc_count %u\n", 701 // media_header->timestamp, media_header->version, media_header->padding, media_header->extension, media_header->csrc_count); 702 // printf("MEDIA HEADER: marker %02x, payload_type %02x, sequence_number %u, synchronization_source %u\n", 703 // media_header->marker, media_header->payload_type, media_header->sequence_number, media_header->synchronization_source); 704 return 1; 705 } 706 707 static void dump_sbc_configuration(avdtp_media_codec_configuration_sbc_t configuration){ 708 printf("Received SBC configuration:\n"); 709 printf(" - num_channels: %d\n", configuration.num_channels); 710 printf(" - sampling_frequency: %d\n", configuration.sampling_frequency); 711 printf(" - channel_mode: %d\n", configuration.channel_mode); 712 printf(" - block_length: %d\n", configuration.block_length); 713 printf(" - subbands: %d\n", configuration.subbands); 714 printf(" - allocation_method: %d\n", configuration.allocation_method); 715 printf(" - bitpool_value [%d, %d] \n", configuration.min_bitpool_value, configuration.max_bitpool_value); 716 printf("\n"); 717 } 718 719 static void avrcp_controller_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ 720 UNUSED(channel); 721 UNUSED(size); 722 uint16_t local_cid; 723 uint8_t status = 0xFF; 724 bd_addr_t adress; 725 726 if (packet_type != HCI_EVENT_PACKET) return; 727 if (hci_event_packet_get_type(packet) != HCI_EVENT_AVRCP_META) return; 728 switch (packet[2]){ 729 case AVRCP_SUBEVENT_CONNECTION_ESTABLISHED: { 730 local_cid = avrcp_subevent_connection_established_get_avrcp_cid(packet); 731 if (avrcp_cid != 0 && avrcp_cid != local_cid) { 732 printf("AVRCP demo: Connection failed, expected 0x%02X l2cap cid, received 0x%02X\n", avrcp_cid, local_cid); 733 return; 734 } 735 736 status = avrcp_subevent_connection_established_get_status(packet); 737 if (status != ERROR_CODE_SUCCESS){ 738 printf("AVRCP demo: Connection failed: status 0x%02x\n", status); 739 avrcp_cid = 0; 740 return; 741 } 742 743 avrcp_cid = local_cid; 744 avrcp_connected = 1; 745 avrcp_subevent_connection_established_get_bd_addr(packet, adress); 746 printf("AVRCP demo: Channel successfully opened: %s, avrcp_cid 0x%02x\n", bd_addr_to_str(adress), avrcp_cid); 747 748 // automatically enable notifications 749 avrcp_controller_enable_notification(avrcp_cid, AVRCP_NOTIFICATION_EVENT_PLAYBACK_STATUS_CHANGED); 750 avrcp_controller_enable_notification(avrcp_cid, AVRCP_NOTIFICATION_EVENT_NOW_PLAYING_CONTENT_CHANGED); 751 avrcp_controller_enable_notification(avrcp_cid, AVRCP_NOTIFICATION_EVENT_VOLUME_CHANGED); 752 avrcp_controller_enable_notification(avrcp_cid, AVRCP_NOTIFICATION_EVENT_TRACK_CHANGED); 753 return; 754 } 755 case AVRCP_SUBEVENT_CONNECTION_RELEASED: 756 printf("AVRCP demo: Channel released: avrcp_cid 0x%02x\n", avrcp_subevent_connection_released_get_avrcp_cid(packet)); 757 avrcp_cid = 0; 758 avrcp_connected = 0; 759 return; 760 default: 761 break; 762 } 763 764 status = packet[5]; 765 if (!avrcp_cid) return; 766 767 // ignore INTERIM status 768 if (status == AVRCP_CTYPE_RESPONSE_INTERIM) return; 769 770 printf("AVRCP demo: command status: %s, ", avrcp_ctype2str(status)); 771 switch (packet[2]){ 772 case AVRCP_SUBEVENT_NOTIFICATION_PLAYBACK_STATUS_CHANGED: 773 printf("notification, playback status changed %s\n", avrcp_play_status2str(avrcp_subevent_notification_playback_status_changed_get_play_status(packet))); 774 return; 775 case AVRCP_SUBEVENT_NOTIFICATION_NOW_PLAYING_CONTENT_CHANGED: 776 printf("notification, playing content changed\n"); 777 return; 778 case AVRCP_SUBEVENT_NOTIFICATION_TRACK_CHANGED: 779 printf("notification track changed\n"); 780 return; 781 case AVRCP_SUBEVENT_NOTIFICATION_VOLUME_CHANGED: 782 printf("notification absolute volume changed %d\n", avrcp_subevent_notification_volume_changed_get_absolute_volume(packet)); 783 return; 784 case AVRCP_SUBEVENT_NOTIFICATION_AVAILABLE_PLAYERS_CHANGED: 785 printf("notification changed\n"); 786 return; 787 case AVRCP_SUBEVENT_SHUFFLE_AND_REPEAT_MODE:{ 788 uint8_t shuffle_mode = avrcp_subevent_shuffle_and_repeat_mode_get_shuffle_mode(packet); 789 uint8_t repeat_mode = avrcp_subevent_shuffle_and_repeat_mode_get_repeat_mode(packet); 790 printf("%s, %s\n", avrcp_shuffle2str(shuffle_mode), avrcp_repeat2str(repeat_mode)); 791 break; 792 } 793 case AVRCP_SUBEVENT_NOW_PLAYING_TITLE_INFO: 794 if (avrcp_subevent_now_playing_title_info_get_value_len(packet) > 0){ 795 memcpy(value, avrcp_subevent_now_playing_title_info_get_value(packet), avrcp_subevent_now_playing_title_info_get_value_len(packet)); 796 printf(" Title: %s\n", value); 797 } 798 break; 799 800 case AVRCP_SUBEVENT_NOW_PLAYING_ARTIST_INFO: 801 if (avrcp_subevent_now_playing_artist_info_get_value_len(packet) > 0){ 802 memcpy(value, avrcp_subevent_now_playing_artist_info_get_value(packet), avrcp_subevent_now_playing_artist_info_get_value_len(packet)); 803 printf(" Artist: %s\n", value); 804 } 805 break; 806 807 case AVRCP_SUBEVENT_NOW_PLAYING_ALBUM_INFO: 808 if (avrcp_subevent_now_playing_album_info_get_value_len(packet) > 0){ 809 memcpy(value, avrcp_subevent_now_playing_album_info_get_value(packet), avrcp_subevent_now_playing_album_info_get_value_len(packet)); 810 printf(" Album: %s\n", value); 811 } 812 break; 813 814 case AVRCP_SUBEVENT_NOW_PLAYING_GENRE_INFO: 815 if (avrcp_subevent_now_playing_genre_info_get_value_len(packet) > 0){ 816 memcpy(value, avrcp_subevent_now_playing_genre_info_get_value(packet), avrcp_subevent_now_playing_genre_info_get_value_len(packet)); 817 printf(" Genre: %s\n", value); 818 } 819 break; 820 821 case AVRCP_SUBEVENT_PLAY_STATUS: 822 printf("song length: %d ms, song position: %d ms, play status: %s\n", 823 avrcp_subevent_play_status_get_song_length(packet), 824 avrcp_subevent_play_status_get_song_position(packet), 825 avrcp_play_status2str(avrcp_subevent_play_status_get_play_status(packet))); 826 break; 827 case AVRCP_SUBEVENT_OPERATION_COMPLETE: 828 printf("operation done %s\n", avrcp_operation2str(avrcp_subevent_operation_complete_get_operation_id(packet))); 829 break; 830 case AVRCP_SUBEVENT_OPERATION_START: 831 printf("operation start %s\n", avrcp_operation2str(avrcp_subevent_operation_complete_get_operation_id(packet))); 832 break; 833 case AVRCP_SUBEVENT_PLAYER_APPLICATION_VALUE_RESPONSE: 834 // response to set shuffle and repeat mode 835 printf("\n"); 836 break; 837 default: 838 printf("AVRCP demo: event is not parsed\n"); 839 break; 840 } 841 } 842 843 static void a2dp_sink_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ 844 UNUSED(channel); 845 UNUSED(size); 846 uint16_t cid; 847 bd_addr_t address; 848 uint8_t status; 849 850 if (packet_type != HCI_EVENT_PACKET) return; 851 if (hci_event_packet_get_type(packet) != HCI_EVENT_A2DP_META) return; 852 853 switch (packet[2]){ 854 case A2DP_SUBEVENT_SIGNALING_MEDIA_CODEC_OTHER_CONFIGURATION: 855 printf("A2DP Sink demo: received non SBC codec. not implemented.\n"); 856 break; 857 case A2DP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CONFIGURATION:{ 858 printf("A2DP Sink demo: received SBC codec configuration.\n"); 859 sbc_configuration.reconfigure = a2dp_subevent_signaling_media_codec_sbc_configuration_get_reconfigure(packet); 860 sbc_configuration.num_channels = a2dp_subevent_signaling_media_codec_sbc_configuration_get_num_channels(packet); 861 sbc_configuration.sampling_frequency = a2dp_subevent_signaling_media_codec_sbc_configuration_get_sampling_frequency(packet); 862 sbc_configuration.channel_mode = a2dp_subevent_signaling_media_codec_sbc_configuration_get_channel_mode(packet); 863 sbc_configuration.block_length = a2dp_subevent_signaling_media_codec_sbc_configuration_get_block_length(packet); 864 sbc_configuration.subbands = a2dp_subevent_signaling_media_codec_sbc_configuration_get_subbands(packet); 865 sbc_configuration.allocation_method = a2dp_subevent_signaling_media_codec_sbc_configuration_get_allocation_method(packet); 866 sbc_configuration.min_bitpool_value = a2dp_subevent_signaling_media_codec_sbc_configuration_get_min_bitpool_value(packet); 867 sbc_configuration.max_bitpool_value = a2dp_subevent_signaling_media_codec_sbc_configuration_get_max_bitpool_value(packet); 868 sbc_configuration.frames_per_buffer = sbc_configuration.subbands * sbc_configuration.block_length; 869 dump_sbc_configuration(sbc_configuration); 870 871 if (sbc_configuration.reconfigure){ 872 media_processing_close(); 873 } 874 // prepare media processing 875 media_processing_init(sbc_configuration); 876 break; 877 } 878 case A2DP_SUBEVENT_STREAM_ESTABLISHED: 879 a2dp_subevent_stream_established_get_bd_addr(packet, address); 880 status = a2dp_subevent_stream_established_get_status(packet); 881 cid = a2dp_subevent_stream_established_get_a2dp_cid(packet); 882 printf("A2DP_SUBEVENT_STREAM_ESTABLISHED %d, %d \n", cid, a2dp_cid); 883 if (!a2dp_cid){ 884 // incoming connection 885 a2dp_cid = cid; 886 } else if (cid != a2dp_cid) { 887 break; 888 } 889 if (status){ 890 a2dp_sink_connected = 0; 891 printf("A2DP Sink demo: streaming connection failed, status 0x%02x\n", status); 892 break; 893 } 894 printf("A2DP Sink demo: streaming connection is established, address %s, a2dp cid 0x%02X, local_seid %d\n", bd_addr_to_str(address), a2dp_cid, local_seid); 895 896 memcpy(device_addr, address, 6); 897 local_seid = a2dp_subevent_stream_established_get_local_seid(packet); 898 a2dp_sink_connected = 1; 899 break; 900 901 case A2DP_SUBEVENT_STREAM_STARTED: 902 cid = a2dp_subevent_stream_started_get_a2dp_cid(packet); 903 if (cid != a2dp_cid) break; 904 local_seid = a2dp_subevent_stream_started_get_local_seid(packet); 905 printf("A2DP Sink demo: stream started, a2dp cid 0x%02X, local_seid %d\n", a2dp_cid, local_seid); 906 // started 907 media_processing_init(sbc_configuration); 908 break; 909 910 case A2DP_SUBEVENT_STREAM_SUSPENDED: 911 cid = a2dp_subevent_stream_suspended_get_a2dp_cid(packet); 912 if (cid != a2dp_cid) break; 913 local_seid = a2dp_subevent_stream_suspended_get_local_seid(packet); 914 printf("A2DP Sink demo: stream paused, a2dp cid 0x%02X, local_seid %d\n", a2dp_cid, local_seid); 915 media_processing_close(); 916 break; 917 918 case A2DP_SUBEVENT_STREAM_RELEASED: 919 cid = a2dp_subevent_stream_released_get_a2dp_cid(packet); 920 if (cid != a2dp_cid) { 921 printf("A2DP Sink demo: unexpected cid 0x%02x instead of 0x%02x\n", cid, a2dp_cid); 922 break; 923 } 924 local_seid = a2dp_subevent_stream_released_get_local_seid(packet); 925 printf("A2DP Sink demo: stream released, a2dp cid 0x%02X, local_seid %d\n", a2dp_cid, local_seid); 926 media_processing_close(); 927 break; 928 case A2DP_SUBEVENT_SIGNALING_CONNECTION_RELEASED: 929 cid = a2dp_subevent_signaling_connection_released_get_a2dp_cid(packet); 930 if (cid != a2dp_cid) { 931 printf("A2DP Sink demo: unexpected cid 0x%02x instead of 0x%02x\n", cid, a2dp_cid); 932 break; 933 } 934 a2dp_sink_connected = 0; 935 printf("A2DP Sink demo: signaling connection released\n"); 936 break; 937 default: 938 printf("A2DP Sink demo: not parsed 0x%02x\n", packet[2]); 939 break; 940 } 941 } 942 943 #ifdef HAVE_BTSTACK_STDIN 944 static void show_usage(void){ 945 bd_addr_t iut_address; 946 gap_local_bd_addr(iut_address); 947 printf("\n--- Bluetooth AVDTP Sink/AVRCP Connection Test Console %s ---\n", bd_addr_to_str(iut_address)); 948 printf("b - AVDTP Sink create connection to addr %s\n", bd_addr_to_str(device_addr)); 949 printf("B - AVDTP Sink disconnect\n"); 950 printf("c - AVRCP create connection to addr %s\n", bd_addr_to_str(device_addr)); 951 printf("C - AVRCP disconnect\n"); 952 953 printf("\n--- Bluetooth AVRCP Commands %s ---\n", bd_addr_to_str(iut_address)); 954 printf("O - get play status\n"); 955 printf("j - get now playing info\n"); 956 printf("k - play\n"); 957 printf("K - stop\n"); 958 printf("L - pause\n"); 959 printf("u - start fast forward\n"); 960 printf("U - stop fast forward\n"); 961 printf("n - start rewind\n"); 962 printf("N - stop rewind\n"); 963 printf("i - forward\n"); 964 printf("I - backward\n"); 965 printf("t - volume up\n"); 966 printf("T - volume down\n"); 967 printf("p - absolute volume of 50 percent\n"); 968 printf("M - mute\n"); 969 printf("r - skip\n"); 970 printf("q - query repeat and shuffle mode\n"); 971 printf("v - repeat single track\n"); 972 printf("x - repeat all tracks\n"); 973 printf("X - disable repeat mode\n"); 974 printf("z - shuffle all tracks\n"); 975 printf("Z - disable shuffle mode\n"); 976 printf("---\n"); 977 } 978 #endif 979 980 #ifdef HAVE_BTSTACK_STDIN 981 static void stdin_process(char cmd){ 982 uint8_t status = ERROR_CODE_SUCCESS; 983 printf("stdin_process \n"); 984 if (!avrcp_connected){ 985 switch (cmd){ 986 case 'b': 987 case 'B': 988 case 'c': 989 break; 990 default: 991 printf("Command '%c' cannot be performed - please use 'c' to establish an AVRCP connection with device (addr %s).\n", cmd, bd_addr_to_str(device_addr)); 992 return; 993 } 994 995 } 996 997 switch (cmd){ 998 case 'b': 999 status = a2dp_sink_establish_stream(device_addr, local_seid, &a2dp_cid); 1000 printf(" - Create AVDTP connection to addr %s, and local seid %d, expected cid 0x%02x.\n", bd_addr_to_str(device_addr), local_seid, a2dp_cid); 1001 break; 1002 case 'B': 1003 printf(" - AVDTP disconnect from addr %s.\n", bd_addr_to_str(device_addr)); 1004 status = avdtp_sink_disconnect(a2dp_cid); 1005 break; 1006 case 'c': 1007 printf(" - Create AVRCP connection to addr %s.\n", bd_addr_to_str(device_addr)); 1008 status = avrcp_controller_connect(device_addr, &avrcp_cid); 1009 break; 1010 case 'C': 1011 printf(" - AVRCP disconnect from addr %s.\n", bd_addr_to_str(device_addr)); 1012 status = avrcp_controller_disconnect(avrcp_cid); 1013 break; 1014 1015 case '\n': 1016 case '\r': 1017 break; 1018 case 'O': 1019 printf(" - get play status\n"); 1020 status = avrcp_controller_get_play_status(avrcp_cid); 1021 break; 1022 case 'j': 1023 printf(" - get now playing info\n"); 1024 status = avrcp_controller_get_now_playing_info(avrcp_cid); 1025 break; 1026 case 'k': 1027 printf(" - play\n"); 1028 status = avrcp_controller_play(avrcp_cid); 1029 break; 1030 case 'K': 1031 printf(" - stop\n"); 1032 status = avrcp_controller_stop(avrcp_cid); 1033 break; 1034 case 'L': 1035 printf(" - pause\n"); 1036 status = avrcp_controller_pause(avrcp_cid); 1037 break; 1038 case 'u': 1039 printf(" - start fast forward\n"); 1040 status = avrcp_controller_start_fast_forward(avrcp_cid); 1041 break; 1042 case 'U': 1043 printf(" - stop fast forward\n"); 1044 status = avrcp_controller_stop_fast_forward(avrcp_cid); 1045 break; 1046 case 'n': 1047 printf(" - start rewind\n"); 1048 status = avrcp_controller_start_rewind(avrcp_cid); 1049 break; 1050 case 'N': 1051 printf(" - stop rewind\n"); 1052 status = avrcp_controller_stop_rewind(avrcp_cid); 1053 break; 1054 case 'i': 1055 printf(" - forward\n"); 1056 status = avrcp_controller_forward(avrcp_cid); 1057 break; 1058 case 'I': 1059 printf(" - backward\n"); 1060 status = avrcp_controller_backward(avrcp_cid); 1061 break; 1062 case 't': 1063 printf(" - volume up\n"); 1064 status = avrcp_controller_volume_up(avrcp_cid); 1065 break; 1066 case 'T': 1067 printf(" - volume down\n"); 1068 status = avrcp_controller_volume_down(avrcp_cid); 1069 break; 1070 case 'p': 1071 printf(" - absolute volume of 50 percent\n"); 1072 status = avrcp_controller_set_absolute_volume(avrcp_cid, 50); 1073 break; 1074 case 'M': 1075 printf(" - mute\n"); 1076 status = avrcp_controller_mute(avrcp_cid); 1077 break; 1078 case 'r': 1079 printf(" - skip\n"); 1080 status = avrcp_controller_skip(avrcp_cid); 1081 break; 1082 case 'q': 1083 printf(" - query repeat and shuffle mode\n"); 1084 status = avrcp_controller_query_shuffle_and_repeat_modes(avrcp_cid); 1085 break; 1086 case 'v': 1087 printf(" - repeat single track\n"); 1088 status = avrcp_controller_set_repeat_mode(avrcp_cid, AVRCP_REPEAT_MODE_SINGLE_TRACK); 1089 break; 1090 case 'x': 1091 printf(" - repeat all tracks\n"); 1092 status = avrcp_controller_set_repeat_mode(avrcp_cid, AVRCP_REPEAT_MODE_ALL_TRACKS); 1093 break; 1094 case 'X': 1095 printf(" - disable repeat mode\n"); 1096 status = avrcp_controller_set_repeat_mode(avrcp_cid, AVRCP_REPEAT_MODE_OFF); 1097 break; 1098 case 'z': 1099 printf(" - shuffle all tracks\n"); 1100 status = avrcp_controller_set_shuffle_mode(avrcp_cid, AVRCP_SHUFFLE_MODE_ALL_TRACKS); 1101 break; 1102 case 'Z': 1103 printf(" - disable shuffle mode\n"); 1104 status = avrcp_controller_set_shuffle_mode(avrcp_cid, AVRCP_SHUFFLE_MODE_OFF); 1105 break; 1106 default: 1107 show_usage(); 1108 return; 1109 } 1110 if (status != ERROR_CODE_SUCCESS){ 1111 printf("Could not perform command, status 0x%2x\n", status); 1112 } 1113 } 1114 #endif 1115 1116 int btstack_main(int argc, const char * argv[]); 1117 int btstack_main(int argc, const char * argv[]){ 1118 (void)argc; 1119 (void)argv; 1120 1121 int err = a2dp_sink_and_avrcp_services_init(); 1122 if (err) return err; 1123 // turn on! 1124 printf("Starting BTstack ...\n"); 1125 hci_power_control(HCI_POWER_ON); 1126 return 0; 1127 } 1128 /* EXAMPLE_END */ 1129