Problem Description
I'm trying to play an mp3 file from sdcard using tasks to a bluetooth speaker and i was able to play the sound. After playing the mp3 i run the hibernate-method to close the resouces, but it get blocked on the "a2dp.end();" with the following output:
[I] AudioSourceSDFAT.h : 90 - void audio_tools::AudioSourceSDFAT<AudioFs, AudioFile>::end() [with AudioFs = SdFs; AudioFile = FsFile]
I (63820) gpio: GPIO[14]| InputEn: 1| OutputEn: 0| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0
I (63821) gpio: GPIO[13]| InputEn: 1| OutputEn: 0| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0
I (63829) gpio: GPIO[12]| InputEn: 1| OutputEn: 0| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0
[I] AudioEncoded.h : 185 - virtual void audio_tools::EncodedAudioOutput::end()
[I] MetaDataID3.h : 595 - virtual void audio_tools::MetaDataID3::end()
[I] AudioPlayer.h : 234 - reset codec
[I] CodecMP3Helix.h : 82 - virtual bool audio_tools::MP3DecoderHelix::begin()
I (63876) BT_AV: disconect a2d: 11:22:33:44:55:66
I (63876) BT_AV: ==> a2dp esp_a2d_source_disconnect from: 11:22:33:44:55:66
D (67403) BT_API: bt_app_work_dispatch event 0xff00, param len 0
D (67404) BT_API: app_task_handler, signal: 0x1, event: 0xff00
D (67404) BT_AV: app_work_dispatched
I (67408) BT_AV: bt_app_av_sm_hdlr state CONNECTED, evt 0xff00
D (67415) BT_AV: process_user_state_callbacks
D (67419) BT_AV: bt_app_av_state_connected_hdlr evt 65280
D (67425) BT_AV: bt_app_av_media_proc evt 65280
I (67429) BT_AV: a2dp media started
D (77403) BT_API: bt_app_work_dispatch event 0xff00, param len 0
D (77403) BT_API: app_task_handler, signal: 0x1, event: 0xff00
D (77404) BT_AV: app_work_dispatched
I (77408) BT_AV: bt_app_av_sm_hdlr state CONNECTED, evt 0xff00
D (77414) BT_AV: process_user_state_callbacks
D (77418) BT_AV: bt_app_av_state_connected_hdlr evt 65280
D (77424) BT_AV: bt_app_av_media_proc evt 65280
I (77429) BT_AV: a2dp media started
I need to free the resources because the esp32 goes after playing the mp3 to light sleep mode and on wakeup the playback should start again.
Any idea what the problem is? or how to reuse BluetoothA2DPSource after a light sleep?
Best regards
Device Description
ESP32-D0WDQ6-V3 (Dual-core, 240MHz) with 16MB Flash and 8MB PSRAM.
Sketch
The class implementing the ad2p logic looks like this:
#ifndef BLUETOOTH_H
#define BLUETOOTH_H
#include "device.h"
#define USE_HELIX
#define USE_A2DP
#define USE_SDFAT
#include "AudioTools.h"
#include "AudioTools/AudioCodecs/CodecMP3Helix.h"
#include "AudioTools/Communication/A2DPStream.h"
#include "AudioTools/Concurrency/RTOS.h"
#include "AudioTools/Disk/AudioSourceSDFAT.h"
#include <SPI.h>
#include <stdint.h>
#define SD_SPI_CS_PIN 4
extern BufferRTOS<uint8_t> buffer;
int32_t dataCallback(uint8_t *data, int bytes);
class BluetoothSpeaker : public Device {
public:
BluetoothSpeaker(const char *device, const char *file, uint32_t connectionTimeout = 15000, float defaultVolume = 0.5f, float volumeStep = 0.1f) : source("/", "mp3", SD_SPI_CS_PIN, 25, SHARED_SPI), out(buffer), player(source, out, decoder) {
this->device = device;
this->file = file;
this->connectionTimeout = connectionTimeout;
this->defaultVolume = defaultVolume;
this->volumeStep = volumeStep;
}
private:
AudioSourceSDFAT<SdFs, FsFile> source;
MP3DecoderHelix decoder;
QueueStream<uint8_t> out;
AudioPlayer player;
BluetoothA2DPSource a2dp;
const char *device = nullptr;
const char *file = nullptr;
uint32_t connectionTimeout;
float defaultVolume;
float volumeStep;
volatile bool stopRequested = false;
TaskHandle_t taskHandle = nullptr;
static bool parse_mac(const char *str, esp_bd_addr_t addr) {
return sscanf(str, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", &addr[0], &addr[1], &addr[2], &addr[3], &addr[4], &addr[5]) == 6;
}
/// converts a esp_bd_addr_t to a string - the string is 18 characters long!
static const char *to_str(esp_bd_addr_t bda) {
static char bda_str[18];
sprintf(bda_str, "%02x:%02x:%02x:%02x:%02x:%02x", bda[0], bda[1], bda[2], bda[3], bda[4], bda[5]);
return (const char *)bda_str;
}
protected:
void static startPlayingTask(void *pvParameters) {
auto *self = static_cast<BluetoothSpeaker *>(pvParameters);
self->doStartPlaying();
}
void static stopPlayingTask(void *pvParameters) {
auto *self = static_cast<BluetoothSpeaker *>(pvParameters);
self->doStopPlaying();
}
void doStartPlaying() {
buffer.resize(15 * 1024);
out.begin(95);
player.setDelayIfOutputFull(0);
player.setVolume(getVolume());
player.begin();
a2dp.set_data_callback(dataCallback);
bool connected = a2dp.reconnect();
if (!connected) {
if (taskHandle != nullptr) {
vTaskDelete(taskHandle);
taskHandle = nullptr;
}
return;
}
if (!player.setPath(this->file)) {
if (taskHandle != nullptr) {
vTaskDelete(taskHandle);
taskHandle = nullptr;
}
return;
}
stopRequested = false;
player.play();
while (player.copy() > 0 && !stopRequested) {
vTaskDelay(1);
}
player.stop();
if (taskHandle != nullptr) {
vTaskDelete(taskHandle);
taskHandle = nullptr;
}
}
void doStopPlaying() {
stopRequested = true;
vTaskDelete(NULL);
}
static bool ssidCallback(const char *ssid, esp_bd_addr_t address, int rssi) {
Serial.printf("SSID: %s, MAC: %s\n", ssid, to_str(address));
return false;
}
public:
void init() {
a2dp.set_ssid_callback(ssidCallback);
a2dp.start();
}
bool connect() {
AudioToolsLogger.begin(Serial, AudioToolsLogLevel::Info);
esp_bd_addr_t addr;
parse_mac(mac.c_str(), "11:22:33:44:55:66");
a2dp.set_auto_reconnect(addr);
a2dp.set_auto_reconnect(true);
while (!a2dp.is_connected()) {
delay(1000);
}
return a2dp.is_connected();
}
bool isPlaying() {
if (taskHandle == nullptr) {
return false;
}
eTaskState state = eTaskGetState(taskHandle);
return state != eDeleted && state != eInvalid;
}
void startPlaying() {
xTaskCreatePinnedToCore(startPlayingTask, "startPlayingTask", 12000, this, 2, &taskHandle, 1);
}
void stopPlaying() {
xTaskCreatePinnedToCore(stopPlayingTask, "stopPlayingTask", 12000, this, 2, NULL, 1);
}
void hibernate() {
source.end();
player.end();
a2dp.set_auto_reconnect(false);
a2dp.disconnect();
a2dp.cancel_discovery();
a2dp.end();
}
};
#endif
Other Steps to Reproduce
No response
Provide your Version of the EP32 Arduino Core (or the IDF Version)
v5.2.2
I have checked existing issues, discussions and online documentation (incl. the Wiki)
Problem Description
I'm trying to play an mp3 file from sdcard using tasks to a bluetooth speaker and i was able to play the sound. After playing the mp3 i run the hibernate-method to close the resouces, but it get blocked on the "a2dp.end();" with the following output:
I need to free the resources because the esp32 goes after playing the mp3 to light sleep mode and on wakeup the playback should start again.
Any idea what the problem is? or how to reuse BluetoothA2DPSource after a light sleep?
Best regards
Device Description
ESP32-D0WDQ6-V3 (Dual-core, 240MHz) with 16MB Flash and 8MB PSRAM.
Sketch
The class implementing the ad2p logic looks like this:
Other Steps to Reproduce
No response
Provide your Version of the EP32 Arduino Core (or the IDF Version)
v5.2.2
I have checked existing issues, discussions and online documentation (incl. the Wiki)