diff --git a/src/DirectoryNode.cpp b/src/DirectoryNode.cpp index c8817c4..e1f66b8 100644 --- a/src/DirectoryNode.cpp +++ b/src/DirectoryNode.cpp @@ -572,6 +572,10 @@ DirectoryNode *DirectoryNode::findPreviousMP3Globally(const String ¤tGloba void DirectoryNode::buildFlatMP3List(std::vector> &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> 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; diff --git a/src/main.cpp b/src/main.cpp index f44a12c..7a62270 100644 --- a/src/main.cpp +++ b/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")); } diff --git a/src/main.h b/src/main.h index ecaad5e..63dbadd 100644 --- a/src/main.h +++ b/src/main.h @@ -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 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; diff --git a/web/index.html b/web/index.html index 5731476..9c2642f 100644 --- a/web/index.html +++ b/web/index.html @@ -121,8 +121,8 @@