Deluge Firmware 1.3.0
Build date: 2026.08.29
Loading...
Searching...
No Matches
browser.h
1/*
2 * Copyright © 2019-2023 Synthstrom Audible Limited
3 *
4 * This file is part of The Synthstrom Audible Deluge Firmware.
5 *
6 * The Synthstrom Audible Deluge Firmware is free software: you can redistribute it and/or modify it under the
7 * terms of the GNU General Public License as published by the Free Software Foundation,
8 * either version 3 of the License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
11 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 * See the GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License along with this program.
15 * If not, see <https://www.gnu.org/licenses/>.
16 */
17
18#pragma once
19
20#include "definitions_cxx.hpp"
21#include "gui/ui/qwerty_ui.h"
22#include "hid/button.h"
23#include "io/debug/log.h"
24#include "model/favourite/favourite_manager.h"
25#include "storage/file_item.h"
26#include "util/container/array/c_string_array.h"
27
28extern "C" {
29#include "fatfs/ff.h"
30
31FRESULT f_readdir_get_filepointer(DIR* dp, /* Pointer to the open directory object */
32 FILINFO* fno, /* Pointer to file information to return */
33 FilePointer* filePointer);
34}
35
36class Instrument;
37class FileItem;
39class Song;
40
41// FIXME: std::expected<std::pair<bool, FileItem*>, Error>
43 FileItem* fileItem;
44 bool loadedFromFile;
45 Error error;
46};
47
48struct Slot {
49 int16_t slot;
50 int8_t subSlot;
51};
52
53#define CATALOG_SEARCH_LEFT 0
54#define CATALOG_SEARCH_RIGHT 1
55#define CATALOG_SEARCH_BOTH 2
56
57#define FILE_ITEMS_MAX_NUM_ELEMENTS 20
58#define FILE_ITEMS_MAX_NUM_ELEMENTS_FOR_NAVIGATION 20 // It "should" be able to be way less than this.
59
60extern char const* allowedFileExtensionsXML[];
61
62class Browser : public QwertyUI {
63public:
64 Browser();
65
66 void close();
67 virtual Error getCurrentFilePath(String* path) = 0;
68 ActionResult buttonAction(deluge::hid::Button b, bool on, bool inCardRoutine) override;
69 ActionResult padAction(int32_t x, int32_t y, int32_t velocity) override;
70 ActionResult verticalEncoderAction(int32_t offset, bool inCardRoutine) override;
71 void currentFileDeleted();
72 Error goIntoFolder(char const* folderName);
73 Error createFolder();
74 Error createFoldersRecursiveIfNotExists(const char* path);
75 void selectEncoderAction(int8_t offset) override;
76 static FileItem* getCurrentFileItem();
77 Error readFileItemsForFolder(char const* filePrefixHere, bool allowFolders, char const** allowedFileExtensionsHere,
78 char const* filenameToStartAt, int32_t newMaxNumFileItems,
79 int32_t newCatalogSearchDirection = CATALOG_SEARCH_BOTH);
80 Error setFileByFullPath(OutputType outputType, char const* fullPath);
81 void sortFileItems();
82 FileItem* getNewFileItem();
83 static void emptyFileItems();
84 static void deleteSomeFileItems(int32_t startAt, int32_t stopAt);
85 static void deleteFolderAndDuplicateItems(Availability instrumentAvailabilityRequirement = Availability::ANY);
86 Error getUnusedSlot(OutputType outputType, String* newName, char const* thingName);
87 bool opened() override;
88 void cullSomeFileItems();
89 bool checkFP();
90
91 void renderOLED(deluge::hid::display::oled_canvas::Canvas& canvas) override;
92
93 static String currentDir;
94 static CStringArray fileItems;
95 static int32_t numFileItemsDeletedAtStart;
96 static int32_t numFileItemsDeletedAtEnd;
97 // These hold the displayName of the boundary FileItem kept when we cull items off either end of the list to stay
98 // under the memory cap. They must own a *copy* of the name (not borrow the FileItem's buffer): the FileItem they
99 // came from can be destructed - freeing its filename buffer - before these get used as search keys in a later
100 // sortFileItems(). (See the kit-copy use-after-free fix.)
101 static String firstFileItemRemaining;
102 static String lastFileItemRemaining;
103
104 static OutputType outputTypeToLoad;
105 static char const* filenameToStartSearchAt;
106
107 // ui
108 ActionResult exitUI() override {
109 exitAction();
110 return ActionResult::ACTIONED_AND_CAUSED_CHANGE;
111 }
112 bool isFavouritesVisible() override;
113 bool isBanksVisible() override;
114
115protected:
116 Error setEnteredTextFromCurrentFilename();
117 Error goUpOneDirectoryLevel();
118 virtual Error arrivedInNewFolder(int32_t direction, char const* filenameToStartAt = nullptr,
119 char const* defaultDir = nullptr);
120 bool predictExtendedText() override;
121 void goIntoDeleteFileContextMenu();
122 ActionResult mainButtonAction(bool on);
123 virtual void exitAction();
124 virtual ActionResult backButtonAction();
125 virtual void folderContentsReady(int32_t entryDirection) {}
126 virtual void currentFileChanged(int32_t movementDirection) {}
127 void displayText(bool blinkImmediately = false) override;
128 // Keeps the selected file index and top visible browser row inside Browser::fileItems.
129 void clampFileSelectionAndScroll(bool allowNoFileSelection = true);
130 static Slot getSlot(char const* displayName);
133 char const* nameAfterPrefix(char const* name) const;
134 Error readFileItemsFromFolderAndMemory(Song* song, OutputType outputType, char const* filePrefixHere,
135 char const* filenameToStartAt, char const* defaultDirToAlsoTry,
136 bool allowFoldersint,
137 Availability availabilityRequirement = Availability::ANY,
138 int32_t newCatalogSearchDirection = CATALOG_SEARCH_RIGHT);
139 void favouritesChanged();
140
141 static int32_t fileIndexSelected; // If -1, we have not selected any real file/folder. Maybe there are no files, or
142 // maybe we're typing a new name.
143 static int32_t scrollPosVertical;
144 static int32_t
145 numCharsInPrefix; // Only used for deciding Drum names within Kit. Oh and initial text scroll position.
146 static bool qwertyVisible;
147 static bool arrivedAtFileByTyping;
148 static bool allowFoldersSharingNameWithFile;
149 static char const** allowedFileExtensions;
150
151 const uint8_t* fileIcon;
152 const uint8_t* fileIconPt2;
153 int32_t fileIconPt2Width;
154
155 // 7Seg Only
156 static int8_t numberEditPos; // -1 is default
157 static NumericLayerScrollingText* scrollingText;
158 bool shouldWrapFolderContents; // As in, wrap around at the end.
159
160 bool mayDefaultToBrandNewNameOnEntry;
161 bool qwertyAlwaysVisible;
162 // filePrefix is SONG/SYNT/SAMP etc., signifying the portion of the filesystem you're in
163 char const* filePrefix;
164 bool shouldInterpretNoteNamesForThisBrowser;
165};
166
167inline void printInstrumentFileList(const char* where) {
168 D_PRINT("\n");
169 D_PRINT(where);
170 D_PRINT(" List: \n");
171 for (uint32_t idx = 0; idx < Browser::fileItems.getNumElements(); ++idx) {
172 FileItem* fileItem = (FileItem*)Browser::fileItems.getElementAddress(idx);
173 D_PRINTLN(" - %s (%lu)", fileItem->displayName, fileItem->filePointer.sclust);
174 }
175 D_PRINT("\n");
176}
ActionResult exitUI() override
returns whether a UI exited
Definition browser.h:108
char const * nameAfterPrefix(char const *name) const
Definition browser.cpp:1277
Definition c_string_array.h:23
Definition file_item.h:24
Definition instrument.h:45
Definition numeric_layer_scrolling_text.h:22
Definition song.h:103
Definition d_string.h:41
Definition browser.h:42
Definition browser.h:48