v0.9.220
This commit is contained in:
@@ -112,17 +112,13 @@ void audio_id3data(const char *info){ //id3 metadata
|
||||
|
||||
void audio_eof_mp3(const char *info){ //end of file
|
||||
config.sdResumePos = 0;
|
||||
if(config.sdSnuffle){
|
||||
player.sendCommand({PR_PLAY, random(1, config.store.countStation)});
|
||||
}else{
|
||||
player.next();
|
||||
}
|
||||
player.next();
|
||||
}
|
||||
|
||||
void audio_eof_stream(const char *info){
|
||||
player.sendCommand({PR_STOP, 0});
|
||||
if(!player.resumeAfterUrl) return;
|
||||
if (config.store.play_mode==PM_WEB){
|
||||
if (config.getMode()==PM_WEB){
|
||||
player.sendCommand({PR_PLAY, config.store.lastStation});
|
||||
}else{
|
||||
player.setResumeFilePos( config.sdResumePos==0?0:config.sdResumePos-player.sd_min);
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "display.h"
|
||||
#include "player.h"
|
||||
#include "netserver.h"
|
||||
#include "spidog.h"
|
||||
|
||||
Config config;
|
||||
|
||||
@@ -13,8 +14,6 @@ SPIClass SPI2(HSPI);
|
||||
#if defined(SD_SPIPINS) || SD_HSPI
|
||||
SPIClass SDSPI(HSPI);
|
||||
#endif
|
||||
#define SDL() if(player.mutex_pl!=NULL) player.cardLock(true)
|
||||
#define SDU() vTaskDelay(2); if(player.mutex_pl!=NULL) player.cardLock(false)
|
||||
|
||||
void u8fix(char *src){
|
||||
char last = src[strlen(src)-1];
|
||||
@@ -34,6 +33,7 @@ bool Config::_isFSempty() {
|
||||
|
||||
void Config::init() {
|
||||
EEPROM.begin(EEPROM_SIZE);
|
||||
sdog.begin();
|
||||
emptyFS = true;
|
||||
#if IR_PIN!=255
|
||||
irindex=-1;
|
||||
@@ -72,29 +72,37 @@ void Config::init() {
|
||||
}
|
||||
|
||||
bool Config::_sdCardIsConnected() {
|
||||
if(SD.sectorSize()<1) return false;
|
||||
SDL();
|
||||
#if SDC_CS!=255
|
||||
sdog.takeMutex();
|
||||
if(SD.sectorSize()<1) {
|
||||
sdog.giveMutex();
|
||||
return false;
|
||||
}
|
||||
uint8_t buff[SD.sectorSize()] = { 0 };
|
||||
bool bread = SD.readRAW(buff, 1);
|
||||
if(SD.sectorSize()>0 && !bread) SD.end();
|
||||
SDU();
|
||||
sdog.giveMutex();
|
||||
return bread;
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Config::_sdBegin(){
|
||||
bool out;
|
||||
SDL();
|
||||
#if defined(SD_SPIPINS) || SD_HSPI
|
||||
out = SD.begin(SDC_CS, SDSPI);
|
||||
#else
|
||||
out = SD.begin(SDC_CS);
|
||||
bool out = false;
|
||||
#if SDC_CS!=255
|
||||
sdog.takeMutex();
|
||||
#if defined(SD_SPIPINS) || SD_HSPI
|
||||
out = SD.begin(SDC_CS, SDSPI);
|
||||
#else
|
||||
out = SD.begin(SDC_CS);
|
||||
#endif
|
||||
sdog.giveMutex();
|
||||
#endif
|
||||
SDU();
|
||||
return out;
|
||||
}
|
||||
|
||||
void Config::checkSD(){
|
||||
if(SDC_CS==255) return;
|
||||
#if SDC_CS!=255
|
||||
mountSDbusy = true;
|
||||
cardStatus_e prevCardStatus = _cardStatus;
|
||||
if(_sdCardIsConnected()){
|
||||
@@ -103,23 +111,34 @@ void Config::checkSD(){
|
||||
}else{
|
||||
_cardStatus=CS_MOUNTED;
|
||||
}
|
||||
if(_cardStatus==CS_PRESENT && store.play_mode==PM_WEB && SD_AUTOPLAY && prevCardStatus==CS_EJECTED) config.changeMode(PM_SDCARD);
|
||||
if(_cardStatus==CS_PRESENT && getMode()==PM_WEB && SD_AUTOPLAY && prevCardStatus==CS_EJECTED) config.changeMode(PM_SDCARD);
|
||||
}else{
|
||||
if(_cardStatus==CS_MOUNTED || _cardStatus==CS_PRESENT || _cardStatus==CS_EJECTED){
|
||||
if(_cardStatus!=CS_EJECTED && store.play_mode==PM_SDCARD && SD_AUTOPLAY) config.changeMode(PM_WEB);
|
||||
if(_cardStatus!=CS_EJECTED && getMode()==PM_SDCARD && SD_AUTOPLAY) config.changeMode(PM_WEB);
|
||||
_cardStatus=CS_EJECTED;
|
||||
}
|
||||
backupSDStation = 0;
|
||||
}
|
||||
mountSDbusy = false;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool Config::spiffsCleanup(){
|
||||
bool ret = (SPIFFS.exists(PLAYLIST_SD_PATH)) || (SPIFFS.exists(INDEX_SD_PATH)) || (SPIFFS.exists(INDEX_PATH));
|
||||
if(SPIFFS.exists(PLAYLIST_SD_PATH)) SPIFFS.remove(PLAYLIST_SD_PATH);
|
||||
if(SPIFFS.exists(INDEX_SD_PATH)) SPIFFS.remove(INDEX_SD_PATH);
|
||||
if(SPIFFS.exists(INDEX_PATH)) SPIFFS.remove(INDEX_PATH);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void Config::_mountSD(){
|
||||
#if SDC_CS!=255
|
||||
if(SDC_CS==255 || mountSDbusy || display.mode()==SDCHANGE) return;
|
||||
mountSDbusy = true;
|
||||
if(SD.sectorSize()<1) SDinit = _sdBegin();
|
||||
sdog.takeMutex(); uint16_t ssz = SD.sectorSize(); sdog.giveMutex();
|
||||
if(ssz<1) SDinit = _sdBegin();
|
||||
if(!_sdCardIsConnected()) {
|
||||
if(store.play_mode==PM_SDCARD){
|
||||
if(getMode()==PM_SDCARD){
|
||||
SDinit = false;
|
||||
}
|
||||
}else{
|
||||
@@ -132,6 +151,7 @@ void Config::_mountSD(){
|
||||
}
|
||||
}
|
||||
mountSDbusy = false;
|
||||
#endif
|
||||
}
|
||||
|
||||
void Config::initPlaylistMode(){
|
||||
@@ -143,12 +163,13 @@ void Config::initPlaylistMode(){
|
||||
Serial.println("SD Mount Failed");
|
||||
}else{
|
||||
Serial.println("SD Mounted");
|
||||
if(store.play_mode==PM_SDCARD) {
|
||||
if(getMode()==PM_SDCARD) {
|
||||
if(_cardStatus!=CS_MOUNTED){
|
||||
_cardStatus=CS_MOUNTED;
|
||||
if(_bootDone) Serial.println("Waiting for SD card indexing..."); else BOOTLOG("Waiting for SD card indexing...");
|
||||
initSDPlaylist();
|
||||
}else{
|
||||
initSDPlaylist(false);
|
||||
if(backupSDStation==0) {
|
||||
store.lastStation = random(1, store.countStation);
|
||||
backupSDStation = store.lastStation;
|
||||
@@ -160,12 +181,13 @@ void Config::initPlaylistMode(){
|
||||
}else{
|
||||
store.play_mode=PM_WEB;
|
||||
}
|
||||
if(store.play_mode==PM_WEB && !emptyFS) initPlaylist();
|
||||
if(getMode()==PM_WEB && !emptyFS) initPlaylist();
|
||||
|
||||
if (store.lastStation == 0 && store.countStation > 0) {
|
||||
store.lastStation = store.play_mode==PM_WEB?1:random(1, store.countStation);
|
||||
save();
|
||||
store.lastStation = getMode()==PM_WEB?1:random(1, store.countStation);
|
||||
//save();
|
||||
}
|
||||
save();
|
||||
_bootDone = true;
|
||||
loadStation(store.lastStation);
|
||||
}
|
||||
@@ -310,8 +332,8 @@ uint16_t Config::getTimezoneOffset() {
|
||||
void Config::save() {
|
||||
uint16_t ls = store.lastStation;
|
||||
uint8_t pm = store.play_mode;
|
||||
if(store.play_mode==PM_SDCARD) store.lastStation = backupLastStation;
|
||||
if(store.play_mode==PM_WEB) backupLastStation = store.lastStation;
|
||||
if(getMode()==PM_SDCARD) store.lastStation = backupLastStation;
|
||||
if(getMode()==PM_WEB) backupLastStation = store.lastStation;
|
||||
bitWrite(store.play_mode, 2, sdSnuffle);
|
||||
eepromWrite(EEPROM_START, store);
|
||||
store.lastStation = ls;
|
||||
@@ -322,10 +344,10 @@ void Config::setSnuffle(bool sn){
|
||||
sdSnuffle=sn;
|
||||
save();
|
||||
if(sdSnuffle) player.next();
|
||||
//player blah blah blah
|
||||
}
|
||||
|
||||
void Config::changeMode(int newmode){
|
||||
#if SDC_CS!=255
|
||||
if(SDC_CS==255) return;
|
||||
if(!SDinit) {
|
||||
_mountSD();
|
||||
@@ -335,17 +357,17 @@ void Config::changeMode(int newmode){
|
||||
return;
|
||||
}
|
||||
}
|
||||
if(store.play_mode==PM_SDCARD) store.lastStation = config.backupLastStation;
|
||||
if(getMode()==PM_SDCARD) store.lastStation = config.backupLastStation;
|
||||
if(newmode<0){
|
||||
store.play_mode++;
|
||||
if(store.play_mode > MAX_PLAY_MODE){
|
||||
if(getMode() > MAX_PLAY_MODE){
|
||||
store.play_mode=0;
|
||||
}
|
||||
}else{
|
||||
store.play_mode=(playMode_e)newmode;
|
||||
}
|
||||
save();
|
||||
if(store.play_mode==PM_SDCARD && _cardStatus!=CS_MOUNTED){
|
||||
if(getMode()==PM_SDCARD && _cardStatus!=CS_MOUNTED){
|
||||
display.putRequest(NEWMODE, SDCHANGE);
|
||||
while(display.mode()!=SDCHANGE)
|
||||
delay(10);
|
||||
@@ -360,6 +382,7 @@ void Config::changeMode(int newmode){
|
||||
netserver.requestOnChange(GETMODE, 0);
|
||||
display.putRequest(NEWMODE, PLAYER);
|
||||
display.putRequest(NEWSTATION);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if IR_PIN!=255
|
||||
@@ -475,12 +498,12 @@ bool Config::checkNoMedia(const char* path){
|
||||
char nomedia[BUFLEN]= {0};
|
||||
strlcat(nomedia, path, BUFLEN);
|
||||
strlcat(nomedia, "/.nomedia", BUFLEN);
|
||||
SDL(); bool nm = SD.exists(nomedia); SDU();
|
||||
sdog.takeMutex(); bool nm = SD.exists(nomedia); sdog.giveMutex();
|
||||
return nm;
|
||||
}
|
||||
|
||||
void Config::listSD(File &plSDfile, File &plSDindex, const char * dirname, uint8_t levels){
|
||||
SDL(); File root = SD.open(dirname); SDU();
|
||||
sdog.takeMutex(); File root = SD.open(dirname); sdog.giveMutex();
|
||||
if(!root){
|
||||
Serial.println("##[ERROR]#\tFailed to open directory");
|
||||
return;
|
||||
@@ -490,28 +513,34 @@ void Config::listSD(File &plSDfile, File &plSDindex, const char * dirname, uint8
|
||||
return;
|
||||
}
|
||||
|
||||
SDL(); File file = root.openNextFile(); SDU();
|
||||
sdog.takeMutex(); File file = root.openNextFile(); sdog.giveMutex();
|
||||
uint32_t pos = 0;
|
||||
//vTaskDelay(5);
|
||||
while(file){
|
||||
|
||||
if(file.isDirectory()){
|
||||
if(levels && !checkNoMedia(file.path())){
|
||||
listSD(plSDfile, plSDindex, file.path(), levels -1);
|
||||
sdog.takeMutex();
|
||||
bool fid = file.isDirectory();
|
||||
const char * fp = file.path();
|
||||
const char * fn = file.name();
|
||||
sdog.giveMutex();
|
||||
if(fid){
|
||||
if(levels && !checkNoMedia(fp)){
|
||||
listSD(plSDfile, plSDindex, fp, levels -1);
|
||||
}
|
||||
} else {
|
||||
if(endsWith(strlwr((char*)file.name()), ".mp3") || endsWith(file.name(), ".m4a") || endsWith(file.name(), ".aac") || endsWith(file.name(), ".wav") || endsWith(file.name(), ".flac")){
|
||||
if(endsWith(strlwr((char*)fn), ".mp3") || endsWith(fn, ".m4a") || endsWith(fn, ".aac") || endsWith(fn, ".wav") || endsWith(fn, ".flac")){
|
||||
pos = plSDfile.position();
|
||||
plSDfile.print(file.name()); plSDfile.print("\t"); plSDfile.print(file.path()); plSDfile.print("\t"); plSDfile.println(0);
|
||||
plSDfile.print(fn); plSDfile.print("\t"); plSDfile.print(fp); plSDfile.print("\t"); plSDfile.println(0);
|
||||
plSDindex.write((byte *) &pos, 4);
|
||||
}
|
||||
}
|
||||
SDL(); file = root.openNextFile(); SDU();
|
||||
sdog.takeMutex(); file = root.openNextFile(); sdog.giveMutex();
|
||||
}
|
||||
}
|
||||
|
||||
void Config::indexSDPlaylist() {
|
||||
mountSDbusy = true;
|
||||
if(SPIFFS.exists(PLAYLIST_SD_PATH)) SPIFFS.remove(PLAYLIST_SD_PATH);
|
||||
if(SPIFFS.exists(INDEX_SD_PATH)) SPIFFS.remove(INDEX_SD_PATH);
|
||||
File playlist = SPIFFS.open(PLAYLIST_SD_PATH, "w");
|
||||
if (!playlist) {
|
||||
mountSDbusy = false;
|
||||
@@ -519,19 +548,24 @@ void Config::indexSDPlaylist() {
|
||||
}
|
||||
File index = SPIFFS.open(INDEX_SD_PATH, "w");
|
||||
listSD(playlist, index, "/", 2);
|
||||
index.flush();
|
||||
index.close();
|
||||
playlist.flush();
|
||||
playlist.close();
|
||||
delay(50);
|
||||
mountSDbusy = false;
|
||||
}
|
||||
|
||||
void Config::initSDPlaylist() {
|
||||
void Config::initSDPlaylist(bool doIndex) {
|
||||
store.countStation = 0;
|
||||
indexSDPlaylist();
|
||||
if(doIndex) indexSDPlaylist();
|
||||
if (SPIFFS.exists(INDEX_SD_PATH)) {
|
||||
File index = SPIFFS.open(INDEX_SD_PATH, "r");
|
||||
store.countStation = index.size() / 4;
|
||||
store.lastStation = random(1, store.countStation);
|
||||
backupSDStation = store.lastStation;
|
||||
if(doIndex){
|
||||
store.lastStation = random(1, store.countStation);
|
||||
backupSDStation = store.lastStation;
|
||||
}
|
||||
index.close();
|
||||
save();
|
||||
}
|
||||
|
||||
@@ -31,8 +31,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 REAL_PLAYL getMode()==PM_WEB?PLAYLIST_PATH:PLAYLIST_SD_PATH
|
||||
#define REAL_INDEX getMode()==PM_WEB?INDEX_PATH:INDEX_SD_PATH
|
||||
|
||||
#define MAX_PLAY_MODE 1
|
||||
enum playMode_e : uint8_t { PM_WEB=0, PM_SDCARD=1 };
|
||||
@@ -194,7 +194,7 @@ class Config {
|
||||
void setBitrateFormat(BitrateFormat fmt) { configFmt = fmt; }
|
||||
void initPlaylist();
|
||||
void indexPlaylist();
|
||||
void initSDPlaylist();
|
||||
void initSDPlaylist(bool doIndex = true);
|
||||
void indexSDPlaylist();
|
||||
uint8_t fillPlMenu(int from, uint8_t count, bool fromNextion=false);
|
||||
char * stationByNum(uint16_t num);
|
||||
@@ -208,9 +208,12 @@ class Config {
|
||||
void doSleepW();
|
||||
void setSnuffle(bool sn);
|
||||
void changeMode(int newmode=-1);
|
||||
uint8_t getMode() { return store.play_mode & 0b11; }
|
||||
void initPlaylistMode();
|
||||
void checkSD();
|
||||
cardStatus_e getSDStatus(){ return _cardStatus; };
|
||||
void clearCardStatus() { if(_cardStatus!=CS_NONE) _cardStatus=CS_NONE; }
|
||||
bool spiffsCleanup();
|
||||
private:
|
||||
template <class T> int eepromWrite(int ee, const T& value);
|
||||
template <class T> int eepromRead(int ee, T& value);
|
||||
|
||||
@@ -166,13 +166,17 @@ size_t NetServer::chunkedHtmlPageCallback(uint8_t* buffer, size_t maxLen, size_t
|
||||
return canread;
|
||||
}
|
||||
|
||||
void NetServer::chunkedHtmlPage(const String& contentType, AsyncWebServerRequest *request, const char * path, bool gzip) {
|
||||
void NetServer::chunkedHtmlPage(const String& contentType, AsyncWebServerRequest *request, const char * path, bool doproc) {
|
||||
memset(chunkedPathBuffer, 0, sizeof(chunkedPathBuffer));
|
||||
strlcpy(chunkedPathBuffer, path, sizeof(chunkedPathBuffer)-1);
|
||||
AsyncWebServerResponse *response = request->beginChunkedResponse(contentType, chunkedHtmlPageCallback, processor);
|
||||
xSemaphoreTake(player.playmutex, portMAX_DELAY);
|
||||
AsyncWebServerResponse *response;
|
||||
if(doproc)
|
||||
response = request->beginChunkedResponse(contentType, chunkedHtmlPageCallback, processor);
|
||||
else
|
||||
response = request->beginChunkedResponse(contentType, chunkedHtmlPageCallback);
|
||||
//xSemaphoreTake(player.playmutex, portMAX_DELAY);
|
||||
request->send(response);
|
||||
xSemaphoreGive(player.playmutex);
|
||||
//xSemaphoreGive(player.playmutex);
|
||||
}
|
||||
|
||||
#ifndef DSP_NOT_FLIPPED
|
||||
@@ -200,11 +204,11 @@ void NetServer::processQueue(){
|
||||
switch (request.type) {
|
||||
case PLAYLIST: getPlaylist(clientId); break;
|
||||
case PLAYLISTSAVED: {
|
||||
if(config.store.play_mode==PM_SDCARD) {
|
||||
if(config.getMode()==PM_SDCARD) {
|
||||
// config.indexSDPlaylist();
|
||||
config.initSDPlaylist();
|
||||
}
|
||||
if(config.store.play_mode==PM_WEB){
|
||||
if(config.getMode()==PM_WEB){
|
||||
config.indexPlaylist();
|
||||
config.initPlaylist();
|
||||
}
|
||||
@@ -242,7 +246,7 @@ void NetServer::processQueue(){
|
||||
break;
|
||||
}
|
||||
case GETMODE: sprintf (wsbuf, "{\"pmode\":\"%s\"}", network.status == CONNECTED ? "player" : "ap"); break;
|
||||
case GETINDEX: requestOnChange(STATION, clientId); requestOnChange(TITLE, clientId); requestOnChange(VOLUME, clientId); requestOnChange(EQUALIZER, clientId); requestOnChange(BALANCE, clientId); requestOnChange(BITRATE, clientId); requestOnChange(MODE, clientId); requestOnChange(SDINIT, clientId);requestOnChange(GETPLAYERMODE, clientId); if (config.store.play_mode==PM_SDCARD) { requestOnChange(SDPOS, clientId); requestOnChange(SDLEN, clientId); requestOnChange(SDSNUFFLE, clientId); } return; break;
|
||||
case GETINDEX: requestOnChange(STATION, clientId); requestOnChange(TITLE, clientId); requestOnChange(VOLUME, clientId); requestOnChange(EQUALIZER, clientId); requestOnChange(BALANCE, clientId); requestOnChange(BITRATE, clientId); requestOnChange(MODE, clientId); requestOnChange(SDINIT, clientId);requestOnChange(GETPLAYERMODE, clientId); if (config.getMode()==PM_SDCARD) { requestOnChange(SDPOS, clientId); requestOnChange(SDLEN, clientId); requestOnChange(SDSNUFFLE, clientId); } return; break;
|
||||
case GETSYSTEM: sprintf (wsbuf, "{\"sst\":%d,\"aif\":%d,\"vu\":%d,\"softr\":%d}", config.store.smartstart != 2, config.store.audioinfo, config.store.vumeter, config.store.softapdelay); break;
|
||||
case GETSCREEN: sprintf (wsbuf, "{\"flip\":%d,\"inv\":%d,\"nump\":%d,\"tsf\":%d,\"tsd\":%d,\"dspon\":%d,\"br\":%d,\"con\":%d}", config.store.flipscreen, config.store.invertdisplay, config.store.numplaylist, config.store.fliptouch, config.store.dbgtouch, config.store.dspon, config.store.brightness, config.store.contrast); break;
|
||||
case GETTIMEZONE: sprintf (wsbuf, "{\"tzh\":%d,\"tzm\":%d,\"sntp1\":\"%s\",\"sntp2\":\"%s\"}", config.store.tzHour, config.store.tzMin, config.store.sntp1, config.store.sntp2); break;
|
||||
@@ -263,7 +267,7 @@ void NetServer::processQueue(){
|
||||
case EQUALIZER: sprintf (wsbuf, "{\"bass\": %d, \"middle\": %d, \"trebble\": %d}", config.store.bass, config.store.middle, config.store.trebble); break;
|
||||
case BALANCE: sprintf (wsbuf, "{\"balance\": %d}", config.store.balance); break;
|
||||
case SDINIT: sprintf (wsbuf, "{\"sdinit\": %d}", SDC_CS!=255); break;
|
||||
case GETPLAYERMODE: sprintf (wsbuf, "{\"playermode\": \"%s\"}", config.store.play_mode==PM_SDCARD?"modesd":"modeweb"); break;
|
||||
case GETPLAYERMODE: sprintf (wsbuf, "{\"playermode\": \"%s\"}", config.getMode()==PM_SDCARD?"modesd":"modeweb"); break;
|
||||
case CHANGEMODE: config.changeMode(newConfigMode); return; break;
|
||||
default: break;
|
||||
}
|
||||
@@ -541,8 +545,8 @@ void NetServer::onWsMessage(void *arg, uint8_t *data, size_t len, uint8_t client
|
||||
player.setVol(v);
|
||||
}
|
||||
if (strcmp(cmd, "sdpos") == 0) {
|
||||
return;
|
||||
if (config.store.play_mode==PM_SDCARD){
|
||||
//return;
|
||||
if (config.getMode()==PM_SDCARD){
|
||||
config.sdResumePos = 0;
|
||||
if(!player.isRunning()){
|
||||
player.setResumeFilePos(atoi(val)-player.sd_min);
|
||||
@@ -626,41 +630,42 @@ void NetServer::getPlaylist(uint8_t clientId) {
|
||||
if (clientId == 0) { websocket.textAll(buf); } else { websocket.text(clientId, buf); }
|
||||
}
|
||||
|
||||
int NetServer::_readPlaylistLine(File &file, char * line, size_t size){
|
||||
int bytesRead = file.readBytesUntil('\n', line, size);
|
||||
if(bytesRead>0){
|
||||
line[bytesRead] = 0;
|
||||
if(line[bytesRead-1]=='\r') line[bytesRead-1]=0;
|
||||
}
|
||||
return bytesRead;
|
||||
}
|
||||
|
||||
bool NetServer::importPlaylist() {
|
||||
if(config.store.play_mode==PM_SDCARD) return false;
|
||||
if(config.getMode()==PM_SDCARD) return false;
|
||||
File tempfile = SPIFFS.open(TMP_PATH, "r");
|
||||
if (!tempfile) {
|
||||
return false;
|
||||
}
|
||||
char sName[BUFLEN], sUrl[BUFLEN];
|
||||
char sName[BUFLEN], sUrl[BUFLEN], linePl[BUFLEN*3];;
|
||||
int sOvol;
|
||||
String line = tempfile.readStringUntil('\n');
|
||||
if (config.parseCSV(line.c_str(), sName, sUrl, sOvol)) {
|
||||
File playlistfile = SPIFFS.open(PLAYLIST_PATH, "w");
|
||||
playlistfile.println(line);
|
||||
while (tempfile.available()) {
|
||||
line = tempfile.readStringUntil('\n');
|
||||
if (config.parseCSV(line.c_str(), sName, sUrl, sOvol)) {
|
||||
playlistfile.println(line);
|
||||
}
|
||||
}
|
||||
playlistfile.close();
|
||||
_readPlaylistLine(tempfile, linePl, sizeof(linePl)-1);
|
||||
if (config.parseCSV(linePl, sName, sUrl, sOvol)) {
|
||||
tempfile.close();
|
||||
SPIFFS.remove(TMP_PATH);
|
||||
SPIFFS.rename(TMP_PATH, PLAYLIST_PATH);
|
||||
requestOnChange(PLAYLISTSAVED, 0);
|
||||
return true;
|
||||
}
|
||||
if (config.parseJSON(line.c_str(), sName, sUrl, sOvol)) {
|
||||
if (config.parseJSON(linePl, sName, sUrl, sOvol)) {
|
||||
File playlistfile = SPIFFS.open(PLAYLIST_PATH, "w");
|
||||
String wline = String(sName) + "\t" + String(sUrl) + "\t" + String(sOvol);
|
||||
playlistfile.println(wline);
|
||||
snprintf(linePl, sizeof(linePl)-1, "%s\t%s\t%d", sName, sUrl, 0);
|
||||
playlistfile.println(linePl);
|
||||
while (tempfile.available()) {
|
||||
line = tempfile.readStringUntil('\n');
|
||||
if (config.parseJSON(line.c_str(), sName, sUrl, sOvol)) {
|
||||
wline = String(sName) + "\t" + String(sUrl) + "\t" + String(sOvol);
|
||||
playlistfile.println(wline);
|
||||
_readPlaylistLine(tempfile, linePl, sizeof(linePl)-1);
|
||||
if (config.parseJSON(linePl, sName, sUrl, sOvol)) {
|
||||
snprintf(linePl, sizeof(linePl)-1, "%s\t%s\t%d", sName, sUrl, 0);
|
||||
playlistfile.println(linePl);
|
||||
}
|
||||
}
|
||||
playlistfile.flush();
|
||||
playlistfile.close();
|
||||
tempfile.close();
|
||||
SPIFFS.remove(TMP_PATH);
|
||||
@@ -684,26 +689,26 @@ String processor(const String& var) { // %Templates%
|
||||
if (var == "ACTION") return (network.status == CONNECTED && !config.emptyFS)?"webboard":"";
|
||||
if (var == "UPLOADWIFI") return (network.status == CONNECTED)?" hidden":"";
|
||||
if (var == "VERSION") return YOVERSION;
|
||||
/*if (var == "MODE") {
|
||||
if(config.store.play_mode==PM_SDCARD) {
|
||||
return "modescard";
|
||||
}else{
|
||||
return "modeweb";
|
||||
}
|
||||
}*/
|
||||
return String();
|
||||
}
|
||||
|
||||
int freeSpace;
|
||||
void handleUpload(AsyncWebServerRequest *request, String filename, size_t index, uint8_t *data, size_t len, bool final) {
|
||||
if (!index) {
|
||||
//String spath = "/www/";
|
||||
//if(filename=="playlist.csv" || filename=="wifi.csv") spath = "/data/";
|
||||
//request->_tempFile = SPIFFS.open(config.emptyFS?spath + filename:TMP_PATH , "w");
|
||||
if(filename!="tempwifi.csv"){
|
||||
if(SPIFFS.exists(PLAYLIST_PATH)) SPIFFS.remove(PLAYLIST_PATH);
|
||||
if(SPIFFS.exists(INDEX_PATH)) SPIFFS.remove(INDEX_PATH);
|
||||
if(SPIFFS.exists(PLAYLIST_SD_PATH)) SPIFFS.remove(PLAYLIST_PATH);
|
||||
if(SPIFFS.exists(INDEX_SD_PATH)) SPIFFS.remove(INDEX_PATH);
|
||||
config.clearCardStatus();
|
||||
}
|
||||
freeSpace = (float)SPIFFS.totalBytes()/100*68-SPIFFS.usedBytes();
|
||||
request->_tempFile = SPIFFS.open(TMP_PATH , "w");
|
||||
}
|
||||
if (len) {
|
||||
request->_tempFile.write(data, len);
|
||||
//TODO check index+len size
|
||||
if(freeSpace>index+len){
|
||||
request->_tempFile.write(data, len);
|
||||
}
|
||||
}
|
||||
if (final) {
|
||||
request->_tempFile.close();
|
||||
@@ -744,10 +749,10 @@ void handleHTTPArgs(AsyncWebServerRequest * request) {
|
||||
#ifdef MQTT_ROOT_TOPIC
|
||||
if (strcmp(request->url().c_str(), PLAYLIST_PATH) == 0) while (mqttplaylistblock) vTaskDelay(5);
|
||||
#endif
|
||||
if(strcmp(request->url().c_str(), PLAYLIST_PATH) == 0 && config.store.play_mode==PM_SDCARD){
|
||||
netserver.chunkedHtmlPage("application/octet-stream", request, PLAYLIST_SD_PATH);
|
||||
if(strcmp(request->url().c_str(), PLAYLIST_PATH) == 0 && config.getMode()==PM_SDCARD){
|
||||
netserver.chunkedHtmlPage("application/octet-stream", request, PLAYLIST_SD_PATH, false);
|
||||
}else{
|
||||
netserver.chunkedHtmlPage("application/octet-stream", request, request->url().c_str());
|
||||
netserver.chunkedHtmlPage("application/octet-stream", request, request->url().c_str(), false);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -797,6 +802,7 @@ void handleHTTPArgs(AsyncWebServerRequest * request) {
|
||||
int id = atoi(p->value().c_str());
|
||||
if (id < 1) id = 1;
|
||||
if (id > config.store.countStation) id = config.store.countStation;
|
||||
config.sdResumePos = 0;
|
||||
player.sendCommand({PR_PLAY, id});
|
||||
commandFound=true;
|
||||
DBGVB("[%s] play=%d", __func__, id);
|
||||
@@ -840,6 +846,17 @@ void handleHTTPArgs(AsyncWebServerRequest * request) {
|
||||
commandFound=true;
|
||||
}
|
||||
}
|
||||
if (request->hasArg("clearspiffs")) {
|
||||
if(config.spiffsCleanup()){
|
||||
config.store.play_mode = PM_WEB;
|
||||
config.save();
|
||||
request->redirect("/");
|
||||
ESP.restart();
|
||||
}else{
|
||||
request->send(200);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (request->params() > 0) {
|
||||
request->send(commandFound?200:404);
|
||||
return;
|
||||
|
||||
@@ -60,7 +60,7 @@ class NetServer {
|
||||
void requestOnChange(requestType_e request, uint8_t clientId);
|
||||
void setRSSI(int val) { rssi = val; };
|
||||
int getRSSI() { return rssi; };
|
||||
void chunkedHtmlPage(const String& contentType, AsyncWebServerRequest *request, const char * path, bool gzip = false);
|
||||
void chunkedHtmlPage(const String& contentType, AsyncWebServerRequest *request, const char * path, bool doproc = true);
|
||||
void onWsMessage(void *arg, uint8_t *data, size_t len, uint8_t clientId);
|
||||
bool irRecordEnable;
|
||||
#if IR_PIN!=255
|
||||
@@ -77,6 +77,7 @@ class NetServer {
|
||||
static void beginUpload(AsyncWebServerRequest *request);
|
||||
static void beginUpdate(AsyncWebServerRequest *request);
|
||||
void processQueue();
|
||||
int _readPlaylistLine(File &file, char * line, size_t size);
|
||||
};
|
||||
|
||||
extern NetServer netserver;
|
||||
|
||||
@@ -42,12 +42,14 @@ void ticks() {
|
||||
mktime(&network.timeinfo);
|
||||
display.putRequest(CLOCK);
|
||||
}
|
||||
if(player.isRunning() && config.store.play_mode==PM_SDCARD) netserver.requestOnChange(SDPOS, 0);
|
||||
if(player.isRunning() && config.getMode()==PM_SDCARD) netserver.requestOnChange(SDPOS, 0);
|
||||
if(divrssi) {
|
||||
netserver.setRSSI(WiFi.RSSI());
|
||||
netserver.requestOnChange(NRSSI, 0);
|
||||
display.putRequest(DSPRSSI, netserver.getRSSI());
|
||||
#if SDC_CS!=255
|
||||
if(!config.mountSDbusy) player.sendCommand({PR_CHECKSD, 0});
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef options_h
|
||||
#define options_h
|
||||
|
||||
#define YOVERSION "0.9.201"
|
||||
#define YOVERSION "0.9.220"
|
||||
|
||||
/*******************************************************
|
||||
DO NOT EDIT THIS FILE.
|
||||
|
||||
@@ -89,7 +89,7 @@ void Player::setError(const char *e){
|
||||
}
|
||||
|
||||
void Player::_stop(bool alreadyStopped){
|
||||
if(config.store.play_mode==PM_SDCARD && !alreadyStopped) config.sdResumePos = player.getFilePos();
|
||||
if(config.getMode()==PM_SDCARD && !alreadyStopped) config.sdResumePos = player.getFilePos();
|
||||
_status = STOPPED;
|
||||
setOutputPins(false);
|
||||
if(!hasError()) config.setTitle((display.mode()==LOST || display.mode()==UPDATING)?"":const_PlStopped);
|
||||
@@ -175,7 +175,7 @@ void Player::_play(uint16_t stationId) {
|
||||
config.setDspOn(1);
|
||||
display.putRequest(PSTOP);
|
||||
setOutputPins(false);
|
||||
config.setTitle(config.store.play_mode==PM_WEB?const_PlConnect:"");
|
||||
config.setTitle(config.getMode()==PM_WEB?const_PlConnect:"");
|
||||
config.station.bitrate=0;
|
||||
config.setBitrateFormat(BF_UNCNOWN);
|
||||
config.loadStation(stationId);
|
||||
@@ -187,14 +187,17 @@ void Player::_play(uint16_t stationId) {
|
||||
netserver.loop();
|
||||
config.setSmartStart(0);
|
||||
bool isConnected = false;
|
||||
if(config.store.play_mode==PM_SDCARD && SDC_CS!=255)
|
||||
if(config.getMode()==PM_SDCARD && SDC_CS!=255)
|
||||
isConnected=connecttoFS(SD,config.station.url,config.sdResumePos==0?_resumeFilePos:config.sdResumePos-player.sd_min);
|
||||
else config.store.play_mode=PM_WEB;
|
||||
if(config.store.play_mode==PM_WEB) isConnected=connecttohost(config.station.url);
|
||||
else {
|
||||
config.store.play_mode=PM_WEB;
|
||||
config.save();
|
||||
}
|
||||
if(config.getMode()==PM_WEB) isConnected=connecttohost(config.station.url);
|
||||
if(isConnected){
|
||||
//if (config.store.play_mode==PM_WEB?connecttohost(config.station.url):connecttoFS(SD,config.station.url,config.sdResumePos==0?_resumeFilePos:config.sdResumePos-player.sd_min)) {
|
||||
_status = PLAYING;
|
||||
if(config.store.play_mode==PM_SDCARD) {
|
||||
if(config.getMode()==PM_SDCARD) {
|
||||
config.sdResumePos = 0;
|
||||
config.backupSDStation = stationId;
|
||||
}
|
||||
@@ -238,14 +241,14 @@ void Player::browseUrl(){
|
||||
#endif
|
||||
|
||||
void Player::prev() {
|
||||
if(config.store.play_mode==PM_WEB || !config.sdSnuffle){
|
||||
if(config.getMode()==PM_WEB || !config.sdSnuffle){
|
||||
if (config.store.lastStation == 1) config.store.lastStation = config.store.countStation; else config.store.lastStation--;
|
||||
}
|
||||
sendCommand({PR_PLAY, config.store.lastStation});
|
||||
}
|
||||
|
||||
void Player::next() {
|
||||
if(config.store.play_mode==PM_WEB || !config.sdSnuffle){
|
||||
if(config.getMode()==PM_WEB || !config.sdSnuffle){
|
||||
if (config.store.lastStation == config.store.countStation) config.store.lastStation = 1; else config.store.lastStation++;
|
||||
}else{
|
||||
config.store.lastStation = random(1, config.store.countStation);
|
||||
|
||||
37
yoRadio/src/core/spidog.cpp
Normal file
37
yoRadio/src/core/spidog.cpp
Normal file
@@ -0,0 +1,37 @@
|
||||
#include "spidog.h"
|
||||
|
||||
SPIDog sdog;
|
||||
|
||||
SPIDog::SPIDog() {
|
||||
_busy = false;
|
||||
}
|
||||
|
||||
bool SPIDog::begin(){
|
||||
_spiMutex = xSemaphoreCreateMutex();
|
||||
return (_spiMutex != NULL);
|
||||
}
|
||||
|
||||
bool SPIDog::takeMutex(){
|
||||
if(_spiMutex == NULL) {
|
||||
return false;
|
||||
}
|
||||
if(xSemaphoreTake(_spiMutex, SDOG_PORT_DELAY) == pdTRUE){
|
||||
_busy = true;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void SPIDog::giveMutex(){
|
||||
if(_spiMutex != NULL) xSemaphoreGive(_spiMutex);
|
||||
_busy = false;
|
||||
}
|
||||
|
||||
bool SPIDog::breakMutex(uint8_t ticks){
|
||||
if(!_busy){
|
||||
giveMutex();
|
||||
vTaskDelay(ticks);
|
||||
return takeMutex();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
28
yoRadio/src/core/spidog.h
Normal file
28
yoRadio/src/core/spidog.h
Normal file
@@ -0,0 +1,28 @@
|
||||
#ifndef spidog_h
|
||||
#define spidog_h
|
||||
#include <Arduino.h>
|
||||
#include "options.h"
|
||||
|
||||
#ifndef SDOG_PORT_DELAY
|
||||
#define SDOG_PORT_DELAY portMAX_DELAY
|
||||
#endif
|
||||
|
||||
class SPIDog {
|
||||
private:
|
||||
SemaphoreHandle_t _spiMutex=NULL;
|
||||
bool _busy;
|
||||
public:
|
||||
SPIDog();
|
||||
~SPIDog(){}
|
||||
bool begin();
|
||||
bool takeMutex();
|
||||
void giveMutex();
|
||||
bool breakMutex(uint8_t ticks=5);
|
||||
bool busy() { return _busy; }
|
||||
bool tm() { return takeMutex(); }
|
||||
void gm() { giveMutex(); }
|
||||
};
|
||||
|
||||
extern SPIDog sdog;
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user