Skip to content

Commit d291d44

Browse files
committed
Fix for wled#5703
- also remove delayed file close - handle presets and playlists even in realtime mode
1 parent 04a0e1c commit d291d44

6 files changed

Lines changed: 33 additions & 58 deletions

File tree

wled00/fcn_declare.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ bool presetNeedsSaving();
159159
void initPresetsFile();
160160
void handlePresets();
161161
bool applyPreset(byte index, byte callMode = CALL_MODE_DIRECT_CHANGE);
162-
bool applyPresetFromPlaylist(byte index);
162+
bool doApplyPreset(uint8_t index, uint8_t callMode);
163163
void applyPresetWithFallback(uint8_t presetID, uint8_t callMode, uint8_t effectID = 0, uint8_t paletteID = 0);
164164
inline bool applyTemporaryPreset() {return applyPreset(255);};
165165
void savePreset(byte index, const char* pname = nullptr, JsonObject saveobj = JsonObject());

wled00/file.cpp

Lines changed: 8 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -42,17 +42,6 @@ static volatile size_t knownLargestSpace = MAX_SPACE;
4242

4343
static File f; // don't export to other cpp files
4444

45-
//wrapper to find out how long closing takes
46-
void closeFile() {
47-
#ifdef WLED_DEBUG_FS
48-
DEBUGFS_PRINT(F("Close -> "));
49-
uint32_t s = millis();
50-
#endif
51-
f.close();
52-
DEBUGFS_PRINTF("took %lu ms\n", millis() - s);
53-
doCloseFile = false;
54-
}
55-
5645
//find() that reads and buffers data from file stream in 256-byte blocks.
5746
//Significantly faster, f.find(key) can take SECONDS for multi-kB files
5847
static bool bufferedFind(const char *target, bool fromStart = true) {
@@ -186,7 +175,7 @@ static void writeSpace(size_t l)
186175
if (knownLargestSpace < l) knownLargestSpace = l;
187176
}
188177

