From 7545b20f749887be8d831ff57ce4c3bba0c4550d Mon Sep 17 00:00:00 2001 From: George Reales Date: Tue, 4 Oct 2022 19:30:58 +0200 Subject: [PATCH] Copy Paste functionality --- Source/PluginEditor.cpp | 40 ++++++++++++++++++++++++- Source/PluginEditor.h | 2 ++ Source/PluginProcessor.cpp | 60 ++++++++++++++++++++++++++++++++++---- Source/PluginProcessor.h | 3 ++ 4 files changed, 99 insertions(+), 6 deletions(-) diff --git a/Source/PluginEditor.cpp b/Source/PluginEditor.cpp index 9db7c3d..62ba7c2 100755 --- a/Source/PluginEditor.cpp +++ b/Source/PluginEditor.cpp @@ -863,6 +863,8 @@ void ObxdAudioProcessorEditor::rebuildComponents (ObxdAudioProcessor& ownerFilte void ObxdAudioProcessorEditor::createMenu () { + bool enablePasteOption = macPasteboard::containsPresetData(); // Check if the clipboard contains data for a Preset + popupMenus.clear(); PopupMenu* menu = new PopupMenu(); //menu->setLookAndFeel(new CustomLookAndFeel(&this->processor)); @@ -926,7 +928,19 @@ void ObxdAudioProcessorEditor::createMenu () true, false); - /* + fileMenu.addSeparator(); + + fileMenu.addItem(static_cast(MenuAction::CopyPreset), + "Copy Preset...", + true, + false); + + fileMenu.addItem(static_cast(MenuAction::PastePreset), + "Paste Preset...", + enablePasteOption, + false); + + /* fileMenu.addItem(static_cast(MenuAction::DeleteBank), "Delete Bank...", true, @@ -1324,6 +1338,30 @@ void ObxdAudioProcessorEditor::MenuActionCallback(int action){ } }; + // Copy to clipboard + if (action == MenuAction::CopyPreset) + { + juce::MemoryBlock serializedData; + + // Serialize the Preset, produces the same data as an export but into memory instead of a file. + processor.serializePreset(serializedData); + + // Place the data onto the clipboard + macPasteboard::copyPresetDataToClipboard(serializedData.getData(), serializedData.getSize()); + } + + // Paste from clipboard + if (action == MenuAction::PastePreset) + { + juce::MemoryBlock memoryBlock; + + // Fetch Preset data from the clipboard + if (macPasteboard::fetchPresetDataFromClipboard(memoryBlock)) + { + // Load the data + processor.loadFromMemoryBlock(memoryBlock); //loadPreset(memoryBlock); + } + } } diff --git a/Source/PluginEditor.h b/Source/PluginEditor.h index 988e513..e0a94de 100644 --- a/Source/PluginEditor.h +++ b/Source/PluginEditor.h @@ -43,6 +43,8 @@ enum MenuAction DeletePreset, DeleteBank, ShowBanks, + CopyPreset, + PastePreset, LoadBank // LoadBank must be the last enum value }; //============================================================================== diff --git a/Source/PluginProcessor.cpp b/Source/PluginProcessor.cpp index 39c1eef..a553601 100644 --- a/Source/PluginProcessor.cpp +++ b/Source/PluginProcessor.cpp @@ -508,12 +508,38 @@ void ObxdAudioProcessor::saveBank() { } bool ObxdAudioProcessor::loadPreset(const File& fxpFile) { - loadFromFXBFile(fxpFile); + loadFromFXPFile(fxpFile); currentPreset = fxpFile.getFileName(); currentPresetFile = fxpFile; return true; } +/// Serialize the current Preset, just like the saveFXPFile function, +/// but keeps the data in memory instead of writing it to a file. +void ObxdAudioProcessor::serializePreset(MemoryBlock& memoryBlock) +{ + juce::MemoryBlock m; + 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()); + } +} + bool ObxdAudioProcessor::saveFXPFile(const File& fxpFile){ //auto xml = std::unique_ptr(new juce::XmlElement("")); juce::MemoryBlock m, memoryBlock; @@ -612,12 +638,40 @@ bool ObxdAudioProcessor::saveFXBFile(const File& fxbFile) { return true; } +bool ObxdAudioProcessor::loadFromFXPFile(const File& fxpFile) +{ + MemoryBlock mb; + if (! fxpFile.loadFileAsData(mb)) + return false; + + if (!loadFromMemoryBlock(mb)) + return false; + + currentPreset = fxpFile.getFileName(); + currentPresetFile = fxpFile; + updateHostDisplay(); + + return true; +} + bool ObxdAudioProcessor::loadFromFXBFile(const File& fxbFile) { MemoryBlock mb; if (! fxbFile.loadFileAsData(mb)) return false; + + if (!loadFromMemoryBlock(mb)) + return false; + + currentBank = fxbFile.getFileName(); + currentBankFile = fxbFile; + updateHostDisplay(); + + return true; +} +bool ObxdAudioProcessor::loadFromMemoryBlock(MemoryBlock& mb) +{ const void* const data = mb.getData(); const size_t dataSize = mb.getSize(); @@ -706,10 +760,6 @@ bool ObxdAudioProcessor::loadFromFXBFile(const File& fxbFile) return false; } - currentBank = fxbFile.getFileName(); - currentBankFile = fxbFile; - updateHostDisplay(); - return true; } diff --git a/Source/PluginProcessor.h b/Source/PluginProcessor.h index 127dbf8..3363d3f 100644 --- a/Source/PluginProcessor.h +++ b/Source/PluginProcessor.h @@ -177,11 +177,14 @@ public: bool deleteBank(); bool loadPreset(const File& fxpFile); bool savePreset(const File& fxpFile); + void serializePreset(MemoryBlock& memoryBlock); // Copy the current Preset into a MemoryBlock void changePresetName(const String &name); void newPreset(const String &name); void deletePreset(); + bool loadFromFXPFile(const File& fxbFile); bool loadFromFXBFile(const File& fxbFile); + bool loadFromMemoryBlock(MemoryBlock& memoryBlock); bool saveFXBFile(const File& fxbFile); bool saveFXPFile(const File& fxpFile); bool saveBank(const File& fxbFile);