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