v0.9.337b
This commit is contained in:
@@ -5,16 +5,14 @@
|
||||
#include "player.h"
|
||||
#include "network.h"
|
||||
#include "netserver.h"
|
||||
#include "spidog.h"
|
||||
|
||||
#ifdef USE_SD
|
||||
#include "sdmanager.h"
|
||||
#endif
|
||||
Config config;
|
||||
|
||||
#if DSP_HSPI || TS_HSPI || VS_HSPI
|
||||
SPIClass SPI2(HSPI);
|
||||
#endif
|
||||
#if defined(SD_SPIPINS) || SD_HSPI
|
||||
SPIClass SDSPI(HSPI);
|
||||
#endif
|
||||
|
||||
void u8fix(char *src){
|
||||
char last = src[strlen(src)-1];
|
||||
@@ -34,17 +32,16 @@ bool Config::_isFSempty() {
|
||||
|
||||
void Config::init() {
|
||||
EEPROM.begin(EEPROM_SIZE);
|
||||
sdog.begin();
|
||||
bootInfo();
|
||||
#if RTCSUPPORTED
|
||||
_rtcFound = false;
|
||||
BOOTLOG("RTC begin(SDA=%d,SCL=%d)", RTC_SDA, RTC_SCL);
|
||||
if(rtc.init()){
|
||||
BOOTLOG("done");
|
||||
_rtcFound = true;
|
||||
}else{
|
||||
BOOTLOG("[ERROR] - Couldn't find RTC");
|
||||
}
|
||||
_rtcFound = false;
|
||||
BOOTLOG("RTC begin(SDA=%d,SCL=%d)", RTC_SDA, RTC_SCL);
|
||||
if(rtc.init()){
|
||||
BOOTLOG("done");
|
||||
_rtcFound = true;
|
||||
}else{
|
||||
BOOTLOG("[ERROR] - Couldn't find RTC");
|
||||
}
|
||||
#endif
|
||||
emptyFS = true;
|
||||
#if IR_PIN!=255
|
||||
@@ -74,8 +71,12 @@ void Config::init() {
|
||||
emptyFS = _isFSempty();
|
||||
if(emptyFS) BOOTLOG("SPIFFS is empty!");
|
||||
ssidsCount = 0;
|
||||
_cardStatus = CS_NONE;
|
||||
_SDplaylistFS = getMode()==PM_SDCARD?&SD:(true?&SPIFFS:_SDplaylistFS);
|
||||
//!!_cardStatus = CS_NONE;
|
||||
#ifdef USE_SD
|
||||
_SDplaylistFS = getMode()==PM_SDCARD?&sdman:(true?&SPIFFS:_SDplaylistFS);
|
||||
#else
|
||||
_SDplaylistFS = &SPIFFS;
|
||||
#endif
|
||||
//if(SDC_CS!=255) randomSeed(analogRead(SDC_CS));
|
||||
randomSeed(esp_random());
|
||||
backupSDStation = 0;
|
||||
@@ -85,36 +86,10 @@ void Config::init() {
|
||||
}
|
||||
|
||||
#ifdef USE_SD
|
||||
bool Config::_sdCardIsConnected() {
|
||||
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();
|
||||
sdog.giveMutex();
|
||||
return bread;
|
||||
}
|
||||
|
||||
bool Config::_sdBegin(){
|
||||
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
|
||||
return out;
|
||||
}
|
||||
|
||||
/*
|
||||
void Config::checkSD(){
|
||||
cardStatus_e prevCardStatus = _cardStatus;
|
||||
if(_sdCardIsConnected()){
|
||||
if(sdman.cardPresent()){
|
||||
if(_cardStatus==CS_NONE || _cardStatus==CS_PRESENT || _cardStatus==CS_EJECTED) {
|
||||
_cardStatus=CS_PRESENT;
|
||||
}else{
|
||||
@@ -129,37 +104,18 @@ void Config::checkSD(){
|
||||
backupSDStation = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void Config::_mountSD(){
|
||||
if(display.mode()==SDCHANGE) return;
|
||||
sdog.takeMutex(); uint16_t ssz = SD.sectorSize(); sdog.giveMutex();
|
||||
if(ssz<1) SDinit = _sdBegin();
|
||||
if(!_sdCardIsConnected()) {
|
||||
if(getMode()==PM_SDCARD){
|
||||
SDinit = false;
|
||||
}
|
||||
}else{
|
||||
if(!SDinit){
|
||||
if(!_sdBegin()){
|
||||
Serial.println("##[ERROR]#\tCard Mount Failed");
|
||||
}else{
|
||||
SDinit = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
void Config::changeMode(int newmode){
|
||||
if(SDC_CS==255) return;
|
||||
if(network.status==SOFT_AP || display.mode()==LOST){
|
||||
store.play_mode=PM_SDCARD;
|
||||
save();
|
||||
delay(50);
|
||||
ESP.restart();
|
||||
store.play_mode=PM_SDCARD;
|
||||
save();
|
||||
delay(50);
|
||||
ESP.restart();
|
||||
}
|
||||
if(!SDinit) {
|
||||
_mountSD();
|
||||
if(!SDinit){
|
||||
if(!sdman.ready) {
|
||||
sdman.mount();
|
||||
if(!sdman.ready){
|
||||
Serial.println("##[ERROR]#\tSD Not Found");
|
||||
netserver.requestOnChange(GETPLAYERMODE, 0);
|
||||
return;
|
||||
@@ -175,8 +131,8 @@ void Config::changeMode(int newmode){
|
||||
store.play_mode=(playMode_e)newmode;
|
||||
}
|
||||
save();
|
||||
_SDplaylistFS = getMode()==PM_SDCARD?&SD:(true?&SPIFFS:_SDplaylistFS);
|
||||
if(getMode()==PM_SDCARD && _cardStatus!=CS_MOUNTED){
|
||||
_SDplaylistFS = getMode()==PM_SDCARD?&sdman:(true?&SPIFFS:_SDplaylistFS);
|
||||
if(getMode()==PM_SDCARD && sdman.status()!=CS_MOUNTED){
|
||||
display.putRequest(NEWMODE, SDCHANGE);
|
||||
while(display.mode()!=SDCHANGE)
|
||||
delay(10);
|
||||
@@ -196,99 +152,20 @@ void Config::changeMode(int newmode){
|
||||
display.putRequest(NEWSTATION);
|
||||
}
|
||||
|
||||
bool endsWith (const char* base, const char* str) {
|
||||
int slen = strlen(str) - 1;
|
||||
const char *p = base + strlen(base) - 1;
|
||||
while(p > base && isspace(*p)) p--;
|
||||
p -= slen;
|
||||
if (p < base) return false;
|
||||
return (strncmp(p, str, slen) == 0);
|
||||
}
|
||||
|
||||
uint32_t sdFCount;
|
||||
void Config::listSD(File &plSDfile, File &plSDindex, const char * dirname, uint8_t levels){
|
||||
sdog.takeMutex(); File root = SD.open(dirname); sdog.giveMutex();
|
||||
if(!root){
|
||||
Serial.println("##[ERROR]#\tFailed to open directory");
|
||||
return;
|
||||
}
|
||||
sdog.takeMutex();
|
||||
if(!root.isDirectory()){
|
||||
Serial.println("##[ERROR]#\tNot a directory");
|
||||
sdog.giveMutex();
|
||||
return;
|
||||
}
|
||||
sdog.giveMutex();
|
||||
sdog.takeMutex(); File file = root.openNextFile(); sdog.giveMutex();
|
||||
uint32_t pos = 0;
|
||||
while(file){
|
||||
vTaskDelay(2);
|
||||
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*)fn), ".mp3") || endsWith(fn, ".m4a") || endsWith(fn, ".aac") || endsWith(fn, ".wav") || endsWith(fn, ".flac")){
|
||||
sdog.takeMutex();
|
||||
pos = plSDfile.position();
|
||||
plSDfile.print(fn); plSDfile.print("\t"); plSDfile.print(fp); plSDfile.print("\t"); plSDfile.println(0);
|
||||
plSDindex.write((byte *) &pos, 4);
|
||||
sdog.giveMutex();
|
||||
Serial.print(".");
|
||||
if(display.mode()==SDCHANGE) display.putRequest(SDFILEINDEX, sdFCount+1);
|
||||
sdFCount++;
|
||||
if(sdFCount%64==0) Serial.println();
|
||||
}
|
||||
}
|
||||
sdog.takeMutex(); if(file) file.close(); file = root.openNextFile(); sdog.giveMutex();
|
||||
}
|
||||
sdog.takeMutex(); if(root) root.close(); sdog.giveMutex();
|
||||
}
|
||||
|
||||
void Config::indexSDPlaylist() {
|
||||
sdFCount = 0;
|
||||
sdog.takeMutex();
|
||||
if(SDPLFS()->exists(PLAYLIST_SD_PATH)) SDPLFS()->remove(PLAYLIST_SD_PATH);
|
||||
if(SDPLFS()->exists(INDEX_SD_PATH)) SDPLFS()->remove(INDEX_SD_PATH);
|
||||
File playlist = SDPLFS()->open(PLAYLIST_SD_PATH, "w", true);
|
||||
sdog.giveMutex();
|
||||
if (!playlist) {
|
||||
return;
|
||||
}
|
||||
sdog.takeMutex();
|
||||
File index = SDPLFS()->open(INDEX_SD_PATH, "w", true);
|
||||
sdog.giveMutex();
|
||||
listSD(playlist, index, "/", SD_MAX_LEVELS);
|
||||
sdog.takeMutex();
|
||||
index.flush();
|
||||
index.close();
|
||||
playlist.flush();
|
||||
playlist.close();
|
||||
sdog.giveMutex();
|
||||
Serial.println();
|
||||
delay(50);
|
||||
}
|
||||
|
||||
void Config::initSDPlaylist(bool doIndex) {
|
||||
store.countStation = 0;
|
||||
if(doIndex) indexSDPlaylist();
|
||||
sdog.takeMutex();
|
||||
doIndex = !sdman.exists(INDEX_SD_PATH);
|
||||
if(doIndex) sdman.indexSDPlaylist();
|
||||
if (SDPLFS()->exists(INDEX_SD_PATH)) {
|
||||
File index = SDPLFS()->open(INDEX_SD_PATH, "r");
|
||||
store.countStation = index.size() / 4;
|
||||
if(doIndex){
|
||||
store.lastStation = random(1, store.countStation);
|
||||
backupSDStation = store.lastStation;
|
||||
store.lastStation = random(1, store.countStation);
|
||||
backupSDStation = store.lastStation;
|
||||
}
|
||||
index.close();
|
||||
save();
|
||||
}
|
||||
sdog.giveMutex();
|
||||
}
|
||||
|
||||
#endif //#ifdef USE_SD
|
||||
@@ -303,30 +180,31 @@ bool Config::spiffsCleanup(){
|
||||
|
||||
void Config::initPlaylistMode(){
|
||||
sdResumePos = 0;
|
||||
SDinit = false;
|
||||
//SDinit = false;
|
||||
#ifdef USE_SD
|
||||
if(!_sdBegin()){
|
||||
if(!sdman.init()){
|
||||
store.play_mode=PM_WEB;
|
||||
Serial.println("SD Mount Failed");
|
||||
changeMode(PM_WEB);
|
||||
}else{
|
||||
Serial.println("SD Mounted");
|
||||
if(getMode()==PM_SDCARD) {
|
||||
if(_cardStatus!=CS_MOUNTED){
|
||||
_cardStatus=CS_MOUNTED;
|
||||
if(sdman.status()!=CS_MOUNTED){
|
||||
sdman.status(CS_MOUNTED);
|
||||
if(_bootDone) Serial.println("Waiting for SD card indexing..."); else BOOTLOG("Waiting for SD card indexing...");
|
||||
initSDPlaylist();
|
||||
}else{
|
||||
initSDPlaylist(false);
|
||||
initSDPlaylist(false);
|
||||
if(backupSDStation==0) {
|
||||
store.lastStation = random(1, store.countStation);
|
||||
backupSDStation = store.lastStation;
|
||||
}else store.lastStation = backupSDStation;
|
||||
}
|
||||
}
|
||||
SDinit = true;
|
||||
//SDinit = true;
|
||||
}
|
||||
#else
|
||||
store.play_mode=PM_WEB;
|
||||
#else //ifdef USE_SD
|
||||
store.play_mode=PM_WEB;
|
||||
#endif
|
||||
if(getMode()==PM_WEB && !emptyFS) initPlaylist();
|
||||
|
||||
@@ -395,7 +273,7 @@ void Config::loadTheme(){
|
||||
}
|
||||
|
||||
template <class T> int Config::eepromWrite(int ee, const T& value) {
|
||||
const byte* p = (const byte*)(const void*)&value;
|
||||
const uint8_t* p = (const uint8_t*)(const void*)&value;
|
||||
int i;
|
||||
for (i = 0; i < sizeof(value); i++)
|
||||
EEPROM.write(ee++, *p++);
|
||||
@@ -404,7 +282,7 @@ template <class T> int Config::eepromWrite(int ee, const T& value) {
|
||||
}
|
||||
|
||||
template <class T> int Config::eepromRead(int ee, T& value) {
|
||||
byte* p = (byte*)(void*)&value;
|
||||
uint8_t* p = (uint8_t*)(void*)&value;
|
||||
int i;;
|
||||
for (i = 0; i < sizeof(value); i++)
|
||||
*p++ = EEPROM.read(ee++);
|
||||
@@ -503,7 +381,7 @@ void Config::saveVolume(){
|
||||
EEPROM.commit();
|
||||
}
|
||||
|
||||
byte Config::setVolume(byte val) {
|
||||
uint8_t Config::setVolume(uint8_t val) {
|
||||
store.volume = val;
|
||||
display.putRequest(DRAWVOL);
|
||||
netserver.requestOnChange(VOLUME, 0);
|
||||
@@ -517,7 +395,7 @@ void Config::setTone(int8_t bass, int8_t middle, int8_t trebble) {
|
||||
save();
|
||||
}
|
||||
|
||||
void Config::setSmartStart(byte ss) {
|
||||
void Config::setSmartStart(uint8_t ss) {
|
||||
if (store.smartstart < 2) {
|
||||
store.smartstart = ss;
|
||||
save();
|
||||
@@ -529,19 +407,19 @@ void Config::setBalance(int8_t balance) {
|
||||
save();
|
||||
}
|
||||
|
||||
byte Config::setLastStation(uint16_t val) {
|
||||
uint8_t Config::setLastStation(uint16_t val) {
|
||||
store.lastStation = val;
|
||||
save();
|
||||
return store.lastStation;
|
||||
}
|
||||
|
||||
byte Config::setCountStation(uint16_t val) {
|
||||
uint8_t Config::setCountStation(uint16_t val) {
|
||||
store.countStation = val;
|
||||
save();
|
||||
return store.countStation;
|
||||
}
|
||||
|
||||
byte Config::setLastSSID(byte val) {
|
||||
uint8_t Config::setLastSSID(uint8_t val) {
|
||||
store.lastSSID = val;
|
||||
save();
|
||||
return store.lastSSID;
|
||||
@@ -573,7 +451,7 @@ void Config::indexPlaylist() {
|
||||
while (playlist.available()) {
|
||||
uint32_t pos = playlist.position();
|
||||
if (parseCSV(playlist.readStringUntil('\n').c_str(), sName, sUrl, sOvol)) {
|
||||
index.write((byte *) &pos, 4);
|
||||
index.write((uint8_t *) &pos, 4);
|
||||
}
|
||||
}
|
||||
index.close();
|
||||
@@ -591,14 +469,6 @@ void Config::initPlaylist() {
|
||||
save();
|
||||
}
|
||||
}
|
||||
|
||||
bool Config::checkNoMedia(const char* path){
|
||||
char nomedia[BUFLEN]= {0};
|
||||
strlcat(nomedia, path, BUFLEN);
|
||||
strlcat(nomedia, "/.nomedia", BUFLEN);
|
||||
sdog.takeMutex(); bool nm = SD.exists(nomedia); sdog.giveMutex();
|
||||
return nm;
|
||||
}
|
||||
|
||||
void Config::loadStation(uint16_t ls) {
|
||||
char sName[BUFLEN], sUrl[BUFLEN];
|
||||
@@ -613,7 +483,6 @@ void Config::loadStation(uint16_t ls) {
|
||||
if (ls > store.countStation) {
|
||||
ls = 1;
|
||||
}
|
||||
sdog.takeMutex();
|
||||
File playlist = SDPLFS()->open(REAL_PLAYL, "r");
|
||||
|
||||
File index = SDPLFS()->open(REAL_INDEX, "r");
|
||||
@@ -633,11 +502,9 @@ void Config::loadStation(uint16_t ls) {
|
||||
setLastStation(ls);
|
||||
}
|
||||
playlist.close();
|
||||
sdog.giveMutex();
|
||||
}
|
||||
|
||||
char * Config::stationByNum(uint16_t num){
|
||||
sdog.takeMutex();
|
||||
File playlist = SDPLFS()->open(REAL_PLAYL, "r");
|
||||
File index = SDPLFS()->open(REAL_INDEX, "r");
|
||||
index.seek((num - 1) * 4, SeekSet);
|
||||
@@ -648,7 +515,6 @@ char * Config::stationByNum(uint16_t num){
|
||||
playlist.seek(pos, SeekSet);
|
||||
strncpy(_stationBuf, playlist.readStringUntil('\t').c_str(), BUFLEN/2);
|
||||
playlist.close();
|
||||
sdog.giveMutex();
|
||||
return _stationBuf;
|
||||
}
|
||||
|
||||
@@ -659,10 +525,8 @@ uint8_t Config::fillPlMenu(int from, uint8_t count, bool fromNextion) {
|
||||
if (store.countStation == 0) {
|
||||
return 0;
|
||||
}
|
||||
sdog.takeMutex();
|
||||
File playlist = SDPLFS()->open(REAL_PLAYL, "r");
|
||||
File index = SDPLFS()->open(REAL_INDEX, "r");
|
||||
sdog.giveMutex();
|
||||
while (true) {
|
||||
if (ls < 1) {
|
||||
ls++;
|
||||
@@ -674,33 +538,29 @@ uint8_t Config::fillPlMenu(int from, uint8_t count, bool fromNextion) {
|
||||
continue;
|
||||
}
|
||||
if (!finded) {
|
||||
sdog.takeMutex();
|
||||
index.seek((ls - 1) * 4, SeekSet);
|
||||
uint32_t pos;
|
||||
index.readBytes((char *) &pos, 4);
|
||||
finded = true;
|
||||
index.close();
|
||||
playlist.seek(pos, SeekSet);
|
||||
sdog.giveMutex();
|
||||
}
|
||||
bool pla = true;
|
||||
while (pla) {
|
||||
sdog.takeMutex();
|
||||
pla = playlist.available();
|
||||
pla = playlist.available();
|
||||
String stationName = playlist.readStringUntil('\n');
|
||||
sdog.giveMutex();
|
||||
stationName = stationName.substring(0, stationName.indexOf('\t'));
|
||||
if(config.store.numplaylist && stationName.length()>0) stationName = String(from+c)+" "+stationName;
|
||||
if(!fromNextion) display.printPLitem(c, stationName.c_str());
|
||||
#ifdef USE_NEXTION
|
||||
if(fromNextion) nextion.printPLitem(c, stationName.c_str());
|
||||
#endif
|
||||
#ifdef USE_NEXTION
|
||||
if(fromNextion) nextion.printPLitem(c, stationName.c_str());
|
||||
#endif
|
||||
c++;
|
||||
if (c >= count) break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
sdog.takeMutex();playlist.close();sdog.giveMutex();
|
||||
playlist.close();
|
||||
return c;
|
||||
}
|
||||
|
||||
@@ -773,7 +633,7 @@ bool Config::parseJSON(const char* line, char* name, char* url, int &ovol) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Config::parseWsCommand(const char* line, char* cmd, char* val, byte cSize) {
|
||||
bool Config::parseWsCommand(const char* line, char* cmd, char* val, uint8_t cSize) {
|
||||
char *tmpe;
|
||||
tmpe = strstr(line, "=");
|
||||
if (tmpe == NULL) return false;
|
||||
@@ -824,7 +684,7 @@ bool Config::initNetwork() {
|
||||
return false;
|
||||
}
|
||||
char ssidval[30], passval[40];
|
||||
byte c = 0;
|
||||
uint8_t c = 0;
|
||||
while (file.available()) {
|
||||
if (parseSsid(file.readStringUntil('\n').c_str(), ssidval, passval)) {
|
||||
strlcpy(ssids[c].ssid, ssidval, 30);
|
||||
@@ -916,8 +776,8 @@ void Config::bootInfo() {
|
||||
BOOTLOG("esp32core:\t%d.%d.%d", ESP_ARDUINO_VERSION_MAJOR, ESP_ARDUINO_VERSION_MINOR, ESP_ARDUINO_VERSION_PATCH);
|
||||
uint32_t chipId = 0;
|
||||
for(int i=0; i<17; i=i+8) {
|
||||
chipId |= ((ESP.getEfuseMac() >> (40 - i)) & 0xff) << i;
|
||||
}
|
||||
chipId |= ((ESP.getEfuseMac() >> (40 - i)) & 0xff) << i;
|
||||
}
|
||||
BOOTLOG("chip:\t\tmodel: %s | rev: %d | id: %d | cores: %d | psram: %d", ESP.getChipModel(), ESP.getChipRevision(), chipId, ESP.getChipCores(), ESP.getPsramSize());
|
||||
BOOTLOG("display:\t%d", DSP_MODEL);
|
||||
if(VS1053_CS==255) {
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
#include <Ticker.h>
|
||||
#include <SPI.h>
|
||||
#include <SPIFFS.h>
|
||||
#include "SD.h"
|
||||
//#include "SD.h"
|
||||
#include "options.h"
|
||||
#include "rtcsupport.h"
|
||||
|
||||
@@ -38,10 +38,12 @@
|
||||
#define MAX_PLAY_MODE 1
|
||||
|
||||
#if SDC_CS!=255
|
||||
#define USE_SD
|
||||
#define USE_SD
|
||||
#endif
|
||||
#if ESP_ARDUINO_VERSION >= ESP_ARDUINO_VERSION_VAL(3, 0, 0)
|
||||
#define ESP_ARDUINO_3 1
|
||||
#endif
|
||||
enum playMode_e : uint8_t { PM_WEB=0, PM_SDCARD=1 };
|
||||
enum cardStatus_e : uint8_t { CS_NONE=0, CS_PRESENT=1, CS_MOUNTED=2, CS_EJECTED=3 };
|
||||
enum BitrateFormat { BF_UNCNOWN, BF_MP3, BF_AAC, BF_FLAC, BF_OGG, BF_WAV };
|
||||
|
||||
void u8fix(char *src);
|
||||
@@ -79,16 +81,16 @@ struct theme_t {
|
||||
struct config_t
|
||||
{
|
||||
unsigned int config_set; //must be 4262
|
||||
byte volume;
|
||||
uint8_t volume;
|
||||
int8_t balance;
|
||||
int8_t trebble;
|
||||
int8_t middle;
|
||||
int8_t bass;
|
||||
uint16_t lastStation;
|
||||
uint16_t countStation;
|
||||
byte lastSSID;
|
||||
uint8_t lastSSID;
|
||||
bool audioinfo;
|
||||
byte smartstart;
|
||||
uint8_t smartstart;
|
||||
int8_t tzHour;
|
||||
int8_t tzMin;
|
||||
uint16_t timezoneOffset;
|
||||
@@ -161,7 +163,7 @@ class Config {
|
||||
#endif
|
||||
BitrateFormat configFmt = BF_UNCNOWN;
|
||||
neworkItem ssids[5];
|
||||
byte ssidsCount;
|
||||
uint8_t ssidsCount;
|
||||
uint16_t sleepfor;
|
||||
uint32_t sdResumePos;
|
||||
uint16_t backupLastStation;
|
||||
@@ -177,32 +179,31 @@ class Config {
|
||||
#endif
|
||||
void init();
|
||||
void loadTheme();
|
||||
byte setVolume(byte val);
|
||||
uint8_t setVolume(uint8_t val);
|
||||
void saveVolume();
|
||||
void setTone(int8_t bass, int8_t middle, int8_t trebble);
|
||||
void setBalance(int8_t balance);
|
||||
byte setLastStation(uint16_t val);
|
||||
byte setCountStation(uint16_t val);
|
||||
byte setLastSSID(byte val);
|
||||
uint8_t setLastStation(uint16_t val);
|
||||
uint8_t setCountStation(uint16_t val);
|
||||
uint8_t setLastSSID(uint8_t val);
|
||||
void setTitle(const char* title);
|
||||
void setStation(const char* station);
|
||||
bool parseCSV(const char* line, char* name, char* url, int &ovol);
|
||||
bool parseJSON(const char* line, char* name, char* url, int &ovol);
|
||||
bool parseWsCommand(const char* line, char* cmd, char* val, byte cSize);
|
||||
bool parseWsCommand(const char* line, char* cmd, char* val, uint8_t cSize);
|
||||
bool parseSsid(const char* line, char* ssid, char* pass);
|
||||
void loadStation(uint16_t station);
|
||||
bool initNetwork();
|
||||
bool saveWifi();
|
||||
bool saveWifiFromNextion(const char* post);
|
||||
void setSmartStart(byte ss);
|
||||
void setSmartStart(uint8_t ss);
|
||||
void setBitrateFormat(BitrateFormat fmt) { configFmt = fmt; }
|
||||
void initPlaylist();
|
||||
void indexPlaylist();
|
||||
#ifdef USE_SD
|
||||
void initSDPlaylist(bool doIndex = true);
|
||||
void indexSDPlaylist();
|
||||
void changeMode(int newmode=-1);
|
||||
void checkSD();
|
||||
void initSDPlaylist(bool doIndex = true);
|
||||
|
||||
void changeMode(int newmode=-1);
|
||||
#endif
|
||||
uint8_t fillPlMenu(int from, uint8_t count, bool fromNextion=false);
|
||||
char * stationByNum(uint16_t num);
|
||||
@@ -217,33 +218,26 @@ class Config {
|
||||
void setSnuffle(bool sn);
|
||||
uint8_t getMode() { return store.play_mode & 0b11; }
|
||||
void initPlaylistMode();
|
||||
cardStatus_e getSDStatus(){ return _cardStatus; };
|
||||
void clearCardStatus() { if(_cardStatus!=CS_NONE) _cardStatus=CS_NONE; }
|
||||
|
||||
bool spiffsCleanup();
|
||||
FS* SDPLFS(){ return _SDplaylistFS; }
|
||||
#if RTCSUPPORTED
|
||||
bool isRTCFound(){ return _rtcFound; };
|
||||
bool isRTCFound(){ return _rtcFound; };
|
||||
#endif
|
||||
private:
|
||||
template <class T> int eepromWrite(int ee, const T& value);
|
||||
template <class T> int eepromRead(int ee, T& value);
|
||||
cardStatus_e _cardStatus;
|
||||
|
||||
bool _bootDone;
|
||||
#if RTCSUPPORTED
|
||||
bool _rtcFound;
|
||||
bool _rtcFound;
|
||||
#endif
|
||||
FS* _SDplaylistFS;
|
||||
void setDefaults();
|
||||
Ticker _sleepTimer;
|
||||
static void doSleep();
|
||||
uint16_t color565(uint8_t r, uint8_t g, uint8_t b);
|
||||
#ifdef USE_SD
|
||||
void listSD(File &plSDfile, File &plSDindex, const char * dirname, uint8_t levels);
|
||||
bool _sdCardIsConnected();
|
||||
void _mountSD();
|
||||
bool _sdBegin();
|
||||
#endif
|
||||
bool checkNoMedia(const char* path);
|
||||
|
||||
void _initHW();
|
||||
bool _isFSempty();
|
||||
|
||||
|
||||
@@ -49,13 +49,13 @@ constexpr uint8_t nrOfButtons = sizeof(button) / sizeof(button[0]);
|
||||
|
||||
#if IR_PIN!=255
|
||||
#include <assert.h>
|
||||
#include <IRrecv.h>
|
||||
#include <IRremoteESP8266.h>
|
||||
#include <IRac.h>
|
||||
#include <IRtext.h>
|
||||
#include <IRutils.h>
|
||||
|
||||
byte irVolRepeat = 0;
|
||||
#include "../IRremoteESP8266/IRrecv.h"
|
||||
#include "../IRremoteESP8266/IRremoteESP8266.h"
|
||||
#include "../IRremoteESP8266/IRac.h"
|
||||
#include "../IRremoteESP8266/IRtext.h"
|
||||
#include "../IRremoteESP8266/IRutils.h"
|
||||
uint8_t irVolRepeat = 0;
|
||||
const uint16_t kCaptureBufferSize = 1024;
|
||||
const uint8_t kTimeout = IR_TIMEOUT;
|
||||
const uint16_t kMinUnknownSize = 12;
|
||||
@@ -206,7 +206,7 @@ void encoder2Loop() {
|
||||
void irBlink() {
|
||||
if(LED_BUILTIN==255) return;
|
||||
if (player.status() == STOPPED) {
|
||||
for (byte i = 0; i < 7; i++) {
|
||||
for (uint8_t i = 0; i < 7; i++) {
|
||||
digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
|
||||
delay(100);
|
||||
}
|
||||
|
||||
@@ -99,8 +99,8 @@ class Display {
|
||||
void loop(){}
|
||||
bool ready() { return true; }
|
||||
void resetQueue(){}
|
||||
void centerText(const char* text, byte y, uint16_t fg, uint16_t bg){}
|
||||
void rightText(const char* text, byte y, uint16_t fg, uint16_t bg){}
|
||||
void centerText(const char* text, uint8_t y, uint16_t fg, uint16_t bg){}
|
||||
void rightText(const char* text, uint8_t y, uint16_t fg, uint16_t bg){}
|
||||
void flip(){}
|
||||
void invert(){}
|
||||
void setContrast(){}
|
||||
|
||||
@@ -10,8 +10,9 @@
|
||||
#include "mqtt.h"
|
||||
#include "controls.h"
|
||||
#include <Update.h>
|
||||
#include "spidog.h"
|
||||
|
||||
#ifdef USE_SD
|
||||
#include "sdmanager.h"
|
||||
#endif
|
||||
#ifndef MIN_MALLOC
|
||||
#define MIN_MALLOC 24112
|
||||
#endif
|
||||
@@ -19,13 +20,6 @@
|
||||
#define NSQ_SEND_DELAY (TickType_t)100 //portMAX_DELAY?
|
||||
#endif
|
||||
|
||||
#ifdef USE_SD
|
||||
#define CARDLOCK() sdog.tm()
|
||||
#define CARDUNLOCK() sdog.gm()
|
||||
#else
|
||||
#define CARDLOCK() {}
|
||||
#define CARDUNLOCK() {}
|
||||
#endif
|
||||
//#define CORS_DEBUG
|
||||
|
||||
NetServer netserver;
|
||||
@@ -167,30 +161,24 @@ size_t NetServer::chunkedHtmlPageCallback(uint8_t* buffer, size_t maxLen, size_t
|
||||
File requiredfile;
|
||||
bool sdpl = strcmp(netserver.chunkedPathBuffer, PLAYLIST_SD_PATH) == 0;
|
||||
if(sdpl){
|
||||
CARDLOCK();
|
||||
requiredfile = config.SDPLFS()->open(netserver.chunkedPathBuffer, "r");
|
||||
CARDUNLOCK();
|
||||
}else{
|
||||
requiredfile = SPIFFS.open(netserver.chunkedPathBuffer, "r");
|
||||
}
|
||||
if (!requiredfile) return 0;
|
||||
if(sdpl) CARDLOCK();
|
||||
size_t filesize = requiredfile.size();
|
||||
if(sdpl) CARDUNLOCK();
|
||||
size_t needread = filesize - index;
|
||||
if (!needread) {
|
||||
if(sdpl) { CARDLOCK(); requiredfile.close(); CARDUNLOCK(); }
|
||||
requiredfile.close();
|
||||
return 0;
|
||||
}
|
||||
size_t canread = (needread > maxLen) ? maxLen : needread;
|
||||
DBGVB("[%s] seek to %d in %s and read %d bytes with maxLen=%d", __func__, index, netserver.chunkedPathBuffer, canread, maxLen);
|
||||
if(sdpl) CARDLOCK();
|
||||
requiredfile.seek(index, SeekSet);
|
||||
//vTaskDelay(1);
|
||||
requiredfile.read(buffer, canread);
|
||||
index += canread;
|
||||
if (requiredfile) requiredfile.close();
|
||||
if(sdpl) CARDUNLOCK();
|
||||
return canread;
|
||||
}
|
||||
|
||||
@@ -202,9 +190,7 @@ void NetServer::chunkedHtmlPage(const String& contentType, AsyncWebServerRequest
|
||||
response = request->beginChunkedResponse(contentType, chunkedHtmlPageCallback, processor);
|
||||
else
|
||||
response = request->beginChunkedResponse(contentType, chunkedHtmlPageCallback);
|
||||
//xSemaphoreTake(player.playmutex, portMAX_DELAY);
|
||||
request->send(response);
|
||||
//xSemaphoreGive(player.playmutex);
|
||||
}
|
||||
|
||||
#ifndef DSP_NOT_FLIPPED
|
||||
@@ -360,61 +346,61 @@ void NetServer::onWsMessage(void *arg, uint8_t *data, size_t len, uint8_t client
|
||||
if (strcmp(cmd, "getactive") == 0 ) { requestOnChange(GETACTIVE, clientId); return; }
|
||||
if (strcmp(cmd, "newmode") == 0 ) { newConfigMode = atoi(val); requestOnChange(CHANGEMODE, 0); return; }
|
||||
if (strcmp(cmd, "smartstart") == 0) {
|
||||
byte valb = atoi(val);
|
||||
uint8_t valb = atoi(val);
|
||||
config.store.smartstart = valb == 1 ? 1 : 2;
|
||||
if (!player.isRunning() && config.store.smartstart == 1) config.store.smartstart = 0;
|
||||
config.save();
|
||||
return;
|
||||
}
|
||||
if (strcmp(cmd, "audioinfo") == 0) {
|
||||
byte valb = atoi(val);
|
||||
uint8_t valb = atoi(val);
|
||||
config.store.audioinfo = valb;
|
||||
config.save();
|
||||
display.putRequest(AUDIOINFO);
|
||||
return;
|
||||
}
|
||||
if (strcmp(cmd, "vumeter") == 0) {
|
||||
byte valb = atoi(val);
|
||||
uint8_t valb = atoi(val);
|
||||
config.store.vumeter = valb;
|
||||
config.save();
|
||||
display.putRequest(SHOWVUMETER);
|
||||
return;
|
||||
}
|
||||
if (strcmp(cmd, "softap") == 0) {
|
||||
byte valb = atoi(val);
|
||||
uint8_t valb = atoi(val);
|
||||
config.store.softapdelay = valb;
|
||||
config.save();
|
||||
return;
|
||||
}
|
||||
if (strcmp(cmd, "invertdisplay") == 0) {
|
||||
byte valb = atoi(val);
|
||||
uint8_t valb = atoi(val);
|
||||
config.store.invertdisplay = valb;
|
||||
config.save();
|
||||
display.invert();
|
||||
return;
|
||||
}
|
||||
if (strcmp(cmd, "numplaylist") == 0) {
|
||||
byte valb = atoi(val);
|
||||
uint8_t valb = atoi(val);
|
||||
config.store.numplaylist = valb;
|
||||
config.save();
|
||||
display.putRequest(NEWMODE, CLEAR); display.putRequest(NEWMODE, PLAYER);
|
||||
return;
|
||||
}
|
||||
if (strcmp(cmd, "fliptouch") == 0) {
|
||||
byte valb = atoi(val);
|
||||
uint8_t valb = atoi(val);
|
||||
config.store.fliptouch = valb == 1;
|
||||
config.save();
|
||||
flipTS();
|
||||
return;
|
||||
}
|
||||
if (strcmp(cmd, "dbgtouch") == 0) {
|
||||
byte valb = atoi(val);
|
||||
uint8_t valb = atoi(val);
|
||||
config.store.dbgtouch = valb == 1;
|
||||
config.save();
|
||||
return;
|
||||
}
|
||||
if (strcmp(cmd, "flipscreen") == 0) {
|
||||
byte valb = atoi(val);
|
||||
uint8_t valb = atoi(val);
|
||||
config.store.flipscreen = valb;
|
||||
config.save();
|
||||
display.flip();
|
||||
@@ -422,19 +408,19 @@ void NetServer::onWsMessage(void *arg, uint8_t *data, size_t len, uint8_t client
|
||||
return;
|
||||
}
|
||||
if (strcmp(cmd, "brightness") == 0) {
|
||||
byte valb = atoi(val);
|
||||
uint8_t valb = atoi(val);
|
||||
if (!config.store.dspon) requestOnChange(DSPON, 0);
|
||||
config.store.brightness = valb;
|
||||
config.setBrightness(true);
|
||||
return;
|
||||
}
|
||||
if (strcmp(cmd, "screenon") == 0) {
|
||||
byte valb = atoi(val);
|
||||
uint8_t valb = atoi(val);
|
||||
config.setDspOn(valb == 1);
|
||||
return;
|
||||
}
|
||||
if (strcmp(cmd, "contrast") == 0) {
|
||||
byte valb = atoi(val);
|
||||
uint8_t valb = atoi(val);
|
||||
config.store.contrast = valb;
|
||||
config.save();
|
||||
display.setContrast();
|
||||
@@ -574,7 +560,7 @@ void NetServer::onWsMessage(void *arg, uint8_t *data, size_t len, uint8_t client
|
||||
}
|
||||
} /* EOF RESETS */
|
||||
if (strcmp(cmd, "volume") == 0) {
|
||||
byte v = atoi(val);
|
||||
uint8_t v = atoi(val);
|
||||
player.setVol(v);
|
||||
}
|
||||
if (strcmp(cmd, "sdpos") == 0) {
|
||||
@@ -623,7 +609,6 @@ void NetServer::onWsMessage(void *arg, uint8_t *data, size_t len, uint8_t client
|
||||
return;
|
||||
}
|
||||
if (strcmp(cmd, "submitplaylist") == 0) {
|
||||
// xSemaphoreTake(player.playmutex, portMAX_DELAY);
|
||||
return;
|
||||
}
|
||||
if (strcmp(cmd, "submitplaylistdone") == 0) {
|
||||
@@ -631,7 +616,6 @@ void NetServer::onWsMessage(void *arg, uint8_t *data, size_t len, uint8_t client
|
||||
//mqttPublishPlaylist();
|
||||
mqttplaylistticker.attach(5, mqttplaylistSend);
|
||||
#endif
|
||||
// xSemaphoreGive(player.playmutex);
|
||||
if (player.isRunning()) {
|
||||
player.sendCommand({PR_PLAY, -config.store.lastStation});
|
||||
}
|
||||
@@ -649,7 +633,7 @@ void NetServer::onWsMessage(void *arg, uint8_t *data, size_t len, uint8_t client
|
||||
config.irchck = atoi(val);
|
||||
}
|
||||
if (strcmp(cmd, "irclr") == 0) {
|
||||
byte cl = atoi(val);
|
||||
uint8_t cl = atoi(val);
|
||||
config.ircodes.irVals[config.irindex][cl] = 0;
|
||||
}
|
||||
#endif
|
||||
@@ -737,7 +721,9 @@ void handleUpload(AsyncWebServerRequest *request, String filename, size_t index,
|
||||
if(SPIFFS.exists(INDEX_PATH)) SPIFFS.remove(INDEX_PATH);
|
||||
if(SPIFFS.exists(PLAYLIST_SD_PATH)) SPIFFS.remove(PLAYLIST_SD_PATH);
|
||||
if(SPIFFS.exists(INDEX_SD_PATH)) SPIFFS.remove(INDEX_SD_PATH);
|
||||
config.clearCardStatus();
|
||||
#ifdef USE_SD
|
||||
sdman.clearCardStatus();
|
||||
#endif
|
||||
}
|
||||
freeSpace = (float)SPIFFS.totalBytes()/100*68-SPIFFS.usedBytes();
|
||||
request->_tempFile = SPIFFS.open(TMP_PATH , "w");
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef options_h
|
||||
#define options_h
|
||||
|
||||
#define YOVERSION "0.9.313b"
|
||||
#define YOVERSION "0.9.337b"
|
||||
|
||||
/*******************************************************
|
||||
DO NOT EDIT THIS FILE.
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
#include "config.h"
|
||||
#include "telnet.h"
|
||||
#include "display.h"
|
||||
|
||||
#include "sdmanager.h"
|
||||
#include "netserver.h"
|
||||
|
||||
Player player;
|
||||
@@ -13,9 +13,9 @@ QueueHandle_t playerQueue;
|
||||
|
||||
#if VS1053_CS!=255 && !I2S_INTERNAL
|
||||
#if VS_HSPI
|
||||
Player::Player(): Audio(VS1053_CS, VS1053_DCS, VS1053_DREQ, HSPI, 13, 12, 14) {}
|
||||
Player::Player(): Audio(VS1053_CS, VS1053_DCS, VS1053_DREQ, &SPI2) {}
|
||||
#else
|
||||
Player::Player(): Audio(VS1053_CS, VS1053_DCS, VS1053_DREQ) {}
|
||||
Player::Player(): Audio(VS1053_CS, VS1053_DCS, VS1053_DREQ, &SPI) {}
|
||||
#endif
|
||||
void ResetChip(){
|
||||
pinMode(VS1053_RST, OUTPUT);
|
||||
@@ -60,7 +60,6 @@ void Player::init() {
|
||||
_status = STOPPED;
|
||||
//setOutputPins(false);
|
||||
_volTimer=false;
|
||||
playmutex = xSemaphoreCreateMutex();
|
||||
//randomSeed(analogRead(0));
|
||||
#if PLAYER_FORCE_MONO
|
||||
forceMono(true);
|
||||
@@ -114,7 +113,7 @@ void Player::_stop(bool alreadyStopped){
|
||||
|
||||
void Player::initHeaders(const char *file) {
|
||||
if(strlen(file)==0 || true) return; //TODO Read TAGs
|
||||
connecttoFS(SD,file);
|
||||
connecttoFS(sdman,file);
|
||||
eofHeader = false;
|
||||
while(!eofHeader) Audio::loop();
|
||||
//netserver.requestOnChange(SDPOS, 0);
|
||||
@@ -146,16 +145,14 @@ void Player::loop() {
|
||||
}
|
||||
#ifdef USE_SD
|
||||
case PR_CHECKSD: {
|
||||
config.checkSD();
|
||||
sdman.checkSD();
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
xSemaphoreTake(playmutex, portMAX_DELAY);
|
||||
Audio::loop();
|
||||
xSemaphoreGive(playmutex);
|
||||
if(!isRunning() && _status==PLAYING) _stop(true);
|
||||
if(_volTimer){
|
||||
if((millis()-_volTicks)>3000){
|
||||
@@ -199,7 +196,7 @@ void Player::_play(uint16_t stationId) {
|
||||
config.setSmartStart(0);
|
||||
bool isConnected = false;
|
||||
if(config.getMode()==PM_SDCARD && SDC_CS!=255)
|
||||
isConnected=connecttoFS(SD,config.station.url,config.sdResumePos==0?_resumeFilePos:config.sdResumePos-player.sd_min);
|
||||
isConnected=connecttoFS(sdman,config.station.url,config.sdResumePos==0?_resumeFilePos:config.sdResumePos-player.sd_min);
|
||||
else {
|
||||
config.store.play_mode=PM_WEB;
|
||||
config.save();
|
||||
|
||||
@@ -40,7 +40,6 @@ class Player: public Audio {
|
||||
void _play(uint16_t stationId);
|
||||
void _loadVol(uint8_t volume);
|
||||
public:
|
||||
SemaphoreHandle_t playmutex=NULL;
|
||||
bool lockOutput = true;
|
||||
bool resumeAfterUrl = false;
|
||||
uint32_t sd_min, sd_max;
|
||||
|
||||
143
yoRadio/src/core/sdmanager.cpp
Normal file
143
yoRadio/src/core/sdmanager.cpp
Normal file
@@ -0,0 +1,143 @@
|
||||
#if SDC_CS!=255
|
||||
|
||||
#define USE_SD
|
||||
#include "sdmanager.h"
|
||||
#include "display.h"
|
||||
|
||||
#if defined(SD_SPIPINS) || SD_HSPI
|
||||
SPIClass SDSPI(HSPI);
|
||||
#endif
|
||||
|
||||
SDManager sdman(FSImplPtr(new VFSImpl()));
|
||||
|
||||
bool SDManager::init(){
|
||||
ready = false;
|
||||
#if defined(SD_SPIPINS) || SD_HSPI
|
||||
ready = begin(SDC_CS, SDSPI);
|
||||
#else
|
||||
ready = begin(SDC_CS);
|
||||
#endif
|
||||
return ready;
|
||||
}
|
||||
|
||||
bool SDManager::cardPresent() {
|
||||
if(sectorSize()<1) {
|
||||
return false;
|
||||
}
|
||||
uint8_t buff[sectorSize()] = { 0 };
|
||||
bool bread = readRAW(buff, 1);
|
||||
if(sectorSize()>0 && !bread) end();
|
||||
return bread;
|
||||
}
|
||||
|
||||
void SDManager::mount(){
|
||||
if(display.mode()==SDCHANGE) return;
|
||||
uint16_t ssz = sectorSize();
|
||||
if(ssz<1) init();
|
||||
if(!cardPresent()) {
|
||||
if(config.getMode()==PM_SDCARD){
|
||||
ready = false;
|
||||
}
|
||||
}else{
|
||||
if(!ready){
|
||||
if(!init()){
|
||||
Serial.println("##[ERROR]#\tCard Mount Failed");
|
||||
}else{
|
||||
ready = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SDManager::checkSD(){
|
||||
cardStatus_e prevCardStatus = _cardStatus;
|
||||
if(cardPresent()){
|
||||
if(_cardStatus==CS_NONE || _cardStatus==CS_PRESENT || _cardStatus==CS_EJECTED) {
|
||||
_cardStatus=CS_PRESENT;
|
||||
}else{
|
||||
_cardStatus=CS_MOUNTED;
|
||||
}
|
||||
if(_cardStatus==CS_PRESENT && config.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 && config.getMode()==PM_SDCARD && SD_AUTOPLAY) config.changeMode(PM_WEB);
|
||||
_cardStatus=CS_EJECTED;
|
||||
}
|
||||
config.backupSDStation = 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool SDManager::_checkNoMedia(const char* path){
|
||||
char nomedia[BUFLEN]= {0};
|
||||
strlcat(nomedia, path, BUFLEN);
|
||||
strlcat(nomedia, "/.nomedia", BUFLEN);
|
||||
bool nm = exists(nomedia);
|
||||
return nm;
|
||||
}
|
||||
|
||||
bool SDManager::_endsWith (const char* base, const char* str) {
|
||||
int slen = strlen(str) - 1;
|
||||
const char *p = base + strlen(base) - 1;
|
||||
while(p > base && isspace(*p)) p--;
|
||||
p -= slen;
|
||||
if (p < base) return false;
|
||||
return (strncmp(p, str, slen) == 0);
|
||||
}
|
||||
|
||||
void SDManager::listSD(File &plSDfile, File &plSDindex, const char * dirname, uint8_t levels){
|
||||
File root = sdman.open(dirname);
|
||||
if(!root){
|
||||
Serial.println("##[ERROR]#\tFailed to open directory");
|
||||
return;
|
||||
}
|
||||
if(!root.isDirectory()){
|
||||
Serial.println("##[ERROR]#\tNot a directory");
|
||||
return;
|
||||
}
|
||||
File file = root.openNextFile();
|
||||
uint32_t pos = 0;
|
||||
while(file){
|
||||
vTaskDelay(2);
|
||||
bool fid = file.isDirectory();
|
||||
const char * fp = file.path();
|
||||
const char * fn = file.name();
|
||||
if(fid){
|
||||
if(levels && !_checkNoMedia(fp)){
|
||||
listSD(plSDfile, plSDindex, fp, levels -1);
|
||||
}
|
||||
} else {
|
||||
if(_endsWith(strlwr((char*)fn), ".mp3") || _endsWith(fn, ".m4a") || _endsWith(fn, ".aac") || _endsWith(fn, ".wav") || _endsWith(fn, ".flac")){
|
||||
pos = plSDfile.position();
|
||||
plSDfile.print(fn); plSDfile.print("\t"); plSDfile.print(fp); plSDfile.print("\t"); plSDfile.println(0);
|
||||
plSDindex.write((uint8_t *) &pos, 4);
|
||||
Serial.print(".");
|
||||
if(display.mode()==SDCHANGE) display.putRequest(SDFILEINDEX, _sdFCount+1);
|
||||
_sdFCount++;
|
||||
if(_sdFCount%64==0) Serial.println();
|
||||
}
|
||||
}
|
||||
if(file) file.close(); file = root.openNextFile();
|
||||
}
|
||||
if(root) root.close();
|
||||
}
|
||||
|
||||
void SDManager::indexSDPlaylist() {
|
||||
_sdFCount = 0;
|
||||
if(exists(PLAYLIST_SD_PATH)) remove(PLAYLIST_SD_PATH);
|
||||
if(exists(INDEX_SD_PATH)) remove(INDEX_SD_PATH);
|
||||
File playlist = open(PLAYLIST_SD_PATH, "w", true);
|
||||
if (!playlist) {
|
||||
return;
|
||||
}
|
||||
File index = open(INDEX_SD_PATH, "w", true);
|
||||
listSD(playlist, index, "/", SD_MAX_LEVELS);
|
||||
index.flush();
|
||||
index.close();
|
||||
playlist.flush();
|
||||
playlist.close();
|
||||
Serial.println();
|
||||
delay(50);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
39
yoRadio/src/core/sdmanager.h
Normal file
39
yoRadio/src/core/sdmanager.h
Normal file
@@ -0,0 +1,39 @@
|
||||
#ifndef sdmanager_h
|
||||
#define sdmanager_h
|
||||
#include <Arduino.h>
|
||||
#include <SPI.h>
|
||||
#include <SD.h>
|
||||
#include "vfs_api.h"
|
||||
#include "sd_diskio.h"
|
||||
#include "options.h"
|
||||
|
||||
enum cardStatus_e : uint8_t { CS_NONE=0, CS_PRESENT=1, CS_MOUNTED=2, CS_EJECTED=3 };
|
||||
|
||||
class SDManager : public SDFS {
|
||||
public:
|
||||
bool ready;
|
||||
public:
|
||||
SDManager(FSImplPtr impl) : SDFS(impl) {}
|
||||
|
||||
bool init();
|
||||
void mount();
|
||||
bool cardPresent();
|
||||
void listSD(File &plSDfile, File &plSDindex, const char * dirname, uint8_t levels);
|
||||
void indexSDPlaylist();
|
||||
void checkSD();
|
||||
cardStatus_e status(){ return _cardStatus; };
|
||||
void status(cardStatus_e newstatus){ _cardStatus=newstatus; };
|
||||
void clearCardStatus() { if(_cardStatus!=CS_NONE) _cardStatus=CS_NONE; }
|
||||
private:
|
||||
uint32_t _sdFCount;
|
||||
cardStatus_e _cardStatus;
|
||||
private:
|
||||
bool _checkNoMedia(const char* path);
|
||||
bool _endsWith (const char* base, const char* str);
|
||||
};
|
||||
|
||||
extern SDManager sdman;
|
||||
#if defined(SD_SPIPINS) || SD_HSPI
|
||||
extern SPIClass SDSPI;
|
||||
#endif
|
||||
#endif
|
||||
@@ -1,45 +0,0 @@
|
||||
#include "spidog.h"
|
||||
|
||||
SPIDog sdog;
|
||||
|
||||
SPIDog::SPIDog() {
|
||||
_busy = false;
|
||||
}
|
||||
|
||||
bool SPIDog::begin(){
|
||||
if(_spiMutex==NULL){
|
||||
_spiMutex = xSemaphoreCreateMutex();
|
||||
if(_spiMutex==NULL) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SPIDog::takeMutex(){
|
||||
if(_spiMutex == NULL) {
|
||||
return false;
|
||||
}
|
||||
do { } while (xSemaphoreTake(_spiMutex, portMAX_DELAY) != pdPASS);
|
||||
_busy = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
void SPIDog::giveMutex(){
|
||||
if(_spiMutex != NULL) xSemaphoreGive(_spiMutex);
|
||||
_busy = false;
|
||||
}
|
||||
|
||||
bool SPIDog::canTake(){
|
||||
if(_spiMutex == NULL) {
|
||||
return false;
|
||||
}
|
||||
return xSemaphoreTake(_spiMutex, 0) == pdPASS;
|
||||
}
|
||||
|
||||
bool SPIDog::breakMutex(uint8_t ticks){
|
||||
if(!_busy){
|
||||
giveMutex();
|
||||
vTaskDelay(ticks);
|
||||
return takeMutex();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
#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 canTake();
|
||||
bool breakMutex(uint8_t ticks=5);
|
||||
bool busy() { return _busy; }
|
||||
bool tm() { return takeMutex(); }
|
||||
void gm() { giveMutex(); }
|
||||
};
|
||||
|
||||
extern SPIDog sdog;
|
||||
|
||||
#endif
|
||||
@@ -119,7 +119,7 @@ void Telnet::print(const char *buf) {
|
||||
Serial.print(buf);
|
||||
}
|
||||
|
||||
void Telnet::print(byte id, const char *buf) {
|
||||
void Telnet::print(uint8_t id, const char *buf) {
|
||||
if (clients[id] && clients[id].connected()) {
|
||||
clients[id].print(buf);
|
||||
}
|
||||
@@ -143,7 +143,7 @@ void Telnet::printf(const char *format, ...) {
|
||||
Serial.print(buf);
|
||||
}
|
||||
|
||||
void Telnet::printf(byte id, const char *format, ...) {
|
||||
void Telnet::printf(uint8_t id, const char *format, ...) {
|
||||
char buf[MAX_PRINTF_LEN];
|
||||
va_list argptr;
|
||||
va_start(argptr, format);
|
||||
@@ -158,7 +158,7 @@ void Telnet::printf(byte id, const char *format, ...) {
|
||||
}
|
||||
}
|
||||
|
||||
void Telnet::on_connect(const char* str, byte clientId) {
|
||||
void Telnet::on_connect(const char* str, uint8_t clientId) {
|
||||
Serial.printf("Telnet: [%d] %s connected\n", clientId, str);
|
||||
print(clientId, "\nWelcome to ёRadio!\n(Use ^] + q to disconnect.)\n> ");
|
||||
}
|
||||
@@ -181,7 +181,7 @@ void Telnet::info() {
|
||||
telnet.printf("> ");
|
||||
}
|
||||
|
||||
void Telnet::on_input(const char* str, byte clientId) {
|
||||
void Telnet::on_input(const char* str, uint8_t clientId) {
|
||||
if (strlen(str) == 0) return;
|
||||
if(network.status == CONNECTED){
|
||||
if (strcmp(str, "cli.prev") == 0 || strcmp(str, "prev") == 0) {
|
||||
@@ -245,7 +245,7 @@ void Telnet::on_input(const char* str, byte clientId) {
|
||||
}
|
||||
int sstart;
|
||||
if (sscanf(str, "smartstart(%d)", &sstart) == 1 || sscanf(str, "cli.smartstart(\"%d\")", &sstart) == 1 || sscanf(str, "smartstart %d", &sstart) == 1) {
|
||||
config.store.smartstart = (byte)sstart;
|
||||
config.store.smartstart = (uint8_t)sstart;
|
||||
printf(clientId, "new smartstart value is: %d\n> ", config.store.smartstart);
|
||||
config.save();
|
||||
return;
|
||||
@@ -258,7 +258,7 @@ void Telnet::on_input(const char* str, byte clientId) {
|
||||
}
|
||||
char sName[BUFLEN], sUrl[BUFLEN];
|
||||
int sOvol;
|
||||
byte c = 1;
|
||||
uint8_t c = 1;
|
||||
while (file.available()) {
|
||||
if (config.parseCSV(file.readStringUntil('\n').c_str(), sName, sUrl, sOvol)) {
|
||||
printf(clientId, "#CLI.LISTNUM#: %*d: %s, %s\n", 3, c, sName, sUrl);
|
||||
@@ -394,7 +394,7 @@ void Telnet::on_input(const char* str, byte clientId) {
|
||||
File file = SPIFFS.open(SSIDS_PATH, "r");
|
||||
if (file && !file.isDirectory()) {
|
||||
char sSid[BUFLEN], sPas[BUFLEN];
|
||||
byte c = 1;
|
||||
uint8_t c = 1;
|
||||
while (file.available()) {
|
||||
if (config.parseSsid(file.readStringUntil('\n').c_str(), sSid, sPas)) {
|
||||
printf(clientId, "%d: %s, %s\n", c, sSid, sPas);
|
||||
@@ -410,7 +410,7 @@ void Telnet::on_input(const char* str, byte clientId) {
|
||||
File file = SPIFFS.open(SSIDS_PATH, "r");
|
||||
if (file && !file.isDirectory()) {
|
||||
char sSid[BUFLEN], sPas[BUFLEN];
|
||||
byte c = 1;
|
||||
uint8_t c = 1;
|
||||
while (file.available()) {
|
||||
if (config.parseSsid(file.readStringUntil('\n').c_str(), sSid, sPas)) {
|
||||
if(c==config.store.lastSSID) printf(clientId, "%d: %s, %s\n", c, sSid, sPas);
|
||||
|
||||
@@ -12,9 +12,9 @@ class Telnet {
|
||||
bool begin(bool quiet=false);
|
||||
void loop();
|
||||
void stop();
|
||||
void print(byte id, const char *buf);
|
||||
void print(uint8_t id, const char *buf);
|
||||
void print(const char *buf);
|
||||
void printf(byte id, const char *format, ...);
|
||||
void printf(uint8_t id, const char *format, ...);
|
||||
void printf(const char *format, ...);
|
||||
void cleanupClients();
|
||||
void info();
|
||||
@@ -22,8 +22,8 @@ class Telnet {
|
||||
WiFiServer server = WiFiServer(23);
|
||||
WiFiClient clients[MAX_TLN_CLIENTS];
|
||||
void emptyClientStream(WiFiClient client);
|
||||
void on_connect(const char* str, byte clientId);
|
||||
void on_input(const char* str, byte clientId);
|
||||
void on_connect(const char* str, uint8_t clientId);
|
||||
void on_input(const char* str, uint8_t clientId);
|
||||
private:
|
||||
bool _isIPSet(IPAddress ip);
|
||||
void handleSerial();
|
||||
|
||||
Reference in New Issue
Block a user