From 8bac1e5a890aa9793cc5f9d312815c736d79b594 Mon Sep 17 00:00:00 2001 From: nILS Date: Thu, 19 Feb 2026 10:47:06 +0100 Subject: [PATCH 1/9] adds memory pool with 1k buffer and file index list --- sources/Application/Utils/CMakeLists.txt | 1 + sources/Application/Utils/MemoryPool.cpp | 46 ++++++++++++++++++++++++ sources/Application/Utils/MemoryPool.h | 31 ++++++++++++++++ 3 files changed, 78 insertions(+) create mode 100644 sources/Application/Utils/MemoryPool.cpp create mode 100644 sources/Application/Utils/MemoryPool.h diff --git a/sources/Application/Utils/CMakeLists.txt b/sources/Application/Utils/CMakeLists.txt index c7d11033d..96bb5d718 100644 --- a/sources/Application/Utils/CMakeLists.txt +++ b/sources/Application/Utils/CMakeLists.txt @@ -1,4 +1,5 @@ add_library(application_utils + MemoryPool.cpp HexBuffers.cpp char.cpp fixed.cpp diff --git a/sources/Application/Utils/MemoryPool.cpp b/sources/Application/Utils/MemoryPool.cpp new file mode 100644 index 000000000..14493a4c4 --- /dev/null +++ b/sources/Application/Utils/MemoryPool.cpp @@ -0,0 +1,46 @@ +/* + * SPDX-License-Identifier: BSD-3-Clause + * + * Copyright (c) 2026 xiphonics, inc. + * + * This file is part of the picoTracker firmware + */ + +#include "MemoryPool.h" + +#if PROTECT_SCRATCH +#include "Application/AppWindow.h" +#include "Application/Application.h" +#include "Application/Views/ModalDialogs/MessageBox.h" +#include "System/Console/Trace.h" +#endif + +// globally available 1k scratch buffer for temporary use, e.g. for file loading +// string rendering, file sorting +char MemoryPool::buffer_[MEMORYPOOL_SCRATCH_SIZE]; + +#if PROTECT_SCRATCH +bool MemoryPool::used_ = false; +#endif +etl::vector MemoryPool::fileIndexList; + +void *MemoryPool::Acquire() { +#if PROTECT_SCRATCH + if (used_) { + Trace::Error("MemoryPool is already in use!"); + Application *app = Application::GetInstance(); + AppWindow *window = (AppWindow *)app->GetWindow(); + MessageBox *mb = MessageBox::Create( + *(window->getCurrentView()), "MemoryPool is already in use!", MBBF_OK); + window->getCurrentView()->DoModal(mb); + } + used_ = true; +#endif + return buffer_; +} + +void MemoryPool::Release() { +#if PROTECT_SCRATCH + used_ = false; +#endif +} diff --git a/sources/Application/Utils/MemoryPool.h b/sources/Application/Utils/MemoryPool.h new file mode 100644 index 000000000..b7da324c1 --- /dev/null +++ b/sources/Application/Utils/MemoryPool.h @@ -0,0 +1,31 @@ +/* + * SPDX-License-Identifier: BSD-3-Clause + * + * Copyright (c) 2026 xiphonics, inc. + * + * This file is part of the picoTracker firmware + */ + +#include "System/FileSystem/FileSystem.h" + +#ifdef DEBUG +#ifndef PROTECT_SCRATCH +#define PROTECT_SCRATCH 1 +#endif +#endif + +constexpr size_t MEMORYPOOL_SCRATCH_SIZE = 1024; + +class MemoryPool { +private: + static char buffer_[MEMORYPOOL_SCRATCH_SIZE]; +#if PROTECT_SCRATCH + static bool used_; +#endif + +public: + static etl::vector fileIndexList; + + static void *Acquire(); + static void Release(); +}; \ No newline at end of file From 656eb84ce5e4cd3de442fa4706c38ff510a0fe39 Mon Sep 17 00:00:00 2001 From: nILS Date: Thu, 19 Feb 2026 10:48:25 +0100 Subject: [PATCH 2/9] views now use the shared file index list --- sources/Application/Views/ImportView.cpp | 44 +++++++++++-------- sources/Application/Views/ImportView.h | 1 - .../Views/InstrumentImportView.cpp | 27 +++++++----- .../Application/Views/InstrumentImportView.h | 1 - .../Application/Views/SelectProjectView.cpp | 35 ++++++++------- sources/Application/Views/SelectProjectView.h | 1 - sources/Application/Views/ThemeImportView.cpp | 27 +++++++----- sources/Application/Views/ThemeImportView.h | 1 - 8 files changed, 74 insertions(+), 63 deletions(-) diff --git a/sources/Application/Views/ImportView.cpp b/sources/Application/Views/ImportView.cpp index 50960f291..a197a534a 100644 --- a/sources/Application/Views/ImportView.cpp +++ b/sources/Application/Views/ImportView.cpp @@ -8,9 +8,11 @@ */ #include "ImportView.h" + #include "Application/Audio/AudioFileStreamer.h" #include "Application/Instruments/SampleInstrument.h" #include "Application/Instruments/SamplePool.h" +#include "Application/Utils/MemoryPool.h" #include "Application/Views/SampleEditorView.h" #include "Externals/etl/include/etl/string.h" #include "Externals/etl/include/etl/to_string.h" @@ -45,7 +47,7 @@ void ImportView::Reset() { playKeyHeld_ = false; editKeyHeld_ = false; inProjectSampleDir_ = false; - fileIndexList_.clear(); + MemoryPool::fileIndexList.clear(); } // Static method to set the source view type before opening ImportView @@ -77,7 +79,7 @@ void ImportView::ProcessButtonMask(unsigned short mask, bool pressed) { // Handle key press events if (pressed) { auto fs = FileSystem::GetInstance(); - unsigned fileIndex = fileIndexList_[currentIndex_]; + unsigned fileIndex = MemoryPool::fileIndexList[currentIndex_]; if (mask & EPBM_PLAY) { char name[PFILENAME_SIZE]; @@ -125,7 +127,7 @@ void ImportView::ProcessButtonMask(unsigned short mask, bool pressed) { if (mask & EPBM_ENTER) { if (inProjectSampleDir_) { - if (fileIndexList_.empty()) { + if (MemoryPool::fileIndexList.empty()) { return; // Do nothing if the list is empty } // NOTE: the order of buttons in project pool is: edit, remove @@ -156,7 +158,7 @@ void ImportView::ProcessButtonMask(unsigned short mask, bool pressed) { // handle changing selected "bottom button", note: ignore if this is a // nav+arrow combo if ((mask & EPBM_LEFT || mask & EPBM_RIGHT) && !(mask & EPBM_NAV)) { - if (inProjectSampleDir_ && fileIndexList_.empty()) { + if (inProjectSampleDir_ && MemoryPool::fileIndexList.empty()) { return; // Do nothing if the list is empty } // toggle the selected button @@ -171,12 +173,12 @@ void ImportView::ProcessButtonMask(unsigned short mask, bool pressed) { // handle moving up and down the file list if (mask & EPBM_UP) { - if (inProjectSampleDir_ && fileIndexList_.empty()) { + if (inProjectSampleDir_ && MemoryPool::fileIndexList.empty()) { return; // Do nothing if the list is empty } warpToNextSample(true); } else if (mask & EPBM_DOWN) { - if (inProjectSampleDir_ && fileIndexList_.empty()) { + if (inProjectSampleDir_ && MemoryPool::fileIndexList.empty()) { return; // Do nothing if the list is empty } warpToNextSample(false); @@ -193,7 +195,7 @@ void ImportView::ProcessButtonMask(unsigned short mask, bool pressed) { // A modifier if (mask & EPBM_ENTER) { auto fs = FileSystem::GetInstance(); - unsigned fileIndex = fileIndexList_[currentIndex_]; + unsigned fileIndex = MemoryPool::fileIndexList[currentIndex_]; char name[PFILENAME_SIZE]; fs->getFileName(fileIndex, name, PFILENAME_SIZE); if (fs->getFileType(fileIndex) == PFT_DIR) { @@ -234,10 +236,11 @@ void ImportView::DrawView() { // Loop through visible files in the list for (size_t i = topIndex_; - i < topIndex_ + LIST_PAGE_SIZE && (i < fileIndexList_.size()); i++) { + i < topIndex_ + LIST_PAGE_SIZE && (i < MemoryPool::fileIndexList.size()); + i++) { props.invert_ = false; - unsigned fileIndex = fileIndexList_[i]; + unsigned fileIndex = MemoryPool::fileIndexList[i]; etl::string displayName; if (fs->getFileType(fileIndex) != PFT_DIR) { @@ -309,7 +312,7 @@ void ImportView::DrawView() { } DrawString(x + 10, y, "Edit", props); } else { - if (fileIndexList_.empty()) { + if (MemoryPool::fileIndexList.empty()) { // draw this a few lines down from *top* of screen SetColor(CD_NORMAL); props.invert_ = false; @@ -348,7 +351,7 @@ void ImportView::DrawView() { props.invert_ = true; y = 0; uint32_t filesize = 0; - auto currentFileIndex = fileIndexList_[currentIndex_]; + auto currentFileIndex = MemoryPool::fileIndexList[currentIndex_]; // only get file size if it's a file not a dir if (fs->getFileType(currentFileIndex) == PFT_FILE) { @@ -413,7 +416,7 @@ void ImportView::warpToNextSample(bool goUp) { } } } else { - if (currentIndex_ < fileIndexList_.size() - 1) { + if (currentIndex_ < MemoryPool::fileIndexList.size() - 1) { currentIndex_++; // if we have scrolled off the bottom, page the file list down if not // at end of the list @@ -427,7 +430,7 @@ void ImportView::warpToNextSample(bool goUp) { void ImportView::preview(char *name) { auto fs = FileSystem::GetInstance(); - unsigned fileIndex = fileIndexList_[currentIndex_]; + unsigned fileIndex = MemoryPool::fileIndexList[currentIndex_]; // do not preview directories if (fs->getFileType(fileIndex) == PFT_DIR) { @@ -502,7 +505,7 @@ void ImportView::import() { auto fs = FileSystem::GetInstance(); char name[PFILENAME_SIZE]; - unsigned fileIndex = fileIndexList_[currentIndex_]; + unsigned fileIndex = MemoryPool::fileIndexList[currentIndex_]; fs->getFileName(fileIndex, name, PFILENAME_SIZE); // Get current project name @@ -760,20 +763,23 @@ void ImportView::onConfirmRemoveProjectSample(View &, ModalView &dialog) { } void ImportView::refreshFileIndexList(FileSystem *fs) { - fs->list(&fileIndexList_, ".wav", false); + fs->list(&MemoryPool::fileIndexList, ".wav", false); if (fs->isCurrentRoot() || inProjectSampleDir_) { - for (auto it = fileIndexList_.begin(); it != fileIndexList_.end(); ++it) { + for (auto it = MemoryPool::fileIndexList.begin(); + it != MemoryPool::fileIndexList.end(); ++it) { char entryName[PFILENAME_SIZE]; fs->getFileName(*it, entryName, PFILENAME_SIZE); if (strcmp(entryName, "..") == 0) { - fileIndexList_.erase(it); + MemoryPool::fileIndexList.erase(it); break; } } } - if (currentIndex_ >= fileIndexList_.size()) { - currentIndex_ = fileIndexList_.empty() ? 0 : fileIndexList_.size() - 1; + if (currentIndex_ >= MemoryPool::fileIndexList.size()) { + currentIndex_ = MemoryPool::fileIndexList.empty() + ? 0 + : MemoryPool::fileIndexList.size() - 1; } } diff --git a/sources/Application/Views/ImportView.h b/sources/Application/Views/ImportView.h index f4dfa9330..03bc876f8 100644 --- a/sources/Application/Views/ImportView.h +++ b/sources/Application/Views/ImportView.h @@ -59,6 +59,5 @@ class ImportView : public ScreenView { false; // Flag to track if we're in the project's sample directory FileSystem *pendingDeleteFs_ = nullptr; char pendingDeleteFilename_[PFILENAME_SIZE] = {}; - etl::vector fileIndexList_; }; #endif diff --git a/sources/Application/Views/InstrumentImportView.cpp b/sources/Application/Views/InstrumentImportView.cpp index eda74d003..5139953f9 100644 --- a/sources/Application/Views/InstrumentImportView.cpp +++ b/sources/Application/Views/InstrumentImportView.cpp @@ -11,6 +11,7 @@ #include "Application/AppWindow.h" #include "Application/Instruments/I_Instrument.h" #include "Application/Persistency/PersistencyService.h" +#include "Application/Utils/MemoryPool.h" #include "ModalDialogs/MessageBox.h" #include #include @@ -32,7 +33,7 @@ void InstrumentImportView::Reset() { currentIndex_ = 0; selected_ = 0; toInstrID_ = 0; - fileIndexList_.clear(); + MemoryPool::fileIndexList.clear(); } void InstrumentImportView::ProcessButtonMask(unsigned short mask, @@ -44,8 +45,8 @@ void InstrumentImportView::ProcessButtonMask(unsigned short mask, auto fs = FileSystem::GetInstance(); char name[PFILENAME_SIZE]; - if (currentIndex_ < fileIndexList_.size()) { - unsigned fileIndex = fileIndexList_[currentIndex_]; + if (currentIndex_ < MemoryPool::fileIndexList.size()) { + unsigned fileIndex = MemoryPool::fileIndexList[currentIndex_]; fs->getFileName(fileIndex, name, PFILENAME_SIZE); if (mask & EPBM_ALT) { @@ -74,8 +75,8 @@ void InstrumentImportView::ProcessButtonMask(unsigned short mask, if (mask & EPBM_ENTER) { auto fs = FileSystem::GetInstance(); - if (currentIndex_ < fileIndexList_.size()) { - unsigned fileIndex = fileIndexList_[currentIndex_]; + if (currentIndex_ < MemoryPool::fileIndexList.size()) { + unsigned fileIndex = MemoryPool::fileIndexList[currentIndex_]; char name[PFILENAME_SIZE]; fs->getFileName(fileIndex, name, PFILENAME_SIZE); @@ -115,7 +116,8 @@ void InstrumentImportView::DrawView() { // than buffer but instead returns empty string in buffer :-( char buffer[PFILENAME_SIZE]; for (size_t i = topIndex_; - i < topIndex_ + LIST_PAGE_SIZE && (i < fileIndexList_.size()); i++) { + i < topIndex_ + LIST_PAGE_SIZE && (i < MemoryPool::fileIndexList.size()); + i++) { if (i == currentIndex_) { SetColor(CD_HILITE2); props.invert_ = true; @@ -125,7 +127,7 @@ void InstrumentImportView::DrawView() { } memset(buffer, '\0', sizeof(buffer)); - unsigned fileIndex = fileIndexList_[i]; + unsigned fileIndex = MemoryPool::fileIndexList[i]; fs->getFileName(fileIndex, buffer, PFILENAME_SIZE); if (fs->getFileType(fileIndex) == PFT_DIR) { @@ -151,7 +153,7 @@ void InstrumentImportView::OnFocus() { } void InstrumentImportView::warpToNextInstrument(bool goUp) { - if (fileIndexList_.empty()) + if (MemoryPool::fileIndexList.empty()) return; if (goUp) { @@ -162,7 +164,7 @@ void InstrumentImportView::warpToNextInstrument(bool goUp) { } } } else { - if (currentIndex_ < fileIndexList_.size() - 1) { + if (currentIndex_ < MemoryPool::fileIndexList.size() - 1) { currentIndex_++; if (currentIndex_ >= topIndex_ + LIST_PAGE_SIZE) { topIndex_ = currentIndex_ - LIST_PAGE_SIZE + 1; @@ -342,8 +344,9 @@ void InstrumentImportView::setCurrentFolder(FileSystem *fs, const char *name) { isDirty_ = true; // Update list of file indexes in this new dir - fileIndexList_.clear(); + MemoryPool::fileIndexList.clear(); // Use false for subDirOnly to include both files and directories - fs->list(&fileIndexList_, INSTRUMENT_FILE_EXTENSION, false); - Trace::Debug("loaded %d files from %s", fileIndexList_.size(), name); + fs->list(&MemoryPool::fileIndexList, INSTRUMENT_FILE_EXTENSION, false); + Trace::Debug("loaded %d files from %s", MemoryPool::fileIndexList.size(), + name); } diff --git a/sources/Application/Views/InstrumentImportView.h b/sources/Application/Views/InstrumentImportView.h index ebf309156..d22b88b02 100644 --- a/sources/Application/Views/InstrumentImportView.h +++ b/sources/Application/Views/InstrumentImportView.h @@ -37,6 +37,5 @@ class InstrumentImportView : public ScreenView { size_t currentIndex_ = 0; short selected_ = 0; int toInstrID_ = 0; - etl::vector fileIndexList_; }; #endif diff --git a/sources/Application/Views/SelectProjectView.cpp b/sources/Application/Views/SelectProjectView.cpp index 139c847f9..5122d0479 100644 --- a/sources/Application/Views/SelectProjectView.cpp +++ b/sources/Application/Views/SelectProjectView.cpp @@ -10,6 +10,7 @@ #include "SelectProjectView.h" #include "Application/AppWindow.h" #include "Application/Persistency/PersistencyService.h" +#include "Application/Utils/MemoryPool.h" #include "Application/Views/ModalDialogs/MessageBox.h" #include "BaseClasses/ViewEvent.h" #include "Foundation/Constants/SpecialCharacters.h" @@ -57,7 +58,7 @@ void SelectProjectView::Reset() { topIndex_ = 0; currentIndex_ = 0; selection_[0] = '\0'; - fileIndexList_.clear(); + MemoryPool::fileIndexList.clear(); } void SelectProjectView::DrawView() { @@ -84,7 +85,8 @@ void SelectProjectView::DrawView() { const char *currentProject = projectName.c_str(); for (size_t i = topIndex_; - i < topIndex_ + LIST_PAGE_SIZE && (i < fileIndexList_.size()); i++) { + i < topIndex_ + LIST_PAGE_SIZE && (i < MemoryPool::fileIndexList.size()); + i++) { if (i == currentIndex_) { SetColor(CD_HILITE2); props.invert_ = true; @@ -95,7 +97,7 @@ void SelectProjectView::DrawView() { char buffer[MAX_PROJECT_NAME_LENGTH + 1]; memset(buffer, '\0', sizeof(buffer)); - unsigned fileIndex = fileIndexList_[i]; + unsigned fileIndex = MemoryPool::fileIndexList[i]; if (fs->getFileType(fileIndex) == PFT_DIR) { fs->getFileName(fileIndex, buffer, MAX_PROJECT_NAME_LENGTH + 1); @@ -135,7 +137,7 @@ void SelectProjectView::DrawView() { }; void SelectProjectView::DrawScrollBar() { - int totalItems = fileIndexList_.size(); + int totalItems = MemoryPool::fileIndexList.size(); if (totalItems <= LIST_PAGE_SIZE) { return; // no scrollbar needed } @@ -239,7 +241,7 @@ void SelectProjectView::warpToNextProject(bool goUp) { } } } else { - if (currentIndex_ < fileIndexList_.size() - 1) { + if (currentIndex_ < MemoryPool::fileIndexList.size() - 1) { currentIndex_++; // if we have scrolled off the bottom, page the file list down if not // at end of the list @@ -256,13 +258,14 @@ void SelectProjectView::setCurrentFolder() { fs->chdir(PROJECTS_DIR); // get ready - fileIndexList_.clear(); + MemoryPool::fileIndexList.clear(); // Let's read all the directory in the project dir - fs->list(&fileIndexList_, "", true); + fs->list(&MemoryPool::fileIndexList, "", true); // Filter out "." and ".." along with the hidden default project entry - for (auto it = fileIndexList_.begin(); it != fileIndexList_.end();) { + for (auto it = MemoryPool::fileIndexList.begin(); + it != MemoryPool::fileIndexList.end();) { fs->getFileName(*it, selection_, MAX_PROJECT_NAME_LENGTH + 1); const bool isDotEntry = @@ -272,16 +275,16 @@ void SelectProjectView::setCurrentFolder() { if (isDotEntry || isUntitled) { if (isUntitled) { Trace::Log("SELECTPROJECTVIEW", "skipping untitled project on Index:%d", - static_cast(it - fileIndexList_.begin())); + static_cast(it - MemoryPool::fileIndexList.begin())); } - it = fileIndexList_.erase(it); + it = MemoryPool::fileIndexList.erase(it); } else { ++it; } } // reset & redraw screen - currentIndex_ = std::min(currentIndex_, fileIndexList_.size() - 1); + currentIndex_ = std::min(currentIndex_, MemoryPool::fileIndexList.size() - 1); topIndex_ = 0; currentIndex_ = 0; isDirty_ = true; @@ -292,12 +295,12 @@ void SelectProjectView::getSelectedProjectName(char *name) { } void SelectProjectView::getHighlightedProjectName(char *name) { - if (currentIndex_ >= fileIndexList_.size()) { + if (currentIndex_ >= MemoryPool::fileIndexList.size()) { return; } auto fs = FileSystem::GetInstance(); - unsigned fileIndex = fileIndexList_[currentIndex_]; + unsigned fileIndex = MemoryPool::fileIndexList[currentIndex_]; fs->getFileName(fileIndex, name, MAX_PROJECT_NAME_LENGTH + 1); } @@ -307,12 +310,12 @@ void SelectProjectView::SelectButton(int direction) { } void SelectProjectView::LoadProject() { - if (currentIndex_ >= fileIndexList_.size()) { + if (currentIndex_ >= MemoryPool::fileIndexList.size()) { return; } // all subdirs directly inside /project are expected to be projects - unsigned fileIndex = fileIndexList_[currentIndex_]; + unsigned fileIndex = MemoryPool::fileIndexList[currentIndex_]; auto fs = FileSystem::GetInstance(); fs->getFileName(fileIndex, selection_, MAX_PROJECT_NAME_LENGTH + 1); if (strlen(selection_) == 0) { @@ -388,7 +391,7 @@ void SelectProjectView::ConfirmOverwrite() { } void SelectProjectView::AttemptDeletingSelectedProject() { - if (currentIndex_ >= fileIndexList_.size()) { + if (currentIndex_ >= MemoryPool::fileIndexList.size()) { return; } diff --git a/sources/Application/Views/SelectProjectView.h b/sources/Application/Views/SelectProjectView.h index bf075d080..e5055f6b1 100644 --- a/sources/Application/Views/SelectProjectView.h +++ b/sources/Application/Views/SelectProjectView.h @@ -40,7 +40,6 @@ class SelectProjectView : public ScreenView { size_t topIndex_ = 0; size_t currentIndex_ = 0; char selection_[MAX_PROJECT_NAME_LENGTH + 1]; - etl::vector fileIndexList_; int selectedButton_ = 0; void DrawScrollBar(); diff --git a/sources/Application/Views/ThemeImportView.cpp b/sources/Application/Views/ThemeImportView.cpp index 4d411f6e3..70f5f3518 100644 --- a/sources/Application/Views/ThemeImportView.cpp +++ b/sources/Application/Views/ThemeImportView.cpp @@ -11,6 +11,7 @@ #include "Application/AppWindow.h" #include "Application/Model/Config.h" #include "Application/Persistency/PersistenceConstants.h" +#include "Application/Utils/MemoryPool.h" #include "Application/Views/ModalDialogs/MessageBox.h" #include "ModalDialogs/MessageBox.h" #include "System/Console/Trace.h" @@ -30,7 +31,7 @@ ThemeImportView::~ThemeImportView() {} void ThemeImportView::Reset() { topIndex_ = 0; currentIndex_ = 0; - fileIndexList_.clear(); + MemoryPool::fileIndexList.clear(); } void ThemeImportView::ProcessButtonMask(unsigned short mask, bool pressed) { @@ -41,8 +42,8 @@ void ThemeImportView::ProcessButtonMask(unsigned short mask, bool pressed) { auto fs = FileSystem::GetInstance(); char name[PFILENAME_SIZE]; - if (currentIndex_ < fileIndexList_.size()) { - unsigned fileIndex = fileIndexList_[currentIndex_]; + if (currentIndex_ < MemoryPool::fileIndexList.size()) { + unsigned fileIndex = MemoryPool::fileIndexList[currentIndex_]; fs->getFileName(fileIndex, name, PFILENAME_SIZE); if (mask & EPBM_ALT) { @@ -68,8 +69,8 @@ void ThemeImportView::ProcessButtonMask(unsigned short mask, bool pressed) { if (mask & EPBM_ENTER) { auto fs = FileSystem::GetInstance(); - if (currentIndex_ < fileIndexList_.size()) { - unsigned fileIndex = fileIndexList_[currentIndex_]; + if (currentIndex_ < MemoryPool::fileIndexList.size()) { + unsigned fileIndex = MemoryPool::fileIndexList[currentIndex_]; char name[PFILENAME_SIZE]; fs->getFileName(fileIndex, name, PFILENAME_SIZE); @@ -112,7 +113,8 @@ void ThemeImportView::DrawView() { // than buffer but instead returns empty string in buffer :-( char buffer[PFILENAME_SIZE]; for (size_t i = topIndex_; - i < topIndex_ + LIST_PAGE_SIZE && (i < fileIndexList_.size()); i++) { + i < topIndex_ + LIST_PAGE_SIZE && (i < MemoryPool::fileIndexList.size()); + i++) { if (i == currentIndex_) { SetColor(CD_HILITE2); props.invert_ = true; @@ -122,7 +124,7 @@ void ThemeImportView::DrawView() { } memset(buffer, '\0', sizeof(buffer)); - unsigned fileIndex = fileIndexList_[i]; + unsigned fileIndex = MemoryPool::fileIndexList[i]; fs->getFileName(fileIndex, buffer, PFILENAME_SIZE); if (fs->getFileType(fileIndex) == PFT_DIR) { @@ -153,7 +155,7 @@ void ThemeImportView::OnFocus() { } void ThemeImportView::warpToNextTheme(bool goUp) { - if (fileIndexList_.empty()) + if (MemoryPool::fileIndexList.empty()) return; if (goUp) { @@ -166,7 +168,7 @@ void ThemeImportView::warpToNextTheme(bool goUp) { } } } else { - if (currentIndex_ < fileIndexList_.size() - 1) { + if (currentIndex_ < MemoryPool::fileIndexList.size() - 1) { currentIndex_++; // if we have scrolled off the bottom, page the file list down if not // at end of the list @@ -234,8 +236,9 @@ void ThemeImportView::setCurrentFolder(FileSystem *fs, const char *name) { isDirty_ = true; // Update list of file indexes in this new dir - fileIndexList_.clear(); + MemoryPool::fileIndexList.clear(); // Use false for subDirOnly to include both files and directories - fs->list(&fileIndexList_, THEME_FILE_EXTENSION, false); - Trace::Debug("loaded %d files from %s", fileIndexList_.size(), name); + fs->list(&MemoryPool::fileIndexList, THEME_FILE_EXTENSION, false); + Trace::Debug("loaded %d files from %s", MemoryPool::fileIndexList.size(), + name); } diff --git a/sources/Application/Views/ThemeImportView.h b/sources/Application/Views/ThemeImportView.h index 2bb4197cb..022a7c6e4 100644 --- a/sources/Application/Views/ThemeImportView.h +++ b/sources/Application/Views/ThemeImportView.h @@ -35,6 +35,5 @@ class ThemeImportView : public ScreenView { size_t topIndex_ = 0; size_t currentIndex_ = 0; - etl::vector fileIndexList_; }; #endif From 543b6c842eec6a1479b14e4493aba9eb7933eabc Mon Sep 17 00:00:00 2001 From: nILS Date: Thu, 19 Feb 2026 10:53:36 +0100 Subject: [PATCH 3/9] moving fileIndexLists from stack to use the global buffer as well --- sources/Adapters/adv/gui/SerialDebugUI.cpp | 4 ++-- sources/Adapters/picoTracker/gui/SerialDebugUI.cpp | 11 ++++++----- sources/Application/Instruments/SamplePool.cpp | 10 +++++----- 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/sources/Adapters/adv/gui/SerialDebugUI.cpp b/sources/Adapters/adv/gui/SerialDebugUI.cpp index 113673d37..e6f4801fb 100644 --- a/sources/Adapters/adv/gui/SerialDebugUI.cpp +++ b/sources/Adapters/adv/gui/SerialDebugUI.cpp @@ -198,8 +198,8 @@ void SerialDebugUI::listFiles(const char *path) { if (!fs->chdir(path)) { Trace::Error("failed to ls files path:%s", path); } - etl::vector fileIndexes; - fs->list(&fileIndexes, "", false); + + fs->list(&MemoryPool::fileIndexList, "", false); // No need to actually do the printing below for now as the current debug code // in PicoFileSystem class is already printing all the files fetched when the diff --git a/sources/Adapters/picoTracker/gui/SerialDebugUI.cpp b/sources/Adapters/picoTracker/gui/SerialDebugUI.cpp index ef7e869a2..4fe411321 100644 --- a/sources/Adapters/picoTracker/gui/SerialDebugUI.cpp +++ b/sources/Adapters/picoTracker/gui/SerialDebugUI.cpp @@ -8,6 +8,7 @@ #include "SerialDebugUI.h" #include "Application/Model/Config.h" +#include "Application/Utils/MemoryPool.h" #include "System/FileSystem/FileSystem.h" #include "System/FileSystem/I_File.h" #include "hardware/uart.h" @@ -134,13 +135,13 @@ void SerialDebugUI::listFiles(const char *path) { if (!fs->chdir(path)) { Trace::Error("failed to ls files path:%s", path); } - etl::vector fileIndexes; - fs->list(&fileIndexes, "", false); + + fs->list(&MemoryPool::fileIndexList, "", false); char name[PFILENAME_SIZE]; - for (size_t i = 0; i < fileIndexes.size(); i++) { - fs->getFileName(fileIndexes[i], name, PFILENAME_SIZE); - if (fs->getFileType(fileIndexes[i]) == PFT_FILE) { + for (size_t i = 0; i < MemoryPool::fileIndexList.size(); i++) { + fs->getFileName(MemoryPool::fileIndexList[i], name, PFILENAME_SIZE); + if (fs->getFileType(MemoryPool::fileIndexList[i]) == PFT_FILE) { printf("[file] %s\n", name); } else { printf("[dir] %s\n", name); diff --git a/sources/Application/Instruments/SamplePool.cpp b/sources/Application/Instruments/SamplePool.cpp index b0b30d84e..2c12d2f54 100644 --- a/sources/Application/Instruments/SamplePool.cpp +++ b/sources/Application/Instruments/SamplePool.cpp @@ -10,6 +10,7 @@ #include "SamplePool.h" #include "Application/Model/Config.h" #include "Application/Persistency/PersistencyService.h" +#include "Application/Utils/MemoryPool.h" #include "Externals/SRC/common.h" #include "Externals/etl/include/etl/string.h" #include "Externals/etl/include/etl/string_stream.h" @@ -46,13 +47,12 @@ void SamplePool::Load(const char *projectName) { PROJECT_SAMPLES_DIR); } // First, find all wav files - etl::vector fileIndexes; - fs->list(&fileIndexes, ".wav", false); + fs->list(&MemoryPool::fileIndexList, ".wav", false); char name[PFILENAME_SIZE]; - uint totalSamples = fileIndexes.size(); + uint totalSamples = MemoryPool::fileIndexList.size(); for (uint i = 0; i < totalSamples; i++) { - fs->getFileName(fileIndexes[i], name, PFILENAME_SIZE); - if (fs->getFileType(fileIndexes[i]) == PFT_FILE) { + fs->getFileName(MemoryPool::fileIndexList[i], name, PFILENAME_SIZE); + if (fs->getFileType(MemoryPool::fileIndexList[i]) == PFT_FILE) { // Check if the filename exceeds the maximum allowed length if (strlen(name) > MAX_INSTRUMENT_FILENAME_LENGTH) { Trace::Error( From 21cb084b228f9520329990aa312c77df41289c41 Mon Sep 17 00:00:00 2001 From: nILS Date: Thu, 19 Feb 2026 11:51:16 +0100 Subject: [PATCH 4/9] removes unused members and replaces static allocations with the MemoryPool --- .../picoTracker/filesystem/picoTrackerFileSystem.cpp | 12 ++++++++---- .../picoTracker/filesystem/picoTrackerFileSystem.h | 3 --- sources/Application/AppWindow.cpp | 2 -- sources/Application/Audio/AudioFileStreamer.cpp | 12 ++++++------ sources/Application/Audio/AudioFileStreamer.h | 1 - 5 files changed, 14 insertions(+), 16 deletions(-) diff --git a/sources/Adapters/picoTracker/filesystem/picoTrackerFileSystem.cpp b/sources/Adapters/picoTracker/filesystem/picoTrackerFileSystem.cpp index ec6a28aed..fee3249ad 100644 --- a/sources/Adapters/picoTracker/filesystem/picoTrackerFileSystem.cpp +++ b/sources/Adapters/picoTracker/filesystem/picoTrackerFileSystem.cpp @@ -7,6 +7,7 @@ */ #include "picoTrackerFileSystem.h" +#include "Application/Utils/MemoryPool.h" #include "Externals/etl/include/etl/pool.h" #include "pico/multicore.h" #include @@ -277,21 +278,24 @@ bool picoTrackerFileSystem::CopyFile(const char *srcFilename, auto fSrc = sd.open(srcFilename, O_READ); auto fDest = sd.open(destFilename, O_WRITE | O_CREAT); + char *fileBuffer = (char *)MemoryPool::Acquire(); + int n = 0; - int bufferSize = sizeof(fileBuffer_); + while (true) { - n = fSrc.read(fileBuffer_, bufferSize); + n = fSrc.read(fileBuffer, MEMORYPOOL_SCRATCH_SIZE); // check for read error and only write if no error if (n >= 0) { - fDest.write(fileBuffer_, n); + fDest.write(fileBuffer, n); } else { Trace::Error("Failed to read file: %s", srcFilename); return false; } - if (n < bufferSize) { + if ((size_t)n < MEMORYPOOL_SCRATCH_SIZE) { break; } } + MemoryPool::Release(); fSrc.close(); fDest.close(); return true; diff --git a/sources/Adapters/picoTracker/filesystem/picoTrackerFileSystem.h b/sources/Adapters/picoTracker/filesystem/picoTrackerFileSystem.h index 40d649ce4..3bd7355cd 100644 --- a/sources/Adapters/picoTracker/filesystem/picoTrackerFileSystem.h +++ b/sources/Adapters/picoTracker/filesystem/picoTrackerFileSystem.h @@ -50,9 +50,6 @@ class picoTrackerFileSystem : public FileSystem { private: SdFs sd; void tolowercase(char *temp); - // buffer needs to be allocated here as too big for allocation as local - // variable on the stack - uint8_t fileBuffer_[512]; }; // Concrete implementation of PI_File for picoTracker diff --git a/sources/Application/AppWindow.cpp b/sources/Application/AppWindow.cpp index b12a9589f..cfaf48d60 100644 --- a/sources/Application/AppWindow.cpp +++ b/sources/Application/AppWindow.cpp @@ -152,8 +152,6 @@ AppWindow::AppWindow(I_GUIWindowImp &imp, const char *projectName) // Init all members - _statusLine[0] = 0; - _currentView = nullptr; _closeProject = false; _lastA = 0; diff --git a/sources/Application/Audio/AudioFileStreamer.cpp b/sources/Application/Audio/AudioFileStreamer.cpp index 69db4b118..7b20fb1ae 100644 --- a/sources/Application/Audio/AudioFileStreamer.cpp +++ b/sources/Application/Audio/AudioFileStreamer.cpp @@ -9,6 +9,7 @@ #include "AudioFileStreamer.h" #include "Application/Model/Config.h" +#include "Application/Utils/MemoryPool.h" #include "Application/Utils/fixed.h" #include "Services/Audio/Audio.h" #include "System/Console/Trace.h" @@ -40,17 +41,16 @@ AudioFileStreamer::~AudioFileStreamer() { wav_.Close(); }; bool AudioFileStreamer::Start(const char *name, int startSample, bool looping) { Trace::Debug("Starting to stream:%s from sample %d", name, startSample); - strcpy(name_, name); position_ = (startSample > 0) ? float(startSample) : 0.0f; #ifndef ADV stopRequested_ = false; #endif wav_.Close(); - Trace::Log("", "wave open:%s", name_); - auto res = wav_.Open(name_); + Trace::Log("", "wave open:%s", name); + auto res = wav_.Open(name); if (!res) { - Trace::Error("Failed to open streaming of file:%s", name_); + Trace::Error("Failed to open streaming of file:%s", name); mode_ = AFSM_STOPPED; return false; } @@ -89,7 +89,7 @@ bool AudioFileStreamer::Start(const char *name, int startSample, bool looping) { fpSpeed_ = fl2fp(ratio); Trace::Debug("AudioFileStreamer: File '%s' - Sample Rate: %d Hz, Channels: " "%d", - name_, fileSampleRate_, channels); + name, fileSampleRate_, channels); Trace::Debug("Size: %ld samples, Speed: %d", size, fp2i(fpSpeed_)); // Load the entire buffer for single cycle waveforms @@ -197,7 +197,7 @@ bool AudioFileStreamer::Render(fixed *buffer, int samplecount) { } // look if we have the file loaded if (!wav_.IsOpen()) { - Trace::Error("Failed to open streaming of file:%s", name_); + Trace::Error("Failed to open streaming of file"); mode_ = AFSM_STOPPED; return false; } diff --git a/sources/Application/Audio/AudioFileStreamer.h b/sources/Application/Audio/AudioFileStreamer.h index 9e8057b71..0d7d35f5e 100644 --- a/sources/Application/Audio/AudioFileStreamer.h +++ b/sources/Application/Audio/AudioFileStreamer.h @@ -30,7 +30,6 @@ class AudioFileStreamer : public AudioModule { protected: AudioFileStreamerMode mode_; - char name_[256]; WavFile wav_; float position_; Project *project_; From 0784968d08cfda931e979e9772cb5d69372b505f Mon Sep 17 00:00:00 2001 From: nILS Date: Fri, 20 Feb 2026 16:40:13 +0100 Subject: [PATCH 5/9] sort filelists alphabetically, yay (untested on advance) --- .../Adapters/adv/filesystem/advFileSystem.cpp | 48 ++++++++++-- .../Adapters/adv/filesystem/advFileSystem.h | 2 +- sources/Adapters/adv/gui/SerialDebugUI.cpp | 1 + .../filesystem/picoTrackerFileSystem.cpp | 74 ++++++++++++++++--- .../filesystem/picoTrackerFileSystem.h | 2 +- sources/Application/AppWindow.h | 4 +- .../Persistency/PersistencyService.cpp | 19 ++--- .../Persistency/PersistencyService.h | 1 - sources/Application/Views/ImportView.cpp | 2 +- .../Views/InstrumentImportView.cpp | 2 +- .../Application/Views/SelectProjectView.cpp | 2 +- sources/Application/Views/ThemeImportView.cpp | 2 +- sources/System/FileSystem/FileSystem.h | 18 ++++- 13 files changed, 142 insertions(+), 35 deletions(-) diff --git a/sources/Adapters/adv/filesystem/advFileSystem.cpp b/sources/Adapters/adv/filesystem/advFileSystem.cpp index 571d7ee3f..b63a8ef4e 100644 --- a/sources/Adapters/adv/filesystem/advFileSystem.cpp +++ b/sources/Adapters/adv/filesystem/advFileSystem.cpp @@ -7,6 +7,7 @@ */ #include "advFileSystem.h" +#include "Application/Utils/MemoryPool.h" #include "Externals/etl/include/etl/pool.h" #include "FileHandle.h" #include @@ -133,7 +134,7 @@ PicoFileType advFileSystem::getFileType(int index) { } void advFileSystem::list(etl::ivector *fileIndexes, const char *filter, - bool subDirOnly) { + bool subDirOnly, bool sorted = false) { fileIndexes->clear(); @@ -155,6 +156,8 @@ void advFileSystem::list(etl::ivector *fileIndexes, const char *filter, return; } + uint32_t *sortKeys = (uint32_t *)MemoryPool::Acquire(); + for (size_t i = 0; i < file_cache_.size(); ++i) { if (fileIndexes->full()) { Trace::Error("PICOFILESYSTEM: fileIndexes is full, breaking list"); @@ -177,19 +180,52 @@ void advFileSystem::list(etl::ivector *fileIndexes, const char *filter, // filter out "." style hidden entries and files that dont match filter if ((isDir || (isFile && matchesFilter)) && !isHiddenName) { - if (subDirOnly) { - if (fno.fattrib & AM_DIR) { - fileIndexes->push_back(i); - } - } else { + if (!subDirOnly || isDir) { fileIndexes->push_back(i); + + if (sorted) { + sortKeys[fileIndexes->size() - 1] = + FileSystem::getFileSortKey(fno.fname); + } } Trace::Log("FILESYSTEM", "[%d] got file: %s", index, fno.fname); } else { Trace::Log("FILESYSTEM", "skipped hidden: %s", fno.fname); } } + + for (size_t i = 1; i < fileIndexes->size(); i++) { + uint32_t key = sortKeys[i]; + int index = fileIndexes->at(i); + size_t j = i; + + while (j > 0) { + bool shouldMove = sortKeys[j - 1] > key; + + if (!shouldMove && sortKeys[j - 1] == key) { + // keys are identical, do a tiebreaker by doing a string compare to + // ensure stable sorting of files with same first 4 letters + const FILINFO &fA = file_cache_[index]; + const FILINFO &fB = file_cache_[fileIndexes->at(j - 1)]; + + shouldMove = strcasecmp(fA.fname, fB.fname) > 0; + } + + if (shouldMove) { + sortKeys[j] = sortKeys[j - 1]; + fileIndexes->at(j) = fileIndexes->at(j - 1); + --j; + } else { + break; + } + } + + sortKeys[j] = key; + fileIndexes->at(j) = index; + } + f_closedir(&dir); + MemoryPool::Release(); Trace::Log("FILESYSTEM", "added file indexes:%d", fileIndexes->size()); } diff --git a/sources/Adapters/adv/filesystem/advFileSystem.h b/sources/Adapters/adv/filesystem/advFileSystem.h index 3fbd8b624..cdd8072a1 100644 --- a/sources/Adapters/adv/filesystem/advFileSystem.h +++ b/sources/Adapters/adv/filesystem/advFileSystem.h @@ -51,7 +51,7 @@ class advFileSystem : public FileSystem { virtual FileHandle Open(const char *name, const char *mode) override; virtual bool chdir(const char *path) override; virtual void list(etl::ivector *fileIndexes, const char *filter, - bool subDirOnly) override; + bool subDirOnly, bool sorted) override; virtual void getFileName(int index, char *name, int length) override; virtual PicoFileType getFileType(int index) override; virtual bool isParentRoot() override; diff --git a/sources/Adapters/adv/gui/SerialDebugUI.cpp b/sources/Adapters/adv/gui/SerialDebugUI.cpp index e6f4801fb..f6693630c 100644 --- a/sources/Adapters/adv/gui/SerialDebugUI.cpp +++ b/sources/Adapters/adv/gui/SerialDebugUI.cpp @@ -10,6 +10,7 @@ #include "../system/advSystem.h" #include "Adapters/adv/audio/record.h" #include "Application/Model/Config.h" +#include "Application/Utils/MemoryPool.h" #include "System/FileSystem/FileSystem.h" #include "System/FileSystem/I_File.h" #include "System/System/System.h" diff --git a/sources/Adapters/picoTracker/filesystem/picoTrackerFileSystem.cpp b/sources/Adapters/picoTracker/filesystem/picoTrackerFileSystem.cpp index fee3249ad..3d7aac974 100644 --- a/sources/Adapters/picoTracker/filesystem/picoTrackerFileSystem.cpp +++ b/sources/Adapters/picoTracker/filesystem/picoTrackerFileSystem.cpp @@ -7,6 +7,7 @@ */ #include "picoTrackerFileSystem.h" +#include "Application/Persistency/PersistencyService.h" #include "Application/Utils/MemoryPool.h" #include "Externals/etl/include/etl/pool.h" #include "pico/multicore.h" @@ -121,19 +122,20 @@ PicoFileType picoTrackerFileSystem::getFileType(int index) { } void picoTrackerFileSystem::list(etl::ivector *fileIndexes, - const char *filter, bool subDirOnly) { + const char *filter, bool subDirOnly, + bool sorted = false) { std::lock_guard lock(mutex); fileIndexes->clear(); File cwd; + char buffer[PFILENAME_SIZE]; + if (!cwd.openCwd()) { - char name[PFILENAME_SIZE]; - cwd.getName(name, PFILENAME_SIZE); + cwd.getName(buffer, PFILENAME_SIZE); Trace::Error("Failed to open cwd"); return; } - char buffer[PFILENAME_SIZE]; cwd.getName(buffer, PFILENAME_SIZE); Trace::Log("FILESYSTEM", "LIST DIR:%s", buffer); @@ -145,6 +147,8 @@ void picoTrackerFileSystem::list(etl::ivector *fileIndexes, File entry; uint16_t count = 0; + uint32_t *sortKeys = (uint32_t *)MemoryPool::Acquire(); + // ref: https://github.com/greiman/SdFat/issues/353#issuecomment-1003422848 while (entry.openNext(&cwd, O_READ) && (count < fileIndexes->capacity())) { uint32_t index = entry.dirIndex(); @@ -160,23 +164,71 @@ void picoTrackerFileSystem::list(etl::ivector *fileIndexes, // filter out "." and files that dont match filter if a filter is given if ((entry.isDirectory() && entry.dirIndex() != 0) || (!entry.isHidden() && matchesFilter)) { - if (subDirOnly) { - if (entry.isDirectory()) { - fileIndexes->push_back(index); - } - } else { + if (!subDirOnly || entry.isDirectory()) { fileIndexes->push_back(index); + count++; + + if (sorted) { + entry.getName(buffer, PFILENAME_SIZE); + sortKeys[fileIndexes->size() - 1] = + FileSystem::getFileSortKey(buffer); + } } // Trace::Log("FILESYSTEM", "[%d] got file: %s", index, buffer); - count++; } else { // Trace::Log("FILESYSTEM", "skipped hidden: %s", buffer); } entry.close(); } - cwd.close(); + Trace::Log("FILESYSTEM", "scanned: %d, added file indexes:%d", count, fileIndexes->size()); + + if (!sorted) { + MemoryPool::Release(); + return; + } + + // sort using insertion sort (with an extra step if our keys are identical) + char currentName[PFILENAME_SIZE]; + + for (size_t i = 1; i < count; i++) { + uint32_t key = sortKeys[i]; + int index = fileIndexes->at(i); + size_t j = i; + + while (j > 0) { + bool shouldMove = sortKeys[j - 1] > key; + + if (!shouldMove && sortKeys[j - 1] == key) { + // keys are identical, do a tiebreaker by doing a string compare to + // ensure stable sorting of files with same first 4 letters + entry.open(index); + entry.getName(currentName, PFILENAME_SIZE); + entry.close(); + + entry.open(fileIndexes->at(j - 1)); + entry.getName(buffer, PFILENAME_SIZE); + entry.close(); + + shouldMove = strcasecmp(buffer, currentName) > 0; + } + + if (shouldMove) { + sortKeys[j] = sortKeys[j - 1]; + fileIndexes->at(j) = fileIndexes->at(j - 1); + --j; + } else { + break; + } + } + + sortKeys[j] = key; + fileIndexes->at(j) = index; + } + + cwd.close(); + MemoryPool::Release(); } void picoTrackerFileSystem::getFileName(int index, char *name, int length) { diff --git a/sources/Adapters/picoTracker/filesystem/picoTrackerFileSystem.h b/sources/Adapters/picoTracker/filesystem/picoTrackerFileSystem.h index 3bd7355cd..bdb275fbd 100644 --- a/sources/Adapters/picoTracker/filesystem/picoTrackerFileSystem.h +++ b/sources/Adapters/picoTracker/filesystem/picoTrackerFileSystem.h @@ -31,7 +31,7 @@ class picoTrackerFileSystem : public FileSystem { virtual FileHandle Open(const char *name, const char *mode) override; virtual bool chdir(const char *path) override; virtual void list(etl::ivector *fileIndexes, const char *filter, - bool subDirOnly) override; + bool subDirOnly, bool sorted) override; virtual void getFileName(int index, char *name, int length) override; virtual PicoFileType getFileType(int index) override; virtual bool isParentRoot() override; diff --git a/sources/Application/AppWindow.h b/sources/Application/AppWindow.h index 123346f17..f2ebf2dd0 100644 --- a/sources/Application/AppWindow.h +++ b/sources/Application/AppWindow.h @@ -56,12 +56,15 @@ class AppWindow : public GUIWindow, I_Observer, Status { using GUIWindow::Clear; virtual void Clear(bool all = false); virtual void ClearTextRect(GUIRect &rect); + using GUIWindow::SetColor; virtual void SetColor(ColorDefinition cd); void SetDirty(); void UpdateColorsFromConfig(); void SetSdCardPresent(bool present); + View *getCurrentView() const { return _currentView; } + char projectName_[MAX_PROJECT_NAME_LENGTH + 1]; protected: // GUIWindow implementation @@ -103,7 +106,6 @@ class AppWindow : public GUIWindow, I_Observer, Status { unsigned short _mask; unsigned long _lastA; unsigned long _lastB; - char _statusLine[80]; bool lowBatteryState_; bool lowBatteryMessageShown_; diff --git a/sources/Application/Persistency/PersistencyService.cpp b/sources/Application/Persistency/PersistencyService.cpp index fab8cfb5c..5ccf628ac 100644 --- a/sources/Application/Persistency/PersistencyService.cpp +++ b/sources/Application/Persistency/PersistencyService.cpp @@ -9,8 +9,8 @@ #include "PersistencyService.h" #include "../Instruments/SamplePool.h" +#include "Application/Utils/MemoryPool.h" #include "Foundation/Services/ServiceRegistry.h" - #include "Foundation/Types/Types.h" #include "Persistent.h" #include "System/Console/Trace.h" @@ -60,18 +60,18 @@ bool PersistencyService::DeleteProject(const char *projectName) { return false; } - etl::vector fileIndexes; - fs->list(&fileIndexes, ".wav", false); + fs->list(&MemoryPool::fileIndexList, ".wav", false); // delete all samples fs->BeginBatch(); char filename[128]; - for (size_t i = 0; i < fileIndexes.size(); i++) { - fs->getFileName(fileIndexes[i], filename, MAX_PROJECT_SAMPLE_PATH_LENGTH); + for (size_t i = 0; i < MemoryPool::fileIndexList.size(); i++) { + fs->getFileName(MemoryPool::fileIndexList[i], filename, + MAX_PROJECT_SAMPLE_PATH_LENGTH); if (strcmp(filename, "..") == 0 || strcmp(filename, ".") == 0) { continue; } - if (fs->getFileType(fileIndexes[i]) == PFT_DIR) { + if (fs->getFileType(MemoryPool::fileIndexList[i]) == PFT_DIR) { continue; } fs->DeleteFile(filename); @@ -134,10 +134,11 @@ PersistencyResult PersistencyService::Save(const char *projectName, Trace::Debug("get list of samples to copy from old project: %s", oldProjectName); - fs->list(&fileIndexes_, ".wav", false); + fs->list(&MemoryPool::fileIndexList, ".wav", false); char filenameBuffer[PFILENAME_SIZE]; - for (size_t i = 0; i < fileIndexes_.size(); i++) { - fs->getFileName(fileIndexes_[i], filenameBuffer, sizeof(filenameBuffer)); + for (size_t i = 0; i < MemoryPool::fileIndexList.size(); i++) { + fs->getFileName(MemoryPool::fileIndexList[i], filenameBuffer, + sizeof(filenameBuffer)); // ignore . and .. entries as using *.wav doesnt filter them out if (strcmp(filenameBuffer, ".") == 0 || strcmp(filenameBuffer, "..") == 0) diff --git a/sources/Application/Persistency/PersistencyService.h b/sources/Application/Persistency/PersistencyService.h index 165471cc8..2edb90f72 100644 --- a/sources/Application/Persistency/PersistencyService.h +++ b/sources/Application/Persistency/PersistencyService.h @@ -66,7 +66,6 @@ class PersistencyService : public Service, PersistencyResult SaveProjectData(const char *projectName, bool autosave); // need these as statically allocated buffers as too big for stack - etl::vector fileIndexes_; etl::string pathBufferA; etl::string pathBufferB; }; diff --git a/sources/Application/Views/ImportView.cpp b/sources/Application/Views/ImportView.cpp index a197a534a..01a4fbf15 100644 --- a/sources/Application/Views/ImportView.cpp +++ b/sources/Application/Views/ImportView.cpp @@ -763,7 +763,7 @@ void ImportView::onConfirmRemoveProjectSample(View &, ModalView &dialog) { } void ImportView::refreshFileIndexList(FileSystem *fs) { - fs->list(&MemoryPool::fileIndexList, ".wav", false); + fs->list(&MemoryPool::fileIndexList, ".wav", false, true); if (fs->isCurrentRoot() || inProjectSampleDir_) { for (auto it = MemoryPool::fileIndexList.begin(); diff --git a/sources/Application/Views/InstrumentImportView.cpp b/sources/Application/Views/InstrumentImportView.cpp index 5139953f9..a77285eae 100644 --- a/sources/Application/Views/InstrumentImportView.cpp +++ b/sources/Application/Views/InstrumentImportView.cpp @@ -346,7 +346,7 @@ void InstrumentImportView::setCurrentFolder(FileSystem *fs, const char *name) { // Update list of file indexes in this new dir MemoryPool::fileIndexList.clear(); // Use false for subDirOnly to include both files and directories - fs->list(&MemoryPool::fileIndexList, INSTRUMENT_FILE_EXTENSION, false); + fs->list(&MemoryPool::fileIndexList, INSTRUMENT_FILE_EXTENSION, false, true); Trace::Debug("loaded %d files from %s", MemoryPool::fileIndexList.size(), name); } diff --git a/sources/Application/Views/SelectProjectView.cpp b/sources/Application/Views/SelectProjectView.cpp index 5122d0479..813e5f389 100644 --- a/sources/Application/Views/SelectProjectView.cpp +++ b/sources/Application/Views/SelectProjectView.cpp @@ -261,7 +261,7 @@ void SelectProjectView::setCurrentFolder() { MemoryPool::fileIndexList.clear(); // Let's read all the directory in the project dir - fs->list(&MemoryPool::fileIndexList, "", true); + fs->list(&MemoryPool::fileIndexList, "", true, true); // Filter out "." and ".." along with the hidden default project entry for (auto it = MemoryPool::fileIndexList.begin(); diff --git a/sources/Application/Views/ThemeImportView.cpp b/sources/Application/Views/ThemeImportView.cpp index 70f5f3518..7059a469d 100644 --- a/sources/Application/Views/ThemeImportView.cpp +++ b/sources/Application/Views/ThemeImportView.cpp @@ -238,7 +238,7 @@ void ThemeImportView::setCurrentFolder(FileSystem *fs, const char *name) { // Update list of file indexes in this new dir MemoryPool::fileIndexList.clear(); // Use false for subDirOnly to include both files and directories - fs->list(&MemoryPool::fileIndexList, THEME_FILE_EXTENSION, false); + fs->list(&MemoryPool::fileIndexList, THEME_FILE_EXTENSION, false, true); Trace::Debug("loaded %d files from %s", MemoryPool::fileIndexList.size(), name); } diff --git a/sources/System/FileSystem/FileSystem.h b/sources/System/FileSystem/FileSystem.h index 5c4c73937..d0fc5df4f 100644 --- a/sources/System/FileSystem/FileSystem.h +++ b/sources/System/FileSystem/FileSystem.h @@ -37,7 +37,7 @@ class FileSystem : public T_Factory { return false; } // Default implementation virtual void list(etl::ivector *fileIndexes, const char *filter, - bool subDirOnly) = 0; + bool subDirOnly, bool sorted = false) = 0; virtual void getFileName(int index, char *name, int length) = 0; virtual PicoFileType getFileType(int index) = 0; virtual bool isParentRoot() = 0; @@ -53,6 +53,22 @@ class FileSystem : public T_Factory { virtual bool CopyFile(const char *srcFilename, const char *destFilename) = 0; virtual bool MoveFile(const char *srcFilename, const char *destFilename) = 0; virtual bool isExFat() = 0; + + // extracts a uint32 from the first four letters of a string for faster + // sorting by comparing these uint32 values instead of doing string compares + static uint32_t getFileSortKey(const char *filename) { + uint32_t sortKey = 0; + const uint8_t *value = reinterpret_cast(filename); + + for (size_t i = 0; i < 4; i++) { + char c = value[i]; + sortKey <<= 8; + if (c != '\0') { + sortKey |= (c >= 'A' && c <= 'Z') ? 'a' + (c - 'A') : c; + } + } + return sortKey; + } }; #endif // _FILESYSTEM_H_ From 3817649499b54dfd5ad90c408b719f6ac6e0244d Mon Sep 17 00:00:00 2001 From: nILS Date: Fri, 20 Feb 2026 16:40:46 +0100 Subject: [PATCH 6/9] adv doesn't build for me without these changes --- sources/Application/Views/BaseClasses/UIIntField.cpp | 4 +++- sources/Application/Views/BaseClasses/UIIntField.h | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/sources/Application/Views/BaseClasses/UIIntField.cpp b/sources/Application/Views/BaseClasses/UIIntField.cpp index 3e90b739a..fe5ac8686 100644 --- a/sources/Application/Views/BaseClasses/UIIntField.cpp +++ b/sources/Application/Views/BaseClasses/UIIntField.cpp @@ -27,7 +27,9 @@ UIIntField::UIIntField(const GUIPoint &position, int *src, const char *format, yOffset_ = yOffset; }; -void UIIntField::Draw(GUIWindow &w) { +void UIIntField::Draw(GUIWindow &w, int offset) { + + (void)offset; GUITextProperties props; GUIPoint position = GetPosition(); diff --git a/sources/Application/Views/BaseClasses/UIIntField.h b/sources/Application/Views/BaseClasses/UIIntField.h index 3f3b41b9a..2ca645af7 100644 --- a/sources/Application/Views/BaseClasses/UIIntField.h +++ b/sources/Application/Views/BaseClasses/UIIntField.h @@ -18,7 +18,7 @@ class UIIntField : public UIField { UIIntField(const GUIPoint &position, int *src, const char *format, int min, int max, int xOffset, int yOffset); virtual ~UIIntField(){}; - virtual void Draw(GUIWindow &w); + virtual void Draw(GUIWindow &w, int offset = 0) override; virtual void ProcessArrow(unsigned short mask); virtual void OnClick(){}; From d79d443db66395c8a0dce57841470d3e036fcefb Mon Sep 17 00:00:00 2001 From: nILS Date: Fri, 20 Mar 2026 16:50:23 +0100 Subject: [PATCH 7/9] merges upstream/master, removes MemoryPool --- .../Adapters/adv/filesystem/advFileSystem.cpp | 4 +- sources/Adapters/adv/gui/SerialDebugUI.cpp | 3 +- .../filesystem/picoTrackerFileSystem.cpp | 41 +++++++---------- .../picoTracker/gui/SerialDebugUI.cpp | 10 ++-- .../Application/Audio/AudioFileStreamer.cpp | 1 - .../Application/Instruments/SamplePool.cpp | 8 ++-- sources/Application/Instruments/SamplePool.h | 1 + .../Persistency/PersistencyService.cpp | 17 ++++--- .../Persistency/PersistencyService.h | 1 + sources/Application/Utils/CMakeLists.txt | 1 - sources/Application/Utils/MemoryPool.cpp | 46 ------------------- sources/Application/Utils/MemoryPool.h | 31 ------------- sources/Application/Views/ImportView.cpp | 29 ++++++------ sources/Application/Views/ImportView.h | 1 + .../Views/InstrumentImportView.cpp | 27 +++++------ .../Application/Views/InstrumentImportView.h | 1 + .../Application/Views/SelectProjectView.cpp | 32 ++++++------- sources/Application/Views/SelectProjectView.h | 1 + sources/Application/Views/ThemeImportView.cpp | 27 +++++------ sources/Application/Views/ThemeImportView.h | 1 + 20 files changed, 93 insertions(+), 190 deletions(-) delete mode 100644 sources/Application/Utils/MemoryPool.cpp delete mode 100644 sources/Application/Utils/MemoryPool.h diff --git a/sources/Adapters/adv/filesystem/advFileSystem.cpp b/sources/Adapters/adv/filesystem/advFileSystem.cpp index be0b29682..e49cad69b 100644 --- a/sources/Adapters/adv/filesystem/advFileSystem.cpp +++ b/sources/Adapters/adv/filesystem/advFileSystem.cpp @@ -7,7 +7,6 @@ */ #include "advFileSystem.h" -#include "Application/Utils/MemoryPool.h" #include "Externals/etl/include/etl/pool.h" #include "FileHandle.h" #include @@ -156,7 +155,7 @@ void advFileSystem::list(etl::ivector *fileIndexes, const char *filter, return; } - uint32_t *sortKeys = (uint32_t *)MemoryPool::Acquire(); + uint32_t sortKeys[MAX_FILE_INDEX_SIZE]; for (size_t i = 0; i < file_cache_.size(); ++i) { if (fileIndexes->full()) { @@ -233,7 +232,6 @@ void advFileSystem::list(etl::ivector *fileIndexes, const char *filter, } f_closedir(&dir); - MemoryPool::Release(); Trace::Log("FILESYSTEM", "added file indexes:%d", fileIndexes->size()); } diff --git a/sources/Adapters/adv/gui/SerialDebugUI.cpp b/sources/Adapters/adv/gui/SerialDebugUI.cpp index f6693630c..3c193f702 100644 --- a/sources/Adapters/adv/gui/SerialDebugUI.cpp +++ b/sources/Adapters/adv/gui/SerialDebugUI.cpp @@ -10,7 +10,6 @@ #include "../system/advSystem.h" #include "Adapters/adv/audio/record.h" #include "Application/Model/Config.h" -#include "Application/Utils/MemoryPool.h" #include "System/FileSystem/FileSystem.h" #include "System/FileSystem/I_File.h" #include "System/System/System.h" @@ -200,7 +199,7 @@ void SerialDebugUI::listFiles(const char *path) { Trace::Error("failed to ls files path:%s", path); } - fs->list(&MemoryPool::fileIndexList, "", false); + fs->list(&fileIndexList_, "", false, false, true); // No need to actually do the printing below for now as the current debug code // in PicoFileSystem class is already printing all the files fetched when the diff --git a/sources/Adapters/picoTracker/filesystem/picoTrackerFileSystem.cpp b/sources/Adapters/picoTracker/filesystem/picoTrackerFileSystem.cpp index 98c218aa5..cc8c6dd0f 100644 --- a/sources/Adapters/picoTracker/filesystem/picoTrackerFileSystem.cpp +++ b/sources/Adapters/picoTracker/filesystem/picoTrackerFileSystem.cpp @@ -8,7 +8,6 @@ #include "picoTrackerFileSystem.h" #include "Application/Persistency/PersistencyService.h" -#include "Application/Utils/MemoryPool.h" #include "Externals/etl/include/etl/pool.h" #include "pico/multicore.h" #include @@ -123,7 +122,7 @@ PicoFileType picoTrackerFileSystem::getFileType(int index) { void picoTrackerFileSystem::list(etl::ivector *fileIndexes, const char *filter, bool subDirOnly, - bool sorted) { + bool includeHidden, bool sorted) { std::lock_guard lock(mutex); fileIndexes->clear(); @@ -147,7 +146,7 @@ void picoTrackerFileSystem::list(etl::ivector *fileIndexes, File entry; uint16_t count = 0; - uint32_t *sortKeys = (uint32_t *)MemoryPool::Acquire(); + uint32_t sortKeys[MAX_FILE_INDEX_SIZE]; // ref: https://github.com/greiman/SdFat/issues/353#issuecomment-1003422848 while (entry.openNext(&cwd, O_READ) && (count < fileIndexes->capacity())) { @@ -162,25 +161,19 @@ void picoTrackerFileSystem::list(etl::ivector *fileIndexes, // matchesFilter); } // filter out "." and files that dont match filter if a filter is given - if ((entry.isDirectory() && entry.dirIndex() != 0) || - ((!entry.isHidden() || includeHidden) && matchesFilter)) { - if (subDirOnly) { - if (entry.isDirectory()) { - fileIndexes->push_back(index); - } - } else { - fileIndexes->push_back(index); - count++; - - if (sorted) { - entry.getName(buffer, PFILENAME_SIZE); - sortKeys[fileIndexes->size() - 1] = - FileSystem::getFileSortKey(buffer); - } + bool validDir = entry.isDirectory() && entry.dirIndex() != 0; + bool matchVisible = (!entry.isHidden() || includeHidden) && matchesFilter; + + if ((validDir || matchVisible) && (!subDirOnly || entry.isDirectory())) { + if (sorted) { + entry.getName(buffer, PFILENAME_SIZE); + sortKeys[count] = FileSystem::getFileSortKey(buffer); } + fileIndexes->push_back(index); + count++; // Trace::Log("FILESYSTEM", "[%d] got file: %s", index, buffer); } else { - // Trace::Log("FILESYSTEM", "skipped hidden: %s", buffer); + // Trace::Log("FILESYSTEM", "skipped non-matching file: %s", buffer); } entry.close(); } @@ -189,7 +182,6 @@ void picoTrackerFileSystem::list(etl::ivector *fileIndexes, fileIndexes->size()); if (!sorted) { - MemoryPool::Release(); return; } @@ -232,7 +224,6 @@ void picoTrackerFileSystem::list(etl::ivector *fileIndexes, } cwd.close(); - MemoryPool::Release(); } void picoTrackerFileSystem::getFileName(int index, char *name, int length) { @@ -334,12 +325,13 @@ bool picoTrackerFileSystem::CopyFile(const char *srcFilename, auto fSrc = sd.open(srcFilename, O_READ); auto fDest = sd.open(destFilename, O_WRITE | O_CREAT); - char *fileBuffer = (char *)MemoryPool::Acquire(); + const int FILE_BUFFER_SIZE = 1024; + char fileBuffer[FILE_BUFFER_SIZE]; int n = 0; while (true) { - n = fSrc.read(fileBuffer, MEMORYPOOL_SCRATCH_SIZE); + n = fSrc.read(fileBuffer, FILE_BUFFER_SIZE); // check for read error and only write if no error if (n >= 0) { fDest.write(fileBuffer, n); @@ -347,11 +339,10 @@ bool picoTrackerFileSystem::CopyFile(const char *srcFilename, Trace::Error("Failed to read file: %s", srcFilename); return false; } - if ((size_t)n < MEMORYPOOL_SCRATCH_SIZE) { + if ((size_t)n < FILE_BUFFER_SIZE) { break; } } - MemoryPool::Release(); fSrc.close(); fDest.close(); return true; diff --git a/sources/Adapters/picoTracker/gui/SerialDebugUI.cpp b/sources/Adapters/picoTracker/gui/SerialDebugUI.cpp index 4fe411321..c25f5a9f9 100644 --- a/sources/Adapters/picoTracker/gui/SerialDebugUI.cpp +++ b/sources/Adapters/picoTracker/gui/SerialDebugUI.cpp @@ -8,7 +8,6 @@ #include "SerialDebugUI.h" #include "Application/Model/Config.h" -#include "Application/Utils/MemoryPool.h" #include "System/FileSystem/FileSystem.h" #include "System/FileSystem/I_File.h" #include "hardware/uart.h" @@ -136,12 +135,13 @@ void SerialDebugUI::listFiles(const char *path) { Trace::Error("failed to ls files path:%s", path); } - fs->list(&MemoryPool::fileIndexList, "", false); + etl::vector fileIndexList_; + fs->list(&fileIndexList_, "", false, false, true); char name[PFILENAME_SIZE]; - for (size_t i = 0; i < MemoryPool::fileIndexList.size(); i++) { - fs->getFileName(MemoryPool::fileIndexList[i], name, PFILENAME_SIZE); - if (fs->getFileType(MemoryPool::fileIndexList[i]) == PFT_FILE) { + for (size_t i = 0; i < fileIndexList_.size(); i++) { + fs->getFileName(fileIndexList_[i], name, PFILENAME_SIZE); + if (fs->getFileType(fileIndexList_[i]) == PFT_FILE) { printf("[file] %s\n", name); } else { printf("[dir] %s\n", name); diff --git a/sources/Application/Audio/AudioFileStreamer.cpp b/sources/Application/Audio/AudioFileStreamer.cpp index e9c00206f..9ebefaaa6 100644 --- a/sources/Application/Audio/AudioFileStreamer.cpp +++ b/sources/Application/Audio/AudioFileStreamer.cpp @@ -9,7 +9,6 @@ #include "AudioFileStreamer.h" #include "Application/Model/Config.h" -#include "Application/Utils/MemoryPool.h" #include "Application/Utils/fixed.h" #include "Services/Audio/Audio.h" #include "System/Console/Trace.h" diff --git a/sources/Application/Instruments/SamplePool.cpp b/sources/Application/Instruments/SamplePool.cpp index e6bb93123..e0182b13e 100644 --- a/sources/Application/Instruments/SamplePool.cpp +++ b/sources/Application/Instruments/SamplePool.cpp @@ -57,9 +57,9 @@ void SamplePool::Load(const char *projectName) { PROJECT_SAMPLES_DIR); } // First, find all wav files - fs->list(fileIndexList, ".wav", false); + fs->list(&fileIndexList_, ".wav", false, false, true); char name[PFILENAME_SIZE]; - uint totalSamples = fileIndexes.size(); + uint totalSamples = fileIndexList_.size(); // store for ui updates importCount = totalSamples; @@ -68,8 +68,8 @@ void SamplePool::Load(const char *projectName) { importIndex = i; importName = name; - fs->getFileName(fileIndexes[i], name, PFILENAME_SIZE); - if (fs->getFileType(fileIndexes[i]) == PFT_FILE) { + fs->getFileName(fileIndexList_[i], name, PFILENAME_SIZE); + if (fs->getFileType(fileIndexList_[i]) == PFT_FILE) { // Check if the filename exceeds the maximum allowed length if (strlen(name) > MAX_INSTRUMENT_FILENAME_LENGTH) { Trace::Error( diff --git a/sources/Application/Instruments/SamplePool.h b/sources/Application/Instruments/SamplePool.h index a39060e70..910c5420c 100644 --- a/sources/Application/Instruments/SamplePool.h +++ b/sources/Application/Instruments/SamplePool.h @@ -61,6 +61,7 @@ class SamplePool : public T_Factory, public Observable { private: etl::vector observers_; + etl::vector fileIndexList_; }; #endif diff --git a/sources/Application/Persistency/PersistencyService.cpp b/sources/Application/Persistency/PersistencyService.cpp index 6b924c22c..733dc669b 100644 --- a/sources/Application/Persistency/PersistencyService.cpp +++ b/sources/Application/Persistency/PersistencyService.cpp @@ -9,7 +9,6 @@ #include "PersistencyService.h" #include "../Instruments/SamplePool.h" -#include "Application/Utils/MemoryPool.h" #include "Foundation/Services/ServiceRegistry.h" #include "Foundation/Types/Types.h" #include "Persistent.h" @@ -78,13 +77,13 @@ bool PersistencyService::DeleteDirectoryContents_(uint8_t depth) { } while (true) { - fileIndexes_.clear(); - fs->list(&fileIndexes_, "", false, true); + fileIndexList_.clear(); + fs->list(&fileIndexList_, "", false, true); bool foundEntry = false; bool deletedEntry = false; - for (size_t i = 0; i < fileIndexes_.size(); ++i) { - fs->getFileName(fileIndexes_[i], deleteNameBuffer_, + for (size_t i = 0; i < fileIndexList_.size(); ++i) { + fs->getFileName(fileIndexList_[i], deleteNameBuffer_, sizeof(deleteNameBuffer_)); if ((strcmp(deleteNameBuffer_, ".") == 0) || @@ -94,7 +93,7 @@ bool PersistencyService::DeleteDirectoryContents_(uint8_t depth) { foundEntry = true; - const PicoFileType type = fs->getFileType(fileIndexes_[i]); + const PicoFileType type = fs->getFileType(fileIndexList_[i]); if (type == PFT_FILE) { if (!fs->DeleteFile(deleteNameBuffer_)) { Trace::Error("PERSISTENCYSERVICE: Could not delete file: %s", @@ -194,10 +193,10 @@ PersistencyResult PersistencyService::Save(const char *projectName, Trace::Debug("get list of samples to copy from old project: %s", oldProjectName); - fs->list(&MemoryPool::fileIndexList, ".wav", false); + fs->list(&fileIndexList_, ".wav", false); char filenameBuffer[PFILENAME_SIZE]; - for (size_t i = 0; i < MemoryPool::fileIndexList.size(); i++) { - fs->getFileName(MemoryPool::fileIndexList[i], filenameBuffer, + for (size_t i = 0; i < fileIndexList_.size(); i++) { + fs->getFileName(fileIndexList_[i], filenameBuffer, sizeof(filenameBuffer)); // ignore . and .. entries as using *.wav doesnt filter them out diff --git a/sources/Application/Persistency/PersistencyService.h b/sources/Application/Persistency/PersistencyService.h index 9684df913..f5f03835e 100644 --- a/sources/Application/Persistency/PersistencyService.h +++ b/sources/Application/Persistency/PersistencyService.h @@ -70,6 +70,7 @@ class PersistencyService : public Service, // need these as statically allocated buffers as too big for stack etl::string pathBufferA; etl::string pathBufferB; + etl::vector fileIndexList_; char deleteNameBuffer_[PFILENAME_SIZE]; }; diff --git a/sources/Application/Utils/CMakeLists.txt b/sources/Application/Utils/CMakeLists.txt index 96bb5d718..c7d11033d 100644 --- a/sources/Application/Utils/CMakeLists.txt +++ b/sources/Application/Utils/CMakeLists.txt @@ -1,5 +1,4 @@ add_library(application_utils - MemoryPool.cpp HexBuffers.cpp char.cpp fixed.cpp diff --git a/sources/Application/Utils/MemoryPool.cpp b/sources/Application/Utils/MemoryPool.cpp deleted file mode 100644 index 14493a4c4..000000000 --- a/sources/Application/Utils/MemoryPool.cpp +++ /dev/null @@ -1,46 +0,0 @@ -/* - * SPDX-License-Identifier: BSD-3-Clause - * - * Copyright (c) 2026 xiphonics, inc. - * - * This file is part of the picoTracker firmware - */ - -#include "MemoryPool.h" - -#if PROTECT_SCRATCH -#include "Application/AppWindow.h" -#include "Application/Application.h" -#include "Application/Views/ModalDialogs/MessageBox.h" -#include "System/Console/Trace.h" -#endif - -// globally available 1k scratch buffer for temporary use, e.g. for file loading -// string rendering, file sorting -char MemoryPool::buffer_[MEMORYPOOL_SCRATCH_SIZE]; - -#if PROTECT_SCRATCH -bool MemoryPool::used_ = false; -#endif -etl::vector MemoryPool::fileIndexList; - -void *MemoryPool::Acquire() { -#if PROTECT_SCRATCH - if (used_) { - Trace::Error("MemoryPool is already in use!"); - Application *app = Application::GetInstance(); - AppWindow *window = (AppWindow *)app->GetWindow(); - MessageBox *mb = MessageBox::Create( - *(window->getCurrentView()), "MemoryPool is already in use!", MBBF_OK); - window->getCurrentView()->DoModal(mb); - } - used_ = true; -#endif - return buffer_; -} - -void MemoryPool::Release() { -#if PROTECT_SCRATCH - used_ = false; -#endif -} diff --git a/sources/Application/Utils/MemoryPool.h b/sources/Application/Utils/MemoryPool.h deleted file mode 100644 index b7da324c1..000000000 --- a/sources/Application/Utils/MemoryPool.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * SPDX-License-Identifier: BSD-3-Clause - * - * Copyright (c) 2026 xiphonics, inc. - * - * This file is part of the picoTracker firmware - */ - -#include "System/FileSystem/FileSystem.h" - -#ifdef DEBUG -#ifndef PROTECT_SCRATCH -#define PROTECT_SCRATCH 1 -#endif -#endif - -constexpr size_t MEMORYPOOL_SCRATCH_SIZE = 1024; - -class MemoryPool { -private: - static char buffer_[MEMORYPOOL_SCRATCH_SIZE]; -#if PROTECT_SCRATCH - static bool used_; -#endif - -public: - static etl::vector fileIndexList; - - static void *Acquire(); - static void Release(); -}; \ No newline at end of file diff --git a/sources/Application/Views/ImportView.cpp b/sources/Application/Views/ImportView.cpp index d86e6713b..127819d67 100644 --- a/sources/Application/Views/ImportView.cpp +++ b/sources/Application/Views/ImportView.cpp @@ -12,7 +12,6 @@ #include "Application/Audio/AudioFileStreamer.h" #include "Application/Instruments/SampleInstrument.h" #include "Application/Instruments/SamplePool.h" -#include "Application/Utils/MemoryPool.h" #include "Application/Views/SampleEditorView.h" #include "Externals/etl/include/etl/string.h" #include "Externals/etl/include/etl/to_string.h" @@ -65,7 +64,7 @@ void ImportView::Reset() { enterKeyHeld_ = false; pendingDirEnterOnRelease_ = false; inProjectSampleDir_ = false; - MemoryPool::fileIndexList.clear(); + fileIndexList_.clear(); } // Static method to set the source view type before opening ImportView @@ -251,7 +250,7 @@ void ImportView::ProcessButtonMask(unsigned short mask, bool pressed) { // handle changing selected "bottom button", note: ignore if this is a // nav+arrow combo if ((mask & EPBM_LEFT || mask & EPBM_RIGHT) && !(mask & EPBM_NAV)) { - if (inProjectSampleDir_ && MemoryPool::fileIndexList.empty()) { + if (inProjectSampleDir_ && fileIndexList_.empty()) { return; // Do nothing if the list is empty } uint8_t buttonCount = inProjectSampleDir_ @@ -272,12 +271,12 @@ void ImportView::ProcessButtonMask(unsigned short mask, bool pressed) { // handle moving up and down the file list if (mask & EPBM_UP) { - if (inProjectSampleDir_ && MemoryPool::fileIndexList.empty()) { + if (inProjectSampleDir_ && fileIndexList_.empty()) { return; // Do nothing if the list is empty } warpToNextSample(true); } else if (mask & EPBM_DOWN) { - if (inProjectSampleDir_ && MemoryPool::fileIndexList.empty()) { + if (inProjectSampleDir_ && fileIndexList_.empty()) { return; // Do nothing if the list is empty } warpToNextSample(false); @@ -334,11 +333,10 @@ void ImportView::DrawView() { // Loop through visible files in the list for (size_t i = topIndex_; - i < topIndex_ + LIST_PAGE_SIZE && (i < MemoryPool::fileIndexList.size()); - i++) { + i < topIndex_ + LIST_PAGE_SIZE && (i < fileIndexList_.size()); i++) { props.invert_ = false; - unsigned fileIndex = MemoryPool::fileIndexList[i]; + unsigned fileIndex = fileIndexList_[i]; etl::string displayName; if (fs->getFileType(fileIndex) != PFT_DIR) { @@ -435,7 +433,7 @@ void ImportView::DrawView() { npf_snprintf(volField, sizeof(volField), "Vol:%2d", previewVolume); DrawString(x + 23, y, volField, props); } else { - if (MemoryPool::fileIndexList.empty()) { + if (fileIndexList_.empty()) { // draw this a few lines down from *top* of screen SetColor(CD_NORMAL); props.invert_ = false; @@ -555,7 +553,7 @@ void ImportView::warpToNextSample(bool goUp) { } } } else { - if (currentIndex_ < MemoryPool::fileIndexList.size() - 1) { + if (currentIndex_ < fileIndexList_.size() - 1) { currentIndex_++; // if we have scrolled off the bottom, page the file list down if not // at end of the list @@ -569,7 +567,7 @@ void ImportView::warpToNextSample(bool goUp) { void ImportView::preview(char *name) { auto fs = FileSystem::GetInstance(); - unsigned fileIndex = MemoryPool::fileIndexList[currentIndex_]; + unsigned fileIndex = fileIndexList_[currentIndex_]; // do not preview directories if (fs->getFileType(fileIndex) == PFT_DIR) { @@ -644,7 +642,7 @@ void ImportView::import() { auto fs = FileSystem::GetInstance(); char name[PFILENAME_SIZE]; - unsigned fileIndex = MemoryPool::fileIndexList[currentIndex_]; + unsigned fileIndex = fileIndexList_[currentIndex_]; fs->getFileName(fileIndex, name, PFILENAME_SIZE); // Get current project name @@ -899,15 +897,14 @@ void ImportView::onConfirmRemoveProjectSample(View &, ModalView &dialog) { } void ImportView::refreshFileIndexList(FileSystem *fs) { - fs->list(&MemoryPool::fileIndexList, ".wav", false, true); + fs->list(&fileIndexList_, ".wav", false, true, true); if (fs->isCurrentRoot() || inProjectSampleDir_) { - for (auto it = MemoryPool::fileIndexList.begin(); - it != MemoryPool::fileIndexList.end(); ++it) { + for (auto it = fileIndexList_.begin(); it != fileIndexList_.end(); ++it) { char entryName[PFILENAME_SIZE]; fs->getFileName(*it, entryName, PFILENAME_SIZE); if (strcmp(entryName, "..") == 0) { - MemoryPool::fileIndexList.erase(it); + fileIndexList_.erase(it); break; } } diff --git a/sources/Application/Views/ImportView.h b/sources/Application/Views/ImportView.h index d7b2aaec9..fb365333d 100644 --- a/sources/Application/Views/ImportView.h +++ b/sources/Application/Views/ImportView.h @@ -61,5 +61,6 @@ class ImportView : public ScreenView { false; // Flag to track if we're in the project's sample directory FileSystem *pendingDeleteFs_ = nullptr; char pendingDeleteFilename_[PFILENAME_SIZE] = {}; + etl::vector fileIndexList_; }; #endif diff --git a/sources/Application/Views/InstrumentImportView.cpp b/sources/Application/Views/InstrumentImportView.cpp index a77285eae..771107ea0 100644 --- a/sources/Application/Views/InstrumentImportView.cpp +++ b/sources/Application/Views/InstrumentImportView.cpp @@ -11,7 +11,6 @@ #include "Application/AppWindow.h" #include "Application/Instruments/I_Instrument.h" #include "Application/Persistency/PersistencyService.h" -#include "Application/Utils/MemoryPool.h" #include "ModalDialogs/MessageBox.h" #include #include @@ -33,7 +32,7 @@ void InstrumentImportView::Reset() { currentIndex_ = 0; selected_ = 0; toInstrID_ = 0; - MemoryPool::fileIndexList.clear(); + fileIndexList_.clear(); } void InstrumentImportView::ProcessButtonMask(unsigned short mask, @@ -45,8 +44,8 @@ void InstrumentImportView::ProcessButtonMask(unsigned short mask, auto fs = FileSystem::GetInstance(); char name[PFILENAME_SIZE]; - if (currentIndex_ < MemoryPool::fileIndexList.size()) { - unsigned fileIndex = MemoryPool::fileIndexList[currentIndex_]; + if (currentIndex_ < fileIndexList_.size()) { + unsigned fileIndex = fileIndexList_[currentIndex_]; fs->getFileName(fileIndex, name, PFILENAME_SIZE); if (mask & EPBM_ALT) { @@ -75,8 +74,8 @@ void InstrumentImportView::ProcessButtonMask(unsigned short mask, if (mask & EPBM_ENTER) { auto fs = FileSystem::GetInstance(); - if (currentIndex_ < MemoryPool::fileIndexList.size()) { - unsigned fileIndex = MemoryPool::fileIndexList[currentIndex_]; + if (currentIndex_ < fileIndexList_.size()) { + unsigned fileIndex = fileIndexList_[currentIndex_]; char name[PFILENAME_SIZE]; fs->getFileName(fileIndex, name, PFILENAME_SIZE); @@ -116,8 +115,7 @@ void InstrumentImportView::DrawView() { // than buffer but instead returns empty string in buffer :-( char buffer[PFILENAME_SIZE]; for (size_t i = topIndex_; - i < topIndex_ + LIST_PAGE_SIZE && (i < MemoryPool::fileIndexList.size()); - i++) { + i < topIndex_ + LIST_PAGE_SIZE && (i < fileIndexList_.size()); i++) { if (i == currentIndex_) { SetColor(CD_HILITE2); props.invert_ = true; @@ -127,7 +125,7 @@ void InstrumentImportView::DrawView() { } memset(buffer, '\0', sizeof(buffer)); - unsigned fileIndex = MemoryPool::fileIndexList[i]; + unsigned fileIndex = fileIndexList_[i]; fs->getFileName(fileIndex, buffer, PFILENAME_SIZE); if (fs->getFileType(fileIndex) == PFT_DIR) { @@ -153,7 +151,7 @@ void InstrumentImportView::OnFocus() { } void InstrumentImportView::warpToNextInstrument(bool goUp) { - if (MemoryPool::fileIndexList.empty()) + if (fileIndexList_.empty()) return; if (goUp) { @@ -164,7 +162,7 @@ void InstrumentImportView::warpToNextInstrument(bool goUp) { } } } else { - if (currentIndex_ < MemoryPool::fileIndexList.size() - 1) { + if (currentIndex_ < fileIndexList_.size() - 1) { currentIndex_++; if (currentIndex_ >= topIndex_ + LIST_PAGE_SIZE) { topIndex_ = currentIndex_ - LIST_PAGE_SIZE + 1; @@ -344,9 +342,8 @@ void InstrumentImportView::setCurrentFolder(FileSystem *fs, const char *name) { isDirty_ = true; // Update list of file indexes in this new dir - MemoryPool::fileIndexList.clear(); + fileIndexList_.clear(); // Use false for subDirOnly to include both files and directories - fs->list(&MemoryPool::fileIndexList, INSTRUMENT_FILE_EXTENSION, false, true); - Trace::Debug("loaded %d files from %s", MemoryPool::fileIndexList.size(), - name); + fs->list(&fileIndexList_, INSTRUMENT_FILE_EXTENSION, false, true, true); + Trace::Debug("loaded %d files from %s", fileIndexList_.size(), name); } diff --git a/sources/Application/Views/InstrumentImportView.h b/sources/Application/Views/InstrumentImportView.h index d22b88b02..ae0eba615 100644 --- a/sources/Application/Views/InstrumentImportView.h +++ b/sources/Application/Views/InstrumentImportView.h @@ -33,6 +33,7 @@ class InstrumentImportView : public ScreenView { private: void onImportSuccess(View &view, ModalView &dialog); + etl::vector fileIndexList_; size_t topIndex_ = 0; size_t currentIndex_ = 0; short selected_ = 0; diff --git a/sources/Application/Views/SelectProjectView.cpp b/sources/Application/Views/SelectProjectView.cpp index 27414dd47..219264eff 100644 --- a/sources/Application/Views/SelectProjectView.cpp +++ b/sources/Application/Views/SelectProjectView.cpp @@ -191,7 +191,7 @@ void SelectProjectView::Reset() { topIndex_ = 0; currentIndex_ = 0; selection_[0] = '\0'; - MemoryPool::fileIndexList.clear(); + fileIndexList_.clear(); } void SelectProjectView::DrawView() { @@ -218,8 +218,7 @@ void SelectProjectView::DrawView() { const char *currentProject = projectName.c_str(); for (size_t i = topIndex_; - i < topIndex_ + LIST_PAGE_SIZE && (i < MemoryPool::fileIndexList.size()); - i++) { + i < topIndex_ + LIST_PAGE_SIZE && (i < fileIndexList_.size()); i++) { if (i == currentIndex_) { SetColor(CD_HILITE2); props.invert_ = true; @@ -230,7 +229,7 @@ void SelectProjectView::DrawView() { char buffer[MAX_PROJECT_NAME_LENGTH + 1]; memset(buffer, '\0', sizeof(buffer)); - unsigned fileIndex = MemoryPool::fileIndexList[i]; + unsigned fileIndex = fileIndexList_[i]; if (fs->getFileType(fileIndex) == PFT_DIR) { fs->getFileName(fileIndex, buffer, MAX_PROJECT_NAME_LENGTH + 1); @@ -269,7 +268,7 @@ void SelectProjectView::DrawView() { }; void SelectProjectView::DrawScrollBar() { - int totalItems = MemoryPool::fileIndexList.size(); + int totalItems = fileIndexList_.size(); if (totalItems <= LIST_PAGE_SIZE) { return; // no scrollbar needed } @@ -366,7 +365,7 @@ void SelectProjectView::warpToNextProject(bool goUp) { } } } else { - if (currentIndex_ < MemoryPool::fileIndexList.size() - 1) { + if (currentIndex_ < fileIndexList_.size() - 1) { currentIndex_++; // if we have scrolled off the bottom, page the file list down if not // at end of the list @@ -383,14 +382,13 @@ void SelectProjectView::setCurrentFolder() { fs->chdir(PROJECTS_DIR); // get ready - MemoryPool::fileIndexList.clear(); + fileIndexList_.clear(); // Let's read all the directory in the project dir - fs->list(&MemoryPool::fileIndexList, "", true, true); + fs->list(&fileIndexList_, "", true, false, true); // Filter out "." and ".." along with the hidden default project entry - for (auto it = MemoryPool::fileIndexList.begin(); - it != MemoryPool::fileIndexList.end();) { + for (auto it = fileIndexList_.begin(); it != fileIndexList_.end();) { fs->getFileName(*it, selection_, MAX_PROJECT_NAME_LENGTH + 1); const bool isDotEntry = @@ -400,16 +398,16 @@ void SelectProjectView::setCurrentFolder() { if (isDotEntry || isUntitled) { if (isUntitled) { Trace::Log("SELECTPROJECTVIEW", "skipping untitled project on Index:%d", - static_cast(it - MemoryPool::fileIndexList.begin())); + static_cast(it - fileIndexList_.begin())); } - it = MemoryPool::fileIndexList.erase(it); + it = fileIndexList_.erase(it); } else { ++it; } } // reset & redraw screen - currentIndex_ = std::min(currentIndex_, MemoryPool::fileIndexList.size() - 1); + currentIndex_ = std::min(currentIndex_, fileIndexList_.size() - 1); topIndex_ = 0; currentIndex_ = 0; isDirty_ = true; @@ -426,7 +424,7 @@ void SelectProjectView::getHighlightedProjectName(char *name) { } auto fs = FileSystem::GetInstance(); - unsigned fileIndex = MemoryPool::fileIndexList[currentIndex_]; + unsigned fileIndex = fileIndexList_[currentIndex_]; fs->getFileName(fileIndex, name, MAX_PROJECT_NAME_LENGTH + 1); } @@ -436,12 +434,12 @@ void SelectProjectView::SelectButton(int direction) { } void SelectProjectView::LoadProject() { - if (currentIndex_ >= MemoryPool::fileIndexList.size()) { + if (currentIndex_ >= fileIndexList_.size()) { return; } // all subdirs directly inside /project are expected to be projects - unsigned fileIndex = MemoryPool::fileIndexList[currentIndex_]; + unsigned fileIndex = fileIndexList_[currentIndex_]; auto fs = FileSystem::GetInstance(); fs->getFileName(fileIndex, selection_, MAX_PROJECT_NAME_LENGTH + 1); if (strlen(selection_) == 0) { @@ -478,7 +476,7 @@ bool SelectProjectView::SelectionIsCurrentProject() { } void SelectProjectView::AttemptDeletingSelectedProject() { - if (currentIndex_ >= MemoryPool::fileIndexList.size()) { + if (currentIndex_ >= fileIndexList_.size()) { return; } diff --git a/sources/Application/Views/SelectProjectView.h b/sources/Application/Views/SelectProjectView.h index da45604e1..ea5db897c 100644 --- a/sources/Application/Views/SelectProjectView.h +++ b/sources/Application/Views/SelectProjectView.h @@ -40,6 +40,7 @@ class SelectProjectView : public ScreenView { size_t currentIndex_ = 0; char selection_[MAX_PROJECT_NAME_LENGTH + 1]; int selectedButton_ = 0; + etl::vector fileIndexList_; void DrawScrollBar(); void AttemptDeletingSelectedProject(); diff --git a/sources/Application/Views/ThemeImportView.cpp b/sources/Application/Views/ThemeImportView.cpp index 7059a469d..f92217c4a 100644 --- a/sources/Application/Views/ThemeImportView.cpp +++ b/sources/Application/Views/ThemeImportView.cpp @@ -11,7 +11,6 @@ #include "Application/AppWindow.h" #include "Application/Model/Config.h" #include "Application/Persistency/PersistenceConstants.h" -#include "Application/Utils/MemoryPool.h" #include "Application/Views/ModalDialogs/MessageBox.h" #include "ModalDialogs/MessageBox.h" #include "System/Console/Trace.h" @@ -31,7 +30,7 @@ ThemeImportView::~ThemeImportView() {} void ThemeImportView::Reset() { topIndex_ = 0; currentIndex_ = 0; - MemoryPool::fileIndexList.clear(); + fileIndexList_.clear(); } void ThemeImportView::ProcessButtonMask(unsigned short mask, bool pressed) { @@ -42,8 +41,8 @@ void ThemeImportView::ProcessButtonMask(unsigned short mask, bool pressed) { auto fs = FileSystem::GetInstance(); char name[PFILENAME_SIZE]; - if (currentIndex_ < MemoryPool::fileIndexList.size()) { - unsigned fileIndex = MemoryPool::fileIndexList[currentIndex_]; + if (currentIndex_ < fileIndexList_.size()) { + unsigned fileIndex = fileIndexList_[currentIndex_]; fs->getFileName(fileIndex, name, PFILENAME_SIZE); if (mask & EPBM_ALT) { @@ -69,8 +68,8 @@ void ThemeImportView::ProcessButtonMask(unsigned short mask, bool pressed) { if (mask & EPBM_ENTER) { auto fs = FileSystem::GetInstance(); - if (currentIndex_ < MemoryPool::fileIndexList.size()) { - unsigned fileIndex = MemoryPool::fileIndexList[currentIndex_]; + if (currentIndex_ < fileIndexList_.size()) { + unsigned fileIndex = fileIndexList_[currentIndex_]; char name[PFILENAME_SIZE]; fs->getFileName(fileIndex, name, PFILENAME_SIZE); @@ -113,8 +112,7 @@ void ThemeImportView::DrawView() { // than buffer but instead returns empty string in buffer :-( char buffer[PFILENAME_SIZE]; for (size_t i = topIndex_; - i < topIndex_ + LIST_PAGE_SIZE && (i < MemoryPool::fileIndexList.size()); - i++) { + i < topIndex_ + LIST_PAGE_SIZE && (i < fileIndexList_.size()); i++) { if (i == currentIndex_) { SetColor(CD_HILITE2); props.invert_ = true; @@ -124,7 +122,7 @@ void ThemeImportView::DrawView() { } memset(buffer, '\0', sizeof(buffer)); - unsigned fileIndex = MemoryPool::fileIndexList[i]; + unsigned fileIndex = fileIndexList_[i]; fs->getFileName(fileIndex, buffer, PFILENAME_SIZE); if (fs->getFileType(fileIndex) == PFT_DIR) { @@ -155,7 +153,7 @@ void ThemeImportView::OnFocus() { } void ThemeImportView::warpToNextTheme(bool goUp) { - if (MemoryPool::fileIndexList.empty()) + if (fileIndexList_.empty()) return; if (goUp) { @@ -168,7 +166,7 @@ void ThemeImportView::warpToNextTheme(bool goUp) { } } } else { - if (currentIndex_ < MemoryPool::fileIndexList.size() - 1) { + if (currentIndex_ < fileIndexList_.size() - 1) { currentIndex_++; // if we have scrolled off the bottom, page the file list down if not // at end of the list @@ -236,9 +234,8 @@ void ThemeImportView::setCurrentFolder(FileSystem *fs, const char *name) { isDirty_ = true; // Update list of file indexes in this new dir - MemoryPool::fileIndexList.clear(); + fileIndexList_.clear(); // Use false for subDirOnly to include both files and directories - fs->list(&MemoryPool::fileIndexList, THEME_FILE_EXTENSION, false, true); - Trace::Debug("loaded %d files from %s", MemoryPool::fileIndexList.size(), - name); + fs->list(&fileIndexList_, THEME_FILE_EXTENSION, false, true, true); + Trace::Debug("loaded %d files from %s", fileIndexList_.size(), name); } diff --git a/sources/Application/Views/ThemeImportView.h b/sources/Application/Views/ThemeImportView.h index 022a7c6e4..2bb4197cb 100644 --- a/sources/Application/Views/ThemeImportView.h +++ b/sources/Application/Views/ThemeImportView.h @@ -35,5 +35,6 @@ class ThemeImportView : public ScreenView { size_t topIndex_ = 0; size_t currentIndex_ = 0; + etl::vector fileIndexList_; }; #endif From 0e70ed030fea5deebe03a353bc74168924ed91fe Mon Sep 17 00:00:00 2001 From: nILS Date: Wed, 8 Apr 2026 20:25:42 +0200 Subject: [PATCH 8/9] consolidates bool parameters into a single bitfield --- sources/Adapters/adv/filesystem/advFileSystem.cpp | 5 ++++- sources/Adapters/adv/filesystem/advFileSystem.h | 3 +-- sources/Adapters/adv/gui/SerialDebugUI.cpp | 2 +- .../picoTracker/filesystem/picoTrackerFileSystem.cpp | 6 ++++-- .../picoTracker/filesystem/picoTrackerFileSystem.h | 3 +-- sources/Adapters/picoTracker/gui/SerialDebugUI.cpp | 2 +- sources/Application/Instruments/SamplePool.cpp | 2 +- sources/Application/Persistency/PersistencyService.cpp | 4 ++-- sources/Application/Views/ImportView.cpp | 2 +- sources/Application/Views/InstrumentImportView.cpp | 3 ++- sources/Application/Views/SelectProjectView.cpp | 2 +- sources/Application/Views/ThemeImportView.cpp | 2 +- sources/System/FileSystem/FileSystem.h | 10 ++++++++-- 13 files changed, 28 insertions(+), 18 deletions(-) diff --git a/sources/Adapters/adv/filesystem/advFileSystem.cpp b/sources/Adapters/adv/filesystem/advFileSystem.cpp index e49cad69b..72b7e9e18 100644 --- a/sources/Adapters/adv/filesystem/advFileSystem.cpp +++ b/sources/Adapters/adv/filesystem/advFileSystem.cpp @@ -133,7 +133,10 @@ PicoFileType advFileSystem::getFileType(int index) { } void advFileSystem::list(etl::ivector *fileIndexes, const char *filter, - bool subDirOnly, bool includeHidden, bool sorted) { + ListFlags flags) { + bool subDirOnly = flags & LF_SUBDIRS_ONLY; + bool includeHidden = flags & LF_INCLUDE_HIDDEN; + bool sorted = flags & LF_SORTED; fileIndexes->clear(); diff --git a/sources/Adapters/adv/filesystem/advFileSystem.h b/sources/Adapters/adv/filesystem/advFileSystem.h index 78aed8ad8..ec3ea3597 100644 --- a/sources/Adapters/adv/filesystem/advFileSystem.h +++ b/sources/Adapters/adv/filesystem/advFileSystem.h @@ -51,8 +51,7 @@ class advFileSystem : public FileSystem { virtual FileHandle Open(const char *name, const char *mode) override; virtual bool chdir(const char *path) override; virtual void list(etl::ivector *fileIndexes, const char *filter, - bool subDirOnly, bool includeHidden = false, - bool sorted = false) override; + ListFlags flags) override; virtual void getFileName(int index, char *name, int length) override; virtual PicoFileType getFileType(int index) override; virtual bool isParentRoot() override; diff --git a/sources/Adapters/adv/gui/SerialDebugUI.cpp b/sources/Adapters/adv/gui/SerialDebugUI.cpp index 3c193f702..cb4b69b9b 100644 --- a/sources/Adapters/adv/gui/SerialDebugUI.cpp +++ b/sources/Adapters/adv/gui/SerialDebugUI.cpp @@ -199,7 +199,7 @@ void SerialDebugUI::listFiles(const char *path) { Trace::Error("failed to ls files path:%s", path); } - fs->list(&fileIndexList_, "", false, false, true); + fs->list(&fileIndexList_, "", LF_SORTED); // No need to actually do the printing below for now as the current debug code // in PicoFileSystem class is already printing all the files fetched when the diff --git a/sources/Adapters/picoTracker/filesystem/picoTrackerFileSystem.cpp b/sources/Adapters/picoTracker/filesystem/picoTrackerFileSystem.cpp index cc8c6dd0f..4a91b38e7 100644 --- a/sources/Adapters/picoTracker/filesystem/picoTrackerFileSystem.cpp +++ b/sources/Adapters/picoTracker/filesystem/picoTrackerFileSystem.cpp @@ -121,8 +121,10 @@ PicoFileType picoTrackerFileSystem::getFileType(int index) { } void picoTrackerFileSystem::list(etl::ivector *fileIndexes, - const char *filter, bool subDirOnly, - bool includeHidden, bool sorted) { + const char *filter, ListFlags flags) { + bool subDirOnly = flags & LF_SUBDIRS_ONLY; + bool includeHidden = flags & LF_INCLUDE_HIDDEN; + bool sorted = flags & LF_SORTED; std::lock_guard lock(mutex); fileIndexes->clear(); diff --git a/sources/Adapters/picoTracker/filesystem/picoTrackerFileSystem.h b/sources/Adapters/picoTracker/filesystem/picoTrackerFileSystem.h index 384d952dd..43b7fb7ae 100644 --- a/sources/Adapters/picoTracker/filesystem/picoTrackerFileSystem.h +++ b/sources/Adapters/picoTracker/filesystem/picoTrackerFileSystem.h @@ -31,8 +31,7 @@ class picoTrackerFileSystem : public FileSystem { virtual FileHandle Open(const char *name, const char *mode) override; virtual bool chdir(const char *path) override; virtual void list(etl::ivector *fileIndexes, const char *filter, - bool subDirOnly, bool includeHidden = false, - bool sorted = false) override; + ListFlags flags) override; virtual void getFileName(int index, char *name, int length) override; virtual PicoFileType getFileType(int index) override; virtual bool isParentRoot() override; diff --git a/sources/Adapters/picoTracker/gui/SerialDebugUI.cpp b/sources/Adapters/picoTracker/gui/SerialDebugUI.cpp index c25f5a9f9..009a3c36a 100644 --- a/sources/Adapters/picoTracker/gui/SerialDebugUI.cpp +++ b/sources/Adapters/picoTracker/gui/SerialDebugUI.cpp @@ -136,7 +136,7 @@ void SerialDebugUI::listFiles(const char *path) { } etl::vector fileIndexList_; - fs->list(&fileIndexList_, "", false, false, true); + fs->list(&fileIndexList_, "", LF_SORTED); char name[PFILENAME_SIZE]; for (size_t i = 0; i < fileIndexList_.size(); i++) { diff --git a/sources/Application/Instruments/SamplePool.cpp b/sources/Application/Instruments/SamplePool.cpp index e0182b13e..800cfc549 100644 --- a/sources/Application/Instruments/SamplePool.cpp +++ b/sources/Application/Instruments/SamplePool.cpp @@ -57,7 +57,7 @@ void SamplePool::Load(const char *projectName) { PROJECT_SAMPLES_DIR); } // First, find all wav files - fs->list(&fileIndexList_, ".wav", false, false, true); + fs->list(&fileIndexList_, ".wav", LF_SORTED); char name[PFILENAME_SIZE]; uint totalSamples = fileIndexList_.size(); diff --git a/sources/Application/Persistency/PersistencyService.cpp b/sources/Application/Persistency/PersistencyService.cpp index 733dc669b..311501ae3 100644 --- a/sources/Application/Persistency/PersistencyService.cpp +++ b/sources/Application/Persistency/PersistencyService.cpp @@ -78,7 +78,7 @@ bool PersistencyService::DeleteDirectoryContents_(uint8_t depth) { while (true) { fileIndexList_.clear(); - fs->list(&fileIndexList_, "", false, true); + fs->list(&fileIndexList_, "", LF_INCLUDE_HIDDEN); bool foundEntry = false; bool deletedEntry = false; @@ -193,7 +193,7 @@ PersistencyResult PersistencyService::Save(const char *projectName, Trace::Debug("get list of samples to copy from old project: %s", oldProjectName); - fs->list(&fileIndexList_, ".wav", false); + fs->list(&fileIndexList_, ".wav"); char filenameBuffer[PFILENAME_SIZE]; for (size_t i = 0; i < fileIndexList_.size(); i++) { fs->getFileName(fileIndexList_[i], filenameBuffer, diff --git a/sources/Application/Views/ImportView.cpp b/sources/Application/Views/ImportView.cpp index 127819d67..965136308 100644 --- a/sources/Application/Views/ImportView.cpp +++ b/sources/Application/Views/ImportView.cpp @@ -897,7 +897,7 @@ void ImportView::onConfirmRemoveProjectSample(View &, ModalView &dialog) { } void ImportView::refreshFileIndexList(FileSystem *fs) { - fs->list(&fileIndexList_, ".wav", false, true, true); + fs->list(&fileIndexList_, ".wav", (ListFlags)(LF_INCLUDE_HIDDEN | LF_SORTED)); if (fs->isCurrentRoot() || inProjectSampleDir_) { for (auto it = fileIndexList_.begin(); it != fileIndexList_.end(); ++it) { diff --git a/sources/Application/Views/InstrumentImportView.cpp b/sources/Application/Views/InstrumentImportView.cpp index 771107ea0..989a6482f 100644 --- a/sources/Application/Views/InstrumentImportView.cpp +++ b/sources/Application/Views/InstrumentImportView.cpp @@ -344,6 +344,7 @@ void InstrumentImportView::setCurrentFolder(FileSystem *fs, const char *name) { // Update list of file indexes in this new dir fileIndexList_.clear(); // Use false for subDirOnly to include both files and directories - fs->list(&fileIndexList_, INSTRUMENT_FILE_EXTENSION, false, true, true); + fs->list(&fileIndexList_, INSTRUMENT_FILE_EXTENSION, + (ListFlags)(LF_INCLUDE_HIDDEN | LF_SORTED)); Trace::Debug("loaded %d files from %s", fileIndexList_.size(), name); } diff --git a/sources/Application/Views/SelectProjectView.cpp b/sources/Application/Views/SelectProjectView.cpp index cfb22cb38..0dda1292a 100644 --- a/sources/Application/Views/SelectProjectView.cpp +++ b/sources/Application/Views/SelectProjectView.cpp @@ -356,7 +356,7 @@ void SelectProjectView::setCurrentFolder() { fileIndexList_.clear(); // Let's read all the directory in the project dir - fs->list(&fileIndexList_, "", true, false, true); + fs->list(&fileIndexList_, "", (ListFlags)(LF_SUBDIRS_ONLY | LF_SORTED)); // Filter out "." and ".." along with the hidden default project entry for (auto it = fileIndexList_.begin(); it != fileIndexList_.end();) { diff --git a/sources/Application/Views/ThemeImportView.cpp b/sources/Application/Views/ThemeImportView.cpp index 3df16f95a..3d5bdbaee 100644 --- a/sources/Application/Views/ThemeImportView.cpp +++ b/sources/Application/Views/ThemeImportView.cpp @@ -206,7 +206,7 @@ void ThemeImportView::setCurrentFolder() { isDirty_ = true; // get the directory listing - fs->list(&fileIndexList_, THEME_FILE_EXTENSION, false); + fs->list(&fileIndexList_, THEME_FILE_EXTENSION); // remove directories from listing for (int i = fileIndexList_.size() - 1; i >= 0; i--) { diff --git a/sources/System/FileSystem/FileSystem.h b/sources/System/FileSystem/FileSystem.h index 100d4569e..09792866c 100644 --- a/sources/System/FileSystem/FileSystem.h +++ b/sources/System/FileSystem/FileSystem.h @@ -21,6 +21,13 @@ enum PicoFileType { PFT_UNKNOWN, PFT_FILE, PFT_DIR }; +enum ListFlags { + LF_NONE = 0, + LF_SUBDIRS_ONLY = 1 << 0, + LF_INCLUDE_HIDDEN = 1 << 1, + LF_SORTED = 1 << 2, +}; + // Forward declaration class I_File; @@ -37,8 +44,7 @@ class FileSystem : public T_Factory { return false; } // Default implementation virtual void list(etl::ivector *fileIndexes, const char *filter, - bool subDirOnly, bool includeHidden = false, - bool sorted = false) = 0; + ListFlags flags = LF_NONE) = 0; virtual void getFileName(int index, char *name, int length) = 0; virtual PicoFileType getFileType(int index) = 0; virtual bool isParentRoot() = 0; From 622b0d22e1be35dfd5a82dfc439e0a4402c08c05 Mon Sep 17 00:00:00 2001 From: nILS Date: Wed, 8 Apr 2026 20:28:14 +0200 Subject: [PATCH 9/9] reverted cleanup --- sources/Application/Views/BaseClasses/UIIntField.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sources/Application/Views/BaseClasses/UIIntField.h b/sources/Application/Views/BaseClasses/UIIntField.h index 2ca645af7..3f3b41b9a 100644 --- a/sources/Application/Views/BaseClasses/UIIntField.h +++ b/sources/Application/Views/BaseClasses/UIIntField.h @@ -18,7 +18,7 @@ class UIIntField : public UIField { UIIntField(const GUIPoint &position, int *src, const char *format, int min, int max, int xOffset, int yOffset); virtual ~UIIntField(){}; - virtual void Draw(GUIWindow &w, int offset = 0) override; + virtual void Draw(GUIWindow &w); virtual void ProcessArrow(unsigned short mask); virtual void OnClick(){};