From 605d0b9c8cc47e172b0a49bc4f3252aa522e95aa Mon Sep 17 00:00:00 2001 From: Alex Woznyuk Date: Tue, 19 Mar 2024 19:25:06 +0000 Subject: [PATCH] not enough stack, let's use heap instead(sdBrowserMenu) (#8) keira: allow more than 32 items in sdBrowserMenu keira: use unique_ptr to track Entry[] allocation lib: add getEntryCount --- firmware/keira/src/apps/launcher.cpp | 42 ++++++++++++++-------------- sdk/lib/lilka/src/lilka/sdcard.cpp | 31 ++++++++++++++++++++ sdk/lib/lilka/src/lilka/sdcard.h | 1 + 3 files changed, 53 insertions(+), 21 deletions(-) diff --git a/firmware/keira/src/apps/launcher.cpp b/firmware/keira/src/apps/launcher.cpp index b3b5bd4d..b82902b1 100644 --- a/firmware/keira/src/apps/launcher.cpp +++ b/firmware/keira/src/apps/launcher.cpp @@ -143,34 +143,34 @@ void LauncherApp::sdBrowserMenu(String path) { if (!lilka::sdcard.available()) { alert("Помилка", "SD-карта не знайдена"); } + size_t _numEntries = lilka::sdcard.getEntryCount(path); + if (_numEntries == 0) { + alert("Помилка", "Директорія пуста або сталася помилка читання директорії"); + return; + } + + lilka::Entry* entries = new lilka::Entry[_numEntries]; - lilka::Entry entries - [32]; // TODO - allocate dynamically (increasing to 64 causes task stack overflow which is limited by ARDUINO_LOOP_STACK_SIZE) int numEntries = lilka::sdcard.listDir(path, entries); + std::unique_ptr entriesPtr(entries); - if (numEntries == -1) { - // lilka::ui_alert(canvas, "Помилка", "Не вдалося прочитати директорію"); + // Так як listDir має повертати -1 в разі помилки + // а countFilesIndir size_t >= 0 додаткові перевірки не потрібні + if (_numEntries != numEntries) { alert("Помилка", "Не вдалося прочитати директорію"); return; } - String filenames[32]; - const menu_icon_t* icons[32]; - uint16_t colors[32]; - for (int i = 0; i < numEntries; i++) { - filenames[i] = entries[i].name; - icons[i] = entries[i].type == lilka::EntryType::ENT_DIRECTORY ? &folder : get_file_icon(filenames[i]); - colors[i] = entries[i].type == lilka::EntryType::ENT_DIRECTORY ? lilka::display.color565(255, 255, 200) - : get_file_color(filenames[i]); - } - filenames[numEntries++] = "<< Назад"; - icons[numEntries - 1] = 0; - colors[numEntries - 1] = 0; - lilka::Menu menu("SD: " + path); for (int i = 0; i < numEntries; i++) { - menu.addItem(filenames[i], icons[i], colors[i]); + String filename = entries[i].name; + const menu_icon_t* icon = + entries[i].type == lilka::EntryType::ENT_DIRECTORY ? &folder : get_file_icon(filename); + uint16_t color = entries[i].type == lilka::EntryType::ENT_DIRECTORY ? lilka::display.color565(255, 255, 200) + : get_file_color(filename); + menu.addItem(filename, icon, color); } + menu.addItem("<< Назад", 0, 0); while (1) { menu.update(); @@ -178,9 +178,7 @@ void LauncherApp::sdBrowserMenu(String path) { queueDraw(); int16_t index = menu.getSelectedIndex(); if (index != -1) { - if (index == numEntries - 1) { - return; - } + if (index >= numEntries - 1) break; if (entries[index].type == lilka::EntryType::ENT_DIRECTORY) { sdBrowserMenu(path + entries[index].name + "/"); } else { @@ -189,6 +187,8 @@ void LauncherApp::sdBrowserMenu(String path) { } taskYIELD(); } + + return; } void LauncherApp::spiffsBrowserMenu() { diff --git a/sdk/lib/lilka/src/lilka/sdcard.cpp b/sdk/lib/lilka/src/lilka/sdcard.cpp index 17336132..9d7658b4 100644 --- a/sdk/lib/lilka/src/lilka/sdcard.cpp +++ b/sdk/lib/lilka/src/lilka/sdcard.cpp @@ -89,6 +89,37 @@ int SDCard::listDir(String path, Entry entries[]) { return i; } +size_t SDCard::getEntryCount(String path) { + size_t countFiles = 0; + + while (!path.equals("/") && path.endsWith("/")) { + // Strip trailing slashes, unless it's the root directory + path.remove(path.length() - 1); + } + File root = fs->open(path); + // Below we assume if folder can't be open then it has zero files + // Btw we will show this error using serial + if (!root) { + serial_err("%s:%d:getEntryCount: failed to open directory: %s", __FILE__, __LINE__, path.c_str()); + return 0; + } + if (!root.isDirectory()) { + serial_err("%s:%d:getEntryCount: not a directory: %s", __FILE__, __LINE__, path.c_str()); + return 0; + } + + File file = root.openNextFile(); + + while (file) { + file = root.openNextFile(); + countFiles++; + } + + root.close(); + + return countFiles; +} + String SDCard::abspath(String filename) { while (filename.length() > 0 && filename[0] == '/') { filename = filename.substring(1); diff --git a/sdk/lib/lilka/src/lilka/sdcard.h b/sdk/lib/lilka/src/lilka/sdcard.h index a972f658..d3d70735 100644 --- a/sdk/lib/lilka/src/lilka/sdcard.h +++ b/sdk/lib/lilka/src/lilka/sdcard.h @@ -26,6 +26,7 @@ class SDCard { SDFS* fs; int listDir(String path, Entry entries[]); + size_t getEntryCount(String path); String abspath(String path); };