Compare commits

...

4 Commits

Author SHA1 Message Date
e2002 e4175e8a8e v0.9.420 2025-01-15 18:02:10 +03:00
e2002 98c005d5e0 Merge branch 'trip5-screensaver' into new 2025-01-15 16:26:37 +03:00
darkpoet78 e339e820fc options to blank the screen added 2024-12-30 19:22:24 +09:00
darkpoet78 c7eb9cc700 Screensaver while playing option 2024-12-29 17:41:24 +09:00
18 changed files with 172 additions and 50 deletions

View File

@ -234,6 +234,16 @@ Work is in progress...
---
## Version history
### 0.9.420
**!!! a [full update](#update-over-web-interface) with Sketch data upload is required. After updating please press CTRL+F5 in browser !!!**
- added screensaver mode during playback, configurable via the web interface, pull request[#129](https://github.com/e2002/yoradio/pull/129)
- added blank screen mode to screensaver, configurable via the web interface, pull request[#129](https://github.com/e2002/yoradio/pull/129)
Thanks to @trip5 for the amazing code!
- speeding up indexing of SD cards (advice - don't put all files in one folder)
- i don't remember (honestly) why the AsyncTCP server worked on the same core with the player, now it works on the same core with the display
`#define CONFIG_ASYNC_TCP_RUNNING_CORE 0`
- bug fixes
### v0.9.412
**!!! a [full update](#update-over-web-interface) with Sketch data upload is required. After updating please press CTRL+F5 in browser !!!**
- added mDNS support, configurable via the web interface, pull[#125](https://github.com/e2002/yoradio/pull/125)

Binary file not shown.

View File

@ -78,12 +78,30 @@
<div class="row-title"><span>screensaver</span></div>
<div class="flex-row group group_tft group_oled group_nextion hidden" style="margin-top:20px;">
<div class="inputwrap">
<span class="inputtitle">screensaver enabled</span>
<span class="inputtitle">while not playing</span>
<div class="checkbox off nous" id="screensaverenabled" style="padding-top:16px;"></div>
</div>
<div class="inputwrap">
<span class="inputtitle">screensaver timeout (sec)</span>
<input type="number" id="screensavertimeout" class="textinput inputchange" name="screensavertimeout" value="" maxlength="3" min="0" max="65520" />
<span class="inputtitle">blank screen</span>
<div class="checkbox off nous" id="screensaverblank"></div>
</div>
<div class="inputwrap">
<span class="inputtitle">timeout (sec)</span>
<input type="number" id="screensavertimeout" class="textinput inputchange" name="screensavertimeout" value="" maxlength="3" min="5" max="65520" />
</div>
</div>
<div class="flex-row group group_tft group_oled group_nextion hidden">
<div class="inputwrap">
<span class="inputtitle">while playing</span>
<div class="checkbox off nous" id="screensaverplayingenabled"></div>
</div>
<div class="inputwrap">
<span class="inputtitle">blank screen</span>
<div class="checkbox off nous" id="screensaverplayingblank"></div>
</div>
<div class="inputwrap">
<span class="inputtitle">timeout (min)</span>
<input type="number" id="screensaverplayingtimeout" class="textinput inputchange" name="screensaverplayingtimeout" value="" maxlength="3" min="1" max="1080" />
</div>
</div>
</section>

View File

@ -32,7 +32,7 @@ extern "C" {
//If core is not defined, then we are running in Arduino or PIO
#ifndef CONFIG_ASYNC_TCP_RUNNING_CORE
#define CONFIG_ASYNC_TCP_RUNNING_CORE 1 //any available core (-1)
#define CONFIG_ASYNC_TCP_RUNNING_CORE 0 //any available core (-1)
#endif
#ifndef CONFIG_ASYNC_TCP_USE_WDT
@ -43,7 +43,7 @@ extern "C" {
#define XTASK_MEM_SIZE 6144 // 8192 / 2
#endif
#ifndef XTASK_PRIOTITY
#define XTASK_PRIOTITY 3 //3
#define XTASK_PRIOTITY 5 //3
#endif
#ifndef ATCP_TASK_DELAY
#define ATCP_TASK_DELAY 2

View File

@ -1,7 +1,7 @@
#ifndef COMMON_H
#define COMMON_H
enum displayMode_e { PLAYER, VOL, STATIONS, NUMBERS, LOST, UPDATING, INFO, SETTINGS, TIMEZONE, WIFI, CLEAR, SLEEPING, SDCHANGE, SCREENSAVER };
enum displayMode_e { PLAYER, VOL, STATIONS, NUMBERS, LOST, UPDATING, INFO, SETTINGS, TIMEZONE, WIFI, CLEAR, SLEEPING, SDCHANGE, SCREENSAVER, SCREENBLANK };
enum pages_e : uint8_t { PG_PLAYER=0, PG_DIALOG=1, PG_PLAYLIST=2, PG_SCREENSAVER=3 };
enum displayRequestType_e { BOOTSTRING, NEWMODE, CLOCK, NEWTITLE, NEWSTATION, NEXTSTATION, DRAWPLAYLIST, DRAWVOL, DBITRATE, AUDIOINFO, SHOWVUMETER, DSPRSSI, SHOWWEATHER, NEWWEATHER, PSTOP, PSTART, DSP_START, WAITFORSD, SDFILEINDEX, NEWIP, NOPE };

View File

@ -34,6 +34,7 @@ void Config::init() {
EEPROM.begin(EEPROM_SIZE);
sdResumePos = 0;
screensaverTicks = 0;
screensaverPlayingTicks = 0;
isScreensaver = false;
bootInfo();
#if RTCSUPPORTED
@ -97,6 +98,12 @@ void Config::_setupVersion(){
saveValue(store.mdnsname, buf, MDNS_LENGTH);
saveValue(&store.skipPlaylistUpDown, false);
break;
case 3:
saveValue(&store.screensaverBlank, false);
saveValue(&store.screensaverPlayingEnabled, false);
saveValue(&store.screensaverPlayingTimeout, (uint16_t)5);
saveValue(&store.screensaverPlayingBlank, false);
break;
default:
break;
}
@ -353,6 +360,8 @@ void Config::setDefaults() {
store.screensaverTimeout = 20;
snprintf(store.mdnsname, MDNS_LENGTH, "yoradio-%x", getChipId());
store.skipPlaylistUpDown = false;
store.screensaverPlayingEnabled = false;
store.screensaverPlayingTimeout = 5;
eepromWrite(EEPROM_START, store);
}

View File

@ -46,7 +46,7 @@
#if ESP_ARDUINO_VERSION >= ESP_ARDUINO_VERSION_VAL(3, 0, 0)
#define ESP_ARDUINO_3 1
#endif
#define CONFIG_VERSION 3
#define CONFIG_VERSION 4
enum playMode_e : uint8_t { PM_WEB=0, PM_SDCARD=1 };
enum BitrateFormat { BF_UNCNOWN, BF_MP3, BF_AAC, BF_FLAC, BF_OGG, BF_WAV };
@ -136,6 +136,10 @@ struct config_t
bool rotate90;
bool screensaverEnabled;
uint16_t screensaverTimeout;
bool screensaverBlank;
bool screensaverPlayingEnabled;
uint16_t screensaverPlayingTimeout;
bool screensaverPlayingBlank;
char mdnsname[24];
bool skipPlaylistUpDown;
};
@ -181,6 +185,7 @@ class Config {
bool emptyFS;
uint16_t vuThreshold;
uint16_t screensaverTicks;
uint16_t screensaverPlayingTicks;
bool isScreensaver;
public:
Config() {};

View File

@ -284,11 +284,13 @@ void Display::_swichMode(displayMode_e newmode) {
_pager.setPage( pages[PG_PLAYER]);
pm.on_display_player();
}
if (newmode == SCREENSAVER) {
if (newmode == SCREENSAVER || newmode == SCREENBLANK) {
config.isScreensaver = true;
_pager.setPage( pages[PG_SCREENSAVER]);
if (newmode == SCREENBLANK) dsp.clearClock();
}else{
config.screensaverTicks=SCREENSAVERSTARTUPDELAY;
config.screensaverPlayingTicks=SCREENSAVERSTARTUPDELAY;
config.isScreensaver = false;
}
if (newmode == VOL) {
@ -532,8 +534,14 @@ void Display::_time(bool redraw) {
config.setBrightness();
}
#endif
if(config.isScreensaver && network.timeinfo.tm_sec % 60 == 0)
_clock.moveTo({clockConf.left, random(TFT_FRAMEWDT+clockConf.textsize, (dsp.height()-TFT_FRAMEWDT*2)), 0});
if(config.isScreensaver && network.timeinfo.tm_sec % 60 == 0){
#ifdef GXCLOCKFONT
uint16_t ft=static_cast<uint16_t>(random(TFT_FRAMEWDT, (dsp.height()-dsp.plItemHeight-TFT_FRAMEWDT*2-clockConf.textsize)));
#else
uint16_t ft=static_cast<uint16_t>(random(TFT_FRAMEWDT+clockConf.textsize, (dsp.height()-dsp.plItemHeight-TFT_FRAMEWDT*2)));
#endif
_clock.moveTo({clockConf.left, ft, 0});
}
_clock.draw();
/*#ifdef USE_NEXTION
nextion.printClock(network.timeinfo);

View File

@ -298,7 +298,7 @@ void NetServer::processQueue(){
config.vuThreshold,
config.store.mdnsname);
break;
case GETSCREEN: sprintf (wsbuf, "{\"flip\":%d,\"inv\":%d,\"nump\":%d,\"tsf\":%d,\"tsd\":%d,\"dspon\":%d,\"br\":%d,\"con\":%d,\"scre\":%d,\"scrt\":%d}",
case GETSCREEN: sprintf (wsbuf, "{\"flip\":%d,\"inv\":%d,\"nump\":%d,\"tsf\":%d,\"tsd\":%d,\"dspon\":%d,\"br\":%d,\"con\":%d,\"scre\":%d,\"scrt\":%d,\"scrb\":%d,\"scrpe\":%d,\"scrpt\":%d,\"scrpb\":%d}",
config.store.flipscreen,
config.store.invertdisplay,
config.store.numplaylist,
@ -308,7 +308,11 @@ void NetServer::processQueue(){
config.store.brightness,
config.store.contrast,
config.store.screensaverEnabled,
config.store.screensaverTimeout);
config.store.screensaverTimeout,
config.store.screensaverBlank,
config.store.screensaverPlayingEnabled,
config.store.screensaverPlayingTimeout,
config.store.screensaverPlayingBlank);
break;
case GETTIMEZONE: sprintf (wsbuf, "{\"tzh\":%d,\"tzm\":%d,\"sntp1\":\"%s\",\"sntp2\":\"%s\"}",
config.store.tzHour,
@ -507,13 +511,46 @@ void NetServer::onWsMessage(void *arg, uint8_t *data, size_t len, uint8_t client
}
if (strcmp(cmd, "screensavertimeout") == 0) {
uint16_t valb = atoi(val);
valb = constrain(valb,0,65520);
valb = constrain(valb,5,65520);
config.saveValue(&config.store.screensaverTimeout, valb);
#ifndef DSP_LCD
display.putRequest(NEWMODE, PLAYER);
#endif
return;
}
if (strcmp(cmd, "screensaverblank") == 0) {
bool valb = static_cast<bool>(atoi(val));
config.saveValue(&config.store.screensaverBlank, valb);
#ifndef DSP_LCD
display.putRequest(NEWMODE, PLAYER);
#endif
return;
}
if (strcmp(cmd, "screensaverplayingenabled") == 0) {
bool valb = static_cast<bool>(atoi(val));
config.saveValue(&config.store.screensaverPlayingEnabled, valb);
#ifndef DSP_LCD
display.putRequest(NEWMODE, PLAYER);
#endif
return;
}
if (strcmp(cmd, "screensaverplayingtimeout") == 0) {
uint16_t valb = atoi(val);
valb = constrain(valb,1,1080);
config.saveValue(&config.store.screensaverPlayingTimeout, valb);
#ifndef DSP_LCD
display.putRequest(NEWMODE, PLAYER);
#endif
return;
}
if (strcmp(cmd, "screensaverplayingblank") == 0) {
bool valb = static_cast<bool>(atoi(val));
config.saveValue(&config.store.screensaverPlayingBlank, valb);
#ifndef DSP_LCD
display.putRequest(NEWMODE, PLAYER);
#endif
return;
}
if (strcmp(cmd, "tzh") == 0) {
int8_t vali = atoi(val);
config.saveValue(&config.store.tzHour, vali);
@ -613,6 +650,10 @@ void NetServer::onWsMessage(void *arg, uint8_t *data, size_t len, uint8_t client
config.saveValue(&config.store.numplaylist, false);
config.saveValue(&config.store.screensaverEnabled, false);
config.saveValue(&config.store.screensaverTimeout, (uint16_t)20);
config.saveValue(&config.store.screensaverBlank, false);
config.saveValue(&config.store.screensaverPlayingEnabled, false);
config.saveValue(&config.store.screensaverPlayingTimeout, (uint16_t)5);
config.saveValue(&config.store.screensaverPlayingBlank, false);
display.putRequest(NEWMODE, CLEAR); display.putRequest(NEWMODE, PLAYER);
requestOnChange(GETSCREEN, clientId);
return;

View File

@ -51,7 +51,24 @@ void ticks() {
}
#ifndef DSP_LCD
if(config.store.screensaverEnabled && display.mode()==PLAYER && !player.isRunning()){
if(config.screensaverTicks++ > config.store.screensaverTimeout+SCREENSAVERSTARTUPDELAY) display.putRequest(NEWMODE, SCREENSAVER);
config.screensaverTicks++;
if(config.screensaverTicks > config.store.screensaverTimeout+SCREENSAVERSTARTUPDELAY){
if(config.store.screensaverBlank){
display.putRequest(NEWMODE, SCREENBLANK);
}else{
display.putRequest(NEWMODE, SCREENSAVER);
}
}
}
if(config.store.screensaverPlayingEnabled && display.mode()==PLAYER && player.isRunning()){
config.screensaverPlayingTicks++;
if(config.screensaverPlayingTicks > config.store.screensaverPlayingTimeout*60+SCREENSAVERSTARTUPDELAY){
if(config.store.screensaverPlayingBlank){
display.putRequest(NEWMODE, SCREENBLANK);
}else{
display.putRequest(NEWMODE, SCREENSAVER);
}
}
}
#endif
#if RTCSUPPORTED

View File

@ -1,7 +1,7 @@
#ifndef options_h
#define options_h
#define YOVERSION "0.9.412"
#define YOVERSION "0.9.420"
/*******************************************************
DO NOT EDIT THIS FILE.

View File

@ -191,6 +191,7 @@ void Player::_play(uint16_t stationId) {
config.vuThreshold = 0;
//display.putRequest(PSTOP);
config.screensaverTicks=SCREENSAVERSTARTUPDELAY;
config.screensaverPlayingTicks=SCREENSAVERSTARTUPDELAY;
if(config.getMode()!=PM_SDCARD) {
display.putRequest(PSTOP);
}

View File

@ -60,41 +60,50 @@ bool SDManager::_endsWith (const char* base, const char* str) {
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();
}
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(file) file.close(); file = root.openNextFile();
}
if(root) root.close();
if (!root.isDirectory()) {
Serial.println("##[ERROR]#\tNot a directory");
return;
}
uint32_t pos = 0;
char* filePath;
while (true) {
vTaskDelay(2);
bool isDir;
String fileName = root.getNextFileName(&isDir);
if (fileName.isEmpty()) break;
filePath = (char*)malloc(fileName.length() + 1);
if (filePath == NULL) {
Serial.println("Memory allocation failed");
break;
}
strcpy(filePath, fileName.c_str());
const char* fn = strrchr(filePath, '/') + 1;
if (isDir) {
if (levels && !_checkNoMedia(filePath)) {
listSD(plSDfile, plSDindex, filePath, 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.printf("%s\t%s\t0\n", fn, filePath);
plSDindex.write((uint8_t*)&pos, 4);
Serial.print(".");
if(display.mode()==SDCHANGE) display.putRequest(SDFILEINDEX, _sdFCount+1);
_sdFCount++;
if (_sdFCount % 64 == 0) Serial.println();
}
}
free(filePath);
}
root.close();
}
void SDManager::indexSDPlaylist() {

View File

@ -65,7 +65,7 @@ void DspCore::drawPlaylist(uint16_t currentItem) {
clear();
config.fillPlMenu(currentItem - plCurrentPos, plTtemsCount);
setCursor(0,1);
write(byte(126));
write(uint8_t(126));
}
void DspCore::clearDsp(bool black) {

View File

@ -11,6 +11,7 @@
#define CHARHEIGHT 8
#define DSP_OLED
#define GXCLOCKFONT
typedef GFXcanvas1 Canvas;
#include "widgets/widgets.h"

View File

@ -11,6 +11,7 @@
#define CHARHEIGHT 8
#define DSP_OLED
#define GXCLOCKFONT
typedef GFXcanvas1 Canvas;
#include "widgets/widgets.h"

View File

@ -11,6 +11,7 @@
#define CHARHEIGHT 8
#define DSP_OLED
#define GXCLOCKFONT
typedef GFXcanvas1 Canvas;
#include "widgets/widgets.h"

View File

@ -11,6 +11,7 @@
#define CHARHEIGHT 8
#define DSP_OLED
#define GXCLOCKFONT
typedef GFXcanvas1 Canvas;
#include "widgets/widgets.h"