Skip to content

Commit a1c2c04

Browse files
committed
Playlist handling.
1 parent 94941a7 commit a1c2c04

File tree

2 files changed

+82
-24
lines changed

2 files changed

+82
-24
lines changed

wled00/json.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -279,7 +279,7 @@ bool deserializeState(JsonObject root)
279279

280280
JsonObject playlist = root[F("playlist")];
281281
if (!playlist.isNull()) {
282-
loadPlaylist(playlist); return stateResponse;
282+
loadPlaylist(playlist); //return stateResponse;
283283
}
284284

285285
colorUpdated(noNotification ? NOTIFIER_CALL_MODE_NO_NOTIFY : NOTIFIER_CALL_MODE_DIRECT_CHANGE);

wled00/playlist.cpp

Lines changed: 81 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -10,19 +10,73 @@ typedef struct PlaylistEntry {
1010
uint16_t tr;
1111
} ple;
1212

13-
byte playlistRepeat = 1;
14-
byte playlistEndPreset = 0;
13+
int8_t playlistRepeat = 1;
14+
byte playlistEndPreset = 0;
15+
byte *playlistEntries = nullptr;
16+
byte playlistLen;
17+
int8_t playlistIndex = -1;
18+
uint16_t playlistEntryDur = 0;
1519

16-
uint8_t* playlistEntries;
1720

18-
byte playlistLen;
19-
int8_t playlistIndex = -1;
21+
void shufflePlaylist() {
22+
int currentIndex = playlistLen, randomIndex;
23+
24+
PlaylistEntry temporaryValue, *entries = reinterpret_cast<PlaylistEntry*>(playlistEntries);
25+
26+
// While there remain elements to shuffle...
27+
while (currentIndex--) {
28+
// Pick a random element...
29+
randomIndex = random(0, currentIndex);
30+
// And swap it with the current element.
31+
temporaryValue = entries[currentIndex];
32+
entries[currentIndex] = entries[randomIndex];
33+
entries[randomIndex] = temporaryValue;
34+
}
35+
}
36+
37+
/*
38+
* The same thing as saving and loading playlist can be achieved using JSON API saved in a preset.
39+
*
40+
void deserializePlaylist() {
41+
DynamicJsonDocument doc(JSON_BUFFER_SIZE);
42+
43+
DEBUG_PRINTLN(F("Reading playlist from /playlist.json..."));
44+
45+
if (!readObjectFromFile("/playlist.json", nullptr, &doc)) return; //if file does not exist just exit
46+
47+
JsonObject playlist = doc[F("playlist")];
48+
if (!playlist.isNull()) loadPlaylist(playlist);
49+
}
2050
21-
uint16_t playlistEntryDur = 0;
51+
52+
void serializePlaylist() {
53+
DynamicJsonDocument doc(JSON_BUFFER_SIZE/8); // we don't need big buffer (>1k is ok)
54+
55+
DEBUG_PRINTLN(F("Writing playlist to /playlist.json..."));
56+
57+
PlaylistEntry* entries = reinterpret_cast<PlaylistEntry*>(playlistEntries);
58+
59+
JsonObject playlist = doc.createNestedObject(F("playlist"));
60+
JsonArray ps = playlist.createNestedArray(F("ps"));
61+
JsonArray dur = playlist.createNestedArray(F("dur"));
62+
JsonArray tr = playlist.createNestedArray(F("transition"));
63+
for (uint8_t i=0; i<playlistLen; i++) {
64+
ps.add(entries[i].preset);
65+
dur.add(entries[i].dur);
66+
tr.add(entries[i].tr);
67+
}
68+
playlist[F("repeat")] = playlistRepeat; // TODO: this one is decreasing with each loop
69+
playlist[F("end")] = playlistEndPreset;
70+
71+
File f = WLED_FS.open("/playlist.json", "w");
72+
if (f) serializeJson(doc, f);
73+
f.close();
74+
}
75+
*/
2276

2377
void loadPlaylist(JsonObject playlistObj) {
24-
delete playlistEntries;
25-
playlistIndex = -1; playlistEntryDur = 0;
78+
if (playlistEntries != nullptr) {delete[] playlistEntries; playlistEntries = nullptr;}
79+
currentPlaylist = playlistIndex = -1; playlistEntryDur = 0;
2680
JsonArray presets = playlistObj["ps"];
2781
playlistLen = presets.size();
2882
if (playlistLen == 0) return;
@@ -72,26 +126,30 @@ void loadPlaylist(JsonObject playlistObj) {
72126
currentPlaylist = 0; //TODO here we need the preset ID where the playlist is saved
73127
}
74128

75-
void handlePlaylist()
76-
{
129+
130+
void handlePlaylist() {
77131
if (currentPlaylist < 0 || playlistEntries == nullptr || presetCyclingEnabled) return;
78132

79-
if (millis() - presetCycledTime > (100*playlistEntryDur))
80-
{
133+
if (millis() - presetCycledTime > (100*playlistEntryDur)) {
81134
presetCycledTime = millis();
82135
if (bri == 0 || nightlightActive) return;
83136

84-
playlistIndex++;
85-
if (playlistIndex >= playlistLen) {
86-
playlistIndex = 0;
87-
if (playlistRepeat == 1) { //stop
88-
currentPlaylist = -1;
89-
delete playlistEntries;
90-
playlistEntries = nullptr;
91-
if (playlistEndPreset) applyPreset(playlistEndPreset);
92-
return;
137+
++playlistIndex %= playlistLen; // -1 at 1st run (limit to playlistLen)
138+
139+
if (!playlistRepeat && !playlistIndex) { //stop if repeat == 0 and restart of playlist
140+
currentPlaylist = -1;
141+
delete[] playlistEntries;
142+
playlistEntries = nullptr;
143+
if (playlistEndPreset) applyPreset(playlistEndPreset);
144+
return;
145+
}
146+
// playlist roll-over
147+
if (!playlistIndex) {
148+
if (playlistRepeat > 0) {// playlistRepeat < 0 => endless loop with shuffling presets
149+
playlistRepeat--; // decrease repeat count on each index reset
150+
} else {
151+
shufflePlaylist(); // shuffle playlist and start over
93152
}
94-
if (playlistRepeat > 1) playlistRepeat--;
95153
}
96154

97155
PlaylistEntry* entries = reinterpret_cast<PlaylistEntry*>(playlistEntries);
@@ -103,4 +161,4 @@ void handlePlaylist()
103161
playlistEntryDur = entries[playlistIndex].dur;
104162
if (playlistEntryDur == 0) playlistEntryDur = 10;
105163
}
106-
}
164+
}

0 commit comments

Comments
 (0)