[ai] random mode

This commit is contained in:
Stefan Ostermann 2025-10-05 18:10:50 +02:00
parent 626657a976
commit d0c9a7e482
4 changed files with 43 additions and 7 deletions

View File

@ -133,6 +133,7 @@ Option A: Map through the web app (recommended)
5) Choose Mode:
- Single (s): Play just the selected song/file once.
- Folder (f): Play all files in the selected folder once, then stop.
- Random (r): Play all files in the selected folder in random order once, then stop.
- Continuous (c): Loop through the selected folder continuously.
6) Click “Update Mapping”.

View File

@ -14,6 +14,9 @@
#include <SD.h>
#include <MFRC522.h> //RFID Reader
#include <map>
#if defined(ESP32)
#include <esp_system.h>
#endif
// define pins for RFID
#define CS_RFID 32 // SIC, tried 4 and 32 but only this worked!
@ -127,6 +130,7 @@ uint16_t voltage_threshold_counter = 0;
size_t free_heap = 0;
// webrequest_blockings is a simple watchdog counter that tracks how long at least one HTTP request has been “active” (not yet disconnected) according to the AsyncWebServer.
int webrequest_blockings = 0;
void activateSD()
@ -534,8 +538,8 @@ void playSongByRFID(String id)
targetIsFolder = true;
}
// If the mapping targets a folder (or explicitly 'f' mode), activate folder tracking
if (targetIsFolder || entry.mode == 'f')
// If the mapping targets a folder (or explicitly 'f' or 'r' mode), activate folder tracking
if (targetIsFolder || entry.mode == 'f' || entry.mode == 'r')
{
folderModeActive = true;
folderRootNode = currentNode;
@ -543,6 +547,19 @@ void playSongByRFID(String id)
folderFlatList.clear();
folderRootNode->buildFlatMP3List(folderFlatList);
// If random-folder mode requested, shuffle the flat list once
if (entry.mode == 'r' && folderFlatList.size() > 1)
{
// Fisher-Yates shuffle using Arduino random()
for (int i = (int)folderFlatList.size() - 1; i > 0; --i)
{
int j = (int)random((long)(i + 1)); // 0..i
auto tmp = folderFlatList[i];
folderFlatList[i] = folderFlatList[j];
folderFlatList[j] = tmp;
}
}
// Find index of current playing file within the folder list
for (size_t i = 0; i < folderFlatList.size(); i++)
{
@ -554,6 +571,14 @@ void playSongByRFID(String id)
break;
}
}
// If random mode, make sure the current file is at the start so next advance is random
if (entry.mode == 'r' && folderFlatIndex > 0 && folderFlatIndex < (int)folderFlatList.size())
{
auto tmp = folderFlatList[0];
folderFlatList[0] = folderFlatList[folderFlatIndex];
folderFlatList[folderFlatIndex] = tmp;
folderFlatIndex = 0;
}
// Compute root path for safety checks (path up to last '/')
int lastSlash = mp3File.lastIndexOf('/');
@ -1337,6 +1362,13 @@ void setup()
activateSD();
Serial.println("SD initialization done.");
// Seed RNG for shuffle mode
#if defined(ESP32)
randomSeed(esp_random());
#else
randomSeed((uint32_t)micros());
#endif
// Load configuration from SD card
Serial.println("Loading configuration...");
loadConfig();
@ -1503,7 +1535,7 @@ const String getSysDir(const String filename)
void loop()
{
if (webreq_cnt > 0 && webrequest_blockings > 5000) {
if (webreq_cnt > 0 && webrequest_blockings > 10000) {
Serial.println("excessive webrequest blocking!");
webreq_cnt = 0;
webrequest_blockings = 0;

View File

@ -84,10 +84,12 @@ boolean prepareSleepMode = false;
class DirectoryNode;
// Mapping entry that stores target (file or folder) and playback mode:
// 's' = single (default) - play only the selected song (or single file in folder)
// 'f' = folder - play files inside the selected folder, then stop
// 'c' = continuous - continuously play (like previous continuousMode)
/* Mapping entry that stores target (file or folder) and playback mode:
* 's' = single (default) - play only the selected song (or single file in folder)
* 'f' = folder - play files inside the selected folder, then stop
* 'r' = random-folder - play files inside the selected folder in random order, then stop
* 'c' = continuous - continuously play (like previous continuousMode)
*/
struct MappingEntry {
String target;
char mode;

View File

@ -120,6 +120,7 @@
<select id="mode" name="mode">
<option value="s">Single (play selected song / file)</option>
<option value="f">Folder (play selected folder, then stop)</option>
<option value="r">Random (randomize order in folder, then stop)</option>
<option value="c">Continuous (continuous playback / loop folder)</option>
</select>
</div>