diff --git a/Documents/discoDSP/OB-Xd/Banks/021 - Vivolator.FXB b/Documents/discoDSP/OB-Xd/Banks/021 - Vivolator.FXB
new file mode 100644
index 0000000..40096e2
Binary files /dev/null and b/Documents/discoDSP/OB-Xd/Banks/021 - Vivolator.FXB differ
diff --git a/Documents/discoDSP/OB-Xd/Banks/022 - Blank Canvas.fxb b/Documents/discoDSP/OB-Xd/Banks/022 - Blank Canvas.fxb
new file mode 100644
index 0000000..454988a
Binary files /dev/null and b/Documents/discoDSP/OB-Xd/Banks/022 - Blank Canvas.fxb differ
diff --git a/Source/Components/SetPresetNameWindow.cpp b/Source/Components/SetPresetNameWindow.cpp
new file mode 100644
index 0000000..7283cc4
--- /dev/null
+++ b/Source/Components/SetPresetNameWindow.cpp
@@ -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
+
+
+
+
+
+
+
+
+
+
+
+END_JUCER_METADATA
+*/
+#endif
+
+
+//[EndFile] You can add extra defines here...
+//[/EndFile]
+
diff --git a/Source/Components/SetPresetNameWindow.h b/Source/Components/SetPresetNameWindow.h
new file mode 100644
index 0000000..6478180
--- /dev/null
+++ b/Source/Components/SetPresetNameWindow.h
@@ -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
+//[/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 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 nameTextEditor;
+ std::unique_ptr cancel;
+ std::unique_ptr Ok;
+
+
+ //==============================================================================
+ JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (SetPresetNameWindow)
+};
+
+//[EndFile] You can add extra defines here...
+//[/EndFile]
+
diff --git a/Source/Engine/Params.h b/Source/Engine/Params.h
index ae1b63f..176e3a2 100755
--- a/Source/Engine/Params.h
+++ b/Source/Engine/Params.h
@@ -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;
diff --git a/Source/Images/main.psd b/Source/Images/main.psd
new file mode 100644
index 0000000..c7b831e
Binary files /dev/null and b/Source/Images/main.psd differ
diff --git a/Source/PluginEditor.cpp b/Source/PluginEditor.cpp
index 36e3953..40bf916 100755
--- a/Source/PluginEditor.cpp
+++ b/Source/PluginEditor.cpp
@@ -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(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(MenuAction::ImportPreset),
+ "Import Preset...",
+ true,
+ false);
+
+ fileMenu.addItem(static_cast(MenuAction::ImportBank),
+ "Import Bank...",
+ true,
+ false);
+
+ fileMenu.addSeparator();
+
+ fileMenu.addItem(static_cast(MenuAction::ExportPreset),
+ "Export Preset...",
+ true,
+ false);
+
+ fileMenu.addItem(static_cast(MenuAction::ExportBank),
+ "Export Bank...",
+ true,
+ false);
+
+ fileMenu.addSeparator();
+
+ fileMenu.addItem(static_cast(MenuAction::NewPreset),
+ "New Preset...",
+ true,//enableNewPresetOption,
+ false);
+
+ fileMenu.addItem(static_cast(MenuAction::RenamePreset),
+ "Rename Preset...",
+ true,
+ false);
+
+ fileMenu.addItem(static_cast(MenuAction::SavePreset),
+ "Save Preset...",
+ true,
+ false);
+
+ fileMenu.addItem(static_cast(MenuAction::DeletePreset),
+ "Delete Preset...",
+ true,
+ false);
+
+ /*
+ fileMenu.addItem(static_cast(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 pos)
clean();
loadSkin (processor);
}
+ else if (result < progStart){
+ MenuActionCallback(result);
+ }
}
+void ObxdAudioProcessorEditor::MenuActionCallback(int action){
+
+
+ if (action == MenuAction::ImportBank)
+ {
+ fileChooser = std::make_unique("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();
+ //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();
+ //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("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()) {
diff --git a/Source/PluginEditor.h b/Source/PluginEditor.h
index 586ee8c..7d63dbd 100755
--- a/Source/PluginEditor.h
+++ b/Source/PluginEditor.h
@@ -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 skins;
Array banks;
-
+ std::unique_ptr setPresetNameWindow;
+ std::unique_ptr fileChooser;
// Command manager
ApplicationCommandManager commandManager;
};
diff --git a/Source/PluginProcessor.cpp b/Source/PluginProcessor.cpp
index 230d669..37aa386 100755
--- a/Source/PluginProcessor.cpp
+++ b/Source/PluginProcessor.cpp
@@ -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() << " "<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(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(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(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(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( 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(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:
diff --git a/Source/PluginProcessor.h b/Source/PluginProcessor.h
index 104ab81..a03a87d 100755
--- a/Source/PluginProcessor.h
+++ b/Source/PluginProcessor.h
@@ -167,7 +167,17 @@ public:
void scanAndUpdateSkins();
const Array& getBankFiles() const;
const Array& 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 bankFiles;
Array skinFiles;