diff --git a/usermods/audioreactive/audio_reactive.h b/usermods/audioreactive/audio_reactive.h
index 6f94415f..b6983c6d 100644
--- a/usermods/audioreactive/audio_reactive.h
+++ b/usermods/audioreactive/audio_reactive.h
@@ -2834,18 +2834,19 @@ class AudioReactive : public Usermod {
void appendConfigData()
{
- oappend(SET_F("ux='AudioReactive';")); // fingers crossed that "ux" isn't already used as JS var, html post parameter or css style
+ oappend(SET_F("ux='AudioReactive';")); // ux = shortcut for Audioreactive - fingers crossed that "ux" isn't already used as JS var, html post parameter or css style
+ oappend(SET_F("uxp=ux+':digitalmic:pin[]';")); // uxp = shortcut for AudioReactive:digitalmic:pin[]
oappend(SET_F("addInfo(ux+':help',0,'');"));
#ifdef ARDUINO_ARCH_ESP32
//WLEDMM: add defaults
#if !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32S3) // -S3/-S2/-C3 don't support analog audio
#ifdef AUDIOPIN
- oappend(SET_F("xOpt('AudioReactive:analogmic:pin',1,' ⎌',")); oappendi(AUDIOPIN); oappend(");");
+ oappend(SET_F("xOpt(ux+':analogmic:pin',1,' ⎌',")); oappendi(AUDIOPIN); oappend(");");
#endif
- oappend(SET_F("aOpt('AudioReactive:analogmic:pin',1);")); //only analog options
+ oappend(SET_F("aOpt(ux+':analogmic:pin',1);")); //only analog options
#endif
- oappend(SET_F("dd=addDropdown('AudioReactive','digitalmic:type');"));
+ oappend(SET_F("dd=addDropdown(ux,'digitalmic:type');"));
#if !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32S3)
#if SR_DMTYPE==0
oappend(SET_F("addOption(dd,'Generic Analog (⎌)',0);"));
@@ -2896,34 +2897,34 @@ class AudioReactive : public Usermod {
oappend(SET_F("addOption(dd,'WM8978 ☾',7);"));
#endif
#ifdef SR_SQUELCH
- oappend(SET_F("addInfo('AudioReactive:config:squelch',1,'⎌ ")); oappendi(SR_SQUELCH); oappend("');"); // 0 is field type, 1 is actual field
+ oappend(SET_F("addInfo(ux+':config:squelch',1,'⎌ ")); oappendi(SR_SQUELCH); oappend("');"); // 0 is field type, 1 is actual field
#endif
#ifdef SR_GAIN
- oappend(SET_F("addInfo('AudioReactive:config:gain',1,'⎌ ")); oappendi(SR_GAIN); oappend("');"); // 0 is field type, 1 is actual field
+ oappend(SET_F("addInfo(ux+':config:gain',1,'⎌ ")); oappendi(SR_GAIN); oappend("');"); // 0 is field type, 1 is actual field
#endif
- oappend(SET_F("dd=addDropdown('AudioReactive','config:AGC');"));
+ oappend(SET_F("dd=addDropdown(ux,'config:AGC');"));
oappend(SET_F("addOption(dd,'Off',0);"));
oappend(SET_F("addOption(dd,'Normal',1);"));
oappend(SET_F("addOption(dd,'Vivid',2);"));
oappend(SET_F("addOption(dd,'Lazy',3);"));
//WLEDMM: experimental settings
- oappend(SET_F("dd=addDropdown('AudioReactive','experiments:micLev');"));
+ oappend(SET_F("dd=addDropdown(ux,'experiments:micLev');"));
oappend(SET_F("addOption(dd,'Floating (⎌)',0);"));
oappend(SET_F("addOption(dd,'Freeze',1);"));
oappend(SET_F("addOption(dd,'Fast Freeze',2);"));
- oappend(SET_F("addInfo('AudioReactive:experiments:micLev',1,'☾');"));
+ oappend(SET_F("addInfo(ux+':experiments:micLev',1,'☾');"));
- oappend(SET_F("dd=addDropdown('AudioReactive','experiments:freqDist');"));
+ oappend(SET_F("dd=addDropdown(ux,'experiments:freqDist');"));
oappend(SET_F("addOption(dd,'Normal (⎌)',0);"));
oappend(SET_F("addOption(dd,'RightShift',1);"));
- oappend(SET_F("addInfo('AudioReactive:experiments:freqDist',1,'☾');"));
+ oappend(SET_F("addInfo(ux+':experiments:freqDist',1,'☾');"));
- //oappend(SET_F("dd=addDropdown('AudioReactive','experiments:freqRMS');"));
+ //oappend(SET_F("dd=addDropdown(ux,'experiments:freqRMS');"));
//oappend(SET_F("addOption(dd,'Off (⎌)',0);"));
//oappend(SET_F("addOption(dd,'On',1);"));
- //oappend(SET_F("addInfo('AudioReactive:experiments:freqRMS',1,'☾');"));
+ //oappend(SET_F("addInfo(ux+':experiments:freqRMS',1,'☾');"));
#ifdef FFT_USE_SLIDING_WINDOW
oappend(SET_F("dd=addDropdown(ux,'experiments:I2S_FastPath');"));
@@ -2932,21 +2933,21 @@ class AudioReactive : public Usermod {
oappend(SET_F("addInfo(ux+':experiments:I2S_FastPath',1,'☾');"));
#endif
- oappend(SET_F("dd=addDropdown('AudioReactive','dynamics:limiter');"));
+ oappend(SET_F("dd=addDropdown(ux,'dynamics:limiter');"));
oappend(SET_F("addOption(dd,'Off',0);"));
oappend(SET_F("addOption(dd,'On',1);"));
- oappend(SET_F("addInfo('AudioReactive:dynamics:limiter',0,' On ');")); // 0 is field type, 1 is actual field
- oappend(SET_F("addInfo('AudioReactive:dynamics:rise',1,'ms (♪ effects only)');"));
- oappend(SET_F("addInfo('AudioReactive:dynamics:fall',1,'ms (♪ effects only)');"));
+ oappend(SET_F("addInfo(ux+':dynamics:limiter',0,' On ');")); // 0 is field type, 1 is actual field
+ oappend(SET_F("addInfo(ux+':dynamics:rise',1,'ms (♪ effects only)');"));
+ oappend(SET_F("addInfo(ux+':dynamics:fall',1,'ms (♪ effects only)');"));
- oappend(SET_F("dd=addDropdown('AudioReactive','frequency:scale');"));
+ oappend(SET_F("dd=addDropdown(ux,'frequency:scale');"));
oappend(SET_F("addOption(dd,'None',0);"));
oappend(SET_F("addOption(dd,'Linear (Amplitude)',2);"));
oappend(SET_F("addOption(dd,'Square Root (Energy)',3);"));
oappend(SET_F("addOption(dd,'Logarithmic (Loudness)',1);"));
//WLEDMM add defaults
- oappend(SET_F("dd=addDropdown('AudioReactive','frequency:profile');"));
+ oappend(SET_F("dd=addDropdown(ux,'frequency:profile');"));
#if SR_FREQ_PROF==0
oappend(SET_F("addOption(dd,'Generic Microphone (⎌)',0);"));
#else
@@ -3002,9 +3003,9 @@ class AudioReactive : public Usermod {
#else
oappend(SET_F("addOption(dd,'userdefined #2',9);"));
#endif
- oappend(SET_F("addInfo('AudioReactive:frequency:profile',1,'☾');"));
+ oappend(SET_F("addInfo(ux+':frequency:profile',1,'☾');"));
#endif
- oappend(SET_F("dd=addDropdown('AudioReactive','sync:mode');"));
+ oappend(SET_F("dd=addDropdown(ux,'sync:mode');"));
oappend(SET_F("addOption(dd,'Off',0);")); // AUDIOSYNC_NONE
#ifdef ARDUINO_ARCH_ESP32
oappend(SET_F("addOption(dd,'Send',1);")); // AUDIOSYNC_SEND
@@ -3014,53 +3015,53 @@ class AudioReactive : public Usermod {
oappend(SET_F("addOption(dd,'Receive or Local',6);")); // AUDIOSYNC_REC_PLUS
#endif
// check_sequence: Receiver skips out-of-sequence packets when enabled
- oappend(SET_F("dd=addDropdown('AudioReactive','sync:check_sequence');"));
+ oappend(SET_F("dd=addDropdown(ux,'sync:check_sequence');"));
oappend(SET_F("addOption(dd,'Off',0);"));
oappend(SET_F("addOption(dd,'On',1);"));
- oappend(SET_F("addInfo('AudioReactive:sync:check_sequence',1,'when receiving ☾
Sync audio data with other WLEDs');")); // must append this to the last field of 'sync'
+ oappend(SET_F("addInfo(ux+':sync:check_sequence',1,'when receiving ☾
Sync audio data with other WLEDs');")); // must append this to the last field of 'sync'
- oappend(SET_F("addInfo('AudioReactive:digitalmic:type',1,'requires reboot!');")); // 0 is field type, 1 is actual field
+ oappend(SET_F("addInfo(ux+':digitalmic:type',1,'requires reboot!');")); // 0 is field type, 1 is actual field
#ifdef ARDUINO_ARCH_ESP32
- oappend(SET_F("addInfo('AudioReactive:digitalmic:pin[]',0,'sd/data/dout','I2S SD');"));
+ oappend(SET_F("addInfo(uxp,0,'sd/data/dout','I2S SD');"));
#ifdef I2S_SDPIN
- oappend(SET_F("xOpt('AudioReactive:digitalmic:pin[]',0,' ⎌',")); oappendi(I2S_SDPIN); oappend(");");
+ oappend(SET_F("xOpt(uxp,0,' ⎌',")); oappendi(I2S_SDPIN); oappend(");");
#endif
- oappend(SET_F("addInfo('AudioReactive:digitalmic:pin[]',1,'ws/clk/lrck','I2S WS');"));
- oappend(SET_F("dRO('AudioReactive:digitalmic:pin[]',1);")); // disable read only pins
+ oappend(SET_F("addInfo(uxp,1,'ws/clk/lrck','I2S WS');"));
+ oappend(SET_F("dRO(uxp,1);")); // disable read only pins
#ifdef I2S_WSPIN
- oappend(SET_F("xOpt('AudioReactive:digitalmic:pin[]',1,' ⎌',")); oappendi(I2S_WSPIN); oappend(");");
+ oappend(SET_F("xOpt(uxp,1,' ⎌',")); oappendi(I2S_WSPIN); oappend(");");
#endif
- oappend(SET_F("addInfo('AudioReactive:digitalmic:pin[]',2,'sck/bclk','I2S SCK');"));
- oappend(SET_F("dRO('AudioReactive:digitalmic:pin[]',2);")); // disable read only pins
+ oappend(SET_F("addInfo(uxp,2,'sck/bclk','I2S SCK');"));
+ oappend(SET_F("dRO(uxp,2);")); // disable read only pins
#ifdef I2S_CKPIN
- oappend(SET_F("xOpt('AudioReactive:digitalmic:pin[]',2,' ⎌',")); oappendi(I2S_CKPIN); oappend(");");
+ oappend(SET_F("xOpt(uxp,2,' ⎌',")); oappendi(I2S_CKPIN); oappend(");");
#endif
- oappend(SET_F("addInfo('AudioReactive:digitalmic:pin[]',3,'master clock','I2S MCLK');"));
- oappend(SET_F("dRO('AudioReactive:digitalmic:pin[]',3);")); // disable read only pins
+ oappend(SET_F("addInfo(uxp,3,'master clock','I2S MCLK');"));
+ oappend(SET_F("dRO(uxp,3);")); // disable read only pins
#if !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32S3)
- oappend(SET_F("dOpt('AudioReactive:digitalmic:pin[]',3,2,2);")); //only use -1, 0, 1 or 3
- oappend(SET_F("dOpt('AudioReactive:digitalmic:pin[]',3,4,39);")); //only use -1, 0, 1 or 3
+ oappend(SET_F("dOpt(uxp,3,2,2);")); //only use -1, 0, 1 or 3
+ oappend(SET_F("dOpt(uxp,3,4,39);")); //only use -1, 0, 1 or 3
#endif
#ifdef MCLK_PIN
- oappend(SET_F("xOpt('AudioReactive:digitalmic:pin[]',3,' ⎌',")); oappendi(MCLK_PIN); oappend(");");
+ oappend(SET_F("xOpt(uxp,3,' ⎌',")); oappendi(MCLK_PIN); oappend(");");
#endif
- oappend(SET_F("addInfo('AudioReactive:digitalmic:pin[]',4,'','I2C SDA');"));
- oappend(SET_F("rOpt('AudioReactive:digitalmic:pin[]',4,'use global (")); oappendi(i2c_sda); oappend(")',-1);");
+ oappend(SET_F("addInfo(uxp,4,'','I2C SDA');"));
+ oappend(SET_F("rOpt(uxp,4,'use global (")); oappendi(i2c_sda); oappend(")',-1);");
#ifdef ES7243_SDAPIN
- oappend(SET_F("xOpt('AudioReactive:digitalmic:pin[]',4,' ⎌',")); oappendi(ES7243_SDAPIN); oappend(");");
+ oappend(SET_F("xOpt(uxp,4,' ⎌',")); oappendi(ES7243_SDAPIN); oappend(");");
#endif
- oappend(SET_F("addInfo('AudioReactive:digitalmic:pin[]',5,'','I2C SCL');"));
- oappend(SET_F("rOpt('AudioReactive:digitalmic:pin[]',5,'use global (")); oappendi(i2c_scl); oappend(")',-1);");
+ oappend(SET_F("addInfo(uxp,5,'','I2C SCL');"));
+ oappend(SET_F("rOpt(uxp,5,'use global (")); oappendi(i2c_scl); oappend(")',-1);");
#ifdef ES7243_SCLPIN
- oappend(SET_F("xOpt('AudioReactive:digitalmic:pin[]',5,' ⎌',")); oappendi(ES7243_SCLPIN); oappend(");");
+ oappend(SET_F("xOpt(uxp,5,' ⎌',")); oappendi(ES7243_SCLPIN); oappend(");");
#endif
- oappend(SET_F("dRO('AudioReactive:digitalmic:pin[]',5);")); // disable read only pins
+ oappend(SET_F("dRO(uxp,5);")); // disable read only pins
#endif
}
diff --git a/wled00/data/settings_um.htm b/wled00/data/settings_um.htm
index 759643e6..19a8590f 100644
--- a/wled00/data/settings_um.htm
+++ b/wled00/data/settings_um.htm
@@ -146,6 +146,9 @@
urows += `
`;
}
}
+ function adF(k,f,o,a=false) { //shortcut for addField(key, field, (sub)object, isArray)
+ return addField(k,f,o,a);
+ }
// https://stackoverflow.com/questions/39729741/javascript-change-input-text-to-select-option
function addDropdown(um,fld) {
let sel = d.createElement('select');
@@ -170,6 +173,9 @@
}
return null;
}
+ function adD(um,fld) { // shortcut for addDropdown(um,fld)
+ return addDropdown(um,fld);
+ }
function addOption(sel,txt,val) {
if (sel===null) return; // select object missing
let opt = d.createElement("option");
@@ -181,6 +187,9 @@
if (c.value == sel.dataset.val) sel.selectedIndex = i;
}
}
+ function adO(sel,txt,val) { // shortcut for addOption(sel,txt,val)
+ return addOption(sel,txt,val);
+ }
//WLEDMM: replace Option to set globals
function rOpt(name,el,txt,val) {
let obj = d.getElementsByName(name);
@@ -285,6 +294,9 @@
if (txt2!="") obj[el].insertAdjacentHTML('beforebegin', txt2 + ' '); //add pre texts
}
}
+ function adI(name,el,txt, txt2="") { // shortcut for addInfo(name,el,txt, txt2="")
+ return addInfo(name,el,txt, txt2);
+ }
// add Help Button
function addHB(um)
{
diff --git a/wled00/fcn_declare.h b/wled00/fcn_declare.h
index 38a18b09..aa0645d0 100644
--- a/wled00/fcn_declare.h
+++ b/wled00/fcn_declare.h
@@ -362,6 +362,7 @@ int getNumVal(const String* req, uint16_t pos);
void parseNumber(const char* str, byte* val, byte minv=0, byte maxv=255);
bool getVal(JsonVariant elem, byte* val, byte minv=0, byte maxv=255);
bool updateVal(const char* req, const char* key, byte* val, byte minv=0, byte maxv=255);
+void oappendUseDeflate(bool OnOff); // enable / disable string squeezing
bool oappend(const char* txt); // append new c string to temp buffer efficiently
bool oappendi(int i); // append new number to temp buffer efficiently
void sappend(char stype, const char* key, int val);
diff --git a/wled00/util.cpp b/wled00/util.cpp
index 896b57e3..1bcf2ad0 100644
--- a/wled00/util.cpp
+++ b/wled00/util.cpp
@@ -144,22 +144,34 @@ bool oappendi(int i)
return oappend(s);
}
+static bool squeezeStrings = false;
+void oappendUseDeflate(bool OnOff) { squeezeStrings = OnOff; }
bool oappend(const char* txt)
{
- uint16_t len = strlen(txt);
+ String str = squeezeStrings ? String(txt) : String("");
+ if (squeezeStrings) {
+ // simple fixed-dictionary deflate
+ str.replace(F("addField("), F("adF("));
+ str.replace(F("addDropdown("), F("adD("));
+ str.replace(F("addOption("), F("adO("));
+ str.replace(F("addInfo("), F("adI("));
+ }
+ const char* finalTxt = squeezeStrings ? str.c_str() : txt;
+
+ size_t len = strlen(finalTxt);
if ((obuf == nullptr) || (olen + len >= SETTINGS_STACK_BUF_SIZE)) { // sanity checks
if (obuf == nullptr) { USER_PRINTLN(F("oappend() error: obuf == nullptr."));
} else {
USER_PRINT(F("oappend() error: buffer full. Increase SETTINGS_STACK_BUF_SIZE for "));
USER_PRINTF("%2u bytes \t\"", len /*1 + olen + len - SETTINGS_STACK_BUF_SIZE*/);
- USER_PRINT(txt);
+ USER_PRINT(finalTxt);
USER_PRINTLN(F("\""));
errorFlag = ERR_LOW_AJAX_MEM;
}
return false; // buffer full
}
- strcpy(obuf + olen, txt);
+ strcpy(obuf + olen, finalTxt);
olen += len;
return true;
}
diff --git a/wled00/xml.cpp b/wled00/xml.cpp
index 72fdf219..efc5840c 100644
--- a/wled00/xml.cpp
+++ b/wled00/xml.cpp
@@ -792,6 +792,7 @@ void getSettingsJS(AsyncWebServerRequest* request, byte subPage, char* dest) //W
if (subPage == 8) //usermods
{
appendGPIOinfo();
+ oappendUseDeflate(true); // allow replacing long functions with shorter equivalents - only works for usermods
if (!request->hasParam("um") ) {
// oappend(SET_F("numM="));
// oappendi(usermods.getModCount());
@@ -834,6 +835,7 @@ void getSettingsJS(AsyncWebServerRequest* request, byte subPage, char* dest) //W
Usermod *usermod = usermods.lookupName(request->getParam("um")->value().c_str());
if (usermod) usermod->appendConfigData();
}
+ oappendUseDeflate(false);
// oappend(SET_F("console.log('getSettingsJS fix ro pins', d.max_gpio, d.ro_gpio);"));
oappend(SET_F("pinPost();"));