[ai] quickwin memory optimiziations, wip
This commit is contained in:
parent
465e34e919
commit
3a34b1b8d0
|
|
@ -37,19 +37,20 @@ const std::vector<String> &DirectoryNode::getMP3Files() const
|
||||||
return mp3Files;
|
return mp3Files;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DirectoryNode::setCurrentPlaying(const String mp3File)
|
void DirectoryNode::setCurrentPlaying(const String &mp3File)
|
||||||
{
|
{
|
||||||
currentPlaying = mp3File;
|
currentPlaying = mp3File;
|
||||||
for (int i = 0; i < mp3Files.size(); i++)
|
for (size_t i = 0; i < mp3Files.size(); i++)
|
||||||
{
|
{
|
||||||
if (mp3Files[i] == mp3File && ids.size() > i)
|
if (mp3Files[i] == mp3File && ids.size() > i)
|
||||||
{
|
{
|
||||||
currentPlayingId = ids[i];
|
currentPlayingId = ids[i];
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const String DirectoryNode::getCurrentPlaying() const
|
const String &DirectoryNode::getCurrentPlaying() const
|
||||||
{
|
{
|
||||||
return currentPlaying;
|
return currentPlaying;
|
||||||
}
|
}
|
||||||
|
|
@ -82,7 +83,7 @@ void DirectoryNode::setSecondsPlayed(const uint32_t seconds)
|
||||||
secondsPlayed = seconds;
|
secondsPlayed = seconds;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t DirectoryNode::getSecondsPlayed()
|
uint32_t DirectoryNode::getSecondsPlayed() const
|
||||||
{
|
{
|
||||||
return secondsPlayed;
|
return secondsPlayed;
|
||||||
}
|
}
|
||||||
|
|
@ -97,6 +98,9 @@ void DirectoryNode::buildDirectoryTree(const char *currentPath)
|
||||||
subdirectories.clear();
|
subdirectories.clear();
|
||||||
mp3Files.clear();
|
mp3Files.clear();
|
||||||
ids.clear();
|
ids.clear();
|
||||||
|
subdirectories.shrink_to_fit();
|
||||||
|
mp3Files.shrink_to_fit();
|
||||||
|
ids.shrink_to_fit();
|
||||||
|
|
||||||
// First collect entries so we can sort them alphabetically
|
// First collect entries so we can sort them alphabetically
|
||||||
std::vector<String> dirNames;
|
std::vector<String> dirNames;
|
||||||
|
|
@ -113,27 +117,33 @@ void DirectoryNode::buildDirectoryTree(const char *currentPath)
|
||||||
|
|
||||||
if (entry.isDirectory() && entry.name()[0] != '.' && strcmp(entry.name(), sys_dir))
|
if (entry.isDirectory() && entry.name()[0] != '.' && strcmp(entry.name(), sys_dir))
|
||||||
{
|
{
|
||||||
dirNames.push_back(String(entry.name()));
|
dirNames.emplace_back(entry.name());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
String entryName = entry.name();
|
String entryName = entry.name();
|
||||||
if (entryName.endsWith(".mp3") || entryName.endsWith(".MP3"))
|
if (entryName.endsWith(".mp3") || entryName.endsWith(".MP3"))
|
||||||
{
|
{
|
||||||
fileNames.push_back(entryName);
|
fileNames.push_back(std::move(entryName));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
entry.close();
|
entry.close();
|
||||||
}
|
}
|
||||||
rootDir.close();
|
rootDir.close();
|
||||||
|
|
||||||
// Case-insensitive alphabetical sort
|
// Case-insensitive alphabetical sort without allocations
|
||||||
auto ciLess = [](const String &a, const String &b) {
|
auto ciLess = [](const String &a, const String &b) {
|
||||||
String al = a;
|
const char* pa = a.c_str();
|
||||||
String bl = b;
|
const char* pb = b.c_str();
|
||||||
al.toLowerCase();
|
while (*pa && *pb) {
|
||||||
bl.toLowerCase();
|
char ca = *pa++;
|
||||||
return al.compareTo(bl) < 0;
|
char cb = *pb++;
|
||||||
|
if (ca >= 'A' && ca <= 'Z') ca += 'a' - 'A';
|
||||||
|
if (cb >= 'A' && cb <= 'Z') cb += 'a' - 'A';
|
||||||
|
if (ca < cb) return true;
|
||||||
|
if (ca > cb) return false;
|
||||||
|
}
|
||||||
|
return *pa < *pb;
|
||||||
};
|
};
|
||||||
std::sort(dirNames.begin(), dirNames.end(), ciLess);
|
std::sort(dirNames.begin(), dirNames.end(), ciLess);
|
||||||
std::sort(fileNames.begin(), fileNames.end(), ciLess);
|
std::sort(fileNames.begin(), fileNames.end(), ciLess);
|
||||||
|
|
@ -165,7 +175,7 @@ void DirectoryNode::buildDirectoryTree(const char *currentPath)
|
||||||
fullPath += "/";
|
fullPath += "/";
|
||||||
fullPath += fileName;
|
fullPath += fileName;
|
||||||
|
|
||||||
mp3Files.push_back(fullPath);
|
mp3Files.push_back(std::move(fullPath));
|
||||||
ids.push_back(getNextId());
|
ids.push_back(getNextId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -174,7 +184,7 @@ void DirectoryNode::printDirectoryTree(int level) const
|
||||||
{
|
{
|
||||||
for (int i = 0; i < level; i++)
|
for (int i = 0; i < level; i++)
|
||||||
{
|
{
|
||||||
Serial.print(" ");
|
Serial.print(F(" "));
|
||||||
}
|
}
|
||||||
Serial.println(name);
|
Serial.println(name);
|
||||||
|
|
||||||
|
|
@ -182,7 +192,7 @@ void DirectoryNode::printDirectoryTree(int level) const
|
||||||
{
|
{
|
||||||
for (int i = 0; i <= level; i++)
|
for (int i = 0; i <= level; i++)
|
||||||
{
|
{
|
||||||
Serial.print(" ");
|
Serial.print(F(" "));
|
||||||
}
|
}
|
||||||
Serial.println(mp3File);
|
Serial.println(mp3File);
|
||||||
}
|
}
|
||||||
|
|
@ -256,15 +266,16 @@ DirectoryNode *DirectoryNode::advanceToMP3(const uint16_t id)
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we get here, no song with this ID was found
|
// If we get here, no song with this ID was found
|
||||||
Serial.println("advanceToMP3: No song found for ID: " + String(id));
|
Serial.print(F("advanceToMP3: No song found for ID: "));
|
||||||
|
Serial.println(id);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
DirectoryNode *DirectoryNode::advanceToMP3(const String songName)
|
DirectoryNode *DirectoryNode::advanceToMP3(const String &songName)
|
||||||
{
|
{
|
||||||
if (songName.isEmpty())
|
if (songName.isEmpty())
|
||||||
{
|
{
|
||||||
Serial.println("advanceToMP3: songName is empty");
|
Serial.println(F("advanceToMP3: songName is empty"));
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -279,8 +290,6 @@ DirectoryNode *DirectoryNode::advanceToMP3(const String songName)
|
||||||
// Lowercased copies for case-insensitive comparisons (FAT can uppercase names)
|
// Lowercased copies for case-insensitive comparisons (FAT can uppercase names)
|
||||||
String lowTarget = songName;
|
String lowTarget = songName;
|
||||||
lowTarget.toLowerCase();
|
lowTarget.toLowerCase();
|
||||||
String lowNormPath = normalizedPath;
|
|
||||||
lowNormPath.toLowerCase();
|
|
||||||
|
|
||||||
// First, search in the current directory's MP3 files
|
// First, search in the current directory's MP3 files
|
||||||
for (size_t i = 0; i < mp3Files.size(); i++)
|
for (size_t i = 0; i < mp3Files.size(); i++)
|
||||||
|
|
@ -359,7 +368,8 @@ DirectoryNode *DirectoryNode::advanceToMP3(const String songName)
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we get here, no matching song was found
|
// If we get here, no matching song was found
|
||||||
Serial.println("advanceToMP3: No song found for: " + songName);
|
Serial.print(F("advanceToMP3: No song found for: "));
|
||||||
|
Serial.println(songName);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -376,14 +386,14 @@ DirectoryNode *DirectoryNode::goToPreviousMP3(uint32_t thresholdSeconds)
|
||||||
// Safety check for null pointer
|
// Safety check for null pointer
|
||||||
if (currentPlaying.isEmpty())
|
if (currentPlaying.isEmpty())
|
||||||
{
|
{
|
||||||
Serial.println("goToPreviousMP3: currentPlaying is empty");
|
Serial.println(F("goToPreviousMP3: currentPlaying is empty"));
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we've been playing for more than threshold seconds, restart current song
|
// If we've been playing for more than threshold seconds, restart current song
|
||||||
if (secondsPlayed > thresholdSeconds)
|
if (secondsPlayed > thresholdSeconds)
|
||||||
{
|
{
|
||||||
Serial.println("goToPreviousMP3: Restarting current song (played > threshold)");
|
Serial.println(F("goToPreviousMP3: Restarting current song (played > threshold)"));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -401,7 +411,7 @@ DirectoryNode *DirectoryNode::goToPreviousMP3(uint32_t thresholdSeconds)
|
||||||
// If current song found and not the first song, move to previous
|
// If current song found and not the first song, move to previous
|
||||||
if (currentIndex > 0)
|
if (currentIndex > 0)
|
||||||
{
|
{
|
||||||
Serial.print("goToPreviousMP3: Moving to previous song in same directory: ");
|
Serial.print(F("goToPreviousMP3: Moving to previous song in same directory: "));
|
||||||
Serial.println(mp3Files[currentIndex - 1]);
|
Serial.println(mp3Files[currentIndex - 1]);
|
||||||
setCurrentPlaying(mp3Files[currentIndex - 1]);
|
setCurrentPlaying(mp3Files[currentIndex - 1]);
|
||||||
return this;
|
return this;
|
||||||
|
|
@ -409,15 +419,15 @@ DirectoryNode *DirectoryNode::goToPreviousMP3(uint32_t thresholdSeconds)
|
||||||
|
|
||||||
// If we're at the first song or song not found in current directory,
|
// If we're at the first song or song not found in current directory,
|
||||||
// we need to find the previous song globally
|
// we need to find the previous song globally
|
||||||
Serial.println("goToPreviousMP3: At first song or song not found, looking for previous globally");
|
Serial.println(F("goToPreviousMP3: At first song or song not found, looking for previous globally"));
|
||||||
return nullptr; // Let the caller handle global previous logic
|
return nullptr; // Let the caller handle global previous logic
|
||||||
}
|
}
|
||||||
|
|
||||||
DirectoryNode *DirectoryNode::findPreviousMP3Globally(const String currentGlobal)
|
DirectoryNode *DirectoryNode::findPreviousMP3Globally(const String ¤tGlobal)
|
||||||
{
|
{
|
||||||
if (currentGlobal.isEmpty())
|
if (currentGlobal.isEmpty())
|
||||||
{
|
{
|
||||||
Serial.println("findPreviousMP3Globally: currentGlobal is null");
|
Serial.println(F("findPreviousMP3Globally: currentGlobal is null"));
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -444,23 +454,25 @@ DirectoryNode *DirectoryNode::findPreviousMP3Globally(const String currentGlobal
|
||||||
DirectoryNode *prevNode = allMP3s[currentGlobalIndex - 1].first;
|
DirectoryNode *prevNode = allMP3s[currentGlobalIndex - 1].first;
|
||||||
int prevFileIndex = allMP3s[currentGlobalIndex - 1].second;
|
int prevFileIndex = allMP3s[currentGlobalIndex - 1].second;
|
||||||
|
|
||||||
Serial.print("findPreviousMP3Globally: Moving to previous song globally: ");
|
Serial.print(F("findPreviousMP3Globally: Moving to previous song globally: "));
|
||||||
Serial.println(prevNode->mp3Files[prevFileIndex]);
|
Serial.println(prevNode->mp3Files[prevFileIndex]);
|
||||||
|
|
||||||
prevNode->setCurrentPlaying(prevNode->mp3Files[prevFileIndex]);
|
prevNode->setCurrentPlaying(prevNode->mp3Files[prevFileIndex]);
|
||||||
return prevNode;
|
return prevNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
Serial.println("findPreviousMP3Globally: No previous song found globally");
|
Serial.println(F("findPreviousMP3Globally: No previous song found globally"));
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DirectoryNode::buildFlatMP3List(std::vector<std::pair<DirectoryNode *, int>> &allMP3s)
|
void DirectoryNode::buildFlatMP3List(std::vector<std::pair<DirectoryNode *, int>> &allMP3s)
|
||||||
{
|
{
|
||||||
|
// Pre-reserve to reduce reallocations
|
||||||
|
allMP3s.reserve(allMP3s.size() + mp3Files.size());
|
||||||
// Add all MP3 files from this directory
|
// Add all MP3 files from this directory
|
||||||
for (size_t i = 0; i < mp3Files.size(); i++)
|
for (size_t i = 0; i < mp3Files.size(); i++)
|
||||||
{
|
{
|
||||||
allMP3s.push_back(std::make_pair(this, i));
|
allMP3s.emplace_back(this, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Recursively add MP3 files from subdirectories
|
// Recursively add MP3 files from subdirectories
|
||||||
|
|
@ -470,12 +482,12 @@ void DirectoryNode::buildFlatMP3List(std::vector<std::pair<DirectoryNode *, int>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const size_t DirectoryNode::getNumOfFiles()
|
size_t DirectoryNode::getNumOfFiles() const
|
||||||
{
|
{
|
||||||
return subdirectories.size();
|
return subdirectories.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
DirectoryNode *DirectoryNode::advanceToNextMP3(const String currentGlobal)
|
DirectoryNode *DirectoryNode::advanceToNextMP3(const String ¤tGlobal)
|
||||||
{
|
{
|
||||||
bool useFirst = false;
|
bool useFirst = false;
|
||||||
Serial.println(currentGlobal.c_str());
|
Serial.println(currentGlobal.c_str());
|
||||||
|
|
@ -534,7 +546,7 @@ DirectoryNode *DirectoryNode::advanceToNextMP3(const String currentGlobal)
|
||||||
|
|
||||||
// If we get here, there were no MP3 files or subdirectories left to check
|
// If we get here, there were no MP3 files or subdirectories left to check
|
||||||
currentPlaying = "";
|
currentPlaying = "";
|
||||||
Serial.println("no more nodes found");
|
Serial.println(F("no more nodes found"));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -581,6 +593,3 @@ void DirectoryNode::streamDirectoryHTML(Print &out) const {
|
||||||
yield(); // Final yield before completing
|
yield(); // Final yield before completing
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -34,14 +34,14 @@ public:
|
||||||
const std::vector<DirectoryNode*>& getSubdirectories() const;
|
const std::vector<DirectoryNode*>& getSubdirectories() const;
|
||||||
const std::vector<String>& getMP3Files() const;
|
const std::vector<String>& getMP3Files() const;
|
||||||
|
|
||||||
const size_t getNumOfFiles();
|
size_t getNumOfFiles() const;
|
||||||
|
|
||||||
void setCurrentPlaying(const String mp3File);
|
void setCurrentPlaying(const String& mp3File);
|
||||||
const String getCurrentPlaying() const;
|
const String& getCurrentPlaying() const;
|
||||||
const uint16_t getCurrentPlayingId() const;
|
const uint16_t getCurrentPlayingId() const;
|
||||||
|
|
||||||
void setSecondsPlayed(const uint32_t seconds);
|
void setSecondsPlayed(const uint32_t seconds);
|
||||||
uint32_t getSecondsPlayed();
|
uint32_t getSecondsPlayed() const;
|
||||||
|
|
||||||
uint16_t getNextId();
|
uint16_t getNextId();
|
||||||
|
|
||||||
|
|
@ -49,10 +49,10 @@ public:
|
||||||
void addMP3File(const String& mp3File);
|
void addMP3File(const String& mp3File);
|
||||||
void buildDirectoryTree(const char* currentPath);
|
void buildDirectoryTree(const char* currentPath);
|
||||||
void printDirectoryTree(int level = 0) const;
|
void printDirectoryTree(int level = 0) const;
|
||||||
DirectoryNode* advanceToMP3(const String songName);
|
DirectoryNode* advanceToMP3(const String& songName);
|
||||||
DirectoryNode* advanceToNextMP3(const String currentGlobal);
|
DirectoryNode* advanceToNextMP3(const String& currentGlobal);
|
||||||
DirectoryNode* goToPreviousMP3(uint32_t thresholdSeconds = 3);
|
DirectoryNode* goToPreviousMP3(uint32_t thresholdSeconds = 3);
|
||||||
DirectoryNode* findPreviousMP3Globally(const String currentGlobal);
|
DirectoryNode* findPreviousMP3Globally(const String& currentGlobal);
|
||||||
void buildFlatMP3List(std::vector<std::pair<DirectoryNode*, int>>& allMP3s);
|
void buildFlatMP3List(std::vector<std::pair<DirectoryNode*, int>>& allMP3s);
|
||||||
DirectoryNode* advanceToMP3(const uint16_t id);
|
DirectoryNode* advanceToMP3(const uint16_t id);
|
||||||
void advanceToFirstMP3InThisNode();
|
void advanceToFirstMP3InThisNode();
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue