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