Deluge Firmware 1.3.0
Build date: 2026.07.12
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 NUM_FILES_ON_SCREEN 3
54
55#define CATALOG_SEARCH_LEFT 0
56#define CATALOG_SEARCH_RIGHT 1
57#define CATALOG_SEARCH_BOTH 2
58
59#define FILE_ITEMS_MAX_NUM_ELEMENTS 20
60#define FILE_ITEMS_MAX_NUM_ELEMENTS_FOR_NAVIGATION 20 // It "should" be able to be way less than this.
61
62extern char const* allowedFileExtensionsXML[];
63
64class Browser : public QwertyUI {
65public:
66 Browser();
67
68 void close();
69 virtual Error getCurrentFilePath(String* path) = 0;
70 ActionResult buttonAction(deluge::hid::Button b, bool on, bool inCardRoutine) override;
71 ActionResult padAction(int32_t x, int32_t y, int32_t velocity) override;
72 ActionResult verticalEncoderAction(int32_t offset, bool inCardRoutine) override;
73 void currentFileDeleted();
74 Error goIntoFolder(char const* folderName);
75 Error createFolder();
76 Error createFoldersRecursiveIfNotExists(const char* path);
77 void selectEncoderAction(int8_t offset) override;
78 static FileItem* getCurrentFileItem();
79 Error readFileItemsForFolder(char const* filePrefixHere, bool allowFolders, char const** allowedFileExtensionsHere,
80 char const* filenameToStartAt, int32_t newMaxNumFileItems,
81 int32_t newCatalogSearchDirection = CATALOG_SEARCH_BOTH);
82 Error setFileByFullPath(OutputType outputType, char const* fullPath);
83 void sortFileItems();
84 FileItem* getNewFileItem();
85 static void emptyFileItems();
86 static void deleteSomeFileItems(int32_t startAt, int32_t stopAt);
87 static void deleteFolderAndDuplicateItems(Availability instrumentAvailabilityRequirement = Availability::ANY);
88 Error getUnusedSlot(OutputType outputType, String* newName, char const* thingName);
89 bool opened() override;
90 void cullSomeFileItems();
91 bool checkFP();
92
93 void renderOLED(deluge::hid::display::oled_canvas::Canvas& canvas) override;
94
95 static String currentDir;
96 static CStringArray fileItems;
97 static int32_t numFileItemsDeletedAtStart;
98 static int32_t numFileItemsDeletedAtEnd;
99 // These hold the displayName of the boundary FileItem kept when we cull items off either end of the list to stay
100 // under the memory cap. They must own a *copy* of the name (not borrow the FileItem's buffer): the FileItem they
101 // came from can be destructed - freeing its filename buffer - before these get used as search keys in a later
102 // sortFileItems(). (See the kit-copy use-after-free fix.)
103 static String firstFileItemRemaining;
104 static String lastFileItemRemaining;
105
106 static OutputType outputTypeToLoad;
107 static char const* filenameToStartSearchAt;
108
109 // ui
110 ActionResult exitUI() override {
111 exitAction();
112 return ActionResult::ACTIONED_AND_CAUSED_CHANGE;
113 }
114 bool isFavouritesVisible() override;
115 bool isBanksVisible() override;
116
117protected:
118 Error setEnteredTextFromCurrentFilename();
119 Error goUpOneDirectoryLevel();
120 virtual Error arrivedInNewFolder(int32_t direction, char const* filenameToStartAt = nullptr,
121 char const* defaultDir = nullptr);
122 bool predictExtendedText() override;
123 void goIntoDeleteFileContextMenu();
124 ActionResult mainButtonAction(bool on);
125 virtual void exitAction();
126 virtual ActionResult backButtonAction();
127 virtual void folderContentsReady(int32_t entryDirection) {}
128 virtual void currentFileChanged(int32_t movementDirection) {}
129 void displayText(bool blinkImmediately = false) override;
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:110
char const * nameAfterPrefix(char const *name) const
Definition browser.cpp:1220
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