folder play / next song fixes
This commit is contained in:
parent
69bc259a6c
commit
6ecb54e5ee
|
|
@ -572,6 +572,10 @@ DirectoryNode *DirectoryNode::findPreviousMP3Globally(const String ¤tGloba
|
|||
|
||||
void DirectoryNode::buildFlatMP3List(std::vector<std::pair<DirectoryNode *, int>> &allMP3s)
|
||||
{
|
||||
|
||||
#ifdef DEBUG
|
||||
Serial.println("Building flat mp3 list for folder");
|
||||
#endif
|
||||
// Pre-reserve to reduce reallocations
|
||||
allMP3s.reserve(allMP3s.size() + mp3Files.size());
|
||||
// Add all MP3 files from this directory
|
||||
|
|
@ -594,64 +598,56 @@ size_t DirectoryNode::getNumOfFiles() const
|
|||
|
||||
DirectoryNode *DirectoryNode::advanceToNextMP3(const String ¤tGlobal)
|
||||
{
|
||||
bool useFirst = false;
|
||||
Serial.println(currentGlobal.c_str());
|
||||
|
||||
// Build a flat list of all MP3 files in order to correctly find the next one across directories
|
||||
std::vector<std::pair<DirectoryNode *, int>> allMP3s;
|
||||
buildFlatMP3List(allMP3s);
|
||||
|
||||
if (allMP3s.empty())
|
||||
{
|
||||
Serial.println(F("advanceToNextMP3: No MP3s found in tree"));
|
||||
currentPlaying = "";
|
||||
return this;
|
||||
}
|
||||
|
||||
int currentIndex = -1;
|
||||
if (!currentGlobal.isEmpty())
|
||||
{
|
||||
for (size_t i = 0; i < mp3Files.size(); i++)
|
||||
for (size_t i = 0; i < allMP3s.size(); i++)
|
||||
{
|
||||
buildFullPath(mp3Files[i], buffer, buffer_size);
|
||||
if (currentGlobal == String(buffer))
|
||||
DirectoryNode *node = allMP3s[i].first;
|
||||
int fileIndex = allMP3s[i].second;
|
||||
|
||||
node->buildFullPath(node->mp3Files[fileIndex], buffer, buffer_size);
|
||||
if (comparePathWithString(buffer, currentGlobal))
|
||||
{
|
||||
// Found the current playing MP3 file
|
||||
if (i < mp3Files.size() - 1)
|
||||
{
|
||||
// Advance to the next MP3 file in the same directory
|
||||
setCurrentPlaying(mp3Files[i + 1]);
|
||||
return this;
|
||||
}
|
||||
useFirst = true;
|
||||
// Reached the end of the MP3 files in the directory
|
||||
currentIndex = (int)i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We are either not playing, or we've exhausted all the MP3 files in this directory.
|
||||
// Therefore, we need to recursively look in our subdirectories.
|
||||
for (auto subdir : subdirectories)
|
||||
// If current song found and not the last one, move to next
|
||||
if (currentIndex >= 0 && currentIndex < (int)allMP3s.size() - 1)
|
||||
{
|
||||
|
||||
if (useFirst && subdir->mp3Files.size() > 0)
|
||||
{
|
||||
subdir->setCurrentPlaying(subdir->mp3Files[0]);
|
||||
return subdir;
|
||||
}
|
||||
|
||||
// Have each subdirectory advance its song
|
||||
for (size_t i = 0; i < subdir->mp3Files.size(); i++)
|
||||
{
|
||||
subdir->buildFullPath(subdir->mp3Files[i], buffer, buffer_size);
|
||||
if (currentGlobal == String(buffer))
|
||||
{
|
||||
// Found the current playing MP3 file
|
||||
if (i < subdir->mp3Files.size() - 1)
|
||||
{
|
||||
// Advance to the next MP3 file in the same directory
|
||||
subdir->setCurrentPlaying(subdir->mp3Files[i + 1]);
|
||||
return subdir;
|
||||
}
|
||||
else
|
||||
{
|
||||
useFirst = true;
|
||||
}
|
||||
// Reached the end of the MP3 files in the directory
|
||||
break;
|
||||
}
|
||||
}
|
||||
DirectoryNode *nextNode = allMP3s[currentIndex + 1].first;
|
||||
int nextFileIndex = allMP3s[currentIndex + 1].second;
|
||||
|
||||
nextNode->setCurrentPlaying(nextNode->mp3Files[nextFileIndex]);
|
||||
return nextNode;
|
||||
}
|
||||
|
||||
// If not playing anything (start), play first
|
||||
if (currentIndex == -1 && currentGlobal.isEmpty())
|
||||
{
|
||||
DirectoryNode *nextNode = allMP3s[0].first;
|
||||
int nextFileIndex = allMP3s[0].second;
|
||||
nextNode->setCurrentPlaying(nextNode->mp3Files[nextFileIndex]);
|
||||
return nextNode;
|
||||
}
|
||||
|
||||
// If we get here, there were no MP3 files or subdirectories left to check
|
||||
// If we get here, either we are at the last song, or the current song was not found
|
||||
currentPlaying = "";
|
||||
Serial.println(F("no more nodes found"));
|
||||
return this;
|
||||
|
|
|
|||
49
src/main.cpp
49
src/main.cpp
|
|
@ -492,16 +492,18 @@ void playSongByRFID(const String &id)
|
|||
else
|
||||
{
|
||||
// Find index of current playing file within the folder list
|
||||
uint16_t targetId = currentNode->getCurrentPlayingId();
|
||||
for (size_t i = 0; i < folderFlatList.size(); i++)
|
||||
{
|
||||
DirectoryNode *node = folderFlatList[i].first;
|
||||
int fileIdx = folderFlatList[i].second;
|
||||
if (node->getCurrentPlaying() == mp3File)
|
||||
if (node == currentNode && node->getFileIdAt(fileIdx) == targetId)
|
||||
{
|
||||
folderFlatIndex = (int)i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
Serial.print(F("RFID Folder Index: ")); Serial.println(folderFlatIndex);
|
||||
}
|
||||
|
||||
// Compute root path for safety checks (path up to last '/')
|
||||
|
|
@ -1124,10 +1126,26 @@ void previous()
|
|||
void audio_eof_mp3(const char *info)
|
||||
{
|
||||
Serial.println(F("audio file ended."));
|
||||
if (prepareSleepMode)
|
||||
|
||||
#ifdef DEBUG
|
||||
if (folderModeActive)
|
||||
Serial.println("folder mode active");
|
||||
#endif
|
||||
|
||||
if (prepareSleepMode)
|
||||
return;
|
||||
|
||||
// If folder-mode is active, advance only inside that folder.
|
||||
if (folderModeActive)
|
||||
{
|
||||
if (folderRootNode == nullptr) {
|
||||
#ifdef DEBUG
|
||||
Serial.println(F("DEBUG: folderRootNode was null, fixing..."));
|
||||
#endif
|
||||
folderRootNode = currentNode;
|
||||
}
|
||||
}
|
||||
|
||||
if (folderModeActive && folderRootNode != nullptr)
|
||||
{
|
||||
// Ensure flat list is built
|
||||
|
|
@ -1135,16 +1153,24 @@ void audio_eof_mp3(const char *info)
|
|||
folderRootNode->buildFlatMP3List(folderFlatList);
|
||||
|
||||
// Try to find current index if not set
|
||||
if (folderFlatIndex < 0)
|
||||
if (folderFlatIndex < 0 && currentNode != nullptr)
|
||||
{
|
||||
String cur = currentNode ? currentNode->getCurrentPlaying() : String();
|
||||
uint16_t currentId = currentNode->getCurrentPlayingId();
|
||||
Serial.print(F("EOF: Searching for ID ")); Serial.println(currentId);
|
||||
for (size_t i = 0; i < folderFlatList.size(); i++)
|
||||
{
|
||||
if (folderFlatList[i].first->getCurrentPlaying() == cur)
|
||||
if (folderFlatList[i].first == currentNode &&
|
||||
folderFlatList[i].first->getFileIdAt(folderFlatList[i].second) == currentId)
|
||||
{
|
||||
folderFlatIndex = (int)i;
|
||||
#ifdef DEBUG
|
||||
Serial.print(F("EOF: Found at ")); Serial.println(folderFlatIndex);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (folderFlatIndex < 0) {
|
||||
Serial.println(F("EOF: ID not found in flat list"));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1270,9 +1296,10 @@ static void serveStaticFile(AsyncWebServerRequest *request,
|
|||
if (ctx->f) ctx->f.close();
|
||||
sd_lock_release();
|
||||
delete ctx;
|
||||
webreq_exit();
|
||||
|
||||
});
|
||||
request->send(resp);
|
||||
webreq_exit();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -1535,8 +1562,7 @@ void setup()
|
|||
|
||||
AsyncWiFiManager wifiManager(&server, &dns);
|
||||
|
||||
// Memory optimizations for WiFiManager
|
||||
wifiManager.setDebugOutput(false); // Disable debug strings
|
||||
wifiManager.setDebugOutput(true);
|
||||
|
||||
// Reduce timeouts to free memory faster
|
||||
wifiManager.setTimeout(180); // Reduced from 180
|
||||
|
|
@ -1548,8 +1574,6 @@ void setup()
|
|||
#endif
|
||||
WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0); // disable brownout detector
|
||||
|
||||
// wifiManager.resetSettings();
|
||||
|
||||
if (wifiManager.autoConnect("HannaBox"))
|
||||
{
|
||||
Serial.printf("Heap before init_webserver: %u\n", (unsigned)xPortGetFreeHeapSize());
|
||||
|
|
@ -1585,6 +1609,7 @@ void id_song_action(AsyncWebServerRequest *request)
|
|||
webreq_enter();
|
||||
request->onDisconnect([](){ webreq_exit(); });
|
||||
int params = request->params();
|
||||
folderModeActive = true;
|
||||
for (int i = 0; i < params; i++)
|
||||
{
|
||||
const AsyncWebParameter *p = request->getParam(i);
|
||||
|
|
@ -1593,6 +1618,10 @@ void id_song_action(AsyncWebServerRequest *request)
|
|||
playSongById(atoi(p->value().c_str()));
|
||||
}
|
||||
}
|
||||
if (currentNode != nullptr)
|
||||
{
|
||||
folderRootNode = currentNode;
|
||||
}
|
||||
lastInteraction = millis();
|
||||
request->send_P(200, txt_plain, PSTR("ok"));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -139,7 +139,7 @@ static inline void sd_lock_acquire()
|
|||
}
|
||||
|
||||
static inline void sd_lock_release()
|
||||
{
|
||||
{
|
||||
__sync_lock_release(&sd_lock_flag);
|
||||
}
|
||||
|
||||
|
|
@ -212,7 +212,7 @@ std::map<String, MappingEntry> rfid_map;
|
|||
|
||||
// Folder-play helper: when a mapping requests "folder only" playback we keep
|
||||
// track of the folder root node so EOF handling can advance only inside that folder.
|
||||
bool folderModeActive = false;
|
||||
bool folderModeActive = true;
|
||||
|
||||
bool pendingSeek = false;
|
||||
uint32_t pendingSeekSeconds = 0;
|
||||
|
|
|
|||
|
|
@ -121,8 +121,8 @@
|
|||
<div>
|
||||
<label for="mode">Mode:</label>
|
||||
<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="s">Single (play selected song / file)</option>
|
||||
<option value="r">Random (randomize order in folder, then stop)</option>
|
||||
<option value="c">Continuous (continuous playback / loop folder)</option>
|
||||
</select>
|
||||
|
|
|
|||
Loading…
Reference in New Issue