diff --git a/source/PluginEditor.cpp b/source/PluginEditor.cpp index 1cf70ef..5f7a338 100644 --- a/source/PluginEditor.cpp +++ b/source/PluginEditor.cpp @@ -4,7 +4,7 @@ //============================================================================== AudioPluginAudioProcessorEditor::AudioPluginAudioProcessorEditor (AudioPluginAudioProcessor& p, juce::AudioProcessorValueTreeState& parameters) - : AudioProcessorEditor (&p), apvts(parameters), processorRef (p), transientViewer(p)/*, openGLBackground(parameters, p)*/, advancedParameterControl(parameters), parameterControl(parameters), + : AudioProcessorEditor (&p), apvts(parameters), processorRef (p), fileChooserManager(p), transientViewer(p)/*, openGLBackground(parameters, p)*/, advancedParameterControl(parameters), parameterControl(parameters), footerComponent(p, parameters), headerComponent(p, parameters) { juce::ignoreUnused (processorRef); @@ -165,43 +165,12 @@ void AudioPluginAudioProcessorEditor::resized() void AudioPluginAudioProcessorEditor::parameterChanged(const juce::String ¶meterID, float newValue) { parameterControl.parameterChanged(parameterID, newValue); if (parameterID == PluginParameters::SELECT_NETWORK1_ID.getParamID() && newValue == 1.f) { - openFileChooser(1); + fileChooserManager.openFileChooserForNetwork(1); } else if (parameterID == PluginParameters::SELECT_NETWORK2_ID.getParamID() && newValue == 1.f) { - openFileChooser(2); + fileChooserManager.openFileChooserForNetwork(2); } } -void AudioPluginAudioProcessorEditor::openFileChooser(int networkID) { - fc = std::make_unique ("Choose a file to open...", juce::File::getSpecialLocation(juce::File::SpecialLocationType::userHomeDirectory), - "*.ort", true); - - fc->launchAsync (juce::FileBrowserComponent::openMode - | juce::FileBrowserComponent::canSelectFiles, - [this, networkID] (const juce::FileChooser& chooser) - { - juce::File chosen; - auto results = chooser.getURLResults(); - - for (const auto& result : results) { - if (result.isLocalFile()) { - chosen = result.getLocalFile(); - } - else - { - return; - } - } - - if (chosen.getSize() != 0) { - processorRef.loadExternalModel(chosen.getFullPathName(), networkID); - } else { - auto param = (networkID == 1) ? PluginParameters::SELECT_NETWORK1_ID.getParamID() : PluginParameters::SELECT_NETWORK2_ID.getParamID(); - apvts.getParameter(param)->setValueNotifyingHost(0.f); - } - - }); -} - // Tooltips void AudioPluginAudioProcessorEditor::mouseEnter(const juce::MouseEvent &event) { auto component = event.originalComponent; @@ -237,11 +206,11 @@ void AudioPluginAudioProcessorEditor::initializeTooltipMap() { // Manually add each component to the map with its corresponding tooltip tooltipMap[xyPadComponents[0]] = "RAVE Network 1"; - tooltipMap[xyPadComponents[1]] = "Select RAVE Network 1"; + tooltipMap[xyPadComponents[1]] = "Load custom RAVE Network 1"; tooltipMap[xyPadComponents[2]] = "Grain Delay On/Off RAVE Network 1"; tooltipMap[xyPadComponents[3]] = "On/Off RAVE Network 1"; tooltipMap[xyPadComponents[4]] = "RAVE Network 2"; - tooltipMap[xyPadComponents[5]] = "Select RAVE Network 2"; + tooltipMap[xyPadComponents[5]] = "Load custom RAVE Network 2"; tooltipMap[xyPadComponents[6]] = "Grain Delay On/Off RAVE Network 2"; tooltipMap[xyPadComponents[7]] = "On/Off RAVE Network 2"; diff --git a/source/PluginEditor.h b/source/PluginEditor.h index deb5b97..adb222f 100644 --- a/source/PluginEditor.h +++ b/source/PluginEditor.h @@ -11,6 +11,7 @@ #include "ui/CustomComponents/Footer/FooterComponent.h" #include "ui/LookAndFeel/CustomFontLookAndFeel.h" #include "ui/CustomComponents/Texture/TextureComponent.h" +#include "FileChooserManager.h" //============================================================================== class AudioPluginAudioProcessorEditor : public juce::AudioProcessorEditor, private juce::AudioProcessorValueTreeState::Listener @@ -27,8 +28,6 @@ class AudioPluginAudioProcessorEditor : public juce::AudioProcessorEditor, priv void mouseExit(const juce::MouseEvent &event) override; private: - void openFileChooser(int id); - // This reference is provided as a quick way for your editor to // access the processor object that created it. AudioPluginAudioProcessor& processorRef; @@ -46,7 +45,7 @@ class AudioPluginAudioProcessorEditor : public juce::AudioProcessorEditor, priv CustomFontLookAndFeel customFontLookAndFeel; - std::unique_ptr fc; + FileChooserManager fileChooserManager; juce::Component** xyPadComponents; juce::Component** parameterControlComponents; diff --git a/source/dsp/onnx/WarningWindow.h b/source/dsp/onnx/WarningWindow.h index 7a85f49..209b0a5 100644 --- a/source/dsp/onnx/WarningWindow.h +++ b/source/dsp/onnx/WarningWindow.h @@ -10,7 +10,8 @@ enum WarningType { SampleRateWarning, - SystemTooSlow + SystemTooSlow, + UnsupportedFileType }; class WarningWindow { @@ -32,6 +33,9 @@ class WarningWindow { title = "Warning: system load to high"; errorMessage = "It seems that this system is not fast enough to process the audio data. Try to only use one network."; break; + case UnsupportedFileType: + title = "Warning: Unsupported file type"; + errorMessage = "It seems that you have tried to load an unsupported file (i.e. a shortcut). Please try again."; } juce::AlertWindow window {title, errorMessage, juce::MessageBoxIconType::NoIcon}; diff --git a/source/utils/FileChooserManager.cpp b/source/utils/FileChooserManager.cpp new file mode 100644 index 0000000..518eb45 --- /dev/null +++ b/source/utils/FileChooserManager.cpp @@ -0,0 +1,83 @@ +#include "FileChooserManager.h" + +FileChooserManager::FileChooserManager(AudioPluginAudioProcessor& processor) + : processorRef(processor) +{ + lastOpenedFolder = juce::File::getSpecialLocation(juce::File::SpecialLocationType::userHomeDirectory); +} + +// Generalized function, atm for single files only +void FileChooserManager::openFileChooser(const juce::String& dialogTitle, + const juce::File& initialDirectory, + const juce::String& filePatterns, + std::function onValidFileChosenCallback) +{ + if (lastOpenedFolder.exists()) { + dirToOpen = lastOpenedFolder; + } else { + dirToOpen = initialDirectory;; + } + + fileChooser = std::make_unique(dialogTitle, dirToOpen, filePatterns, true); + + fileChooser->launchAsync(juce::FileBrowserComponent::openMode | juce::FileBrowserComponent::canSelectFiles, + [this, filePatterns, onValidFileChosenCallback](const juce::FileChooser& chooser) + { + juce::File chosen; + auto results = chooser.getURLResults(); + + for (const auto& result : results) + { + if (result.isLocalFile()) + { + chosen = result.getLocalFile(); + lastOpenedFolder = chosen.getParentDirectory(); + break; // We only need one valid file + } + else { + return; + } + } + + // Check if the file is valid (non-empty, correct extension based on filePatterns) + if (chosen.getSize() != 0 && fileHasValidExtension(chosen, filePatterns)) + onValidFileChosenCallback(chosen); + else + warningWindow.showWarningWindow(UnsupportedFileType); + }); +} + +bool FileChooserManager::fileHasValidExtension(const juce::File& file, const juce::String& filePatterns) +{ + juce::StringArray validExtensions; + validExtensions.addTokens(filePatterns, ";,", "*"); + + for (auto& ext : validExtensions) + { + ext = ext.trimCharactersAtStart("*."); // Remove wildcard characters + if (file.hasFileExtension(ext)) + return true; + } + + return false; +} + +// Use case: Network-specific file chooser +void FileChooserManager::openFileChooserForNetwork(int networkID) +{ + if (networkID != 1 && networkID != 2) + { + jassertfalse; + return; + } + + auto onFileChosen = [this, networkID](const juce::File& file) + { + processorRef.loadExternalModel(file.getFullPathName(), networkID); + }; + + openFileChooser("Choose a model file...", + juce::File::getSpecialLocation(juce::File::SpecialLocationType::userHomeDirectory), + "*.ort", + onFileChosen); +} \ No newline at end of file diff --git a/source/utils/FileChooserManager.h b/source/utils/FileChooserManager.h new file mode 100644 index 0000000..cadb269 --- /dev/null +++ b/source/utils/FileChooserManager.h @@ -0,0 +1,30 @@ +#pragma once +#include +#include "FileChooserManager.h" +#include "PluginProcessor.h" + +class FileChooserManager +{ +public: + FileChooserManager(AudioPluginAudioProcessor& processor); + + // Generalized file chooser function, atm for single files only + void openFileChooser(const juce::String& dialogTitle, + const juce::File& initialDirectory, + const juce::String& filePatterns, + std::function onValidFileChosenCallback); + + bool fileHasValidExtension(const juce::File& file, const juce::String& filePatterns); + + // Network-specific file chooser function, using openFileChooser + void openFileChooserForNetwork(int networkID); + +private: + AudioPluginAudioProcessor& processorRef; + + std::unique_ptr fileChooser; + juce::File dirToOpen; + juce::File lastOpenedFolder; + + WarningWindow warningWindow; +};