Arduino A2DP
BluetoothA2DPSource.h
1 // C++ Class Implementation for a A2DP Source to be used as Arduino Library
2 // The original ESP32 implementation can be found at
3 // https://github.com/espressif/esp-idf/tree/master/examples/bluetooth/bluedroid/classic_bt/a2dp_source
4 //
5 // Licensed under the Apache License, Version 2.0 (the "License");
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 // http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 //
17 // Copyright 2020 Phil Schatzmann
18 // Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
19 
20 #pragma once
21 
22 #include <vector>
23 
24 #include "BluetoothA2DPCommon.h"
25 
26 #ifdef ARDUINO
27 #include "Stream.h"
28 #endif
29 
30 #if (ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0))
31 #define TIMER_ARG_TYPE void *
32 #else
33 #define TIMER_ARG_TYPE tmrTimerControl *
34 #endif
35 
36 typedef int32_t (*music_data_cb_t)(uint8_t *data, int32_t len);
37 typedef int32_t (*music_data_frames_cb_t)(Frame *data, int32_t len);
38 typedef void (*bt_app_copy_cb_t)(bt_app_msg_t *msg, void *p_dest, void *p_src);
39 typedef void (*bt_app_cb_t)(uint16_t event, void *param);
40 
41 extern "C" void ccall_a2d_app_heart_beat(TIMER_ARG_TYPE arg);
42 extern "C" void ccall_bt_app_av_sm_hdlr(uint16_t event, void *param);
43 extern "C" void ccall_bt_av_hdl_avrc_ct_evt(uint16_t event, void *param);
44 extern "C" int32_t ccall_bt_app_a2d_data_cb(uint8_t *data, int32_t len);
45 
51  APP_AV_STATE_IDLE,
52  APP_AV_STATE_DISCOVERING,
53  APP_AV_STATE_DISCOVERED,
54  APP_AV_STATE_UNCONNECTED,
55  APP_AV_STATE_CONNECTING,
56  APP_AV_STATE_CONNECTED,
57  APP_AV_STATE_DISCONNECTING,
58 };
59 
60 static const char *APP_AV_STATE_STR[] = {
61  "IDLE", "DISCOVERING", "DISCOVERED", "UNCONNECTED",
62  "CONNECTING", "CONNECTED", "DISCONNECTING"};
63 
72  friend void ccall_a2d_app_heart_beat(TIMER_ARG_TYPE arg);
73  friend void ccall_bt_app_av_sm_hdlr(uint16_t event, void *param);
74  friend void ccall_bt_av_hdl_avrc_ct_evt(uint16_t event, void *param);
75  friend int32_t ccall_bt_app_a2d_data_cb(uint8_t *data, int32_t len);
76 
77  public:
80 
83 
85  virtual void set_ssp_enabled(bool active) { this->ssp_enabled = active; }
86 
89  virtual void set_auto_reconnect(bool active) {
90  this->reconnect_status = active ? AutoReconnect : NoReconnect;
91  }
92 
94  virtual void set_auto_reconnect(esp_bd_addr_t addr) {
95  set_auto_reconnect(true);
96  memcpy(last_connection, addr, ESP_BD_ADDR_LEN);
97  }
98 
100  virtual void set_local_name(const char *name) { dev_name = name; }
101 
103  virtual void set_data_callback(int32_t(cb)(uint8_t *data, int32_t len)) {
104  get_data_cb = cb;
105  }
106 
108  virtual void set_data_callback_in_frames(int32_t(cb)(Frame *data,
109  int32_t len)) {
110  get_data_in_frames_cb = cb;
111  }
112 
113 #ifdef ARDUINO
114 
116  virtual void set_data_source(Stream &data) { p_stream = &data; }
118  virtual void set_data_source_callback(Stream &(*next_stream)()) {
119  get_next_stream_cb = next_stream;
120  }
121 #endif
122 
125  virtual void start() {
126  std::vector<const char *> names; // empty vector
127  start(names);
128  }
129 
131  virtual void start(const char *name) {
132  std::vector<const char *> names = {name}; // empty vector
133  start(names);
134  }
135 
137  virtual void start(std::vector<const char *> names);
138 
140  virtual void start(const char *name, music_data_frames_cb_t callback) {
141  set_data_callback_in_frames(callback);
142  std::vector<const char *> names = {name};
143  start(names);
144  }
145 
147  virtual void start(music_data_frames_cb_t callback) {
148  set_data_callback_in_frames(callback);
149  start();
150  }
151 
153  virtual void start(std::vector<const char *> names,
154  music_data_frames_cb_t callback) {
155  set_data_callback_in_frames(callback);
156  start(names);
157  }
158 
160  virtual void start_raw(const char *name, music_data_cb_t callback = nullptr) {
161  set_data_callback(callback);
162  start(name);
163  }
164 
166  virtual void start_raw(std::vector<const char *> names,
167  music_data_cb_t callback = nullptr) {
168  set_data_callback(callback);
169  start(names);
170  }
171 
173  virtual void start_raw(music_data_cb_t callback = nullptr) {
174  set_data_callback(callback);
175  start();
176  }
177 
179  void set_pin_code(const char *pin_code, esp_bt_pin_type_t pin_type);
180 
182  virtual void set_reset_ble(bool doInit);
183 
185  virtual void set_ssid_callback(bool (*callback)(const char *ssid,
186  esp_bd_addr_t address,
187  int rrsi)) {
188  ssid_callback = callback;
189  }
190 
193  void (*callback)(esp_bt_gap_discovery_state_t discoveryMode)) {
194  discovery_mode_callback = callback;
195  }
196 
199  virtual bool is_discovery_active() { return discovery_active; }
200 
204  virtual void set_valid_cod_service(uint16_t filter) {
205  this->valid_cod_services = filter;
206  }
207 
209  virtual void set_avrc_passthru_command_callback(void (*cb)(uint8_t key,
210  bool isReleased)) {
211  passthru_command_callback = cb;
212  is_passthru_active = (cb != nullptr);
213  }
214 
216  void end(bool releaseMemory=false) override;
217 
218  protected:
220  int32_t (*get_data_cb)(uint8_t *data, int32_t len) = nullptr;
221  int32_t (*get_data_in_frames_cb)(Frame *data, int32_t len) = nullptr;
222 #ifdef ARDUINO
223  Stream *p_stream = nullptr;
224  Stream &(*get_next_stream_cb)() = nullptr;
225 #endif
226  const char *dev_name = "ESP32_A2DP_SRC";
227  bool ssp_enabled = false;
228  std::vector<const char *> bt_names;
229  esp_bt_pin_type_t pin_type;
230  esp_bt_pin_code_t pin_code;
231  uint32_t pin_code_len;
232  uint8_t s_peer_bdname[ESP_BT_GAP_MAX_BDNAME_LEN + 1];
233  APP_AV_STATE s_a2d_state = APP_AV_STATE_IDLE; // Next Target Connection State
234  APP_AV_STATE s_a2d_last_state =
235  APP_AV_STATE_IDLE; // Next Target Connection State
236  int s_media_state = 0;
237  int s_intv_cnt = 0;
238  int s_connecting_heatbeat_count;
239  uint32_t s_pkt_cnt;
240  TimerHandle_t s_tmr;
241 
242  // initialization
243  bool reset_ble = false;
244  bool discovery_active = false;
245  uint16_t valid_cod_services = ESP_BT_COD_SRVC_RENDERING |
246  ESP_BT_COD_SRVC_AUDIO |
247  ESP_BT_COD_SRVC_TELEPHONY;
248 
249  bool (*ssid_callback)(const char *ssid, esp_bd_addr_t address,
250  int rrsi) = nullptr;
251  void (*discovery_mode_callback)(esp_bt_gap_discovery_state_t discoveryMode) =
252  nullptr;
253  void (*passthru_command_callback)(uint8_t, bool) = nullptr;
254  bool is_passthru_active = false;
255 
256 #if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 0, 0)
257  esp_avrc_rn_evt_cap_mask_t s_avrc_peer_rn_cap;
258 #endif
259 
260  void app_gap_callback(esp_bt_gap_cb_event_t event,
261  esp_bt_gap_cb_param_t *param) override;
262  void app_rc_ct_callback(esp_avrc_ct_cb_event_t event,
263  esp_avrc_ct_cb_param_t *param) override;
264  void app_a2d_callback(esp_a2d_cb_event_t event,
265  esp_a2d_cb_param_t *param) override;
266  void av_hdl_stack_evt(uint16_t event, void *p_param) override;
267 
269  virtual int32_t get_audio_data(uint8_t *data, int32_t len);
271  virtual int32_t get_audio_data_volume(uint8_t *data, int32_t len);
272 
273 
274  virtual void process_user_state_callbacks(uint16_t event, void *param);
275 
276  virtual bool bt_app_work_dispatch(bt_app_cb_t p_cback, uint16_t event,
277  void *p_params, int param_len,
278  bt_app_copy_cb_t p_copy_cback);
279  virtual void bt_app_av_media_proc(uint16_t event, void *param);
280 
282  virtual void bt_app_av_state_unconnected_hdlr(uint16_t event, void *param);
283  virtual void bt_app_av_state_connecting_hdlr(uint16_t event, void *param);
284  virtual void bt_app_av_state_connected_hdlr(uint16_t event, void *param);
285  virtual void bt_app_av_state_disconnecting_hdlr(uint16_t event, void *param);
286 
287  virtual bool get_name_from_eir(uint8_t *eir, uint8_t *bdname,
288  uint8_t *bdname_len);
289  virtual void filter_inquiry_scan_result(esp_bt_gap_cb_param_t *param);
290 
291  virtual const char *last_bda_nvs_name() { return "src_bda"; }
292 
293  virtual void a2d_app_heart_beat(void *arg);
295  virtual void bt_app_av_sm_hdlr(uint16_t event, void *param);
297  virtual void bt_av_hdl_avrc_ct_evt(uint16_t event, void *p_param);
299  virtual void reset_last_connection();
302  virtual bool is_valid_cod_service(uint32_t cod);
303 
304  esp_err_t esp_a2d_connect(esp_bd_addr_t peer) override {
305  ESP_LOGI(BT_AV_TAG, "==> a2dp connecting to: %s", to_str(peer));
306  s_media_state = 0;
307  s_a2d_state = APP_AV_STATE_CONNECTING;
308  return esp_a2d_source_connect(peer);
309  }
310 
311  esp_err_t esp_a2d_disconnect(esp_bd_addr_t peer) override {
312  ESP_LOGI(BT_AV_TAG, "==> a2dp esp_a2d_source_disconnect from: %s",
313  to_str(peer));
314  esp_a2d_media_ctrl(ESP_A2D_MEDIA_CTRL_STOP);
315  return esp_a2d_source_disconnect(peer);
316  }
317 
319  const char *to_state_str(int state) { return APP_AV_STATE_STR[state]; }
320 
321  void set_scan_mode_connectable_default() override {
323  }
324 
325 #if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 0, 0)
326  virtual void bt_av_notify_evt_handler(uint8_t event, esp_avrc_rn_param_t *param);
327  virtual void bt_av_volume_changed(void);
328  virtual void app_rc_tg_callback(esp_avrc_tg_cb_event_t event,
329  esp_avrc_tg_cb_param_t *param) override;
330  virtual void av_hdl_avrc_tg_evt(uint16_t event, void *p_param) override;
331  virtual bool isSource() { return true;}
332 
333 #endif
334 };
Common Bluetooth A2DP functions.
Definition: BluetoothA2DPCommon.h:169
const char * to_str(esp_a2d_connection_state_t state)
converts esp_a2d_connection_state_t to a string
Definition: BluetoothA2DPCommon.cpp:364
virtual void set_scan_mode_connectable(bool connectable)
Defines if the bluetooth is connectable.
Definition: BluetoothA2DPCommon.cpp:537
A2DP Bluetooth Source.
Definition: BluetoothA2DPSource.h:71
virtual void bt_app_av_state_unconnected_hdlr(uint16_t event, void *param)
A2DP application state machine handler for each state.
Definition: BluetoothA2DPSource.cpp:604
virtual int32_t get_audio_data_volume(uint8_t *data, int32_t len)
provides the audio after applying the volume
Definition: BluetoothA2DPSource.cpp:151
virtual void start_raw(std::vector< const char * > names, music_data_cb_t callback=nullptr)
Obsolete: use the start w/o callback and set the callback separately.
Definition: BluetoothA2DPSource.h:166
void set_pin_code(const char *pin_code, esp_bt_pin_type_t pin_type)
Defines the pin code. If nothing is defined we use "1234".
Definition: BluetoothA2DPSource.cpp:80
virtual void reset_last_connection()
resets the last connectioin so that we can reconnect
Definition: BluetoothA2DPSource.cpp:183
virtual void start(std::vector< const char * > names, music_data_frames_cb_t callback)
Obsolete: use the start w/o callback and set the callback separately.
Definition: BluetoothA2DPSource.h:153
void app_rc_ct_callback(esp_avrc_ct_cb_event_t event, esp_avrc_ct_cb_param_t *param) override
callback function for AVRCP controller
Definition: BluetoothA2DPSource.cpp:843
virtual void set_valid_cod_service(uint16_t filter)
Definition: BluetoothA2DPSource.h:204
virtual int32_t get_audio_data(uint8_t *data, int32_t len)
provides the audio data to be sent
Definition: BluetoothA2DPSource.cpp:158
virtual void start_raw(music_data_cb_t callback=nullptr)
Obsolete: use the start w/o callback and set the callback separately.
Definition: BluetoothA2DPSource.h:173
~BluetoothA2DPSource()
Destructor.
Definition: BluetoothA2DPSource.cpp:78
virtual bool is_valid_cod_service(uint32_t cod)
Definition: BluetoothA2DPSource.cpp:259
BluetoothA2DPSource()
Constructor.
Definition: BluetoothA2DPSource.cpp:59
virtual void set_reset_ble(bool doInit)
Defines if the BLE should be reset on start.
Definition: BluetoothA2DPSource.cpp:1003
virtual void set_auto_reconnect(bool active)
Definition: BluetoothA2DPSource.h:89
virtual void start(const char *name, music_data_frames_cb_t callback)
Obsolete: use the start w/o callback and set the callback separately.
Definition: BluetoothA2DPSource.h:140
virtual void set_ssid_callback(bool(*callback)(const char *ssid, esp_bd_addr_t address, int rrsi))
Define callback to be notified about the found ssids.
Definition: BluetoothA2DPSource.h:185
virtual void set_avrc_passthru_command_callback(void(*cb)(uint8_t key, bool isReleased))
Define the handler fur button presses on the remote bluetooth speaker.
Definition: BluetoothA2DPSource.h:209
virtual void set_discovery_mode_callback(void(*callback)(esp_bt_gap_discovery_state_t discoveryMode))
Define callback to be notified about bt discovery mode state changes.
Definition: BluetoothA2DPSource.h:192
virtual void set_data_source(Stream &data)
Defines a single Arduino Stream (e.g. File) as audio source.
Definition: BluetoothA2DPSource.h:116
virtual void set_data_source_callback(Stream &(*next_stream)())
Provide a callback which provides streams.
Definition: BluetoothA2DPSource.h:118
virtual void set_ssp_enabled(bool active)
activate Secure Simple Pairing
Definition: BluetoothA2DPSource.h:85
virtual void start()
Definition: BluetoothA2DPSource.h:125
virtual void set_data_callback(int32_t(cb)(uint8_t *data, int32_t len))
Defines the data callback.
Definition: BluetoothA2DPSource.h:103
void app_a2d_callback(esp_a2d_cb_event_t event, esp_a2d_cb_param_t *param) override
callback function for A2DP source
Definition: BluetoothA2DPSource.cpp:531
virtual void set_auto_reconnect(esp_bd_addr_t addr)
automatically tries to reconnect to the indicated address
Definition: BluetoothA2DPSource.h:94
virtual void bt_app_av_state_connecting_hdlr(uint16_t event, void *param)
Definition: BluetoothA2DPSource.cpp:644
int32_t(* get_data_cb)(uint8_t *data, int32_t len)
callback for data
Definition: BluetoothA2DPSource.h:220
const char * to_state_str(int state)
converts a APP_AV_STATE_ENUM to a string
Definition: BluetoothA2DPSource.h:319
virtual void set_local_name(const char *name)
Defines the local name.
Definition: BluetoothA2DPSource.h:100
virtual void start(music_data_frames_cb_t callback)
Obsolete: use the start w/o callback and set the callback separately.
Definition: BluetoothA2DPSource.h:147
virtual void bt_app_av_sm_hdlr(uint16_t event, void *param)
A2DP application state machine.
Definition: BluetoothA2DPSource.cpp:576
virtual void set_data_callback_in_frames(int32_t(cb)(Frame *data, int32_t len))
Defines the data callback.
Definition: BluetoothA2DPSource.h:108
virtual void start_raw(const char *name, music_data_cb_t callback=nullptr)
Obsolete: use the start w/o callback and set the callback separately.
Definition: BluetoothA2DPSource.h:160
virtual void bt_av_hdl_avrc_ct_evt(uint16_t event, void *p_param)
avrc CT event handler
Definition: BluetoothA2DPSource.cpp:900
void end(bool releaseMemory=false) override
Ends the processing and releases the resources.
Definition: BluetoothA2DPSource.cpp:141
virtual bool is_discovery_active()
Definition: BluetoothA2DPSource.h:199
virtual void start(const char *name)
Starts the A2DP source.
Definition: BluetoothA2DPSource.h:131
APP_AV_STATE
Buetooth A2DP global state.
Definition: BluetoothA2DPSource.h:50
uint8_t esp_bd_addr_t[ESP_BD_ADDR_LEN]
Bluetooth address.
Definition: external_lists.h:107
Internal message to be sent for BluetoothA2DPSink and BluetoothA2DPSource.
Definition: BluetoothA2DPCommon.h:124