Unverified Commit 18c3a70b authored by Wolle's avatar Wolle Committed by GitHub

make thread safe

for critical areas:
    xSemaphoreTake(mutex_audio, portMAX_DELAY);
    xSemaphoreGive(mutex_audio);

for areas that can be called by their own thread
    xSemaphoreTakeRecursive(mutex_audio, portMAX_DELAY);
    xSemaphoreGiveRecursive(mutex_audio);
parent f3e24041
...@@ -3,8 +3,8 @@ ...@@ -3,8 +3,8 @@
* *
* Created on: Oct 26.2018 * Created on: Oct 26.2018
* *
* Version 2.0.7k * Version 2.0.8
* Updated on: Jan 08.2023 * Updated on: Jan 09.2023
* Author: Wolle (schreibfaul1) * Author: Wolle (schreibfaul1)
* *
*/ */
...@@ -150,6 +150,8 @@ uint32_t AudioBuffer::getReadPos() { ...@@ -150,6 +150,8 @@ uint32_t AudioBuffer::getReadPos() {
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
Audio::Audio(bool internalDAC /* = false */, uint8_t channelEnabled /* = I2S_DAC_CHANNEL_BOTH_EN */, uint8_t i2sPort) { Audio::Audio(bool internalDAC /* = false */, uint8_t channelEnabled /* = I2S_DAC_CHANNEL_BOTH_EN */, uint8_t i2sPort) {
mutex_audio = xSemaphoreCreateMutex();
// build-in-DAC works only with ESP32 (ESP32-S3 has no build-in-DAC) // build-in-DAC works only with ESP32 (ESP32-S3 has no build-in-DAC)
// build-in-DAC last working Arduino Version: 2.0.0-RC2 // build-in-DAC last working Arduino Version: 2.0.0-RC2
// possible values for channelEnabled are: // possible values for channelEnabled are:
...@@ -298,6 +300,7 @@ Audio::~Audio() { ...@@ -298,6 +300,7 @@ Audio::~Audio() {
if(m_playlistBuff) {free(m_playlistBuff); m_playlistBuff = NULL;} if(m_playlistBuff) {free(m_playlistBuff); m_playlistBuff = NULL;}
i2s_driver_uninstall((i2s_port_t)m_i2s_num); // #215 free I2S buffer i2s_driver_uninstall((i2s_port_t)m_i2s_num); // #215 free I2S buffer
if(m_chbuf) {free(m_chbuf); m_chbuf = NULL;} if(m_chbuf) {free(m_chbuf); m_chbuf = NULL;}
vSemaphoreDelete(mutex_audio);
} }
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
void Audio::setDefaults() { void Audio::setDefaults() {
...@@ -369,8 +372,11 @@ void Audio::setConnectionTimeout(uint16_t timeout_ms, uint16_t timeout_ms_ssl){ ...@@ -369,8 +372,11 @@ void Audio::setConnectionTimeout(uint16_t timeout_ms, uint16_t timeout_ms_ssl){
bool Audio::connecttohost(const char* host, const char* user, const char* pwd) { bool Audio::connecttohost(const char* host, const char* user, const char* pwd) {
// user and pwd for authentification only, can be empty // user and pwd for authentification only, can be empty
xSemaphoreTakeRecursive(mutex_audio, portMAX_DELAY);
if(host == NULL) { if(host == NULL) {
AUDIO_INFO("Hostaddress is empty"); AUDIO_INFO("Hostaddress is empty");
xSemaphoreGiveRecursive(mutex_audio);
return false; return false;
} }
...@@ -378,6 +384,7 @@ bool Audio::connecttohost(const char* host, const char* user, const char* pwd) { ...@@ -378,6 +384,7 @@ bool Audio::connecttohost(const char* host, const char* user, const char* pwd) {
if(lenHost >= 512 - 10) { if(lenHost >= 512 - 10) {
AUDIO_INFO("Hostaddress is too long"); AUDIO_INFO("Hostaddress is too long");
xSemaphoreGiveRecursive(mutex_audio);
return false; return false;
} }
...@@ -515,6 +522,7 @@ bool Audio::connecttohost(const char* host, const char* user, const char* pwd) { ...@@ -515,6 +522,7 @@ bool Audio::connecttohost(const char* host, const char* user, const char* pwd) {
if(extension) {free(extension); extension = NULL;} if(extension) {free(extension); extension = NULL;}
if(l_host ) {free(l_host); l_host = NULL;} if(l_host ) {free(l_host); l_host = NULL;}
if(h_host ) {free(h_host); h_host = NULL;} if(h_host ) {free(h_host); h_host = NULL;}
xSemaphoreGiveRecursive(mutex_audio);
return res; return res;
} }
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
...@@ -671,7 +679,12 @@ bool Audio::connecttoSD(const char* path, uint32_t resumeFilePos) { ...@@ -671,7 +679,12 @@ bool Audio::connecttoSD(const char* path, uint32_t resumeFilePos) {
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
bool Audio::connecttoFS(fs::FS &fs, const char* path, uint32_t resumeFilePos) { bool Audio::connecttoFS(fs::FS &fs, const char* path, uint32_t resumeFilePos) {
if(strlen(path)>255) return false; xSemaphoreTake(mutex_audio, portMAX_DELAY);
if(strlen(path)>255){
xSemaphoreGive(mutex_audio);
return false;
}
m_resumeFilePos = resumeFilePos; m_resumeFilePos = resumeFilePos;
char audioName[256]; char audioName[256];
...@@ -698,6 +711,7 @@ bool Audio::connecttoFS(fs::FS &fs, const char* path, uint32_t resumeFilePos) { ...@@ -698,6 +711,7 @@ bool Audio::connecttoFS(fs::FS &fs, const char* path, uint32_t resumeFilePos) {
if(!audiofile) { if(!audiofile) {
if(audio_info) {vTaskDelay(2); audio_info("Failed to open file for reading");} if(audio_info) {vTaskDelay(2); audio_info("Failed to open file for reading");}
xSemaphoreGive(mutex_audio);
return false; return false;
} }
...@@ -731,11 +745,14 @@ bool Audio::connecttoFS(fs::FS &fs, const char* path, uint32_t resumeFilePos) { ...@@ -731,11 +745,14 @@ bool Audio::connecttoFS(fs::FS &fs, const char* path, uint32_t resumeFilePos) {
bool ret = initializeDecoder(); bool ret = initializeDecoder();
if(ret) m_f_running = true; if(ret) m_f_running = true;
else audiofile.close(); else audiofile.close();
xSemaphoreGive(mutex_audio);
return ret; return ret;
} }
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
bool Audio::connecttospeech(const char* speech, const char* lang){ bool Audio::connecttospeech(const char* speech, const char* lang){
xSemaphoreTake(mutex_audio, portMAX_DELAY);
setDefaults(); setDefaults();
char host[] = "translate.google.com.vn"; char host[] = "translate.google.com.vn";
char path[] = "/translate_tts"; char path[] = "/translate_tts";
...@@ -744,7 +761,11 @@ bool Audio::connecttospeech(const char* speech, const char* lang){ ...@@ -744,7 +761,11 @@ bool Audio::connecttospeech(const char* speech, const char* lang){
uint16_t speechBuffLen = speechLen + 300; uint16_t speechBuffLen = speechLen + 300;
memcpy(m_lastHost, speech, 256); memcpy(m_lastHost, speech, 256);
char* speechBuff = (char*)malloc(speechBuffLen); char* speechBuff = (char*)malloc(speechBuffLen);
if(!speechBuff) {log_e("out of memory"); return false;} if(!speechBuff) {
log_e("out of memory");
xSemaphoreGive(mutex_audio);
return false;
}
memcpy(speechBuff, speech, speechLen); memcpy(speechBuff, speech, speechLen);
speechBuff[speechLen] = '\0'; speechBuff[speechLen] = '\0';
urlencode(speechBuff, speechBuffLen); urlencode(speechBuff, speechBuffLen);
...@@ -769,6 +790,7 @@ bool Audio::connecttospeech(const char* speech, const char* lang){ ...@@ -769,6 +790,7 @@ bool Audio::connecttospeech(const char* speech, const char* lang){
_client = static_cast<WiFiClient*>(&client); _client = static_cast<WiFiClient*>(&client);
if(!_client->connect(host, 80)) { if(!_client->connect(host, 80)) {
log_e("Connection failed"); log_e("Connection failed");
xSemaphoreGive(mutex_audio);
return false; return false;
} }
_client->print(resp); _client->print(resp);
...@@ -778,7 +800,7 @@ bool Audio::connecttospeech(const char* speech, const char* lang){ ...@@ -778,7 +800,7 @@ bool Audio::connecttospeech(const char* speech, const char* lang){
m_f_ssl = false; m_f_ssl = false;
m_f_tts = true; m_f_tts = true;
setDatamode(HTTP_RESPONSE_HEADER); setDatamode(HTTP_RESPONSE_HEADER);
xSemaphoreGive(mutex_audio);
return true; return true;
} }
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
...@@ -822,6 +844,8 @@ bool Audio::connecttomarytts(const char* speech, const char* lang, const char* v ...@@ -822,6 +844,8 @@ bool Audio::connecttomarytts(const char* speech, const char* lang, const char* v
// bits1-hsmm de female hmm // bits1-hsmm de female hmm
// bits1 de female unitselection general // bits1 de female unitselection general
xSemaphoreTake(mutex_audio, portMAX_DELAY);
setDefaults(); setDefaults();
char host[] = "mary.dfki.de"; char host[] = "mary.dfki.de";
char path[] = "/process"; char path[] = "/process";
...@@ -831,7 +855,10 @@ bool Audio::connecttomarytts(const char* speech, const char* lang, const char* v ...@@ -831,7 +855,10 @@ bool Audio::connecttomarytts(const char* speech, const char* lang, const char* v
uint16_t speechBuffLen = speechLen + 300; uint16_t speechBuffLen = speechLen + 300;
memcpy(m_lastHost, speech, 256); memcpy(m_lastHost, speech, 256);
char* speechBuff = (char*)malloc(speechBuffLen); char* speechBuff = (char*)malloc(speechBuffLen);
if(!speechBuff) {log_e("out of memory"); return false;} if(!speechBuff) {log_e("out of memory");
xSemaphoreGive(mutex_audio);
return false;
}
memcpy(speechBuff, speech, speechLen); memcpy(speechBuff, speech, speechLen);
speechBuff[speechLen] = '\0'; speechBuff[speechLen] = '\0';
urlencode(speechBuff, speechBuffLen); urlencode(speechBuff, speechBuffLen);
...@@ -861,6 +888,7 @@ bool Audio::connecttomarytts(const char* speech, const char* lang, const char* v ...@@ -861,6 +888,7 @@ bool Audio::connecttomarytts(const char* speech, const char* lang, const char* v
_client = static_cast<WiFiClient*>(&client); _client = static_cast<WiFiClient*>(&client);
if(!_client->connect(host, port)) { if(!_client->connect(host, port)) {
log_e("Connection failed"); log_e("Connection failed");
xSemaphoreGive(mutex_audio);
return false; return false;
} }
_client->print(resp); _client->print(resp);
...@@ -871,6 +899,7 @@ bool Audio::connecttomarytts(const char* speech, const char* lang, const char* v ...@@ -871,6 +899,7 @@ bool Audio::connecttomarytts(const char* speech, const char* lang, const char* v
m_f_tts = true; m_f_tts = true;
setDatamode(HTTP_RESPONSE_HEADER); setDatamode(HTTP_RESPONSE_HEADER);
xSemaphoreGive(mutex_audio);
return true; return true;
} }
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
...@@ -2071,6 +2100,7 @@ uint32_t Audio::stopSong() { ...@@ -2071,6 +2100,7 @@ uint32_t Audio::stopSong() {
} }
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
bool Audio::pauseResume() { bool Audio::pauseResume() {
xSemaphoreTake(mutex_audio, portMAX_DELAY);
bool retVal = false; bool retVal = false;
if(getDatamode() == AUDIO_LOCALFILE || m_streamType == ST_WEBSTREAM) { if(getDatamode() == AUDIO_LOCALFILE || m_streamType == ST_WEBSTREAM) {
m_f_running = !m_f_running; m_f_running = !m_f_running;
...@@ -2080,6 +2110,7 @@ bool Audio::pauseResume() { ...@@ -2080,6 +2110,7 @@ bool Audio::pauseResume() {
i2s_zero_dma_buffer((i2s_port_t) m_i2s_num); i2s_zero_dma_buffer((i2s_port_t) m_i2s_num);
} }
} }
xSemaphoreGive(mutex_audio);
return retVal; return retVal;
} }
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
...@@ -2172,6 +2203,8 @@ void Audio::loop() { ...@@ -2172,6 +2203,8 @@ void Audio::loop() {
if(!m_f_running) return; if(!m_f_running) return;
xSemaphoreTake(mutex_audio, portMAX_DELAY);
if(m_playlistFormat != FORMAT_M3U8){ // normal process if(m_playlistFormat != FORMAT_M3U8){ // normal process
switch(getDatamode()){ switch(getDatamode()){
case AUDIO_LOCALFILE: case AUDIO_LOCALFILE:
...@@ -2243,6 +2276,7 @@ void Audio::loop() { ...@@ -2243,6 +2276,7 @@ void Audio::loop() {
break; break;
} }
} }
xSemaphoreGive(mutex_audio);
} }
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
bool Audio::readPlayListData() { bool Audio::readPlayListData() {
...@@ -4044,10 +4078,12 @@ bool Audio::setTimeOffset(int sec){ ...@@ -4044,10 +4078,12 @@ bool Audio::setTimeOffset(int sec){
} }
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
bool Audio::setFilePos(uint32_t pos) { bool Audio::setFilePos(uint32_t pos) {
xSemaphoreTakeRecursive(mutex_audio, portMAX_DELAY);
if(!audiofile) return false; if(!audiofile) return false;
if(pos < m_audioDataStart) pos = m_audioDataStart; // issue #96 if(pos < m_audioDataStart) pos = m_audioDataStart; // issue #96
if(pos > m_file_size) pos = m_file_size; if(pos > m_file_size) pos = m_file_size;
m_resumeFilePos = pos; m_resumeFilePos = pos;
xSemaphoreGiveRecursive(mutex_audio);
return true; return true;
} }
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* Audio.h * Audio.h
* *
* Created on: Oct 28,2018 * Created on: Oct 28,2018
* Updated on: Jan 08,2023 * Updated on: Jan 09,2023
* Author: Wolle (schreibfaul1) * Author: Wolle (schreibfaul1)
*/ */
...@@ -164,7 +164,6 @@ public: ...@@ -164,7 +164,6 @@ public:
~Audio(); ~Audio();
void setBufsize(int rambuf_sz, int psrambuf_sz); void setBufsize(int rambuf_sz, int psrambuf_sz);
bool connecttohost(const char* host, const char* user = "", const char* pwd = ""); bool connecttohost(const char* host, const char* user = "", const char* pwd = "");
bool connecttospeech(const char* speech, const char* lang); bool connecttospeech(const char* speech, const char* lang);
bool connecttomarytts(const char* speech, const char* lang, const char* voice); bool connecttomarytts(const char* speech, const char* lang, const char* voice);
bool connecttoFS(fs::FS &fs, const char* path, uint32_t resumeFilePos = 0); bool connecttoFS(fs::FS &fs, const char* path, uint32_t resumeFilePos = 0);
...@@ -465,6 +464,7 @@ private: ...@@ -465,6 +464,7 @@ private:
WiFiClient client; // @suppress("Abstract class cannot be instantiated") WiFiClient client; // @suppress("Abstract class cannot be instantiated")
WiFiClientSecure clientsecure; // @suppress("Abstract class cannot be instantiated") WiFiClientSecure clientsecure; // @suppress("Abstract class cannot be instantiated")
WiFiClient* _client = nullptr; WiFiClient* _client = nullptr;
SemaphoreHandle_t mutex_audio;
i2s_config_t m_i2s_config = {}; // stores values for I2S driver i2s_config_t m_i2s_config = {}; // stores values for I2S driver
i2s_pin_config_t m_pin_config = {}; i2s_pin_config_t m_pin_config = {};
std::vector<char*> m_playlistContent; // m3u8 playlist buffer std::vector<char*> m_playlistContent; // m3u8 playlist buffer
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment