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