commit
321dc1e304
10 changed files with 746 additions and 41 deletions
BIN
Documents/discoDSP/OB-Xd/Banks/021 - Vivolator.FXB
Normal file
BIN
Documents/discoDSP/OB-Xd/Banks/021 - Vivolator.FXB
Normal file
Binary file not shown.
BIN
Documents/discoDSP/OB-Xd/Banks/022 - Blank Canvas.fxb
Normal file
BIN
Documents/discoDSP/OB-Xd/Banks/022 - Blank Canvas.fxb
Normal file
Binary file not shown.
206
Source/Components/SetPresetNameWindow.cpp
Normal file
206
Source/Components/SetPresetNameWindow.cpp
Normal file
|
@ -0,0 +1,206 @@
|
|||
/*
|
||||
==============================================================================
|
||||
|
||||
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...
|
||||
//[/Headers]
|
||||
|
||||
#include "SetPresetNameWindow.h"
|
||||
|
||||
|
||||
//[MiscUserDefs] You can add your own user definitions and misc code here...
|
||||
//[/MiscUserDefs]
|
||||
|
||||
//==============================================================================
|
||||
SetPresetNameWindow::SetPresetNameWindow ()
|
||||
{
|
||||
//[Constructor_pre] You can add your own custom stuff here..
|
||||
//[/Constructor_pre]
|
||||
|
||||
nameTextEditor.reset (new juce::TextEditor ("nameTextEditor"));
|
||||
addAndMakeVisible (nameTextEditor.get());
|
||||
nameTextEditor->setMultiLine (false);
|
||||
nameTextEditor->setReturnKeyStartsNewLine (false);
|
||||
nameTextEditor->setReadOnly (false);
|
||||
nameTextEditor->setScrollbarsShown (true);
|
||||
nameTextEditor->setCaretVisible (true);
|
||||
nameTextEditor->setPopupMenuEnabled (false);
|
||||
nameTextEditor->setColour (juce::TextEditor::backgroundColourId, juce::Colours::black);
|
||||
nameTextEditor->setColour (juce::CaretComponent::caretColourId, juce::Colours::white);
|
||||
nameTextEditor->setText (juce::String());
|
||||
|
||||
cancel.reset (new juce::TextButton ("cancel"));
|
||||
addAndMakeVisible (cancel.get());
|
||||
cancel->setButtonText (TRANS("Cancel"));
|
||||
cancel->addListener (this);
|
||||
cancel->setColour (juce::TextButton::buttonColourId, juce::Colours::black);
|
||||
|
||||
Ok.reset (new juce::TextButton ("Ok"));
|
||||
addAndMakeVisible (Ok.get());
|
||||
Ok->setButtonText (TRANS("OK"));
|
||||
Ok->addListener (this);
|
||||
Ok->setColour (juce::TextButton::buttonColourId, juce::Colours::black);
|
||||
|
||||
|
||||
//[UserPreSize]
|
||||
cancel->setColour (juce::ComboBox::ColourIds::outlineColourId, juce::Colours::white);
|
||||
Ok->setColour (juce::ComboBox::ColourIds::outlineColourId, juce::Colours::white);
|
||||
//[/UserPreSize]
|
||||
|
||||
setSize (300, 150);
|
||||
|
||||
|
||||
//[Constructor] You can add your own custom stuff here..
|
||||
//[/Constructor]
|
||||
}
|
||||
|
||||
SetPresetNameWindow::~SetPresetNameWindow()
|
||||
{
|
||||
//[Destructor_pre]. You can add your own custom destruction code here..
|
||||
//[/Destructor_pre]
|
||||
|
||||
nameTextEditor = nullptr;
|
||||
cancel = nullptr;
|
||||
Ok = nullptr;
|
||||
|
||||
|
||||
//[Destructor]. You can add your own custom destruction code here..
|
||||
//[/Destructor]
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void SetPresetNameWindow::paint (juce::Graphics& g)
|
||||
{
|
||||
//[UserPrePaint] Add your own custom painting code here..
|
||||
//[/UserPrePaint]
|
||||
|
||||
g.fillAll (juce::Colours::black);
|
||||
|
||||
{
|
||||
int x = 0, y = proportionOfHeight (0.0000f), width = proportionOfWidth (1.0000f), height = proportionOfHeight (1.0000f);
|
||||
juce::Colour fillColour = juce::Colours::black;
|
||||
juce::Colour strokeColour = juce::Colour (0xff666666);
|
||||
//[UserPaintCustomArguments] Customize the painting arguments here..
|
||||
//[/UserPaintCustomArguments]
|
||||
g.setColour (fillColour);
|
||||
g.fillRect (x, y, width, height);
|
||||
g.setColour (strokeColour);
|
||||
g.drawRect (x, y, width, height, 1);
|
||||
|
||||
}
|
||||
|
||||
{
|
||||
int x = proportionOfWidth (0.0000f), y = proportionOfHeight (0.1000f), width = proportionOfWidth (1.0000f), height = proportionOfHeight (0.2000f);
|
||||
juce::String text (TRANS("Preset Name"));
|
||||
juce::Colour fillColour = juce::Colours::white;
|
||||
//[UserPaintCustomArguments] Customize the painting arguments here..
|
||||
//[/UserPaintCustomArguments]
|
||||
g.setColour (fillColour);
|
||||
g.setFont (juce::Font (15.00f, juce::Font::plain).withTypefaceStyle ("Regular"));
|
||||
g.drawText (text, x, y, width, height,
|
||||
juce::Justification::centred, true);
|
||||
}
|
||||
|
||||
//[UserPaint] Add your own custom painting code here..
|
||||
//[/UserPaint]
|
||||
}
|
||||
|
||||
void SetPresetNameWindow::resized()
|
||||
{
|
||||
//[UserPreResize] Add your own custom resize code here..
|
||||
//[/UserPreResize]
|
||||
|
||||
nameTextEditor->setBounds (proportionOfWidth (0.1500f), proportionOfHeight (0.3467f), proportionOfWidth (0.7000f), proportionOfHeight (0.1733f));
|
||||
cancel->setBounds (proportionOfWidth (0.2000f), proportionOfHeight (0.7000f), proportionOfWidth (0.2500f), proportionOfHeight (0.1600f));
|
||||
Ok->setBounds (proportionOfWidth (0.5500f), proportionOfHeight (0.7000f), proportionOfWidth (0.2500f), proportionOfHeight (0.1600f));
|
||||
//[UserResized] Add your own custom resize handling here..
|
||||
//[/UserResized]
|
||||
}
|
||||
|
||||
void SetPresetNameWindow::buttonClicked (juce::Button* buttonThatWasClicked)
|
||||
{
|
||||
//[UserbuttonClicked_Pre]
|
||||
//[/UserbuttonClicked_Pre]
|
||||
|
||||
if (buttonThatWasClicked == cancel.get())
|
||||
{
|
||||
//[UserButtonCode_cancel] -- add your button handler code here..
|
||||
callback(0, nameTextEditor->getText());
|
||||
//[/UserButtonCode_cancel]
|
||||
}
|
||||
else if (buttonThatWasClicked == Ok.get())
|
||||
{
|
||||
//[UserButtonCode_Ok] -- add your button handler code here..
|
||||
callback(1, nameTextEditor->getText());
|
||||
//[/UserButtonCode_Ok]
|
||||
}
|
||||
|
||||
//[UserbuttonClicked_Post]
|
||||
//[/UserbuttonClicked_Post]
|
||||
}
|
||||
|
||||
|
||||
|
||||
//[MiscUserCode] You can add your own definitions of your custom methods or any other code here...
|
||||
void SetPresetNameWindow::grabTextEditorFocus()
|
||||
{
|
||||
nameTextEditor->grabKeyboardFocus();
|
||||
};
|
||||
//[/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
|
||||
|
||||
<JUCER_COMPONENT documentType="Component" className="SetPresetNameWindow" componentName=""
|
||||
parentClasses="public juce::Component" constructorParams="" variableInitialisers=""
|
||||
snapPixels="8" snapActive="1" snapShown="1" overlayOpacity="0.330"
|
||||
fixedSize="1" initialWidth="300" initialHeight="150">
|
||||
<BACKGROUND backgroundColour="ff000000">
|
||||
<RECT pos="0 0% 100% 100%" fill="solid: ff000000" hasStroke="1" stroke="1, mitered, butt"
|
||||
strokeColour="solid: ff666666"/>
|
||||
<TEXT pos="0% 10% 100% 20%" fill="solid: ffffffff" hasStroke="0" text="Preset Name"
|
||||
fontname="Default font" fontsize="15.0" kerning="0.0" bold="0"
|
||||
italic="0" justification="36"/>
|
||||
</BACKGROUND>
|
||||
<TEXTEDITOR name="nameTextEditor" id="13e287a1045d7d6d" memberName="nameTextEditor"
|
||||
virtualName="" explicitFocusOrder="0" pos="15% 34.667% 70% 17.333%"
|
||||
bkgcol="ff000000" caretcol="ffffffff" initialText="" multiline="0"
|
||||
retKeyStartsLine="0" readonly="0" scrollbars="1" caret="1" popupmenu="0"/>
|
||||
<TEXTBUTTON name="cancel" id="873979f2630a3992" memberName="cancel" virtualName=""
|
||||
explicitFocusOrder="0" pos="20% 70% 25% 16%" bgColOff="ff000000"
|
||||
buttonText="Cancel" connectedEdges="0" needsCallback="1" radioGroupId="0"/>
|
||||
<TEXTBUTTON name="Ok" id="2874357d53dac91e" memberName="Ok" virtualName=""
|
||||
explicitFocusOrder="0" pos="55% 70% 25% 16%" bgColOff="ff000000"
|
||||
buttonText="OK" connectedEdges="0" needsCallback="1" radioGroupId="0"/>
|
||||
</JUCER_COMPONENT>
|
||||
|
||||
END_JUCER_METADATA
|
||||
*/
|
||||
#endif
|
||||
|
||||
|
||||
//[EndFile] You can add extra defines here...
|
||||
//[/EndFile]
|
||||
|
75
Source/Components/SetPresetNameWindow.h
Normal file
75
Source/Components/SetPresetNameWindow.h
Normal file
|
@ -0,0 +1,75 @@
|
|||
/*
|
||||
==============================================================================
|
||||
|
||||
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 <JuceHeader.h>
|
||||
//[/Headers]
|
||||
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
//[Comments]
|
||||
An auto-generated component, created by the Projucer.
|
||||
|
||||
Describe your class and how it works here!
|
||||
//[/Comments]
|
||||
*/
|
||||
class SetPresetNameWindow : public juce::Component,
|
||||
public juce::Button::Listener
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
SetPresetNameWindow ();
|
||||
~SetPresetNameWindow() override;
|
||||
|
||||
//==============================================================================
|
||||
//[UserMethods] -- You can add your own custom methods in this section.
|
||||
std::function<void(int, juce::String)> callback;
|
||||
void setText(const String &txt){
|
||||
nameTextEditor->setText(txt);
|
||||
}
|
||||
void grabTextEditorFocus();
|
||||
//[/UserMethods]
|
||||
|
||||
void paint (juce::Graphics& g) override;
|
||||
void resized() override;
|
||||
void buttonClicked (juce::Button* buttonThatWasClicked) override;
|
||||
|
||||
|
||||
|
||||
private:
|
||||
//[UserVariables] -- You can add your own custom variables in this section.
|
||||
//[/UserVariables]
|
||||
|
||||
//==============================================================================
|
||||
std::unique_ptr<juce::TextEditor> nameTextEditor;
|
||||
std::unique_ptr<juce::TextButton> cancel;
|
||||
std::unique_ptr<juce::TextButton> Ok;
|
||||
|
||||
|
||||
//==============================================================================
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (SetPresetNameWindow)
|
||||
};
|
||||
|
||||
//[EndFile] You can add extra defines here...
|
||||
//[/EndFile]
|
||||
|
|
@ -41,7 +41,7 @@ public:
|
|||
{
|
||||
values[k] = 0.0f;
|
||||
}
|
||||
values[VOICE_COUNT] = 1.0f;
|
||||
values[VOICE_COUNT] = 0.2f;
|
||||
values[BRIGHTNESS]=1.0f;
|
||||
values[OCTAVE]=0.5;
|
||||
values[TUNE] = 0.5f;
|
||||
|
|
BIN
Source/Images/main.psd
Normal file
BIN
Source/Images/main.psd
Normal file
Binary file not shown.
|
@ -16,14 +16,19 @@ It contains the basic startup code for a Juce application.
|
|||
ObxdAudioProcessorEditor::ObxdAudioProcessorEditor (ObxdAudioProcessor& ownerFilter)
|
||||
: AudioProcessorEditor (&ownerFilter), processor (ownerFilter),
|
||||
skinFolder (processor.getSkinFolder()),
|
||||
progStart (2000),
|
||||
bankStart (1000),
|
||||
skinStart (0),
|
||||
progStart (3000),
|
||||
bankStart (2000),
|
||||
skinStart (1000),
|
||||
skins (processor.getSkinFiles()),
|
||||
banks (processor.getBankFiles())
|
||||
{
|
||||
|
||||
// skinFolder = ownerFilter.getCurrentSkinFolder(); // initialized above
|
||||
LookAndFeel& lf = getLookAndFeel();
|
||||
// Popup Menu Look and Feel
|
||||
lf.setColour(PopupMenu::backgroundColourId, Colour(20, 20, 20));
|
||||
lf.setColour(PopupMenu::textColourId, Colour(245, 245, 245));
|
||||
lf.setColour(PopupMenu::highlightedBackgroundColourId, Colour(60, 60, 60));
|
||||
|
||||
//skinFolder = ownerFilter.getCurrentSkinFolder(); // initialized above
|
||||
commandManager.registerAllCommandsForTarget(this);
|
||||
commandManager.setFirstCommandTarget(this);
|
||||
|
||||
|
@ -51,6 +56,26 @@ ObxdAudioProcessorEditor::ObxdAudioProcessorEditor (ObxdAudioProcessor& ownerFil
|
|||
updateFromHost();
|
||||
}
|
||||
|
||||
|
||||
void ObxdAudioProcessorEditor::resized() {
|
||||
if (setPresetNameWindow != nullptr )
|
||||
{
|
||||
if (auto wrapper = dynamic_cast<ObxdAudioProcessorEditor*>(processor.getActiveEditor()))
|
||||
{
|
||||
|
||||
auto w = proportionOfWidth(0.25f);
|
||||
auto h = proportionOfHeight(0.3f);
|
||||
auto x = proportionOfWidth(0.5f) - (w / 2);
|
||||
auto y = wrapper->getY();
|
||||
|
||||
if (setPresetNameWindow != nullptr)
|
||||
{
|
||||
y += proportionOfHeight(0.15f);
|
||||
setPresetNameWindow->setBounds(x, y, w, h);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
void ObxdAudioProcessorEditor::loadSkin (ObxdAudioProcessor& ownerFilter)
|
||||
{
|
||||
knobAttachments.clear();
|
||||
|
@ -377,13 +402,68 @@ void ObxdAudioProcessorEditor::rebuildComponents (ObxdAudioProcessor& ownerFilte
|
|||
|
||||
void ObxdAudioProcessorEditor::createMenu ()
|
||||
{
|
||||
popupMenus.clear();
|
||||
PopupMenu* menu = new PopupMenu();
|
||||
PopupMenu progMenu;
|
||||
PopupMenu bankMenu;
|
||||
PopupMenu skinMenu;
|
||||
|
||||
PopupMenu fileMenu;
|
||||
skins = processor.getSkinFiles();
|
||||
banks = processor.getBankFiles();
|
||||
{
|
||||
|
||||
fileMenu.addItem(static_cast<int>(MenuAction::ImportPreset),
|
||||
"Import Preset...",
|
||||
true,
|
||||
false);
|
||||
|
||||
fileMenu.addItem(static_cast<int>(MenuAction::ImportBank),
|
||||
"Import Bank...",
|
||||
true,
|
||||
false);
|
||||
|
||||
fileMenu.addSeparator();
|
||||
|
||||
fileMenu.addItem(static_cast<int>(MenuAction::ExportPreset),
|
||||
"Export Preset...",
|
||||
true,
|
||||
false);
|
||||
|
||||
fileMenu.addItem(static_cast<int>(MenuAction::ExportBank),
|
||||
"Export Bank...",
|
||||
true,
|
||||
false);
|
||||
|
||||
fileMenu.addSeparator();
|
||||
|
||||
fileMenu.addItem(static_cast<int>(MenuAction::NewPreset),
|
||||
"New Preset...",
|
||||
true,//enableNewPresetOption,
|
||||
false);
|
||||
|
||||
fileMenu.addItem(static_cast<int>(MenuAction::RenamePreset),
|
||||
"Rename Preset...",
|
||||
true,
|
||||
false);
|
||||
|
||||
fileMenu.addItem(static_cast<int>(MenuAction::SavePreset),
|
||||
"Save Preset...",
|
||||
true,
|
||||
false);
|
||||
|
||||
fileMenu.addItem(static_cast<int>(MenuAction::DeletePreset),
|
||||
"Delete Preset...",
|
||||
true,
|
||||
false);
|
||||
|
||||
/*
|
||||
fileMenu.addItem(static_cast<int>(MenuAction::DeleteBank),
|
||||
"Delete Bank...",
|
||||
true,
|
||||
false);
|
||||
*/
|
||||
menu->addSubMenu("File", fileMenu);
|
||||
}
|
||||
|
||||
{
|
||||
for (int i = 0; i < processor.getNumPrograms(); ++i)
|
||||
|
@ -463,8 +543,180 @@ void ObxdAudioProcessorEditor::resultFromMenu (const Point<int> pos)
|
|||
clean();
|
||||
loadSkin (processor);
|
||||
}
|
||||
else if (result < progStart){
|
||||
MenuActionCallback(result);
|
||||
}
|
||||
}
|
||||
|
||||
void ObxdAudioProcessorEditor::MenuActionCallback(int action){
|
||||
|
||||
|
||||
if (action == MenuAction::ImportBank)
|
||||
{
|
||||
fileChooser = std::make_unique<juce::FileChooser>("Import Bank (*.fxb)", juce::File(), "*.fxb", true);
|
||||
|
||||
if (fileChooser->browseForFileToOpen()) {
|
||||
File result = fileChooser->getResult();
|
||||
auto name = result.getFileName().replace("%20", " ");
|
||||
auto file = processor.getBanksFolder().getChildFile(name);
|
||||
|
||||
if (result == file || result.copyFileTo(file)){
|
||||
processor.loadFromFXBFile(file);
|
||||
processor.scanAndUpdateBanks();
|
||||
createMenu();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if (action == MenuAction::ExportBank)
|
||||
{
|
||||
auto file = processor.getDocumentFolder().getChildFile("Banks");
|
||||
FileChooser myChooser ("Export Bank (*.fxb)", file, "*.fxb", true);
|
||||
if(myChooser.browseForFileToSave(true))
|
||||
{
|
||||
File result = myChooser.getResult();
|
||||
|
||||
String temp = result.getFullPathName();
|
||||
if (!temp.endsWith(".fxb")) {
|
||||
temp += ".fxb";
|
||||
}
|
||||
processor.saveBank(File(temp));
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
if (action == MenuAction::DeleteBank)
|
||||
{
|
||||
if(NativeMessageBox::showOkCancelBox(AlertWindow::NoIcon, "Delete Bank", "Delete current bank: " + processor.currentBank + "?")){
|
||||
processor.deleteBank();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (action == MenuAction::SavePreset)
|
||||
{
|
||||
auto presetName = processor.currentPreset;
|
||||
if (presetName.isEmpty() )
|
||||
{
|
||||
processor.saveBank();
|
||||
return;
|
||||
}
|
||||
processor.savePreset();
|
||||
processor.saveBank();
|
||||
}
|
||||
|
||||
if (action == MenuAction::NewPreset)
|
||||
{
|
||||
setPresetNameWindow = std::make_unique<SetPresetNameWindow>();
|
||||
//preventBackgroundClick();
|
||||
addAndMakeVisible(setPresetNameWindow.get());
|
||||
resized();
|
||||
|
||||
auto callback = [this](int i, juce::String name)
|
||||
{
|
||||
if (i)
|
||||
{
|
||||
if (name.isNotEmpty())
|
||||
{
|
||||
processor.newPreset(name);
|
||||
createMenu();
|
||||
}
|
||||
}
|
||||
|
||||
setPresetNameWindow.reset();
|
||||
//preventBackgroundClickComponent.reset();
|
||||
};
|
||||
|
||||
setPresetNameWindow->callback = callback;
|
||||
setPresetNameWindow->grabTextEditorFocus();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (action == MenuAction::RenamePreset)
|
||||
{
|
||||
setPresetNameWindow = std::make_unique<SetPresetNameWindow>();
|
||||
//preventBackgroundClick();
|
||||
setPresetNameWindow->setText(processor.getProgramName(processor.getCurrentProgram()));
|
||||
addAndMakeVisible(setPresetNameWindow.get());
|
||||
resized();
|
||||
|
||||
auto callback = [this](int i, juce::String name)
|
||||
{
|
||||
if (i)
|
||||
{
|
||||
if (name.isNotEmpty())
|
||||
{
|
||||
processor.changePresetName(name);
|
||||
createMenu();
|
||||
}
|
||||
}
|
||||
|
||||
setPresetNameWindow.reset();
|
||||
//preventBackgroundClickComponent.reset();
|
||||
};
|
||||
|
||||
setPresetNameWindow->callback = callback;
|
||||
setPresetNameWindow->grabTextEditorFocus();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (action == MenuAction::DeletePreset)
|
||||
{
|
||||
if(NativeMessageBox::showOkCancelBox(AlertWindow::NoIcon, "Delete Preset", "Delete current preset " + processor.currentPreset + "?")){
|
||||
processor.deletePreset();
|
||||
createMenu();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (action == MenuAction::ImportPreset)
|
||||
{
|
||||
DBG("Import Preset");
|
||||
fileChooser = std::make_unique<juce::FileChooser>("Import Preset (*.fxp)", juce::File(), "*.fxp", true);
|
||||
|
||||
if (fileChooser->browseForFileToOpen()) {
|
||||
File result = fileChooser->getResult();
|
||||
//auto name = result.getFileName().replace("%20", " ");
|
||||
//auto file = processor.getPresetsFolder().getChildFile(name);
|
||||
DBG("Import Preset: " << result.getFileName());
|
||||
//if (result == file || result.copyFileTo(file)){
|
||||
processor.loadPreset(result);
|
||||
createMenu();
|
||||
//}
|
||||
}
|
||||
};
|
||||
|
||||
if (action == MenuAction::ExportPreset)
|
||||
{
|
||||
|
||||
auto file = processor.getPresetsFolder();
|
||||
FileChooser myChooser ("Export Preset (*.fxp)", file, "*.fxp", true);
|
||||
if(myChooser.browseForFileToSave(true))
|
||||
{
|
||||
File result = myChooser.getResult();
|
||||
|
||||
String temp = result.getFullPathName();
|
||||
if (!temp.endsWith(".fxp")) {
|
||||
temp += ".fxp";
|
||||
}
|
||||
processor.savePreset(File(temp));
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void ObxdAudioProcessorEditor::deleteBank()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
void ObxdAudioProcessorEditor::nextProgram() {
|
||||
int cur = processor.getCurrentProgram() + 1;
|
||||
if (cur == processor.getNumPrograms()) {
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include "Gui/Knob.h"
|
||||
#include "Gui/TooglableButton.h"
|
||||
#include "Gui/ButtonList.h"
|
||||
#include "Components/SetPresetNameWindow.h"
|
||||
|
||||
enum KeyPressCommandIDs
|
||||
{
|
||||
|
@ -26,6 +27,23 @@ enum KeyPressCommandIDs
|
|||
buttonPadPrevProgram,
|
||||
|
||||
};
|
||||
|
||||
enum MenuAction
|
||||
{
|
||||
Cancel = 0,
|
||||
ToggleMidiKeyboard,
|
||||
ImportPreset,
|
||||
ImportBank,
|
||||
ExportBank,
|
||||
ExportPreset,
|
||||
SavePreset,
|
||||
NewPreset,
|
||||
RenamePreset,
|
||||
DeletePreset,
|
||||
DeleteBank,
|
||||
ShowBanks,
|
||||
LoadBank // LoadBank must be the last enum value
|
||||
};
|
||||
//==============================================================================
|
||||
/**
|
||||
*/
|
||||
|
@ -121,6 +139,11 @@ public:
|
|||
|
||||
void nextProgram();
|
||||
void prevProgram();
|
||||
|
||||
void MenuActionCallback(int action);
|
||||
void deleteBank();
|
||||
|
||||
void resized() override;
|
||||
private:
|
||||
Knob* addKnob (int x, int y, int d, ObxdAudioProcessor& filter, int parameter, String name, float defval);
|
||||
void placeLabel (int x, int y, String text);
|
||||
|
@ -227,7 +250,8 @@ private:
|
|||
int skinStart;
|
||||
Array<File> skins;
|
||||
Array<File> banks;
|
||||
|
||||
std::unique_ptr<SetPresetNameWindow> setPresetNameWindow;
|
||||
std::unique_ptr<FileChooser> fileChooser;
|
||||
// Command manager
|
||||
ApplicationCommandManager commandManager;
|
||||
};
|
||||
|
|
|
@ -63,7 +63,7 @@ ObxdAudioProcessor::ObxdAudioProcessor()
|
|||
lastUsedParameter = 0;
|
||||
|
||||
synth.setSampleRate (44100);
|
||||
|
||||
|
||||
PropertiesFile::Options options;
|
||||
options.applicationName = JucePlugin_Name;
|
||||
options.storageFormat = PropertiesFile::storeAsXML;
|
||||
|
@ -225,33 +225,6 @@ inline void ObxdAudioProcessor::processMidiPerSample (MidiBuffer::Iterator* iter
|
|||
{
|
||||
synth.procModWheel (midiMsg->getControllerValue() / 127.0f);
|
||||
}
|
||||
if (midiMsg->isController())
|
||||
{
|
||||
lastMovedController = midiMsg->getControllerNumber();
|
||||
|
||||
if (programs.currentProgramPtr->values[MIDILEARN] > 0.5f){
|
||||
midiControlledParamSet = true;
|
||||
bindings[lastMovedController] = lastUsedParameter;
|
||||
setEngineParameterValue (MIDILEARN, 0, true);
|
||||
lastMovedController = 0;
|
||||
lastUsedParameter = 0;
|
||||
midiControlledParamSet = false;
|
||||
}
|
||||
|
||||
if (bindings[lastMovedController] > 0)
|
||||
{
|
||||
midiControlledParamSet = true;
|
||||
setEngineParameterValue (bindings[lastMovedController],
|
||||
midiMsg->getControllerValue() / 127.0f, true);
|
||||
|
||||
setEngineParameterValue (MIDILEARN, 0, true);
|
||||
lastMovedController = 0;
|
||||
lastUsedParameter = 0;
|
||||
|
||||
midiControlledParamSet = false;
|
||||
}
|
||||
|
||||
}
|
||||
if(midiMsg->isSustainPedalOn())
|
||||
{
|
||||
synth.sustainOn();
|
||||
|
@ -267,8 +240,39 @@ inline void ObxdAudioProcessor::processMidiPerSample (MidiBuffer::Iterator* iter
|
|||
if(midiMsg->isAllSoundOff())
|
||||
{
|
||||
synth.allSoundOff();
|
||||
}
|
||||
}
|
||||
|
||||
DBG(" Message: " << midiMsg->getChannel() << " "<<midiMsg->getRawData()[0] << " "<< midiMsg->getRawData()[1] << " "<< midiMsg->getRawData()[2]);
|
||||
|
||||
if (midiMsg->isProgramChange()){ // xC0
|
||||
setCurrentProgram(midiMsg->getProgramChangeNumber());
|
||||
|
||||
} else
|
||||
if (midiMsg->isController()) // xB0
|
||||
{
|
||||
lastMovedController = midiMsg->getControllerNumber();
|
||||
if (programs.currentProgramPtr->values[MIDILEARN] > 0.5f){
|
||||
midiControlledParamSet = true;
|
||||
bindings[lastMovedController] = lastUsedParameter;
|
||||
setEngineParameterValue (MIDILEARN, 0, true);
|
||||
lastMovedController = 0;
|
||||
lastUsedParameter = 0;
|
||||
midiControlledParamSet = false;
|
||||
}
|
||||
|
||||
if (bindings[lastMovedController] > 0)
|
||||
{
|
||||
midiControlledParamSet = true;
|
||||
setEngineParameterValue (bindings[lastMovedController],
|
||||
midiMsg->getControllerValue() / 127.0f, true);
|
||||
|
||||
setEngineParameterValue (MIDILEARN, 0, true);
|
||||
lastMovedController = 0;
|
||||
lastUsedParameter = 0;
|
||||
|
||||
midiControlledParamSet = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -381,7 +385,7 @@ void ObxdAudioProcessor::setStateInformation(const void* data, int sizeInBytes)
|
|||
if (xmlState)
|
||||
{
|
||||
XmlElement* xprogs = xmlState->getFirstChildElement();
|
||||
if (xprogs->hasTagName(S("programs")))
|
||||
if (xprogs && xprogs->hasTagName(S("programs")))
|
||||
{
|
||||
int i = 0;
|
||||
forEachXmlChildElement(*xprogs, e)
|
||||
|
@ -457,6 +461,123 @@ void ObxdAudioProcessor::setCurrentProgramStateInformation(const void* data, in
|
|||
}
|
||||
|
||||
//==============================================================================
|
||||
bool ObxdAudioProcessor::deleteBank() {
|
||||
currentBankFile.deleteFile();
|
||||
scanAndUpdateBanks();
|
||||
if (bankFiles.size() > 0)
|
||||
{
|
||||
loadFromFXBFile (bankFiles[0]);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void ObxdAudioProcessor::saveBank() {
|
||||
saveFXBFile(currentBankFile);
|
||||
}
|
||||
|
||||
bool ObxdAudioProcessor::loadPreset(const File& fxpFile) {
|
||||
loadFromFXBFile(fxpFile);
|
||||
currentPreset = fxpFile.getFileName();
|
||||
currentPresetFile = fxpFile;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ObxdAudioProcessor::saveFXPFile(const File& fxpFile){
|
||||
//auto xml = std::unique_ptr<juce::XmlElement>(new juce::XmlElement(""));
|
||||
juce::MemoryBlock m, memoryBlock;
|
||||
getCurrentProgramStateInformation(m);
|
||||
{
|
||||
memoryBlock.reset();
|
||||
auto totalLen = sizeof (fxProgramSet) + m.getSize() - 8;
|
||||
memoryBlock.setSize (totalLen, true);
|
||||
|
||||
auto set = static_cast<fxProgramSet*>(memoryBlock.getData());
|
||||
set->chunkMagic = fxbName ("CcnK");
|
||||
set->byteSize = 0;
|
||||
set->fxMagic = fxbName ("FPCh");
|
||||
set->version = fxbSwap (fxbVersionNum);
|
||||
set->fxID = fxbName ("Obxd");
|
||||
set->fxVersion = fxbSwap (fxbVersionNum);
|
||||
set->numPrograms = fxbSwap (getNumPrograms());
|
||||
programs.currentProgramPtr->name.copyToUTF8(set->name, 28);
|
||||
set->chunkSize = fxbSwap (static_cast<int32>(m.getSize()));
|
||||
|
||||
m.copyTo (set->chunk, 0, m.getSize());
|
||||
|
||||
fxpFile.replaceWithData(memoryBlock.getData(), memoryBlock.getSize());
|
||||
}
|
||||
}
|
||||
|
||||
bool ObxdAudioProcessor::savePreset(const File& fxpFile) {
|
||||
saveFXPFile(fxpFile);
|
||||
currentPreset = fxpFile.getFileName();
|
||||
currentPresetFile = fxpFile;
|
||||
}
|
||||
|
||||
void ObxdAudioProcessor::changePresetName(const String &name){
|
||||
programs.currentProgramPtr->name = name;
|
||||
//savePreset();
|
||||
//saveBank();
|
||||
}
|
||||
|
||||
void ObxdAudioProcessor::deletePreset(){
|
||||
programs.currentProgramPtr->setDefaultValues();
|
||||
programs.currentProgramPtr->name = "Default";
|
||||
sendChangeMessage();
|
||||
//saveBank();
|
||||
}
|
||||
|
||||
void ObxdAudioProcessor::newPreset(const String &name) {
|
||||
for (int i = 0; i < PROGRAMCOUNT; ++i)
|
||||
{
|
||||
if (programs.programs[i].name == "Default"){
|
||||
setCurrentProgram(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
//savePreset();
|
||||
//saveBank();
|
||||
}
|
||||
|
||||
void ObxdAudioProcessor::savePreset() {
|
||||
savePreset(currentPresetFile);
|
||||
|
||||
}
|
||||
|
||||
bool ObxdAudioProcessor::saveBank(const File& fxbFile){
|
||||
saveFXBFile(fxbFile);
|
||||
currentBankFile = fxbFile;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ObxdAudioProcessor::saveFXBFile(const File& fxbFile) {
|
||||
//auto xml = std::unique_ptr<juce::XmlElement>(new juce::XmlElement(""));
|
||||
juce::MemoryBlock m, memoryBlock;
|
||||
getStateInformation(m);
|
||||
|
||||
{
|
||||
memoryBlock.reset();
|
||||
auto totalLen = sizeof (fxChunkSet) + m.getSize() - 8;
|
||||
memoryBlock.setSize (totalLen, true);
|
||||
|
||||
auto set = static_cast<fxChunkSet*>( memoryBlock.getData());
|
||||
set->chunkMagic = fxbName ("CcnK");
|
||||
set->byteSize = 0;
|
||||
set->fxMagic = fxbName ("FBCh");
|
||||
set->version = fxbSwap (fxbVersionNum);
|
||||
set->fxID = fxbName ("Obxd");
|
||||
set->fxVersion = fxbSwap (fxbVersionNum);
|
||||
set->numPrograms = fxbSwap (getNumPrograms());
|
||||
set->chunkSize = fxbSwap (static_cast<int32>(m.getSize()));
|
||||
|
||||
m.copyTo (set->chunk, 0, m.getSize());
|
||||
fxbFile.replaceWithData(memoryBlock.getData(), memoryBlock.getSize());
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ObxdAudioProcessor::loadFromFXBFile(const File& fxbFile)
|
||||
{
|
||||
MemoryBlock mb;
|
||||
|
@ -551,7 +672,7 @@ bool ObxdAudioProcessor::loadFromFXBFile(const File& fxbFile)
|
|||
}
|
||||
|
||||
currentBank = fxbFile.getFileName();
|
||||
|
||||
currentBankFile = fxbFile;
|
||||
updateHostDisplay();
|
||||
|
||||
return true;
|
||||
|
@ -576,13 +697,14 @@ bool ObxdAudioProcessor::restoreProgramSettings(const fxProgram* const prog)
|
|||
//==============================================================================
|
||||
void ObxdAudioProcessor::scanAndUpdateBanks()
|
||||
{
|
||||
bankFiles.clearQuick();
|
||||
bankFiles.clear();
|
||||
|
||||
DirectoryIterator it (getBanksFolder(), false, "*.fxb", File::findFiles);
|
||||
|
||||
while (it.next())
|
||||
{
|
||||
bankFiles.addUsingDefaultSort (it.getFile());
|
||||
DBG("Scan Banks: " << it.getFile().getFullPathName());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -638,6 +760,11 @@ File ObxdAudioProcessor::getBanksFolder() const
|
|||
return getDocumentFolder().getChildFile("Banks");
|
||||
}
|
||||
|
||||
File ObxdAudioProcessor::getPresetsFolder() const
|
||||
{
|
||||
return getDocumentFolder().getChildFile("Presets");
|
||||
}
|
||||
|
||||
File ObxdAudioProcessor::getCurrentSkinFolder() const
|
||||
{
|
||||
return getSkinFolder().getChildFile(currentSkin);
|
||||
|
@ -771,6 +898,7 @@ void ObxdAudioProcessor::setEngineParameterValue (int index, float newValue, boo
|
|||
apvtState.getParameter(getEngineParameterId(index))->setValue(newValue);
|
||||
}
|
||||
|
||||
//DBG("Set Value Parameter: " << getEngineParameterId(index) << " Val: " << newValue);
|
||||
switch (index)
|
||||
{
|
||||
case SELF_OSC_PUSH:
|
||||
|
|
|
@ -167,7 +167,17 @@ public:
|
|||
void scanAndUpdateSkins();
|
||||
const Array<File>& getBankFiles() const;
|
||||
const Array<File>& getSkinFiles() const;
|
||||
bool deleteBank();
|
||||
bool loadPreset(const File& fxpFile);
|
||||
bool savePreset(const File& fxpFile);
|
||||
void changePresetName(const String &name);
|
||||
void newPreset(const String &name);
|
||||
void deletePreset();
|
||||
|
||||
bool loadFromFXBFile(const File& fxbFile);
|
||||
bool saveFXBFile(const File& fxbFile);
|
||||
bool saveFXPFile(const File& fxpFile);
|
||||
bool saveBank(const File& fxbFile);
|
||||
bool restoreProgramSettings(const fxProgram* const prog);
|
||||
File getCurrentBankFile() const;
|
||||
|
||||
|
@ -178,8 +188,9 @@ public:
|
|||
//==============================================================================
|
||||
File getDocumentFolder() const;
|
||||
File getSkinFolder() const;
|
||||
File getPresetsFolder() const;
|
||||
File getBanksFolder() const;
|
||||
|
||||
|
||||
File getCurrentSkinFolder() const;
|
||||
void setCurrentSkinFolder(const String& folderName);
|
||||
|
||||
|
@ -209,7 +220,16 @@ private:
|
|||
ObxdBank programs;
|
||||
|
||||
String currentSkin;
|
||||
public:
|
||||
String currentBank;
|
||||
File currentBankFile;
|
||||
void saveBank();
|
||||
|
||||
|
||||
String currentPreset;
|
||||
File currentPresetFile;
|
||||
void savePreset();
|
||||
private:
|
||||
Array<File> bankFiles;
|
||||
Array<File> skinFiles;
|
||||
|
||||
|
|
Loading…
Reference in a new issue