diff --git a/Modules/juce_audio_plugin_client/Standalone/juce_StandaloneFilterWindow.h b/Modules/juce_audio_plugin_client/Standalone/juce_StandaloneFilterWindow.h index 493aa86..716c570 100644 --- a/Modules/juce_audio_plugin_client/Standalone/juce_StandaloneFilterWindow.h +++ b/Modules/juce_audio_plugin_client/Standalone/juce_StandaloneFilterWindow.h @@ -2,17 +2,16 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2017 - ROLI Ltd. + Copyright (c) 2020 - Raw Material Software Limited JUCE is an open source library subject to commercial or open-source licensing. - By using JUCE, you agree to the terms of both the JUCE 5 End-User License - Agreement and JUCE 5 Privacy Policy (both updated and effective as of the - 27th April 2017). + By using JUCE, you agree to the terms of both the JUCE 6 End-User License + Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020). - End User License Agreement: www.juce.com/juce-5-licence - Privacy Policy: www.juce.com/juce-5-privacy-policy + End User License Agreement: www.juce.com/juce-6-licence + Privacy Policy: www.juce.com/juce-privacy-policy Or: You may also use this code under the terms of the GPL v3 (see www.gnu.org/licenses). @@ -24,8 +23,10 @@ ============================================================================== */ -#if JUCE_MODULE_AVAILABLE_juce_audio_plugin_client -extern juce::AudioProcessor* JUCE_API JUCE_CALLTYPE createPluginFilterOfType (juce::AudioProcessor::WrapperType type); +#pragma once + +#ifndef DOXYGEN + #include "../utility/juce_CreatePluginFilter.h" #endif namespace juce @@ -123,15 +124,7 @@ public: //============================================================================== virtual void createPlugin() { - #if JUCE_MODULE_AVAILABLE_juce_audio_plugin_client - processor.reset (::createPluginFilterOfType (AudioProcessor::wrapperType_Standalone)); - #else - AudioProcessor::setTypeOfNextNewPlugin (AudioProcessor::wrapperType_Standalone); - processor.reset (createPluginFilter()); - AudioProcessor::setTypeOfNextNewPlugin (AudioProcessor::wrapperType_Undefined); - #endif - jassert (processor != nullptr); // Your createPluginFilter() function must return a valid object! - + processor.reset (createPluginFilterOfType (AudioProcessor::wrapperType_Standalone)); processor->disableNonMainBuses(); processor->setRateAndBufferSizeDetails (44100, 512); @@ -272,12 +265,15 @@ public: maxNumOutputs = jmax (0, bus->getDefaultLayout().size()); o.content.setOwned (new SettingsComponent (*this, deviceManager, maxNumInputs, maxNumOutputs)); -//#if JUCE_MAC + + LookAndFeel_V4 *lfv4 = dynamic_cast(&o.content->getLookAndFeel()); + + if (lfv4) { + lfv4->setColour(ResizableWindow::backgroundColourId, Colour::fromHSV (0.0f, 0.0f, 0.1f, 1.0f)); + } + o.content->setSize (500, 400); -//#endif -//#if ! JUCE_MAC -// o.content->setSize (500, 450); -//#endif + o.dialogTitle = TRANS("Audio/MIDI Settings"); o.dialogBackgroundColour = o.content->getLookAndFeel().findColour (ResizableWindow::backgroundColourId); o.escapeKeyTriggersCloseButton = true; @@ -376,7 +372,6 @@ public: return false; } - #if JUCE_MODULE_AVAILABLE_juce_gui_basics Image getIAAHostIcon (int size) { #if JUCE_IOS && JucePlugin_Enable_IAA @@ -388,7 +383,6 @@ public: return {}; } - #endif static StandalonePluginHolder* getInstance(); @@ -420,10 +414,10 @@ private: int maxAudioOutputChannels) : owner (pluginHolder), deviceSelector (deviceManagerToUse, - 0, maxAudioInputChannels, + 0, 0, // maxAudioInputChannels, // force zero to fully disable input selection 0, maxAudioOutputChannels, true, - false, // disables MIDI Out // (pluginHolder.processor.get() != nullptr && pluginHolder.processor->producesMidi()), + (pluginHolder.processor.get() != nullptr && pluginHolder.processor->producesMidi()), true, false), shouldMuteLabel ("Feedback Loop:", "Feedback Loop:"), shouldMuteButton ("Mute audio input") @@ -442,6 +436,17 @@ private: shouldMuteLabel.attachToComponent (&shouldMuteButton, true); } + + for (int i =0; i < deviceSelector.getNumChildComponents(); i ++){ + + LookAndFeel_V4 *lfv4 = dynamic_cast(&deviceSelector.getChildComponent(i) ->getLookAndFeel()); + if (lfv4) { + lfv4->setColour(ComboBox::ColourIds::backgroundColourId, Colour::fromHSV (0.0f, 0.0f, 0.2f, 1.0f)); + lfv4->setColour(ListBox::ColourIds::backgroundColourId, Colour::fromHSV (0.0f, 0.0f, 0.2f, 1.0f)); + lfv4->setColour(TextButton::ColourIds::buttonColourId, Colour::fromHSV (0.0f, 0.0f, 0.1f, 1.0f)); + + } + } } void paint (Graphics& g) override @@ -586,20 +591,33 @@ public: #if JUCE_ANDROID || JUCE_IOS bool autoOpenMidiDevices = true #else - bool autoOpenMidiDevices = true + bool autoOpenMidiDevices = false #endif ) - : DocumentWindow ("", Colour::fromHSV (0.0f, 0.0f, 0.1f, 1.0f), DocumentWindow::minimiseButton | DocumentWindow::closeButton) - , menuBar(this) +#if JUCE_MAC + : DocumentWindow ("", backgroundColour, DocumentWindow::minimiseButton | DocumentWindow::closeButton), +#endif + +#if ! JUCE_MAC + : DocumentWindow (title, Colour::fromHSV (0.0f, 0.0f, 0.1f, 0.5f), DocumentWindow::minimiseButton | DocumentWindow::closeButton), +#endif + + menuBar(this) #if ! JUCE_MAC - , optionsButton ("Settings") + , optionsButton ("Settings") #endif { #if JUCE_IOS || JUCE_ANDROID setTitleBarHeight (0); #else + + LookAndFeel_V4 *lfv4 = dynamic_cast(&getLookAndFeel()); +if (lfv4) { +lfv4->getCurrentColourScheme().setUIColour (LookAndFeel_V4::ColourScheme::widgetBackground, Colour::fromHSV (0.0f, 0.0f, 0.1f, 1.0f)); +} + setTitleBarButtonsRequired (DocumentWindow::minimiseButton | DocumentWindow::closeButton, false); - + #if JUCE_MAC setUsingNativeTitleBar(true); menu.addItem (1, TRANS("Audio/MIDI Settings...")); @@ -709,20 +727,7 @@ public: void menuBarActivated (bool isActive) override {}; - void buttonClicked (Button*) override - { - pluginHolder->showAudioSettingsDialog(); - - // PopupMenu m; - // m.addItem (1, TRANS("Audio/MIDI Settings...")); - // m.addSeparator(); - // m.addItem (2, TRANS("Save current state...")); - // m.addItem (3, TRANS("Load a saved state...")); - // m.addSeparator(); - // m.addItem (4, TRANS("Reset to default state")); - - // m.showMenuAsync (PopupMenu::Options(),ModalCallbackFunction::forComponent (menuCallback, this)); - } + void handleMenuResult (int result) { @@ -745,9 +750,9 @@ public: void resized() override { DocumentWindow::resized(); - #if ! JUCE_MAC + #if ! JUCE_MAC optionsButton.setBounds (8, 6, 60, getTitleBarHeight() - 8); - #endif + #endif } virtual StandalonePluginHolder* getPluginHolder() { return pluginHolder.get(); } @@ -757,6 +762,22 @@ public: PopupMenu menu; private: + void buttonClicked (Button*) override + { + pluginHolder->showAudioSettingsDialog(); + + //PopupMenu m; + //m.addItem (1, TRANS("Audio/MIDI Settings...")); + //m.addSeparator(); + //m.addItem (2, TRANS("Save current state...")); + //m.addItem (3, TRANS("Load a saved state...")); + //m.addSeparator(); + //m.addItem (4, TRANS("Reset to default state")); + + //m.showMenuAsync (PopupMenu::Options(), + // ModalCallbackFunction::forComponent (menuCallback, this)); + } + //============================================================================== class MainContentComponent : public Component, private Value::Listener, @@ -808,8 +829,9 @@ private: notification.setBounds (r.removeFromTop (NotificationArea::height)); if (editor != nullptr) - editor->setBounds (editor->getLocalArea (this, r) - .withPosition (r.getTopLeft().transformedBy (editor->getTransform().inverted()))); + editor->setBounds (editor->getLocalArea (this, r.toFloat()) + .withPosition (r.getTopLeft().toFloat().transformedBy (editor->getTransform().inverted())) + .toNearestInt()); } private: @@ -824,7 +846,7 @@ private: #if JUCE_IOS || JUCE_ANDROID settingsButton ("Unmute Input") #else - settingsButton ("Settings...") + settingsButton ("Settings") #endif { setOpaque (true); @@ -919,9 +941,9 @@ private: }; //============================================================================== - #if ! JUCE_MAC + #if ! JUCE_MAC TextButton optionsButton; - #endif + #endif JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (StandaloneFilterWindow) }; diff --git a/OB-Xd.jucer b/OB-Xd.jucer index 9aceccb..d71f44f 100644 --- a/OB-Xd.jucer +++ b/OB-Xd.jucer @@ -1,6 +1,6 @@ - + + + @@ -76,7 +80,7 @@ stripLocalSymbols="0" linkTimeOptimisation="0"/> + enablePluginBinaryCopyStep="1"/> @@ -124,7 +128,8 @@ + targetName="OB-Xd" headerPath="../../Modules/asiosdk2.3.2/common" + enablePluginBinaryCopyStep="1"/> diff --git a/Source/Components/PresetBar.cpp b/Source/Components/PresetBar.cpp new file mode 100644 index 0000000..354cb26 --- /dev/null +++ b/Source/Components/PresetBar.cpp @@ -0,0 +1,251 @@ +/* + ============================================================================== + + This is an automatically generated GUI class created by the Projucer! + + Be careful when adding custom code to these files, as only the code within + the "//[xyz]" and "//[/xyz]" sections will be retained when the file is loaded + and re-saved. + + Created with Projucer version: 6.0.8 + + ------------------------------------------------------------------------------ + + The Projucer is part of the JUCE library. + Copyright (c) 2020 - Raw Material Software Limited. + + ============================================================================== +*/ + +//[Headers] You can add your own extra header files here... +#include "../PluginEditor.h" +//[/Headers] + +#include "PresetBar.h" + + +//[MiscUserDefs] You can add your own user definitions and misc code here... +//[/MiscUserDefs] + +//============================================================================== +PresetBar::PresetBar (ObxdAudioProcessorEditor &gui) + : editor(gui) +{ + //[Constructor_pre] You can add your own custom stuff here.. + //[/Constructor_pre] + + presetNameLb.reset (new juce::Label ("new label", + TRANS("---\n"))); + addAndMakeVisible (presetNameLb.get()); + presetNameLb->setFont (juce::Font (15.00f, juce::Font::plain).withTypefaceStyle ("Regular")); + presetNameLb->setJustificationType (juce::Justification::centred); + presetNameLb->setEditable (false, false, false); + presetNameLb->setColour (juce::TextEditor::textColourId, juce::Colours::black); + presetNameLb->setColour (juce::TextEditor::backgroundColourId, juce::Colour (0x00000000)); + + presetNameLb->setBounds (24, 8, 368, 24); + + previousBtn.reset (new juce::ImageButton ("new button")); + addAndMakeVisible (previousBtn.get()); + previousBtn->setButtonText (juce::String()); + previousBtn->addListener (this); + + previousBtn->setImages (false, true, true, + juce::Image(), 1.000f, juce::Colour (0x00000000), + juce::Image(), 1.000f, juce::Colour (0x00000000), + juce::Image(), 1.000f, juce::Colour (0x00000000)); + previousBtn->setBounds (407, 8, 20, 24); + + nextBtn.reset (new juce::ImageButton ("new button")); + addAndMakeVisible (nextBtn.get()); + nextBtn->setButtonText (juce::String()); + nextBtn->addListener (this); + + nextBtn->setImages (false, true, true, + juce::Image(), 1.000f, juce::Colour (0x00000000), + juce::Image(), 1.000f, juce::Colour (0x00000000), + juce::Image(), 1.000f, juce::Colour (0x00000000)); + nextBtn->setBounds (435, 8, 20, 24); + + drawable1 = juce::Drawable::createFromImageData (presetnavigation_svg, presetnavigation_svgSize); + + //[UserPreSize] + //[/UserPreSize] + + setSize (471, 40); + + + //[Constructor] You can add your own custom stuff here.. + startTimer(500); + //[/Constructor] +} + +PresetBar::~PresetBar() +{ + //[Destructor_pre]. You can add your own custom destruction code here.. + //[/Destructor_pre] + + presetNameLb = nullptr; + previousBtn = nullptr; + nextBtn = nullptr; + drawable1 = nullptr; + + + //[Destructor]. You can add your own custom destruction code here.. + //[/Destructor] +} + +//============================================================================== +void PresetBar::paint (juce::Graphics& g) +{ + //[UserPrePaint] Add your own custom painting code here.. + //[/UserPrePaint] + + g.fillAll (juce::Colours::black); + + { + int x = 0, y = 0, width = 471, height = 40; + //[UserPaintCustomArguments] Customize the painting arguments here.. + //[/UserPaintCustomArguments] + g.setColour (juce::Colours::black); + jassert (drawable1 != nullptr); + if (drawable1 != nullptr) + drawable1->drawWithin (g, juce::Rectangle (x, y, width, height).toFloat(), + juce::RectanglePlacement::centred, 1.000f); + } + + //[UserPaint] Add your own custom painting code here.. + //[/UserPaint] +} + +void PresetBar::resized() +{ + //[UserPreResize] Add your own custom resize code here.. + //[/UserPreResize] + + //[UserResized] Add your own custom resize handling here.. + //[/UserResized] +} + +void PresetBar::buttonClicked (juce::Button* buttonThatWasClicked) +{ + //[UserbuttonClicked_Pre] + //[/UserbuttonClicked_Pre] + + if (buttonThatWasClicked == previousBtn.get()) + { + //[UserButtonCode_previousBtn] -- add your button handler code here.. + editor.prevProgram(); + //[/UserButtonCode_previousBtn] + } + else if (buttonThatWasClicked == nextBtn.get()) + { + //[UserButtonCode_nextBtn] -- add your button handler code here.. + editor.nextProgram(); + //[/UserButtonCode_nextBtn] + } + + //[UserbuttonClicked_Post] + //[/UserbuttonClicked_Post] +} + + + +//[MiscUserCode] You can add your own definitions of your custom methods or any other code here... +void PresetBar::timerCallback() { + update(); +} + +void PresetBar::update(){ + presetNameLb->setText(editor.getCurrentProgramName(), NotificationType::dontSendNotification); +} +//[/MiscUserCode] + + +//============================================================================== +#if 0 +/* -- Projucer information section -- + + This is where the Projucer stores the metadata that describe this GUI layout, so + make changes in here at your peril! + +BEGIN_JUCER_METADATA + + + + + + + +END_JUCER_METADATA +*/ +#endif + +//============================================================================== +// Binary resources - be careful not to edit any of these sections! + +// JUCER_RESOURCE: presetnavigation_svg, 2078, "../../../../GitHub/OB-Xd/Source/Images/presetnavigation.svg" +static const unsigned char resource_PresetBar_presetnavigation_svg[] = { 60,63,120,109,108,32,118,101,114,115,105,111,110,61,34,49,46,48,34,32,101,110,99,111,100,105,110,103,61,34,85,84,70,45,56,34,32, +115,116,97,110,100,97,108,111,110,101,61,34,110,111,34,63,62,10,60,33,68,79,67,84,89,80,69,32,115,118,103,32,80,85,66,76,73,67,32,34,45,47,47,87,51,67,47,47,68,84,68,32,83,86,71,32,49,46,49,47,47,69,78, +34,32,34,104,116,116,112,58,47,47,119,119,119,46,119,51,46,111,114,103,47,71,114,97,112,104,105,99,115,47,83,86,71,47,49,46,49,47,68,84,68,47,115,118,103,49,49,46,100,116,100,34,62,10,60,115,118,103,32, +119,105,100,116,104,61,34,49,48,48,37,34,32,104,101,105,103,104,116,61,34,49,48,48,37,34,32,118,105,101,119,66,111,120,61,34,48,32,48,32,52,55,49,32,51,57,34,32,118,101,114,115,105,111,110,61,34,49,46, +49,34,32,120,109,108,110,115,61,34,104,116,116,112,58,47,47,119,119,119,46,119,51,46,111,114,103,47,50,48,48,48,47,115,118,103,34,32,120,109,108,110,115,58,120,108,105,110,107,61,34,104,116,116,112,58, +47,47,119,119,119,46,119,51,46,111,114,103,47,49,57,57,57,47,120,108,105,110,107,34,32,120,109,108,58,115,112,97,99,101,61,34,112,114,101,115,101,114,118,101,34,32,120,109,108,110,115,58,115,101,114,105, +102,61,34,104,116,116,112,58,47,47,119,119,119,46,115,101,114,105,102,46,99,111,109,47,34,32,115,116,121,108,101,61,34,102,105,108,108,45,114,117,108,101,58,101,118,101,110,111,100,100,59,99,108,105,112, +45,114,117,108,101,58,101,118,101,110,111,100,100,59,115,116,114,111,107,101,45,108,105,110,101,99,97,112,58,114,111,117,110,100,59,115,116,114,111,107,101,45,108,105,110,101,106,111,105,110,58,114,111, +117,110,100,59,115,116,114,111,107,101,45,109,105,116,101,114,108,105,109,105,116,58,49,46,53,59,34,62,10,32,32,32,32,60,114,101,99,116,32,120,61,34,48,34,32,121,61,34,48,34,32,119,105,100,116,104,61, +34,52,55,49,34,32,104,101,105,103,104,116,61,34,51,57,34,47,62,10,32,32,32,32,60,112,97,116,104,32,100,61,34,77,51,57,56,44,57,46,50,48,53,67,51,57,56,44,55,46,52,51,54,32,51,57,54,46,53,54,52,44,54,32, +51,57,52,46,55,57,53,44,54,76,50,52,46,50,48,53,44,54,67,50,50,46,52,51,54,44,54,32,50,49,44,55,46,52,51,54,32,50,49,44,57,46,50,48,53,76,50,49,44,50,57,46,55,57,53,67,50,49,44,51,49,46,53,54,52,32,50, +50,46,52,51,54,44,51,51,32,50,52,46,50,48,53,44,51,51,76,51,57,52,46,55,57,53,44,51,51,67,51,57,54,46,53,54,52,44,51,51,32,51,57,56,44,51,49,46,53,54,52,32,51,57,56,44,50,57,46,55,57,53,76,51,57,56,44, +57,46,50,48,53,90,34,32,115,116,121,108,101,61,34,115,116,114,111,107,101,58,114,103,98,40,49,50,49,44,49,50,49,44,49,50,49,41,59,115,116,114,111,107,101,45,119,105,100,116,104,58,49,112,120,59,34,47, +62,10,32,32,32,32,60,103,32,116,114,97,110,115,102,111,114,109,61,34,109,97,116,114,105,120,40,49,44,48,44,48,44,49,44,52,46,50,50,50,54,54,44,49,49,46,48,50,52,53,41,34,62,10,32,32,32,32,32,32,32,32, +60,103,32,116,114,97,110,115,102,111,114,109,61,34,109,97,116,114,105,120,40,50,52,44,48,44,48,44,50,52,44,52,48,54,46,54,50,49,44,49,55,46,50,54,52,53,41,34,62,10,32,32,32,32,32,32,32,32,32,32,32,32, +60,112,97,116,104,32,100,61,34,77,48,46,52,50,53,44,45,48,46,49,53,54,67,48,46,52,51,53,44,45,48,46,49,52,55,32,48,46,52,51,57,44,45,48,46,49,51,53,32,48,46,52,51,57,44,45,48,46,49,50,50,67,48,46,52,51, +57,44,45,48,46,49,48,57,32,48,46,52,51,53,44,45,48,46,48,57,55,32,48,46,52,50,53,44,45,48,46,48,56,56,67,48,46,52,49,53,44,45,48,46,48,55,56,32,48,46,52,48,52,44,45,48,46,48,55,51,32,48,46,51,57,49,44, +45,48,46,48,55,51,67,48,46,51,55,55,44,45,48,46,48,55,51,32,48,46,51,54,54,44,45,48,46,48,55,56,32,48,46,51,53,54,44,45,48,46,48,56,55,76,48,46,49,49,50,44,45,48,46,51,51,50,67,48,46,49,48,50,44,45,48, +46,51,52,49,32,48,46,48,57,56,44,45,48,46,51,53,51,32,48,46,48,57,56,44,45,48,46,51,54,54,67,48,46,48,57,56,44,45,48,46,51,56,32,48,46,49,48,51,44,45,48,46,51,57,49,32,48,46,49,49,50,44,45,48,46,52,48, +49,76,48,46,51,53,54,44,45,48,46,54,52,53,67,48,46,51,54,54,44,45,48,46,54,53,52,32,48,46,51,55,55,44,45,48,46,54,53,57,32,48,46,51,57,49,44,45,48,46,54,53,57,67,48,46,52,48,52,44,45,48,46,54,53,57,32, +48,46,52,49,53,44,45,48,46,54,53,52,32,48,46,52,50,53,44,45,48,46,54,52,53,67,48,46,52,51,53,44,45,48,46,54,51,53,32,48,46,52,51,57,44,45,48,46,54,50,52,32,48,46,52,51,57,44,45,48,46,54,49,67,48,46,52, +51,57,44,45,48,46,53,57,55,32,48,46,52,51,53,44,45,48,46,53,56,53,32,48,46,52,50,53,44,45,48,46,53,55,54,76,48,46,50,49,53,44,45,48,46,51,54,54,76,48,46,52,50,53,44,45,48,46,49,53,54,90,34,32,115,116, +121,108,101,61,34,102,105,108,108,58,114,103,98,40,49,50,49,44,49,50,49,44,49,50,49,41,59,102,105,108,108,45,114,117,108,101,58,110,111,110,122,101,114,111,59,34,47,62,10,32,32,32,32,32,32,32,32,60,47, +103,62,10,32,32,32,32,60,47,103,62,10,32,32,32,32,60,103,32,116,114,97,110,115,102,111,114,109,61,34,109,97,116,114,105,120,40,49,44,48,44,48,44,49,44,51,49,46,50,50,50,55,44,49,49,46,48,50,52,53,41,34, +62,10,32,32,32,32,32,32,32,32,60,103,32,116,114,97,110,115,102,111,114,109,61,34,109,97,116,114,105,120,40,50,52,44,48,44,48,44,50,52,44,52,48,54,46,54,50,49,44,49,55,46,50,54,52,53,41,34,62,10,32,32, +32,32,32,32,32,32,32,32,32,32,60,112,97,116,104,32,100,61,34,77,48,46,51,50,50,44,45,48,46,51,54,54,76,48,46,49,49,50,44,45,48,46,53,55,54,67,48,46,49,48,51,44,45,48,46,53,56,53,32,48,46,48,57,56,44,45, +48,46,53,57,55,32,48,46,48,57,56,44,45,48,46,54,49,67,48,46,48,57,56,44,45,48,46,54,50,52,32,48,46,49,48,50,44,45,48,46,54,51,53,32,48,46,49,49,50,44,45,48,46,54,52,53,67,48,46,49,50,50,44,45,48,46,54, +53,52,32,48,46,49,51,51,44,45,48,46,54,53,57,32,48,46,49,52,54,44,45,48,46,54,53,57,67,48,46,49,54,44,45,48,46,54,53,57,32,48,46,49,55,49,44,45,48,46,54,53,52,32,48,46,49,56,49,44,45,48,46,54,52,53,76, +48,46,52,50,53,44,45,48,46,52,48,49,67,48,46,52,51,53,44,45,48,46,51,57,49,32,48,46,52,51,57,44,45,48,46,51,56,32,48,46,52,51,57,44,45,48,46,51,54,54,67,48,46,52,51,57,44,45,48,46,51,53,51,32,48,46,52, +51,53,44,45,48,46,51,52,49,32,48,46,52,50,53,44,45,48,46,51,51,50,76,48,46,49,56,49,44,45,48,46,48,56,55,67,48,46,49,55,49,44,45,48,46,48,55,56,32,48,46,49,54,44,45,48,46,48,55,51,32,48,46,49,52,54,44, +45,48,46,48,55,51,67,48,46,49,51,51,44,45,48,46,48,55,51,32,48,46,49,50,50,44,45,48,46,48,55,56,32,48,46,49,49,50,44,45,48,46,48,56,56,67,48,46,49,48,50,44,45,48,46,48,57,55,32,48,46,48,57,56,44,45,48, +46,49,48,57,32,48,46,48,57,56,44,45,48,46,49,50,50,67,48,46,48,57,56,44,45,48,46,49,51,53,32,48,46,49,48,51,44,45,48,46,49,52,55,32,48,46,49,49,50,44,45,48,46,49,53,54,76,48,46,51,50,50,44,45,48,46,51, +54,54,90,34,32,115,116,121,108,101,61,34,102,105,108,108,58,114,103,98,40,49,50,49,44,49,50,49,44,49,50,49,41,59,102,105,108,108,45,114,117,108,101,58,110,111,110,122,101,114,111,59,34,47,62,10,32,32, +32,32,32,32,32,32,60,47,103,62,10,32,32,32,32,60,47,103,62,10,60,47,115,118,103,62,10,0,0}; + +const char* PresetBar::presetnavigation_svg = (const char*) resource_PresetBar_presetnavigation_svg; +const int PresetBar::presetnavigation_svgSize = 2078; + + +//[EndFile] You can add extra defines here... +//[/EndFile] + diff --git a/Source/Components/PresetBar.h b/Source/Components/PresetBar.h new file mode 100644 index 0000000..dd05f21 --- /dev/null +++ b/Source/Components/PresetBar.h @@ -0,0 +1,79 @@ +/* + ============================================================================== + + This is an automatically generated GUI class created by the Projucer! + + Be careful when adding custom code to these files, as only the code within + the "//[xyz]" and "//[/xyz]" sections will be retained when the file is loaded + and re-saved. + + Created with Projucer version: 6.0.8 + + ------------------------------------------------------------------------------ + + The Projucer is part of the JUCE library. + Copyright (c) 2020 - Raw Material Software Limited. + + ============================================================================== +*/ + +#pragma once + +//[Headers] -- You can add your own extra header files here -- +#include +class ObxdAudioProcessorEditor; +//[/Headers] + + + +//============================================================================== +/** + //[Comments] + An auto-generated component, created by the Projucer. + + Describe your class and how it works here! + //[/Comments] +*/ +class PresetBar : public juce::Component, + public Timer, + public juce::Button::Listener +{ +public: + //============================================================================== + PresetBar (ObxdAudioProcessorEditor &gui); + ~PresetBar() override; + + //============================================================================== + //[UserMethods] -- You can add your own custom methods in this section. + void timerCallback() override; + void update(); + //[/UserMethods] + + void paint (juce::Graphics& g) override; + void resized() override; + void buttonClicked (juce::Button* buttonThatWasClicked) override; + + // Binary resources: + static const char* presetnavigation_svg; + static const int presetnavigation_svgSize; + + +private: + //[UserVariables] -- You can add your own custom variables in this section. + ObxdAudioProcessorEditor &editor; + //[/UserVariables] + + //============================================================================== + std::unique_ptr presetNameLb; + std::unique_ptr previousBtn; + std::unique_ptr nextBtn; + std::unique_ptr drawable1; + + + //============================================================================== + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (PresetBar) +}; + +//[EndFile] You can add extra defines here... +//[/EndFile] + diff --git a/Source/Engine/midiMap.h b/Source/Engine/midiMap.h index d17396b..972a30e 100755 --- a/Source/Engine/midiMap.h +++ b/Source/Engine/midiMap.h @@ -31,6 +31,8 @@ public: int controllers[255]; int controllers_default[255]; + std::map mapping; + bool loaded = false; MidiMap() { @@ -39,243 +41,320 @@ public: } void reset(){ for(int i = 0 ; i < 255;i++){ - controllers[i] = 0; - controllers_default[i] = 0; + controllers[i] = -1; + controllers_default[i] = -1; } } void set_default(){ int midicc = 71; controllers[midicc] = controllers_default[midicc] = VOLUME; + mapping["VOLUME"]=VOLUME; midicc = 15; controllers[midicc] = controllers_default[midicc] = VOICE_COUNT; + mapping["VOICE_COUNT"]=VOICE_COUNT; midicc = 33; controllers[midicc] = controllers_default[midicc] = TUNE; + mapping["TUNE"]=TUNE; + midicc = 17; controllers[midicc] = controllers_default[midicc] = OCTAVE; + mapping["OCTAVE"]=OCTAVE; midicc = 118; controllers[midicc] = controllers_default[midicc] = BENDRANGE; + mapping["BENDRANGE"]=BENDRANGE; midicc = 34; controllers[midicc] = controllers_default[midicc] = BENDOSC2; + mapping["BENDOSC2"]=BENDOSC2; midicc = 35; controllers[midicc] = controllers_default[midicc] = LEGATOMODE; + mapping["LEGATOMODE"]=LEGATOMODE; midicc = 75; controllers[midicc] = controllers_default[midicc] = BENDLFORATE; + mapping["BENDLFORATE"]=BENDLFORATE; midicc = 76; controllers[midicc] = controllers_default[midicc] = VFLTENV; + mapping["VFLTENV"]=VFLTENV; midicc = 20; controllers[midicc] = controllers_default[midicc] = VAMPENV; + mapping["VAMPENV"]=VAMPENV; midicc = 21; controllers[midicc] = controllers_default[midicc] = ASPLAYEDALLOCATION; + mapping["ASPLAYEDALLOCATION"]=ASPLAYEDALLOCATION; midicc = 23; controllers[midicc] = controllers_default[midicc] = PORTAMENTO; + mapping["PORTAMENTO"]=PORTAMENTO; midicc = 16; controllers[midicc] = controllers_default[midicc] = UNISON; + mapping["UNISON"]=UNISON; midicc = 24; controllers[midicc] = controllers_default[midicc] = UDET; + mapping["UDET"]=UDET; midicc = 43; controllers[midicc] = controllers_default[midicc] = OSC2_DET; + mapping["OSC2_DET"]=OSC2_DET; midicc = 19; controllers[midicc] = controllers_default[midicc] = LFOFREQ; + mapping["LFOFREQ"]=LFOFREQ; midicc = 44; controllers[midicc] = controllers_default[midicc] = LFOSINWAVE; + mapping["LFOSINWAVE"]=LFOSINWAVE; midicc = 45; controllers[midicc] = controllers_default[midicc] = LFOSQUAREWAVE; + mapping["LFOSQUAREWAVE"]=LFOSQUAREWAVE; midicc = 46; controllers[midicc] = controllers_default[midicc] = LFOSHWAVE; + mapping["LFOSHWAVE"]=LFOSHWAVE; midicc = 22; controllers[midicc] = controllers_default[midicc] = LFO1AMT; + mapping["LFO1AMT"]=LFO1AMT; midicc = 25; controllers[midicc] = controllers_default[midicc] = LFO2AMT; + mapping["LFO2AMT"]=LFO2AMT; midicc = 47; controllers[midicc] = controllers_default[midicc] = LFOOSC1; + mapping["LFOOSC1"]=LFOOSC1; midicc = 48; controllers[midicc] = controllers_default[midicc] = LFOOSC2; + mapping["LFOOSC2"]=LFOOSC2; midicc = 49; controllers[midicc] = controllers_default[midicc] = LFOFILTER; + mapping["LFOFILTER"]=LFOFILTER; midicc = 50; controllers[midicc] = controllers_default[midicc] = LFOPW1; + mapping["LFOPW1"]=LFOPW1; midicc = 51; controllers[midicc] = controllers_default[midicc] = LFOPW2; + mapping["LFOPW2"]=LFOPW2; midicc = 52; controllers[midicc] = controllers_default[midicc] = OSC2HS; + mapping["OSC2HS"]=OSC2HS; midicc = 53; controllers[midicc] = controllers_default[midicc] = XMOD; + mapping["XMOD"]=XMOD; midicc = 54; controllers[midicc] = controllers_default[midicc] = OSC1P; + mapping["OSC1P"]=OSC1P; midicc = 55; controllers[midicc] = controllers_default[midicc] = OSC2P; + mapping["OSC2P"]=OSC2P; midicc = 56; controllers[midicc] = controllers_default[midicc] = OSCQuantize; + mapping["OSCQuantize"]=OSCQuantize; midicc = 57; controllers[midicc] = controllers_default[midicc] = OSC1Saw; + mapping["OSC1Saw"]=OSC1Saw; midicc = 58; controllers[midicc] = controllers_default[midicc] = OSC1Pul; + mapping["OSC1Pul"]=OSC1Pul; midicc = 59; controllers[midicc] = controllers_default[midicc] = OSC2Saw; + mapping["OSC2Saw"]=OSC2Saw; midicc = 60; controllers[midicc] = controllers_default[midicc] = OSC2Pul; + mapping["OSC2Pul"]=OSC2Pul; midicc = 61; controllers[midicc] = controllers_default[midicc] = PW; + mapping["PW"]=PW; midicc = 62; controllers[midicc] = controllers_default[midicc] = BRIGHTNESS; + mapping["BRIGHTNESS"]=BRIGHTNESS; midicc = 63; controllers[midicc] = controllers_default[midicc] = ENVPITCH; + mapping["ENVPITCH"]=ENVPITCH; midicc = 77; controllers[midicc] = controllers_default[midicc] = OSC1MIX; - + mapping["OSC1MIX"]=OSC1MIX; + midicc = 78; controllers[midicc] = controllers_default[midicc] = OSC2MIX; + mapping["OSC2MIX"]=OSC2MIX; midicc = 102; controllers[midicc] = controllers_default[midicc] = NOISEMIX; + mapping["NOISEMIX"]=NOISEMIX; midicc = 103; controllers[midicc] = controllers_default[midicc] = FLT_KF; + mapping["FLT_KF"]=FLT_KF; midicc = 74; controllers[midicc] = controllers_default[midicc] = CUTOFF; + mapping["CUTOFF"]=CUTOFF; midicc = 42; controllers[midicc] = controllers_default[midicc] = RESONANCE; + mapping["RESONANCE"]=RESONANCE; midicc = 104; controllers[midicc] = controllers_default[midicc] = MULTIMODE; + mapping["MULTIMODE"]=MULTIMODE; midicc = 18; controllers[midicc] = controllers_default[midicc] = FILTER_WARM; + mapping["FILTER_WARM"]=FILTER_WARM; midicc = 105; controllers[midicc] = controllers_default[midicc] = BANDPASS; + mapping["BANDPASS"]=BANDPASS; midicc = 106; controllers[midicc] = controllers_default[midicc] = FOURPOLE; + mapping["FOURPOLE"]=FOURPOLE; midicc = 107; controllers[midicc] = controllers_default[midicc] = ENVELOPE_AMT; + mapping["ENVELOPE_AMT"]=ENVELOPE_AMT; midicc = 73; controllers[midicc] = controllers_default[midicc] = LATK; + mapping["LATK"]=LATK; midicc = 36; controllers[midicc] = controllers_default[midicc] = LDEC; + mapping["LDEC"]=LDEC; midicc = 37; controllers[midicc] = controllers_default[midicc] = LSUS; + mapping["LSUS"]=LSUS; midicc = 72; controllers[midicc] = controllers_default[midicc] = LREL; + mapping["LREL"]=LREL; midicc = 38; controllers[midicc] = controllers_default[midicc] = FATK; + mapping["FATK"]=FATK; midicc = 39; controllers[midicc] = controllers_default[midicc] = FDEC; + mapping["FDEC"]=FDEC; midicc = 40; controllers[midicc] = controllers_default[midicc] = FSUS; + mapping["FSUS"]=FSUS; midicc = 41; controllers[midicc] = controllers_default[midicc] = FREL; + mapping["FREL"]=FREL; midicc = 108; controllers[midicc] = controllers_default[midicc] = ENVDER; + mapping["ENVDER"]=ENVDER; midicc = 109; controllers[midicc] = controllers_default[midicc] = FILTERDER; + mapping["FILTERDER"]=FILTERDER; midicc = 110; controllers[midicc] = controllers_default[midicc] = PORTADER; + mapping["PORTADER"]=PORTADER; midicc = 81; controllers[midicc] = controllers_default[midicc] = PAN1; + mapping["PAN1"]=PAN1; midicc = 82; controllers[midicc] = controllers_default[midicc] = PAN2; + mapping["PAN2"]=PAN2; midicc = 83; controllers[midicc] = controllers_default[midicc] = PAN3; + mapping["PAN3"]=PAN3; midicc = 84; controllers[midicc] = controllers_default[midicc] = PAN4; + mapping["PAN4"]=PAN4; midicc = 85; controllers[midicc] = controllers_default[midicc] = PAN5; + mapping["PAN5"]=PAN5; midicc = 86; controllers[midicc] = controllers_default[midicc] = PAN6; + mapping["PAN6"]=PAN6; midicc = 87; controllers[midicc] = controllers_default[midicc] = PAN7; + mapping["PAN7"]=PAN7; midicc = 88; controllers[midicc] = controllers_default[midicc] = PAN8; + mapping["PAN8"]=PAN8; midicc = 111; controllers[midicc] = controllers_default[midicc] = ECONOMY_MODE; + mapping["ECONOMY_MODE"]=ECONOMY_MODE; //midicc = 112; //controllers[midicc] = controllers_default[midicc] = LFO_SYNC; midicc = 113; controllers[midicc] = controllers_default[midicc] = PW_ENV; + mapping["PW_ENV"]=PW_ENV; midicc = 114; controllers[midicc] = controllers_default[midicc] = PW_ENV_BOTH; + mapping["PW_ENV_BOTH"]=PW_ENV_BOTH; midicc = 115; controllers[midicc] = controllers_default[midicc] = ENV_PITCH_BOTH; + mapping["ENV_PITCH_BOTH"]=ENV_PITCH_BOTH; midicc = 116; controllers[midicc] = controllers_default[midicc] = FENV_INVERT; + mapping["FENV_INVERT"]=FENV_INVERT; midicc = 117; controllers[midicc] = controllers_default[midicc] = PW_OSC2_OFS; + mapping["PW_OSC2_OFS"]=PW_OSC2_OFS; midicc = 118; controllers[midicc] = controllers_default[midicc] = LEVEL_DIF; + mapping["LEVEL_DIF"]=LEVEL_DIF; midicc = 119; controllers[midicc] = controllers_default[midicc] = SELF_OSC_PUSH; - + mapping["SELF_OSC_PUSH"]=SELF_OSC_PUSH; + } @@ -290,19 +369,31 @@ public: void setXml( XmlElement &xml){ for (int i = 0; i < 255; ++i) { - xml.setAttribute("Val_" + String(i), controllers[i]); + if (controllers[i]!= -1){ + xml.setAttribute("MIDI_" +String(i), getTag(controllers[i])); + } } } + String getTag(int paraId){ + for (std::map::iterator it = this->mapping.begin(); it != this->mapping.end(); it ++){ + if (paraId == it->second){ + return it->first; + } + } + return "undefine"; + } + + int getParaId(String tagName){ + return mapping[tagName]; + } void getXml(XmlElement &xml){ for (int i = 0; i < 255; ++i) { - int tmp = xml.getIntAttribute("Val_" + String(i), controllers_default[i]); - if (tmp == 0){ - tmp = controllers_default[i]; + String tmp = xml.getStringAttribute("MIDI_" + String(i), "undefine"); + if (tmp != "undefine"){ + controllers[i] = getParaId(tmp); } - - controllers[i] = tmp; } // Backward keys @@ -316,4 +407,35 @@ public: } } + bool loadFile(File& xml){ + reset(); + set_default(); + if (xml.existsAsFile()){ + XmlDocument xmlDoc (xml); + this->getXml(*xmlDoc.getDocumentElement()); + return true; + } + + return false; + } + + void updateCC(int idx_para, int midiCC) { + for (int i =0; i < 255; i++) { + if (controllers[i] == idx_para){ + controllers[i] = -1; + } + } + controllers[midiCC] = idx_para; + } + + void saveFile(File& xml){ + XmlElement ele("Data"); + this->setXml(ele); + ele.writeToFile(xml, String()); + } + + void clean(){ + reset(); + } + }; diff --git a/Source/Images/presetnavigation.svg b/Source/Images/presetnavigation.svg new file mode 100644 index 0000000..244979f --- /dev/null +++ b/Source/Images/presetnavigation.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/Source/PluginEditor.cpp b/Source/PluginEditor.cpp index 40bf916..3c4f454 100755 --- a/Source/PluginEditor.cpp +++ b/Source/PluginEditor.cpp @@ -45,12 +45,14 @@ ObxdAudioProcessorEditor::ObxdAudioProcessorEditor (ObxdAudioProcessor& ownerFil getTopLevelComponent()->addKeyListener (commandManager.getKeyMappings()); //Timer::callAfterDelay (100, [this] { this->grabKeyboardFocus(); }); // ensure that key presses are sent to the KeyPressTarget object -#if JUCE_WINDOWS - // No run timer to grab component on window -#else + startTimer(100); // This will fix the issue -#endif + + + DBG("W: " <getTagName() == "PROPERTIES"){ - + forEachXmlChildElementWithTagName(*doc, child, "VALUE"){ if (child->hasAttribute("NAME") && child->hasAttribute("x") && child->hasAttribute("y")) { String name = child->getStringAttribute("NAME"); @@ -115,7 +117,17 @@ void ObxdAudioProcessorEditor::loadSkin (ObxdAudioProcessor& ownerFilter) int w = child->getIntAttribute("w"); int h = child->getIntAttribute("h"); - if (name == "guisize"){ setSize (x, y); } + if (name == "guisize"){ + xScreen = x; + yScreen = y; + if (processor.getShowPresetBar()) { + setSize(xScreen, yScreen +40); + } + else { + setSize(xScreen, yScreen); + } + + } if (name == "resonanceKnob"){ resonanceKnob = addKnob (x, y, d, ownerFilter, RESONANCE, "Resonance", 0); } if (name == "cutoffKnob"){ cutoffKnob = addKnob (x, y, d, ownerFilter, CUTOFF, "Cutoff", 0.4); } @@ -239,6 +251,17 @@ void ObxdAudioProcessorEditor::loadSkin (ObxdAudioProcessor& ownerFilter) } } } + + + presetBar.reset(new PresetBar(*this)); + addAndMakeVisible(*presetBar); + presetBar->setVisible(processor.getShowPresetBar()); + + + presetBar->setBounds( + (xScreen - presetBar->getWidth()) / 2, yScreen, presetBar->getWidth(), presetBar->getHeight()); + + updatePresetBar(false); } // Prepare data @@ -264,7 +287,10 @@ void ObxdAudioProcessorEditor::loadSkin (ObxdAudioProcessor& ownerFilter) } createMenu(); + ownerFilter.addChangeListener (this); + + repaint(); } ObxdAudioProcessorEditor::~ObxdAudioProcessorEditor() @@ -408,6 +434,8 @@ void ObxdAudioProcessorEditor::createMenu () PopupMenu bankMenu; PopupMenu skinMenu; PopupMenu fileMenu; + PopupMenu viewMenu; + PopupMenu midiMenu; skins = processor.getSkinFiles(); banks = processor.getBankFiles(); { @@ -505,12 +533,62 @@ void ObxdAudioProcessorEditor::createMenu () menu->addSubMenu ("Themes", skinMenu); // About // menu.addItem(1, String("Release ") + String(JucePlugin_VersionString).dropLastCharacters(2), false); } - + viewMenu.addItem(progStart + 1000, "Preset Bar", true, processor.showPresetBar); + menu->addSubMenu ("View", viewMenu); + menuMidiNum = progStart +2000; + createMidi(menuMidiNum, midiMenu); + menu->addSubMenu ("MIDI", midiMenu); popupMenus.add (menu); } +void ObxdAudioProcessorEditor::createMidi(int menuNo, PopupMenu &menuMidi) { + File midi_dir = processor.getMidiFolder(); + File default_file = midi_dir.getChildFile("Default.xml"); + if(default_file.exists()){ + if (processor.currentMidiPath != default_file.getFullPathName()){ + menuMidi.addItem(menuNo++, default_file.getFileNameWithoutExtension(), true, false); + } else { + menuMidi.addItem(menuNo++, default_file.getFileNameWithoutExtension(), true, true); + } + midiFiles.add(default_file.getFullPathName()); + } + + File custom_file = midi_dir.getChildFile("Custom.xml"); + + if(custom_file.exists()){ + if (processor.currentMidiPath != custom_file.getFullPathName()){ + menuMidi.addItem(menuNo++, custom_file.getFileNameWithoutExtension(), true, false); + } else { + menuMidi.addItem(menuNo++, custom_file.getFileNameWithoutExtension(), true, true); + } + midiFiles.add(custom_file.getFullPathName()); + } + + DirectoryIterator iter (midi_dir, true, "*.xml"); + StringArray list; + while (iter.next()) + { + list.add(iter.getFile().getFullPathName()); + } + + list.sort(true); + + for (int i =0; i < list.size() ; i ++){ + File f (list[i]); + if (f.getFileNameWithoutExtension() != "Default" && f.getFileNameWithoutExtension() != "Custom" && f.getFileNameWithoutExtension() != "Config") { + if (processor.currentMidiPath != f.getFullPathName()){ + menuMidi.addItem(menuNo++, f.getFileNameWithoutExtension(), true, false); + } else { + menuMidi.addItem(menuNo++, f.getFileNameWithoutExtension(), true, true); + } + midiFiles.add(f.getFullPathName()); + } + } +} + void ObxdAudioProcessorEditor::resultFromMenu (const Point pos) { + createMenu(); int result = popupMenus[0]->showAt (Rectangle (pos.getX(), pos.getY(), 1, 1)); if (result >= (skinStart + 1) && result <= (skinStart + skins.size())) @@ -546,6 +624,43 @@ void ObxdAudioProcessorEditor::resultFromMenu (const Point pos) else if (result < progStart){ MenuActionCallback(result); } + else if (result == progStart + 1000){ + processor.setShowPresetBar(!processor.getShowPresetBar()); + //createMenu(); + updatePresetBar(); + } + else if (result >= menuMidiNum){ + unsigned int selected_idx = result - menuMidiNum; + if (selected_idx >= 0 && selected_idx < midiFiles.size()){ + File f(midiFiles[selected_idx]); + if (f.exists()) { + processor.currentMidiPath = midiFiles[selected_idx]; + processor.bindings.loadFile(f); + processor.updateConfig(); + + //createMenu(); + } + } + } +} + +void ObxdAudioProcessorEditor::updatePresetBar(bool resize){ + DBG(" H: " << getHeight() <<" W:" <getWidth() << " CH" <getHeight() << " CX:" <getX() << " CY: " <getY()); + + if (processor.getShowPresetBar()) { + if (resize) { + this->setSize(this->getWidth(), this->getHeight() + 40); + } + presetBar->setVisible(true); + } + else if (presetBar->isVisible()) { + if (resize) { + this->setSize(this->getWidth(), this->getHeight() - 40); + } + presetBar->setVisible(false); + } + presetBar->update(); + } void ObxdAudioProcessorEditor::MenuActionCallback(int action){ @@ -563,7 +678,7 @@ void ObxdAudioProcessorEditor::MenuActionCallback(int action){ if (result == file || result.copyFileTo(file)){ processor.loadFromFXBFile(file); processor.scanAndUpdateBanks(); - createMenu(); + //createMenu(); } } }; @@ -619,7 +734,7 @@ void ObxdAudioProcessorEditor::MenuActionCallback(int action){ if (name.isNotEmpty()) { processor.newPreset(name); - createMenu(); + //createMenu(); } } @@ -648,7 +763,7 @@ void ObxdAudioProcessorEditor::MenuActionCallback(int action){ if (name.isNotEmpty()) { processor.changePresetName(name); - createMenu(); + //createMenu(); } } @@ -666,7 +781,7 @@ void ObxdAudioProcessorEditor::MenuActionCallback(int action){ { if(NativeMessageBox::showOkCancelBox(AlertWindow::NoIcon, "Delete Preset", "Delete current preset " + processor.currentPreset + "?")){ processor.deletePreset(); - createMenu(); + //createMenu(); } return; } @@ -684,7 +799,7 @@ void ObxdAudioProcessorEditor::MenuActionCallback(int action){ DBG("Import Preset: " << result.getFileName()); //if (result == file || result.copyFileTo(file)){ processor.loadPreset(result); - createMenu(); + //createMenu(); //} } }; @@ -722,7 +837,11 @@ void ObxdAudioProcessorEditor::nextProgram() { if (cur == processor.getNumPrograms()) { cur = 0; } - processor.setCurrentProgram (cur); + processor.setCurrentProgram (cur, false); + + needNotifytoHost = true; + countTimer = 0; + clean(); loadSkin (processor); } @@ -731,7 +850,11 @@ void ObxdAudioProcessorEditor::prevProgram() { if (cur < 0) { cur = processor.getNumPrograms() - 1; } - processor.setCurrentProgram (cur); + processor.setCurrentProgram (cur, false); + + needNotifytoHost = true; + countTimer = 0; + clean(); loadSkin (processor); } @@ -754,6 +877,7 @@ void ObxdAudioProcessorEditor::buttonClicked (Button* b) auto toggleButton = dynamic_cast (b); if (toggleButton == midiUnlearnButton){ if (midiUnlearnButton->getToggleState()){ + countTimerForLed = 0; processor.getMidiMap().reset(); processor.getMidiMap().set_default(); processor.sendChangeMessage(); @@ -781,9 +905,10 @@ void ObxdAudioProcessorEditor::updateFromHost() { } // Set to unlearn to false - if ( midiUnlearnButton && midiUnlearnButton->getToggleState()) { - midiUnlearnButton->setToggleState(false, NotificationType:: sendNotification); - } + //if ( midiUnlearnButton && midiUnlearnButton->getToggleState()) { + // Thread::sleep(500); + // midiUnlearnButton->setToggleState(false, NotificationType:: sendNotification); + //} repaint(); } @@ -838,6 +963,67 @@ void ObxdAudioProcessorEditor::paint(Graphics& g) } + +bool ObxdAudioProcessorEditor::isInterestedInFileDrag(const StringArray& files) +{ + StringArray extensions; + extensions.add(".fxp"); + extensions.add(".fxb"); + + if (files.size() == 1) { + File file = File(files[0]); + String ext = file.getFileExtension().toLowerCase(); + return file.existsAsFile() && extensions.contains(ext); + } else { + for (int q = 0; q < files.size(); q++) { + File file = File(files[q]); + String ext = file.getFileExtension().toLowerCase(); + + if (ext == ".fxb" || ext == ".fxp") { + return true; + } + } + } + return false; +} + +void ObxdAudioProcessorEditor::filesDropped(const StringArray& files, int x, int y) +{ + if (files.size() == 1) { + File file = File(files[0]); + String ext = file.getFileExtension().toLowerCase(); + + if (ext == ".fxp") { + processor.loadPreset(file); + //createMenu(); + } else if (ext == ".fxb") { + auto name = file.getFileName().replace("%20", " "); + auto result = processor.getBanksFolder().getChildFile(name); + + if (file.copyFileTo(result)){ + processor.loadFromFXBFile(result); + processor.scanAndUpdateBanks(); + //createMenu(); + } + } + } else { + int i = processor.getCurrentProgram(); + + for (int q = 0; q < files.size(); q++) { + File file = File(files[q]); + String ext = file.getFileExtension().toLowerCase(); + if (ext == ".fxp") { + processor.setCurrentProgram(i++); + processor.loadPreset(file); + } + if (i >=processor.getNumPrograms()){ + i = 0; + } + } + processor.sendChangeMessage(); + //createMenu(); + } +} /* bool ObxdAudioProcessorEditor::keyPressed(const KeyPress & press) { if (press.getKeyCode() == '+' || press.getKeyCode() == KeyPress::numberPadAdd) diff --git a/Source/PluginEditor.h b/Source/PluginEditor.h index 7d63dbd..e39564c 100755 --- a/Source/PluginEditor.h +++ b/Source/PluginEditor.h @@ -18,7 +18,7 @@ #include "Gui/TooglableButton.h" #include "Gui/ButtonList.h" #include "Components/SetPresetNameWindow.h" - +#include "Components/PresetBar.h" enum KeyPressCommandIDs { buttonNextProgram = 1, @@ -55,24 +55,46 @@ class ObxdAudioProcessorEditor : public AudioProcessorEditor // , public ComboBox::Listener , public ApplicationCommandTarget , public Timer + , public FileDragAndDropTarget { public: ObxdAudioProcessorEditor(ObxdAudioProcessor& ownerFilter); ~ObxdAudioProcessorEditor(); - + + bool isInterestedInFileDrag(const StringArray& files) override; + void filesDropped(const StringArray& files, int x, int y) override; void mouseUp (const MouseEvent& e) override; void paint (Graphics& g) override; void updateFromHost(); - + String getCurrentProgramName(){ + return processor.getProgramName(processor.getCurrentProgram()); + } + void updatePresetBar(bool resize=true); //============================================================================== void changeListenerCallback (ChangeBroadcaster* source) override; void buttonClicked (Button *) override; //bool keyPressed(const KeyPress & press) override; void timerCallback() override { +#if JUCE_WINDOWS || JUCE_LINUX + // No run timer to grab component on window +#else this->grabKeyboardFocus(); +#endif + countTimer ++; + if (countTimer == 4 && needNotifytoHost){ + countTimer = 0; + needNotifytoHost= false; + processor.updateHostDisplay(); + } + + countTimerForLed++; + if (midiUnlearnButton && midiUnlearnButton->getToggleState() && countTimerForLed > 3) { + midiUnlearnButton->setToggleState(false, NotificationType::sendNotification); + countTimerForLed = 0; + } } ApplicationCommandTarget* getNextCommandTarget() override { return nullptr; @@ -151,9 +173,11 @@ private: ButtonList* addList(int x, int y, int w, int h, ObxdAudioProcessor& filter, int parameter, String name, Image img); void addMenuButton (int x, int y, int d, const Image&); void createMenu (); + void createMidi(int, PopupMenu &); void resultFromMenu (const Point); void clean(); + void rebuildComponents (ObxdAudioProcessor&); void loadSkin(ObxdAudioProcessor&); //============================================================================== @@ -248,12 +272,21 @@ private: int progStart; int bankStart; int skinStart; + Array skins; Array banks; std::unique_ptr setPresetNameWindow; + std::unique_ptr presetBar; std::unique_ptr fileChooser; // Command manager ApplicationCommandManager commandManager; + int countTimer =0; + bool needNotifytoHost = false; + + Array midiFiles; + int menuMidiNum; + int countTimerForLed = 0; + }; #endif // PLUGINEDITOR_H_INCLUDED diff --git a/Source/PluginProcessor.cpp b/Source/PluginProcessor.cpp index 37aa386..4547608 100755 --- a/Source/PluginProcessor.cpp +++ b/Source/PluginProcessor.cpp @@ -70,7 +70,7 @@ ObxdAudioProcessor::ObxdAudioProcessor() options.millisecondsBeforeSaving = 2500; options.processLock = &configLock; config = std::unique_ptr (new PropertiesFile (getDocumentFolder().getChildFile ("Skin.xml"), options)); - + showPresetBar = config->getBoolValue("presetnavigation"); currentSkin = config->containsKey("skin") ? config->getValue("skin") : "Ilkka Rosma Dark"; currentBank = "000 - FMR OB-Xa Patch Book"; @@ -89,10 +89,12 @@ ObxdAudioProcessor::ObxdAudioProcessor() } apvtState.state = ValueTree (JucePlugin_Name); + initMidi(); } ObxdAudioProcessor::~ObxdAudioProcessor() { + config->saveIfNeeded(); config = nullptr; } @@ -166,6 +168,23 @@ int ObxdAudioProcessor::getCurrentProgram() return programs.currentProgram; } +void ObxdAudioProcessor::setCurrentProgram (int index, bool updateHost){ + programs.currentProgram = index; + programs.currentProgramPtr = programs.programs + programs.currentProgram; + isHostAutomatedChange = false; + + for (int i = 0; i < PARAM_COUNT; ++i) + setEngineParameterValue (i, programs.currentProgramPtr->values[i], true); + + isHostAutomatedChange = true; + + sendChangeMessage(); + // Will delay + if (updateHost) { + updateHostDisplay(); + } +} + void ObxdAudioProcessor::setCurrentProgram (int index) { programs.currentProgram = index; @@ -253,11 +272,18 @@ inline void ObxdAudioProcessor::processMidiPerSample (MidiBuffer::Iterator* iter lastMovedController = midiMsg->getControllerNumber(); if (programs.currentProgramPtr->values[MIDILEARN] > 0.5f){ midiControlledParamSet = true; - bindings[lastMovedController] = lastUsedParameter; + //bindings[lastMovedController] = lastUsedParameter; + bindings.updateCC(lastUsedParameter, lastMovedController); + File midi_file = getMidiFolder().getChildFile("Custom.xml"); + bindings.saveFile(midi_file); + currentMidiPath = midi_file.getFullPathName(); + setEngineParameterValue (MIDILEARN, 0, true); lastMovedController = 0; lastUsedParameter = 0; midiControlledParamSet = false; + + } if (bindings[lastMovedController] > 0) @@ -355,7 +381,7 @@ void ObxdAudioProcessor::getStateInformation(MemoryBlock& destData) xmlState.addChildElement(xprogs); - bindings.setXml(xmlState); + //bindings.setXml(xmlState); copyXmlToBinary(xmlState, destData); } @@ -412,7 +438,7 @@ void ObxdAudioProcessor::setStateInformation(const void* data, int sizeInBytes) } } - bindings.getXml(*xmlState); + //bindings.getXml(*xmlState); #if ! DEMOVERSION setCurrentProgram(xmlState->getIntAttribute(S("currentProgram"), 0)); @@ -506,12 +532,14 @@ bool ObxdAudioProcessor::saveFXPFile(const File& fxpFile){ fxpFile.replaceWithData(memoryBlock.getData(), memoryBlock.getSize()); } + return true; } bool ObxdAudioProcessor::savePreset(const File& fxpFile) { saveFXPFile(fxpFile); currentPreset = fxpFile.getFileName(); currentPresetFile = fxpFile; + return true; } void ObxdAudioProcessor::changePresetName(const String &name){ @@ -653,6 +681,7 @@ bool ObxdAudioProcessor::loadFromFXBFile(const File& fxbFile) return false; setStateInformation(cset->chunk, fxbSwap (cset->chunkSize)); + setCurrentProgram(0); // Set to first preset position } else if (compareMagic (set->fxMagic, "FPCh")) { @@ -760,6 +789,12 @@ File ObxdAudioProcessor::getBanksFolder() const return getDocumentFolder().getChildFile("Banks"); } +File ObxdAudioProcessor::getMidiFolder() const +{ + return getDocumentFolder().getChildFile("Midi"); +} + + File ObxdAudioProcessor::getPresetsFolder() const { return getDocumentFolder().getChildFile("Presets"); @@ -1165,3 +1200,42 @@ AudioProcessor* JUCE_CALLTYPE createPluginFilter() { return new ObxdAudioProcessor(); } + + + +void ObxdAudioProcessor::initMidi(){ + //Documents > Obxd > MIDI > Default.xml + File default_file = getMidiFolder().getChildFile("Default.xml"); + if (!default_file.exists()){ + bindings.saveFile(default_file); + } + + File midi_config_file = getMidiFolder().getChildFile("Config.xml"); + XmlDocument xmlDoc (midi_config_file); + std::unique_ptr ele_file = xmlDoc.getDocumentElementIfTagMatches("File"); + + if (ele_file) { + String file_name = ele_file->getStringAttribute("name"); + // Midi cc loading + File midi_file = getMidiFolder().getChildFile(file_name); + if (bindings.loadFile(midi_file)){ + currentMidiPath = midi_file.getFullPathName(); + } else { + File midi_file = getMidiFolder().getChildFile("Default.xml"); + if (bindings.loadFile(midi_file)){ + currentMidiPath = midi_file.getFullPathName(); + } + } + } +} + +void ObxdAudioProcessor::updateConfig(){ + File midi_config_file = getMidiFolder().getChildFile("Config.xml"); + XmlDocument xmlDoc (midi_config_file); + std::unique_ptr ele_file = xmlDoc.getDocumentElementIfTagMatches("File"); + if (ele_file) { + File f(currentMidiPath); + ele_file->setAttribute("name", f.getFileName()); + ele_file->writeTo(midi_config_file.getFullPathName()); + } +} diff --git a/Source/PluginProcessor.h b/Source/PluginProcessor.h index a03a87d..005dc14 100755 --- a/Source/PluginProcessor.h +++ b/Source/PluginProcessor.h @@ -138,7 +138,7 @@ public: //============================================================================== void initAllParams(); - + void initMidi(); const String getInputChannelName (int channelIndex) const override; // WATCH OUT! const String getOutputChannelName (int channelIndex) const override; // WATCH OUT! bool isInputChannelStereoPair (int index) const override; // WATCH OUT! @@ -153,6 +153,7 @@ public: int getNumPrograms() override; int getCurrentProgram() override; void setCurrentProgram (int index) override; + void setCurrentProgram (int index, bool updateHost); const String getProgramName (int index) override; void changeProgramName (int index, const String& newName) override; @@ -190,6 +191,7 @@ public: File getSkinFolder() const; File getPresetsFolder() const; File getBanksFolder() const; + File getMidiFolder() const; File getCurrentSkinFolder() const; void setCurrentSkinFolder(const String& folderName); @@ -200,7 +202,15 @@ public: void setEngineParameterValue (int, float, bool notifyToHost= false); void parameterChanged (const String&, float) override; AudioProcessorValueTreeState& getPluginState(); - + + bool getShowPresetBar(){ + return this->showPresetBar; + } + + void setShowPresetBar(bool val){ + this->showPresetBar = val; + config->setValue("presetnavigation", this->showPresetBar); + } private: //============================================================================== bool isHostAutomatedChange; @@ -210,7 +220,7 @@ private: MidiMessage* nextMidi; MidiMessage* midiMsg; - MidiMap bindings; + bool midiControlledParamSet; bool hasMidiMessage; @@ -225,10 +235,14 @@ public: File currentBankFile; void saveBank(); - + String currentMidiPath; String currentPreset; File currentPresetFile; void savePreset(); + MidiMap bindings; + bool showPresetBar = false; + + void updateConfig(); private: Array bankFiles; Array skinFiles;