| @@ -401,50 +401,38 @@ struct GraphEditorPanel::PluginComponent : public Component, | |||||
| void showPopupMenu() | void showPopupMenu() | ||||
| { | { | ||||
| menu.reset (new PopupMenu); | menu.reset (new PopupMenu); | ||||
| menu->addItem (1, "Delete this filter"); | |||||
| menu->addItem (2, "Disconnect all pins"); | |||||
| menu->addItem (3, "Toggle Bypass"); | |||||
| menu->addItem ("Delete this filter", [this] { graph.graph.removeNode (pluginID); }); | |||||
| menu->addItem ("Disconnect all pins", [this] { graph.graph.disconnectNode (pluginID); }); | |||||
| menu->addItem ("Toggle Bypass", [this] | |||||
| { | |||||
| if (auto* node = graph.graph.getNodeForId (pluginID)) | |||||
| node->setBypassed (! node->isBypassed()); | |||||
| repaint(); | |||||
| }); | |||||
| menu->addSeparator(); | menu->addSeparator(); | ||||
| if (getProcessor()->hasEditor()) | if (getProcessor()->hasEditor()) | ||||
| menu->addItem (10, "Show plugin GUI"); | |||||
| menu->addItem ("Show plugin GUI", [this] { showWindow (PluginWindow::Type::normal); }); | |||||
| menu->addItem (11, "Show all programs"); | |||||
| menu->addItem (12, "Show all parameters"); | |||||
| menu->addItem (13, "Show debug log"); | |||||
| menu->addItem ("Show all programs", [this] { showWindow (PluginWindow::Type::programs); }); | |||||
| menu->addItem ("Show all parameters", [this] { showWindow (PluginWindow::Type::generic); }); | |||||
| menu->addItem ("Show debug log", [this] { showWindow (PluginWindow::Type::debug); }); | |||||
| if (autoScaleOptionAvailable) | if (autoScaleOptionAvailable) | ||||
| addPluginAutoScaleOptionsSubMenu (dynamic_cast<AudioPluginInstance*> (getProcessor()), *menu); | addPluginAutoScaleOptionsSubMenu (dynamic_cast<AudioPluginInstance*> (getProcessor()), *menu); | ||||
| menu->addSeparator(); | menu->addSeparator(); | ||||
| menu->addItem (20, "Configure Audio I/O"); | |||||
| menu->addItem (21, "Test state save/load"); | |||||
| menu->showMenuAsync ({}, ModalCallbackFunction::create | |||||
| ([this] (int r) { | |||||
| switch (r) | |||||
| { | |||||
| case 1: graph.graph.removeNode (pluginID); break; | |||||
| case 2: graph.graph.disconnectNode (pluginID); break; | |||||
| case 3: | |||||
| { | |||||
| if (auto* node = graph.graph.getNodeForId (pluginID)) | |||||
| node->setBypassed (! node->isBypassed()); | |||||
| menu->addItem ("Configure Audio I/O", [this] { showWindow (PluginWindow::Type::audioIO); }); | |||||
| menu->addItem ("Test state save/load", [this] { testStateSaveLoad(); }); | |||||
| repaint(); | |||||
| #if ! JUCE_IOS && ! JUCE_ANDROID | |||||
| menu->addSeparator(); | |||||
| menu->addItem ("Save plugin state", [this] { savePluginState(); }); | |||||
| menu->addItem ("Load plugin state", [this] { loadPluginState(); }); | |||||
| #endif | |||||
| break; | |||||
| } | |||||
| case 10: showWindow (PluginWindow::Type::normal); break; | |||||
| case 11: showWindow (PluginWindow::Type::programs); break; | |||||
| case 12: showWindow (PluginWindow::Type::generic) ; break; | |||||
| case 13: showWindow (PluginWindow::Type::debug); break; | |||||
| case 20: showWindow (PluginWindow::Type::audioIO); break; | |||||
| case 21: testStateSaveLoad(); break; | |||||
| default: break; | |||||
| } | |||||
| })); | |||||
| menu->showMenuAsync ({}); | |||||
| } | } | ||||
| void testStateSaveLoad() | void testStateSaveLoad() | ||||
| @@ -484,6 +472,59 @@ struct GraphEditorPanel::PluginComponent : public Component, | |||||
| void handleAsyncUpdate() override { repaint(); } | void handleAsyncUpdate() override { repaint(); } | ||||
| void savePluginState() | |||||
| { | |||||
| fileChooser = std::make_unique<FileChooser> ("Save plugin state"); | |||||
| const auto onChosen = [ref = SafePointer<PluginComponent> (this)] (const FileChooser& chooser) | |||||
| { | |||||
| if (ref == nullptr) | |||||
| return; | |||||
| const auto result = chooser.getResult(); | |||||
| if (result == File()) | |||||
| return; | |||||
| if (auto* node = ref->graph.graph.getNodeForId (ref->pluginID)) | |||||
| { | |||||
| MemoryBlock block; | |||||
| node->getProcessor()->getStateInformation (block); | |||||
| result.replaceWithData (block.getData(), block.getSize()); | |||||
| } | |||||
| }; | |||||
| fileChooser->launchAsync (FileBrowserComponent::saveMode | FileBrowserComponent::warnAboutOverwriting, onChosen); | |||||
| } | |||||
| void loadPluginState() | |||||
| { | |||||
| fileChooser = std::make_unique<FileChooser> ("Load plugin state"); | |||||
| const auto onChosen = [ref = SafePointer<PluginComponent> (this)] (const FileChooser& chooser) | |||||
| { | |||||
| if (ref == nullptr) | |||||
| return; | |||||
| const auto result = chooser.getResult(); | |||||
| if (result == File()) | |||||
| return; | |||||
| if (auto* node = ref->graph.graph.getNodeForId (ref->pluginID)) | |||||
| { | |||||
| if (auto stream = result.createInputStream()) | |||||
| { | |||||
| MemoryBlock block; | |||||
| stream->readIntoMemoryBlock (block); | |||||
| node->getProcessor()->setStateInformation (block.getData(), (int) block.getSize()); | |||||
| } | |||||
| } | |||||
| }; | |||||
| fileChooser->launchAsync (FileBrowserComponent::openMode | FileBrowserComponent::canSelectFiles, onChosen); | |||||
| } | |||||
| GraphEditorPanel& panel; | GraphEditorPanel& panel; | ||||
| PluginGraph& graph; | PluginGraph& graph; | ||||
| const AudioProcessorGraph::NodeID pluginID; | const AudioProcessorGraph::NodeID pluginID; | ||||
| @@ -495,6 +536,7 @@ struct GraphEditorPanel::PluginComponent : public Component, | |||||
| int numIns = 0, numOuts = 0; | int numIns = 0, numOuts = 0; | ||||
| DropShadowEffect shadow; | DropShadowEffect shadow; | ||||
| std::unique_ptr<PopupMenu> menu; | std::unique_ptr<PopupMenu> menu; | ||||
| std::unique_ptr<FileChooser> fileChooser; | |||||
| const String formatSuffix = getFormatSuffix (getProcessor()); | const String formatSuffix = getFormatSuffix (getProcessor()); | ||||
| }; | }; | ||||