This commit is contained in:
Christian Baars 2025-07-07 21:26:52 +02:00 committed by GitHub
parent 3dec15322f
commit ae3dbde4b1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 60 additions and 8 deletions

View File

@ -98,8 +98,12 @@ struct AUDIO_I2S_MP3_t {
bool mic_stop = false;
bool use_stream = false;
bool task_running = false;
bool file_play_pausing = false;
bool task_has_ended = false;
bool file_has_paused = false;
bool task_loop_mode = false;
uint8_t current_file_type = 0; // for resumed playback
uint32_t paused_position = 0; // position in the file for paused audio file
// RECORD/STREAM/ENCODING
uint32_t recdur;
@ -119,6 +123,10 @@ struct AUDIO_I2S_MP3_t {
} audio_i2s_mp3;
struct AUDIO_I2S_WEBRADIO_t {
AudioFileSourceICYStream *ifile = NULL;
} Audio_webradio;
#define I2S_AUDIO_MODE_MIC 1
#define I2S_AUDIO_MODE_SPK 2
@ -148,7 +156,7 @@ void I2sWrShow(bool json) {
const char kI2SAudio_Commands[] PROGMEM = "I2S|"
"Gain|Rec|Stop|Config"
#ifdef USE_I2S_MP3
"|Play|Loop"
"|Play|Loop|Pause"
#endif
#ifdef USE_I2S_DEBUG
"|Mic" // debug only
@ -178,6 +186,7 @@ void (* const I2SAudio_Command[])(void) PROGMEM = {
#ifdef USE_I2S_MP3
&CmndI2SPlay,
&CmndI2SLoop,
&CmndI2SPause,
#endif
#ifdef USE_I2S_DEBUG
&CmndI2SMic,
@ -678,10 +687,16 @@ int32_t I2SPrepareRx(void) {
#if defined(USE_I2S_MP3) || defined(USE_I2S_WEBRADIO)
void I2sMp3Task(void *arg) {
audio_i2s_mp3.task_running = true;
audio_i2s_mp3.file_play_pausing = false;
while (audio_i2s_mp3.decoder->isRunning() && audio_i2s_mp3.task_running) {
if (!audio_i2s_mp3.decoder->loop()) {
audio_i2s_mp3.task_running = false;
}
if (audio_i2s_mp3.file_play_pausing == true) {
audio_i2s_mp3.paused_position = audio_i2s_mp3.file->getPos();
audio_i2s_mp3.decoder->stop();
audio_i2s_mp3.file_has_paused = true;
}
vTaskDelay(pdMS_TO_TICKS(1));
}
audio_i2s.out->flush();
@ -797,6 +812,7 @@ int32_t I2SPlayFile(const char *path, uint32_t decoder_type) {
strncpy(audio_i2s_mp3.audio_title, fname, sizeof(audio_i2s_mp3.audio_title));
audio_i2s_mp3.audio_title[sizeof(audio_i2s_mp3.audio_title)-1] = 0;
audio_i2s_mp3.current_file_type = decoder_type; //save for i2spause
I2SAudioPower(true);
@ -815,6 +831,7 @@ int32_t I2SPlayFile(const char *path, uint32_t decoder_type) {
if(I2SinitDecoder(decoder_type)){
audio_i2s_mp3.decoder->begin(audio_i2s_mp3.id3, audio_i2s.out);
audio_i2s_mp3.file->seek(audio_i2s_mp3.paused_position, 1); // seek to the position where we paused or have it set to 0, 1 = SEEK_CUR
} else {
return I2S_ERR_DECODER_FAILED_TO_INIT;
}
@ -835,8 +852,14 @@ void mp3_delete(void) {
delete audio_i2s_mp3.id3;
delete audio_i2s_mp3.decoder;
audio_i2s_mp3.decoder = nullptr;
}
void i2s_clean_pause_data(void) {
audio_i2s_mp3.current_file_type = MP3_DECODER;
audio_i2s_mp3.paused_position = 0;
audio_i2s_mp3.file_play_pausing = false;
}
#endif // USE_I2S_MP3
/*********************************************************************************************\
@ -878,6 +901,7 @@ void CmndI2SStop(void) {
return;
}
audio_i2s.out->setGain(0);
i2s_clean_pause_data();
ResponseCmndDone();
}
@ -887,8 +911,25 @@ void CmndI2SLoop(void) {
CmndI2SPlay();
}
void CmndI2SPause(void) {
if(audio_i2s_mp3.task_running
#ifdef MP3_MIC_STREAM
&& !audio_i2s_mp3.stream_active
#endif //MP3_MIC_STREAM
#ifdef USE_I2S_WEBRADIO
&& Audio_webradio.ifile == nullptr
#endif // USE_I2S_WEBRADIO
){
audio_i2s_mp3.file_play_pausing = true;
ResponseCmndChar("Player Paused");
} else {
ResponseCmndChar("Player not running"); // or webradio is using decoder
}
}
void CmndI2SPlay(void) {
if (XdrvMailbox.data_len > 0) {
i2s_clean_pause_data(); // clean up any previous pause data, set start to 0
int32_t err = I2SPlayFile(XdrvMailbox.data, XdrvMailbox.index);
// display return message
switch (err) {
@ -915,7 +956,13 @@ void CmndI2SPlay(void) {
break;
}
} else {
ResponseCmndChar("Missing filename");
if(audio_i2s_mp3.file_play_pausing == true){
int32_t err = I2SPlayFile((const char *)audio_i2s_mp3.audio_title, (uint32_t)audio_i2s_mp3.current_file_type); // the line above should rule out basically any error, but we'll see ...
AddLog(LOG_LEVEL_DEBUG, "I2S: Resume: %s, type: %i at %i , err: %i", audio_i2s_mp3.audio_title, audio_i2s_mp3.current_file_type, audio_i2s_mp3.paused_position, err);
ResponseCmndChar("Player resumed");
} else {
ResponseCmndChar("Missing filename");
}
}
}
#endif // USE_I2S_MP3
@ -993,8 +1040,17 @@ void CmndI2SMicRec(void) {
}
void I2sEventHandler(){
if(audio_i2s_mp3.file_has_paused == true){
audio_i2s_mp3.task_has_ended = false; //do not send ended event
audio_i2s_mp3.file_has_paused = false;
audio_i2s_mp3.task_running = false;
MqttPublishPayloadPrefixTopicRulesProcess_P(RESULT_OR_STAT,PSTR(""),PSTR("{\"Event\":{\"I2SPlay\":\"Paused\"}}"));
// Rule1 ON event#i2splay=paused DO <something> ENDON
I2SAudioPower(false);
}
if(audio_i2s_mp3.task_has_ended == true){
audio_i2s_mp3.task_has_ended = false;
audio_i2s_mp3.task_running = false;
MqttPublishPayloadPrefixTopicRulesProcess_P(RESULT_OR_STAT,PSTR(""),PSTR("{\"Event\":{\"I2SPlay\":\"Ended\"}}"));
// Rule1 ON event#i2splay=ended DO <something> ENDON
I2SAudioPower(false);

View File

@ -20,10 +20,6 @@
#if defined(ESP32) && ESP_IDF_VERSION_MAJOR >= 5
#if defined(USE_I2S_AUDIO) && defined(USE_I2S_WEBRADIO)
struct AUDIO_I2S_WEBRADIO_t {
AudioFileSourceICYStream *ifile = NULL;
} Audio_webradio;
void I2sMDCallback(void *cbData, const char *type, bool isUnicode, const char *str) {
const char *ptr = reinterpret_cast<const char *>(cbData);
(void) isUnicode; // Punt this ball for now
@ -43,7 +39,7 @@ void I2SWrStatusCB(void *cbData, int code, const char *str){
bool I2SWebradio(const char *url, uint32_t decoder_type) {
size_t wr_tasksize = 8000; // suitable for ACC and MP3
if(decoder_type == 2){ // opus needs a ton of stack
if(decoder_type == OPUS_DECODER){ // opus needs a ton of stack
wr_tasksize = 26000;
}