a2dp_source_demo.c 46 KB

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