189-
static bool appendObjectToFile(const char* key, const JsonDocument* content, uint32_t s, uint32_t contentLen = 0)
178+
static bool appendObjectToFileAndClose(const char* key, const JsonDocument* content, uint32_t s, uint32_t contentLen = 0)
190179
{
191180
#ifdef WLED_DEBUG_FS
192181
DEBUGFS_PRINTLN(F("Append"));
@@ -198,7 +187,7 @@ static bool appendObjectToFile(const char* key, const JsonDocument* content, uin
198187
if (f.size() < 3) f.print(F("{\"0\":{}}"));
199188

200189
if (content->isNull()) {
201-
doCloseFile = true;
190+
f.close();
202191
return true; //nothing to append
203192
}
204193

@@ -210,7 +199,7 @@ static bool appendObjectToFile(const char* key, const JsonDocument* content, uin
210199
f.print(key);
211200
serializeJson(*content, f);
212201
DEBUGFS_PRINTF("Inserted, took %lu ms (total %lu)", millis() - s1, millis() - s);
213-
doCloseFile = true;
202+
f.close();
214203
return true;
215204
}
216205

@@ -221,7 +210,7 @@ static bool appendObjectToFile(const char* key, const JsonDocument* content, uin
221210

222211
if (f.size() + 9000 > (fsBytesTotal - fsBytesUsed)) { //make sure there is enough space to at least copy the file once
223212
errorFlag = ERR_FS_QUOTA;
224-
doCloseFile = true;
213+
f.close();
225214
return false;
226215
}
227216

@@ -255,8 +244,7 @@ static bool appendObjectToFile(const char* key, const JsonDocument* content, uin
255244
//Append object
256245
serializeJson(*content, f);
257246
f.write('}');
258-
259-
doCloseFile = true;
247+
f.close();
260248
DEBUGFS_PRINTF("Appended, took %lu ms (total %lu)", millis() - s1, millis() - s);
261249
return true;
262250
}
@@ -270,8 +258,6 @@ bool writeObjectToFileUsingId(const char* file, uint16_t id, const JsonDocument*
270258

271259
bool writeObjectToFile(const char* file, const char* key, const JsonDocument* content)
272260
{
273-
if (doCloseFile) closeFile();
274-
275261
uint32_t s = 0; //timing
276262
#ifdef WLED_DEBUG_FS
277263
DEBUGFS_PRINTF("Write to %s with key %s >>>\n", file, (key==nullptr)?"nullptr":key);
@@ -289,7 +275,7 @@ bool writeObjectToFile(const char* file, const char* key, const JsonDocument* co
289275

290276
if (!bufferedFind(key)) //key does not exist in file
291277
{
292-
return appendObjectToFile(key, content, s);
278+
return appendObjectToFileAndClose(key, content, s);
293279
}
294280

295281
//an object with this key already exists, replace or delete it
@@ -325,10 +311,10 @@ bool writeObjectToFile(const char* file, const char* key, const JsonDocument* co
325311
if (pos > 3) pos--; //also delete leading comma if not first object
326312
f.seek(pos);
327313
writeSpace(pos2 - pos);
328-
if (contentLen) return appendObjectToFile(key, content, s, contentLen);
314+
if (contentLen) return appendObjectToFileAndClose(key, content, s, contentLen);
329315
}
330316

331-
doCloseFile = true;
317+
f.close();
332318
DEBUGFS_PRINTF("Replaced/deleted, took %lu ms\n", millis() - s);
333319
return true;
334320
}
@@ -343,7 +329,6 @@ bool readObjectFromFileUsingId(const char* file, uint16_t id, JsonDocument* dest
343329
//if the key is a nullptr, deserialize entire object
344330
bool readObjectFromFile(const char* file, const char* key, JsonDocument* dest, const JsonDocument* filter)
345331
{
346-
if (doCloseFile) closeFile();
347332
#ifdef WLED_DEBUG_FS
348333
DEBUGFS_PRINTF("Read from %s with key %s >>>\n", file, (key==nullptr)?"nullptr":key);
349334
uint32_t s = millis();

wled00/playlist.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -153,9 +153,9 @@ void handlePlaylist() {
153153
if (playlistRepeat == 1) { //stop if all repetitions are done
154154
unloadPlaylist();
155155
if (parentPlaylistPresetId > 0) {
156-
applyPresetFromPlaylist(parentPlaylistPresetId); // reload previous playlist (unfortunately asynchronous)
156+
doApplyPreset(parentPlaylistPresetId, CALL_MODE_DIRECT_CHANGE); // reload previous playlist
157157
parentPlaylistPresetId = 0; // reset previous playlist but do not reset Index or Repeat (they will be loaded & reset in loadPlaylist())
158-
} else if (playlistEndPreset) applyPresetFromPlaylist(playlistEndPreset);
158+
} else if (playlistEndPreset) doApplyPreset(playlistEndPreset, CALL_MODE_DIRECT_CHANGE);
159159
return;
160160
}
161161
if (playlistRepeat > 1) playlistRepeat--; // decrease repeat count on each index reset if not an endless playlist
@@ -166,7 +166,7 @@ void handlePlaylist() {
166166
jsonTransitionOnce = true;
167167
strip.setTransition(playlistEntries[playlistIndex].tr * 100);
168168
playlistEntryDur = playlistEntries[playlistIndex].dur > 0 ? playlistEntries[playlistIndex].dur : UINT16_MAX;
169-
applyPresetFromPlaylist(playlistEntries[playlistIndex].preset);
169+
doApplyPreset(playlistEntries[playlistIndex].preset, CALL_MODE_DIRECT_CHANGE);
170170
doAdvancePlaylist = false;
171171
}
172172
}

wled00/presets.cpp

Lines changed: 16 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -120,17 +120,8 @@ void initPresetsFile()
120120
f.close();
121121
}
122122

123-
bool applyPresetFromPlaylist(byte index)
124-
{
125-
DEBUG_PRINTF_P(PSTR("Request to apply preset: %d\n"), index);
126-
presetToApply = index;
127-
callModeToApply = CALL_MODE_DIRECT_CHANGE;
128-
return true;
129-
}
130-
131123
bool applyPreset(byte index, byte callMode)
132124
{
133-
unloadPlaylist(); // applying a preset unloads the playlist (#3827)
134125
DEBUG_PRINTF_P(PSTR("Request to apply preset: %u\n"), index);
135126
presetToApply = index;
136127
callModeToApply = callMode;
@@ -149,22 +140,24 @@ void applyPresetWithFallback(uint8_t index, uint8_t callMode, uint8_t effectID,
149140
void handlePresets()
150141
{
151142
// handlePreset() is called from loop(), so there is no need to suspend strip
152-
byte presetErrFlag = ERR_NONE;
153143
if (presetToSave) {
154144
doSaveState();
155-
return;
145+
} else {
146+
if (presetToApply) { // preset waiting to apply
147+
if (doApplyPreset(presetToApply, callModeToApply)) {
148+
presetToApply = 0; //clear request for preset
149+
callModeToApply = CALL_MODE_INIT;
150+
}
151+
}
156152
}
153+
}
157154

158-
if (presetToApply == 0 || !requestJSONBufferLock(9)) return; // no preset waiting to apply, or JSON buffer is already allocated, return to loop until free
155+
bool doApplyPreset(uint8_t tmpPreset, uint8_t tmpMode)
156+
{
157+
if (!requestJSONBufferLock(9)) return false; // JSON buffer is already allocated
159158

160159
bool changePreset = false;
161-
uint8_t tmpPreset = presetToApply; // store temporary since deserializeState() may call applyPreset()
162-
uint8_t tmpMode = callModeToApply;
163-
164-
JsonObject fdo;
165-
166-
presetToApply = 0; //clear request for preset
167-
callModeToApply = CALL_MODE_INIT;
160+
byte presetErrFlag = ERR_NONE;
168161

169162
DEBUG_PRINTF_P(PSTR("Applying preset: %u\n"), (unsigned)tmpPreset);
170163

@@ -181,19 +174,21 @@ void handlePresets()
181174
{
182175
presetErrFlag = readObjectFromFileUsingId(getPresetsFileName(tmpPreset < 255), tmpPreset, pDoc) ? ERR_NONE : ERR_FS_PLOAD;
183176
}
184-
fdo = pDoc->as<JsonObject>();
177+
JsonObject fdo = pDoc->as<JsonObject>();
185178

186179
// only reset errorflag if previous error was preset-related
187180
if ((errorFlag == ERR_NONE) || (errorFlag == ERR_FS_PLOAD)) errorFlag = presetErrFlag;
188181

189182
//HTTP API commands
190183
const char* httpwin = fdo["win"];
191184
if (httpwin) {
185+
if (currentPlaylist && fdo["win"].as<String>().indexOf(F("NP")) < 0) unloadPlaylist(); // #5703
192186
String apireq = "win"; apireq += '&'; // reduce RAM string usage
193187
apireq += httpwin;
194188
handleSet(nullptr, apireq, false); // may call applyPreset() via PL=
195189
setValuesFromFirstSelectedSeg(); // fills legacy values
196190
} else {
191+
if (currentPlaylist && fdo[F("np")].isNull()) unloadPlaylist(); // applying a preset unloads the playlist (#3827 & #5703)
197192
// remove load request for presets to prevent recursive crash, except if:
198193
// - called by button preset which contains preset cycling string "1~5~"
199194
// - or boot preset (i.e. with preset chaining like {"lor":2,"udpn":{"send":true},"MultiRelay":{"relay":1,"on":true},"ps":"1~5r"})
@@ -216,6 +211,7 @@ void handlePresets()
216211
#endif
217212

218213
releaseJSONBufferLock();
214+
return true;
219215
}
220216

221217
//called from handleSet(PS=) [network callback (sObj is empty)], IR (irrational) [loop context] and deserializeState() [network callback]

wled00/wled.cpp

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -94,10 +94,12 @@ void WLED::loop()
9494
//handle still pending interface update
9595
updateInterfaces(interfaceUpdateCallMode);
9696

97-
if (doCloseFile) {
98-
closeFile();
97+
if (!presetNeedsSaving()) {
98+
handlePlaylist();
9999
yield();
100100
}
101+
handlePresets();
102+
yield();
101103

102104
#if defined(WLED_DEBUG) && defined(WLED_DEBUG_STATS)
103105
stripMillis = millis();
@@ -117,13 +119,6 @@ void WLED::loop()
117119
yield();
118120
#endif
119121

120-
if (!presetNeedsSaving()) {
121-
handlePlaylist();
122-
yield();
123-
}
124-
handlePresets();
125-
yield();
126-
127122
if (!offMode || strip.isOffRefreshRequired() || strip.needsUpdate())
128123
strip.service();
129124
else {

wled00/wled.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
// version code in format yymmddb (b = daily build)
1111
#ifndef AUTOBUILD
12-
#define VERSION 2606020
12+
#define VERSION 2606270
1313
#else
1414
#define VERSION BUILD
1515
#endif
@@ -687,7 +687,6 @@ WLED_GLOBAL Toki toki _INIT(Toki());
687687
WLED_GLOBAL size_t fsBytesUsed _INIT(0);
688688
WLED_GLOBAL size_t fsBytesTotal _INIT(0);
689689
WLED_GLOBAL unsigned long presetsModifiedTime _INIT(0L);
690-
WLED_GLOBAL bool doCloseFile _INIT(false);
691690

692691
// presets
693692
WLED_GLOBAL byte currentPreset _INIT(0);

0 commit comments

Comments
 (0)