v0.9.561
This commit is contained in:
@@ -234,6 +234,14 @@ Work is in progress...
|
|||||||
|
|
||||||
---
|
---
|
||||||
## Version history
|
## Version history
|
||||||
|
### 0.9.561
|
||||||
|
**!!! a [full update](#update-over-web-interface) with Sketch data upload is required !!!**\
|
||||||
|
or-> just upload `yoRadio/data/www/script.js.gz` to Webboard Uploader http://radioipaddr/webboard\
|
||||||
|
After updating please clear browser cache.
|
||||||
|
- fixed error when switching to SD Card mode
|
||||||
|
- fixed issue causing random reboots
|
||||||
|
- fixed preview playback bug in Playlist Editor
|
||||||
|
|
||||||
### 0.9.555
|
### 0.9.555
|
||||||
- fixed error "assert failed: udp_new_ip_type /IDF/components/lwip/lwip/src/core/udp.c:1278 (Required to lock TCPIP core functionality!)"\
|
- fixed error "assert failed: udp_new_ip_type /IDF/components/lwip/lwip/src/core/udp.c:1278 (Required to lock TCPIP core functionality!)"\
|
||||||
part #2
|
part #2
|
||||||
|
|||||||
Binary file not shown.
@@ -1225,12 +1225,14 @@ AsyncWebSocketMessageBuffer * AsyncWebSocket::makeBuffer(uint8_t * data, size_t
|
|||||||
void AsyncWebSocket::_cleanBuffers()
|
void AsyncWebSocket::_cleanBuffers()
|
||||||
{
|
{
|
||||||
AsyncWebLockGuard l(_lock);
|
AsyncWebLockGuard l(_lock);
|
||||||
|
while (_buffers.remove_first([](AsyncWebSocketMessageBuffer* b) {
|
||||||
for(AsyncWebSocketMessageBuffer * c: _buffers){
|
return b && b->canDelete();
|
||||||
|
}));
|
||||||
|
/*for(AsyncWebSocketMessageBuffer * c: _buffers){
|
||||||
if(c && c->canDelete()){
|
if(c && c->canDelete()){
|
||||||
_buffers.remove(c);
|
_buffers.remove(c);
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
AsyncWebSocket::AsyncWebSocketClientLinkedList AsyncWebSocket::getClients() const {
|
AsyncWebSocket::AsyncWebSocketClientLinkedList AsyncWebSocket::getClients() const {
|
||||||
|
|||||||
@@ -86,9 +86,8 @@ class AsyncWebSocketMessageBuffer {
|
|||||||
private:
|
private:
|
||||||
uint8_t * _data;
|
uint8_t * _data;
|
||||||
size_t _len;
|
size_t _len;
|
||||||
bool _lock;
|
volatile bool _lock;
|
||||||
uint32_t _count;
|
uint32_t _count;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
AsyncWebSocketMessageBuffer();
|
AsyncWebSocketMessageBuffer();
|
||||||
AsyncWebSocketMessageBuffer(size_t size);
|
AsyncWebSocketMessageBuffer(size_t size);
|
||||||
|
|||||||
@@ -1717,7 +1717,6 @@ void Audio::setConnectionTimeout(uint16_t timeout_ms, uint16_t timeout_ms_ssl){
|
|||||||
void Audio::connectTask(void* pvParams) {
|
void Audio::connectTask(void* pvParams) {
|
||||||
ConnectParams* params = static_cast<ConnectParams*>(pvParams);
|
ConnectParams* params = static_cast<ConnectParams*>(pvParams);
|
||||||
Audio* self = params->instance;
|
Audio* self = params->instance;
|
||||||
bool res = true;
|
|
||||||
if(self->_client){
|
if(self->_client){
|
||||||
self->_connectionResult = self->_client->connect(params->hostwoext, params->port/*, self->m_f_ssl ? self->m_timeout_ms_ssl : self->m_timeout_ms*/);
|
self->_connectionResult = self->_client->connect(params->hostwoext, params->port/*, self->m_f_ssl ? self->m_timeout_ms_ssl : self->m_timeout_ms*/);
|
||||||
}else{
|
}else{
|
||||||
|
|||||||
@@ -175,8 +175,10 @@ void Config::changeMode(int newmode){
|
|||||||
if(getMode()==PM_SDCARD){
|
if(getMode()==PM_SDCARD){
|
||||||
if(pir) player.sendCommand({PR_STOP, 0});
|
if(pir) player.sendCommand({PR_STOP, 0});
|
||||||
display.putRequest(NEWMODE, SDCHANGE);
|
display.putRequest(NEWMODE, SDCHANGE);
|
||||||
|
#ifdef NETSERVER_LOOP1
|
||||||
while(display.mode()!=SDCHANGE)
|
while(display.mode()!=SDCHANGE)
|
||||||
delay(10);
|
delay(10);
|
||||||
|
#endif
|
||||||
delay(50);
|
delay(50);
|
||||||
}
|
}
|
||||||
if(getMode()==PM_WEB) {
|
if(getMode()==PM_WEB) {
|
||||||
@@ -222,6 +224,11 @@ bool Config::spiffsCleanup(){
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Config::waitConnection(){
|
||||||
|
while(!player.connproc) vTaskDelay(50);
|
||||||
|
vTaskDelay(500);
|
||||||
|
}
|
||||||
|
|
||||||
char * Config::ipToStr(IPAddress ip){
|
char * Config::ipToStr(IPAddress ip){
|
||||||
snprintf(ipBuf, 16, "%u.%u.%u.%u", ip[0], ip[1], ip[2], ip[3]);
|
snprintf(ipBuf, 16, "%u.%u.%u.%u", ip[0], ip[1], ip[2], ip[3]);
|
||||||
return ipBuf;
|
return ipBuf;
|
||||||
|
|||||||
@@ -280,6 +280,7 @@ class Config {
|
|||||||
#endif
|
#endif
|
||||||
void resetSystem(const char *val, uint8_t clientId);
|
void resetSystem(const char *val, uint8_t clientId);
|
||||||
bool spiffsCleanup();
|
bool spiffsCleanup();
|
||||||
|
void waitConnection();
|
||||||
char * ipToStr(IPAddress ip);
|
char * ipToStr(IPAddress ip);
|
||||||
bool prepareForPlaying(uint16_t stationId);
|
bool prepareForPlaying(uint16_t stationId);
|
||||||
void configPostPlaying(uint16_t stationId);
|
void configPostPlaying(uint16_t stationId);
|
||||||
|
|||||||
@@ -22,6 +22,16 @@ Nextion nextion;
|
|||||||
#ifndef DSP_TASK_CORE_ID
|
#ifndef DSP_TASK_CORE_ID
|
||||||
#define DSP_TASK_CORE_ID 0
|
#define DSP_TASK_CORE_ID 0
|
||||||
#endif
|
#endif
|
||||||
|
#ifndef DSP_TASK_DELAY
|
||||||
|
#define DSP_TASK_DELAY pdMS_TO_TICKS(10) // cap for 50 fps
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define DSP_QUEUE_TICKS 0
|
||||||
|
|
||||||
|
#ifndef DSQ_SEND_DELAY
|
||||||
|
//#define DSQ_SEND_DELAY portMAX_DELAY
|
||||||
|
#define DSQ_SEND_DELAY pdMS_TO_TICKS(200)
|
||||||
|
#endif
|
||||||
|
|
||||||
QueueHandle_t displayQueue;
|
QueueHandle_t displayQueue;
|
||||||
|
|
||||||
@@ -29,16 +39,19 @@ static void loopDspTask(void * pvParameters){
|
|||||||
while(true){
|
while(true){
|
||||||
#ifndef DUMMYDISPLAY
|
#ifndef DUMMYDISPLAY
|
||||||
if(displayQueue==NULL) break;
|
if(displayQueue==NULL) break;
|
||||||
netserver.loop();
|
if(timekeeper.loop0()){
|
||||||
if(timekeeper.loop0())
|
|
||||||
display.loop();
|
display.loop();
|
||||||
// will NOT delay here, would use message dequeue timeout instead
|
#ifndef NETSERVER_LOOP1
|
||||||
//vTaskDelay(DSP_TASK_DELAY);
|
netserver.loop();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
netserver.loop();
|
|
||||||
timekeeper.loop0();
|
timekeeper.loop0();
|
||||||
vTaskDelay(10);
|
#ifndef NETSERVER_LOOP1
|
||||||
|
netserver.loop();
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
vTaskDelay(DSP_TASK_DELAY);
|
||||||
}
|
}
|
||||||
vTaskDelete( NULL );
|
vTaskDelete( NULL );
|
||||||
}
|
}
|
||||||
@@ -53,18 +66,6 @@ DspCore dsp;
|
|||||||
|
|
||||||
Page *pages[] = { new Page(), new Page(), new Page(), new Page() };
|
Page *pages[] = { new Page(), new Page(), new Page(), new Page() };
|
||||||
|
|
||||||
#ifndef DSQ_SEND_DELAY
|
|
||||||
//#define DSQ_SEND_DELAY portMAX_DELAY
|
|
||||||
#define DSQ_SEND_DELAY pdMS_TO_TICKS(200)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef DSP_TASK_DELAY
|
|
||||||
#define DSP_TASK_DELAY pdMS_TO_TICKS(20) // cap for 50 fps
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// will use DSP_QUEUE_TICKS as delay interval for display task runner when there are no msgs in a queue to process
|
|
||||||
#define DSP_QUEUE_TICKS DSP_TASK_DELAY
|
|
||||||
|
|
||||||
#if !((DSP_MODEL==DSP_ST7735 && DTYPE==INITR_BLACKTAB) || DSP_MODEL==DSP_ST7789 || DSP_MODEL==DSP_ST7796 || DSP_MODEL==DSP_ILI9488 || DSP_MODEL==DSP_ILI9486 || DSP_MODEL==DSP_ILI9341 || DSP_MODEL==DSP_ILI9225)
|
#if !((DSP_MODEL==DSP_ST7735 && DTYPE==INITR_BLACKTAB) || DSP_MODEL==DSP_ST7789 || DSP_MODEL==DSP_ST7796 || DSP_MODEL==DSP_ILI9488 || DSP_MODEL==DSP_ILI9486 || DSP_MODEL==DSP_ILI9341 || DSP_MODEL==DSP_ILI9225)
|
||||||
#undef BITRATE_FULL
|
#undef BITRATE_FULL
|
||||||
#define BITRATE_FULL false
|
#define BITRATE_FULL false
|
||||||
@@ -397,7 +398,7 @@ void Display::loop() {
|
|||||||
_bootScreen();
|
_bootScreen();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(displayQueue==NULL) return;
|
if(displayQueue==NULL || _locked) return;
|
||||||
_pager.loop();
|
_pager.loop();
|
||||||
#ifdef USE_NEXTION
|
#ifdef USE_NEXTION
|
||||||
nextion.loop();
|
nextion.loop();
|
||||||
|
|||||||
@@ -37,6 +37,8 @@ class Display {
|
|||||||
void wakeup();
|
void wakeup();
|
||||||
void setContrast();
|
void setContrast();
|
||||||
void printPLitem(uint8_t pos, const char* item);
|
void printPLitem(uint8_t pos, const char* item);
|
||||||
|
void lock() { _locked=true; }
|
||||||
|
void unlock() { _locked=false; }
|
||||||
private:
|
private:
|
||||||
ScrollWidget _meta, _title1, _plcurrent;
|
ScrollWidget _meta, _title1, _plcurrent;
|
||||||
ScrollWidget *_weather;
|
ScrollWidget *_weather;
|
||||||
@@ -52,6 +54,7 @@ class Display {
|
|||||||
ClockWidget _clock;
|
ClockWidget _clock;
|
||||||
Page *_boot;
|
Page *_boot;
|
||||||
TextWidget *_bootstring, *_volip, *_voltxt, *_rssi, *_bitrate;
|
TextWidget *_bootstring, *_volip, *_voltxt, *_rssi, *_bitrate;
|
||||||
|
bool _locked = false;
|
||||||
uint8_t _bootStep;
|
uint8_t _bootStep;
|
||||||
void _time(bool redraw = false);
|
void _time(bool redraw = false);
|
||||||
void _apScreen();
|
void _apScreen();
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ TimerHandle_t mqttReconnectTimer;
|
|||||||
char topic[100], status[BUFLEN+50];
|
char topic[100], status[BUFLEN+50];
|
||||||
|
|
||||||
void connectToMqtt() {
|
void connectToMqtt() {
|
||||||
while(!player.connproc) vTaskDelay(50);
|
//config.waitConnection();
|
||||||
mqttClient.connect();
|
mqttClient.connect();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
#include "commandhandler.h"
|
#include "commandhandler.h"
|
||||||
#include "timekeeper.h"
|
#include "timekeeper.h"
|
||||||
#include <Update.h>
|
#include <Update.h>
|
||||||
#include <ESPmDNS.h>
|
|
||||||
//#include <Ticker.h>
|
//#include <Ticker.h>
|
||||||
|
|
||||||
#ifdef USE_SD
|
#ifdef USE_SD
|
||||||
@@ -21,7 +21,12 @@
|
|||||||
#define MIN_MALLOC 24112
|
#define MIN_MALLOC 24112
|
||||||
#endif
|
#endif
|
||||||
#ifndef NSQ_SEND_DELAY
|
#ifndef NSQ_SEND_DELAY
|
||||||
#define NSQ_SEND_DELAY pdMS_TO_TICKS(100) //portMAX_DELAY?
|
//#define NSQ_SEND_DELAY portMAX_DELAY
|
||||||
|
#define NSQ_SEND_DELAY pdMS_TO_TICKS(300)
|
||||||
|
#endif
|
||||||
|
#ifndef NS_QUEUE_TICKS
|
||||||
|
//#define NS_QUEUE_TICKS pdMS_TO_TICKS(2)
|
||||||
|
#define NS_QUEUE_TICKS 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//#define CORS_DEBUG //Enable CORS policy: 'Access-Control-Allow-Origin' (for testing)
|
//#define CORS_DEBUG //Enable CORS policy: 'Access-Control-Allow-Origin' (for testing)
|
||||||
@@ -72,8 +77,8 @@ bool NetServer::begin(bool quiet) {
|
|||||||
DefaultHeaders::Instance().addHeader(F("Access-Control-Allow-Headers"), F("content-type"));
|
DefaultHeaders::Instance().addHeader(F("Access-Control-Allow-Headers"), F("content-type"));
|
||||||
#endif
|
#endif
|
||||||
webserver.begin();
|
webserver.begin();
|
||||||
if(strlen(config.store.mdnsname)>0)
|
//if(strlen(config.store.mdnsname)>0)
|
||||||
MDNS.begin(config.store.mdnsname);
|
// MDNS.begin(config.store.mdnsname);
|
||||||
websocket.onEvent(onWsEvent);
|
websocket.onEvent(onWsEvent);
|
||||||
webserver.addHandler(&websocket);
|
webserver.addHandler(&websocket);
|
||||||
if(!quiet) Serial.println("done");
|
if(!quiet) Serial.println("done");
|
||||||
@@ -93,10 +98,12 @@ size_t NetServer::chunkedHtmlPageCallback(uint8_t* buffer, size_t maxLen, size_t
|
|||||||
size_t needread = filesize - index;
|
size_t needread = filesize - index;
|
||||||
if (!needread) {
|
if (!needread) {
|
||||||
requiredfile.close();
|
requiredfile.close();
|
||||||
|
display.unlock();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
size_t canread = (needread > maxLen) ? maxLen : needread;
|
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);
|
DBGVB("[%s] seek to %d in %s and read %d bytes with maxLen=%d", __func__, index, netserver.chunkedPathBuffer, canread, maxLen);
|
||||||
|
//netserver.loop();
|
||||||
requiredfile.seek(index, SeekSet);
|
requiredfile.seek(index, SeekSet);
|
||||||
requiredfile.read(buffer, canread);
|
requiredfile.read(buffer, canread);
|
||||||
index += canread;
|
index += canread;
|
||||||
@@ -108,6 +115,9 @@ void NetServer::chunkedHtmlPage(const String& contentType, AsyncWebServerRequest
|
|||||||
memset(chunkedPathBuffer, 0, sizeof(chunkedPathBuffer));
|
memset(chunkedPathBuffer, 0, sizeof(chunkedPathBuffer));
|
||||||
strlcpy(chunkedPathBuffer, path, sizeof(chunkedPathBuffer)-1);
|
strlcpy(chunkedPathBuffer, path, sizeof(chunkedPathBuffer)-1);
|
||||||
AsyncWebServerResponse *response;
|
AsyncWebServerResponse *response;
|
||||||
|
#ifndef NETSERVER_LOOP1
|
||||||
|
display.lock();
|
||||||
|
#endif
|
||||||
response = request->beginChunkedResponse(contentType, chunkedHtmlPageCallback);
|
response = request->beginChunkedResponse(contentType, chunkedHtmlPageCallback);
|
||||||
response->addHeader("Cache-Control","max-age=31536000");
|
response->addHeader("Cache-Control","max-age=31536000");
|
||||||
request->send(response);
|
request->send(response);
|
||||||
@@ -124,10 +134,6 @@ void NetServer::chunkedHtmlPage(const String& contentType, AsyncWebServerRequest
|
|||||||
#define SHOW_WEATHER false
|
#define SHOW_WEATHER false
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef NS_QUEUE_TICKS
|
|
||||||
#define NS_QUEUE_TICKS 2
|
|
||||||
#endif
|
|
||||||
|
|
||||||
const char *getFormat(BitrateFormat _format) {
|
const char *getFormat(BitrateFormat _format) {
|
||||||
switch (_format) {
|
switch (_format) {
|
||||||
case BF_MP3: return "MP3";
|
case BF_MP3: return "MP3";
|
||||||
@@ -308,13 +314,14 @@ void NetServer::loop() {
|
|||||||
delay(100);
|
delay(100);
|
||||||
ESP.restart();
|
ESP.restart();
|
||||||
}
|
}
|
||||||
|
processQueue();
|
||||||
websocket.cleanupClients();
|
websocket.cleanupClients();
|
||||||
switch (importRequest) {
|
switch (importRequest) {
|
||||||
case IMPL: importPlaylist(); importRequest = IMDONE; break;
|
case IMPL: importPlaylist(); importRequest = IMDONE; break;
|
||||||
case IMWIFI: config.saveWifi(); importRequest = IMDONE; break;
|
case IMWIFI: config.saveWifi(); importRequest = IMDONE; break;
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
processQueue();
|
//processQueue();
|
||||||
}
|
}
|
||||||
|
|
||||||
#if IR_PIN!=255
|
#if IR_PIN!=255
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
#include "player.h"
|
#include "player.h"
|
||||||
#include "mqtt.h"
|
#include "mqtt.h"
|
||||||
#include "timekeeper.h"
|
#include "timekeeper.h"
|
||||||
|
#include <ESPmDNS.h>
|
||||||
|
|
||||||
#ifndef WIFI_ATTEMPTS
|
#ifndef WIFI_ATTEMPTS
|
||||||
#define WIFI_ATTEMPTS 16
|
#define WIFI_ATTEMPTS 16
|
||||||
@@ -154,6 +155,8 @@ void MyNetwork::setWifiParams(){
|
|||||||
WiFi.onEvent(WiFiReconnected, WiFiEvent_t::ARDUINO_EVENT_WIFI_STA_GOT_IP);
|
WiFi.onEvent(WiFiReconnected, WiFiEvent_t::ARDUINO_EVENT_WIFI_STA_GOT_IP);
|
||||||
WiFi.onEvent(WiFiLostConnection, WiFiEvent_t::ARDUINO_EVENT_WIFI_STA_DISCONNECTED);
|
WiFi.onEvent(WiFiLostConnection, WiFiEvent_t::ARDUINO_EVENT_WIFI_STA_DISCONNECTED);
|
||||||
//config.setTimeConf(); //??
|
//config.setTimeConf(); //??
|
||||||
|
if(strlen(config.store.mdnsname)>0)
|
||||||
|
MDNS.begin(config.store.mdnsname);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MyNetwork::requestTimeSync(bool withTelnetOutput, uint8_t clientId) {
|
void MyNetwork::requestTimeSync(bool withTelnetOutput, uint8_t clientId) {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#ifndef options_h
|
#ifndef options_h
|
||||||
#define options_h
|
#define options_h
|
||||||
|
|
||||||
#define YOVERSION "0.9.555"
|
#define YOVERSION "0.9.561"
|
||||||
|
|
||||||
/*******************************************************
|
/*******************************************************
|
||||||
DO NOT EDIT THIS FILE.
|
DO NOT EDIT THIS FILE.
|
||||||
|
|||||||
@@ -206,6 +206,7 @@ void TimeKeeper::_upSDPos(){
|
|||||||
|
|
||||||
void TimeKeeper::timeTask(){
|
void TimeKeeper::timeTask(){
|
||||||
static uint8_t tsFailCnt = 0;
|
static uint8_t tsFailCnt = 0;
|
||||||
|
config.waitConnection();
|
||||||
if(getLocalTime(&network.timeinfo)){
|
if(getLocalTime(&network.timeinfo)){
|
||||||
tsFailCnt = 0;
|
tsFailCnt = 0;
|
||||||
forceTimeSync = false;
|
forceTimeSync = false;
|
||||||
@@ -226,8 +227,8 @@ void TimeKeeper::timeTask(){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
void TimeKeeper::weatherTask(){
|
void TimeKeeper::weatherTask(){
|
||||||
if(!weatherBuf || strlen(config.store.weatherkey)==0 || !config.store.showweather) return;
|
|
||||||
forceWeather = false;
|
forceWeather = false;
|
||||||
|
if(!weatherBuf || strlen(config.store.weatherkey)==0 || !config.store.showweather) return;
|
||||||
_getWeather();
|
_getWeather();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -328,7 +329,7 @@ bool _getWeather() {
|
|||||||
}
|
}
|
||||||
}, NULL); // <-- client->onData
|
}, NULL); // <-- client->onData
|
||||||
}, NULL); // <-- weatherClient->onConnect
|
}, NULL); // <-- weatherClient->onConnect
|
||||||
while(!player.connproc) vTaskDelay(50);
|
config.waitConnection();
|
||||||
if(!weatherClient->connect(host, 80)){
|
if(!weatherClient->connect(host, 80)){
|
||||||
Serial.println("##WEATHER###: connection failed");
|
Serial.println("##WEATHER###: connection failed");
|
||||||
AsyncClient * client = weatherClient;
|
AsyncClient * client = weatherClient;
|
||||||
|
|||||||
@@ -99,7 +99,6 @@ void setup() {
|
|||||||
if (config.getMode()==PM_SDCARD) player.initHeaders(config.station.url);
|
if (config.getMode()==PM_SDCARD) player.initHeaders(config.station.url);
|
||||||
player.lockOutput=false;
|
player.lockOutput=false;
|
||||||
if (config.store.smartstart == 1) {
|
if (config.store.smartstart == 1) {
|
||||||
delay(250);
|
|
||||||
player.sendCommand({PR_PLAY, config.lastStation()});
|
player.sendCommand({PR_PLAY, config.lastStation()});
|
||||||
}
|
}
|
||||||
pm.on_end_setup();
|
pm.on_end_setup();
|
||||||
@@ -115,7 +114,9 @@ void loop() {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
loopControls();
|
loopControls();
|
||||||
//netserver.loop();
|
#ifdef NETSERVER_LOOP1
|
||||||
|
netserver.loop();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "core/audiohandlers.h"
|
#include "core/audiohandlers.h"
|
||||||
|
|||||||
Reference in New Issue
Block a user