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