hannabox/src/DirectoryNode.cpp

276 lines
6.7 KiB
C++

#include "DirectoryNode.h"
DirectoryNode::DirectoryNode(const String &nodeName)
: name(nodeName), currentPlaying(nullptr) {}
DirectoryNode::~DirectoryNode()
{
for (DirectoryNode *childNode : subdirectories)
{
delete childNode;
}
}
const String &DirectoryNode::getName() const
{
return name;
}
const std::vector<DirectoryNode *> &DirectoryNode::getSubdirectories() const
{
return subdirectories;
}
const std::vector<String> &DirectoryNode::getMP3Files() const
{
return mp3Files;
}
void DirectoryNode::setCurrentPlaying(const String *mp3File)
{
currentPlaying = mp3File;
}
const String *DirectoryNode::getCurrentPlaying() const
{
return currentPlaying;
}
void DirectoryNode::addSubdirectory(DirectoryNode *subdirectory)
{
subdirectories.push_back(subdirectory);
}
void DirectoryNode::addMP3File(const String &mp3File)
{
mp3Files.push_back(mp3File);
}
void DirectoryNode::setSecondsPlayed(const uint32_t seconds) {
secondsPlayed = seconds;
}
uint32_t DirectoryNode::getSecondsPlayed() {
return secondsPlayed;
}
void DirectoryNode::buildDirectoryTree(const char *currentPath)
{
File rootDir = SD.open(currentPath);
while (true)
{
File entry = rootDir.openNextFile();
if (!entry)
{
break;
}
if (entry.isDirectory() && strcmp(entry.name(),sys_dir.c_str()))
{
DirectoryNode *newNode = new DirectoryNode(entry.name());
subdirectories.push_back(newNode);
newNode->buildDirectoryTree((String(currentPath) + entry.name()).c_str());
}
else if (String(entry.name()).endsWith(".mp3"))
{
mp3Files.push_back(entry.name());
}
entry.close();
}
rootDir.close();
}
void DirectoryNode::printDirectoryTree(int level) const
{
for (int i = 0; i < level; i++)
{
Serial.print(" ");
}
Serial.println(name);
for (const String &mp3File : mp3Files)
{
for (int i = 0; i <= level; i++)
{
Serial.print(" ");
}
Serial.println(mp3File);
}
for (DirectoryNode *childNode : subdirectories)
{
childNode->printDirectoryTree(level + 1);
}
}
DirectoryNode *DirectoryNode::findFirstDirectoryWithMP3s()
{
if (!mp3Files.empty())
{
// Found a directory with MP3 files
return this;
}
for (DirectoryNode *subdirectory : subdirectories)
{
DirectoryNode *result = subdirectory->findFirstDirectoryWithMP3s();
if (result != nullptr)
{
// Found a directory with MP3 files in the subdirectories
return result;
}
}
// No directory with MP3 files found
return nullptr;
}
void DirectoryNode::advanceToFirstMP3InThisNode() {
if (mp3Files.size()>0) {
currentPlaying = &mp3Files[0];
}
}
DirectoryNode* DirectoryNode::advanceToMP3(const String* currentGlobal) {
for (auto subdir : subdirectories)
{
if (subdir->getName()==*currentGlobal) {
subdir->advanceToFirstMP3InThisNode();
return subdir;
}
// Have each subdirectory advance its song
for (size_t i = 0; i < subdir->mp3Files.size(); i++)
{
if (*currentGlobal == subdir->mp3Files[i])
{
// Found the current MP3 file
if (i < subdir->mp3Files.size() - 1)
{
subdir->currentPlaying = &subdir->mp3Files[i];
return subdir;
}
}
}
}
// If we get here, there were no MP3 files or subdirectories left to check
currentPlaying = nullptr;
Serial.println("no more nodes found");
return this;
}
DirectoryNode* DirectoryNode::advanceToNextMP3(const String* currentGlobal)
{
bool useFirst = false;
Serial.println(currentGlobal->c_str());
if (currentGlobal != nullptr)
{
for (size_t i = 0; i < mp3Files.size(); i++)
{
if (*currentGlobal == mp3Files[i])
{
// Found the current playing MP3 file
if (i < mp3Files.size() - 1)
{
// Advance to the next MP3 file in the same directory
currentPlaying = &mp3Files[i + 1];
return this;
}
useFirst = true;
// Reached the end of the MP3 files in the directory
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)
{
Serial.println("searching next node");
if (useFirst && subdir->mp3Files.size()>0) {
subdir->currentPlaying = &subdir->mp3Files[0];
return subdir;
}
// Have each subdirectory advance its song
for (size_t i = 0; i < subdir->mp3Files.size(); i++)
{
if (*currentGlobal == subdir->mp3Files[i])
{
// Found the current playing MP3 file
if (i < subdir->mp3Files.size() - 1)
{
// Advance to the next MP3 file in the same directory
subdir->currentPlaying = &subdir->mp3Files[i + 1];
return subdir;
} else {
useFirst = true;
}
// Reached the end of the MP3 files in the directory
break;
}
}
}
// If we get here, there were no MP3 files or subdirectories left to check
currentPlaying = nullptr;
Serial.println("no more nodes found");
return this;
}
String DirectoryNode::getDirectoryStructureHTML() const
{
String html;
html.reserve(1024); // Reserve memory for better performance
if (name=="/") {
html += "<ul>\n";
}
if (name!="/") {
html += "<li><b>" + name + "</b></li>\n";
}
for (const String &mp3File : mp3Files)
{
html += "<li>" + mp3File + "</li>\n";
}
for (DirectoryNode *childNode : subdirectories)
{
html += childNode->getDirectoryStructureHTML();
}
if (name=="/") {
html += "</ul>\n";
}
return html;
}
void DirectoryNode::appendIndentation(String &html, int level) const
{
for (int i = 0; i < level; i++)
{
html += " ";
}
}
String DirectoryNode::getCurrentPlayingFilePath() const
{
if (currentPlaying != nullptr)
{
String filePath = "/" + name;
if (!filePath.endsWith("/"))
{
filePath += "/";
}
filePath += *currentPlaying;
return filePath;
}
return "";
}