xref: /btstack/example/a2dp_source_demo.c (revision a62edf8ad2ecffe78e81a384139d12bb4d45f94f)
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 // mac 2013:        static const char * device_addr_string = "84:38:35:65:d1:15";
143 // phone 2013:      static const char * device_addr_string = "D8:BB:2C:DF:F0:F2";
144 // Minijambox:
145 static const char * device_addr_string = "00:21:3C:AC:F7:38";
146 // Philips SHB9100: static const char * device_addr_string = "00:22:37:05:FD:E8";
147 // RT-B6:           static const char * device_addr_string = "00:75:58:FF:C9:7D";
148 // BT dongle:       static const char * device_addr_string = "00:1A:7D:DA:71:0A";
149 // Sony MDR-ZX330BT static const char * device_addr_string = "00:18:09:28:50:18";
150 // Panda (BM6)      static const char * device_addr_string = "4F:3F:66:52:8B:E0";
151 
152 static bd_addr_t device_addr;
153 static uint8_t sdp_a2dp_source_service_buffer[150];
154 static uint8_t sdp_avrcp_target_service_buffer[200];
155 static uint8_t sdp_avrcp_controller_service_buffer[200];
156 
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 stream_data_source_t data_source;
164 
165 static int sine_phase;
166 
167 static int hxcmod_initialized;
168 static modcontext mod_context;
169 static tracker_buffer_state trkbuf;
170 
171 static uint16_t avrcp_controller_cid = 0;
172 
173 /* AVRCP Target context START */
174 static const uint8_t subunit_info[] = {
175     0,0,0,0,
176     1,1,1,1,
177     2,2,2,2,
178     3,3,3,3,
179     4,4,4,4,
180     5,5,5,5,
181     6,6,6,6,
182     7,7,7,7
183 };
184 
185 static uint32_t company_id = 0x112233;
186 static uint8_t companies_num = 1;
187 static uint8_t companies[] = {
188     0x00, 0x19, 0x58 //BT SIG registered CompanyID
189 };
190 
191 static uint8_t events_num = 13;
192 static uint8_t events[] = {
193     AVRCP_NOTIFICATION_EVENT_PLAYBACK_STATUS_CHANGED,
194     AVRCP_NOTIFICATION_EVENT_TRACK_CHANGED,
195     AVRCP_NOTIFICATION_EVENT_TRACK_REACHED_END,
196     AVRCP_NOTIFICATION_EVENT_TRACK_REACHED_START,
197     AVRCP_NOTIFICATION_EVENT_PLAYBACK_POS_CHANGED,
198     AVRCP_NOTIFICATION_EVENT_BATT_STATUS_CHANGED,
199     AVRCP_NOTIFICATION_EVENT_SYSTEM_STATUS_CHANGED,
200     AVRCP_NOTIFICATION_EVENT_PLAYER_APPLICATION_SETTING_CHANGED,
201     AVRCP_NOTIFICATION_EVENT_NOW_PLAYING_CONTENT_CHANGED,
202     AVRCP_NOTIFICATION_EVENT_AVAILABLE_PLAYERS_CHANGED,
203     AVRCP_NOTIFICATION_EVENT_ADDRESSED_PLAYER_CHANGED,
204     AVRCP_NOTIFICATION_EVENT_UIDS_CHANGED,
205     AVRCP_NOTIFICATION_EVENT_VOLUME_CHANGED
206 };
207 
208 typedef struct {
209     uint8_t track_id[8];
210     uint32_t song_length_ms;
211     avrcp_playback_status_t status;
212     uint32_t song_position_ms; // 0xFFFFFFFF if not supported
213 } avrcp_play_status_info_t;
214 
215 // python -c "print('a'*512)"
216 static const char title[] = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
217 
218 avrcp_track_t tracks[] = {
219     {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, 1, "Sine", "Generated", "A2DP Source Demo", "monotone", 12345},
220     {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02}, 2, "Nao-deceased", "Decease", "A2DP Source Demo", "vivid", 12345},
221     {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03}, 3, (char *)title, "Decease", "A2DP Source Demo", "vivid", 12345},
222 };
223 int current_track_index;
224 avrcp_play_status_info_t play_info;
225 
226 /* AVRCP Target context END */
227 
228 /* @section Main Application Setup
229  *
230  * @text The Listing MainConfiguration shows how to setup AD2P Source and AVRCP Target services.
231  */
232 
233 /* LISTING_START(MainConfiguration): Setup Audio Source and AVRCP Target services */
234 static void a2dp_source_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t * event, uint16_t event_size);
235 static void avrcp_target_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size);
236 static void avrcp_controller_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size);
237 #ifdef HAVE_BTSTACK_STDIN
238 static void stdin_process(char cmd);
239 #endif
240 
241 static int a2dp_source_and_avrcp_services_init(void){
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: 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     // 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 a2dp_source_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
440     UNUSED(channel);
441     UNUSED(size);
442     uint8_t status;
443     uint8_t local_seid;
444     bd_addr_t address;
445     uint16_t cid;
446 
447     if (packet_type != HCI_EVENT_PACKET) return;
448 
449 #ifndef HAVE_BTSTACK_STDIN
450     if (hci_event_packet_get_type(packet) == BTSTACK_EVENT_STATE){
451         if (btstack_event_state_get_state(packet) != HCI_STATE_WORKING) return;
452         printf("Create A2DP Source connection to addr %s.\n", bd_addr_to_str(device_addr));
453         status = a2dp_source_establish_stream(device_addr, media_tracker.local_seid, &media_tracker.a2dp_cid);
454         if (status != ERROR_CODE_SUCCESS){
455             printf("Could not perform command, status 0x%2x\n", status);
456         }
457         return;
458     }
459 #endif
460     if (hci_event_packet_get_type(packet) == HCI_EVENT_PIN_CODE_REQUEST) {
461         printf("Pin code request - using '0000'\n");
462         hci_event_pin_code_request_get_bd_addr(packet, address);
463         gap_pin_code_response(address, "0000");
464         return;
465     }
466 
467     if (hci_event_packet_get_type(packet) != HCI_EVENT_A2DP_META) return;
468 
469     switch (hci_event_a2dp_meta_get_subevent_code(packet)){
470         case A2DP_SUBEVENT_SIGNALING_CONNECTION_ESTABLISHED:
471             a2dp_subevent_signaling_connection_established_get_bd_addr(packet, address);
472             cid = a2dp_subevent_signaling_connection_established_get_a2dp_cid(packet);
473             status = a2dp_subevent_signaling_connection_established_get_status(packet);
474 
475             if (status != ERROR_CODE_SUCCESS){
476                 printf("A2DP Source: Connection failed, status 0x%02x, cid 0x%02x, a2dp_cid 0x%02x \n", status, cid, media_tracker.a2dp_cid);
477                 media_tracker.a2dp_cid = 0;
478                 break;
479             }
480             media_tracker.a2dp_cid = cid;
481             printf("A2DP Source: Connected to address %s, a2dp cid 0x%02x.\n", bd_addr_to_str(address), media_tracker.a2dp_cid);
482             break;
483 
484          case A2DP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CONFIGURATION:{
485             sbc_configuration.reconfigure = a2dp_subevent_signaling_media_codec_sbc_configuration_get_reconfigure(packet);
486             sbc_configuration.num_channels = a2dp_subevent_signaling_media_codec_sbc_configuration_get_num_channels(packet);
487             sbc_configuration.sampling_frequency = a2dp_subevent_signaling_media_codec_sbc_configuration_get_sampling_frequency(packet);
488             sbc_configuration.channel_mode = a2dp_subevent_signaling_media_codec_sbc_configuration_get_channel_mode(packet);
489             sbc_configuration.block_length = a2dp_subevent_signaling_media_codec_sbc_configuration_get_block_length(packet);
490             sbc_configuration.subbands = a2dp_subevent_signaling_media_codec_sbc_configuration_get_subbands(packet);
491             sbc_configuration.allocation_method = a2dp_subevent_signaling_media_codec_sbc_configuration_get_allocation_method(packet);
492             sbc_configuration.min_bitpool_value = a2dp_subevent_signaling_media_codec_sbc_configuration_get_min_bitpool_value(packet);
493             sbc_configuration.max_bitpool_value = a2dp_subevent_signaling_media_codec_sbc_configuration_get_max_bitpool_value(packet);
494             sbc_configuration.frames_per_buffer = sbc_configuration.subbands * sbc_configuration.block_length;
495             printf("A2DP Source: Received SBC codec configuration, sampling frequency %u.\n", sbc_configuration.sampling_frequency);
496 
497             btstack_sbc_encoder_init(&sbc_encoder_state, SBC_MODE_STANDARD,
498                 sbc_configuration.block_length, sbc_configuration.subbands,
499                 sbc_configuration.allocation_method, sbc_configuration.sampling_frequency,
500                 sbc_configuration.max_bitpool_value,
501                 sbc_configuration.channel_mode);
502             break;
503         }
504 
505         case A2DP_SUBEVENT_STREAM_ESTABLISHED:
506             a2dp_subevent_stream_established_get_bd_addr(packet, address);
507             status = a2dp_subevent_stream_established_get_status(packet);
508             if (status){
509                 printf("A2DP Source: Stream failed, status 0x%02x.\n", status);
510                 break;
511             }
512             local_seid = a2dp_subevent_stream_established_get_local_seid(packet);
513             if (local_seid != media_tracker.local_seid){
514                 printf("A2DP Source: Stream failed, wrong local seid %d, expected %d.\n", local_seid, media_tracker.local_seid);
515                 break;
516             }
517             printf("A2DP Source: Stream established, address %s, a2dp cid 0x%02x, local seid %d, remote seid %d.\n", bd_addr_to_str(address),
518                 media_tracker.a2dp_cid, media_tracker.local_seid, a2dp_subevent_stream_established_get_remote_seid(packet));
519             media_tracker.stream_opened = 1;
520             data_source = STREAM_MOD;
521             status = a2dp_source_start_stream(media_tracker.a2dp_cid, media_tracker.local_seid);
522             break;
523 
524         case A2DP_SUBEVENT_STREAM_RECONFIGURED:
525             status = a2dp_subevent_stream_reconfigured_get_status(packet);
526             printf("A2DP Source: Reconfigured, status 0x%02x\n", status);
527             break;
528 
529         case A2DP_SUBEVENT_STREAM_STARTED:
530             play_info.status = AVRCP_PLAYBACK_STATUS_PLAYING;
531             if (media_tracker.avrcp_cid){
532                 avrcp_target_set_now_playing_info(media_tracker.avrcp_cid, &tracks[data_source], sizeof(tracks)/sizeof(avrcp_track_t));
533                 avrcp_target_set_playback_status(media_tracker.avrcp_cid, AVRCP_PLAYBACK_STATUS_PLAYING);
534             }
535             a2dp_demo_timer_start(&media_tracker);
536             printf("A2DP Source: Stream started.\n");
537             break;
538 
539         case A2DP_SUBEVENT_STREAMING_CAN_SEND_MEDIA_PACKET_NOW:
540             a2dp_demo_send_media_packet();
541             break;
542 
543         case A2DP_SUBEVENT_STREAM_SUSPENDED:
544             play_info.status = AVRCP_PLAYBACK_STATUS_PAUSED;
545             if (media_tracker.avrcp_cid){
546                 avrcp_target_set_playback_status(media_tracker.avrcp_cid, AVRCP_PLAYBACK_STATUS_PAUSED);
547             }
548             printf("A2DP Source: Stream paused.\n");
549             a2dp_demo_timer_stop(&media_tracker);
550             break;
551 
552         case A2DP_SUBEVENT_STREAM_RELEASED:
553             play_info.status = AVRCP_PLAYBACK_STATUS_STOPPED;
554             cid = a2dp_subevent_stream_released_get_a2dp_cid(packet);
555             if (cid == media_tracker.a2dp_cid) {
556                 media_tracker.stream_opened = 0;
557                 printf("A2DP Source: Stream released.\n");
558             }
559             if (media_tracker.avrcp_cid){
560                 avrcp_target_set_now_playing_info(media_tracker.avrcp_cid, NULL, sizeof(tracks)/sizeof(avrcp_track_t));
561                 avrcp_target_set_playback_status(media_tracker.avrcp_cid, AVRCP_PLAYBACK_STATUS_STOPPED);
562             }
563             a2dp_demo_timer_stop(&media_tracker);
564             break;
565         case A2DP_SUBEVENT_SIGNALING_CONNECTION_RELEASED:
566             cid = a2dp_subevent_signaling_connection_released_get_a2dp_cid(packet);
567             if (cid == media_tracker.a2dp_cid) {
568                 media_tracker.avrcp_cid = 0;
569                 media_tracker.a2dp_cid = 0;
570                 printf("A2DP Source: Signaling released.\n\n");
571             }
572             break;
573         default:
574             break;
575     }
576 }
577 
578 static void avrcp_target_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
579     UNUSED(channel);
580     UNUSED(size);
581     bd_addr_t event_addr;
582     uint16_t local_cid;
583     uint8_t  status = ERROR_CODE_SUCCESS;
584 
585     if (packet_type != HCI_EVENT_PACKET) return;
586     if (hci_event_packet_get_type(packet) != HCI_EVENT_AVRCP_META) return;
587 
588     switch (packet[2]){
589         case AVRCP_SUBEVENT_CONNECTION_ESTABLISHED: {
590             local_cid = avrcp_subevent_connection_established_get_avrcp_cid(packet);
591             // if (avrcp_cid != 0 && avrcp_cid != local_cid) {
592             //     printf("AVRCP Target: Connection failed, expected 0x%02X l2cap cid, received 0x%02X\n", avrcp_cid, local_cid);
593             //     return;
594             // }
595             // if (avrcp_cid != local_cid) break;
596 
597             status = avrcp_subevent_connection_established_get_status(packet);
598             if (status != ERROR_CODE_SUCCESS){
599                 printf("AVRCP Target: Connection failed, status 0x%02x\n", status);
600                 return;
601             }
602             media_tracker.avrcp_cid = local_cid;
603             avrcp_subevent_connection_established_get_bd_addr(packet, event_addr);
604             printf("AVRCP Target: Connected to %s, avrcp_cid 0x%02x\n", bd_addr_to_str(event_addr), local_cid);
605 
606             avrcp_target_set_now_playing_info(media_tracker.avrcp_cid, NULL, sizeof(tracks)/sizeof(avrcp_track_t));
607             avrcp_target_set_unit_info(media_tracker.avrcp_cid, AVRCP_SUBUNIT_TYPE_AUDIO, company_id);
608             avrcp_target_set_subunit_info(media_tracker.avrcp_cid, AVRCP_SUBUNIT_TYPE_AUDIO, (uint8_t *)subunit_info, sizeof(subunit_info));
609             return;
610         }
611         case AVRCP_SUBEVENT_NOTIFICATION_VOLUME_CHANGED:
612             printf("AVRCP Target: new volume %d\n", avrcp_subevent_notification_volume_changed_get_absolute_volume(packet));
613             break;
614         case AVRCP_SUBEVENT_EVENT_IDS_QUERY:
615             status = avrcp_target_supported_events(media_tracker.avrcp_cid, events_num, events, sizeof(events));
616             break;
617         case AVRCP_SUBEVENT_COMPANY_IDS_QUERY:
618             status = avrcp_target_supported_companies(media_tracker.avrcp_cid, companies_num, companies, sizeof(companies));
619             break;
620         case AVRCP_SUBEVENT_PLAY_STATUS_QUERY:
621             status = avrcp_target_play_status(media_tracker.avrcp_cid, play_info.song_length_ms, play_info.song_position_ms, play_info.status);
622             break;
623         // case AVRCP_SUBEVENT_NOW_PLAYING_INFO_QUERY:
624         //     status = avrcp_target_now_playing_info(avrcp_cid);
625         //     break;
626         case AVRCP_SUBEVENT_OPERATION:{
627             avrcp_operation_id_t operation_id = avrcp_subevent_operation_get_operation_id(packet);
628             switch (operation_id){
629                 case AVRCP_OPERATION_ID_PLAY:
630                     printf("AVRCP Target: PLAY\n");
631                     status = a2dp_source_start_stream(media_tracker.a2dp_cid, media_tracker.local_seid);
632                     break;
633                 case AVRCP_OPERATION_ID_PAUSE:
634                     printf("AVRCP Target: PAUSE\n");
635                     status = a2dp_source_pause_stream(media_tracker.a2dp_cid, media_tracker.local_seid);
636                     break;
637                 case AVRCP_OPERATION_ID_STOP:
638                     printf("AVRCP Target: STOP\n");
639                     status = a2dp_source_disconnect(media_tracker.a2dp_cid);
640                     break;
641                 default:
642                     printf("AVRCP Target: operation 0x%2x is not handled\n", operation_id);
643                     return;
644             }
645             break;
646         }
647         case AVRCP_SUBEVENT_CONNECTION_RELEASED:
648             printf("AVRCP Target: Disconnected, avrcp_cid 0x%02x\n", avrcp_subevent_connection_released_get_avrcp_cid(packet));
649             media_tracker.avrcp_cid = 0;
650             return;
651         default:
652             break;
653     }
654 
655     if (status != ERROR_CODE_SUCCESS){
656         printf("Responding to event 0x%02x failed with status 0x%02x\n", packet[2], status);
657     }
658 }
659 
660 static void avrcp_controller_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
661     UNUSED(channel);
662     UNUSED(size);
663     uint16_t local_cid;
664     uint8_t  status = 0xFF;
665     bd_addr_t adress;
666 
667     if (packet_type != HCI_EVENT_PACKET) return;
668     if (hci_event_packet_get_type(packet) != HCI_EVENT_AVRCP_META) return;
669     switch (packet[2]){
670         case AVRCP_SUBEVENT_CONNECTION_ESTABLISHED: {
671             local_cid = avrcp_subevent_connection_established_get_avrcp_cid(packet);
672             if (avrcp_controller_cid != 0 && avrcp_controller_cid != local_cid) {
673                 printf("AVRCP Controller: Connection failed, expected 0x%02X l2cap cid, received 0x%02X\n", avrcp_controller_cid, local_cid);
674                 return;
675             }
676 
677             status = avrcp_subevent_connection_established_get_status(packet);
678             if (status != ERROR_CODE_SUCCESS){
679                 printf("AVRCP Controller: Connection failed: status 0x%02x\n", status);
680                 avrcp_controller_cid = 0;
681                 return;
682             }
683 
684             avrcp_controller_cid = local_cid;
685             avrcp_subevent_connection_established_get_bd_addr(packet, adress);
686             printf("AVRCP Controller: Channel successfully opened: %s, avrcp_controller_cid 0x%02x\n", bd_addr_to_str(adress), avrcp_controller_cid);
687 
688             // automatically enable notifications
689             avrcp_controller_enable_notification(avrcp_controller_cid, AVRCP_NOTIFICATION_EVENT_VOLUME_CHANGED);
690             return;
691         }
692         case AVRCP_SUBEVENT_CONNECTION_RELEASED:
693             printf("AVRCP Controller: Channel released: avrcp_controller_cid 0x%02x\n", avrcp_subevent_connection_released_get_avrcp_cid(packet));
694             avrcp_controller_cid = 0;
695             return;
696         default:
697             break;
698     }
699 
700     status = packet[5];
701     if (!avrcp_controller_cid) return;
702 
703     // ignore INTERIM status
704     if (status == AVRCP_CTYPE_RESPONSE_INTERIM) return;
705 
706     switch (packet[2]){
707         case AVRCP_SUBEVENT_NOTIFICATION_VOLUME_CHANGED:{
708             int volume_percentage = avrcp_subevent_notification_volume_changed_get_absolute_volume(packet) * 100 / 127;
709             printf("AVRCP Controller: notification absolute volume changed %d %%\n", volume_percentage);
710             return;
711         }
712         default:
713             break;
714     }
715 }
716 
717 #ifdef HAVE_BTSTACK_STDIN
718 static void show_usage(void){
719     bd_addr_t      iut_address;
720     gap_local_bd_addr(iut_address);
721     printf("\n--- Bluetooth  A2DP Source/AVRCP Target Demo %s ---\n", bd_addr_to_str(iut_address));
722     printf("b      - A2DP Source create connection to addr %s\n", device_addr_string);
723     printf("B      - A2DP Source disconnect\n");
724     printf("c      - AVRCP Target create connection to addr %s\n", device_addr_string);
725     printf("C      - AVRCP Target disconnect\n");
726 
727     printf("x      - start streaming sine\n");
728     if (hxcmod_initialized){
729         printf("z      - start streaming '%s'\n", mod_name);
730     }
731     printf("p      - pause streaming\n");
732     printf("w      - reconfigure stream for 44100 Hz\n");
733     printf("e      - reconfigure stream for 48000 Hz\n");
734     printf("t      - volume up\n");
735     printf("T      - volume down\n");
736     printf("v      - absolute volume of 50 percent\n");
737 
738     printf("\n--- Bluetooth  AVRCP Target Commands %s ---\n", bd_addr_to_str(iut_address));
739     printf("---\n");
740 }
741 
742 static void stdin_process(char cmd){
743     uint8_t status = ERROR_CODE_SUCCESS;
744     switch (cmd){
745         case 'b':
746             status = a2dp_source_establish_stream(device_addr, media_tracker.local_seid, &media_tracker.a2dp_cid);
747             printf("%c - Create A2DP Source connection to addr %s, cid 0x%02x.\n", cmd, bd_addr_to_str(device_addr), media_tracker.a2dp_cid);
748             break;
749         case 'B':
750             printf("%c - A2DP Source Disconnect from cid 0x%2x\n", cmd, media_tracker.a2dp_cid);
751             status = a2dp_source_disconnect(media_tracker.a2dp_cid);
752             break;
753         case 'c':
754             printf("%c - Create AVRCP Target connection to addr %s.\n", cmd, bd_addr_to_str(device_addr));
755             status = avrcp_target_connect(device_addr, &media_tracker.avrcp_cid);
756             break;
757         case 'C':
758             printf("%c - AVRCP Target disconnect\n", cmd);
759             status = avrcp_target_disconnect(media_tracker.avrcp_cid);
760             break;
761 
762         case '\n':
763         case '\r':
764             break;
765 
766         case 't':
767             printf(" - volume up\n");
768             status = avrcp_controller_volume_up(avrcp_controller_cid);
769             break;
770         case 'T':
771             printf(" - volume down\n");
772             status = avrcp_controller_volume_down(avrcp_controller_cid);
773             break;
774         case 'v':
775             printf(" - absolute volume of 50%% (64)\n");
776             status = avrcp_controller_set_absolute_volume(avrcp_controller_cid, 64);
777             break;
778 
779         case 'x':
780             if (media_tracker.avrcp_cid){
781                 avrcp_target_set_now_playing_info(media_tracker.avrcp_cid, &tracks[data_source], sizeof(tracks)/sizeof(avrcp_track_t));
782             }
783             printf("%c - Play sine.\n", cmd);
784             data_source = STREAM_SINE;
785             if (!media_tracker.stream_opened) break;
786             status = a2dp_source_start_stream(media_tracker.a2dp_cid, media_tracker.local_seid);
787             break;
788         case 'z':
789             if (media_tracker.avrcp_cid){
790                 avrcp_target_set_now_playing_info(media_tracker.avrcp_cid, &tracks[data_source], sizeof(tracks)/sizeof(avrcp_track_t));
791             }
792             printf("%c - Play mod.\n", cmd);
793             data_source = STREAM_MOD;
794             if (!media_tracker.stream_opened) break;
795             status = a2dp_source_start_stream(media_tracker.a2dp_cid, media_tracker.local_seid);
796             break;
797 
798         case 'p':
799             if (!media_tracker.stream_opened) break;
800             printf("%c - Pause stream.\n", cmd);
801             status = a2dp_source_pause_stream(media_tracker.a2dp_cid, media_tracker.local_seid);
802             break;
803 
804         case 'w':
805             if (!media_tracker.stream_opened) break;
806             if (play_info.status == AVRCP_PLAYBACK_STATUS_PLAYING){
807                 printf("Stream cannot be reconfigured while playing, please pause stream first\n");
808                 break;
809             }
810             printf("%c - Reconfigure for 44100 Hz.\n", cmd);
811             status = a2dp_source_reconfigure_stream_sampling_frequency(media_tracker.a2dp_cid, 44100);
812             break;
813 
814         case 'e':
815             if (!media_tracker.stream_opened) break;
816             if (play_info.status == AVRCP_PLAYBACK_STATUS_PLAYING){
817                 printf("Stream cannot be reconfigured while playing, please pause stream first\n");
818                 break;
819             }
820             printf("%c - Reconfigure for 48000 Hz.\n", cmd);
821             status = a2dp_source_reconfigure_stream_sampling_frequency(media_tracker.a2dp_cid, 48000);
822             break;
823 
824         default:
825             show_usage();
826             return;
827     }
828     if (status != ERROR_CODE_SUCCESS){
829         printf("Could not perform command \'%c\', status 0x%2x\n", cmd, status);
830     }
831 }
832 #endif
833 
834 
835 int btstack_main(int argc, const char * argv[]);
836 int btstack_main(int argc, const char * argv[]){
837     (void)argc;
838     (void)argv;
839 
840     int err = a2dp_source_and_avrcp_services_init();
841     if (err) return err;
842     // turn on!
843     hci_power_control(HCI_POWER_ON);
844     return 0;
845 }
846 /* EXAMPLE_END */
847