mirror of
https://github.com/arendst/Tasmota.git
synced 2025-07-19 08:46:32 +00:00
i2spause (#23646)
This commit is contained in:
parent
3dec15322f
commit
ae3dbde4b1
@ -98,8 +98,12 @@ struct AUDIO_I2S_MP3_t {
|
|||||||
bool mic_stop = false;
|
bool mic_stop = false;
|
||||||
bool use_stream = false;
|
bool use_stream = false;
|
||||||
bool task_running = false;
|
bool task_running = false;
|
||||||
|
bool file_play_pausing = false;
|
||||||
bool task_has_ended = false;
|
bool task_has_ended = false;
|
||||||
|
bool file_has_paused = false;
|
||||||
bool task_loop_mode = 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
|
// RECORD/STREAM/ENCODING
|
||||||
uint32_t recdur;
|
uint32_t recdur;
|
||||||
@ -119,6 +123,10 @@ struct AUDIO_I2S_MP3_t {
|
|||||||
|
|
||||||
} audio_i2s_mp3;
|
} audio_i2s_mp3;
|
||||||
|
|
||||||
|
struct AUDIO_I2S_WEBRADIO_t {
|
||||||
|
AudioFileSourceICYStream *ifile = NULL;
|
||||||
|
} Audio_webradio;
|
||||||
|
|
||||||
#define I2S_AUDIO_MODE_MIC 1
|
#define I2S_AUDIO_MODE_MIC 1
|
||||||
#define I2S_AUDIO_MODE_SPK 2
|
#define I2S_AUDIO_MODE_SPK 2
|
||||||
|
|
||||||
@ -148,7 +156,7 @@ void I2sWrShow(bool json) {
|
|||||||
const char kI2SAudio_Commands[] PROGMEM = "I2S|"
|
const char kI2SAudio_Commands[] PROGMEM = "I2S|"
|
||||||
"Gain|Rec|Stop|Config"
|
"Gain|Rec|Stop|Config"
|
||||||
#ifdef USE_I2S_MP3
|
#ifdef USE_I2S_MP3
|
||||||
"|Play|Loop"
|
"|Play|Loop|Pause"
|
||||||
#endif
|
#endif
|
||||||
#ifdef USE_I2S_DEBUG
|
#ifdef USE_I2S_DEBUG
|
||||||
"|Mic" // debug only
|
"|Mic" // debug only
|
||||||
@ -178,6 +186,7 @@ void (* const I2SAudio_Command[])(void) PROGMEM = {
|
|||||||
#ifdef USE_I2S_MP3
|
#ifdef USE_I2S_MP3
|
||||||
&CmndI2SPlay,
|
&CmndI2SPlay,
|
||||||
&CmndI2SLoop,
|
&CmndI2SLoop,
|
||||||
|
&CmndI2SPause,
|
||||||
#endif
|
#endif
|
||||||
#ifdef USE_I2S_DEBUG
|
#ifdef USE_I2S_DEBUG
|
||||||
&CmndI2SMic,
|
&CmndI2SMic,
|
||||||
@ -678,10 +687,16 @@ int32_t I2SPrepareRx(void) {
|
|||||||
#if defined(USE_I2S_MP3) || defined(USE_I2S_WEBRADIO)
|
#if defined(USE_I2S_MP3) || defined(USE_I2S_WEBRADIO)
|
||||||
void I2sMp3Task(void *arg) {
|
void I2sMp3Task(void *arg) {
|
||||||
audio_i2s_mp3.task_running = true;
|
audio_i2s_mp3.task_running = true;
|
||||||
|
audio_i2s_mp3.file_play_pausing = false;
|
||||||
while (audio_i2s_mp3.decoder->isRunning() && audio_i2s_mp3.task_running) {
|
while (audio_i2s_mp3.decoder->isRunning() && audio_i2s_mp3.task_running) {
|
||||||
if (!audio_i2s_mp3.decoder->loop()) {
|
if (!audio_i2s_mp3.decoder->loop()) {
|
||||||
audio_i2s_mp3.task_running = false;
|
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));
|
vTaskDelay(pdMS_TO_TICKS(1));
|
||||||
}
|
}
|
||||||
audio_i2s.out->flush();
|
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));
|
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.audio_title[sizeof(audio_i2s_mp3.audio_title)-1] = 0;
|
||||||
|
audio_i2s_mp3.current_file_type = decoder_type; //save for i2spause
|
||||||
|
|
||||||
I2SAudioPower(true);
|
I2SAudioPower(true);
|
||||||
|
|
||||||
@ -815,6 +831,7 @@ int32_t I2SPlayFile(const char *path, uint32_t decoder_type) {
|
|||||||
|
|
||||||
if(I2SinitDecoder(decoder_type)){
|
if(I2SinitDecoder(decoder_type)){
|
||||||
audio_i2s_mp3.decoder->begin(audio_i2s_mp3.id3, audio_i2s.out);
|
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 {
|
} else {
|
||||||
return I2S_ERR_DECODER_FAILED_TO_INIT;
|
return I2S_ERR_DECODER_FAILED_TO_INIT;
|
||||||
}
|
}
|
||||||
@ -835,8 +852,14 @@ void mp3_delete(void) {
|
|||||||
delete audio_i2s_mp3.id3;
|
delete audio_i2s_mp3.id3;
|
||||||
delete audio_i2s_mp3.decoder;
|
delete audio_i2s_mp3.decoder;
|
||||||
audio_i2s_mp3.decoder = nullptr;
|
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
|
#endif // USE_I2S_MP3
|
||||||
|
|
||||||
/*********************************************************************************************\
|
/*********************************************************************************************\
|
||||||
@ -878,6 +901,7 @@ void CmndI2SStop(void) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
audio_i2s.out->setGain(0);
|
audio_i2s.out->setGain(0);
|
||||||
|
i2s_clean_pause_data();
|
||||||
ResponseCmndDone();
|
ResponseCmndDone();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -887,8 +911,25 @@ void CmndI2SLoop(void) {
|
|||||||
CmndI2SPlay();
|
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) {
|
void CmndI2SPlay(void) {
|
||||||
if (XdrvMailbox.data_len > 0) {
|
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);
|
int32_t err = I2SPlayFile(XdrvMailbox.data, XdrvMailbox.index);
|
||||||
// display return message
|
// display return message
|
||||||
switch (err) {
|
switch (err) {
|
||||||
@ -915,7 +956,13 @@ void CmndI2SPlay(void) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} 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
|
#endif // USE_I2S_MP3
|
||||||
@ -993,8 +1040,17 @@ void CmndI2SMicRec(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void I2sEventHandler(){
|
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){
|
if(audio_i2s_mp3.task_has_ended == true){
|
||||||
audio_i2s_mp3.task_has_ended = false;
|
audio_i2s_mp3.task_has_ended = false;
|
||||||
|
audio_i2s_mp3.task_running = false;
|
||||||
MqttPublishPayloadPrefixTopicRulesProcess_P(RESULT_OR_STAT,PSTR(""),PSTR("{\"Event\":{\"I2SPlay\":\"Ended\"}}"));
|
MqttPublishPayloadPrefixTopicRulesProcess_P(RESULT_OR_STAT,PSTR(""),PSTR("{\"Event\":{\"I2SPlay\":\"Ended\"}}"));
|
||||||
// Rule1 ON event#i2splay=ended DO <something> ENDON
|
// Rule1 ON event#i2splay=ended DO <something> ENDON
|
||||||
I2SAudioPower(false);
|
I2SAudioPower(false);
|
||||||
|
@ -20,10 +20,6 @@
|
|||||||
#if defined(ESP32) && ESP_IDF_VERSION_MAJOR >= 5
|
#if defined(ESP32) && ESP_IDF_VERSION_MAJOR >= 5
|
||||||
#if defined(USE_I2S_AUDIO) && defined(USE_I2S_WEBRADIO)
|
#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) {
|
void I2sMDCallback(void *cbData, const char *type, bool isUnicode, const char *str) {
|
||||||
const char *ptr = reinterpret_cast<const char *>(cbData);
|
const char *ptr = reinterpret_cast<const char *>(cbData);
|
||||||
(void) isUnicode; // Punt this ball for now
|
(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) {
|
bool I2SWebradio(const char *url, uint32_t decoder_type) {
|
||||||
|
|
||||||
size_t wr_tasksize = 8000; // suitable for ACC and MP3
|
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;
|
wr_tasksize = 26000;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user