Vital
Loading...
Searching...
No Matches
synth_preset_selector.cpp
Go to the documentation of this file.
1
3
5
6#include "paths.h"
7#include "skin.h"
9#include "fonts.h"
10#include "load_save.h"
11#include "full_interface.h"
12#include "save_section.h"
13#include "synth_gui_interface.h"
14#include "tuning.h"
15
16namespace {
20 void menuCallback(int result, SynthPresetSelector* preset_selector) {
21 if (preset_selector == nullptr)
22 return;
24 preset_selector->initPreset();
25 else if (result == SynthPresetSelector::kImportPreset)
26 preset_selector->importPreset();
27 else if (result == SynthPresetSelector::kExportPreset)
28 preset_selector->exportPreset();
29 else if (result == SynthPresetSelector::kImportBank)
30 preset_selector->importBank();
31 else if (result == SynthPresetSelector::kExportBank)
32 preset_selector->exportBank();
33 else if (result == SynthPresetSelector::kSavePreset)
34 preset_selector->savePreset();
35 else if (result == SynthPresetSelector::kBrowsePresets)
36 preset_selector->browsePresets();
37 else if (result == SynthPresetSelector::kLoadTuning)
38 preset_selector->loadTuningFile();
39 else if (result == SynthPresetSelector::kClearTuning)
40 preset_selector->clearTuning();
42 preset_selector->openSkinDesigner();
43 else if (result == SynthPresetSelector::kLoadSkin)
44 preset_selector->loadSkin();
45 else if (result == SynthPresetSelector::kClearSkin)
46 preset_selector->clearSkin();
47 else if (result == SynthPresetSelector::kLogOut)
48 preset_selector->signOut();
49 else if (result == SynthPresetSelector::kLogIn)
50 preset_selector->signIn();
51 }
52
56 String redactEmail(const String& email) {
57 static constexpr int kLeaveCharacters = 2;
58
59 StringArray tokens;
60 tokens.addTokens(email, "@", "");
61 String beginning = tokens[0];
62 String result = beginning.substring(0, 2);
63 for (int i = kLeaveCharacters; i < beginning.length(); ++i)
64 result += "*";
65
66 return result + "@" + tokens[1];
67 }
68}
69
70SynthPresetSelector::SynthPresetSelector() : SynthSection("preset_selector"), bank_exporter_(nullptr),
71 browser_(nullptr), save_section_(nullptr), modified_(false) {
72 static const PathStrokeType arrow_stroke(0.05f, PathStrokeType::JointStyle::curved,
73 PathStrokeType::EndCapStyle::rounded);
74 full_skin_ = std::make_unique<Skin>();
75 selector_ = std::make_unique<PresetSelector>();
76 addSubSection(selector_.get());
77 selector_->addListener(this);
78
79 menu_button_ = std::make_unique<OpenGlShapeButton>("Menu");
80 addAndMakeVisible(menu_button_.get());
81 addOpenGlComponent(menu_button_->getGlComponent());
82 menu_button_->addListener(this);
83 menu_button_->setTriggeredOnMouseDown(true);
84 menu_button_->setShape(Paths::menu());
85
86 save_button_ = std::make_unique<OpenGlShapeButton>("Save");
87 addAndMakeVisible(save_button_.get());
88 addOpenGlComponent(save_button_->getGlComponent());
89 save_button_->addListener(this);
90
91 save_button_->setShape(Paths::save());
92}
93
95 skin_designer_.deleteAndZero();
96}
97
99 static constexpr float kSelectorButtonPaddingHeightPercent = 0.2f;
100
101 int height = getHeight();
102 selector_->setRoundAmount(height / 2.0f);
103 int padding = kSelectorButtonPaddingHeightPercent * height;
104 selector_->setBounds(0, 0, getWidth() - 2 * height - padding, height);
105 save_button_->setBounds(getWidth() - 2 * height, 0, height, height);
106 save_button_->setShape(Paths::save(height));
107 menu_button_->setBounds(getWidth() - height, 0, height, height);
108 menu_button_->setShape(Paths::menu(height));
109
110 resetText();
111
112 Component::resized();
113}
114
115void SynthPresetSelector::buttonClicked(Button* clicked_button) {
116 if (clicked_button == menu_button_.get()) {
117 if (ModifierKeys::getCurrentModifiersRealtime().isAltDown())
118 showAlternatePopupMenu(menu_button_.get());
119 else
120 showPopupMenu(menu_button_.get());
121 }
122 else if (clicked_button == save_button_.get())
123 savePreset();
124}
125
127 browser_->clearExternalPreset();
128 SynthGuiInterface* parent = findParentComponentOfClass<SynthGuiInterface>();
129 std::string error;
130 bool result = parent->getSynth()->loadFromFile(preset, error);
131 if (result)
132 resetText();
133 else {
134 error = "There was an error open the preset. " + error;
135 AlertWindow::showNativeDialogBox("Error opening preset", error, false);
136 }
137}
138
140 for (Listener* listener : listeners_)
141 listener->deleteRequested(preset);
142}
143
145 for (Listener* listener : listeners_)
146 listener->setPresetBrowserVisibility(false);
147}
148
150 for (Listener* listener : listeners_)
151 listener->setBankExporterVisibility(false);
152}
153
155 SynthGuiInterface* parent = findParentComponentOfClass<SynthGuiInterface>();
156 if (parent == nullptr)
157 return;
158
159 String preset_text = parent->getSynth()->getPresetName();
160 if (preset_text == "")
161 preset_text = TRANS("Init Preset");
162
163 if (modified_)
164 preset_text = "*" + preset_text;
165
166 selector_->setText(preset_text);
167 repaint();
168}
169
171 if (browser_)
172 browser_->loadPrevPreset();
173}
174
176 if (browser_)
177 browser_->loadNextPreset();
178}
179
180void SynthPresetSelector::textMouseUp(const MouseEvent& e) {
181 if (e.mods.isPopupMenu())
182 showPopupMenu(selector_.get());
183 else if (browser_)
184 setPresetBrowserVisibile(!browser_->isVisible());
185}
186
187void SynthPresetSelector::showPopupMenu(Component* anchor) {
188 PopupItems options;
189 options.addItem(kBrowsePresets, "Browse Presets");
190 options.addItem(kSavePreset, "Save Preset");
191 options.addItem(kImportPreset, "Open External Preset");
192 options.addItem(kExportPreset, "Export Preset");
193 options.addItem(kImportBank, "Import Bank");
194 options.addItem(kExportBank, "Export Bank");
195 options.addItem(-1, "");
196 options.addItem(kInitPreset, "Initialize Preset");
197 options.addItem(-1, "");
198 options.addItem(kLoadTuning, "Load Tuning File");
199 if (!hasDefaultTuning())
200 options.addItem(kClearTuning, "Clear Tuning: " + getTuningName());
201
202 options.addItem(-1, "");
203 std::string logged_in_as = loggedInName();
204 if (logged_in_as.empty())
205 options.addItem(kLogIn, "Log in");
206 else
207 options.addItem(kLogOut, "Log out - " + redactEmail(logged_in_as).toStdString());
208
209 if (LoadSave::getDefaultSkin().exists()) {
210 options.addItem(-1, "");
211 options.addItem(kClearSkin, "Load Default Skin");
212 }
213
214 showPopupSelector(this, Point<int>(anchor->getX(), anchor->getBottom()), options,
215 [=](int selection) { menuCallback(selection, this); });
216}
217
219 PopupItems options;
220 options.addItem(kOpenSkinDesigner, "Open Skin Designer");
221 options.addItem(kLoadSkin, "Load Skin");
222
223 if (LoadSave::getDefaultSkin().exists())
224 options.addItem(kClearSkin, "Load Default Skin");
225
226 showPopupSelector(this, Point<int>(anchor->getX(), anchor->getBottom()), options,
227 [=](int selection) { menuCallback(selection, this); });
228}
229
231 if (modified_ == modified)
232 return;
233
234 modified_ = modified;
235 String text = selector_->getText();
236 if (modified_ && text.length() && text[0] != '*')
237 selector_->setText("*" + text);
238 else if (!modified_ && text.length() && text[0] == '*')
239 selector_->setText(text.substring(1));
240}
241
242void SynthPresetSelector::loadFromFile(File& preset) {
243 SynthGuiInterface* parent = findParentComponentOfClass<SynthGuiInterface>();
244 std::string error;
245 parent->getSynth()->loadFromFile(preset, error);
246}
247
249 for (Listener* listener : listeners_)
250 listener->setPresetBrowserVisibility(visible);
251}
252
254 for (Listener* listener : listeners_)
255 listener->setBankExporterVisibility(true);
256}
257
259 SynthGuiInterface* parent = findParentComponentOfClass<SynthGuiInterface>();
260 parent->getSynth()->loadInitPreset();
261 if (browser_)
262 browser_->externalPresetLoaded(File());
263 parent->updateFullGui();
264 parent->notifyFresh();
265 resetText();
266}
267
269 if (save_section_) {
270 save_section_->setIsPreset(true);
271 save_section_->setVisible(true);
272 }
273}
274
276 SynthGuiInterface* parent = findParentComponentOfClass<SynthGuiInterface>();
277 File active_file = parent->getSynth()->getActiveFile();
278 FileChooser open_box("Open Preset", active_file, String("*.") + vital::kPresetExtension);
279 if (!open_box.browseForFileToOpen())
280 return;
281
282 File choice = open_box.getResult();
283 if (!choice.exists())
284 return;
285
286 std::string error;
287 if (!parent->getSynth()->loadFromFile(choice, error)) {
288 std::string name = ProjectInfo::projectName;
289 error = "There was an error open the preset. " + error;
290 AlertWindow::showNativeDialogBox("Error opening preset", error, false);
291 }
292 else
293 parent->externalPresetLoaded(choice);
294}
295
297 SynthGuiInterface* parent = findParentComponentOfClass<SynthGuiInterface>();
298 if (parent == nullptr)
299 return;
300
301 SynthBase* synth = parent->getSynth();
302 File active_file = synth->getActiveFile();
303 FileChooser save_box("Export Preset", File(), String("*.") + vital::kPresetExtension);
304 if (!save_box.browseForFileToSave(true))
305 return;
306
307 synth->saveToFile(save_box.getResult().withFileExtension(vital::kPresetExtension));
308 parent->externalPresetLoaded(synth->getActiveFile());
309}
310
312 FileChooser import_box("Import Bank", File(), String("*.") + vital::kBankExtension);
313 if (import_box.browseForFileToOpen()) {
314 File result = import_box.getResult();
315 FileInputStream input_stream(result);
316 if (input_stream.openedOk()) {
317 File data_directory = LoadSave::getDataDirectory();
318 data_directory.createDirectory();
320 LoadSave::saveDataDirectory(data_directory);
321
322 ZipFile import_zip(input_stream);
323 Result unzip_result = import_zip.uncompressTo(data_directory);
324 if (unzip_result == Result::ok())
325 LoadSave::markPackInstalled(result.getFileNameWithoutExtension().toStdString());
326 else
327 LoadSave::writeErrorLog("Unzipping bank failed!");
328
329 for (Listener* listener : listeners_)
330 listener->bankImported();
331 }
332 else
333 LoadSave::writeErrorLog("Opening file stream to bank failed!");
334 }
335}
336
340
342 SynthGuiInterface* parent = findParentComponentOfClass<SynthGuiInterface>();
343 FileChooser load_box("Load Tuning", File(), Tuning::allFileExtensions());
344 if (load_box.browseForFileToOpen())
345 parent->getSynth()->loadTuningFile(load_box.getResult());
346}
347
349 SynthGuiInterface* parent = findParentComponentOfClass<SynthGuiInterface>();
350 parent->getSynth()->getTuning()->setDefaultTuning();
351}
352
354 SynthGuiInterface* parent = findParentComponentOfClass<SynthGuiInterface>();
355 return parent->getSynth()->getTuning()->getName();
356}
357
359 SynthGuiInterface* parent = findParentComponentOfClass<SynthGuiInterface>();
360 return parent->getSynth()->getTuning()->isDefault();
361}
362
364 FullInterface* full_interface = findParentComponentOfClass<FullInterface>();
365 if (full_interface)
366 return full_interface->getSignedInName();
367 return "";
368}
369
371 FullInterface* full_interface = findParentComponentOfClass<FullInterface>();
372 return full_interface->signOut();
373}
374
376 FullInterface* full_interface = findParentComponentOfClass<FullInterface>();
377 return full_interface->signIn();
378}
379
381 skin_designer_.deleteAndZero();
382 SkinDesigner* skin_designer = new SkinDesigner(full_skin_.get(), findParentComponentOfClass<FullInterface>());
383 RectanglePlacement placement(RectanglePlacement::xLeft |
384 RectanglePlacement::yTop |
385 RectanglePlacement::doNotResize);
386
387 Rectangle<int> area(0, 0, 700, 800);
388 Rectangle<int> bounds = Desktop::getInstance().getDisplays().getMainDisplay().userArea.reduced(20);
389 Rectangle<int> bounds_result(placement.appliedTo(area, bounds));
390
391 skin_designer->setBounds(bounds_result);
392 skin_designer->setResizable(true, false);
393 skin_designer->setUsingNativeTitleBar(true);
394 skin_designer->setVisible(true);
395 skin_designer_ = skin_designer;
396}
397
399 FileChooser open_box("Open Skin", File(), String("*.") + vital::kSkinExtension);
400 if (open_box.browseForFileToOpen()) {
401 File loaded = open_box.getResult();
402 loaded.copyFileTo(LoadSave::getDefaultSkin());
403 full_skin_->loadFromFile(loaded);
405 }
406}
407
409 File default_skin = LoadSave::getDefaultSkin();
410 if (default_skin.exists() && default_skin.hasWriteAccess())
411 default_skin.deleteFile();
412
413 full_skin_->loadDefaultSkin();
415}
416
418 FullInterface* full_interface = findParentComponentOfClass<FullInterface>();
419 full_interface->reloadSkin(*full_skin_);
420}
421
423 if (browser_)
425}
The main GUI container for the entire synthesizer interface.
Definition full_interface.h:61
std::string getSignedInName()
Gets the name of the currently signed-in user, if any.
Definition full_interface.cpp:792
void reloadSkin(const Skin &skin)
Reloads and applies a new skin, then adjusts layout accordingly.
Definition full_interface.cpp:276
void signIn()
Opens the sign-in interface, if available.
Definition full_interface.cpp:804
void signOut()
Signs out the current user, if signed in.
Definition full_interface.cpp:799
static void markPackInstalled(int id)
Marks a pack as installed by ID in the packs file.
Definition load_save.cpp:1494
static File getDataDirectory()
Gets the current data directory from the config.
Definition load_save.cpp:1718
static void saveDataDirectory(const File &data_directory)
Saves the given directory as the data directory in the configuration.
Definition load_save.cpp:1508
static File getDefaultSkin()
Retrieves the file specifying the default skin.
Definition load_save.cpp:1168
static void writeErrorLog(String error_log)
Appends an error message to an error log file.
Definition load_save.cpp:1140
static bool hasDataDirectory()
Checks if a data directory is properly configured (exists and has packs.json).
Definition load_save.cpp:1417
static Path save()
Definition paths.h:607
static Path menu()
Creates a menu icon path (three horizontal lines).
Definition paths.h:271
void clearExternalPreset()
Clears the reference to any external preset.
Definition preset_browser.h:545
void externalPresetLoaded(File file)
Loads an external preset file and sets it as the current selection.
Definition preset_browser.cpp:943
void loadNextPreset()
Loads the next preset in the list.
Definition preset_browser.cpp:939
void loadPrevPreset()
Loads the previous preset in the list.
Definition preset_browser.cpp:935
void setIsPreset(bool preset)
Configures the section for saving a preset (true) or another file type.
Definition save_section.h:135
void setVisible(bool should_be_visible) override
Sets the visibility of this overlay. Adjusts layout when becoming visible.
Definition save_section.cpp:267
A DocumentWindow that allows interactive editing of the Skin.
Definition skin.h:418
A base class providing foundational functionality for the Vital synthesizer’s engine,...
Definition synth_base.h:42
Tuning * getTuning()
Returns a pointer to the synth's Tuning object.
Definition synth_base.h:554
bool saveToFile(File preset)
Saves the current preset state to the specified file.
Definition synth_base.cpp:531
bool loadFromFile(File preset, std::string &error)
Attempts to load a preset from a file.
Definition synth_base.cpp:338
File getActiveFile()
Gets the currently active preset file.
Definition synth_base.h:342
String getPresetName()
Gets the current preset’s name.
Definition synth_base.cpp:713
void loadInitPreset()
Loads an "init" preset, resetting Vital to its default initial state.
Definition synth_base.cpp:316
void loadTuningFile(const File &file)
Loads a tuning file into the synthesizer’s tuning system.
Definition synth_base.cpp:312
An interface class linking the Vital synthesizer backend (SynthBase) with a GUI.
Definition synth_gui_interface.h:56
SynthBase * getSynth()
Returns the SynthBase instance this interface is managing.
Definition synth_gui_interface.h:85
virtual void updateFullGui()
Updates the entire GUI to reflect the current synth state.
Definition synth_gui_interface.cpp:62
void externalPresetLoaded(File preset)
Notifies the GUI that a preset was loaded externally (outside the GUI controls).
Definition synth_gui_interface.cpp:186
void notifyFresh()
Notifies the GUI that a fresh state (like a new preset load) has occurred, prompting a full refresh.
Definition synth_gui_interface.cpp:172
Interface for components that need to respond to preset selector events.
Definition synth_preset_selector.h:29
A UI section that allows the user to select, load, save, and browse presets, and manage associated re...
Definition synth_preset_selector.h:25
void buttonClicked(Button *buttonThatWasClicked) override
Definition synth_preset_selector.cpp:115
void signIn()
Opens the sign-in dialog for the user.
Definition synth_preset_selector.cpp:375
void setModified(bool modified)
Definition synth_preset_selector.cpp:230
void textMouseUp(const MouseEvent &e) override
Definition synth_preset_selector.cpp:180
void makeBankExporterVisibile()
Makes the bank exporter visible.
Definition synth_preset_selector.cpp:253
void resetText()
Resets the text displayed in the PresetSelector to reflect current state.
Definition synth_preset_selector.cpp:154
void exportBank()
Exports the current bank.
Definition synth_preset_selector.cpp:337
void loadTuningFile()
Loads a tuning file and applies it to the synthesizer.
Definition synth_preset_selector.cpp:341
void loadSkin()
Loads a skin from a file.
Definition synth_preset_selector.cpp:398
void nextClicked() override
Called when the next preset button is clicked in the PresetSelector.
Definition synth_preset_selector.cpp:175
void initPreset()
Initializes the current preset to a default state.
Definition synth_preset_selector.cpp:258
~SynthPresetSelector()
Destructor.
Definition synth_preset_selector.cpp:94
void browsePresets()
Shows the preset browser UI.
Definition synth_preset_selector.cpp:422
SynthPresetSelector()
Constructor.
Definition synth_preset_selector.cpp:70
void setPresetBrowserVisibile(bool visible)
Definition synth_preset_selector.cpp:248
void hidePresetBrowser() override
Called when the PresetBrowser is requested to be hidden.
Definition synth_preset_selector.cpp:144
void prevClicked() override
Called when the previous preset button is clicked in the PresetSelector.
Definition synth_preset_selector.cpp:170
void resized() override
Resizes and lays out UI components.
Definition synth_preset_selector.cpp:98
void savePreset()
Saves the current preset.
Definition synth_preset_selector.cpp:268
@ kImportBank
Definition synth_preset_selector.h:57
@ kInitPreset
Definition synth_preset_selector.h:53
@ kLoadSkin
Definition synth_preset_selector.h:63
@ kBrowsePresets
Definition synth_preset_selector.h:59
@ kImportPreset
Definition synth_preset_selector.h:55
@ kExportPreset
Definition synth_preset_selector.h:56
@ kClearTuning
Definition synth_preset_selector.h:61
@ kLoadTuning
Definition synth_preset_selector.h:60
@ kExportBank
Definition synth_preset_selector.h:58
@ kLogIn
Definition synth_preset_selector.h:66
@ kSavePreset
Definition synth_preset_selector.h:54
@ kClearSkin
Definition synth_preset_selector.h:64
@ kOpenSkinDesigner
Definition synth_preset_selector.h:62
@ kLogOut
Definition synth_preset_selector.h:65
void clearTuning()
Clears the currently loaded tuning, reverting to default.
Definition synth_preset_selector.cpp:348
std::string loggedInName()
Definition synth_preset_selector.cpp:363
void showAlternatePopupMenu(Component *anchor)
Definition synth_preset_selector.cpp:218
bool hasDefaultTuning()
Definition synth_preset_selector.cpp:358
void deleteRequested(File preset) override
Definition synth_preset_selector.cpp:139
void clearSkin()
Clears the current skin and reverts to the default.
Definition synth_preset_selector.cpp:408
void importPreset()
Imports a preset from an external file.
Definition synth_preset_selector.cpp:275
void showPopupMenu(Component *anchor)
Definition synth_preset_selector.cpp:187
void openSkinDesigner()
Opens the skin designer tool.
Definition synth_preset_selector.cpp:380
void newPresetSelected(File preset) override
Definition synth_preset_selector.cpp:126
void repaintWithSkin()
Repaints the interface with the current skin settings.
Definition synth_preset_selector.cpp:417
void hideBankExporter() override
Called when the BankExporter is requested to be hidden.
Definition synth_preset_selector.cpp:149
std::string getTuningName()
Definition synth_preset_selector.cpp:353
void exportPreset()
Exports the current preset to a file.
Definition synth_preset_selector.cpp:296
void importBank()
Imports a bank from an external file.
Definition synth_preset_selector.cpp:311
void signOut()
Signs out the currently logged-in user.
Definition synth_preset_selector.cpp:370
Base class for all synthesizer sections, providing UI layout, painting, and interaction logic.
Definition synth_section.h:193
void addSubSection(SynthSection *section, bool show=true)
Adds a subsection (another SynthSection) as a child.
Definition synth_section.cpp:457
void showPopupSelector(Component *source, Point< int > position, const PopupItems &options, std::function< void(int)> callback, std::function< void()> cancel={ })
Shows a popup selector with options.
Definition synth_section.cpp:119
void addOpenGlComponent(OpenGlComponent *open_gl_component, bool to_beginning=false)
Definition synth_section.cpp:489
static String allFileExtensions()
Returns a string listing all supported tuning file extensions.
Definition tuning.cpp:93
std::string getName() const
Gets the name of the current tuning, combining tuning and mapping names if both exist.
Definition tuning.h:157
void setDefaultTuning()
Resets the tuning to the default 12-tone equal temperament with a standard reference pitch.
Definition tuning.cpp:354
bool isDefault() const
Checks if the tuning is the default equal temperament.
Definition tuning.h:180
const std::string kBankExtension
File extension for Vital bank files, which group multiple presets.
Definition synth_constants.h:103
const std::string kSkinExtension
File extension for Vital skin/theme files.
Definition synth_constants.h:97
const std::string kPresetExtension
File extension for Vital preset files.
Definition synth_constants.h:85
A hierarchical structure of popup menu items for a selector component.
Definition synth_section.h:29
void addItem(int sub_id, const std::string &sub_name, bool sub_selected=false)
Adds a new item as a submenu entry.
Definition synth_section.h:51
Declares the SynthPresetSelector class, which provides UI elements for selecting, browsing,...