xref: /btstack/example/a2dp_source_demo.c (revision 6ff556f67e95f414d4bd7ba0f439fd97c1097d8d)
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     // Initialize AVRCP Target.
303     avrcp_target_init();
304     avrcp_target_register_packet_handler(&avrcp_target_packet_handler);
305     // Initialize AVRCP Controller
306     avrcp_controller_init();
307     avrcp_controller_register_packet_handler(&avrcp_controller_packet_handler);
308 
309     // Initialize SDP,
310     sdp_init();
311 
312     // Create  A2DP Source service record and register it with SDP.
313     memset(sdp_a2dp_source_service_buffer, 0, sizeof(sdp_a2dp_source_service_buffer));
314     a2dp_source_create_sdp_record(sdp_a2dp_source_service_buffer, 0x10002, 1, NULL, NULL);
315     sdp_register_service(sdp_a2dp_source_service_buffer);
316 
317     // Create AVRCP target service record and register it with SDP.
318     memset(sdp_avrcp_target_service_buffer, 0, sizeof(sdp_avrcp_target_service_buffer));
319     uint16_t supported_features = (1 << AVRCP_TARGET_SUPPORTED_FEATURE_CATEGORY_PLAYER_OR_RECORDER);
320 #ifdef AVRCP_BROWSING_ENABLED
321     supported_features |= (1 << AVRCP_TARGET_SUPPORTED_FEATURE_BROWSING);
322 #endif
323     avrcp_target_create_sdp_record(sdp_avrcp_target_service_buffer, 0x10001, supported_features, NULL, NULL);
324     sdp_register_service(sdp_avrcp_target_service_buffer);
325 
326     // setup AVRCP Controller
327     memset(sdp_avrcp_controller_service_buffer, 0, sizeof(sdp_avrcp_controller_service_buffer));
328     uint16_t controller_supported_features = (1 << AVRCP_CONTROLLER_SUPPORTED_FEATURE_CATEGORY_MONITOR_OR_AMPLIFIER);
329     avrcp_controller_create_sdp_record(sdp_avrcp_controller_service_buffer, 0x10002, controller_supported_features, NULL, NULL);
330     sdp_register_service(sdp_avrcp_controller_service_buffer);
331 
332     // Set local name with a template Bluetooth address, that will be automatically
333     // replaced with a actual address once it is available, i.e. when BTstack boots
334     // up and starts talking to a Bluetooth module.
335     gap_set_local_name("A2DP Source 00:00:00:00:00:00");
336     gap_discoverable_control(1);
337     gap_set_class_of_device(0x200408);
338 
339     // Register for HCI events.
340     hci_event_callback_registration.callback = &a2dp_source_packet_handler;
341     hci_add_event_handler(&hci_event_callback_registration);
342 
343     a2dp_demo_reconfigure_sample_rate(sample_rate);
344 
345     // Parse human readable Bluetooth address.
346     sscanf_bd_addr(device_addr_string, device_addr);
347 
348 #ifdef HAVE_BTSTACK_STDIN
349     btstack_stdin_setup(stdin_process);
350 #endif
351     return 0;
352 }
353 /* LISTING_END */
354 
355 static void a2dp_demo_send_media_packet(void){
356     int num_bytes_in_frame = btstack_sbc_encoder_sbc_buffer_length();
357     int bytes_in_storage = media_tracker.sbc_storage_count;
358     uint8_t num_frames = bytes_in_storage / num_bytes_in_frame;
359     a2dp_source_stream_send_media_payload(media_tracker.a2dp_cid, media_tracker.local_seid, media_tracker.sbc_storage, bytes_in_storage, num_frames, 0);
360     media_tracker.sbc_storage_count = 0;
361     media_tracker.sbc_ready_to_send = 0;
362 }
363 
364 static void produce_sine_audio(int16_t * pcm_buffer, int num_samples_to_write){
365     int count;
366     for (count = 0; count < num_samples_to_write ; count++){
367         switch (sample_rate){
368             case 44100:
369                 pcm_buffer[count * 2]     = sine_int16_44100[sine_phase];
370                 pcm_buffer[count * 2 + 1] = sine_int16_44100[sine_phase];
371                 sine_phase++;
372                 if (sine_phase >= num_samples_sine_int16_44100){
373                     sine_phase -= num_samples_sine_int16_44100;
374                 }
375                 break;
376             case 48000:
377                 pcm_buffer[count * 2]     = sine_int16_48000[sine_phase];
378                 pcm_buffer[count * 2 + 1] = sine_int16_48000[sine_phase];
379                 sine_phase++;
380                 if (sine_phase >= num_samples_sine_int16_48000){
381                     sine_phase -= num_samples_sine_int16_48000;
382                 }
383                 break;
384             default:
385                 break;
386         }
387 
388 
389     }
390 }
391 
392 static void produce_mod_audio(int16_t * pcm_buffer, int num_samples_to_write){
393     hxcmod_fillbuffer(&mod_context, (unsigned short *) &pcm_buffer[0], num_samples_to_write, &trkbuf);
394 }
395 
396 static void produce_audio(int16_t * pcm_buffer, int num_samples){
397     switch (data_source){
398         case STREAM_SINE:
399             produce_sine_audio(pcm_buffer, num_samples);
400             break;
401         case STREAM_MOD:
402             produce_mod_audio(pcm_buffer, num_samples);
403             break;
404         default:
405             break;
406     }
407 #ifdef VOLUME_REDUCTION
408     int i;
409     for (i=0;i<num_samples*2;i++){
410         if (pcm_buffer[i] > 0){
411             pcm_buffer[i] =     pcm_buffer[i]  >> VOLUME_REDUCTION;
412         } else {
413             pcm_buffer[i] = -((-pcm_buffer[i]) >> VOLUME_REDUCTION);
414         }
415     }
416 #endif
417 }
418 
419 static int a2dp_demo_fill_sbc_audio_buffer(a2dp_media_sending_context_t * context){
420     // perform sbc encodin
421     int total_num_bytes_read = 0;
422     unsigned int num_audio_samples_per_sbc_buffer = btstack_sbc_encoder_num_audio_frames();
423     while (context->samples_ready >= num_audio_samples_per_sbc_buffer
424         && (context->max_media_payload_size - context->sbc_storage_count) >= btstack_sbc_encoder_sbc_buffer_length()){
425 
426         int16_t pcm_frame[256*NUM_CHANNELS];
427 
428         produce_audio(pcm_frame, num_audio_samples_per_sbc_buffer);
429         btstack_sbc_encoder_process_data(pcm_frame);
430 
431         uint16_t sbc_frame_size = btstack_sbc_encoder_sbc_buffer_length();
432         uint8_t * sbc_frame = btstack_sbc_encoder_sbc_buffer();
433 
434         total_num_bytes_read += num_audio_samples_per_sbc_buffer;
435         memcpy(&context->sbc_storage[context->sbc_storage_count], sbc_frame, sbc_frame_size);
436         context->sbc_storage_count += sbc_frame_size;
437         context->samples_ready -= num_audio_samples_per_sbc_buffer;
438     }
439     return total_num_bytes_read;
440 }
441 
442 static void a2dp_demo_audio_timeout_handler(btstack_timer_source_t * timer){
443     a2dp_media_sending_context_t * context = (a2dp_media_sending_context_t *) btstack_run_loop_get_timer_context(timer);
444     btstack_run_loop_set_timer(&context->audio_timer, AUDIO_TIMEOUT_MS);
445     btstack_run_loop_add_timer(&context->audio_timer);
446     uint32_t now = btstack_run_loop_get_time_ms();
447 
448     uint32_t update_period_ms = AUDIO_TIMEOUT_MS;
449     if (context->time_audio_data_sent > 0){
450         update_period_ms = now - context->time_audio_data_sent;
451     }
452 
453     uint32_t num_samples = (update_period_ms * sample_rate) / 1000;
454     context->acc_num_missed_samples += (update_period_ms * sample_rate) % 1000;
455 
456     while (context->acc_num_missed_samples >= 1000){
457         num_samples++;
458         context->acc_num_missed_samples -= 1000;
459     }
460     context->time_audio_data_sent = now;
461     context->samples_ready += num_samples;
462 
463     if (context->sbc_ready_to_send) return;
464 
465     a2dp_demo_fill_sbc_audio_buffer(context);
466 
467     if ((context->sbc_storage_count + btstack_sbc_encoder_sbc_buffer_length()) > context->max_media_payload_size){
468         // schedule sending
469         context->sbc_ready_to_send = 1;
470         a2dp_source_stream_endpoint_request_can_send_now(context->a2dp_cid, context->local_seid);
471     }
472 }
473 
474 static void a2dp_demo_timer_start(a2dp_media_sending_context_t * context){
475     context->max_media_payload_size = btstack_min(a2dp_max_media_payload_size(context->a2dp_cid, context->local_seid), SBC_STORAGE_SIZE);
476     context->sbc_storage_count = 0;
477     context->sbc_ready_to_send = 0;
478     context->streaming = 1;
479     btstack_run_loop_remove_timer(&context->audio_timer);
480     btstack_run_loop_set_timer_handler(&context->audio_timer, a2dp_demo_audio_timeout_handler);
481     btstack_run_loop_set_timer_context(&context->audio_timer, context);
482     btstack_run_loop_set_timer(&context->audio_timer, AUDIO_TIMEOUT_MS);
483     btstack_run_loop_add_timer(&context->audio_timer);
484 }
485 
486 static void a2dp_demo_timer_stop(a2dp_media_sending_context_t * context){
487     context->time_audio_data_sent = 0;
488     context->acc_num_missed_samples = 0;
489     context->samples_ready = 0;
490     context->streaming = 1;
491     context->sbc_storage_count = 0;
492     context->sbc_ready_to_send = 0;
493     btstack_run_loop_remove_timer(&context->audio_timer);
494 }
495 
496 static void dump_sbc_configuration(avdtp_media_codec_configuration_sbc_t * configuration){
497     printf("Received media codec configuration:\n");
498     printf("    - num_channels: %d\n", configuration->num_channels);
499     printf("    - sampling_frequency: %d\n", configuration->sampling_frequency);
500     printf("    - channel_mode: %d\n", configuration->channel_mode);
501     printf("    - block_length: %d\n", configuration->block_length);
502     printf("    - subbands: %d\n", configuration->subbands);
503     printf("    - allocation_method: %d\n", configuration->allocation_method);
504     printf("    - bitpool_value [%d, %d] \n", configuration->min_bitpool_value, configuration->max_bitpool_value);
505 }
506 
507 static void a2dp_source_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
508     UNUSED(channel);
509     UNUSED(size);
510     uint8_t status;
511     uint8_t local_seid;
512     bd_addr_t address;
513     uint16_t cid;
514 
515     if (packet_type != HCI_EVENT_PACKET) return;
516 
517 #ifndef HAVE_BTSTACK_STDIN
518     if (hci_event_packet_get_type(packet) == BTSTACK_EVENT_STATE){
519         if (btstack_event_state_get_state(packet) != HCI_STATE_WORKING) return;
520         printf("Create A2DP Source connection to addr %s.\n", bd_addr_to_str(device_addr));
521         status = a2dp_source_establish_stream(device_addr, media_tracker.local_seid, &media_tracker.a2dp_cid);
522         if (status != ERROR_CODE_SUCCESS){
523             printf("Could not perform command, status 0x%2x\n", status);
524         }
525         return;
526     }
527 #endif
528     if (hci_event_packet_get_type(packet) == HCI_EVENT_PIN_CODE_REQUEST) {
529         printf("Pin code request - using '0000'\n");
530         hci_event_pin_code_request_get_bd_addr(packet, address);
531         gap_pin_code_response(address, "0000");
532         return;
533     }
534 
535     if (hci_event_packet_get_type(packet) != HCI_EVENT_A2DP_META) return;
536 
537     switch (hci_event_a2dp_meta_get_subevent_code(packet)){
538         case A2DP_SUBEVENT_SIGNALING_CONNECTION_ESTABLISHED:
539             a2dp_subevent_signaling_connection_established_get_bd_addr(packet, address);
540             cid = a2dp_subevent_signaling_connection_established_get_a2dp_cid(packet);
541             status = a2dp_subevent_signaling_connection_established_get_status(packet);
542 
543             if (status != ERROR_CODE_SUCCESS){
544                 printf("A2DP Source: Connection failed, status 0x%02x, cid 0x%02x, a2dp_cid 0x%02x \n", status, cid, media_tracker.a2dp_cid);
545                 media_tracker.a2dp_cid = 0;
546                 break;
547             }
548             media_tracker.a2dp_cid = cid;
549             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);
550             break;
551 
552          case A2DP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CONFIGURATION:{
553             cid  = avdtp_subevent_signaling_media_codec_sbc_configuration_get_avdtp_cid(packet);
554             if (cid != media_tracker.a2dp_cid) return;
555             media_tracker.remote_seid = a2dp_subevent_signaling_media_codec_sbc_configuration_get_acp_seid(packet);
556 
557             sbc_configuration.reconfigure = a2dp_subevent_signaling_media_codec_sbc_configuration_get_reconfigure(packet);
558             sbc_configuration.num_channels = a2dp_subevent_signaling_media_codec_sbc_configuration_get_num_channels(packet);
559             sbc_configuration.sampling_frequency = a2dp_subevent_signaling_media_codec_sbc_configuration_get_sampling_frequency(packet);
560             sbc_configuration.channel_mode = a2dp_subevent_signaling_media_codec_sbc_configuration_get_channel_mode(packet);
561             sbc_configuration.block_length = a2dp_subevent_signaling_media_codec_sbc_configuration_get_block_length(packet);
562             sbc_configuration.subbands = a2dp_subevent_signaling_media_codec_sbc_configuration_get_subbands(packet);
563             sbc_configuration.allocation_method = a2dp_subevent_signaling_media_codec_sbc_configuration_get_allocation_method(packet);
564             sbc_configuration.min_bitpool_value = a2dp_subevent_signaling_media_codec_sbc_configuration_get_min_bitpool_value(packet);
565             sbc_configuration.max_bitpool_value = a2dp_subevent_signaling_media_codec_sbc_configuration_get_max_bitpool_value(packet);
566             sbc_configuration.frames_per_buffer = sbc_configuration.subbands * sbc_configuration.block_length;
567             printf("A2DP Source: Received SBC codec configuration, sampling frequency %u, a2dp_cid 0x%02x, local seid %d (expected %d), remote seid %d .\n",
568                 sbc_configuration.sampling_frequency, cid,
569                 a2dp_subevent_signaling_media_codec_sbc_configuration_get_int_seid(packet),
570                 media_tracker.local_seid,
571                 media_tracker.remote_seid);
572 
573             // Adapt Bluetooth spec definition to SBC Encoder expected input
574             sbc_configuration.allocation_method -= 1;
575             sbc_configuration.num_channels = 2;
576             switch (sbc_configuration.channel_mode){
577                 case AVDTP_SBC_JOINT_STEREO:
578                     sbc_configuration.channel_mode = 3;
579                     break;
580                 case AVDTP_SBC_STEREO:
581                     sbc_configuration.channel_mode = 2;
582                     break;
583                 case AVDTP_SBC_DUAL_CHANNEL:
584                     sbc_configuration.channel_mode = 1;
585                     break;
586                 case AVDTP_SBC_MONO:
587                     sbc_configuration.channel_mode = 0;
588                     sbc_configuration.num_channels = 1;
589                     break;
590             }
591             dump_sbc_configuration(&sbc_configuration);
592 
593             btstack_sbc_encoder_init(&sbc_encoder_state, SBC_MODE_STANDARD,
594                 sbc_configuration.block_length, sbc_configuration.subbands,
595                 sbc_configuration.allocation_method, sbc_configuration.sampling_frequency,
596                 sbc_configuration.max_bitpool_value,
597                 sbc_configuration.channel_mode);
598             break;
599         }
600 
601         case A2DP_SUBEVENT_SIGNALING_DELAY_REPORTING_CAPABILITY:
602             printf("A2DP Source: remote supports delay report, remote seid %d\n",
603                 avdtp_subevent_signaling_delay_reporting_capability_get_remote_seid(packet));
604             break;
605         case A2DP_SUBEVENT_SIGNALING_CAPABILITIES_DONE:
606             printf("A2DP Source: All capabilities reported, remote seid %d\n",
607                 avdtp_subevent_signaling_capabilities_done_get_remote_seid(packet));
608             break;
609 
610         case A2DP_SUBEVENT_SIGNALING_DELAY_REPORT:
611             printf("A2DP Source: Received delay report of %d.%0d ms, local seid %d\n",
612                 avdtp_subevent_signaling_delay_report_get_delay_100us(packet)/10, avdtp_subevent_signaling_delay_report_get_delay_100us(packet)%10,
613                 avdtp_subevent_signaling_delay_report_get_local_seid(packet));
614             break;
615 
616         case A2DP_SUBEVENT_STREAM_ESTABLISHED:
617             a2dp_subevent_stream_established_get_bd_addr(packet, address);
618             status = a2dp_subevent_stream_established_get_status(packet);
619             if (status){
620                 printf("A2DP Source: Stream failed, status 0x%02x.\n", status);
621                 break;
622             }
623 
624             local_seid = a2dp_subevent_stream_established_get_local_seid(packet);
625             cid = a2dp_subevent_stream_established_get_a2dp_cid(packet);
626             printf("A2DP_SUBEVENT_STREAM_ESTABLISHED:  a2dp_cid [expected 0x%02x, received 0x%02x], local_seid %d (expected %d), remote_seid %d (expected %d)\n",
627                      media_tracker.a2dp_cid, cid,
628                      local_seid, media_tracker.local_seid,
629                      a2dp_subevent_stream_established_get_remote_seid(packet), media_tracker.remote_seid);
630 
631             if (local_seid != media_tracker.local_seid){
632                 printf("A2DP Source: Stream failed, wrong local seid %d, expected %d.\n", local_seid, media_tracker.local_seid);
633                 break;
634             }
635             printf("A2DP Source: Stream established, address %s, a2dp cid 0x%02x, local seid %d, remote seid %d.\n", bd_addr_to_str(address),
636                 media_tracker.a2dp_cid, media_tracker.local_seid, a2dp_subevent_stream_established_get_remote_seid(packet));
637             media_tracker.stream_opened = 1;
638             data_source = STREAM_MOD;
639             status = a2dp_source_start_stream(media_tracker.a2dp_cid, media_tracker.local_seid);
640             break;
641 
642         case A2DP_SUBEVENT_STREAM_RECONFIGURED:
643             status = a2dp_subevent_stream_reconfigured_get_status(packet);
644             local_seid = a2dp_subevent_stream_reconfigured_get_local_seid(packet);
645             cid = a2dp_subevent_stream_reconfigured_get_a2dp_cid(packet);
646 
647             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);
648             printf("Status 0x%02x\n", status);
649             break;
650 
651         case A2DP_SUBEVENT_STREAM_STARTED:
652             local_seid = a2dp_subevent_stream_started_get_local_seid(packet);
653             cid = a2dp_subevent_stream_started_get_a2dp_cid(packet);
654 
655             play_info.status = AVRCP_PLAYBACK_STATUS_PLAYING;
656             if (media_tracker.avrcp_cid){
657                 avrcp_target_set_now_playing_info(media_tracker.avrcp_cid, &tracks[data_source], sizeof(tracks)/sizeof(avrcp_track_t));
658                 avrcp_target_set_playback_status(media_tracker.avrcp_cid, AVRCP_PLAYBACK_STATUS_PLAYING);
659             }
660             a2dp_demo_timer_start(&media_tracker);
661             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);
662             break;
663 
664         case A2DP_SUBEVENT_STREAMING_CAN_SEND_MEDIA_PACKET_NOW:
665             local_seid = a2dp_subevent_streaming_can_send_media_packet_now_get_local_seid(packet);
666             cid = a2dp_subevent_signaling_media_codec_sbc_configuration_get_a2dp_cid(packet);
667             // 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);
668             a2dp_demo_send_media_packet();
669             break;
670 
671         case A2DP_SUBEVENT_STREAM_SUSPENDED:
672             local_seid = a2dp_subevent_stream_suspended_get_local_seid(packet);
673             cid = a2dp_subevent_stream_suspended_get_a2dp_cid(packet);
674 
675             play_info.status = AVRCP_PLAYBACK_STATUS_PAUSED;
676             if (media_tracker.avrcp_cid){
677                 avrcp_target_set_playback_status(media_tracker.avrcp_cid, AVRCP_PLAYBACK_STATUS_PAUSED);
678             }
679             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);
680 
681             a2dp_demo_timer_stop(&media_tracker);
682             break;
683 
684         case A2DP_SUBEVENT_STREAM_RELEASED:
685             play_info.status = AVRCP_PLAYBACK_STATUS_STOPPED;
686             cid = a2dp_subevent_stream_released_get_a2dp_cid(packet);
687             local_seid = a2dp_subevent_stream_released_get_local_seid(packet);
688 
689             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);
690 
691             if (cid == media_tracker.a2dp_cid) {
692                 media_tracker.stream_opened = 0;
693                 printf("A2DP Source: Stream released.\n");
694             }
695             if (media_tracker.avrcp_cid){
696                 avrcp_target_set_now_playing_info(media_tracker.avrcp_cid, NULL, sizeof(tracks)/sizeof(avrcp_track_t));
697                 avrcp_target_set_playback_status(media_tracker.avrcp_cid, AVRCP_PLAYBACK_STATUS_STOPPED);
698             }
699 
700             a2dp_demo_timer_stop(&media_tracker);
701             break;
702         case A2DP_SUBEVENT_SIGNALING_CONNECTION_RELEASED:
703             cid = a2dp_subevent_signaling_connection_released_get_a2dp_cid(packet);
704             if (cid == media_tracker.a2dp_cid) {
705                 media_tracker.avrcp_cid = 0;
706                 media_tracker.a2dp_cid = 0;
707                 printf("A2DP Source: Signaling released.\n\n");
708             }
709             break;
710         default:
711             break;
712     }
713 }
714 
715 static void avrcp_target_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
716     UNUSED(channel);
717     UNUSED(size);
718     bd_addr_t event_addr;
719     uint16_t local_cid;
720     uint8_t  status = ERROR_CODE_SUCCESS;
721 
722     if (packet_type != HCI_EVENT_PACKET) return;
723     if (hci_event_packet_get_type(packet) != HCI_EVENT_AVRCP_META) return;
724 
725     switch (packet[2]){
726         case AVRCP_SUBEVENT_CONNECTION_ESTABLISHED: {
727             local_cid = avrcp_subevent_connection_established_get_avrcp_cid(packet);
728             // if (avrcp_cid != 0 && avrcp_cid != local_cid) {
729             //     printf("AVRCP Target: Connection failed, expected 0x%02X l2cap cid, received 0x%02X\n", avrcp_cid, local_cid);
730             //     return;
731             // }
732             // if (avrcp_cid != local_cid) break;
733 
734             status = avrcp_subevent_connection_established_get_status(packet);
735             if (status != ERROR_CODE_SUCCESS){
736                 printf("AVRCP Target: Connection failed, status 0x%02x\n", status);
737                 return;
738             }
739             media_tracker.avrcp_cid = local_cid;
740             avrcp_subevent_connection_established_get_bd_addr(packet, event_addr);
741             printf("AVRCP Target: Connected to %s, avrcp_cid 0x%02x\n", bd_addr_to_str(event_addr), local_cid);
742 
743             avrcp_target_set_now_playing_info(media_tracker.avrcp_cid, NULL, sizeof(tracks)/sizeof(avrcp_track_t));
744             avrcp_target_set_unit_info(media_tracker.avrcp_cid, AVRCP_SUBUNIT_TYPE_AUDIO, company_id);
745             avrcp_target_set_subunit_info(media_tracker.avrcp_cid, AVRCP_SUBUNIT_TYPE_AUDIO, (uint8_t *)subunit_info, sizeof(subunit_info));
746             return;
747         }
748         case AVRCP_SUBEVENT_NOTIFICATION_VOLUME_CHANGED:
749             printf("AVRCP Target: new volume %d\n", avrcp_subevent_notification_volume_changed_get_absolute_volume(packet));
750             break;
751         case AVRCP_SUBEVENT_EVENT_IDS_QUERY:
752             status = avrcp_target_supported_events(media_tracker.avrcp_cid, events_num, events, sizeof(events));
753             break;
754         case AVRCP_SUBEVENT_COMPANY_IDS_QUERY:
755             status = avrcp_target_supported_companies(media_tracker.avrcp_cid, companies_num, companies, sizeof(companies));
756             break;
757         case AVRCP_SUBEVENT_PLAY_STATUS_QUERY:
758             status = avrcp_target_play_status(media_tracker.avrcp_cid, play_info.song_length_ms, play_info.song_position_ms, play_info.status);
759             break;
760         // case AVRCP_SUBEVENT_NOW_PLAYING_INFO_QUERY:
761         //     status = avrcp_target_now_playing_info(avrcp_cid);
762         //     break;
763         case AVRCP_SUBEVENT_OPERATION:{
764             avrcp_operation_id_t operation_id = avrcp_subevent_operation_get_operation_id(packet);
765             switch (operation_id){
766                 case AVRCP_OPERATION_ID_PLAY:
767                     printf("AVRCP Target: PLAY\n");
768                     status = a2dp_source_start_stream(media_tracker.a2dp_cid, media_tracker.local_seid);
769                     break;
770                 case AVRCP_OPERATION_ID_PAUSE:
771                     printf("AVRCP Target: PAUSE\n");
772                     status = a2dp_source_pause_stream(media_tracker.a2dp_cid, media_tracker.local_seid);
773                     break;
774                 case AVRCP_OPERATION_ID_STOP:
775                     printf("AVRCP Target: STOP\n");
776                     status = a2dp_source_disconnect(media_tracker.a2dp_cid);
777                     break;
778                 default:
779                     printf("AVRCP Target: operation 0x%2x is not handled\n", operation_id);
780                     return;
781             }
782             break;
783         }
784         case AVRCP_SUBEVENT_CONNECTION_RELEASED:
785             printf("AVRCP Target: Disconnected, avrcp_cid 0x%02x\n", avrcp_subevent_connection_released_get_avrcp_cid(packet));
786             media_tracker.avrcp_cid = 0;
787             return;
788         default:
789             break;
790     }
791 
792     if (status != ERROR_CODE_SUCCESS){
793         printf("Responding to event 0x%02x failed with status 0x%02x\n", packet[2], status);
794     }
795 }
796 
797 static void avrcp_controller_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
798     UNUSED(channel);
799     UNUSED(size);
800     uint16_t local_cid;
801     uint8_t  status = 0xFF;
802     bd_addr_t adress;
803 
804     if (packet_type != HCI_EVENT_PACKET) return;
805     if (hci_event_packet_get_type(packet) != HCI_EVENT_AVRCP_META) return;
806     switch (packet[2]){
807         case AVRCP_SUBEVENT_CONNECTION_ESTABLISHED: {
808             local_cid = avrcp_subevent_connection_established_get_avrcp_cid(packet);
809             if (avrcp_controller_cid != 0 && avrcp_controller_cid != local_cid) {
810                 printf("AVRCP Controller: Connection failed, expected 0x%02X l2cap cid, received 0x%02X\n", avrcp_controller_cid, local_cid);
811                 return;
812             }
813 
814             status = avrcp_subevent_connection_established_get_status(packet);
815             if (status != ERROR_CODE_SUCCESS){
816                 printf("AVRCP Controller: Connection failed: status 0x%02x\n", status);
817                 avrcp_controller_cid = 0;
818                 return;
819             }
820 
821             avrcp_controller_cid = local_cid;
822             avrcp_subevent_connection_established_get_bd_addr(packet, adress);
823             printf("AVRCP Controller: Channel successfully opened: %s, avrcp_controller_cid 0x%02x\n", bd_addr_to_str(adress), avrcp_controller_cid);
824 
825             // automatically enable notifications
826             avrcp_controller_enable_notification(avrcp_controller_cid, AVRCP_NOTIFICATION_EVENT_VOLUME_CHANGED);
827             return;
828         }
829         case AVRCP_SUBEVENT_CONNECTION_RELEASED:
830             printf("AVRCP Controller: Channel released: avrcp_controller_cid 0x%02x\n", avrcp_subevent_connection_released_get_avrcp_cid(packet));
831             avrcp_controller_cid = 0;
832             return;
833         default:
834             break;
835     }
836 
837     status = packet[5];
838     if (!avrcp_controller_cid) return;
839 
840     // ignore INTERIM status
841     if (status == AVRCP_CTYPE_RESPONSE_INTERIM) return;
842 
843     switch (packet[2]){
844         case AVRCP_SUBEVENT_NOTIFICATION_VOLUME_CHANGED:{
845             int volume_percentage = avrcp_subevent_notification_volume_changed_get_absolute_volume(packet) * 100 / 127;
846             printf("AVRCP Controller: notification absolute volume changed %d %%\n", volume_percentage);
847             return;
848         }
849         default:
850             break;
851     }
852 }
853 
854 #ifdef HAVE_BTSTACK_STDIN
855 static void show_usage(void){
856     bd_addr_t      iut_address;
857     gap_local_bd_addr(iut_address);
858     printf("\n--- Bluetooth  A2DP Source/AVRCP Target Demo %s ---\n", bd_addr_to_str(iut_address));
859     printf("b      - A2DP Source create connection to addr %s\n", device_addr_string);
860     printf("B      - A2DP Source disconnect\n");
861     printf("c      - AVRCP Target create connection to addr %s\n", device_addr_string);
862     printf("C      - AVRCP Target disconnect\n");
863 
864     printf("x      - start streaming sine\n");
865     if (hxcmod_initialized){
866         printf("z      - start streaming '%s'\n", mod_name);
867     }
868     printf("p      - pause streaming\n");
869     printf("w      - reconfigure stream for 44100 Hz\n");
870     printf("e      - reconfigure stream for 48000 Hz\n");
871     printf("t      - volume up\n");
872     printf("T      - volume down\n");
873     printf("v      - absolute volume of 50 percent\n");
874 
875     printf("\n--- Bluetooth  AVRCP Target Commands %s ---\n", bd_addr_to_str(iut_address));
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 Target connection to addr %s.\n", cmd, bd_addr_to_str(device_addr));
892             status = avrcp_target_connect(device_addr, &media_tracker.avrcp_cid);
893             break;
894         case 'C':
895             printf("%c - AVRCP Target disconnect\n", cmd);
896             status = avrcp_target_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