[ai] random mode
This commit is contained in:
parent
626657a976
commit
d0c9a7e482
|
|
@ -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”.
|
||||
|
||||
|
|
|
|||
38
src/main.cpp
38
src/main.cpp
|
|
@ -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;
|
||||
|
|
|
|||
10
src/main.h
10
src/main.h
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
Loading…
Reference in New Issue