From 33701636afdc4a270819d5f04e4ddab616a2e29b Mon Sep 17 00:00:00 2001 From: Stefan Ostermann Date: Sun, 5 Oct 2025 18:26:15 +0200 Subject: [PATCH] [ai] random mode now really working --- src/DirectoryNode.cpp | 58 ++++++++++++++++++++++++++++++++++++------- src/main.cpp | 42 ++++++++++++++++++++----------- 2 files changed, 77 insertions(+), 23 deletions(-) diff --git a/src/DirectoryNode.cpp b/src/DirectoryNode.cpp index 8bb28fe..730e3fa 100644 --- a/src/DirectoryNode.cpp +++ b/src/DirectoryNode.cpp @@ -270,29 +270,58 @@ DirectoryNode *DirectoryNode::advanceToMP3(const String *songName) // Check if the input is an absolute path (starts with '/') or just a filename bool isAbsolutePath = songName->startsWith("/"); + // Normalize trailing slash for absolute folder path targets + String normalizedPath = *songName; + if (isAbsolutePath && normalizedPath.length() > 1 && normalizedPath.endsWith("/")) + { + normalizedPath.remove(normalizedPath.length() - 1); + } + // Lowercased copies for case-insensitive comparisons (FAT can uppercase names) + String lowTarget = *songName; + lowTarget.toLowerCase(); + String lowNormPath = normalizedPath; + lowNormPath.toLowerCase(); // First, search in the current directory's MP3 files for (size_t i = 0; i < mp3Files.size(); i++) { if (isAbsolutePath) { - if (*songName == mp3Files[i]) + if (mp3Files[i].equalsIgnoreCase(*songName)) { setCurrentPlaying(&mp3Files[i]); return this; } } - else if (mp3Files[i].endsWith(*songName)) + else { - setCurrentPlaying(&mp3Files[i]); - return this; + String f = mp3Files[i]; + f.toLowerCase(); + if (f.endsWith(lowTarget)) + { + setCurrentPlaying(&mp3Files[i]); + return this; + } } } // Then search in subdirectories for (auto subdir : subdirectories) { - if (!isAbsolutePath && subdir->getName() == *songName) + // Absolute folder target: match directory by its full path derived from its files + if (isAbsolutePath && subdir->mp3Files.size() > 0) + { + String anyFile = subdir->mp3Files[0]; + int lastSlash = anyFile.lastIndexOf('/'); + String subdirPath = (lastSlash >= 0) ? anyFile.substring(0, lastSlash) : String(); + if (subdirPath.equalsIgnoreCase(normalizedPath)) + { + subdir->advanceToFirstMP3InThisNode(); + return subdir; + } + } + + if (!isAbsolutePath && subdir->getName().equalsIgnoreCase(*songName)) { subdir->advanceToFirstMP3InThisNode(); return subdir; @@ -304,18 +333,29 @@ DirectoryNode *DirectoryNode::advanceToMP3(const String *songName) if (isAbsolutePath) { - if (*songName == subdir->mp3Files[i]) + if (subdir->mp3Files[i].equalsIgnoreCase(*songName)) { subdir->setCurrentPlaying(&subdir->mp3Files[i]); return subdir; } } - else if (subdir->mp3Files[i].endsWith(*songName)) + else { - subdir->setCurrentPlaying(&subdir->mp3Files[i]); - return subdir; + String f = subdir->mp3Files[i]; + f.toLowerCase(); + if (f.endsWith(lowTarget)) + { + subdir->setCurrentPlaying(&subdir->mp3Files[i]); + return subdir; + } } } + // Recurse into deeper subdirectories to support nested folders and files + DirectoryNode* deeper = subdir->advanceToMP3(songName); + if (deeper != nullptr) + { + return deeper; + } } // If we get here, no matching song was found diff --git a/src/main.cpp b/src/main.cpp index 109cdb6..9939c8f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -560,24 +560,38 @@ void playSongByRFID(String id) } } - // Find index of current playing file within the folder list - for (size_t i = 0; i < folderFlatList.size(); i++) + if (entry.mode == 'r' && !folderFlatList.empty()) { - DirectoryNode *node = folderFlatList[i].first; - int fileIdx = folderFlatList[i].second; - if (node->getCurrentPlayingFilePath() == mp3File) + // In random mode, pick a random start index and move it to front + int startIdx = (int)random((long)folderFlatList.size()); + if (startIdx != 0) { - folderFlatIndex = (int)i; - break; + auto tmp = folderFlatList[0]; + folderFlatList[0] = folderFlatList[startIdx]; + folderFlatList[startIdx] = tmp; } - } - // 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; + DirectoryNode *startNode = folderFlatList[0].first; + int fileIdx = folderFlatList[0].second; + Serial.print("Shuffle start: "); + Serial.println(startNode->getMP3Files()[fileIdx]); + startNode->setCurrentPlaying(&startNode->getMP3Files()[fileIdx]); + currentNode = startNode; + mp3File = currentNode->getCurrentPlayingFilePath(); + } + else + { + // Find index of current playing file within the folder list + for (size_t i = 0; i < folderFlatList.size(); i++) + { + DirectoryNode *node = folderFlatList[i].first; + int fileIdx = folderFlatList[i].second; + if (node->getCurrentPlayingFilePath() == mp3File) + { + folderFlatIndex = (int)i; + break; + } + } } // Compute root path for safety checks (path up to last '/')