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