[ai] further memory optimizations

This commit is contained in:
2025-11-02 21:27:21 +01:00
parent 3a34b1b8d0
commit fd40b663a0
6 changed files with 187 additions and 76 deletions

View File

@@ -37,12 +37,42 @@ const std::vector<String> &DirectoryNode::getMP3Files() const
return mp3Files;
}
const String &DirectoryNode::getDirPath() const
{
return dirPath;
}
String DirectoryNode::getFullPathByIndex(size_t index) const
{
if (index < mp3Files.size())
{
return buildFullPath(mp3Files[index]);
}
return String();
}
String DirectoryNode::buildFullPath(const String &fileName) const
{
if (dirPath == "/")
{
String p = "/";
p += fileName;
return p;
}
String p = dirPath;
p += "/";
p += fileName;
return p;
}
void DirectoryNode::setCurrentPlaying(const String &mp3File)
{
currentPlaying = mp3File;
bool isAbs = (mp3File.length() > 0) && (mp3File.charAt(0) == '/');
const String &fileName = isAbs ? mp3File.substring(mp3File.lastIndexOf('/') + 1) : mp3File;
currentPlaying = isAbs ? mp3File : buildFullPath(fileName);
for (size_t i = 0; i < mp3Files.size(); i++)
{
if (mp3Files[i] == mp3File && ids.size() > i)
if (mp3Files[i] == fileName && ids.size() > i)
{
currentPlayingId = ids[i];
break;
@@ -102,6 +132,14 @@ void DirectoryNode::buildDirectoryTree(const char *currentPath)
mp3Files.shrink_to_fit();
ids.shrink_to_fit();
// Set directory path for this node (normalize: keep "/" or remove trailing slash)
String path = String(currentPath);
if (path.length() > 1 && path.endsWith("/"))
{
path.remove(path.length() - 1);
}
dirPath = path;
// First collect entries so we can sort them alphabetically
std::vector<String> dirNames;
std::vector<String> fileNames;
@@ -167,15 +205,10 @@ void DirectoryNode::buildDirectoryTree(const char *currentPath)
newNode->buildDirectoryTree(childPath.c_str());
}
// Add MP3 files in alphabetical order
// Add MP3 files in alphabetical order (store only filenames; build full paths on demand)
for (const String &fileName : fileNames)
{
String fullPath = String(currentPath);
if (!fullPath.endsWith("/"))
fullPath += "/";
fullPath += fileName;
mp3Files.push_back(std::move(fullPath));
mp3Files.push_back(fileName);
ids.push_back(getNextId());
}
}
@@ -194,7 +227,7 @@ void DirectoryNode::printDirectoryTree(int level) const
{
Serial.print(F(" "));
}
Serial.println(mp3File);
Serial.println(buildFullPath(mp3File));
}
for (DirectoryNode *childNode : subdirectories)
@@ -241,7 +274,7 @@ DirectoryNode *DirectoryNode::advanceToMP3(const uint16_t id)
if (id == ids[i])
{
// Found the current MP3 file
currentPlaying = mp3Files[i];
currentPlaying = buildFullPath(mp3Files[i]);
currentPlayingId = id;
return this;
}
@@ -296,7 +329,7 @@ DirectoryNode *DirectoryNode::advanceToMP3(const String &songName)
{
if (isAbsolutePath)
{
if (mp3Files[i].equalsIgnoreCase(songName))
if (buildFullPath(mp3Files[i]).equalsIgnoreCase(songName))
{
setCurrentPlaying(mp3Files[i]);
return this;
@@ -317,13 +350,10 @@ DirectoryNode *DirectoryNode::advanceToMP3(const String &songName)
// Then search in subdirectories
for (auto subdir : subdirectories)
{
// Absolute folder target: match directory by its full path derived from its files
if (isAbsolutePath && subdir->mp3Files.size() > 0)
// Absolute folder target: match directory by its full path (dirPath)
if (isAbsolutePath)
{
String anyFile = subdir->mp3Files[0];
int lastSlash = anyFile.lastIndexOf('/');
String subdirPath = (lastSlash >= 0) ? anyFile.substring(0, lastSlash) : String();
if (subdirPath.equalsIgnoreCase(normalizedPath))
if (subdir->getDirPath().equalsIgnoreCase(normalizedPath))
{
subdir->advanceToFirstMP3InThisNode();
return subdir;
@@ -342,7 +372,7 @@ DirectoryNode *DirectoryNode::advanceToMP3(const String &songName)
if (isAbsolutePath)
{
if (subdir->mp3Files[i].equalsIgnoreCase(songName))
if (subdir->buildFullPath(subdir->mp3Files[i]).equalsIgnoreCase(songName))
{
subdir->setCurrentPlaying(subdir->mp3Files[i]);
return subdir;
@@ -401,7 +431,7 @@ DirectoryNode *DirectoryNode::goToPreviousMP3(uint32_t thresholdSeconds)
int currentIndex = -1;
for (size_t i = 0; i < mp3Files.size(); i++)
{
if (currentPlaying == mp3Files[i])
if (currentPlaying == buildFullPath(mp3Files[i]))
{
currentIndex = i;
break;
@@ -412,7 +442,7 @@ DirectoryNode *DirectoryNode::goToPreviousMP3(uint32_t thresholdSeconds)
if (currentIndex > 0)
{
Serial.print(F("goToPreviousMP3: Moving to previous song in same directory: "));
Serial.println(mp3Files[currentIndex - 1]);
Serial.println(buildFullPath(mp3Files[currentIndex - 1]));
setCurrentPlaying(mp3Files[currentIndex - 1]);
return this;
}
@@ -441,7 +471,7 @@ DirectoryNode *DirectoryNode::findPreviousMP3Globally(const String &currentGloba
{
DirectoryNode *node = allMP3s[i].first;
int fileIndex = allMP3s[i].second;
if (node->mp3Files[fileIndex] == currentGlobal)
if (node->buildFullPath(node->mp3Files[fileIndex]) == currentGlobal)
{
currentGlobalIndex = i;
break;
@@ -455,7 +485,7 @@ DirectoryNode *DirectoryNode::findPreviousMP3Globally(const String &currentGloba
int prevFileIndex = allMP3s[currentGlobalIndex - 1].second;
Serial.print(F("findPreviousMP3Globally: Moving to previous song globally: "));
Serial.println(prevNode->mp3Files[prevFileIndex]);
Serial.println(prevNode->buildFullPath(prevNode->mp3Files[prevFileIndex]));
prevNode->setCurrentPlaying(prevNode->mp3Files[prevFileIndex]);
return prevNode;
@@ -495,7 +525,7 @@ DirectoryNode *DirectoryNode::advanceToNextMP3(const String &currentGlobal)
{
for (size_t i = 0; i < mp3Files.size(); i++)
{
if (currentGlobal == mp3Files[i])
if (currentGlobal == buildFullPath(mp3Files[i]))
{
// Found the current playing MP3 file
if (i < mp3Files.size() - 1)
@@ -525,7 +555,7 @@ DirectoryNode *DirectoryNode::advanceToNextMP3(const String &currentGlobal)
// Have each subdirectory advance its song
for (size_t i = 0; i < subdir->mp3Files.size(); i++)
{
if (currentGlobal == subdir->mp3Files[i])
if (currentGlobal == subdir->buildFullPath(subdir->mp3Files[i]))
{
// Found the current playing MP3 file
if (i < subdir->mp3Files.size() - 1)
@@ -573,10 +603,10 @@ void DirectoryNode::streamDirectoryHTML(Print &out) const {
out.print(F("<li data-id=\""));
out.print(ids[i]);
out.print(F("\">"));
out.print(mp3Files[i]);
out.print(buildFullPath(mp3Files[i]));
out.println(F("</li>"));
#ifdef DEBUG
Serial.printf("stream song: %s\n",mp3Files[i].c_str());
Serial.printf("stream song: %s\n", buildFullPath(mp3Files[i]).c_str());
#endif
// Yield every few items to allow the async web server to send buffered data
if (i % 5 == 4) {