feat: add file manager and file browser view
This commit is contained in:
parent
3a5fb66a6f
commit
6320ba96e0
0
data/audio/some_song.mp3
Normal file
0
data/audio/some_song.mp3
Normal file
0
data/test_file.txt
Normal file
0
data/test_file.txt
Normal file
@ -285,7 +285,7 @@
|
|||||||
*LV_LOG_LEVEL_ERROR Only critical issue, when the system may fail
|
*LV_LOG_LEVEL_ERROR Only critical issue, when the system may fail
|
||||||
*LV_LOG_LEVEL_USER Only logs added by the user
|
*LV_LOG_LEVEL_USER Only logs added by the user
|
||||||
*LV_LOG_LEVEL_NONE Do not log anything*/
|
*LV_LOG_LEVEL_NONE Do not log anything*/
|
||||||
#define LV_LOG_LEVEL LV_LOG_LEVEL_INFO
|
#define LV_LOG_LEVEL LV_LOG_LEVEL_WARN
|
||||||
|
|
||||||
/*1: Print the log with 'printf';
|
/*1: Print the log with 'printf';
|
||||||
*0: User need to register a callback with `lv_log_register_print_cb()`*/
|
*0: User need to register a callback with `lv_log_register_print_cb()`*/
|
||||||
|
|||||||
@ -13,6 +13,7 @@ platform = espressif32
|
|||||||
board = esp32doit-devkit-v1
|
board = esp32doit-devkit-v1
|
||||||
framework = arduino
|
framework = arduino
|
||||||
monitor_speed = 115200
|
monitor_speed = 115200
|
||||||
|
board_build.filesystem = littlefs
|
||||||
lib_deps =
|
lib_deps =
|
||||||
ruiseixasm/Versatile_RotaryEncoder@^1.3.1
|
ruiseixasm/Versatile_RotaryEncoder@^1.3.1
|
||||||
bodmer/TFT_eSPI@^2.5.43
|
bodmer/TFT_eSPI@^2.5.43
|
||||||
|
|||||||
@ -51,10 +51,8 @@ namespace UserInputManager
|
|||||||
|
|
||||||
void pushEvent(InputEvent event)
|
void pushEvent(InputEvent event)
|
||||||
{
|
{
|
||||||
Serial.println("pushing new event " + String(event));
|
|
||||||
for (auto &queue : input_event_queues)
|
for (auto &queue : input_event_queues)
|
||||||
{
|
{
|
||||||
Serial.println("pushing event to queue " + queue.first + " (" + String(queue.second.size()) + ")");
|
|
||||||
queue.second.push(event);
|
queue.second.push(event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -15,6 +15,7 @@
|
|||||||
#include <input/pad_reader.hpp>
|
#include <input/pad_reader.hpp>
|
||||||
#include <input/user_input_manager.hpp>
|
#include <input/user_input_manager.hpp>
|
||||||
#include <audio/tone_generator.hpp>
|
#include <audio/tone_generator.hpp>
|
||||||
|
#include <tools/file_manager.hpp>
|
||||||
|
|
||||||
const int ONBOARD_LED_PIN = 2;
|
const int ONBOARD_LED_PIN = 2;
|
||||||
|
|
||||||
@ -25,6 +26,7 @@ void setup()
|
|||||||
|
|
||||||
PadReader::init();
|
PadReader::init();
|
||||||
Encoder::init();
|
Encoder::init();
|
||||||
|
FileManager::init();
|
||||||
Display::init();
|
Display::init();
|
||||||
ToneGenerator::init();
|
ToneGenerator::init();
|
||||||
UserInputManager::init();
|
UserInputManager::init();
|
||||||
|
|||||||
47
src/tools/file_manager.cpp
Normal file
47
src/tools/file_manager.cpp
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
#include <Arduino.h>
|
||||||
|
#include <LittleFS.h>
|
||||||
|
|
||||||
|
#include <tools/file_manager.hpp>
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace FileManager
|
||||||
|
{
|
||||||
|
using std::vector;
|
||||||
|
|
||||||
|
void init()
|
||||||
|
{
|
||||||
|
if (!LittleFS.begin())
|
||||||
|
{
|
||||||
|
Serial.println("LittleFS Mount Failed");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
vector<File> listFiles(const String path)
|
||||||
|
{
|
||||||
|
vector<File> files;
|
||||||
|
|
||||||
|
fs::File root = LittleFS.open(path, "r");
|
||||||
|
if (!root)
|
||||||
|
{
|
||||||
|
Serial.println("Failed to open root directory");
|
||||||
|
}
|
||||||
|
if (!root.isDirectory())
|
||||||
|
{
|
||||||
|
Serial.println("Root is not a directory");
|
||||||
|
}
|
||||||
|
|
||||||
|
fs::File fsFile = root.openNextFile();
|
||||||
|
while (fsFile)
|
||||||
|
{
|
||||||
|
File file;
|
||||||
|
file.name = fsFile.name();
|
||||||
|
file.isDirectory = fsFile.isDirectory();
|
||||||
|
files.push_back(file);
|
||||||
|
fsFile = root.openNextFile();
|
||||||
|
}
|
||||||
|
|
||||||
|
return files;
|
||||||
|
}
|
||||||
|
}
|
||||||
21
src/tools/file_manager.hpp
Normal file
21
src/tools/file_manager.hpp
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
#ifndef DRUMZ_TOOLS_FILE_MANAGER
|
||||||
|
#define DRUMZ_TOOLS_FILE_MANAGER
|
||||||
|
|
||||||
|
#include <Arduino.h>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace FileManager
|
||||||
|
{
|
||||||
|
using std::vector;
|
||||||
|
|
||||||
|
struct File
|
||||||
|
{
|
||||||
|
String name;
|
||||||
|
bool isDirectory;
|
||||||
|
};
|
||||||
|
|
||||||
|
void init();
|
||||||
|
vector<File> listFiles(const String path);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif //DRUMZ_TOOLS_FILE_MANAGER
|
||||||
@ -167,22 +167,18 @@ namespace Display
|
|||||||
case InputEvent::EncoderButtonRelease:
|
case InputEvent::EncoderButtonRelease:
|
||||||
data->key = LV_KEY_ENTER;
|
data->key = LV_KEY_ENTER;
|
||||||
data->state = LV_INDEV_STATE_RELEASED;
|
data->state = LV_INDEV_STATE_RELEASED;
|
||||||
Serial.println("indev event EncoderButtonRelease");
|
|
||||||
break;
|
break;
|
||||||
case InputEvent::EncoderButtonPress:
|
case InputEvent::EncoderButtonPress:
|
||||||
data->key = LV_KEY_ENTER;
|
data->key = LV_KEY_ENTER;
|
||||||
data->state = LV_INDEV_STATE_PRESSED;
|
data->state = LV_INDEV_STATE_PRESSED;
|
||||||
Serial.println("indev event EncoderButtonPress");
|
|
||||||
break;
|
break;
|
||||||
case InputEvent::EncoderRotateLeft:
|
case InputEvent::EncoderRotateLeft:
|
||||||
data->key = LV_KEY_PREV;
|
data->key = LV_KEY_PREV;
|
||||||
data->state = LV_INDEV_STATE_PRESSED;
|
data->state = LV_INDEV_STATE_PRESSED;
|
||||||
Serial.println("indev event EncoderRotateLeft");
|
|
||||||
break;
|
break;
|
||||||
case InputEvent::EncoderRotateRight:
|
case InputEvent::EncoderRotateRight:
|
||||||
data->key = LV_KEY_NEXT;
|
data->key = LV_KEY_NEXT;
|
||||||
data->state = LV_INDEV_STATE_PRESSED;
|
data->state = LV_INDEV_STATE_PRESSED;
|
||||||
Serial.println("indev event EncoderRotateRight");
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
119
src/ui/views/file_browser_view.cpp
Normal file
119
src/ui/views/file_browser_view.cpp
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
#include <Arduino.h>
|
||||||
|
#include <lvgl.h>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include <tools/file_manager.hpp>
|
||||||
|
|
||||||
|
namespace FileBrowserView
|
||||||
|
{
|
||||||
|
using FileManager::File;
|
||||||
|
using std::vector;
|
||||||
|
|
||||||
|
void renderList(lv_obj_t *parent);
|
||||||
|
void updateList();
|
||||||
|
void changeDirRelative(String dir);
|
||||||
|
void changeDir(String dir);
|
||||||
|
|
||||||
|
static vector<File> files;
|
||||||
|
String currentDir = "/";
|
||||||
|
|
||||||
|
lv_obj_t *label;
|
||||||
|
lv_obj_t *list;
|
||||||
|
lv_obj_t *content;
|
||||||
|
lv_group_t *group;
|
||||||
|
lv_indev_t *indev;
|
||||||
|
|
||||||
|
void render(lv_obj_t *parent, lv_indev_t *newIndev)
|
||||||
|
{
|
||||||
|
indev = newIndev;
|
||||||
|
group = lv_group_create();
|
||||||
|
lv_indev_set_group(indev, group);
|
||||||
|
content = lv_obj_create(parent);
|
||||||
|
lv_obj_set_width(content, lv_pct(100));
|
||||||
|
lv_obj_set_height(content, lv_pct(100));
|
||||||
|
lv_obj_center(content);
|
||||||
|
|
||||||
|
files = FileManager::listFiles(currentDir);
|
||||||
|
lv_obj_clean(content);
|
||||||
|
renderList(parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
void update()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void renderList(lv_obj_t *parent)
|
||||||
|
{
|
||||||
|
list = lv_list_create(parent);
|
||||||
|
lv_obj_set_width(list, lv_pct(100));
|
||||||
|
lv_obj_set_height(list, lv_pct(100));
|
||||||
|
lv_obj_center(list);
|
||||||
|
updateList();
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateList()
|
||||||
|
{
|
||||||
|
lv_obj_clean(list);
|
||||||
|
|
||||||
|
lv_obj_t *btn;
|
||||||
|
if (currentDir != "/")
|
||||||
|
{
|
||||||
|
btn = lv_list_add_btn(list, LV_SYMBOL_DIRECTORY, "..");
|
||||||
|
lv_group_add_obj(group, btn);
|
||||||
|
auto callback = [](lv_event_t *event) {
|
||||||
|
changeDirRelative("..");
|
||||||
|
};
|
||||||
|
lv_obj_add_event_cb(btn, callback, LV_EVENT_CLICKED, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < files.size(); i++)
|
||||||
|
{
|
||||||
|
File file = files.at(i);
|
||||||
|
auto symbol = file.isDirectory? LV_SYMBOL_DIRECTORY : LV_SYMBOL_FILE;
|
||||||
|
btn = lv_list_add_btn(list, symbol, file.name.c_str());
|
||||||
|
lv_group_add_obj(group, btn);
|
||||||
|
|
||||||
|
auto callback = [](lv_event_t *event) {
|
||||||
|
File *file = (File *)lv_event_get_user_data(event);
|
||||||
|
if (!file->isDirectory)
|
||||||
|
return;
|
||||||
|
changeDirRelative(file->name);
|
||||||
|
};
|
||||||
|
Serial.println(file.name + "\t" + (int)&files.at(i));
|
||||||
|
lv_obj_add_event_cb(btn, callback, LV_EVENT_CLICKED, &files.at(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void changeDirRelative(String dir)
|
||||||
|
{
|
||||||
|
String newDir = currentDir;
|
||||||
|
if (dir == "..")
|
||||||
|
{
|
||||||
|
if (currentDir == "/")
|
||||||
|
return;
|
||||||
|
if (newDir.endsWith("/"))
|
||||||
|
{
|
||||||
|
newDir = newDir.substring(0, newDir.length() - 1);
|
||||||
|
}
|
||||||
|
int lastSlash = newDir.lastIndexOf("/");
|
||||||
|
if (lastSlash == -1)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
newDir = newDir.substring(0, lastSlash + 1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
newDir = newDir + dir + "/";
|
||||||
|
}
|
||||||
|
changeDir(newDir);
|
||||||
|
}
|
||||||
|
|
||||||
|
void changeDir(String dir)
|
||||||
|
{
|
||||||
|
Serial.println("changeDir: " + dir);
|
||||||
|
currentDir = dir;
|
||||||
|
files = FileManager::listFiles(currentDir);
|
||||||
|
updateList();
|
||||||
|
}
|
||||||
|
}
|
||||||
12
src/ui/views/file_browser_view.hpp
Normal file
12
src/ui/views/file_browser_view.hpp
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
#ifndef DRUMZ_VIEWS_FILE_BROWSER_VIEW
|
||||||
|
#define DRUMZ_VIEWS_FILE_BROWSER_VIEW
|
||||||
|
|
||||||
|
#include <lvgl.h>
|
||||||
|
|
||||||
|
namespace FileBrowserView
|
||||||
|
{
|
||||||
|
void update();
|
||||||
|
void render(lv_obj_t *parent, lv_indev_t *indev);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif //DRUMZ_VIEWS_FILE_BROWSER_VIEW
|
||||||
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#include <input/encoder.hpp>
|
#include <input/encoder.hpp>
|
||||||
#include <audio/tone_generator.hpp>
|
#include <audio/tone_generator.hpp>
|
||||||
|
#include <ui/views/file_browser_view.hpp>
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
@ -10,41 +11,15 @@ namespace MainView
|
|||||||
{
|
{
|
||||||
using std::vector;
|
using std::vector;
|
||||||
|
|
||||||
lv_obj_t *label;
|
|
||||||
lv_obj_t *list;
|
|
||||||
String label_text;
|
String label_text;
|
||||||
|
|
||||||
void render(lv_obj_t *parent, lv_indev_t *indev)
|
void render(lv_obj_t *parent, lv_indev_t *indev)
|
||||||
{
|
{
|
||||||
lv_group_t *group = lv_group_create();
|
FileBrowserView::render(parent, indev);
|
||||||
lv_indev_set_group(indev, group);
|
|
||||||
|
|
||||||
list = lv_list_create(parent);
|
|
||||||
lv_obj_set_width(list, lv_pct(100));
|
|
||||||
lv_obj_set_height(list, lv_pct(100));
|
|
||||||
lv_obj_center(list);
|
|
||||||
|
|
||||||
vector<String> items = {
|
|
||||||
"Michael Jackson",
|
|
||||||
"The Beatles",
|
|
||||||
"Rolling Stones",
|
|
||||||
"Led Zeppelin",
|
|
||||||
"Queen",
|
|
||||||
"Prince",
|
|
||||||
"The Who",
|
|
||||||
"Nirvana",
|
|
||||||
"Pink Floyd",
|
|
||||||
"The Clash"};
|
|
||||||
|
|
||||||
lv_obj_t *btn;
|
|
||||||
for (String item : items)
|
|
||||||
{
|
|
||||||
btn = lv_list_add_btn(list, NULL, item.c_str());
|
|
||||||
lv_group_add_obj(group, btn);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void update()
|
void update()
|
||||||
{
|
{
|
||||||
|
FileBrowserView::update();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Loading…
Reference in New Issue
Block a user