xref: /btstack/example/a2dp_source_demo.c (revision ec3d71e3557bf886c8e08b6a537dab30fb67333b)
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 
67 #include "classic/btstack_sbc.h"
68 
69 #include "hxcmod.h"
70 #include "mods/mod.h"
71 
72 
73 #define AVRCP_BROWSING_ENABLED 0
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  connected;
93     uint8_t  stream_opened;
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 #ifdef HAVE_BTSTACK_STDIN
142 // pts:             static const char * device_addr_string = "00:1B:DC:08:0A:A5";
143 // mac 2013:        static const char * device_addr_string = "84:38:35:65:d1:15";
144 // phone 2013:      static const char * device_addr_string = "D8:BB:2C:DF:F0:F2";
145 // Minijambox:
146 // 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:
150 static const char * device_addr_string = "00:1A:7D:DA:71:0A";
151 // Sony MDR-ZX330BT static const char * device_addr_string = "00:18:09:28:50:18";
152 #endif
153 
154 static bd_addr_t device_addr;
155 static uint8_t sdp_a2dp_source_service_buffer[150];
156 static uint8_t sdp_avrcp_target_service_buffer[200];
157 static avdtp_media_codec_configuration_sbc_t sbc_configuration;
158 static btstack_sbc_encoder_state_t sbc_encoder_state;
159 
160 static uint8_t media_sbc_codec_configuration[4];
161 static a2dp_media_sending_context_t media_tracker;
162 
163 static uint16_t avrcp_cid;
164 static uint8_t  avrcp_connected;
165 
166 static stream_data_source_t data_source;
167 
168 static int sine_phase;
169 
170 static int hxcmod_initialized;
171 static modcontext mod_context;
172 static tracker_buffer_state trkbuf;
173 
174 
175 /* AVRCP Target context START */
176 static const uint8_t subunit_info[] = {
177     0,0,0,0,
178     1,1,1,1,
179     2,2,2,2,
180     3,3,3,3,
181     4,4,4,4,
182     5,5,5,5,
183     6,6,6,6,
184     7,7,7,7
185 };
186 
187 static uint32_t company_id = 0x112233;
188 static uint8_t companies_num = 1;
189 static uint8_t companies[] = {
190     0x00, 0x19, 0x58 //BT SIG registered CompanyID
191 };
192 
193 static uint8_t events_num = 13;
194 static uint8_t events[] = {
195     AVRCP_NOTIFICATION_EVENT_PLAYBACK_STATUS_CHANGED,
196     AVRCP_NOTIFICATION_EVENT_TRACK_CHANGED,
197     AVRCP_NOTIFICATION_EVENT_TRACK_REACHED_END,
198     AVRCP_NOTIFICATION_EVENT_TRACK_REACHED_START,
199     AVRCP_NOTIFICATION_EVENT_PLAYBACK_POS_CHANGED,
200     AVRCP_NOTIFICATION_EVENT_BATT_STATUS_CHANGED,
201     AVRCP_NOTIFICATION_EVENT_SYSTEM_STATUS_CHANGED,
202     AVRCP_NOTIFICATION_EVENT_PLAYER_APPLICATION_SETTING_CHANGED,
203     AVRCP_NOTIFICATION_EVENT_NOW_PLAYING_CONTENT_CHANGED,
204     AVRCP_NOTIFICATION_EVENT_AVAILABLE_PLAYERS_CHANGED,
205     AVRCP_NOTIFICATION_EVENT_ADDRESSED_PLAYER_CHANGED,
206     AVRCP_NOTIFICATION_EVENT_UIDS_CHANGED,
207     AVRCP_NOTIFICATION_EVENT_VOLUME_CHANGED
208 };
209 
210 typedef struct {
211     uint8_t track_id[8];
212     uint32_t song_length_ms;
213     avrcp_playback_status_t status;
214     uint32_t song_position_ms; // 0xFFFFFFFF if not supported
215 } avrcp_play_status_info_t;
216 
217 // python -c "print('a'*512)"
218 static const char title[] = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
219 
220 avrcp_track_t tracks[] = {
221     {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, 1, "Sine", "Generated", "AVRCP Demo", "monotone", 12345},
222     {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02}, 2, "Nao-deceased", "Decease", "AVRCP Demo", "vivid", 12345},
223     {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03}, 3, (char *)title, "Decease", "AVRCP Demo", "vivid", 12345},
224 };
225 int current_track_index;
226 avrcp_play_status_info_t play_info;
227 
228 /* AVRCP Target context END */
229 
230 /* @section Main Application Setup
231  *
232  * @text The Listing MainConfiguration shows how to setup AD2P Source and AVRCP Target services.
233  */
234 
235 /* LISTING_START(MainConfiguration): Setup Audio Source and AVRCP Target services */
236 static void a2dp_source_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t * event, uint16_t event_size);
237 static void avrcp_target_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     // Register for HCI events.
244     hci_event_callback_registration.callback = &a2dp_source_packet_handler;
245     hci_add_event_handler(&hci_event_callback_registration);
246 
247     l2cap_init();
248     // Initialize  A2DP Source.
249     a2dp_source_init();
250     a2dp_source_register_packet_handler(&a2dp_source_packet_handler);
251 
252     // Create stream endpoint.
253     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));
254     if (!local_stream_endpoint){
255         printf(" A2DP Source demo: not enough memory to create local stream endpoint\n");
256         return 1;
257     }
258     media_tracker.local_seid = avdtp_local_seid(local_stream_endpoint);
259 
260     // Initialize AVRCP Target.
261     avrcp_target_init();
262     avrcp_target_register_packet_handler(&avrcp_target_packet_handler);
263 
264     // Initialize SDP,
265     sdp_init();
266 
267     // Create  A2DP Source service record and register it with SDP.
268     memset(sdp_a2dp_source_service_buffer, 0, sizeof(sdp_a2dp_source_service_buffer));
269     a2dp_source_create_sdp_record(sdp_a2dp_source_service_buffer, 0x10002, 1, NULL, NULL);
270     sdp_register_service(sdp_a2dp_source_service_buffer);
271 
272     // Create AVRCP target service record and register it with SDP.
273     memset(sdp_avrcp_target_service_buffer, 0, sizeof(sdp_avrcp_target_service_buffer));
274     avrcp_target_create_sdp_record(sdp_avrcp_target_service_buffer, 0x10001, AVRCP_BROWSING_ENABLED, 1, NULL, NULL);
275     sdp_register_service(sdp_avrcp_target_service_buffer);
276 
277     // Set local name with a template Bluetooth address, that will be automatically
278     // replaced with a actual address once it is available, i.e. when BTstack boots
279     // up and starts talking to a Bluetooth module.
280     gap_set_local_name(" A2DP Source Demo 00:00:00:00:00:00");
281     gap_discoverable_control(1);
282     gap_set_class_of_device(0x200408);
283 
284     hxcmod_initialized = hxcmod_init(&mod_context);
285     if (hxcmod_initialized){
286         hxcmod_setcfg(&mod_context, A2DP_SAMPLE_RATE, 16, 1, 1, 1);
287         hxcmod_load(&mod_context, (void *) &mod_data, mod_len);
288         printf("loaded mod '%s', size %u\n", mod_name, mod_len);
289     }
290     // Parse human readable Bluetooth address.
291     sscanf_bd_addr(device_addr_string, device_addr);
292 
293 #ifdef HAVE_BTSTACK_STDIN
294     btstack_stdin_setup(stdin_process);
295 #endif
296     return 0;
297 }
298 /* LISTING_END */
299 
300 static void a2dp_demo_send_media_packet(void){
301     int num_bytes_in_frame = btstack_sbc_encoder_sbc_buffer_length();
302     int bytes_in_storage = media_tracker.sbc_storage_count;
303     uint8_t num_frames = bytes_in_storage / num_bytes_in_frame;
304     a2dp_source_stream_send_media_payload(media_tracker.a2dp_cid, media_tracker.local_seid, media_tracker.sbc_storage, bytes_in_storage, num_frames, 0);
305     media_tracker.sbc_storage_count = 0;
306     media_tracker.sbc_ready_to_send = 0;
307 }
308 
309 static void produce_sine_audio(int16_t * pcm_buffer, int num_samples_to_write){
310     int count;
311     for (count = 0; count < num_samples_to_write ; count++){
312         pcm_buffer[count * 2]     = sine_int16[sine_phase];
313         pcm_buffer[count * 2 + 1] = sine_int16[sine_phase];
314         sine_phase++;
315         if (sine_phase >= TABLE_SIZE_441HZ){
316             sine_phase -= TABLE_SIZE_441HZ;
317         }
318     }
319 }
320 
321 static void produce_mod_audio(int16_t * pcm_buffer, int num_samples_to_write){
322     hxcmod_fillbuffer(&mod_context, (unsigned short *) &pcm_buffer[0], num_samples_to_write, &trkbuf);
323 }
324 
325 static void produce_audio(int16_t * pcm_buffer, int num_samples){
326     switch (data_source){
327         case STREAM_SINE:
328             produce_sine_audio(pcm_buffer, num_samples);
329             break;
330         case STREAM_MOD:
331             produce_mod_audio(pcm_buffer, num_samples);
332             break;
333         default:
334             break;
335     }
336 }
337 
338 static int a2dp_demo_fill_sbc_audio_buffer(a2dp_media_sending_context_t * context){
339     // perform sbc encodin
340     int total_num_bytes_read = 0;
341     unsigned int num_audio_samples_per_sbc_buffer = btstack_sbc_encoder_num_audio_frames();
342     while (context->samples_ready >= num_audio_samples_per_sbc_buffer
343         && (context->max_media_payload_size - context->sbc_storage_count) >= btstack_sbc_encoder_sbc_buffer_length()){
344 
345         int16_t pcm_frame[256*NUM_CHANNELS];
346 
347         produce_audio(pcm_frame, num_audio_samples_per_sbc_buffer);
348         btstack_sbc_encoder_process_data(pcm_frame);
349 
350         uint16_t sbc_frame_size = btstack_sbc_encoder_sbc_buffer_length();
351         uint8_t * sbc_frame = btstack_sbc_encoder_sbc_buffer();
352 
353         total_num_bytes_read += num_audio_samples_per_sbc_buffer;
354         memcpy(&context->sbc_storage[context->sbc_storage_count], sbc_frame, sbc_frame_size);
355         context->sbc_storage_count += sbc_frame_size;
356         context->samples_ready -= num_audio_samples_per_sbc_buffer;
357     }
358     return total_num_bytes_read;
359 }
360 
361 static void a2dp_demo_audio_timeout_handler(btstack_timer_source_t * timer){
362     a2dp_media_sending_context_t * context = (a2dp_media_sending_context_t *) btstack_run_loop_get_timer_context(timer);
363     btstack_run_loop_set_timer(&context->audio_timer, AUDIO_TIMEOUT_MS);
364     btstack_run_loop_add_timer(&context->audio_timer);
365     uint32_t now = btstack_run_loop_get_time_ms();
366 
367     uint32_t update_period_ms = AUDIO_TIMEOUT_MS;
368     if (context->time_audio_data_sent > 0){
369         update_period_ms = now - context->time_audio_data_sent;
370     }
371 
372     uint32_t num_samples = (update_period_ms * A2DP_SAMPLE_RATE) / 1000;
373     context->acc_num_missed_samples += (update_period_ms * A2DP_SAMPLE_RATE) % 1000;
374 
375     while (context->acc_num_missed_samples >= 1000){
376         num_samples++;
377         context->acc_num_missed_samples -= 1000;
378     }
379     context->time_audio_data_sent = now;
380     context->samples_ready += num_samples;
381 
382     if (context->sbc_ready_to_send) return;
383 
384     a2dp_demo_fill_sbc_audio_buffer(context);
385 
386     if ((context->sbc_storage_count + btstack_sbc_encoder_sbc_buffer_length()) > context->max_media_payload_size){
387         // schedule sending
388         context->sbc_ready_to_send = 1;
389         a2dp_source_stream_endpoint_request_can_send_now(context->a2dp_cid, context->local_seid);
390     }
391 }
392 
393 static void a2dp_demo_timer_start(a2dp_media_sending_context_t * context){
394     context->max_media_payload_size = btstack_min(a2dp_max_media_payload_size(context->a2dp_cid, context->local_seid), SBC_STORAGE_SIZE);
395     context->sbc_storage_count = 0;
396     context->sbc_ready_to_send = 0;
397     context->streaming = 1;
398     btstack_run_loop_remove_timer(&context->audio_timer);
399     btstack_run_loop_set_timer_handler(&context->audio_timer, a2dp_demo_audio_timeout_handler);
400     btstack_run_loop_set_timer_context(&context->audio_timer, context);
401     btstack_run_loop_set_timer(&context->audio_timer, AUDIO_TIMEOUT_MS);
402     btstack_run_loop_add_timer(&context->audio_timer);
403 }
404 
405 static void a2dp_demo_timer_stop(a2dp_media_sending_context_t * context){
406     context->time_audio_data_sent = 0;
407     context->acc_num_missed_samples = 0;
408     context->samples_ready = 0;
409     context->streaming = 1;
410     context->sbc_storage_count = 0;
411     context->sbc_ready_to_send = 0;
412     btstack_run_loop_remove_timer(&context->audio_timer);
413 }
414 
415 static void a2dp_source_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
416     UNUSED(channel);
417     UNUSED(size);
418     uint8_t status;
419     uint8_t local_seid;
420     bd_addr_t address;
421     uint16_t cid;
422 
423     if (packet_type != HCI_EVENT_PACKET) return;
424 
425 #ifndef HAVE_BTSTACK_STDIN
426     if (hci_event_packet_get_type(packet) == BTSTACK_EVENT_STATE){
427         if (btstack_event_state_get_state(packet) != HCI_STATE_WORKING) return;
428         printf("Create AVDTP Source connection to addr %s.\n", bd_addr_to_str(device_addr));
429         status = a2dp_source_establish_stream(device_addr, media_tracker.local_seid, &media_tracker.a2dp_cid);
430         if (status != ERROR_CODE_SUCCESS){
431             printf("Could not perform command, status 0x%2x\n", status);
432         }
433         return;
434     }
435 #endif
436 
437     if (hci_event_packet_get_type(packet) != HCI_EVENT_A2DP_META) return;
438     switch (packet[2]){
439         case A2DP_SUBEVENT_SIGNALING_CONNECTION_ESTABLISHED:
440             a2dp_subevent_signaling_connection_established_get_bd_addr(packet, address);
441             cid = a2dp_subevent_signaling_connection_established_get_a2dp_cid(packet);
442 
443             if (!media_tracker.a2dp_cid){
444                 media_tracker.a2dp_cid = cid;
445             } else if (cid != media_tracker.a2dp_cid){
446                 printf(" A2DP Source demo: Connection failed, received cid 0x%02x, expected cid 0x%02x\n", cid, media_tracker.a2dp_cid);
447                 break;
448             }
449             printf(" A2DP Source demo: Connected to address %s, a2dp cid 0x%02x.\n", bd_addr_to_str(address), media_tracker.a2dp_cid);
450             break;
451 
452          case A2DP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CONFIGURATION:{
453             printf(" A2DP Source demo: Received SBC codec configuration.\n");
454             sbc_configuration.reconfigure = a2dp_subevent_signaling_media_codec_sbc_configuration_get_reconfigure(packet);
455             sbc_configuration.num_channels = a2dp_subevent_signaling_media_codec_sbc_configuration_get_num_channels(packet);
456             sbc_configuration.sampling_frequency = a2dp_subevent_signaling_media_codec_sbc_configuration_get_sampling_frequency(packet);
457             sbc_configuration.channel_mode = a2dp_subevent_signaling_media_codec_sbc_configuration_get_channel_mode(packet);
458             sbc_configuration.block_length = a2dp_subevent_signaling_media_codec_sbc_configuration_get_block_length(packet);
459             sbc_configuration.subbands = a2dp_subevent_signaling_media_codec_sbc_configuration_get_subbands(packet);
460             sbc_configuration.allocation_method = a2dp_subevent_signaling_media_codec_sbc_configuration_get_allocation_method(packet);
461             sbc_configuration.min_bitpool_value = a2dp_subevent_signaling_media_codec_sbc_configuration_get_min_bitpool_value(packet);
462             sbc_configuration.max_bitpool_value = a2dp_subevent_signaling_media_codec_sbc_configuration_get_max_bitpool_value(packet);
463             sbc_configuration.frames_per_buffer = sbc_configuration.subbands * sbc_configuration.block_length;
464 
465             btstack_sbc_encoder_init(&sbc_encoder_state, SBC_MODE_STANDARD,
466                 sbc_configuration.block_length, sbc_configuration.subbands,
467                 sbc_configuration.allocation_method, sbc_configuration.sampling_frequency,
468                 sbc_configuration.max_bitpool_value,
469                 sbc_configuration.channel_mode);
470 
471             // status = a2dp_source_establish_stream(device_addr, media_tracker.local_seid, &media_tracker.a2dp_cid);
472             // if (status != ERROR_CODE_SUCCESS){
473             //     printf("Could not perform command, status 0x%2x\n", status);
474             // }
475             break;
476         }
477 
478         case A2DP_SUBEVENT_STREAM_ESTABLISHED:
479             a2dp_subevent_stream_established_get_bd_addr(packet, address);
480             status = a2dp_subevent_stream_established_get_status(packet);
481             if (status){
482                 printf(" A2DP Source demo: Stream failed, status 0x%02x.\n", status);
483                 break;
484             }
485             local_seid = a2dp_subevent_stream_established_get_local_seid(packet);
486             if (local_seid != media_tracker.local_seid){
487                 printf(" A2DP Source demo: Stream failed, wrong local seid %d, expected %d.\n", local_seid, media_tracker.local_seid);
488                 break;
489             }
490             printf(" A2DP Source demo: Stream established, address %s, a2dp cid 0x%02x, local seid %d, remote seid %d.\n", bd_addr_to_str(address),
491                 media_tracker.a2dp_cid, media_tracker.local_seid, a2dp_subevent_stream_established_get_remote_seid(packet));
492             printf(" A2DP Source demo: Start playing mod, a2dp cid 0x%02x.\n", media_tracker.a2dp_cid);
493             media_tracker.stream_opened = 1;
494             data_source = STREAM_MOD;
495             status = a2dp_source_start_stream(media_tracker.a2dp_cid, media_tracker.local_seid);
496             break;
497 
498         case A2DP_SUBEVENT_STREAM_STARTED:
499             play_info.status = AVRCP_PLAYBACK_STATUS_PLAYING;
500             if (avrcp_connected){
501                 avrcp_target_set_now_playing_info(avrcp_cid, &tracks[data_source], sizeof(tracks)/sizeof(avrcp_track_t));
502                 avrcp_target_set_playback_status(avrcp_cid, AVRCP_PLAYBACK_STATUS_PLAYING);
503             }
504             a2dp_demo_timer_start(&media_tracker);
505             printf(" A2DP Source demo: Stream started.\n");
506             break;
507 
508         case A2DP_SUBEVENT_STREAMING_CAN_SEND_MEDIA_PACKET_NOW:
509             a2dp_demo_send_media_packet();
510             break;
511 
512         case A2DP_SUBEVENT_STREAM_SUSPENDED:
513             play_info.status = AVRCP_PLAYBACK_STATUS_PAUSED;
514             if (avrcp_connected){
515                 avrcp_target_set_playback_status(avrcp_cid, AVRCP_PLAYBACK_STATUS_PAUSED);
516             }
517             printf(" A2DP Source demo: Stream paused.\n");
518             a2dp_demo_timer_stop(&media_tracker);
519             break;
520 
521         case A2DP_SUBEVENT_STREAM_RELEASED:
522             play_info.status = AVRCP_PLAYBACK_STATUS_STOPPED;
523             cid = a2dp_subevent_stream_released_get_a2dp_cid(packet);
524             if (cid == media_tracker.a2dp_cid) {
525                 media_tracker.stream_opened = 0;
526                 printf(" A2DP Source demo: Stream released.\n");
527             }
528             if (avrcp_connected){
529                 avrcp_target_set_now_playing_info(avrcp_cid, NULL, sizeof(tracks)/sizeof(avrcp_track_t));
530                 avrcp_target_set_playback_status(avrcp_cid, AVRCP_PLAYBACK_STATUS_STOPPED);
531             }
532             a2dp_demo_timer_stop(&media_tracker);
533             break;
534         case A2DP_SUBEVENT_SIGNALING_CONNECTION_RELEASED:
535             cid = a2dp_subevent_signaling_connection_released_get_a2dp_cid(packet);
536             if (cid == media_tracker.a2dp_cid) {
537                 media_tracker.connected = 0;
538                 media_tracker.a2dp_cid = 0;
539                 printf(" A2DP Source demo: Signaling released.\n\n");
540             }
541             break;
542         default:
543             break;
544     }
545 }
546 
547 static void avrcp_target_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
548     UNUSED(channel);
549     UNUSED(size);
550     bd_addr_t event_addr;
551     uint16_t local_cid;
552     uint8_t  status = ERROR_CODE_SUCCESS;
553 
554     if (packet_type != HCI_EVENT_PACKET) return;
555     if (hci_event_packet_get_type(packet) != HCI_EVENT_AVRCP_META) return;
556 
557     switch (packet[2]){
558         case AVRCP_SUBEVENT_CONNECTION_ESTABLISHED: {
559             local_cid = avrcp_subevent_connection_established_get_avrcp_cid(packet);
560             // if (avrcp_cid != 0 && avrcp_cid != local_cid) {
561             //     printf("AVRCP Source demo: Connection failed, expected 0x%02X l2cap cid, received 0x%02X\n", avrcp_cid, local_cid);
562             //     return;
563             // }
564             // if (avrcp_cid != local_cid) break;
565 
566             status = avrcp_subevent_connection_established_get_status(packet);
567             if (status != ERROR_CODE_SUCCESS){
568                 printf("AVRCP Source demo: Connection failed, status 0x%02x\n", status);
569                 return;
570             }
571             avrcp_connected = 1;
572             avrcp_cid = local_cid;
573             avrcp_subevent_connection_established_get_bd_addr(packet, event_addr);
574             printf("AVRCP Source demo: Connected to %s, avrcp_cid 0x%02x\n", bd_addr_to_str(event_addr), local_cid);
575 
576             avrcp_target_set_now_playing_info(avrcp_cid, NULL, sizeof(tracks)/sizeof(avrcp_track_t));
577             avrcp_target_set_unit_info(avrcp_cid, AVRCP_SUBUNIT_TYPE_AUDIO, company_id);
578             avrcp_target_set_subunit_info(avrcp_cid, AVRCP_SUBUNIT_TYPE_AUDIO, (uint8_t *)subunit_info, sizeof(subunit_info));
579             return;
580         }
581 
582         case AVRCP_SUBEVENT_EVENT_IDS_QUERY:
583             status = avrcp_target_supported_events(avrcp_cid, events_num, events, sizeof(events));
584             break;
585         case AVRCP_SUBEVENT_COMPANY_IDS_QUERY:
586             status = avrcp_target_supported_companies(avrcp_cid, companies_num, companies, sizeof(companies));
587             break;
588         case AVRCP_SUBEVENT_PLAY_STATUS_QUERY:
589             status = avrcp_target_play_status(avrcp_cid, play_info.song_length_ms, play_info.song_position_ms, play_info.status);
590             break;
591         // case AVRCP_SUBEVENT_NOW_PLAYING_INFO_QUERY:
592         //     status = avrcp_target_now_playing_info(avrcp_cid);
593         //     break;
594         case AVRCP_SUBEVENT_OPERATION:{
595             avrcp_operation_id_t operation_id = avrcp_subevent_operation_get_operation_id(packet);
596             if (!media_tracker.connected) break;
597             switch (operation_id){
598                 case AVRCP_OPERATION_ID_PLAY:
599                     printf("AVRCP Source demo: PLAY\n");
600                     status = a2dp_source_start_stream(media_tracker.a2dp_cid, media_tracker.local_seid);
601                     break;
602                 case AVRCP_OPERATION_ID_PAUSE:
603                     printf("AVRCP Source demo: PAUSE\n");
604                     status = a2dp_source_pause_stream(media_tracker.a2dp_cid, media_tracker.local_seid);
605                     break;
606                 case AVRCP_OPERATION_ID_STOP:
607                     printf("AVRCP Source demo: STOP\n");
608                     status = a2dp_source_disconnect(media_tracker.a2dp_cid);
609                     break;
610                 default:
611                     return;
612             }
613             break;
614         }
615         case AVRCP_SUBEVENT_CONNECTION_RELEASED:
616             printf("AVRCP Source demo: Disconnected, avrcp_cid 0x%02x\n", avrcp_subevent_connection_released_get_avrcp_cid(packet));
617             avrcp_cid = 0;
618             avrcp_connected = 0;
619             return;
620         default:
621             break;
622     }
623 
624     if (status != ERROR_CODE_SUCCESS){
625         printf("Responding to event 0x%02x failed with status 0x%02x\n", packet[2], status);
626     }
627 }
628 
629 #ifdef HAVE_BTSTACK_STDIN
630 static void show_usage(void){
631     bd_addr_t      iut_address;
632     gap_local_bd_addr(iut_address);
633     printf("\n--- Bluetooth  A2DP Source/AVRCP Target Demo %s ---\n", bd_addr_to_str(iut_address));
634     printf("b      - AVDTP Source create  connection to addr %s\n", device_addr_string);
635     printf("B      - AVDTP Source disconnect\n");
636     printf("c      - AVRCP Target create connection to addr %s\n", device_addr_string);
637     printf("C      - AVRCP Target disconnect\n");
638     printf("0      - AVRCP reset now playing info\n");
639 
640     printf("x      - start streaming sine\n");
641     if (hxcmod_initialized){
642         printf("z      - start streaming '%s'\n", mod_name);
643     }
644     printf("p      - pause streaming\n");
645 
646     printf("\n--- Bluetooth  AVRCP Target Commands %s ---\n", bd_addr_to_str(iut_address));
647     printf("---\n");
648 }
649 
650 static void stdin_process(char cmd){
651     uint8_t status = ERROR_CODE_SUCCESS;
652     switch (cmd){
653         case 'b':
654             status = a2dp_source_establish_stream(device_addr, media_tracker.local_seid, &media_tracker.a2dp_cid);
655             printf(" - Create AVDTP Source connection to addr %s, cid 0x%02x.\n", bd_addr_to_str(device_addr), media_tracker.a2dp_cid);
656             break;
657         case 'B':
658             printf(" - AVDTP Source Disconnect from cid 0x%2x\n", media_tracker.a2dp_cid);
659             status = a2dp_source_disconnect(media_tracker.a2dp_cid);
660             break;
661         case 'c':
662             printf(" - Create AVRCP Target connection to addr %s.\n", bd_addr_to_str(device_addr));
663             status = avrcp_target_connect(device_addr, &avrcp_cid);
664             break;
665         case 'C':
666             printf(" - AVRCP Target disconnect\n");
667             status = avrcp_target_disconnect(avrcp_cid);
668             break;
669 
670         case '\n':
671         case '\r':
672             break;
673 
674         case 't':
675             printf("STREAM_PTS_TEST.\n");
676             data_source = STREAM_PTS_TEST;
677             if (avrcp_connected){
678                 avrcp_target_set_now_playing_info(avrcp_cid, &tracks[data_source], sizeof(tracks)/sizeof(avrcp_track_t));
679             }
680             if (!media_tracker.stream_opened) break;
681             status = a2dp_source_start_stream(media_tracker.a2dp_cid, media_tracker.local_seid);
682             break;
683 
684         case 'x':
685             if (avrcp_connected){
686                 avrcp_target_set_now_playing_info(avrcp_cid, &tracks[data_source], sizeof(tracks)/sizeof(avrcp_track_t));
687             }
688             printf("Playing sine.\n");
689             data_source = STREAM_SINE;
690             if (!media_tracker.stream_opened) break;
691             status = a2dp_source_start_stream(media_tracker.a2dp_cid, media_tracker.local_seid);
692             break;
693         case 'z':
694             if (avrcp_connected){
695                 avrcp_target_set_now_playing_info(avrcp_cid, &tracks[data_source], sizeof(tracks)/sizeof(avrcp_track_t));
696             }
697             printf("Playing mod.\n");
698             data_source = STREAM_MOD;
699             if (!media_tracker.stream_opened) break;
700             status = a2dp_source_start_stream(media_tracker.a2dp_cid, media_tracker.local_seid);
701             break;
702         case 'p':
703             if (!media_tracker.connected) break;
704             printf("Pause stream.\n");
705             status = a2dp_source_pause_stream(media_tracker.a2dp_cid, media_tracker.local_seid);
706             break;
707         case '0':
708             if (avrcp_connected){
709                 avrcp_target_set_now_playing_info(avrcp_cid, NULL, sizeof(tracks)/sizeof(avrcp_track_t));
710                 printf("Reset now playing info\n");
711             }
712             break;
713         default:
714             show_usage();
715             return;
716     }
717     if (status != ERROR_CODE_SUCCESS){
718         printf("Could not perform command, status 0x%2x\n", status);
719     }
720 }
721 #endif
722 
723 
724 int btstack_main(int argc, const char * argv[]);
725 int btstack_main(int argc, const char * argv[]){
726     (void)argc;
727     (void)argv;
728 
729     int err = a2dp_source_and_avrcp_services_init();
730     if (err) return err;
731     // turn on!
732     hci_power_control(HCI_POWER_ON);
733     return 0;
734 }
735 /* EXAMPLE_END */
736