276 lines
6.7 KiB
C++
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 "";
|
|
}
|