From 495d4375dac79bdd51a8670f4c5451f6f76ac4af Mon Sep 17 00:00:00 2001 From: e2002 Date: Thu, 15 Dec 2022 17:49:44 +0300 Subject: [PATCH] sd_i2s+sd_vs_v1 --- exsamples/myoptions.h | 1 + yoRadio/data/www/style.css.gz | Bin 6382 -> 6383 bytes yoRadio/src/audioI2S/Audio.cpp | 60 +++++++++++++++------- yoRadio/src/audioI2S/AudioEx.h | 6 ++- yoRadio/src/audioVS1053/audioVS1053Ex.cpp | 53 +++++++++++++------ yoRadio/src/audioVS1053/audioVS1053Ex.h | 6 ++- yoRadio/src/core/config.cpp | 33 ++++++------ yoRadio/src/core/config.h | 4 +- yoRadio/src/core/controls.cpp | 12 +++-- yoRadio/src/core/display.cpp | 7 ++- yoRadio/src/core/display.h | 2 +- yoRadio/src/core/netserver.cpp | 6 ++- yoRadio/src/core/network.cpp | 1 + yoRadio/src/core/options.h | 4 +- yoRadio/src/core/player.cpp | 16 ++++-- yoRadio/yoRadio.ino | 47 +++++++++++++++++ 16 files changed, 191 insertions(+), 67 deletions(-) diff --git a/exsamples/myoptions.h b/exsamples/myoptions.h index 0272003..22a47c2 100644 --- a/exsamples/myoptions.h +++ b/exsamples/myoptions.h @@ -73,6 +73,7 @@ The connection tables are located here https://github.com/e2002/yoradio#connecti /******************************************/ /* SDCARD */ +/* MISO is the same as D0, MOSI is the same as D1 */ //#define SDC_SPI 18, 19, 23 /* SDCARD SPI pins (SCK, MISO, MOSI) */ //#define SDC_CS 255 /* SDCARD CS pin */ diff --git a/yoRadio/data/www/style.css.gz b/yoRadio/data/www/style.css.gz index 81c91324474891bb9fbf622fcab4d52e5a4eef5e..2d9fc53b7203bad0d715b16b4c58dc7d62be0243 100644 GIT binary patch delta 5392 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 0) { InBuff.bytesWritten(bytesAddedToBuffer); } @@ -2974,14 +2990,14 @@ void Audio::processLocalFile() { } //TEST loop f_stream = false; m_streamType = ST_NONE; - +cardLock(true); #ifdef SDFATFS_USED audiofile.getName(chbuf, sizeof(chbuf)); char *afn =strdup(chbuf); #else char *afn =strdup(audiofile.name()); // store temporary the name #endif - +cardLock(false); stopSong(); if(m_codec == CODEC_MP3) MP3Decoder_FreeBuffers(); if(m_codec == CODEC_AAC) AACDecoder_FreeBuffers(); @@ -4336,12 +4352,18 @@ bool Audio::setPinout(uint8_t BCLK, uint8_t LRC, uint8_t DOUT, int8_t DIN, int8_ //--------------------------------------------------------------------------------------------------------------------- uint32_t Audio::getFileSize() { if(!audiofile) return 0; - return audiofile.size(); + cardLock(true); + uint32_t s = audiofile.size(); + cardLock(false); + return s; } //--------------------------------------------------------------------------------------------------------------------- uint32_t Audio::getFilePos() { if(!audiofile) return 0; - return audiofile.position(); + cardLock(true); + uint32_t p = audiofile.position(); + cardLock(false); + return p; } //--------------------------------------------------------------------------------------------------------------------- uint32_t Audio::getAudioDataStartPos() { diff --git a/yoRadio/src/audioI2S/AudioEx.h b/yoRadio/src/audioI2S/AudioEx.h index 5d6ab3f..3e8a070 100644 --- a/yoRadio/src/audioI2S/AudioEx.h +++ b/yoRadio/src/audioI2S/AudioEx.h @@ -73,6 +73,10 @@ using namespace std; extern __attribute__((weak)) void audio_info(const char*); extern __attribute__((weak)) void audio_id3data(const char*); //ID3 metadata +extern __attribute__((weak)) void audio_id3artist(const char*); +extern __attribute__((weak)) void audio_id3album(const char*); +extern __attribute__((weak)) void audio_id3title(const char*); +extern __attribute__((weak)) void audio_beginSDread(); extern __attribute__((weak)) void audio_id3image(File& file, const size_t pos, const size_t size); //ID3 metadata image extern __attribute__((weak)) void audio_eof_mp3(const char*); //end of mp3 file extern __attribute__((weak)) void audio_showstreamtitle(const char*); @@ -213,7 +217,7 @@ public: void setI2SCommFMT_LSB(bool commFMT); int getCodec() {return m_codec;} const char *getCodecname() {return codecname[m_codec];} - + void cardLock(bool lock); private: #ifndef ESP_ARDUINO_VERSION_VAL diff --git a/yoRadio/src/audioVS1053/audioVS1053Ex.cpp b/yoRadio/src/audioVS1053/audioVS1053Ex.cpp index 8ed90f4..03ddd65 100644 --- a/yoRadio/src/audioVS1053/audioVS1053Ex.cpp +++ b/yoRadio/src/audioVS1053/audioVS1053Ex.cpp @@ -568,6 +568,16 @@ void Audio::showstreamtitle(const char* ml) { } } //--------------------------------------------------------------------------------------------------------------------- +void Audio::cardLock(bool lock){ +#if (TFT_CS!=255) || (SDC_CS!=255) + if(lock){ + xSemaphoreTake(mutex_pl, portMAX_DELAY); + }else{ + xSemaphoreGive(mutex_pl); + } +#endif +} +//--------------------------------------------------------------------------------------------------------------------- void Audio::loop(){ // - localfile - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - if(m_f_localfile) { // Playing file fron SPIFFS or SD? @@ -634,7 +644,7 @@ void Audio::processLocalFile() { } } //---------------------------------------------------------------------------------------------------- - bytesAddedToBuffer = audiofile.read(InBuff.getWritePtr(), bytesCanBeWritten); + cardLock(true); bytesAddedToBuffer = audiofile.read(InBuff.getWritePtr(), bytesCanBeWritten); cardLock(false); if(bytesAddedToBuffer > 0) { InBuff.bytesWritten(bytesAddedToBuffer); } @@ -718,9 +728,9 @@ void Audio::processLocalFile() { f_stream = false; m_f_localfile = false; - + cardLock(true); char *afn =strdup(audiofile.name()); // store temporary the name - + cardLock(false); stopSong(); sprintf(chbuf, "End of file \"%s\"", afn); if(audio_info) audio_info(chbuf); @@ -1562,7 +1572,7 @@ uint32_t Audio::stop_mp3client(){ uint32_t pos = 0; if(m_f_localfile){ pos = getFilePos() - InBuff.bufferFilled(); - audiofile.close(); + cardLock(true); audiofile.close(); cardLock(false); m_f_localfile=false; } int v=read_register(SCI_VOL); @@ -1897,14 +1907,14 @@ bool Audio::connecttoFS(fs::FS &fs, const char* path, uint32_t resumeFilePos) { sprintf(chbuf, "Reading file: \"%s\"", audioName); if(audio_info) {vTaskDelay(2); audio_info(chbuf);} - - audiofile.close(); + if(audio_beginSDread) audio_beginSDread(); + cardLock(true); audiofile.close(); cardLock(false); if(fs.exists(audioName)) { - audiofile = fs.open(audioName); + cardLock(true); audiofile = fs.open(audioName); cardLock(false); } else { UTF8toASCII(audioName); if(fs.exists(audioName)) { - audiofile = fs.open(audioName); + cardLock(true); audiofile = fs.open(audioName); cardLock(false); } } @@ -1914,9 +1924,11 @@ bool Audio::connecttoFS(fs::FS &fs, const char* path, uint32_t resumeFilePos) { } m_f_localfile = true; + cardLock(true); m_file_size = audiofile.size();//TEST loop - + char* afn = strdup(audiofile.name()); // audioFileName + cardLock(false); uint8_t dotPos = lastIndexOf(afn, "."); for(uint8_t i = dotPos + 1; i < strlen(afn); i++){ afn[i] = toLowerCase(afn[i]); @@ -1960,7 +1972,7 @@ bool Audio::connecttoFS(fs::FS &fs, const char* path, uint32_t resumeFilePos) { sprintf(chbuf, "The %s format is not supported", afn + dotPos); if(audio_info) audio_info(chbuf); - audiofile.close(); + cardLock(true); audiofile.close(); cardLock(false); if(afn) free(afn); return false; } @@ -2391,7 +2403,7 @@ void Audio::showID3Tag(const char* tag, const char* value){ if(!strcmp(tag, "OWNE")) sprintf(chbuf, "Ownership: %s", value); // if(!strcmp(tag, "PRIV")) sprintf(chbuf, "Private: %s", value); if(!strcmp(tag, "SYLT")) sprintf(chbuf, "SynLyrics: %s", value); - if(!strcmp(tag, "TALB")) sprintf(chbuf, "Album: %s", value); + if(!strcmp(tag, "TALB")) { sprintf(chbuf, "Album: %s", value); if(audio_id3album) audio_id3album(value); } if(!strcmp(tag, "TBPM")) sprintf(chbuf, "BeatsPerMinute: %s", value); if(!strcmp(tag, "TCMP")) sprintf(chbuf, "Compilation: %s", value); if(!strcmp(tag, "TCOM")) sprintf(chbuf, "Composer: %s", value); @@ -2401,7 +2413,7 @@ void Audio::showID3Tag(const char* tag, const char* value){ if(!strcmp(tag, "TEXT")) sprintf(chbuf, "Lyricist: %s", value); if(!strcmp(tag, "TIME")) sprintf(chbuf, "Time: %s", value); if(!strcmp(tag, "TIT1")) sprintf(chbuf, "Grouping: %s", value); - if(!strcmp(tag, "TIT2")) sprintf(chbuf, "Title: %s", value); + if(!strcmp(tag, "TIT2")) { sprintf(chbuf, "Title: %s", value); if(audio_id3album) audio_id3album(value); } if(!strcmp(tag, "TIT3")) sprintf(chbuf, "Subtitle: %s", value); if(!strcmp(tag, "TLAN")) sprintf(chbuf, "Language: %s", value); if(!strcmp(tag, "TLEN")) sprintf(chbuf, "Length (ms): %s", value); @@ -2409,7 +2421,7 @@ void Audio::showID3Tag(const char* tag, const char* value){ if(!strcmp(tag, "TOAL")) sprintf(chbuf, "OriginalAlbum: %s", value); if(!strcmp(tag, "TOPE")) sprintf(chbuf, "OriginalArtist: %s", value); if(!strcmp(tag, "TORY")) sprintf(chbuf, "OriginalReleaseYear: %s", value); - if(!strcmp(tag, "TPE1")) sprintf(chbuf, "Artist: %s", value); + if(!strcmp(tag, "TPE1")) { sprintf(chbuf, "Artist: %s", value); if(audio_id3artist) audio_id3artist(value); } if(!strcmp(tag, "TPE2")) sprintf(chbuf, "Band: %s", value); if(!strcmp(tag, "TPE3")) sprintf(chbuf, "Conductor: %s", value); if(!strcmp(tag, "TPE4")) sprintf(chbuf, "InterpretedBy: %s", value); @@ -2431,17 +2443,26 @@ void Audio::showID3Tag(const char* tag, const char* value){ //--------------------------------------------------------------------------------------------------------------------- uint32_t Audio::getFileSize(){ if (!audiofile) return 0; - return audiofile.size(); + cardLock(true); + uint32_t s = audiofile.size(); + cardLock(false); + return s; } //--------------------------------------------------------------------------------------------------------------------- uint32_t Audio::getFilePos(){ if (!audiofile) return 0; - return audiofile.position(); + cardLock(true); + uint32_t p = audiofile.position(); + cardLock(false); + return p; } //--------------------------------------------------------------------------------------------------------------------- bool Audio::setFilePos(uint32_t pos){ if (!audiofile) return false; - return audiofile.seek(pos); + cardLock(true); + uint32_t s = audiofile.seek(pos); + cardLock(false); + return s; } //--------------------------------------------------------------------------------------------------------------------- uint32_t Audio::getAudioDataStartPos() { diff --git a/yoRadio/src/audioVS1053/audioVS1053Ex.h b/yoRadio/src/audioVS1053/audioVS1053Ex.h index b7020ba..3151114 100644 --- a/yoRadio/src/audioVS1053/audioVS1053Ex.h +++ b/yoRadio/src/audioVS1053/audioVS1053Ex.h @@ -36,6 +36,10 @@ extern __attribute__((weak)) void audio_showstreamtitle(const char*); extern __attribute__((weak)) void audio_showstation(const char*); extern __attribute__((weak)) void audio_showstreaminfo(const char*); extern __attribute__((weak)) void audio_id3data(const char*); //ID3 metadata +extern __attribute__((weak)) void audio_id3artist(const char*); +extern __attribute__((weak)) void audio_id3album(const char*); +extern __attribute__((weak)) void audio_id3title(const char*); +extern __attribute__((weak)) void audio_beginSDread(); extern __attribute__((weak)) void audio_id3image(File& file, const size_t pos, const size_t size); //ID3 metadata image extern __attribute__((weak)) void audio_eof_mp3(const char*); extern __attribute__((weak)) void audio_eof_speech(const char*); @@ -311,7 +315,7 @@ public: void setVUmeter(); void getVUlevel(); uint8_t vuLeft, vuRight; - + void cardLock(bool lock); // implement several function with respect to the index of string bool startsWith (const char* base, const char* str) { return (strstr(base, str) - base) == 0;} bool endsWith (const char* base, const char* str) { diff --git a/yoRadio/src/core/config.cpp b/yoRadio/src/core/config.cpp index 5a07319..f4c36d8 100644 --- a/yoRadio/src/core/config.cpp +++ b/yoRadio/src/core/config.cpp @@ -9,7 +9,7 @@ Config config; #if DSP_HSPI || TS_HSPI || VS_HSPI SPIClass SPI2(HSPI); #endif -SPIClass SDSPI(VSPI); +//SPIClass SDSPI(VSPI); void u8fix(char *src){ char last = src[strlen(src)-1]; @@ -32,10 +32,11 @@ void Config::init() { loadTheme(); ssidsCount = 0; - if(SDC_CS!=255 && store.play_mode==PM_WEB){ - pinMode(SDC_CS, OUTPUT); digitalWrite(SDC_CS, HIGH); - SDSPI.begin(SDC_SPI); - SDSPI.setFrequency(1000000); + if(SDC_CS!=255 && store.play_mode==PM_SDCARD){ + //pinMode(SDC_CS, OUTPUT); digitalWrite(SDC_CS, HIGH); + //SDSPI.begin(SDC_SPI); + //SDSPI.setFrequency(1000000); + //SDSPI.setFrequency(100000); if(!SD.begin(SDC_CS)){ store.play_mode=PM_WEB; Serial.println("##[ERROR]#\tCard Mount Failed"); @@ -49,6 +50,7 @@ void Config::init() { store.lastStation = 1; save(); } + loadStation(store.lastStation); #if IR_PIN!=255 eepromRead(EEPROM_START_IR, ircodes); @@ -297,11 +299,11 @@ bool endsWith (const char* base, const char* str) { void Config::listSD(File &plSDfile, File &plSDindex, const char * dirname, uint8_t levels){ File root = SD.open(dirname); if(!root){ - Serial.println("Failed to open directory"); + Serial.println("##[ERROR]#\tFailed to open directory"); return; } if(!root.isDirectory()){ - Serial.println("Not a directory"); + Serial.println("##[ERROR]#\tNot a directory"); return; } @@ -315,12 +317,10 @@ void Config::listSD(File &plSDfile, File &plSDindex, const char * dirname, uint8 listSD(plSDfile, plSDindex, file.path(), levels -1); } } else { - if(endsWith(file.name(), ".mp3") || endsWith(file.name(), ".m4a") || endsWith(file.name(), ".aac") || endsWith(file.name(), ".wav") || endsWith(file.name(), ".flac")){ + if(endsWith(strlwr((char*)file.name()), ".mp3") || endsWith(file.name(), ".m4a") || endsWith(file.name(), ".aac") || endsWith(file.name(), ".wav") || endsWith(file.name(), ".flac")){ pos = plSDfile.position(); plSDfile.print(file.name()); plSDfile.print("\t"); plSDfile.print(file.path()); plSDfile.print("\t"); plSDfile.println(0); plSDindex.write((byte *) &pos, 4); - Serial.print(" plSDfile.position:\t"); - Serial.println(pos); } } file = root.openNextFile(); @@ -342,8 +342,9 @@ void Config::initSDPlaylist() { store.countStation = 0; indexSDPlaylist(); if (SPIFFS.exists(INDEX_SD_PATH)) { - File index = SD.open(INDEX_SD_PATH, "r"); + File index = SPIFFS.open(INDEX_SD_PATH, "r"); store.countStation = index.size() / 4; + store.lastStation = random(1, store.countStation); index.close(); save(); } @@ -362,9 +363,9 @@ void Config::loadStation(uint16_t ls) { if (ls > store.countStation) { ls = 1; } - File playlist = SPIFFS.open(PLAYLIST_PATH, "r"); + File playlist = SPIFFS.open(REAL_PLAYL, "r"); - File index = SPIFFS.open(INDEX_PATH, "r"); + File index = SPIFFS.open(REAL_INDEX, "r"); index.seek((ls - 1) * 4, SeekSet); uint32_t pos; @@ -378,7 +379,7 @@ void Config::loadStation(uint16_t ls) { strncpy(station.name, sName, BUFLEN); strncpy(station.url, sUrl, BUFLEN); station.ovol = sOvol; - setLastStation(ls); + if(store.play_mode==PM_WEB) setLastStation(ls); } playlist.close(); } @@ -392,8 +393,8 @@ void Config::fillPlMenu(char plmenu[][40], int from, byte count, bool removeNum) if (store.countStation == 0) { return; } - File playlist = SPIFFS.open(PLAYLIST_PATH, "r"); - File index = SPIFFS.open(INDEX_PATH, "r"); + File playlist = SPIFFS.open(REAL_PLAYL, "r"); + File index = SPIFFS.open(REAL_INDEX, "r"); while (true) { if (ls < 1) { ls++; diff --git a/yoRadio/src/core/config.h b/yoRadio/src/core/config.h index 07f52c2..6a9458b 100644 --- a/yoRadio/src/core/config.h +++ b/yoRadio/src/core/config.h @@ -4,7 +4,7 @@ #include #include #include -#include +#include "SD.h" #include "options.h" #define EEPROM_SIZE 768 @@ -29,6 +29,8 @@ #endif #define BOOTLOG( ... ) { char buf[120]; sprintf( buf, __VA_ARGS__ ) ; Serial.print("##[BOOT]#\t"); Serial.println(buf); } #define EVERY_MS(x) static uint32_t tmr; bool flag = millis() - tmr >= (x); if (flag) tmr += (x); if (flag) +#define REAL_PLAYL store.play_mode==PM_WEB?PLAYLIST_PATH:PLAYLIST_SD_PATH +#define REAL_INDEX store.play_mode==PM_WEB?INDEX_PATH:INDEX_SD_PATH #define MAX_PLAY_MODE 1 diff --git a/yoRadio/src/core/controls.cpp b/yoRadio/src/core/controls.cpp index e8e80eb..adff3a6 100644 --- a/yoRadio/src/core/controls.cpp +++ b/yoRadio/src/core/controls.cpp @@ -363,8 +363,8 @@ void onBtnLongPressStart(int id) { break; } case EVT_BTNMODE: { - //onBtnClick(EVT_BTNMODE); - config.doSleepW(); + //config.doSleepW(); + display.putRequest(NEWMODE, SLEEPING); break; } default: break; @@ -380,6 +380,10 @@ void onBtnLongPressStop(int id) { lpId = -1; break; } + case EVT_BTNMODE: { + config.doSleepW(); + break; + } default: break; } @@ -498,9 +502,9 @@ void onBtnClick(int id) { config.store.play_mode++; if(config.store.play_mode > MAX_PLAY_MODE){ config.store.play_mode=0; - config.save(); - ESP.restart(); } + config.save(); + ESP.restart(); break; } default: break; diff --git a/yoRadio/src/core/display.cpp b/yoRadio/src/core/display.cpp index def32e2..26dab6a 100644 --- a/yoRadio/src/core/display.cpp +++ b/yoRadio/src/core/display.cpp @@ -262,6 +262,7 @@ void Display::_swichMode(displayMode_e newmode) { } if (newmode == LOST) _showDialog(const_DlgLost); if (newmode == UPDATING) _showDialog(const_DlgUpdate); + if (newmode == SLEEPING) _showDialog("SLEEPING"); if (newmode == INFO || newmode == SETTINGS || newmode == TIMEZONE || newmode == WIFI) _showDialog(const_DlgNextion); if (newmode == NUMBERS) _showDialog(""); if (newmode == STATIONS) { @@ -443,8 +444,12 @@ void Display::_title() { /*#ifdef USE_NEXTION nextion.newTitle(config.station.title); #endif*/ - if (player_on_track_change) player_on_track_change(); + + }else{ + _title1.setText(""); + if(_title2) _title2->setText(""); } + if (player_on_track_change) player_on_track_change(); } void Display::_time(bool redraw) { diff --git a/yoRadio/src/core/display.h b/yoRadio/src/core/display.h index 18c9f0a..2b85613 100644 --- a/yoRadio/src/core/display.h +++ b/yoRadio/src/core/display.h @@ -8,7 +8,7 @@ #include "../displays/dspcore.h" -enum displayMode_e { PLAYER, VOL, STATIONS, NUMBERS, LOST, UPDATING, INFO, SETTINGS, TIMEZONE, WIFI, CLEAR }; +enum displayMode_e { PLAYER, VOL, STATIONS, NUMBERS, LOST, UPDATING, INFO, SETTINGS, TIMEZONE, WIFI, CLEAR, SLEEPING }; enum pages_e : uint8_t { PG_PLAYER=0, PG_DIALOG=1, PG_PLAYLIST=2 }; //enum dialogType_e : uint8_t { DG_NONE=0, DG_VOLUME=1, DG_LOST=2, DG_UPDATING=3, DG_NEXTION=4 }; diff --git a/yoRadio/src/core/netserver.cpp b/yoRadio/src/core/netserver.cpp index 87fdc99..a6d38ba 100644 --- a/yoRadio/src/core/netserver.cpp +++ b/yoRadio/src/core/netserver.cpp @@ -636,7 +636,11 @@ void handleHTTPArgs(AsyncWebServerRequest * request) { #ifdef MQTT_HOST if (strcmp(request->url().c_str(), PLAYLIST_PATH) == 0) while (mqttplaylistblock) vTaskDelay(5); #endif - netserver.chunkedHtmlPage("application/octet-stream", request, request->url().c_str()); + if(strcmp(request->url().c_str(), PLAYLIST_PATH) == 0 && config.store.play_mode==PM_SDCARD){ + netserver.chunkedHtmlPage("application/octet-stream", request, PLAYLIST_SD_PATH); + }else{ + netserver.chunkedHtmlPage("application/octet-stream", request, request->url().c_str()); + } return; } if (strcmp(request->url().c_str(), "/") == 0 && request->params() == 0) { diff --git a/yoRadio/src/core/network.cpp b/yoRadio/src/core/network.cpp index 144f4ce..59c7e07 100644 --- a/yoRadio/src/core/network.cpp +++ b/yoRadio/src/core/network.cpp @@ -76,6 +76,7 @@ void Network::begin() { errcnt = 0; ls++; if (ls > config.ssidsCount - 1) ls = 0; + Serial.println(); break; } } diff --git a/yoRadio/src/core/options.h b/yoRadio/src/core/options.h index 15f9ba5..cd4b916 100644 --- a/yoRadio/src/core/options.h +++ b/yoRadio/src/core/options.h @@ -1,7 +1,7 @@ #ifndef options_h #define options_h -#define YOVERSION "0.9.000" +#define YOVERSION "0.8.800" /******************************************************* DO NOT EDIT THIS FILE. @@ -58,7 +58,7 @@ The connection tables are located here https://github.com/e2002/yoradio#connecti /* TFT DISPLAY */ #ifndef TFT_CS - #define TFT_CS 5 + #define TFT_CS 255 #endif #ifndef TFT_RST #define TFT_RST 15 // Or set to -1 and connect to Esp EN pin diff --git a/yoRadio/src/core/player.cpp b/yoRadio/src/core/player.cpp index d8c56db..54cde3d 100644 --- a/yoRadio/src/core/player.cpp +++ b/yoRadio/src/core/player.cpp @@ -128,7 +128,7 @@ void Player::play(uint16_t stationId) { display.putRequest(PSTOP); setDefaults(); setOutputPins(false); - config.setTitle(const_PlConnect); + config.setTitle(config.store.play_mode==PM_WEB?const_PlConnect:""); config.station.bitrate=0; netserver.requestOnChange(TITLE, 0); config.loadStation(stationId); @@ -136,8 +136,10 @@ void Player::play(uint16_t stationId) { display.putRequest(NEWSTATION); netserver.requestOnChange(STATION, 0); telnet.printf("##CLI.NAMESET#: %d %s\n", config.store.lastStation, config.station.name); - if (connecttohost(config.station.url)) { + if (config.store.play_mode==PM_WEB?connecttohost(config.station.url):connecttoFS(SD,config.station.url)) { mode = PLAYING; + config.setTitle(""); + netserver.requestOnChange(TITLE, 0); config.setSmartStart(1); netserver.requestOnChange(MODE, 0); setOutputPins(true); @@ -150,13 +152,19 @@ void Player::play(uint16_t stationId) { } void Player::prev() { - if (config.store.lastStation == 1) config.store.lastStation = config.store.countStation; else config.store.lastStation--; + if(config.store.play_mode==PM_WEB){ + if (config.store.lastStation == 1) config.store.lastStation = config.store.countStation; else config.store.lastStation--; + } request.station = config.store.lastStation; request.doSave = true; } void Player::next() { - if (config.store.lastStation == config.store.countStation) config.store.lastStation = 1; else config.store.lastStation++; + if(config.store.play_mode==PM_WEB){ + if (config.store.lastStation == config.store.countStation) config.store.lastStation = 1; else config.store.lastStation++; + }else{ + config.store.lastStation = random(1, config.store.countStation); + } request.station = config.store.lastStation; request.doSave = true; } diff --git a/yoRadio/yoRadio.ino b/yoRadio/yoRadio.ino index bbae0c8..7a2f255 100644 --- a/yoRadio/yoRadio.ino +++ b/yoRadio/yoRadio.ino @@ -100,8 +100,17 @@ void audio_info(const char *info) { #ifdef USE_NEXTION nextion.audioinfo(info); #endif + if (strstr(info, "skip metadata") != NULL){ + config.setTitle(config.station.name); + netserver.requestOnChange(TITLE, 0); + } if (strstr(info, "failed!") != NULL || strstr(info, " 404") != NULL || strstr(info, " 403") != NULL || strstr(info, "address is empty") != NULL) player.stop(info); if (strstr(info, "not supported") != NULL || strstr(info, "Account already in use") != NULL || strstr(info, "HTTP/1.0 401") != NULL) player.stop(info); + char* ici; char b[20]={0}; + if ((ici = strstr(info, "BitRate: ")) != NULL) { + strlcpy(b, ici + 9, 50); + audio_bitrate(b); + } } void audio_bitrate(const char *info) @@ -149,3 +158,41 @@ void audio_showstreamtitle(const char *info) { netserver.requestOnChange(TITLE, 0); } } + +void audio_id3artist(const char *info){ + if(printable(info)) config.setStation(info); + display.putRequest(NEWSTATION); + netserver.requestOnChange(STATION, 0); + +} + +void audio_id3album(const char *info){ + if(printable(info)){ + if(strlen(config.station.title)==0){ + config.setTitle(info); + }else{ + char out[BUFLEN]= {0}; + strlcat(out, config.station.title, BUFLEN); + strlcat(out, " - ", BUFLEN); + strlcat(out, info, BUFLEN); + config.setTitle(out); + } + netserver.requestOnChange(TITLE, 0); + } +} + +void audio_id3title(const char *info){ + audio_id3album(info); +} + +void audio_beginSDread(){ + config.setTitle(""); + netserver.requestOnChange(TITLE, 0); +} + +void audio_id3data(const char *info){ //id3 metadata + telnet.printf("##AUDIO.ID3#: %s\n", info); +} +void audio_eof_mp3(const char *info){ //end of file + player.play(random(1, config.store.countStation)); +}