diff --git a/src/DirectoryNode.cpp b/src/DirectoryNode.cpp index 59cbce2..51386d3 100644 --- a/src/DirectoryNode.cpp +++ b/src/DirectoryNode.cpp @@ -262,39 +262,103 @@ DirectoryNode *DirectoryNode::advanceToMP3(const String *currentGlobal) */ DirectoryNode *DirectoryNode::goToPreviousMP3(uint32_t thresholdSeconds) { - if (secondsPlayed > thresholdSeconds || currentPlaying == nullptr) + // Safety check for null pointer + if (currentPlaying == nullptr) { - // Restart the current song if it's been playing for more than thresholdSeconds - // Or if there is no current song (at the start of the list) + Serial.println("goToPreviousMP3: currentPlaying is null"); + return nullptr; + } + + // If we've been playing for more than threshold seconds, restart current song + if (secondsPlayed > thresholdSeconds) + { + Serial.println("goToPreviousMP3: Restarting current song (played > threshold)"); return this; } - else - { - // Find the previous song - for (size_t i = 0; i < mp3Files.size(); i++) - { - if (currentPlaying != nullptr && *currentPlaying == mp3Files[i] && i > 0) - { - // Move to the previous song - setCurrentPlaying(&mp3Files[i - 1]); - return this; - } - } - // If the first song in the directory or no song was playing, move to the previous directory, if any - for (auto subdir : subdirectories) + // Find the current song index in this directory + int currentIndex = -1; + for (size_t i = 0; i < mp3Files.size(); i++) + { + if (*currentPlaying == mp3Files[i]) { - DirectoryNode *previousNode = subdir->goToPreviousMP3(thresholdSeconds); - if (previousNode != nullptr) - { - return previousNode; - } + currentIndex = i; + break; } } - // No previous song available + + // If current song found and not the first song, move to previous + if (currentIndex > 0) + { + Serial.print("goToPreviousMP3: Moving to previous song in same directory: "); + Serial.println(mp3Files[currentIndex - 1]); + setCurrentPlaying(&mp3Files[currentIndex - 1]); + return this; + } + + // If we're at the first song or song not found in current directory, + // we need to find the previous song globally + Serial.println("goToPreviousMP3: At first song or song not found, looking for previous globally"); + return nullptr; // Let the caller handle global previous logic +} + +DirectoryNode *DirectoryNode::findPreviousMP3Globally(const String *currentGlobal) +{ + if (currentGlobal == nullptr) + { + Serial.println("findPreviousMP3Globally: currentGlobal is null"); + return nullptr; + } + + // Build a flat list of all MP3 files in order + std::vector> allMP3s; + buildFlatMP3List(allMP3s); + + // Find current song in the flat list + int currentGlobalIndex = -1; + for (size_t i = 0; i < allMP3s.size(); i++) + { + DirectoryNode* node = allMP3s[i].first; + int fileIndex = allMP3s[i].second; + if (node->mp3Files[fileIndex] == *currentGlobal) + { + currentGlobalIndex = i; + break; + } + } + + // If current song found and not the first globally, move to previous + if (currentGlobalIndex > 0) + { + DirectoryNode* prevNode = allMP3s[currentGlobalIndex - 1].first; + int prevFileIndex = allMP3s[currentGlobalIndex - 1].second; + + Serial.print("findPreviousMP3Globally: Moving to previous song globally: "); + Serial.println(prevNode->mp3Files[prevFileIndex]); + + prevNode->setCurrentPlaying(&prevNode->mp3Files[prevFileIndex]); + return prevNode; + } + + Serial.println("findPreviousMP3Globally: No previous song found globally"); return nullptr; } +void DirectoryNode::buildFlatMP3List(std::vector>& allMP3s) +{ + // Add all MP3 files from this directory + for (size_t i = 0; i < mp3Files.size(); i++) + { + allMP3s.push_back(std::make_pair(this, i)); + } + + // Recursively add MP3 files from subdirectories + for (DirectoryNode* subdir : subdirectories) + { + subdir->buildFlatMP3List(allMP3s); + } +} + DirectoryNode *DirectoryNode::advanceToNextMP3(const String *currentGlobal) { bool useFirst = false; diff --git a/src/DirectoryNode.h b/src/DirectoryNode.h index 39710a7..03fd86a 100644 --- a/src/DirectoryNode.h +++ b/src/DirectoryNode.h @@ -50,6 +50,8 @@ public: DirectoryNode* advanceToMP3(const String* currentGlobal); DirectoryNode* advanceToNextMP3(const String* currentGlobal); DirectoryNode* goToPreviousMP3(uint32_t thresholdSeconds = 3); + DirectoryNode* findPreviousMP3Globally(const String* currentGlobal); + void buildFlatMP3List(std::vector>& allMP3s); DirectoryNode* advanceToMP3(const uint16_t id); void advanceToFirstMP3InThisNode(); String getDirectoryStructureHTML() const; diff --git a/src/main.cpp b/src/main.cpp index e8bda27..1715a99 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -592,33 +592,85 @@ void next() void previous() { - if (currentNode != NULL) { + Serial.println("=== PREVIOUS FUNCTION CALLED ==="); + + if (currentNode == NULL) { + Serial.println("previous(): currentNode is null, cannot go to previous"); + lastInteraction = millis(); + return; + } + + // Validate current state + const String* currentSong = currentNode->getCurrentPlaying(); + if (currentSong == NULL) { + Serial.println("previous(): currentPlaying is null, cannot go to previous"); + lastInteraction = millis(); + return; + } + + Serial.print("previous(): Current song: "); + Serial.println(*currentSong); + + // Use audio library's current time instead of tracked seconds for more accuracy + uint32_t currentAudioTime = audio.getAudioCurrentTime(); + Serial.print("previous(): Current audio time: "); + Serial.print(currentAudioTime); + Serial.println(" seconds"); + + // Try to go to previous within current directory first + DirectoryNode* newNode = currentNode->goToPreviousMP3(2); // Use 2 second threshold + + if (newNode != NULL) { + // Check if we're restarting the same song or moving to a different song + const String* newSong = newNode->getCurrentPlaying(); - const String* curr = currentNode->getCurrentPlaying(); - DirectoryNode* newNode = currentNode->goToPreviousMP3(); + if (newSong != NULL && currentSong == newSong && currentAudioTime > 2) { + // Restart current song if it's been playing for more than 2 seconds + Serial.println("previous(): Restarting current song"); + audio.setAudioPlayPosition(0); + currentNode->setSecondsPlayed(0); + } else if (newSong != NULL && currentSong != newSong) { + // Move to previous song in same directory + Serial.print("previous(): Moving to previous song in directory: "); + Serial.println(*newSong); + currentNode = newNode; + stop(); + deactivateRFID(); + activateSD(); + playFile(currentNode->getCurrentPlayingFilePath().c_str()); + activateRFID(); + deactivateSD(); + } + } else { + // Need to find previous song globally (across directories) + Serial.println("previous(): Looking for previous song globally"); + DirectoryNode* globalPrevNode = rootNode.findPreviousMP3Globally(currentSong); - if (newNode != NULL) { - if (curr == newNode->getCurrentPlaying()) { - // reset to 0 seconds playtime: - audio.setAudioPlayPosition(0); + if (globalPrevNode != NULL) { + const String* globalPrevSong = globalPrevNode->getCurrentPlaying(); + if (globalPrevSong != NULL) { + Serial.print("previous(): Found previous song globally: "); + Serial.println(*globalPrevSong); + currentNode = globalPrevNode; + stop(); + deactivateRFID(); + activateSD(); + playFile(currentNode->getCurrentPlayingFilePath().c_str()); + activateRFID(); + deactivateSD(); } else { - // Update the current node and start playing the previous song - Serial.println(""); - Serial.print("Playing previous song: "); - Serial.println(currentNode->getCurrentPlayingFilePath()); - currentNode = newNode; - stop(); - deactivateRFID(); - activateSD(); - playSongByPath(currentNode->getCurrentPlayingFilePath()); - deactivateSD(); - activateRFID(); + Serial.println("previous(): Global previous song is null"); } - - + } else { + Serial.println("previous(): No previous song found globally - at beginning of playlist"); + // Optionally restart current song or do nothing + audio.setAudioPlayPosition(0); + currentNode->setSecondsPlayed(0); } } - lastInteraction = millis(); + + lastInteraction = millis(); + Serial.println("=== PREVIOUS FUNCTION COMPLETED ==="); } void audio_eof_mp3(const char *info)