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/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..5749c6c 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,64 @@ 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.addItem(static_cast(MenuAction::ExportPreset), + "Export Preset...", + true, + false); + + fileMenu.addItem(static_cast(MenuAction::ExportBank), + "Export Bank...", + true, + false); + + fileMenu.addItem(static_cast(MenuAction::SavePreset), + "Save Preset...", + true, + false); + + fileMenu.addItem(static_cast(MenuAction::RenamePreset), + "Rename Preset...", + true, + false); + + fileMenu.addItem(static_cast(MenuAction::NewPreset), + "New Preset...", + true,//enableNewPresetOption, + 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 +539,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 6a520ad..b5d8e29 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,20 +240,39 @@ inline void ObxdAudioProcessor::processMidiPerSample (MidiBuffer::Iterator* iter if(midiMsg->isAllSoundOff()) { synth.allSoundOff(); - } - char* midi_data = (char*)midiMsg->getRawData(); - int const status = midi_data[0] & 0xF0; - if (status == 0xC0) - { - { - //const ScopedUnlock unlocker(criticalSection); - // TODO - must issue setProgram - setCurrentProgram(midi_data[1]); - } - //sendChangeMessage(); - //updateHostDisplay(); } + + 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; + } + } } } @@ -469,6 +461,119 @@ void ObxdAudioProcessor::setCurrentProgramStateInformation(const void* data, in } //============================================================================== +bool ObxdAudioProcessor::deleteBank() { + currentBankFile.deleteFile(); + scanAndUpdateBanks(); + if (bankFiles.size() > 0) + { + loadFromFXBFile (bankFiles[0]); + } +} + +void ObxdAudioProcessor::saveBank() { + saveFXBFile(currentBankFile); +} + +bool ObxdAudioProcessor::loadPreset(const File& fxpFile) { + loadFromFXBFile(fxpFile); + currentPreset = fxpFile.getFileName(); + currentPresetFile = fxpFile; +} + +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"; + 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; +} + +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; @@ -563,7 +668,7 @@ bool ObxdAudioProcessor::loadFromFXBFile(const File& fxbFile) } currentBank = fxbFile.getFileName(); - + currentBankFile = fxbFile; updateHostDisplay(); return true; @@ -588,13 +693,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()); } } @@ -650,6 +756,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); @@ -783,6 +894,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;