Merge branch '0_15' into random-bg-img
This commit is contained in:
commit
bfd58b3cdf
@ -664,7 +664,7 @@ class AudioReactive : public Usermod {
|
|||||||
void removeAudioPalettes(void);
|
void removeAudioPalettes(void);
|
||||||
void createAudioPalettes(void);
|
void createAudioPalettes(void);
|
||||||
CRGB getCRGBForBand(int x, int pal);
|
CRGB getCRGBForBand(int x, int pal);
|
||||||
void fillAudioPalette(int pal);
|
void fillAudioPalettes(void);
|
||||||
|
|
||||||
////////////////////
|
////////////////////
|
||||||
// Debug support //
|
// Debug support //
|
||||||
@ -1371,7 +1371,7 @@ class AudioReactive : public Usermod {
|
|||||||
lastTime = millis();
|
lastTime = millis();
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i=0; i<MAX_PALETTES; i++) fillAudioPalette(i);
|
fillAudioPalettes();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1859,7 +1859,7 @@ class AudioReactive : public Usermod {
|
|||||||
|
|
||||||
void AudioReactive::removeAudioPalettes(void) {
|
void AudioReactive::removeAudioPalettes(void) {
|
||||||
DEBUG_PRINTLN(F("Removing audio palettes."));
|
DEBUG_PRINTLN(F("Removing audio palettes."));
|
||||||
while (palettes) {
|
while (palettes>0) {
|
||||||
strip.customPalettes.pop_back();
|
strip.customPalettes.pop_back();
|
||||||
DEBUG_PRINTLN(palettes);
|
DEBUG_PRINTLN(palettes);
|
||||||
palettes--;
|
palettes--;
|
||||||
@ -1869,6 +1869,7 @@ void AudioReactive::removeAudioPalettes(void) {
|
|||||||
|
|
||||||
void AudioReactive::createAudioPalettes(void) {
|
void AudioReactive::createAudioPalettes(void) {
|
||||||
DEBUG_PRINT(F("Total # of palettes: ")); DEBUG_PRINTLN(strip.customPalettes.size());
|
DEBUG_PRINT(F("Total # of palettes: ")); DEBUG_PRINTLN(strip.customPalettes.size());
|
||||||
|
if (palettes) return;
|
||||||
DEBUG_PRINTLN(F("Adding audio palettes."));
|
DEBUG_PRINTLN(F("Adding audio palettes."));
|
||||||
for (int i=0; i<MAX_PALETTES; i++)
|
for (int i=0; i<MAX_PALETTES; i++)
|
||||||
if (strip.customPalettes.size() < 10) {
|
if (strip.customPalettes.size() < 10) {
|
||||||
@ -1907,36 +1908,39 @@ CRGB AudioReactive::getCRGBForBand(int x, int pal) {
|
|||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioReactive::fillAudioPalette(int pal) {
|
void AudioReactive::fillAudioPalettes() {
|
||||||
if (pal>=palettes) return; // palette does not exist
|
if (!palettes) return;
|
||||||
|
size_t lastCustPalette = strip.customPalettes.size();
|
||||||
|
if (lastCustPalette >= palettes) lastCustPalette -= palettes;
|
||||||
|
for (size_t pal=0; pal<palettes; pal++) {
|
||||||
|
uint8_t tcp[16]; // Needs to be 4 times however many colors are being used.
|
||||||
|
// 3 colors = 12, 4 colors = 16, etc.
|
||||||
|
|
||||||
uint8_t tcp[16]; // Needs to be 4 times however many colors are being used.
|
tcp[0] = 0; // anchor of first color - must be zero
|
||||||
// 3 colors = 12, 4 colors = 16, etc.
|
tcp[1] = 0;
|
||||||
|
tcp[2] = 0;
|
||||||
|
tcp[3] = 0;
|
||||||
|
|
||||||
|
CRGB rgb = getCRGBForBand(1, pal);
|
||||||
|
tcp[4] = 1; // anchor of first color
|
||||||
|
tcp[5] = rgb.r;
|
||||||
|
tcp[6] = rgb.g;
|
||||||
|
tcp[7] = rgb.b;
|
||||||
|
|
||||||
|
rgb = getCRGBForBand(128, pal);
|
||||||
|
tcp[8] = 128;
|
||||||
|
tcp[9] = rgb.r;
|
||||||
|
tcp[10] = rgb.g;
|
||||||
|
tcp[11] = rgb.b;
|
||||||
|
|
||||||
|
rgb = getCRGBForBand(255, pal);
|
||||||
|
tcp[12] = 255; // anchor of last color - must be 255
|
||||||
|
tcp[13] = rgb.r;
|
||||||
|
tcp[14] = rgb.g;
|
||||||
|
tcp[15] = rgb.b;
|
||||||
|
|
||||||
tcp[0] = 0; // anchor of first color - must be zero
|
strip.customPalettes[lastCustPalette+pal].loadDynamicGradientPalette(tcp);
|
||||||
tcp[1] = 0;
|
}
|
||||||
tcp[2] = 0;
|
|
||||||
tcp[3] = 0;
|
|
||||||
|
|
||||||
CRGB rgb = getCRGBForBand(1, pal);
|
|
||||||
tcp[4] = 1; // anchor of first color
|
|
||||||
tcp[5] = rgb.r;
|
|
||||||
tcp[6] = rgb.g;
|
|
||||||
tcp[7] = rgb.b;
|
|
||||||
|
|
||||||
rgb = getCRGBForBand(128, pal);
|
|
||||||
tcp[8] = 128;
|
|
||||||
tcp[9] = rgb.r;
|
|
||||||
tcp[10] = rgb.g;
|
|
||||||
tcp[11] = rgb.b;
|
|
||||||
|
|
||||||
rgb = getCRGBForBand(255, pal);
|
|
||||||
tcp[12] = 255; // anchor of last color - must be 255
|
|
||||||
tcp[13] = rgb.r;
|
|
||||||
tcp[14] = rgb.g;
|
|
||||||
tcp[15] = rgb.b;
|
|
||||||
|
|
||||||
strip.customPalettes[strip.customPalettes.size()-1-palettes+pal].loadDynamicGradientPalette(tcp);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// strings to reduce flash memory usage (used more than twice)
|
// strings to reduce flash memory usage (used more than twice)
|
||||||
|
@ -2590,14 +2590,14 @@ uint16_t mode_twinklefox()
|
|||||||
{
|
{
|
||||||
return twinklefox_base(false);
|
return twinklefox_base(false);
|
||||||
}
|
}
|
||||||
static const char _data_FX_MODE_TWINKLEFOX[] PROGMEM = "Twinklefox@!,Twinkle rate,,,,Cool;;!";
|
static const char _data_FX_MODE_TWINKLEFOX[] PROGMEM = "Twinklefox@!,Twinkle rate,,,,Cool;!,!;!";
|
||||||
|
|
||||||
|
|
||||||
uint16_t mode_twinklecat()
|
uint16_t mode_twinklecat()
|
||||||
{
|
{
|
||||||
return twinklefox_base(true);
|
return twinklefox_base(true);
|
||||||
}
|
}
|
||||||
static const char _data_FX_MODE_TWINKLECAT[] PROGMEM = "Twinklecat@!,Twinkle rate,,,,Cool;;!";
|
static const char _data_FX_MODE_TWINKLECAT[] PROGMEM = "Twinklecat@!,Twinkle rate,,,,Cool;!,!;!";
|
||||||
|
|
||||||
|
|
||||||
//inspired by https://www.tweaking4all.com/hardware/arduino/adruino-led-strip-effects/#LEDStripEffectBlinkingHalloweenEyes
|
//inspired by https://www.tweaking4all.com/hardware/arduino/adruino-led-strip-effects/#LEDStripEffectBlinkingHalloweenEyes
|
||||||
|
@ -90,18 +90,21 @@ Segment::Segment(const Segment &orig) {
|
|||||||
//DEBUG_PRINTF("-- Copy segment constructor: %p -> %p\n", &orig, this);
|
//DEBUG_PRINTF("-- Copy segment constructor: %p -> %p\n", &orig, this);
|
||||||
memcpy((void*)this, (void*)&orig, sizeof(Segment));
|
memcpy((void*)this, (void*)&orig, sizeof(Segment));
|
||||||
_t = nullptr; // copied segment cannot be in transition
|
_t = nullptr; // copied segment cannot be in transition
|
||||||
if (orig.name) { name = new char[strlen(orig.name)+1]; if (name) strcpy(name, orig.name); } else { name = nullptr; }
|
name = nullptr;
|
||||||
if (orig.data) { if (allocateData(orig._dataLen)) memcpy(data, orig.data, orig._dataLen); } else { data = nullptr; _dataLen = 0; }
|
data = nullptr;
|
||||||
|
_dataLen = 0;
|
||||||
|
if (orig.name) { name = new char[strlen(orig.name)+1]; if (name) strcpy(name, orig.name); }
|
||||||
|
if (orig.data) { if (allocateData(orig._dataLen)) memcpy(data, orig.data, orig._dataLen); }
|
||||||
}
|
}
|
||||||
|
|
||||||
// move constructor
|
// move constructor
|
||||||
Segment::Segment(Segment &&orig) noexcept {
|
Segment::Segment(Segment &&orig) noexcept {
|
||||||
//DEBUG_PRINTF("-- Move segment constructor: %p -> %p\n", &orig, this);
|
//DEBUG_PRINTF("-- Move segment constructor: %p -> %p\n", &orig, this);
|
||||||
memcpy((void*)this, (void*)&orig, sizeof(Segment));
|
memcpy((void*)this, (void*)&orig, sizeof(Segment));
|
||||||
|
orig._t = nullptr; // old segment cannot be in transition any more
|
||||||
orig.name = nullptr;
|
orig.name = nullptr;
|
||||||
orig.data = nullptr;
|
orig.data = nullptr;
|
||||||
orig._dataLen = 0;
|
orig._dataLen = 0;
|
||||||
orig._t = nullptr; // old segment cannot be in transition any more
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// copy assignment
|
// copy assignment
|
||||||
@ -110,14 +113,7 @@ Segment& Segment::operator= (const Segment &orig) {
|
|||||||
if (this != &orig) {
|
if (this != &orig) {
|
||||||
// clean destination
|
// clean destination
|
||||||
if (name) { delete[] name; name = nullptr; }
|
if (name) { delete[] name; name = nullptr; }
|
||||||
if (orig.name) { name = new char[strlen(orig.name)+1]; if (name) strcpy(name, orig.name); }
|
stopTransition();
|
||||||
if (_t) {
|
|
||||||
#ifndef WLED_DISABLE_MODE_BLEND
|
|
||||||
if (_t->_segT._dataT) free(_t->_segT._dataT);
|
|
||||||
#endif
|
|
||||||
delete _t;
|
|
||||||
_t = nullptr; // copied segment cannot be in transition
|
|
||||||
}
|
|
||||||
deallocateData();
|
deallocateData();
|
||||||
// copy source
|
// copy source
|
||||||
memcpy((void*)this, (void*)&orig, sizeof(Segment));
|
memcpy((void*)this, (void*)&orig, sizeof(Segment));
|
||||||
@ -125,6 +121,7 @@ Segment& Segment::operator= (const Segment &orig) {
|
|||||||
data = nullptr;
|
data = nullptr;
|
||||||
_dataLen = 0;
|
_dataLen = 0;
|
||||||
// copy source data
|
// copy source data
|
||||||
|
if (orig.name) { name = new char[strlen(orig.name)+1]; if (name) strcpy(name, orig.name); }
|
||||||
if (orig.data) { if (allocateData(orig._dataLen)) memcpy(data, orig.data, orig._dataLen); }
|
if (orig.data) { if (allocateData(orig._dataLen)) memcpy(data, orig.data, orig._dataLen); }
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
@ -135,13 +132,7 @@ Segment& Segment::operator= (Segment &&orig) noexcept {
|
|||||||
//DEBUG_PRINTF("-- Moving segment: %p -> %p\n", &orig, this);
|
//DEBUG_PRINTF("-- Moving segment: %p -> %p\n", &orig, this);
|
||||||
if (this != &orig) {
|
if (this != &orig) {
|
||||||
if (name) { delete[] name; name = nullptr; } // free old name
|
if (name) { delete[] name; name = nullptr; } // free old name
|
||||||
if (_t) {
|
stopTransition();
|
||||||
#ifndef WLED_DISABLE_MODE_BLEND
|
|
||||||
if (_t->_segT._dataT) free(_t->_segT._dataT);
|
|
||||||
#endif
|
|
||||||
delete _t;
|
|
||||||
_t = nullptr;
|
|
||||||
}
|
|
||||||
deallocateData(); // free old runtime data
|
deallocateData(); // free old runtime data
|
||||||
memcpy((void*)this, (void*)&orig, sizeof(Segment));
|
memcpy((void*)this, (void*)&orig, sizeof(Segment));
|
||||||
orig.name = nullptr;
|
orig.name = nullptr;
|
||||||
@ -312,7 +303,7 @@ void Segment::startTransition(uint16_t dur) {
|
|||||||
if (_dataLen > 0 && data) {
|
if (_dataLen > 0 && data) {
|
||||||
_t->_segT._dataT = (byte *)malloc(_dataLen);
|
_t->_segT._dataT = (byte *)malloc(_dataLen);
|
||||||
if (_t->_segT._dataT) {
|
if (_t->_segT._dataT) {
|
||||||
//DEBUG_PRINTF("-- Allocated duplicate data (%d): %p\n", _dataLen, _t->_segT._dataT);
|
//DEBUG_PRINTF("-- Allocated duplicate data (%d) for %p: %p\n", _dataLen, this, _t->_segT._dataT);
|
||||||
memcpy(_t->_segT._dataT, data, _dataLen);
|
memcpy(_t->_segT._dataT, data, _dataLen);
|
||||||
_t->_segT._dataLenT = _dataLen;
|
_t->_segT._dataLenT = _dataLen;
|
||||||
}
|
}
|
||||||
@ -330,7 +321,7 @@ void Segment::stopTransition() {
|
|||||||
if (isInTransition()) {
|
if (isInTransition()) {
|
||||||
#ifndef WLED_DISABLE_MODE_BLEND
|
#ifndef WLED_DISABLE_MODE_BLEND
|
||||||
if (_t->_segT._dataT && _t->_segT._dataLenT > 0) {
|
if (_t->_segT._dataT && _t->_segT._dataLenT > 0) {
|
||||||
//DEBUG_PRINTF("-- Released duplicate data (%d): %p\n", _t->_segT._dataLenT, _t->_segT._dataT);
|
//DEBUG_PRINTF("-- Released duplicate data (%d) for %p: %p\n", _t->_segT._dataLenT, this, _t->_segT._dataT);
|
||||||
free(_t->_segT._dataT);
|
free(_t->_segT._dataT);
|
||||||
_t->_segT._dataT = nullptr;
|
_t->_segT._dataT = nullptr;
|
||||||
_t->_segT._dataLenT = 0;
|
_t->_segT._dataLenT = 0;
|
||||||
@ -588,7 +579,7 @@ void Segment::setMode(uint8_t fx, bool loadDefaults) {
|
|||||||
sOpt = extractModeDefaults(fx, "o2"); check2 = (sOpt >= 0) ? (bool)sOpt : false;
|
sOpt = extractModeDefaults(fx, "o2"); check2 = (sOpt >= 0) ? (bool)sOpt : false;
|
||||||
sOpt = extractModeDefaults(fx, "o3"); check3 = (sOpt >= 0) ? (bool)sOpt : false;
|
sOpt = extractModeDefaults(fx, "o3"); check3 = (sOpt >= 0) ? (bool)sOpt : false;
|
||||||
sOpt = extractModeDefaults(fx, "m12"); if (sOpt >= 0) map1D2D = constrain(sOpt, 0, 7);
|
sOpt = extractModeDefaults(fx, "m12"); if (sOpt >= 0) map1D2D = constrain(sOpt, 0, 7);
|
||||||
sOpt = extractModeDefaults(fx, "si"); if (sOpt >= 0) soundSim = constrain(sOpt, 0, 1);
|
sOpt = extractModeDefaults(fx, "si"); if (sOpt >= 0) soundSim = constrain(sOpt, 0, 3);
|
||||||
sOpt = extractModeDefaults(fx, "rev"); if (sOpt >= 0) reverse = (bool)sOpt;
|
sOpt = extractModeDefaults(fx, "rev"); if (sOpt >= 0) reverse = (bool)sOpt;
|
||||||
sOpt = extractModeDefaults(fx, "mi"); if (sOpt >= 0) mirror = (bool)sOpt; // NOTE: setting this option is a risky business
|
sOpt = extractModeDefaults(fx, "mi"); if (sOpt >= 0) mirror = (bool)sOpt; // NOTE: setting this option is a risky business
|
||||||
sOpt = extractModeDefaults(fx, "rY"); if (sOpt >= 0) reverse_y = (bool)sOpt;
|
sOpt = extractModeDefaults(fx, "rY"); if (sOpt >= 0) reverse_y = (bool)sOpt;
|
||||||
|
@ -34,6 +34,7 @@
|
|||||||
--bhd: none;
|
--bhd: none;
|
||||||
--sgp: "block";
|
--sgp: "block";
|
||||||
--bmt: 0;
|
--bmt: 0;
|
||||||
|
--sti: 42px;
|
||||||
}
|
}
|
||||||
|
|
||||||
html {
|
html {
|
||||||
@ -219,7 +220,7 @@ button {
|
|||||||
.pop-c span {
|
.pop-c span {
|
||||||
padding: 2px 6px;
|
padding: 2px 6px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.search-icon {
|
.search-icon {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 8px;
|
top: 8px;
|
||||||
@ -457,12 +458,17 @@ button {
|
|||||||
padding: 4px 2px;
|
padding: 4px 2px;
|
||||||
position: relative;
|
position: relative;
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
transition: opacity .5s linear, height .5s, transform .5s;
|
transition: opacity .5s linear, height .25s, transform .25s;
|
||||||
}
|
}
|
||||||
|
|
||||||
.filter {
|
.filter {
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
/*overflow: visible;*/
|
/*overflow: visible;*/
|
||||||
|
border-radius: 0 0 16px 16px;
|
||||||
|
max-width: 220px;
|
||||||
|
height: 54px;
|
||||||
|
line-height: 1.5;
|
||||||
|
padding-bottom: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* New tooltip */
|
/* New tooltip */
|
||||||
@ -470,7 +476,7 @@ button {
|
|||||||
position: absolute;
|
position: absolute;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
visibility: hidden;
|
visibility: hidden;
|
||||||
transition: opacity .4s ease, visibility .4s ease;
|
transition: opacity .25s ease, visibility .25s ease;
|
||||||
background-color: var(--c-5);
|
background-color: var(--c-5);
|
||||||
box-shadow: 4px 4px 10px 4px var(--c-1);
|
box-shadow: 4px 4px 10px 4px var(--c-1);
|
||||||
color: var(--c-f);
|
color: var(--c-f);
|
||||||
@ -478,13 +484,13 @@ button {
|
|||||||
padding: 8px 16px;
|
padding: 8px 16px;
|
||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tooltip::after {
|
.tooltip::after {
|
||||||
content: "";
|
content: "";
|
||||||
position: absolute;
|
position: absolute;
|
||||||
border: 8px;
|
border: 8px solid;
|
||||||
border-style: solid;
|
|
||||||
border-color: var(--c-5) transparent transparent transparent;
|
border-color: var(--c-5) transparent transparent transparent;
|
||||||
top: 100%;
|
top: 100%;
|
||||||
left: calc(50% - 8px);
|
left: calc(50% - 8px);
|
||||||
@ -1231,6 +1237,10 @@ TD .checkmark, TD .radiomark {
|
|||||||
-webkit-filter: grayscale(100%); /* Safari 6.0 - 9.0 */
|
-webkit-filter: grayscale(100%); /* Safari 6.0 - 9.0 */
|
||||||
filter: grayscale(100%);
|
filter: grayscale(100%);
|
||||||
}
|
}
|
||||||
|
.filter .fchkl {
|
||||||
|
margin: 0 4px;
|
||||||
|
min-width: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
.lbl-l {
|
.lbl-l {
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
@ -1307,20 +1317,14 @@ TD .checkmark, TD .radiomark {
|
|||||||
top: 42px;
|
top: 42px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#fxlist .lstI.selected {
|
#fxlist .lstI.selected,
|
||||||
top: 84px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#fxlist .lstI.sticky {
|
|
||||||
top: 42px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#pallist .lstI.selected {
|
#pallist .lstI.selected {
|
||||||
top: 84px;
|
top: calc(var(--sti) + 42px);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#fxlist .lstI.sticky,
|
||||||
#pallist .lstI.sticky {
|
#pallist .lstI.sticky {
|
||||||
top: 42px;
|
top: var(--sti);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* list item content */
|
/* list item content */
|
||||||
|
@ -182,7 +182,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div id="pallist" class="list">
|
<div id="pallist" class="list">
|
||||||
<div class="lstI">
|
<div class="lstI">
|
||||||
<label class="radio schkl" onclick="loadPalettes()">
|
<label class="radio schkl" onclick="loadPalettes()">
|
||||||
<div class="lstIcontent">
|
<div class="lstIcontent">
|
||||||
<span class="lstIname">
|
<span class="lstIname">
|
||||||
Loading...
|
Loading...
|
||||||
@ -198,13 +198,39 @@
|
|||||||
<div id="fx">
|
<div id="fx">
|
||||||
<p class="labels hd" id="modeLabel">Effect mode</p>
|
<p class="labels hd" id="modeLabel">Effect mode</p>
|
||||||
<div class="staytop fnd" id="fxFind">
|
<div class="staytop fnd" id="fxFind">
|
||||||
<input type="text" placeholder="Search" oninput="search(this,'fxlist')" onfocus="search(this,'fxlist');gId('filters').classList.add('fade');" onblur="gId('filters').classList.remove('fade')"/>
|
<input type="text" placeholder="Search" oninput="search(this,'fxlist')" onfocus="filterFocus(event);search(this,'fxlist');" onblur="filterFocus(event);" />
|
||||||
<i class="icons clear-icon" onclick="clean(this);"></i>
|
<i class="icons clear-icon" onclick="clean(this);"></i>
|
||||||
<i class="icons search-icon" onclick="gId('filters').classList.toggle('hide');" style="cursor:pointer;"></i>
|
<i class="icons search-icon" style="cursor:pointer;"></i>
|
||||||
|
<div id="filters" class="filter fade">
|
||||||
|
<label id="filterPal" tooltip="Uses palette" class="check fchkl">🎨
|
||||||
|
<input type="checkbox" data-flt="🎨" onchange="filterFx(this);">
|
||||||
|
<span class="checkmark"></span>
|
||||||
|
</label>
|
||||||
|
<label id="filter0D" tooltip="Single pixel" class="check fchkl">•
|
||||||
|
<input type="checkbox" data-flt="•" onchange="filterFx(this);">
|
||||||
|
<span class="checkmark"></span>
|
||||||
|
</label>
|
||||||
|
<label id="filter1D" tooltip="1D" class="check fchkl">⋮
|
||||||
|
<input type="checkbox" data-flt="⋮" onchange="filterFx(this);">
|
||||||
|
<span class="checkmark"></span>
|
||||||
|
</label>
|
||||||
|
<label id="filter2D" tooltip="2D" class="check fchkl">▦
|
||||||
|
<input type="checkbox" data-flt="▦" onchange="filterFx(this);">
|
||||||
|
<span class="checkmark"></span>
|
||||||
|
</label>
|
||||||
|
<label id="filterVol" tooltip="Volume" class="check fchkl">♪
|
||||||
|
<input type="checkbox" data-flt="♪" onchange="filterFx(this);">
|
||||||
|
<span class="checkmark"></span>
|
||||||
|
</label>
|
||||||
|
<label id="filterFreq" tooltip="Frequency" class="check fchkl">♫
|
||||||
|
<input type="checkbox" data-flt="♫" onchange="filterFx(this);">
|
||||||
|
<span class="checkmark"></span>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="fxlist" class="list">
|
<div id="fxlist" class="list">
|
||||||
<div class="lstI">
|
<div class="lstI">
|
||||||
<label class="radio schkl" onclick="loadFX()">
|
<label class="radio schkl" onclick="loadFX()">
|
||||||
<div class="lstIcontent">
|
<div class="lstIcontent">
|
||||||
<span class="lstIname">
|
<span class="lstIname">
|
||||||
Loading...
|
Loading...
|
||||||
@ -215,32 +241,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="sliders">
|
<div id="sliders">
|
||||||
<div id="filters" class="filter">
|
|
||||||
<label id="filterPal" tooltip="Uses palette" class="check fchkl">🎨
|
|
||||||
<input type="checkbox" data-flt="🎨" onchange="filterFx(this)">
|
|
||||||
<span class="checkmark"></span>
|
|
||||||
</label>
|
|
||||||
<label id="filter0D" tooltip="Single pixel" class="check fchkl hide">•
|
|
||||||
<input type="checkbox" data-flt="•" onchange="filterFx(this)">
|
|
||||||
<span class="checkmark"></span>
|
|
||||||
</label>
|
|
||||||
<label id="filter1D" tooltip="1D" class="check fchkl">⋮
|
|
||||||
<input type="checkbox" data-flt="⋮" onchange="filterFx(this)">
|
|
||||||
<span class="checkmark"></span>
|
|
||||||
</label>
|
|
||||||
<label id="filter2D" tooltip="2D" class="check fchkl">▦
|
|
||||||
<input type="checkbox" data-flt="▦" onchange="filterFx(this)">
|
|
||||||
<span class="checkmark"></span>
|
|
||||||
</label>
|
|
||||||
<label id="filterVol" tooltip="Volume" class="check fchkl">♪
|
|
||||||
<input type="checkbox" data-flt="♪" onchange="filterFx(this)">
|
|
||||||
<span class="checkmark"></span>
|
|
||||||
</label>
|
|
||||||
<label id="filterFreq" tooltip="Frequency" class="check fchkl">♫
|
|
||||||
<input type="checkbox" data-flt="♫" onchange="filterFx(this)">
|
|
||||||
<span class="checkmark"></span>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
<div id="slider0" class="slider">
|
<div id="slider0" class="slider">
|
||||||
<i class="icons slider-icon" onclick="tglFreeze()"></i>
|
<i class="icons slider-icon" onclick="tglFreeze()"></i>
|
||||||
<div tooltip="Effect speed" class="sliderwrap il">
|
<div tooltip="Effect speed" class="sliderwrap il">
|
||||||
@ -360,7 +360,7 @@
|
|||||||
<div id="kn">Loading...</div>
|
<div id="kn">Loading...</div>
|
||||||
<div style="position:sticky;bottom:0;">
|
<div style="position:sticky;bottom:0;">
|
||||||
<button class="btn infobtn" onclick="loadNodes()">Refresh</button>
|
<button class="btn infobtn" onclick="loadNodes()">Refresh</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="mlv2D" class="modal">
|
<div id="mlv2D" class="modal">
|
||||||
|
@ -232,6 +232,7 @@ function onLoad()
|
|||||||
var sett = localStorage.getItem('wledUiCfg');
|
var sett = localStorage.getItem('wledUiCfg');
|
||||||
if (sett) cfg = mergeDeep(cfg, JSON.parse(sett));
|
if (sett) cfg = mergeDeep(cfg, JSON.parse(sett));
|
||||||
|
|
||||||
|
tooltip();
|
||||||
resetPUtil();
|
resetPUtil();
|
||||||
|
|
||||||
if (localStorage.getItem('pcm') == "true" || (!/Mobi/.test(navigator.userAgent) && localStorage.getItem('pcm') == null)) togglePcMode(true);
|
if (localStorage.getItem('pcm') == "true" || (!/Mobi/.test(navigator.userAgent) && localStorage.getItem('pcm') == null)) togglePcMode(true);
|
||||||
@ -637,12 +638,12 @@ function parseInfo(i) {
|
|||||||
mh = i.leds.matrix ? i.leds.matrix.h : 0;
|
mh = i.leds.matrix ? i.leds.matrix.h : 0;
|
||||||
isM = mw>0 && mh>0;
|
isM = mw>0 && mh>0;
|
||||||
if (!isM) {
|
if (!isM) {
|
||||||
gId("filter0D").classList.remove('hide');
|
//gId("filter0D").classList.remove('hide');
|
||||||
gId("filter1D").classList.add('hide');
|
//gId("filter1D").classList.add('hide');
|
||||||
gId("filter2D").classList.add('hide');
|
gId("filter2D").classList.add('hide');
|
||||||
} else {
|
} else {
|
||||||
gId("filter0D").classList.add('hide');
|
//gId("filter0D").classList.add('hide');
|
||||||
gId("filter1D").classList.remove('hide');
|
//gId("filter1D").classList.remove('hide');
|
||||||
gId("filter2D").classList.remove('hide');
|
gId("filter2D").classList.remove('hide');
|
||||||
}
|
}
|
||||||
// if (i.noaudio) {
|
// if (i.noaudio) {
|
||||||
@ -1421,7 +1422,7 @@ function readState(s,command=false)
|
|||||||
|
|
||||||
if (s.seg.length>2) d.querySelectorAll(".pop").forEach((e)=>{e.classList.remove("hide");});
|
if (s.seg.length>2) d.querySelectorAll(".pop").forEach((e)=>{e.classList.remove("hide");});
|
||||||
|
|
||||||
var cd = gId('csl').children;
|
var cd = gId('csl').querySelectorAll("button");
|
||||||
for (let e = cd.length-1; e >= 0; e--) {
|
for (let e = cd.length-1; e >= 0; e--) {
|
||||||
cd[e].dataset.r = i.col[e][0];
|
cd[e].dataset.r = i.col[e][0];
|
||||||
cd[e].dataset.g = i.col[e][1];
|
cd[e].dataset.g = i.col[e][1];
|
||||||
@ -1541,7 +1542,7 @@ function setEffectParameters(idx)
|
|||||||
var cslLabel = '';
|
var cslLabel = '';
|
||||||
var sep = '';
|
var sep = '';
|
||||||
var cslCnt = 0, oCsel = csel;
|
var cslCnt = 0, oCsel = csel;
|
||||||
for (let i=0; i<gId("csl").children.length; i++) {
|
for (let i=0; i<gId("csl").querySelectorAll("button"); i++) {
|
||||||
var btn = gId("csl" + i);
|
var btn = gId("csl" + i);
|
||||||
// if no controlDefined or coOnOff has a value
|
// if no controlDefined or coOnOff has a value
|
||||||
if (coOnOff.length>i && coOnOff[i] != "") {
|
if (coOnOff.length>i && coOnOff[i] != "") {
|
||||||
@ -2744,6 +2745,25 @@ function clean(c)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function filterFocus(e)
|
||||||
|
{
|
||||||
|
let t = e.explicitOriginalTarget;
|
||||||
|
let f = gId("filters");
|
||||||
|
if (e.type === "focus") f.classList.remove('fade'); // immediately show (still has transition)
|
||||||
|
// compute sticky top (with delay for transition)
|
||||||
|
setTimeout(()=>{
|
||||||
|
let sti = parseInt(getComputedStyle(d.documentElement).getPropertyValue('--sti')) + (e.type === "focus" ? 1 : -1) * f.offsetHeight;
|
||||||
|
sCol('--sti', sti+"px");
|
||||||
|
}, 252);
|
||||||
|
if (e.type === "blur") {
|
||||||
|
do {
|
||||||
|
if (t.id && (t.id === "fxFind")) { setTimeout(()=>{t.firstElementChild.focus();},150); return; }
|
||||||
|
t = t.parentElement;
|
||||||
|
} while (t.tagName !== "BODY");
|
||||||
|
setTimeout(()=>{f.classList.add('fade');},255); // wait with hiding
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function filterFx(o)
|
function filterFx(o)
|
||||||
{
|
{
|
||||||
if (!o) return;
|
if (!o) return;
|
||||||
@ -2933,34 +2953,33 @@ function mergeDeep(target, ...sources)
|
|||||||
function tooltip()
|
function tooltip()
|
||||||
{
|
{
|
||||||
const elements = d.querySelectorAll("[tooltip]");
|
const elements = d.querySelectorAll("[tooltip]");
|
||||||
|
|
||||||
elements.forEach((element)=>{
|
elements.forEach((element)=>{
|
||||||
element.addEventListener("mouseover", ()=>{
|
element.addEventListener("mouseover", ()=>{
|
||||||
const tooltip = d.createElement("span");
|
const tooltip = d.createElement("span");
|
||||||
|
|
||||||
tooltip.className = "tooltip";
|
tooltip.className = "tooltip";
|
||||||
tooltip.textContent = element.getAttribute("tooltip");
|
tooltip.textContent = element.getAttribute("tooltip");
|
||||||
|
|
||||||
let { top, left, width } = element.getBoundingClientRect();
|
let { top, left, width } = element.getBoundingClientRect();
|
||||||
|
|
||||||
d.body.appendChild(tooltip);
|
d.body.appendChild(tooltip);
|
||||||
|
|
||||||
const { offsetHeight, offsetWidth } = tooltip;
|
const { offsetHeight, offsetWidth } = tooltip;
|
||||||
|
|
||||||
const offset = element.classList.contains("sliderwrap") ? 6 : 12;
|
const offset = element.classList.contains("sliderwrap") ? 4 : 10;
|
||||||
top -= offsetHeight + offset;
|
top -= offsetHeight + offset;
|
||||||
left += (width - offsetWidth) / 2;
|
left += (width - offsetWidth) / 2;
|
||||||
|
|
||||||
tooltip.style.top = top + "px";
|
tooltip.style.top = top + "px";
|
||||||
tooltip.style.left = left + "px";
|
tooltip.style.left = left + "px";
|
||||||
|
|
||||||
tooltip.classList.add("visible");
|
tooltip.classList.add("visible");
|
||||||
});
|
});
|
||||||
|
|
||||||
element.addEventListener("mouseout", ()=>{
|
element.addEventListener("mouseout", ()=>{
|
||||||
const tooltip = d.querySelector('.tooltip');
|
const tooltips = d.querySelectorAll('.tooltip');
|
||||||
tooltip.classList.remove("visible");
|
tooltips.forEach((tooltip)=>{
|
||||||
d.body.removeChild(tooltip);
|
tooltip.classList.remove("visible");
|
||||||
|
d.body.removeChild(tooltip);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@ -2976,5 +2995,3 @@ _C.addEventListener('touchstart', lock, false);
|
|||||||
_C.addEventListener('mouseout', move, false);
|
_C.addEventListener('mouseout', move, false);
|
||||||
_C.addEventListener('mouseup', move, false);
|
_C.addEventListener('mouseup', move, false);
|
||||||
_C.addEventListener('touchend', move, false);
|
_C.addEventListener('touchend', move, false);
|
||||||
|
|
||||||
d.addEventListener('DOMContentLoaded', tooltip);
|
|
4039
wled00/html_ui.h
4039
wled00/html_ui.h
File diff suppressed because it is too large
Load Diff
@ -33,9 +33,9 @@ bool deserializeSegment(JsonObject elem, byte it, byte presetId)
|
|||||||
|
|
||||||
//DEBUG_PRINTLN("-- JSON deserialize segment.");
|
//DEBUG_PRINTLN("-- JSON deserialize segment.");
|
||||||
Segment& seg = strip.getSegment(id);
|
Segment& seg = strip.getSegment(id);
|
||||||
//DEBUG_PRINTF("-- Original segment: %p\n", &seg);
|
//DEBUG_PRINTF("-- Original segment: %p (%p)\n", &seg, seg.data);
|
||||||
Segment prev = seg; //make a backup so we can tell if something changed
|
Segment prev = seg; //make a backup so we can tell if something changed (calling copy constructor)
|
||||||
//DEBUG_PRINTF("-- Duplicate segment: %p\n", &prev);
|
//DEBUG_PRINTF("-- Duplicate segment: %p (%p)\n", &prev, prev.data);
|
||||||
|
|
||||||
uint16_t start = elem["start"] | seg.start;
|
uint16_t start = elem["start"] | seg.start;
|
||||||
if (stop < 0) {
|
if (stop < 0) {
|
||||||
@ -100,7 +100,7 @@ bool deserializeSegment(JsonObject elem, byte it, byte presetId)
|
|||||||
if ((spc>0 && spc!=seg.spacing) || seg.map1D2D!=map1D2D) seg.fill(BLACK); // clear spacing gaps
|
if ((spc>0 && spc!=seg.spacing) || seg.map1D2D!=map1D2D) seg.fill(BLACK); // clear spacing gaps
|
||||||
|
|
||||||
seg.map1D2D = constrain(map1D2D, 0, 7);
|
seg.map1D2D = constrain(map1D2D, 0, 7);
|
||||||
seg.soundSim = constrain(soundSim, 0, 1);
|
seg.soundSim = constrain(soundSim, 0, 3);
|
||||||
|
|
||||||
uint8_t set = elem[F("set")] | seg.set;
|
uint8_t set = elem[F("set")] | seg.set;
|
||||||
seg.set = constrain(set, 0, 3);
|
seg.set = constrain(set, 0, 3);
|
||||||
@ -1015,8 +1015,15 @@ void serializeModeNames(JsonArray arr)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static volatile bool servingClient = false;
|
||||||
void serveJson(AsyncWebServerRequest* request)
|
void serveJson(AsyncWebServerRequest* request)
|
||||||
{
|
{
|
||||||
|
if (servingClient) {
|
||||||
|
request->send(503, "application/json", F("{\"error\":2}")); // ERR_CONCURENCY
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
servingClient = true;
|
||||||
|
|
||||||
byte subJson = 0;
|
byte subJson = 0;
|
||||||
const String& url = request->url();
|
const String& url = request->url();
|
||||||
if (url.indexOf("state") > 0) subJson = JSON_PATH_STATE;
|
if (url.indexOf("state") > 0) subJson = JSON_PATH_STATE;
|
||||||
@ -1030,23 +1037,28 @@ void serveJson(AsyncWebServerRequest* request)
|
|||||||
#ifdef WLED_ENABLE_JSONLIVE
|
#ifdef WLED_ENABLE_JSONLIVE
|
||||||
else if (url.indexOf("live") > 0) {
|
else if (url.indexOf("live") > 0) {
|
||||||
serveLiveLeds(request);
|
serveLiveLeds(request);
|
||||||
|
servingClient = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
else if (url.indexOf("pal") > 0) {
|
else if (url.indexOf("pal") > 0) {
|
||||||
request->send_P(200, "application/json", JSON_palette_names);
|
request->send_P(200, "application/json", JSON_palette_names);
|
||||||
|
servingClient = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (url.indexOf("cfg") > 0 && handleFileRead(request, "/cfg.json")) {
|
else if (url.indexOf("cfg") > 0 && handleFileRead(request, "/cfg.json")) {
|
||||||
|
servingClient = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (url.length() > 6) { //not just /json
|
else if (url.length() > 6) { //not just /json
|
||||||
request->send(501, "application/json", F("{\"error\":\"Not implemented\"}"));
|
request->send(501, "application/json", F("{\"error\":\"Not implemented\"}"));
|
||||||
|
servingClient = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!requestJSONBufferLock(17)) {
|
if (!requestJSONBufferLock(17)) {
|
||||||
request->send(503, "application/json", F("{\"error\":3}"));
|
request->send(503, "application/json", F("{\"error\":3}"));
|
||||||
|
servingClient = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
AsyncJsonResponse *response = new AsyncJsonResponse(&doc, subJson==JSON_PATH_FXDATA || subJson==JSON_PATH_EFFECTS); // will clear and convert JsonDocument into JsonArray if necessary
|
AsyncJsonResponse *response = new AsyncJsonResponse(&doc, subJson==JSON_PATH_FXDATA || subJson==JSON_PATH_EFFECTS); // will clear and convert JsonDocument into JsonArray if necessary
|
||||||
@ -1093,10 +1105,11 @@ void serveJson(AsyncWebServerRequest* request)
|
|||||||
|
|
||||||
request->send(response);
|
request->send(response);
|
||||||
releaseJSONBufferLock();
|
releaseJSONBufferLock();
|
||||||
|
servingClient = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef WLED_ENABLE_JSONLIVE
|
#ifdef WLED_ENABLE_JSONLIVE
|
||||||
#define MAX_LIVE_LEDS 180
|
#define MAX_LIVE_LEDS 256
|
||||||
|
|
||||||
bool serveLiveLeds(AsyncWebServerRequest* request, uint32_t wsClient)
|
bool serveLiveLeds(AsyncWebServerRequest* request, uint32_t wsClient)
|
||||||
{
|
{
|
||||||
@ -1110,13 +1123,26 @@ bool serveLiveLeds(AsyncWebServerRequest* request, uint32_t wsClient)
|
|||||||
|
|
||||||
uint16_t used = strip.getLengthTotal();
|
uint16_t used = strip.getLengthTotal();
|
||||||
uint16_t n = (used -1) /MAX_LIVE_LEDS +1; //only serve every n'th LED if count over MAX_LIVE_LEDS
|
uint16_t n = (used -1) /MAX_LIVE_LEDS +1; //only serve every n'th LED if count over MAX_LIVE_LEDS
|
||||||
char buffer[2000];
|
#ifndef WLED_DISABLE_2D
|
||||||
|
if (strip.isMatrix) {
|
||||||
|
// ignore anything behid matrix (i.e. extra strip)
|
||||||
|
used = Segment::maxWidth*Segment::maxHeight; // always the size of matrix (more or less than strip.getLengthTotal())
|
||||||
|
n = 1;
|
||||||
|
if (used > MAX_LIVE_LEDS) n = 2;
|
||||||
|
if (used > MAX_LIVE_LEDS*4) n = 4;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
char buffer[2048]; // shoud be enough for 256 LEDs [RRGGBB] + all other text (9+25)
|
||||||
strcpy_P(buffer, PSTR("{\"leds\":["));
|
strcpy_P(buffer, PSTR("{\"leds\":["));
|
||||||
obuf = buffer;
|
obuf = buffer; // assign buffer for oappnd() functions
|
||||||
olen = 9;
|
olen = 9;
|
||||||
|
|
||||||
for (size_t i= 0; i < used; i += n)
|
for (size_t i = 0; i < used; i += n)
|
||||||
{
|
{
|
||||||
|
#ifndef WLED_DISABLE_2D
|
||||||
|
if (strip.isMatrix && n>1 && (i/Segment::maxWidth)%n) i += Segment::maxWidth * (n-1);
|
||||||
|
#endif
|
||||||
uint32_t c = strip.getPixelColor(i);
|
uint32_t c = strip.getPixelColor(i);
|
||||||
uint8_t r = R(c);
|
uint8_t r = R(c);
|
||||||
uint8_t g = G(c);
|
uint8_t g = G(c);
|
||||||
@ -1125,11 +1151,19 @@ bool serveLiveLeds(AsyncWebServerRequest* request, uint32_t wsClient)
|
|||||||
r = scale8(qadd8(w, r), strip.getBrightness()); //R, add white channel to RGB channels as a simple RGBW -> RGB map
|
r = scale8(qadd8(w, r), strip.getBrightness()); //R, add white channel to RGB channels as a simple RGBW -> RGB map
|
||||||
g = scale8(qadd8(w, g), strip.getBrightness()); //G
|
g = scale8(qadd8(w, g), strip.getBrightness()); //G
|
||||||
b = scale8(qadd8(w, b), strip.getBrightness()); //B
|
b = scale8(qadd8(w, b), strip.getBrightness()); //B
|
||||||
olen += sprintf(obuf + olen, "\"%06X\",", RGBW32(r,g,b,0));
|
olen += sprintf_P(obuf + olen, PSTR("\"%06X\","), RGBW32(r,g,b,0));
|
||||||
}
|
}
|
||||||
olen -= 1;
|
olen -= 1;
|
||||||
oappend((const char*)F("],\"n\":"));
|
oappend((const char*)F("],\"n\":"));
|
||||||
oappendi(n);
|
oappendi(n);
|
||||||
|
#ifndef WLED_DISABLE_2D
|
||||||
|
if (strip.isMatrix) {
|
||||||
|
oappend((const char*)F(",\"w\":"));
|
||||||
|
oappendi(Segment::maxWidth/n);
|
||||||
|
oappend((const char*)F(",\"h\":"));
|
||||||
|
oappendi(Segment::maxHeight/n);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
oappend("}");
|
oappend("}");
|
||||||
if (request) {
|
if (request) {
|
||||||
request->send(200, "application/json", buffer);
|
request->send(200, "application/json", buffer);
|
||||||
@ -1139,6 +1173,7 @@ bool serveLiveLeds(AsyncWebServerRequest* request, uint32_t wsClient)
|
|||||||
wsc->text(obuf, olen);
|
wsc->text(obuf, olen);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
obuf = nullptr;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -296,8 +296,9 @@ void parseNotifyPacket(uint8_t *udpIn) {
|
|||||||
}
|
}
|
||||||
if (version > 11) {
|
if (version > 11) {
|
||||||
// when applying synced options ignore selected as it may be used as indicator of which segments to sync
|
// when applying synced options ignore selected as it may be used as indicator of which segments to sync
|
||||||
// freeze, reset & transitional should never be synced
|
// freeze, reset should never be synced
|
||||||
selseg.options = (selseg.options & 0x0071U) | (udpIn[28+ofs]<<8) | (udpIn[9 +ofs] & 0x8E); // ignore selected, freeze, reset & transitional
|
// LSB to MSB: select, reverse, on, mirror, freeze, reset, reverse_y, mirror_y, transpose, map1d2d (3), ssim (2), set (2)
|
||||||
|
selseg.options = (selseg.options & 0b0000000000110001U) | (udpIn[28+ofs]<<8) | (udpIn[9 +ofs] & 0b11001110U); // ignore selected, freeze, reset
|
||||||
if (applyEffects) {
|
if (applyEffects) {
|
||||||
selseg.custom1 = udpIn[29+ofs];
|
selseg.custom1 = udpIn[29+ofs];
|
||||||
selseg.custom2 = udpIn[30+ofs];
|
selseg.custom2 = udpIn[30+ofs];
|
||||||
@ -532,6 +533,7 @@ void handleNotifications()
|
|||||||
//wled notifier, ignore if realtime packets active
|
//wled notifier, ignore if realtime packets active
|
||||||
if (udpIn[0] == 0 && !realtimeMode && receiveGroups)
|
if (udpIn[0] == 0 && !realtimeMode && receiveGroups)
|
||||||
{
|
{
|
||||||
|
DEBUG_PRINT(F("UDP notification from: ")); DEBUG_PRINTLN(notifierUdp.remoteIP());
|
||||||
parseNotifyPacket(udpIn);
|
parseNotifyPacket(udpIn);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -61,11 +61,11 @@ void WLED::loop()
|
|||||||
#ifdef WLED_ENABLE_DMX
|
#ifdef WLED_ENABLE_DMX
|
||||||
handleDMX();
|
handleDMX();
|
||||||
#endif
|
#endif
|
||||||
userLoop();
|
|
||||||
|
|
||||||
#ifdef WLED_DEBUG
|
#ifdef WLED_DEBUG
|
||||||
unsigned long usermodMillis = millis();
|
unsigned long usermodMillis = millis();
|
||||||
#endif
|
#endif
|
||||||
|
userLoop();
|
||||||
usermods.loop();
|
usermods.loop();
|
||||||
#ifdef WLED_DEBUG
|
#ifdef WLED_DEBUG
|
||||||
usermodMillis = millis() - usermodMillis;
|
usermodMillis = millis() - usermodMillis;
|
||||||
@ -186,7 +186,9 @@ void WLED::loop()
|
|||||||
|
|
||||||
yield();
|
yield();
|
||||||
handleWs();
|
handleWs();
|
||||||
|
#if defined(STATUSLED)
|
||||||
handleStatusLED();
|
handleStatusLED();
|
||||||
|
#endif
|
||||||
|
|
||||||
toki.resetTick();
|
toki.resetTick();
|
||||||
|
|
||||||
@ -256,9 +258,9 @@ void WLED::loop()
|
|||||||
#endif // WLED_DEBUG
|
#endif // WLED_DEBUG
|
||||||
}
|
}
|
||||||
|
|
||||||
void WLED::enableWatchdog() {
|
|
||||||
#if WLED_WATCHDOG_TIMEOUT > 0
|
#if WLED_WATCHDOG_TIMEOUT > 0
|
||||||
#ifdef ARDUINO_ARCH_ESP32
|
void WLED::enableWatchdog() {
|
||||||
|
#ifdef ARDUINO_ARCH_ESP32
|
||||||
esp_err_t watchdog = esp_task_wdt_init(WLED_WATCHDOG_TIMEOUT, true);
|
esp_err_t watchdog = esp_task_wdt_init(WLED_WATCHDOG_TIMEOUT, true);
|
||||||
DEBUG_PRINT(F("Watchdog enabled: "));
|
DEBUG_PRINT(F("Watchdog enabled: "));
|
||||||
if (watchdog == ESP_OK) {
|
if (watchdog == ESP_OK) {
|
||||||
@ -268,22 +270,20 @@ void WLED::enableWatchdog() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
esp_task_wdt_add(NULL);
|
esp_task_wdt_add(NULL);
|
||||||
#else
|
#else
|
||||||
ESP.wdtEnable(WLED_WATCHDOG_TIMEOUT * 1000);
|
ESP.wdtEnable(WLED_WATCHDOG_TIMEOUT * 1000);
|
||||||
#endif
|
#endif
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void WLED::disableWatchdog() {
|
void WLED::disableWatchdog() {
|
||||||
#if WLED_WATCHDOG_TIMEOUT > 0
|
DEBUG_PRINTLN(F("Watchdog: disabled"));
|
||||||
DEBUG_PRINTLN(F("Watchdog: disabled"));
|
#ifdef ARDUINO_ARCH_ESP32
|
||||||
#ifdef ARDUINO_ARCH_ESP32
|
|
||||||
esp_task_wdt_delete(NULL);
|
esp_task_wdt_delete(NULL);
|
||||||
#else
|
#else
|
||||||
ESP.wdtDisable();
|
ESP.wdtDisable();
|
||||||
#endif
|
#endif
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void WLED::setup()
|
void WLED::setup()
|
||||||
{
|
{
|
||||||
@ -464,15 +464,19 @@ void WLED::setup()
|
|||||||
#ifndef WLED_DISABLE_OTA
|
#ifndef WLED_DISABLE_OTA
|
||||||
if (aOtaEnabled) {
|
if (aOtaEnabled) {
|
||||||
ArduinoOTA.onStart([]() {
|
ArduinoOTA.onStart([]() {
|
||||||
#ifdef ESP8266
|
#ifdef ESP8266
|
||||||
wifi_set_sleep_type(NONE_SLEEP_T);
|
wifi_set_sleep_type(NONE_SLEEP_T);
|
||||||
#endif
|
#endif
|
||||||
|
#if WLED_WATCHDOG_TIMEOUT > 0
|
||||||
WLED::instance().disableWatchdog();
|
WLED::instance().disableWatchdog();
|
||||||
|
#endif
|
||||||
DEBUG_PRINTLN(F("Start ArduinoOTA"));
|
DEBUG_PRINTLN(F("Start ArduinoOTA"));
|
||||||
});
|
});
|
||||||
ArduinoOTA.onError([](ota_error_t error) {
|
ArduinoOTA.onError([](ota_error_t error) {
|
||||||
|
#if WLED_WATCHDOG_TIMEOUT > 0
|
||||||
// reenable watchdog on failed update
|
// reenable watchdog on failed update
|
||||||
WLED::instance().enableWatchdog();
|
WLED::instance().enableWatchdog();
|
||||||
|
#endif
|
||||||
});
|
});
|
||||||
if (strlen(cmDNS) > 0)
|
if (strlen(cmDNS) > 0)
|
||||||
ArduinoOTA.setHostname(cmDNS);
|
ArduinoOTA.setHostname(cmDNS);
|
||||||
@ -491,7 +495,9 @@ void WLED::setup()
|
|||||||
initServer();
|
initServer();
|
||||||
DEBUG_PRINT(F("heap ")); DEBUG_PRINTLN(ESP.getFreeHeap());
|
DEBUG_PRINT(F("heap ")); DEBUG_PRINTLN(ESP.getFreeHeap());
|
||||||
|
|
||||||
|
#if WLED_WATCHDOG_TIMEOUT > 0
|
||||||
enableWatchdog();
|
enableWatchdog();
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(ARDUINO_ARCH_ESP32) && defined(WLED_DISABLE_BROWNOUT_DET)
|
#if defined(ARDUINO_ARCH_ESP32) && defined(WLED_DISABLE_BROWNOUT_DET)
|
||||||
WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 1); //enable brownout detector
|
WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 1); //enable brownout detector
|
||||||
@ -915,9 +921,9 @@ void WLED::handleConnection()
|
|||||||
// else blink at 1Hz when WLED_CONNECTED is false (no WiFi, ?? no Ethernet ??)
|
// else blink at 1Hz when WLED_CONNECTED is false (no WiFi, ?? no Ethernet ??)
|
||||||
// else blink at 2Hz when MQTT is enabled but not connected
|
// else blink at 2Hz when MQTT is enabled but not connected
|
||||||
// else turn the status LED off
|
// else turn the status LED off
|
||||||
|
#if defined(STATUSLED)
|
||||||
void WLED::handleStatusLED()
|
void WLED::handleStatusLED()
|
||||||
{
|
{
|
||||||
#if defined(STATUSLED)
|
|
||||||
uint32_t c = 0;
|
uint32_t c = 0;
|
||||||
|
|
||||||
#if STATUSLED>=0
|
#if STATUSLED>=0
|
||||||
@ -957,5 +963,5 @@ void WLED::handleStatusLED()
|
|||||||
busses.setStatusPixel(0);
|
busses.setStatusPixel(0);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// version code in format yymmddb (b = daily build)
|
// version code in format yymmddb (b = daily build)
|
||||||
#define VERSION 2310180
|
#define VERSION 2310300
|
||||||
|
|
||||||
//uncomment this if you have a "my_config.h" file you'd like to use
|
//uncomment this if you have a "my_config.h" file you'd like to use
|
||||||
//#define WLED_USE_MY_CONFIG
|
//#define WLED_USE_MY_CONFIG
|
||||||
@ -864,8 +864,12 @@ public:
|
|||||||
void initAP(bool resetAP = false);
|
void initAP(bool resetAP = false);
|
||||||
void initConnection();
|
void initConnection();
|
||||||
void initInterfaces();
|
void initInterfaces();
|
||||||
|
#if defined(STATUSLED)
|
||||||
void handleStatusLED();
|
void handleStatusLED();
|
||||||
|
#endif
|
||||||
|
#if WLED_WATCHDOG_TIMEOUT > 0
|
||||||
void enableWatchdog();
|
void enableWatchdog();
|
||||||
void disableWatchdog();
|
void disableWatchdog();
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
#endif // WLED_H
|
#endif // WLED_H
|
||||||
|
@ -308,10 +308,13 @@ void initServer()
|
|||||||
if (!correctPIN || otaLock) return;
|
if (!correctPIN || otaLock) return;
|
||||||
if(!index){
|
if(!index){
|
||||||
DEBUG_PRINTLN(F("OTA Update Start"));
|
DEBUG_PRINTLN(F("OTA Update Start"));
|
||||||
|
#if WLED_WATCHDOG_TIMEOUT > 0
|
||||||
WLED::instance().disableWatchdog();
|
WLED::instance().disableWatchdog();
|
||||||
|
#endif
|
||||||
usermods.onUpdateBegin(true); // notify usermods that update is about to begin (some may require task de-init)
|
usermods.onUpdateBegin(true); // notify usermods that update is about to begin (some may require task de-init)
|
||||||
lastEditTime = millis(); // make sure PIN does not lock during update
|
lastEditTime = millis(); // make sure PIN does not lock during update
|
||||||
#ifdef ESP8266
|
#ifdef ESP8266
|
||||||
|
strip.purgeSegments(true); // free as much memory as you can
|
||||||
Update.runAsync(true);
|
Update.runAsync(true);
|
||||||
#endif
|
#endif
|
||||||
Update.begin((ESP.getFreeSketchSpace() - 0x1000) & 0xFFFFF000);
|
Update.begin((ESP.getFreeSketchSpace() - 0x1000) & 0xFFFFF000);
|
||||||
@ -323,7 +326,9 @@ void initServer()
|
|||||||
} else {
|
} else {
|
||||||
DEBUG_PRINTLN(F("Update Failed"));
|
DEBUG_PRINTLN(F("Update Failed"));
|
||||||
usermods.onUpdateBegin(false); // notify usermods that update has failed (some may require task init)
|
usermods.onUpdateBegin(false); // notify usermods that update has failed (some may require task init)
|
||||||
|
#if WLED_WATCHDOG_TIMEOUT > 0
|
||||||
WLED::instance().enableWatchdog();
|
WLED::instance().enableWatchdog();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -164,39 +164,39 @@ bool sendLiveLedsWs(uint32_t wsClient)
|
|||||||
const size_t MAX_LIVE_LEDS_WS = 1024U;
|
const size_t MAX_LIVE_LEDS_WS = 1024U;
|
||||||
#endif
|
#endif
|
||||||
size_t n = ((used -1)/MAX_LIVE_LEDS_WS) +1; //only serve every n'th LED if count over MAX_LIVE_LEDS_WS
|
size_t n = ((used -1)/MAX_LIVE_LEDS_WS) +1; //only serve every n'th LED if count over MAX_LIVE_LEDS_WS
|
||||||
size_t pos = (strip.isMatrix ? 4 : 2); // start of data
|
size_t pos = 2; // start of data
|
||||||
|
#ifndef WLED_DISABLE_2D
|
||||||
|
if (strip.isMatrix) {
|
||||||
|
// ignore anything behid matrix (i.e. extra strip)
|
||||||
|
used = Segment::maxWidth*Segment::maxHeight; // always the size of matrix (more or less than strip.getLengthTotal())
|
||||||
|
n = 1;
|
||||||
|
if (used > MAX_LIVE_LEDS_WS) n = 2;
|
||||||
|
if (used > MAX_LIVE_LEDS_WS*4) n = 4;
|
||||||
|
pos = 4;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
size_t bufSize = pos + (used/n)*3;
|
size_t bufSize = pos + (used/n)*3;
|
||||||
|
|
||||||
AsyncWebSocketMessageBuffer * wsBuf = ws.makeBuffer(bufSize);
|
AsyncWebSocketMessageBuffer * wsBuf = ws.makeBuffer(bufSize);
|
||||||
if (!wsBuf) return false; //out of memory
|
if (!wsBuf) return false; //out of memory
|
||||||
uint8_t* buffer = wsBuf->get();
|
uint8_t* buffer = wsBuf->get();
|
||||||
|
if (!buffer) return false; //out of memory
|
||||||
|
wsBuf->lock(); // protect buffer from being cleaned by another WS instance
|
||||||
buffer[0] = 'L';
|
buffer[0] = 'L';
|
||||||
buffer[1] = 1; //version
|
buffer[1] = 1; //version
|
||||||
|
|
||||||
#ifndef WLED_DISABLE_2D
|
#ifndef WLED_DISABLE_2D
|
||||||
size_t skipLines = 0;
|
|
||||||
if (strip.isMatrix) {
|
if (strip.isMatrix) {
|
||||||
buffer[1] = 2; //version
|
buffer[1] = 2; //version
|
||||||
buffer[2] = Segment::maxWidth;
|
buffer[2] = Segment::maxWidth/n;
|
||||||
buffer[3] = Segment::maxHeight;
|
buffer[3] = Segment::maxHeight/n;
|
||||||
if (used > MAX_LIVE_LEDS_WS*4) {
|
|
||||||
buffer[2] = Segment::maxWidth/4;
|
|
||||||
buffer[3] = Segment::maxHeight/4;
|
|
||||||
skipLines = 3;
|
|
||||||
} else if (used > MAX_LIVE_LEDS_WS) {
|
|
||||||
buffer[2] = Segment::maxWidth/2;
|
|
||||||
buffer[3] = Segment::maxHeight/2;
|
|
||||||
skipLines = 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
for (size_t i = 0; pos < bufSize -2; i += n)
|
for (size_t i = 0; pos < bufSize -2; i += n)
|
||||||
{
|
{
|
||||||
#ifndef WLED_DISABLE_2D
|
#ifndef WLED_DISABLE_2D
|
||||||
if (strip.isMatrix && skipLines) {
|
if (strip.isMatrix && n>1 && (i/Segment::maxWidth)%n) i += Segment::maxWidth * (n-1);
|
||||||
if ((i/Segment::maxWidth)%(skipLines+1)) i += Segment::maxWidth * skipLines;
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
uint32_t c = strip.getPixelColor(i);
|
uint32_t c = strip.getPixelColor(i);
|
||||||
uint8_t r = R(c);
|
uint8_t r = R(c);
|
||||||
@ -209,6 +209,8 @@ bool sendLiveLedsWs(uint32_t wsClient)
|
|||||||
}
|
}
|
||||||
|
|
||||||
wsc->binary(wsBuf);
|
wsc->binary(wsBuf);
|
||||||
|
wsBuf->unlock(); // un-protect buffer
|
||||||
|
ws._cleanBuffers();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user