xref: /btstack/example/a2dp_source_demo.c (revision 8b69b608f0aa375cd73bae7194395b910ad6fa3f)
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 BLUEKITCHEN
24  * GMBH 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): A2DP Source - Stream Audio and Control Volume
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. If HAVE_BTSTACK_STDIN
51  * is set, press SPACE on the console to show the available AVDTP and AVRCP commands.
52  *
53  * @text To test with a remote device, e.g. a Bluetooth speaker,
54  * set the device_addr_string to the Bluetooth address of your
55  * remote device in the code, and use the UI to connect and start playback.
56  *
57  * @text 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 <inttypes.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 
76 //#define AVRCP_BROWSING_ENABLED
77 
78 // select preferred audio sampling rate: 44100 or 48000
79 #define A2DP_SOURCE_DEMO_PREFERRED_SAMPLING_RATE 44100
80 
81 #define NUM_CHANNELS                2
82 #define BYTES_PER_AUDIO_SAMPLE      (2*NUM_CHANNELS)
83 #define AUDIO_TIMEOUT_MS            10
84 #define TABLE_SIZE_441HZ            100
85 
86 #define SBC_STORAGE_SIZE 1030
87 
88 typedef enum {
89     STREAM_SINE = 0,
90     STREAM_MOD,
91     STREAM_PTS_TEST
92 } stream_data_source_t;
93 
94 typedef struct {
95     uint16_t a2dp_cid;
96     uint8_t  local_seid;
97     uint8_t  remote_seid;
98     uint8_t  stream_opened;
99     uint16_t avrcp_cid;
100 
101     uint32_t time_audio_data_sent; // ms
102     uint32_t acc_num_missed_samples;
103     uint32_t samples_ready;
104     btstack_timer_source_t audio_timer;
105     uint8_t  streaming;
106     int      max_media_payload_size;
107     uint32_t rtp_timestamp;
108 
109     uint8_t  sbc_storage[SBC_STORAGE_SIZE];
110     uint16_t sbc_storage_count;
111     uint8_t  sbc_ready_to_send;
112 
113     uint8_t volume;
114 } a2dp_media_sending_context_t;
115 
116 static  uint8_t media_sbc_codec_capabilities[] = {
117     (AVDTP_SBC_44100 << 4) | (AVDTP_SBC_48000 << 4) | AVDTP_SBC_STEREO,
118     0xFF,//(AVDTP_SBC_BLOCK_LENGTH_16 << 4) | (AVDTP_SBC_SUBBANDS_8 << 2) | AVDTP_SBC_ALLOCATION_METHOD_LOUDNESS,
119     2, 53
120 };
121 
122 // input signal: pre-computed int16 sine wave, 44100 Hz at 441 Hz
123 static const int16_t sine_int16_44100[] = {
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      0,   -2057,   -4107,   -6140,   -8149,  -10126,  -12062,  -13952,  -15786,  -17557,
130 -19260,  -20886,  -22431,  -23886,  -25247,  -26509,  -27666,  -28714,  -29648,  -30466,
131 -31163,  -31738,  -32187,  -32509,  -32702,  -32767,  -32702,  -32509,  -32187,  -31738,
132 -31163,  -30466,  -29648,  -28714,  -27666,  -26509,  -25247,  -23886,  -22431,  -20886,
133 -19260,  -17557,  -15786,  -13952,  -12062,  -10126,   -8149,   -6140,   -4107,   -2057,
134 };
135 
136 static const int num_samples_sine_int16_44100 = sizeof(sine_int16_44100) / 2;
137 
138 // input signal: pre-computed int16 sine wave, 48000 Hz at 441 Hz
139 static const int16_t sine_int16_48000[] = {
140      0,    1905,    3804,    5690,    7557,    9398,   11207,   12978,   14706,   16383,
141  18006,   19567,   21062,   22486,   23834,   25101,   26283,   27376,   28377,   29282,
142  30087,   30791,   31390,   31884,   32269,   32545,   32712,   32767,   32712,   32545,
143  32269,   31884,   31390,   30791,   30087,   29282,   28377,   27376,   26283,   25101,
144  23834,   22486,   21062,   19567,   18006,   16383,   14706,   12978,   11207,    9398,
145   7557,    5690,    3804,    1905,       0,   -1905,   -3804,   -5690,   -7557,   -9398,
146 -11207,  -12978,  -14706,  -16384,  -18006,  -19567,  -21062,  -22486,  -23834,  -25101,
147 -26283,  -27376,  -28377,  -29282,  -30087,  -30791,  -31390,  -31884,  -32269,  -32545,
148 -32712,  -32767,  -32712,  -32545,  -32269,  -31884,  -31390,  -30791,  -30087,  -29282,
149 -28377,  -27376,  -26283,  -25101,  -23834,  -22486,  -21062,  -19567,  -18006,  -16384,
150 -14706,  -12978,  -11207,   -9398,   -7557,   -5690,   -3804,   -1905,  };
151 
152 static const int num_samples_sine_int16_48000 = sizeof(sine_int16_48000) / 2;
153 
154 static const int A2DP_SOURCE_DEMO_INQUIRY_DURATION_1280MS = 12;
155 
156 typedef struct {
157     int reconfigure;
158 
159     int num_channels;
160     int sampling_frequency;
161     int block_length;
162     int subbands;
163     int min_bitpool_value;
164     int max_bitpool_value;
165     btstack_sbc_channel_mode_t      channel_mode;
166     btstack_sbc_allocation_method_t allocation_method;
167 } media_codec_configuration_sbc_t;
168 
169 static btstack_packet_callback_registration_t hci_event_callback_registration;
170 
171 // Minijambox:
172 static const char * device_addr_string = "00:21:3C:AC:F7:38";
173 
174 static bd_addr_t device_addr;
175 static bool scan_active;
176 
177 static uint8_t sdp_a2dp_source_service_buffer[150];
178 static uint8_t sdp_avrcp_target_service_buffer[200];
179 static uint8_t sdp_avrcp_controller_service_buffer[200];
180 static uint8_t device_id_sdp_service_buffer[100];
181 
182 static media_codec_configuration_sbc_t sbc_configuration;
183 
184 static const btstack_sbc_encoder_t *   sbc_encoder_instance;
185 static btstack_sbc_encoder_bluedroid_t sbc_encoder_state;
186 
187 static uint8_t media_sbc_codec_configuration[4];
188 static a2dp_media_sending_context_t media_tracker;
189 
190 static stream_data_source_t data_source;
191 
192 static int sine_phase;
193 static int current_sample_rate = 44100;
194 static int new_sample_rate = 44100;
195 
196 static int hxcmod_initialized;
197 static modcontext mod_context;
198 static tracker_buffer_state trkbuf;
199 
200 /* AVRCP Target context START */
201 
202 typedef struct {
203     uint8_t track_id[8];
204     uint32_t song_length_ms;
205     avrcp_playback_status_t status;
206     uint32_t song_position_ms; // 0xFFFFFFFF if not supported
207 } avrcp_play_status_info_t;
208 
209 // python -c "print('a'*512)"
210 static const char title[] = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
211 
212 avrcp_track_t tracks[] = {
213     {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, 1, "Sine", "Generated", "A2DP Source Demo", "monotone", 12345, 6789},
214     {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02}, 2, "Nao-deceased", "Decease", "A2DP Source Demo", "vivid", 12345, 6789},
215     {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03}, 3, (char *)title, "Decease", "A2DP Source Demo", "vivid", 12345, 6789},
216 };
217 int current_track_index;
218 avrcp_play_status_info_t play_info;
219 
220 /* AVRCP Target context END */
221 
222 /* @section Main Application Setup
223  *
224  * @text The Listing MainConfiguration shows how to setup AD2P Source and AVRCP services.
225  * Besides calling init() method for each service, you'll also need to register several packet handlers:
226  * - hci_packet_handler - handles legacy pairing, here by using fixed '0000' pin code.
227  * - a2dp_source_packet_handler - handles events on stream connection status (established, released), the media codec configuration, and, the commands on stream itself (open, pause, stopp).
228  * - avrcp_packet_handler - receives connect/disconnect event.
229  * - avrcp_controller_packet_handler - receives answers for sent AVRCP commands.
230  * - avrcp_target_packet_handler - receives AVRCP commands, and registered notifications.
231  * - stdin_process - used to trigger AVRCP commands to the A2DP Source device, such are get now playing info, start, stop, volume control. Requires HAVE_BTSTACK_STDIN.
232  *
233  * @text To announce A2DP Source and AVRCP services, you need to create corresponding
234  * SDP records and register them with the SDP service.
235  */
236 
237 /* LISTING_START(MainConfiguration): Setup Audio Source and AVRCP Target services */
238 static void hci_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size);
239 static void a2dp_source_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t * event, uint16_t event_size);
240 static void avrcp_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size);
241 static void avrcp_target_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size);
242 static void avrcp_controller_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size);
243 #ifdef HAVE_BTSTACK_STDIN
244 static void stdin_process(char cmd);
245 #endif
246 
247 static void a2dp_demo_hexcmod_configure_sample_rate(int sample_rate);
248 
249 static int a2dp_source_and_avrcp_services_init(void){
250 
251     // Request role change on reconnecting headset to always use them in slave mode
252     hci_set_master_slave_policy(0);
253     // enabled EIR
254     hci_set_inquiry_mode(INQUIRY_MODE_RSSI_AND_EIR);
255 
256     l2cap_init();
257 
258 #ifdef ENABLE_BLE
259     // Initialize LE Security Manager. Needed for cross-transport key derivation
260     sm_init();
261 #endif
262 
263     // Initialize  A2DP Source
264     a2dp_source_init();
265     a2dp_source_register_packet_handler(&a2dp_source_packet_handler);
266 
267     // Create stream endpoint
268     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));
269     if (!local_stream_endpoint){
270         printf("A2DP Source: not enough memory to create local stream endpoint\n");
271         return 1;
272     }
273 
274     avdtp_set_preferred_sampling_frequency(local_stream_endpoint, A2DP_SOURCE_DEMO_PREFERRED_SAMPLING_RATE);
275 
276     // Store stream enpoint's SEP ID, as it is used by A2DP API to indentify the stream endpoint
277     media_tracker.local_seid = avdtp_local_seid(local_stream_endpoint);
278     avdtp_source_register_delay_reporting_category(media_tracker.local_seid);
279 
280     // Initialize AVRCP Service
281     avrcp_init();
282     avrcp_register_packet_handler(&avrcp_packet_handler);
283     // Initialize AVRCP Target
284     avrcp_target_init();
285     avrcp_target_register_packet_handler(&avrcp_target_packet_handler);
286 
287     // Initialize AVRCP Controller
288     avrcp_controller_init();
289     avrcp_controller_register_packet_handler(&avrcp_controller_packet_handler);
290 
291     // Initialize SDP,
292     sdp_init();
293 
294     // Create A2DP Source service record and register it with SDP
295     memset(sdp_a2dp_source_service_buffer, 0, sizeof(sdp_a2dp_source_service_buffer));
296     a2dp_source_create_sdp_record(sdp_a2dp_source_service_buffer, sdp_create_service_record_handle(), AVDTP_SOURCE_FEATURE_MASK_PLAYER, NULL, NULL);
297     btstack_assert(de_get_len( sdp_a2dp_source_service_buffer) <= sizeof(sdp_a2dp_source_service_buffer));
298     sdp_register_service(sdp_a2dp_source_service_buffer);
299 
300     // Create AVRCP Target service record and register it with SDP. We receive Category 1 commands from the headphone, e.g. play/pause
301     memset(sdp_avrcp_target_service_buffer, 0, sizeof(sdp_avrcp_target_service_buffer));
302     uint16_t supported_features = AVRCP_FEATURE_MASK_CATEGORY_PLAYER_OR_RECORDER;
303 #ifdef AVRCP_BROWSING_ENABLED
304     supported_features |= AVRCP_FEATURE_MASK_BROWSING;
305 #endif
306     avrcp_target_create_sdp_record(sdp_avrcp_target_service_buffer, sdp_create_service_record_handle(), supported_features, NULL, NULL);
307     btstack_assert(de_get_len( sdp_avrcp_target_service_buffer) <= sizeof(sdp_avrcp_target_service_buffer));
308     sdp_register_service(sdp_avrcp_target_service_buffer);
309 
310     // Create AVRCP Controller service record and register it with SDP. We send Category 2 commands to the headphone, e.g. volume up/down
311     memset(sdp_avrcp_controller_service_buffer, 0, sizeof(sdp_avrcp_controller_service_buffer));
312     uint16_t controller_supported_features = AVRCP_FEATURE_MASK_CATEGORY_MONITOR_OR_AMPLIFIER;
313     avrcp_controller_create_sdp_record(sdp_avrcp_controller_service_buffer, sdp_create_service_record_handle(), controller_supported_features, NULL, NULL);
314     btstack_assert(de_get_len( sdp_avrcp_controller_service_buffer) <= sizeof(sdp_avrcp_controller_service_buffer));
315     sdp_register_service(sdp_avrcp_controller_service_buffer);
316 
317     // Register Device ID (PnP) service SDP record
318     memset(device_id_sdp_service_buffer, 0, sizeof(device_id_sdp_service_buffer));
319     device_id_create_sdp_record(device_id_sdp_service_buffer, sdp_create_service_record_handle(), DEVICE_ID_VENDOR_ID_SOURCE_BLUETOOTH, BLUETOOTH_COMPANY_ID_BLUEKITCHEN_GMBH, 1, 1);
320     btstack_assert(de_get_len( device_id_sdp_service_buffer) <= sizeof(device_id_sdp_service_buffer));
321     sdp_register_service(device_id_sdp_service_buffer);
322 
323     // Set local name with a template Bluetooth address, that will be automatically
324     // replaced with a actual address once it is available, i.e. when BTstack boots
325     // up and starts talking to a Bluetooth module.
326     gap_set_local_name("A2DP Source 00:00:00:00:00:00");
327     gap_discoverable_control(1);
328     gap_set_class_of_device(0x200408);
329 
330     // Register for HCI events.
331     hci_event_callback_registration.callback = &hci_packet_handler;
332     hci_add_event_handler(&hci_event_callback_registration);
333 
334     data_source = STREAM_MOD;
335 
336     // Parse human readable Bluetooth address.
337     sscanf_bd_addr(device_addr_string, device_addr);
338 
339 #ifdef HAVE_BTSTACK_STDIN
340     btstack_stdin_setup(stdin_process);
341 #endif
342     return 0;
343 }
344 /* LISTING_END */
345 
346 static void a2dp_demo_hexcmod_configure_sample_rate(int sample_rate){
347     if (!hxcmod_initialized){
348         hxcmod_initialized = hxcmod_init(&mod_context);
349         if (!hxcmod_initialized) {
350             printf("could not initialize hxcmod\n");
351             return;
352         }
353     }
354     current_sample_rate = sample_rate;
355     media_tracker.sbc_storage_count = 0;
356     media_tracker.samples_ready = 0;
357     hxcmod_unload(&mod_context);
358     hxcmod_setcfg(&mod_context, current_sample_rate, 16, 1, 1, 1);
359     hxcmod_load(&mod_context, (void *) &mod_data, mod_len);
360 }
361 
362 static void a2dp_demo_send_media_packet(void){
363     int num_bytes_in_frame = sbc_encoder_instance->sbc_buffer_length(&sbc_encoder_state);
364     int bytes_in_storage = media_tracker.sbc_storage_count;
365     uint8_t num_sbc_frames = bytes_in_storage / num_bytes_in_frame;
366     // Prepend SBC Header
367     media_tracker.sbc_storage[0] = num_sbc_frames;  // (fragmentation << 7) | (starting_packet << 6) | (last_packet << 5) | num_frames;
368     a2dp_source_stream_send_media_payload_rtp(media_tracker.a2dp_cid, media_tracker.local_seid, 0,
369                                                media_tracker.rtp_timestamp,
370                                                media_tracker.sbc_storage, bytes_in_storage + 1);
371 
372     // update rtp_timestamp
373     unsigned int num_audio_samples_per_sbc_buffer = sbc_encoder_instance->num_audio_frames(&sbc_encoder_state);
374     media_tracker.rtp_timestamp += num_sbc_frames * num_audio_samples_per_sbc_buffer;
375 
376     media_tracker.sbc_storage_count = 0;
377     media_tracker.sbc_ready_to_send = 0;
378 }
379 
380 static void produce_sine_audio(int16_t * pcm_buffer, int num_samples_to_write){
381     int count;
382     for (count = 0; count < num_samples_to_write ; count++){
383         switch (current_sample_rate){
384             case 44100:
385                 pcm_buffer[count * 2]     = sine_int16_44100[sine_phase];
386                 pcm_buffer[count * 2 + 1] = sine_int16_44100[sine_phase];
387                 sine_phase++;
388                 if (sine_phase >= num_samples_sine_int16_44100){
389                     sine_phase -= num_samples_sine_int16_44100;
390                 }
391                 break;
392             case 48000:
393                 pcm_buffer[count * 2]     = sine_int16_48000[sine_phase];
394                 pcm_buffer[count * 2 + 1] = sine_int16_48000[sine_phase];
395                 sine_phase++;
396                 if (sine_phase >= num_samples_sine_int16_48000){
397                     sine_phase -= num_samples_sine_int16_48000;
398                 }
399                 break;
400             default:
401                 break;
402         }
403     }
404 }
405 
406 static void produce_mod_audio(int16_t * pcm_buffer, int num_samples_to_write){
407     hxcmod_fillbuffer(&mod_context, (unsigned short *) &pcm_buffer[0], num_samples_to_write, &trkbuf);
408 }
409 
410 static void produce_audio(int16_t * pcm_buffer, int num_samples){
411     switch (data_source){
412         case STREAM_SINE:
413             produce_sine_audio(pcm_buffer, num_samples);
414             break;
415         case STREAM_MOD:
416             produce_mod_audio(pcm_buffer, num_samples);
417             break;
418         default:
419             break;
420     }
421 #ifdef VOLUME_REDUCTION
422     int i;
423     for (i=0;i<num_samples*2;i++){
424         if (pcm_buffer[i] > 0){
425             pcm_buffer[i] =     pcm_buffer[i]  >> VOLUME_REDUCTION;
426         } else {
427             pcm_buffer[i] = -((-pcm_buffer[i]) >> VOLUME_REDUCTION);
428         }
429     }
430 #endif
431 }
432 
433 static int a2dp_demo_fill_sbc_audio_buffer(a2dp_media_sending_context_t * context){
434     // perform sbc encoding
435     int total_num_bytes_read = 0;
436     unsigned int num_audio_samples_per_sbc_buffer =  sbc_encoder_instance->num_audio_frames(&sbc_encoder_state);
437     uint16_t sbc_buffer_length = sbc_encoder_instance->sbc_buffer_length(&sbc_encoder_state);
438     while (context->samples_ready >= num_audio_samples_per_sbc_buffer
439         && (context->max_media_payload_size - context->sbc_storage_count) >= sbc_buffer_length){
440 
441         int16_t pcm_frame[256*NUM_CHANNELS];
442 
443         produce_audio(pcm_frame, num_audio_samples_per_sbc_buffer);
444 
445         // encode into sbc storage buffer, first byte contains sbc media header
446         sbc_encoder_instance->encode_signed_16(&sbc_encoder_state, pcm_frame, &context->sbc_storage[1 + context->sbc_storage_count]);
447 
448         total_num_bytes_read += num_audio_samples_per_sbc_buffer;
449 
450         uint16_t sbc_frame_size =  sbc_encoder_instance->sbc_buffer_length(&sbc_encoder_state);
451         context->sbc_storage_count += sbc_frame_size;
452         context->samples_ready -= num_audio_samples_per_sbc_buffer;
453     }
454     return total_num_bytes_read;
455 }
456 
457 static void a2dp_demo_audio_timeout_handler(btstack_timer_source_t * timer){
458     a2dp_media_sending_context_t * context = (a2dp_media_sending_context_t *) btstack_run_loop_get_timer_context(timer);
459     btstack_run_loop_set_timer(&context->audio_timer, AUDIO_TIMEOUT_MS);
460     btstack_run_loop_add_timer(&context->audio_timer);
461     uint32_t now = btstack_run_loop_get_time_ms();
462 
463     uint32_t update_period_ms = AUDIO_TIMEOUT_MS;
464     if (context->time_audio_data_sent > 0){
465         update_period_ms = now - context->time_audio_data_sent;
466     }
467 
468     uint32_t num_samples = (update_period_ms * current_sample_rate) / 1000;
469     context->acc_num_missed_samples += (update_period_ms * current_sample_rate) % 1000;
470 
471     while (context->acc_num_missed_samples >= 1000){
472         num_samples++;
473         context->acc_num_missed_samples -= 1000;
474     }
475     context->time_audio_data_sent = now;
476     context->samples_ready += num_samples;
477 
478     if (context->sbc_ready_to_send) return;
479 
480     a2dp_demo_fill_sbc_audio_buffer(context);
481 
482     if ((context->sbc_storage_count + sbc_encoder_instance->sbc_buffer_length(&sbc_encoder_state)) > context->max_media_payload_size){
483         // schedule sending
484         context->sbc_ready_to_send = 1;
485         a2dp_source_stream_endpoint_request_can_send_now(context->a2dp_cid, context->local_seid);
486     }
487 }
488 
489 static void a2dp_demo_timer_start(a2dp_media_sending_context_t * context){
490     context->max_media_payload_size = btstack_min(a2dp_max_media_payload_size(context->a2dp_cid, context->local_seid), SBC_STORAGE_SIZE);
491     context->sbc_storage_count = 0;
492     context->sbc_ready_to_send = 0;
493     context->streaming = 1;
494     btstack_run_loop_remove_timer(&context->audio_timer);
495     btstack_run_loop_set_timer_handler(&context->audio_timer, a2dp_demo_audio_timeout_handler);
496     btstack_run_loop_set_timer_context(&context->audio_timer, context);
497     btstack_run_loop_set_timer(&context->audio_timer, AUDIO_TIMEOUT_MS);
498     btstack_run_loop_add_timer(&context->audio_timer);
499 }
500 
501 static void a2dp_demo_timer_stop(a2dp_media_sending_context_t * context){
502     context->time_audio_data_sent = 0;
503     context->acc_num_missed_samples = 0;
504     context->samples_ready = 0;
505     context->streaming = 1;
506     context->sbc_storage_count = 0;
507     context->sbc_ready_to_send = 0;
508     btstack_run_loop_remove_timer(&context->audio_timer);
509 }
510 
511 static void dump_sbc_configuration(media_codec_configuration_sbc_t * configuration){
512     printf("Received media codec configuration:\n");
513     printf("    - num_channels: %d\n", configuration->num_channels);
514     printf("    - sampling_frequency: %d\n", configuration->sampling_frequency);
515     printf("    - channel_mode: %d\n", configuration->channel_mode);
516     printf("    - block_length: %d\n", configuration->block_length);
517     printf("    - subbands: %d\n", configuration->subbands);
518     printf("    - allocation_method: %d\n", configuration->allocation_method);
519     printf("    - bitpool_value [%d, %d] \n", configuration->min_bitpool_value, configuration->max_bitpool_value);
520 }
521 
522 static void a2dp_source_demo_start_scanning(void){
523     printf("Start scanning...\n");
524     gap_inquiry_start(A2DP_SOURCE_DEMO_INQUIRY_DURATION_1280MS);
525     scan_active = true;
526 }
527 
528 static void hci_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
529     UNUSED(channel);
530     UNUSED(size);
531     if (packet_type != HCI_EVENT_PACKET) return;
532     uint8_t status;
533     UNUSED(status);
534 
535     bd_addr_t address;
536     uint32_t cod;
537 
538     // Service Class: Rendering | Audio, Major Device Class: Audio
539     const uint32_t bluetooth_speaker_cod = 0x200000 | 0x040000 | 0x000400;
540 
541     switch (hci_event_packet_get_type(packet)){
542 #ifndef HAVE_BTSTACK_STDIN
543         case  BTSTACK_EVENT_STATE:
544             if (btstack_event_state_get_state(packet) != HCI_STATE_WORKING) return;
545             a2dp_source_demo_start_scanning();
546             break;
547 #endif
548         case HCI_EVENT_PIN_CODE_REQUEST:
549             printf("Pin code request - using '0000'\n");
550             hci_event_pin_code_request_get_bd_addr(packet, address);
551             gap_pin_code_response(address, "0000");
552             break;
553         case GAP_EVENT_INQUIRY_RESULT:
554             gap_event_inquiry_result_get_bd_addr(packet, address);
555             // print info
556             printf("Device found: %s ",  bd_addr_to_str(address));
557             cod = gap_event_inquiry_result_get_class_of_device(packet);
558             printf("with COD: %06" PRIx32, cod);
559             if (gap_event_inquiry_result_get_rssi_available(packet)){
560                 printf(", rssi %d dBm", (int8_t) gap_event_inquiry_result_get_rssi(packet));
561             }
562             if (gap_event_inquiry_result_get_name_available(packet)){
563                 char name_buffer[240];
564                 int name_len = gap_event_inquiry_result_get_name_len(packet);
565                 memcpy(name_buffer, gap_event_inquiry_result_get_name(packet), name_len);
566                 name_buffer[name_len] = 0;
567                 printf(", name '%s'", name_buffer);
568             }
569             printf("\n");
570             if ((cod & bluetooth_speaker_cod) == bluetooth_speaker_cod){
571                 memcpy(device_addr, address, 6);
572                 printf("Bluetooth speaker detected, trying to connect to %s...\n", bd_addr_to_str(device_addr));
573                 scan_active = false;
574                 gap_inquiry_stop();
575                 a2dp_source_establish_stream(device_addr, &media_tracker.a2dp_cid);
576             }
577             break;
578         case GAP_EVENT_INQUIRY_COMPLETE:
579             if (scan_active){
580                 printf("No Bluetooth speakers found, scanning again...\n");
581                 gap_inquiry_start(A2DP_SOURCE_DEMO_INQUIRY_DURATION_1280MS);
582             }
583             break;
584         default:
585             break;
586     }
587 }
588 
589 static void a2dp_source_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
590     UNUSED(channel);
591     UNUSED(size);
592     uint8_t status;
593     uint8_t local_seid;
594     bd_addr_t address;
595     uint16_t cid;
596 
597     avdtp_channel_mode_t channel_mode;
598     uint8_t allocation_method;
599 
600     if (packet_type != HCI_EVENT_PACKET) return;
601     if (hci_event_packet_get_type(packet) != HCI_EVENT_A2DP_META) return;
602 
603     switch (hci_event_a2dp_meta_get_subevent_code(packet)){
604         case A2DP_SUBEVENT_SIGNALING_CONNECTION_ESTABLISHED:
605             a2dp_subevent_signaling_connection_established_get_bd_addr(packet, address);
606             cid = a2dp_subevent_signaling_connection_established_get_a2dp_cid(packet);
607             status = a2dp_subevent_signaling_connection_established_get_status(packet);
608 
609             if (status != ERROR_CODE_SUCCESS){
610                 printf("A2DP Source: Connection failed, status 0x%02x, cid 0x%02x, a2dp_cid 0x%02x \n", status, cid, media_tracker.a2dp_cid);
611                 media_tracker.a2dp_cid = 0;
612                 break;
613             }
614             media_tracker.a2dp_cid = cid;
615             media_tracker.volume = 32;
616 
617             printf("A2DP Source: Connected to address %s, a2dp cid 0x%02x, local seid 0x%02x.\n", bd_addr_to_str(address), media_tracker.a2dp_cid, media_tracker.local_seid);
618             break;
619 
620         case A2DP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CONFIGURATION:
621             cid  = avdtp_subevent_signaling_media_codec_sbc_configuration_get_avdtp_cid(packet);
622             if (cid != media_tracker.a2dp_cid) return;
623 
624             media_tracker.remote_seid = a2dp_subevent_signaling_media_codec_sbc_configuration_get_remote_seid(packet);
625 
626             sbc_configuration.reconfigure = a2dp_subevent_signaling_media_codec_sbc_configuration_get_reconfigure(packet);
627             sbc_configuration.num_channels = a2dp_subevent_signaling_media_codec_sbc_configuration_get_num_channels(packet);
628             sbc_configuration.sampling_frequency = a2dp_subevent_signaling_media_codec_sbc_configuration_get_sampling_frequency(packet);
629             sbc_configuration.block_length = a2dp_subevent_signaling_media_codec_sbc_configuration_get_block_length(packet);
630             sbc_configuration.subbands = a2dp_subevent_signaling_media_codec_sbc_configuration_get_subbands(packet);
631             sbc_configuration.min_bitpool_value = a2dp_subevent_signaling_media_codec_sbc_configuration_get_min_bitpool_value(packet);
632             sbc_configuration.max_bitpool_value = a2dp_subevent_signaling_media_codec_sbc_configuration_get_max_bitpool_value(packet);
633 
634             channel_mode = (avdtp_channel_mode_t) a2dp_subevent_signaling_media_codec_sbc_configuration_get_channel_mode(packet);
635             allocation_method = a2dp_subevent_signaling_media_codec_sbc_configuration_get_allocation_method(packet);
636 
637             printf("A2DP Source: Received SBC codec configuration, sampling frequency %u, a2dp_cid 0x%02x, local seid 0x%02x, remote seid 0x%02x.\n",
638                 sbc_configuration.sampling_frequency, cid,
639                    a2dp_subevent_signaling_media_codec_sbc_configuration_get_local_seid(packet),
640                    a2dp_subevent_signaling_media_codec_sbc_configuration_get_remote_seid(packet));
641 
642             // Adapt Bluetooth spec definition to SBC Encoder expected input
643             sbc_configuration.allocation_method = (btstack_sbc_allocation_method_t)(allocation_method - 1);
644             switch (channel_mode){
645                 case AVDTP_CHANNEL_MODE_JOINT_STEREO:
646                     sbc_configuration.channel_mode = SBC_CHANNEL_MODE_JOINT_STEREO;
647                     break;
648                 case AVDTP_CHANNEL_MODE_STEREO:
649                     sbc_configuration.channel_mode = SBC_CHANNEL_MODE_STEREO;
650                     break;
651                 case AVDTP_CHANNEL_MODE_DUAL_CHANNEL:
652                     sbc_configuration.channel_mode = SBC_CHANNEL_MODE_DUAL_CHANNEL;
653                     break;
654                 case AVDTP_CHANNEL_MODE_MONO:
655                     sbc_configuration.channel_mode = SBC_CHANNEL_MODE_MONO;
656                     break;
657                 default:
658                     btstack_assert(false);
659                     break;
660             }
661             dump_sbc_configuration(&sbc_configuration);
662 
663             current_sample_rate = sbc_configuration.sampling_frequency;
664             a2dp_demo_hexcmod_configure_sample_rate(current_sample_rate);
665 
666             sbc_encoder_instance = btstack_sbc_encoder_bluedroid_init_instance(&sbc_encoder_state);
667             sbc_encoder_instance->configure(&sbc_encoder_state, SBC_MODE_STANDARD,
668                                             sbc_configuration.block_length, sbc_configuration.subbands,
669                                             sbc_configuration.allocation_method, sbc_configuration.sampling_frequency,
670                                             sbc_configuration.max_bitpool_value,
671                                             sbc_configuration.channel_mode);
672             break;
673 
674         case A2DP_SUBEVENT_SIGNALING_DELAY_REPORTING_CAPABILITY:
675             printf("A2DP Source: remote supports delay report, remote seid %d\n",
676                 avdtp_subevent_signaling_delay_reporting_capability_get_remote_seid(packet));
677             break;
678         case A2DP_SUBEVENT_SIGNALING_CAPABILITIES_DONE:
679             printf("A2DP Source: All capabilities reported, remote seid %d\n",
680                 avdtp_subevent_signaling_capabilities_done_get_remote_seid(packet));
681             break;
682 
683         case A2DP_SUBEVENT_SIGNALING_DELAY_REPORT:
684             printf("A2DP Source: Received delay report of %d.%0d ms, local seid %d\n",
685                 avdtp_subevent_signaling_delay_report_get_delay_100us(packet)/10, avdtp_subevent_signaling_delay_report_get_delay_100us(packet)%10,
686                 avdtp_subevent_signaling_delay_report_get_local_seid(packet));
687             break;
688 
689         case A2DP_SUBEVENT_STREAM_ESTABLISHED:
690             a2dp_subevent_stream_established_get_bd_addr(packet, address);
691             status = a2dp_subevent_stream_established_get_status(packet);
692             if (status != ERROR_CODE_SUCCESS){
693                 printf("A2DP Source: Stream failed, status 0x%02x.\n", status);
694                 break;
695             }
696 
697             local_seid = a2dp_subevent_stream_established_get_local_seid(packet);
698             cid = a2dp_subevent_stream_established_get_a2dp_cid(packet);
699 
700             printf("A2DP Source: Stream established a2dp_cid 0x%02x, local_seid 0x%02x, remote_seid 0x%02x\n", cid, local_seid, a2dp_subevent_stream_established_get_remote_seid(packet));
701 
702             a2dp_demo_hexcmod_configure_sample_rate(current_sample_rate);
703             media_tracker.stream_opened = 1;
704             status = a2dp_source_start_stream(media_tracker.a2dp_cid, media_tracker.local_seid);
705             break;
706 
707         case A2DP_SUBEVENT_STREAM_RECONFIGURED:
708             status = a2dp_subevent_stream_reconfigured_get_status(packet);
709             local_seid = a2dp_subevent_stream_reconfigured_get_local_seid(packet);
710             cid = a2dp_subevent_stream_reconfigured_get_a2dp_cid(packet);
711 
712             if (status != ERROR_CODE_SUCCESS){
713                 printf("A2DP Source: Stream reconfiguration failed, status 0x%02x\n", status);
714                 break;
715             }
716 
717             printf("A2DP Source: Stream reconfigured a2dp_cid 0x%02x, local_seid 0x%02x\n", cid, local_seid);
718             a2dp_demo_hexcmod_configure_sample_rate(new_sample_rate);
719             status = a2dp_source_start_stream(media_tracker.a2dp_cid, media_tracker.local_seid);
720             break;
721 
722         case A2DP_SUBEVENT_STREAM_STARTED:
723             local_seid = a2dp_subevent_stream_started_get_local_seid(packet);
724             cid = a2dp_subevent_stream_started_get_a2dp_cid(packet);
725 
726             play_info.status = AVRCP_PLAYBACK_STATUS_PLAYING;
727             if (media_tracker.avrcp_cid){
728                 avrcp_target_set_now_playing_info(media_tracker.avrcp_cid, &tracks[data_source], sizeof(tracks)/sizeof(avrcp_track_t));
729                 avrcp_target_set_playback_status(media_tracker.avrcp_cid, AVRCP_PLAYBACK_STATUS_PLAYING);
730             }
731             a2dp_demo_timer_start(&media_tracker);
732             printf("A2DP Source: Stream started, a2dp_cid 0x%02x, local_seid 0x%02x\n", cid, local_seid);
733             break;
734 
735         case A2DP_SUBEVENT_STREAMING_CAN_SEND_MEDIA_PACKET_NOW:
736             local_seid = a2dp_subevent_streaming_can_send_media_packet_now_get_local_seid(packet);
737             cid = a2dp_subevent_signaling_media_codec_sbc_configuration_get_a2dp_cid(packet);
738             a2dp_demo_send_media_packet();
739             break;
740 
741         case A2DP_SUBEVENT_STREAM_SUSPENDED:
742             local_seid = a2dp_subevent_stream_suspended_get_local_seid(packet);
743             cid = a2dp_subevent_stream_suspended_get_a2dp_cid(packet);
744 
745             play_info.status = AVRCP_PLAYBACK_STATUS_PAUSED;
746             if (media_tracker.avrcp_cid){
747                 avrcp_target_set_playback_status(media_tracker.avrcp_cid, AVRCP_PLAYBACK_STATUS_PAUSED);
748             }
749             printf("A2DP Source: Stream paused, a2dp_cid 0x%02x, local_seid 0x%02x\n", cid, local_seid);
750 
751             a2dp_demo_timer_stop(&media_tracker);
752             break;
753 
754         case A2DP_SUBEVENT_STREAM_RELEASED:
755             play_info.status = AVRCP_PLAYBACK_STATUS_STOPPED;
756             cid = a2dp_subevent_stream_released_get_a2dp_cid(packet);
757             local_seid = a2dp_subevent_stream_released_get_local_seid(packet);
758 
759             printf("A2DP Source: Stream released, a2dp_cid 0x%02x, local_seid 0x%02x\n", cid, local_seid);
760 
761             if (cid == media_tracker.a2dp_cid) {
762                 media_tracker.stream_opened = 0;
763                 printf("A2DP Source: Stream released.\n");
764             }
765             if (media_tracker.avrcp_cid){
766                 avrcp_target_set_now_playing_info(media_tracker.avrcp_cid, NULL, sizeof(tracks)/sizeof(avrcp_track_t));
767                 avrcp_target_set_playback_status(media_tracker.avrcp_cid, AVRCP_PLAYBACK_STATUS_STOPPED);
768             }
769             a2dp_demo_timer_stop(&media_tracker);
770             break;
771         case A2DP_SUBEVENT_SIGNALING_CONNECTION_RELEASED:
772             cid = a2dp_subevent_signaling_connection_released_get_a2dp_cid(packet);
773             if (cid == media_tracker.a2dp_cid) {
774                 media_tracker.avrcp_cid = 0;
775                 media_tracker.a2dp_cid = 0;
776                 printf("A2DP Source: Signaling released.\n\n");
777             }
778             break;
779         default:
780             break;
781     }
782 }
783 
784 static void avrcp_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
785     UNUSED(channel);
786     UNUSED(size);
787     bd_addr_t event_addr;
788     uint16_t local_cid;
789     uint8_t  status = ERROR_CODE_SUCCESS;
790 
791     if (packet_type != HCI_EVENT_PACKET) return;
792     if (hci_event_packet_get_type(packet) != HCI_EVENT_AVRCP_META) return;
793 
794     switch (packet[2]){
795         case AVRCP_SUBEVENT_CONNECTION_ESTABLISHED:
796             local_cid = avrcp_subevent_connection_established_get_avrcp_cid(packet);
797             status = avrcp_subevent_connection_established_get_status(packet);
798             if (status != ERROR_CODE_SUCCESS){
799                 printf("AVRCP: Connection failed, local cid 0x%02x, status 0x%02x\n", local_cid, status);
800                 return;
801             }
802             media_tracker.avrcp_cid = local_cid;
803             avrcp_subevent_connection_established_get_bd_addr(packet, event_addr);
804 
805             printf("AVRCP: Channel to %s successfully opened, avrcp_cid 0x%02x\n", bd_addr_to_str(event_addr), media_tracker.avrcp_cid);
806 
807             avrcp_target_support_event(media_tracker.avrcp_cid, AVRCP_NOTIFICATION_EVENT_PLAYBACK_STATUS_CHANGED);
808             avrcp_target_support_event(media_tracker.avrcp_cid, AVRCP_NOTIFICATION_EVENT_TRACK_CHANGED);
809             avrcp_target_support_event(media_tracker.avrcp_cid, AVRCP_NOTIFICATION_EVENT_NOW_PLAYING_CONTENT_CHANGED);
810             avrcp_target_set_now_playing_info(media_tracker.avrcp_cid, NULL, sizeof(tracks)/sizeof(avrcp_track_t));
811 
812             printf("Enable Volume Change notification\n");
813             avrcp_controller_enable_notification(media_tracker.avrcp_cid, AVRCP_NOTIFICATION_EVENT_VOLUME_CHANGED);
814             printf("Enable Battery Status Change notification\n");
815             avrcp_controller_enable_notification(media_tracker.avrcp_cid, AVRCP_NOTIFICATION_EVENT_BATT_STATUS_CHANGED);
816             return;
817 
818         case AVRCP_SUBEVENT_CONNECTION_RELEASED:
819             printf("AVRCP Target: Disconnected, avrcp_cid 0x%02x\n", avrcp_subevent_connection_released_get_avrcp_cid(packet));
820             media_tracker.avrcp_cid = 0;
821             return;
822         default:
823             break;
824     }
825 
826     if (status != ERROR_CODE_SUCCESS){
827         printf("Responding to event 0x%02x failed, status 0x%02x\n", packet[2], status);
828     }
829 }
830 
831 static void avrcp_target_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
832     UNUSED(channel);
833     UNUSED(size);
834     uint8_t  status = ERROR_CODE_SUCCESS;
835 
836     if (packet_type != HCI_EVENT_PACKET) return;
837     if (hci_event_packet_get_type(packet) != HCI_EVENT_AVRCP_META) return;
838 
839     bool button_pressed;
840     char const * button_state;
841     avrcp_operation_id_t operation_id;
842 
843     switch (packet[2]){
844         case AVRCP_SUBEVENT_PLAY_STATUS_QUERY:
845             status = avrcp_target_play_status(media_tracker.avrcp_cid, play_info.song_length_ms, play_info.song_position_ms, play_info.status);
846             break;
847         // case AVRCP_SUBEVENT_NOW_PLAYING_INFO_QUERY:
848         //     status = avrcp_target_now_playing_info(avrcp_cid);
849         //     break;
850         case AVRCP_SUBEVENT_OPERATION:
851             operation_id = (avrcp_operation_id_t) avrcp_subevent_operation_get_operation_id(packet);
852             button_pressed = avrcp_subevent_operation_get_button_pressed(packet) > 0;
853             button_state = button_pressed ? "PRESS" : "RELEASE";
854 
855             printf("AVRCP Target: operation %s (%s)\n", avrcp_operation2str(operation_id), button_state);
856 
857             if (!button_pressed){
858                 break;
859             }
860             switch (operation_id) {
861                 case AVRCP_OPERATION_ID_PLAY:
862                     status = a2dp_source_start_stream(media_tracker.a2dp_cid, media_tracker.local_seid);
863                     break;
864                 case AVRCP_OPERATION_ID_PAUSE:
865                     status = a2dp_source_pause_stream(media_tracker.a2dp_cid, media_tracker.local_seid);
866                     break;
867                 case AVRCP_OPERATION_ID_STOP:
868                     status = a2dp_source_disconnect(media_tracker.a2dp_cid);
869                     break;
870                 default:
871                     break;
872             }
873             break;
874         default:
875             break;
876     }
877 
878     if (status != ERROR_CODE_SUCCESS){
879         printf("Responding to event 0x%02x failed, status 0x%02x\n", packet[2], status);
880     }
881 }
882 
883 static void avrcp_controller_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
884     UNUSED(channel);
885     UNUSED(size);
886 
887     if (packet_type != HCI_EVENT_PACKET) return;
888     if (hci_event_packet_get_type(packet) != HCI_EVENT_AVRCP_META) return;
889     if (!media_tracker.avrcp_cid) return;
890 
891     switch (packet[2]){
892         case AVRCP_SUBEVENT_NOTIFICATION_VOLUME_CHANGED:
893             printf("AVRCP Controller: Notification Absolute Volume %d %%\n", avrcp_subevent_notification_volume_changed_get_absolute_volume(packet) * 100 / 127);
894             break;
895         case AVRCP_SUBEVENT_NOTIFICATION_EVENT_BATT_STATUS_CHANGED:
896             // see avrcp_battery_status_t
897             printf("AVRCP Controller: Notification Battery Status 0x%02x\n", avrcp_subevent_notification_event_batt_status_changed_get_battery_status(packet));
898             break;
899         case AVRCP_SUBEVENT_NOTIFICATION_STATE:
900             printf("AVRCP Controller: Notification %s - %s\n",
901                 avrcp_event2str(avrcp_subevent_notification_state_get_event_id(packet)),
902                 avrcp_subevent_notification_state_get_enabled(packet) != 0 ? "enabled" : "disabled");
903             break;
904         default:
905             break;
906     }
907 }
908 
909 #ifdef HAVE_BTSTACK_STDIN
910 static void show_usage(void){
911     bd_addr_t      iut_address;
912     gap_local_bd_addr(iut_address);
913     printf("\n--- Bluetooth  A2DP Source/AVRCP Demo %s ---\n", bd_addr_to_str(iut_address));
914     printf("a      - Scan for Bluetooth speaker and connect\n");
915     printf("b      - A2DP Source create connection to addr %s\n", device_addr_string);
916     printf("B      - A2DP Source disconnect\n");
917     printf("c      - AVRCP create connection to addr %s\n", device_addr_string);
918     printf("C      - AVRCP disconnect\n");
919     printf("D      - delete all link keys\n");
920 
921     printf("x      - start streaming sine\n");
922     if (hxcmod_initialized){
923         printf("z      - start streaming '%s'\n", mod_name);
924     }
925     printf("p      - pause streaming\n");
926     printf("w      - reconfigure stream for 44100 Hz\n");
927     printf("e      - reconfigure stream for 48000 Hz\n");
928     printf("t      - volume up\n");
929     printf("T      - volume down\n");
930     printf("v      - volume up (via set absolute volume)\n");
931     printf("V      - volume down (via set absolute volume)\n");
932 
933     printf("---\n");
934 }
935 
936 static void stdin_process(char cmd){
937     uint8_t status = ERROR_CODE_SUCCESS;
938     switch (cmd){
939         case 'a':
940             a2dp_source_demo_start_scanning();
941             break;
942         case 'b':
943             status = a2dp_source_establish_stream(device_addr, &media_tracker.a2dp_cid);
944             printf("%c - Create A2DP Source connection to addr %s, cid 0x%02x.\n", cmd, bd_addr_to_str(device_addr), media_tracker.a2dp_cid);
945             break;
946         case 'B':
947             printf("%c - A2DP Source Disconnect from cid 0x%2x\n", cmd, media_tracker.a2dp_cid);
948             status = a2dp_source_disconnect(media_tracker.a2dp_cid);
949             break;
950         case 'c':
951             printf("%c - Create AVRCP connection to addr %s.\n", cmd, bd_addr_to_str(device_addr));
952             status = avrcp_connect(device_addr, &media_tracker.avrcp_cid);
953             break;
954         case 'C':
955             printf("%c - AVRCP disconnect\n", cmd);
956             status = avrcp_disconnect(media_tracker.avrcp_cid);
957             break;
958         case 'D':
959             printf("Deleting all link keys\n");
960             gap_delete_all_link_keys();
961             break;
962         case '\n':
963         case '\r':
964             break;
965 
966         case 't':
967             printf(" - volume up\n");
968             status = avrcp_controller_volume_up(media_tracker.avrcp_cid);
969             break;
970         case 'T':
971             printf(" - volume down\n");
972             status = avrcp_controller_volume_down(media_tracker.avrcp_cid);
973             break;
974 
975         case 'v':
976             if (media_tracker.volume > 117){
977                 media_tracker.volume = 127;
978             } else {
979                 media_tracker.volume += 10;
980             }
981             printf(" - volume up (via set absolute volume) %d%% (%d)\n",  media_tracker.volume * 100 / 127,  media_tracker.volume);
982             status = avrcp_controller_set_absolute_volume(media_tracker.avrcp_cid, media_tracker.volume);
983             break;
984         case 'V':
985             if (media_tracker.volume < 10){
986                 media_tracker.volume = 0;
987             } else {
988                 media_tracker.volume -= 10;
989             }
990             printf(" - volume down (via set absolute volume) %d%% (%d)\n",  media_tracker.volume * 100 / 127,  media_tracker.volume);
991             status = avrcp_controller_set_absolute_volume(media_tracker.avrcp_cid, media_tracker.volume);
992             break;
993 
994         case 'x':
995             if (media_tracker.avrcp_cid){
996                 avrcp_target_set_now_playing_info(media_tracker.avrcp_cid, &tracks[data_source], sizeof(tracks)/sizeof(avrcp_track_t));
997             }
998             printf("%c - Play sine.\n", cmd);
999             data_source = STREAM_SINE;
1000             if (!media_tracker.stream_opened) break;
1001             status = a2dp_source_start_stream(media_tracker.a2dp_cid, media_tracker.local_seid);
1002             break;
1003         case 'z':
1004             if (media_tracker.avrcp_cid){
1005                 avrcp_target_set_now_playing_info(media_tracker.avrcp_cid, &tracks[data_source], sizeof(tracks)/sizeof(avrcp_track_t));
1006             }
1007             printf("%c - Play mod.\n", cmd);
1008             data_source = STREAM_MOD;
1009             if (!media_tracker.stream_opened) break;
1010             status = a2dp_source_start_stream(media_tracker.a2dp_cid, media_tracker.local_seid);
1011             break;
1012 
1013         case 'p':
1014             if (!media_tracker.stream_opened) break;
1015             printf("%c - Pause stream.\n", cmd);
1016             status = a2dp_source_pause_stream(media_tracker.a2dp_cid, media_tracker.local_seid);
1017             break;
1018 
1019         case 'w':
1020             if (!media_tracker.stream_opened) break;
1021             if (play_info.status == AVRCP_PLAYBACK_STATUS_PLAYING){
1022                 printf("Stream cannot be reconfigured while playing, please pause stream first\n");
1023                 break;
1024             }
1025             new_sample_rate = 44100;
1026             if (current_sample_rate == new_sample_rate){
1027                 printf("%c - Stream already configured for %d Hz.\n", cmd, new_sample_rate);
1028             } else {
1029                 printf("%c - Reconfigure for %d Hz.\n", cmd, new_sample_rate);
1030                 status = a2dp_source_reconfigure_stream_sampling_frequency(media_tracker.a2dp_cid, new_sample_rate);
1031             }
1032             break;
1033 
1034         case 'e':
1035             if (!media_tracker.stream_opened) break;
1036             if (play_info.status == AVRCP_PLAYBACK_STATUS_PLAYING){
1037                 printf("Stream cannot be reconfigured while playing, please pause stream first\n");
1038                 break;
1039             }
1040             new_sample_rate = 48000;
1041             if (current_sample_rate == new_sample_rate){
1042                 printf("%c - Stream already configured for %d Hz.\n", cmd, new_sample_rate);
1043             } else {
1044                 printf("%c - Reconfigure for %d Hz.\n", cmd, new_sample_rate);
1045                 status = a2dp_source_reconfigure_stream_sampling_frequency(media_tracker.a2dp_cid, new_sample_rate);
1046             }
1047             break;
1048 
1049         default:
1050             show_usage();
1051             return;
1052     }
1053     if (status != ERROR_CODE_SUCCESS){
1054         printf("Could not perform command \'%c\', status 0x%02x\n", cmd, status);
1055     }
1056 }
1057 #endif
1058 
1059 
1060 int btstack_main(int argc, const char * argv[]);
1061 int btstack_main(int argc, const char * argv[]){
1062     (void)argc;
1063     (void)argv;
1064 
1065     int err = a2dp_source_and_avrcp_services_init();
1066     if (err) return err;
1067     // turn on!
1068     hci_power_control(HCI_POWER_ON);
1069     return 0;
1070 }
1071 /* EXAMPLE_END */
1072