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