From 00eacaf42e538e6da6be07b4d9a268ea91cf5e2e Mon Sep 17 00:00:00 2001 From: jules Date: Thu, 14 Nov 2013 16:20:42 +0000 Subject: [PATCH] Added some new window types to the plugin host demo --- .../Source/GraphEditorPanel.cpp | 194 ++++++++++++++---- .../Source/GraphEditorPanel.h | 44 ++-- .../audio plugin host/Source/HostStartup.cpp | 6 +- 3 files changed, 184 insertions(+), 60 deletions(-) diff --git a/extras/audio plugin host/Source/GraphEditorPanel.cpp b/extras/audio plugin host/Source/GraphEditorPanel.cpp index d5bd08b0f9..79283dbb8e 100644 --- a/extras/audio plugin host/Source/GraphEditorPanel.cpp +++ b/extras/audio plugin host/Source/GraphEditorPanel.cpp @@ -32,17 +32,17 @@ class PluginWindow; static Array activePluginWindows; -PluginWindow::PluginWindow (Component* const uiComp, - AudioProcessorGraph::Node* owner_, - const bool isGeneric_) - : DocumentWindow (uiComp->getName(), Colours::lightblue, +PluginWindow::PluginWindow (Component* const pluginEditor, + AudioProcessorGraph::Node* const o, + WindowFormatType t) + : DocumentWindow (pluginEditor->getName(), Colours::lightblue, DocumentWindow::minimiseButton | DocumentWindow::closeButton), - owner (owner_), - isGeneric (isGeneric_) + owner (o), + type (t) { setSize (400, 300); - setContentOwned (uiComp, true); + setContentOwned (pluginEditor, true); setTopLeftPosition (owner->properties.getWithDefault ("uiLastX", Random::getSystemRandom().nextInt (500)), owner->properties.getWithDefault ("uiLastY", Random::getSystemRandom().nextInt (500))); @@ -55,7 +55,7 @@ void PluginWindow::closeCurrentlyOpenWindowsFor (const uint32 nodeId) { for (int i = activePluginWindows.size(); --i >= 0;) if (activePluginWindows.getUnchecked(i)->owner->nodeId == nodeId) - delete activePluginWindows.getUnchecked(i); + delete activePluginWindows.getUnchecked (i); } void PluginWindow::closeAllCurrentlyOpenWindows() @@ -63,7 +63,7 @@ void PluginWindow::closeAllCurrentlyOpenWindows() if (activePluginWindows.size() > 0) { for (int i = activePluginWindows.size(); --i >= 0;) - delete activePluginWindows.getUnchecked(i); + delete activePluginWindows.getUnchecked (i); Component dummyModalComp; dummyModalComp.enterModalState(); @@ -71,33 +71,120 @@ void PluginWindow::closeAllCurrentlyOpenWindows() } } -PluginWindow* PluginWindow::getWindowFor (AudioProcessorGraph::Node* node, - bool useGenericView) +//============================================================================== +class ProcessorProgramPropertyComp : public PropertyComponent, + private AudioProcessorListener { - for (int i = activePluginWindows.size(); --i >= 0;) - if (activePluginWindows.getUnchecked(i)->owner == node - && activePluginWindows.getUnchecked(i)->isGeneric == useGenericView) - return activePluginWindows.getUnchecked(i); - - AudioProcessorEditor* ui = nullptr; - - if (! useGenericView) +public: + ProcessorProgramPropertyComp (const String& name, AudioProcessor& p, int index_) + : PropertyComponent (name), + owner (p), + index (index_) { - ui = node->getProcessor()->createEditorIfNeeded(); - - if (ui == nullptr) - useGenericView = true; + owner.addListener (this); } - if (useGenericView) - ui = new GenericAudioProcessorEditor (node->getProcessor()); + ~ProcessorProgramPropertyComp() + { + owner.removeListener (this); + } + + void refresh() { } + void audioProcessorChanged (AudioProcessor*) { } + void audioProcessorParameterChanged (AudioProcessor*, int, float) { } + +private: + AudioProcessor& owner; + const int index; + + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ProcessorProgramPropertyComp) +}; + +class ProgramAudioProcessorEditor : public AudioProcessorEditor +{ +public: + ProgramAudioProcessorEditor (AudioProcessor* const p) + : AudioProcessorEditor (p) + { + jassert (p != nullptr); + setOpaque (true); + + addAndMakeVisible (&panel); + + Array programs; + + const int numPrograms = p->getNumPrograms(); + int totalHeight = 0; + + for (int i = 0; i < numPrograms; ++i) + { + String name (p->getProgramName (i).trim()); + + if (name.isEmpty()) + name = "Unnamed"; + + ProcessorProgramPropertyComp* const pc = new ProcessorProgramPropertyComp (name, *p, i); + programs.add (pc); + totalHeight += pc->getPreferredHeight(); + } + + panel.addProperties (programs); + + setSize (400, jlimit (25, 400, totalHeight)); + } + + void paint (Graphics& g) + { + g.fillAll (Colours::grey); + } + + void resized() + { + panel.setBounds (getLocalBounds()); + } + +private: + PropertyPanel panel; + + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ProgramAudioProcessorEditor) +}; + +//============================================================================== +PluginWindow* PluginWindow::getWindowFor (AudioProcessorGraph::Node* const node, + WindowFormatType type) +{ + jassert (node != nullptr); + + for (int i = activePluginWindows.size(); --i >= 0;) + if (activePluginWindows.getUnchecked(i)->owner == node + && activePluginWindows.getUnchecked(i)->type == type) + return activePluginWindows.getUnchecked(i); + + AudioProcessor* processor = node->getProcessor(); + AudioProcessorEditor* ui = nullptr; + + if (type == Normal) + { + ui = processor->createEditorIfNeeded(); + + if (ui == nullptr) + type = Generic; + } + + if (ui == nullptr) + { + if (type == Generic || type == Parameters) + ui = new GenericAudioProcessorEditor (processor); + else if (type == Programs) + ui = new ProgramAudioProcessorEditor (processor); + } if (ui != nullptr) { - if (AudioPluginInstance* const plugin = dynamic_cast (node->getProcessor())) + if (AudioPluginInstance* const plugin = dynamic_cast (processor)) ui->setName (plugin->getName()); - return new PluginWindow (ui, node, useGenericView); + return new PluginWindow (ui, node, type); } return nullptr; @@ -136,16 +223,18 @@ public: { String tip; - if (isInput) - tip = node->getProcessor()->getInputChannelName (index_); - else - tip = node->getProcessor()->getOutputChannelName (index_); - - if (tip.isEmpty()) + if (index_ == FilterGraph::midiChannelNumber) { - if (index_ == FilterGraph::midiChannelNumber) - tip = isInput ? "Midi Input" : "Midi Output"; + tip = isInput ? "MIDI Input" : "MIDI Output"; + } + else + { + if (isInput) + tip = node->getProcessor()->getInputChannelName (index_); else + tip = node->getProcessor()->getOutputChannelName (index_); + + if (tip.isEmpty()) tip = (isInput ? "Input " : "Output ") + String (index_ + 1); } @@ -242,7 +331,9 @@ public: m.addItem (2, "Disconnect all pins"); m.addSeparator(); m.addItem (3, "Show plugin UI"); - m.addItem (4, "Show all parameters"); + m.addItem (4, "Show all programs"); + m.addItem (5, "Show all parameters"); + m.addItem (6, "Test state save/load"); const int r = m.show(); @@ -255,12 +346,35 @@ public: { graph.disconnectFilter (filterID); } - else if (r == 3 || r == 4) + else { if (AudioProcessorGraph::Node::Ptr f = graph.getNodeForId (filterID)) { - if (PluginWindow* const w = PluginWindow::getWindowFor (f, r == 4)) - w->toFront (true); + AudioProcessor* const processor = f->getProcessor(); + jassert (processor != nullptr); + + if (r == 6) + { + MemoryBlock state; + processor->getStateInformation (state); + processor->setStateInformation (state.getData(), (int) state.getSize()); + } + else + { + PluginWindow::WindowFormatType type = processor->hasEditor() ? PluginWindow::Normal + : PluginWindow::Generic; + + switch (r) + { + case 4: type = PluginWindow::Programs; break; + case 5: type = PluginWindow::Parameters; break; + + default: break; + }; + + if (PluginWindow* const w = PluginWindow::getWindowFor (f, type)) + w->toFront (true); + } } } } @@ -288,7 +402,7 @@ public: if (e.mouseWasClicked() && e.getNumberOfClicks() == 2) { if (const AudioProcessorGraph::Node::Ptr f = graph.getNodeForId (filterID)) - if (PluginWindow* const w = PluginWindow::getWindowFor (f, false)) + if (PluginWindow* const w = PluginWindow::getWindowFor (f, PluginWindow::Normal)) w->toFront (true); } else if (! e.mouseWasClicked()) diff --git a/extras/audio plugin host/Source/GraphEditorPanel.h b/extras/audio plugin host/Source/GraphEditorPanel.h index 4635e4d083..d09b841dc4 100644 --- a/extras/audio plugin host/Source/GraphEditorPanel.h +++ b/extras/audio plugin host/Source/GraphEditorPanel.h @@ -48,17 +48,17 @@ public: void createNewPlugin (const PluginDescription* desc, int x, int y); - FilterComponent* getComponentForFilter (const uint32 filterID) const; + FilterComponent* getComponentForFilter (uint32 filterID) const; ConnectorComponent* getComponentForConnection (const AudioProcessorGraph::Connection& conn) const; - PinComponent* findPinAt (const int x, const int y) const; + PinComponent* findPinAt (int x, int y) const; void resized(); void changeListenerCallback (ChangeBroadcaster*); void updateComponents(); //============================================================================== - void beginConnectorDrag (const uint32 sourceFilterID, const int sourceFilterChannel, - const uint32 destFilterID, const int destFilterChannel, + void beginConnectorDrag (uint32 sourceFilterID, int sourceFilterChannel, + uint32 destFilterID, int destFilterChannel, const MouseEvent& e); void dragConnector (const MouseEvent& e); void endDraggingConnector (const MouseEvent& e); @@ -109,30 +109,36 @@ private: }; //============================================================================== -/** A desktop window containing a plugin's UI. -*/ +/** A desktop window containing a plugin's UI. */ class PluginWindow : public DocumentWindow { - PluginWindow (Component* const uiComp, - AudioProcessorGraph::Node* owner_, - const bool isGeneric_); - public: - static PluginWindow* getWindowFor (AudioProcessorGraph::Node* node, - bool useGenericView); - - static void closeCurrentlyOpenWindowsFor (const uint32 nodeId); - - static void closeAllCurrentlyOpenWindows(); + enum WindowFormatType + { + Normal = 0, + Generic, + Programs, + Parameters + }; + PluginWindow (Component* pluginEditor, AudioProcessorGraph::Node*, WindowFormatType); ~PluginWindow(); - void moved(); - void closeButtonPressed(); + static PluginWindow* getWindowFor (AudioProcessorGraph::Node*, WindowFormatType); + + static void closeCurrentlyOpenWindowsFor (const uint32 nodeId); + static void closeAllCurrentlyOpenWindows(); + + void moved() override; + void closeButtonPressed() override; private: AudioProcessorGraph::Node* owner; - bool isGeneric; + WindowFormatType type; + + float getDesktopScaleFactor() const override { return 1.0f; } + + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (PluginWindow) }; #endif // __GRAPHEDITORPANEL_JUCEHEADER__ diff --git a/extras/audio plugin host/Source/HostStartup.cpp b/extras/audio plugin host/Source/HostStartup.cpp index 1e9233cec5..2cc1ca52a9 100644 --- a/extras/audio plugin host/Source/HostStartup.cpp +++ b/extras/audio plugin host/Source/HostStartup.cpp @@ -26,7 +26,7 @@ #include "MainHostWindow.h" #include "InternalFilters.h" -#if ! (JUCE_PLUGINHOST_VST || JUCE_PLUGINHOST_AU) +#if ! (JUCE_PLUGINHOST_VST || JUCE_PLUGINHOST_VST3 || JUCE_PLUGINHOST_AU) #error "If you're building the audio plugin host, you probably want to enable VST and/or AU support" #endif @@ -49,6 +49,8 @@ public: appProperties = new ApplicationProperties(); appProperties->setStorageParameters (options); + LookAndFeel::setDefaultLookAndFeel (&lookAndFeel); + mainWindow = new MainHostWindow(); mainWindow->setUsingNativeTitleBar (true); @@ -68,6 +70,7 @@ public: { mainWindow = nullptr; appProperties = nullptr; + LookAndFeel::setDefaultLookAndFeel (nullptr); } void systemRequestedQuit() @@ -84,6 +87,7 @@ public: ApplicationCommandManager commandManager; ScopedPointer appProperties; + LookAndFeel_V3 lookAndFeel; private: ScopedPointer mainWindow;