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