| @@ -120,7 +120,7 @@ endif | |||
| # -------------------------------------------------------------- | |||
| TARGETS = jackplugin native | |||
| TARGETS = native | |||
| # -------------------------------------------------------------- | |||
| # UI bridges | |||
| @@ -22,10 +22,9 @@ | |||
| ============================================================================== | |||
| */ | |||
| //#include "MainHostWindow.h" | |||
| #include "FilterGraph.h" | |||
| #include "InternalFilters.h" | |||
| //#include "GraphEditorPanel.h" | |||
| #include "GraphEditorPanel.h" | |||
| //============================================================================== | |||
| @@ -36,7 +35,7 @@ FilterGraph::FilterGraph (AudioPluginFormatManager& formatManager_) | |||
| filenameWildcard, | |||
| "Load a filter graph", | |||
| "Save a filter graph"), | |||
| formatManager (formatManager_), lastUID (0) | |||
| formatManager (formatManager_), lastUID (0), appProperties (nullptr), panel (nullptr) | |||
| { | |||
| setChangedFlag (false); | |||
| } | |||
| @@ -46,13 +45,21 @@ FilterGraph::~FilterGraph() | |||
| graph.clear(); | |||
| } | |||
| void FilterGraph::ready() | |||
| void FilterGraph::ready(ApplicationProperties* ap) | |||
| { | |||
| appProperties = ap; | |||
| InternalPluginFormat internalFormat; | |||
| addFilter (internalFormat.getDescriptionFor (InternalPluginFormat::audioInputFilter), 0.5f, 0.1f); | |||
| addFilter (internalFormat.getDescriptionFor (InternalPluginFormat::midiInputFilter), 0.25f, 0.1f); | |||
| addFilter (internalFormat.getDescriptionFor (InternalPluginFormat::audioOutputFilter), 0.5f, 0.9f); | |||
| addFilter (internalFormat.getDescriptionFor (InternalPluginFormat::midiOutputFilter), 0.25f, 0.9f); | |||
| } | |||
| void FilterGraph::setPanel(GraphEditorPanel* p) | |||
| { | |||
| panel = p; | |||
| } | |||
| uint32 FilterGraph::getNextUID() noexcept | |||
| @@ -104,7 +111,8 @@ void FilterGraph::addFilter (const PluginDescription* desc, double x, double y) | |||
| void FilterGraph::removeFilter (const uint32 id) | |||
| { | |||
| //PluginWindow::closeCurrentlyOpenWindowsFor (id); | |||
| if (panel != nullptr) | |||
| panel->closeCurrentlyOpenWindowsFor (id); | |||
| if (graph.removeNode (id)) | |||
| changed(); | |||
| @@ -199,7 +207,8 @@ void FilterGraph::removeConnection (uint32 sourceFilterUID, int sourceFilterChan | |||
| void FilterGraph::clear() | |||
| { | |||
| //PluginWindow::closeAllCurrentlyOpenWindows(); | |||
| if (panel != nullptr) | |||
| panel->closeAllCurrentlyOpenWindows(); | |||
| graph.clear(); | |||
| changed(); | |||
| @@ -238,11 +247,29 @@ Result FilterGraph::saveDocument (const File& file) | |||
| File FilterGraph::getLastDocumentOpened() | |||
| { | |||
| return File(); | |||
| if (appProperties == nullptr) | |||
| return File(); | |||
| RecentlyOpenedFilesList recentFiles; | |||
| recentFiles.restoreFromString (appProperties->getUserSettings() | |||
| ->getValue ("recentFilterGraphFiles")); | |||
| return recentFiles.getFile (0); | |||
| } | |||
| void FilterGraph::setLastDocumentOpened (const File&) | |||
| void FilterGraph::setLastDocumentOpened (const File& file) | |||
| { | |||
| if (appProperties == nullptr) | |||
| return; | |||
| RecentlyOpenedFilesList recentFiles; | |||
| recentFiles.restoreFromString (appProperties->getUserSettings() | |||
| ->getValue ("recentFilterGraphFiles")); | |||
| recentFiles.addFile (file); | |||
| appProperties->getUserSettings() | |||
| ->setValue ("recentFilterGraphFiles", recentFiles.toString()); | |||
| } | |||
| //============================================================================== | |||
| @@ -27,6 +27,7 @@ | |||
| class FilterInGraph; | |||
| class FilterGraph; | |||
| class GraphEditorPanel; | |||
| const char* const filenameSuffix = ".filtergraph"; | |||
| const char* const filenameWildcard = "*.filtergraph"; | |||
| @@ -41,7 +42,8 @@ public: | |||
| //============================================================================== | |||
| FilterGraph (AudioPluginFormatManager& formatManager); | |||
| ~FilterGraph(); | |||
| void ready(); | |||
| void ready(ApplicationProperties* appProperties); | |||
| void setPanel(GraphEditorPanel* panel); | |||
| //============================================================================== | |||
| AudioProcessorGraph& getGraph() noexcept { return graph; } | |||
| @@ -107,6 +109,9 @@ private: | |||
| void createNodeFromXml (const XmlElement& xml); | |||
| ApplicationProperties* appProperties; | |||
| GraphEditorPanel* panel; | |||
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (FilterGraph) | |||
| }; | |||
| @@ -22,53 +22,31 @@ | |||
| ============================================================================== | |||
| */ | |||
| #include "juce_gui_basics.h" | |||
| #include "GraphEditorPanel.h" | |||
| #include "InternalFilters.h" | |||
| //#include "MainHostWindow.h" | |||
| //============================================================================== | |||
| class PluginWindow; | |||
| static Array <PluginWindow*> activePluginWindows; | |||
| PluginWindow::PluginWindow (Component* const pluginEditor, | |||
| PluginWindow::PluginWindow (GraphEditorPanel* const p, | |||
| Component* const pluginEditor, | |||
| AudioProcessorGraph::Node* const o, | |||
| WindowFormatType t) | |||
| : DocumentWindow (pluginEditor->getName(), Colours::lightblue, | |||
| DocumentWindow::minimiseButton | DocumentWindow::closeButton), | |||
| owner (o), | |||
| type (t) | |||
| type (t), | |||
| panel (p) | |||
| { | |||
| setSize (400, 300); | |||
| setContentOwned (pluginEditor, true); | |||
| setUsingNativeTitleBar (true); | |||
| setTopLeftPosition (owner->properties.getWithDefault ("uiLastX", Random::getSystemRandom().nextInt (500)), | |||
| owner->properties.getWithDefault ("uiLastY", Random::getSystemRandom().nextInt (500))); | |||
| setVisible (true); | |||
| activePluginWindows.add (this); | |||
| } | |||
| void PluginWindow::closeCurrentlyOpenWindowsFor (const uint32 nodeId) | |||
| { | |||
| for (int i = activePluginWindows.size(); --i >= 0;) | |||
| if (activePluginWindows.getUnchecked(i)->owner->nodeId == nodeId) | |||
| delete activePluginWindows.getUnchecked (i); | |||
| } | |||
| void PluginWindow::closeAllCurrentlyOpenWindows() | |||
| { | |||
| if (activePluginWindows.size() > 0) | |||
| { | |||
| for (int i = activePluginWindows.size(); --i >= 0;) | |||
| delete activePluginWindows.getUnchecked (i); | |||
| Component dummyModalComp; | |||
| dummyModalComp.enterModalState(); | |||
| MessageManager::getInstance()->runDispatchLoopUntil (50); | |||
| } | |||
| panel->activePluginWindows.add (this); | |||
| } | |||
| //============================================================================== | |||
| @@ -149,50 +127,9 @@ private: | |||
| 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<AudioPluginInstance*> (processor)) | |||
| ui->setName (plugin->getName()); | |||
| return new PluginWindow (ui, node, type); | |||
| } | |||
| return nullptr; | |||
| } | |||
| PluginWindow::~PluginWindow() | |||
| { | |||
| activePluginWindows.removeFirstMatchingValue (this); | |||
| panel->activePluginWindows.removeFirstMatchingValue (this); | |||
| clearContentComponent(); | |||
| } | |||
| @@ -372,7 +309,7 @@ public: | |||
| default: break; | |||
| }; | |||
| if (PluginWindow* const w = PluginWindow::getWindowFor (f, type)) | |||
| if (PluginWindow* const w = getGraphPanel()->getWindowFor (f, type)) | |||
| w->toFront (true); | |||
| } | |||
| } | |||
| @@ -402,7 +339,7 @@ public: | |||
| if (e.mouseWasClicked() && e.getNumberOfClicks() == 2) | |||
| { | |||
| if (const AudioProcessorGraph::Node::Ptr f = graph.getNodeForId (filterID)) | |||
| if (PluginWindow* const w = PluginWindow::getWindowFor (f, PluginWindow::Normal)) | |||
| if (PluginWindow* const w = getGraphPanel()->getWindowFor (f, PluginWindow::Normal)) | |||
| w->toFront (true); | |||
| } | |||
| else if (! e.mouseWasClicked()) | |||
| @@ -814,7 +751,6 @@ void GraphEditorPanel::mouseDown (const MouseEvent& e) | |||
| { | |||
| if (e.mods.isPopupMenu()) | |||
| { | |||
| #if 0 | |||
| PopupMenu m; | |||
| if (MainHostWindow* const mainWindow = findParentComponentOfClass<MainHostWindow>()) | |||
| @@ -825,7 +761,6 @@ void GraphEditorPanel::mouseDown (const MouseEvent& e) | |||
| createNewPlugin (mainWindow->getChosenType (r), e.x, e.y); | |||
| } | |||
| #endif | |||
| } | |||
| } | |||
| @@ -1041,6 +976,67 @@ void GraphEditorPanel::endDraggingConnector (const MouseEvent& e) | |||
| } | |||
| } | |||
| //============================================================================== | |||
| PluginWindow* GraphEditorPanel::getWindowFor (AudioProcessorGraph::Node* const node, | |||
| PluginWindow::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 == PluginWindow::Normal) | |||
| { | |||
| ui = processor->createEditorIfNeeded(); | |||
| if (ui == nullptr) | |||
| type = PluginWindow::Generic; | |||
| } | |||
| if (ui == nullptr) | |||
| { | |||
| if (type == PluginWindow::Generic || type == PluginWindow::Parameters) | |||
| ui = new GenericAudioProcessorEditor (processor); | |||
| else if (type == PluginWindow::Programs) | |||
| ui = new ProgramAudioProcessorEditor (processor); | |||
| } | |||
| if (ui != nullptr) | |||
| { | |||
| if (AudioPluginInstance* const plugin = dynamic_cast<AudioPluginInstance*> (processor)) | |||
| ui->setName (plugin->getName()); | |||
| return new PluginWindow (this, ui, node, type); | |||
| } | |||
| return nullptr; | |||
| } | |||
| void GraphEditorPanel::closeCurrentlyOpenWindowsFor (const uint32 nodeId) | |||
| { | |||
| for (int i = activePluginWindows.size(); --i >= 0;) | |||
| if (activePluginWindows.getUnchecked(i)->owner->nodeId == nodeId) | |||
| delete activePluginWindows.getUnchecked (i); | |||
| } | |||
| void GraphEditorPanel::closeAllCurrentlyOpenWindows() | |||
| { | |||
| if (activePluginWindows.size() > 0) | |||
| { | |||
| for (int i = activePluginWindows.size(); --i >= 0;) | |||
| delete activePluginWindows.getUnchecked (i); | |||
| Component dummyModalComp; | |||
| dummyModalComp.enterModalState(); | |||
| MessageManager::getInstance()->runDispatchLoopUntil (50); | |||
| } | |||
| } | |||
| //============================================================================== | |||
| class TooltipBar : public Component, | |||
| @@ -1088,6 +1084,7 @@ GraphDocumentComponent::GraphDocumentComponent (FilterGraph& g) | |||
| { | |||
| addAndMakeVisible (graphPanel = new GraphEditorPanel (graph)); | |||
| // listen for audio/midi count change | |||
| //deviceManager->addChangeListener (graphPanel); | |||
| //keyState.addListener (&graphPlayer.getMidiMessageCollector()); | |||
| @@ -1098,10 +1095,15 @@ GraphDocumentComponent::GraphDocumentComponent (FilterGraph& g) | |||
| addAndMakeVisible (statusBar = new TooltipBar()); | |||
| graphPanel->updateComponents(); | |||
| graph.setPanel(graphPanel); | |||
| } | |||
| GraphDocumentComponent::~GraphDocumentComponent() | |||
| { | |||
| graph.setPanel(nullptr); | |||
| // listen for audio/midi count change | |||
| //deviceManager->removeChangeListener (graphPanel); | |||
| deleteAllChildren(); | |||
| @@ -1123,3 +1125,8 @@ void GraphDocumentComponent::createNewPlugin (const PluginDescription* desc, int | |||
| { | |||
| graphPanel->createNewPlugin (desc, x, y); | |||
| } | |||
| void GraphDocumentComponent::closeAllCurrentlyOpenWindows() | |||
| { | |||
| graphPanel->closeAllCurrentlyOpenWindows(); | |||
| } | |||
| @@ -30,6 +30,39 @@ | |||
| class FilterComponent; | |||
| class ConnectorComponent; | |||
| class PinComponent; | |||
| class GraphEditorPanel; | |||
| //============================================================================== | |||
| /** A desktop window containing a plugin's UI. */ | |||
| class PluginWindow : public DocumentWindow | |||
| { | |||
| public: | |||
| enum WindowFormatType | |||
| { | |||
| Normal = 0, | |||
| Generic, | |||
| Programs, | |||
| Parameters | |||
| }; | |||
| PluginWindow (GraphEditorPanel* const panel, Component* pluginEditor, AudioProcessorGraph::Node*, WindowFormatType); | |||
| ~PluginWindow(); | |||
| void moved() override; | |||
| void closeButtonPressed() override; | |||
| private: | |||
| AudioProcessorGraph::Node* owner; | |||
| WindowFormatType type; | |||
| float getDesktopScaleFactor() const override { return 1.0f; } | |||
| GraphEditorPanel* const panel; | |||
| friend class GraphEditorPanel; | |||
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (PluginWindow) | |||
| }; | |||
| //============================================================================== | |||
| @@ -64,6 +97,15 @@ public: | |||
| void endDraggingConnector (const MouseEvent& e); | |||
| //============================================================================== | |||
| Array <PluginWindow*> activePluginWindows; | |||
| PluginWindow* getWindowFor (AudioProcessorGraph::Node*, PluginWindow::WindowFormatType); | |||
| void closeCurrentlyOpenWindowsFor (const uint32 nodeId); | |||
| void closeAllCurrentlyOpenWindows(); | |||
| //============================================================================== | |||
| private: | |||
| FilterGraph& graph; | |||
| ScopedPointer<ConnectorComponent> draggingConnector; | |||
| @@ -94,6 +136,9 @@ public: | |||
| //============================================================================== | |||
| void resized(); | |||
| //============================================================================== | |||
| void closeAllCurrentlyOpenWindows(); | |||
| private: | |||
| //============================================================================== | |||
| MidiKeyboardState keyState; | |||
| @@ -105,37 +150,4 @@ private: | |||
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (GraphDocumentComponent) | |||
| }; | |||
| //============================================================================== | |||
| /** A desktop window containing a plugin's UI. */ | |||
| class PluginWindow : public DocumentWindow | |||
| { | |||
| public: | |||
| enum WindowFormatType | |||
| { | |||
| Normal = 0, | |||
| Generic, | |||
| Programs, | |||
| Parameters | |||
| }; | |||
| PluginWindow (Component* pluginEditor, AudioProcessorGraph::Node*, WindowFormatType); | |||
| ~PluginWindow(); | |||
| 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; | |||
| WindowFormatType type; | |||
| float getDesktopScaleFactor() const override { return 1.0f; } | |||
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (PluginWindow) | |||
| }; | |||
| #endif // __GRAPHEDITORPANEL_JUCEHEADER__ | |||
| @@ -43,6 +43,11 @@ InternalPluginFormat::InternalPluginFormat() | |||
| AudioProcessorGraph::AudioGraphIOProcessor p (AudioProcessorGraph::AudioGraphIOProcessor::midiInputNode); | |||
| p.fillInPluginDescription (midiInDesc); | |||
| } | |||
| { | |||
| AudioProcessorGraph::AudioGraphIOProcessor p (AudioProcessorGraph::AudioGraphIOProcessor::midiOutputNode); | |||
| p.fillInPluginDescription (midiOutDesc); | |||
| } | |||
| } | |||
| AudioPluginInstance* InternalPluginFormat::createInstanceFromDescription (const PluginDescription& desc, | |||
| @@ -57,6 +62,9 @@ AudioPluginInstance* InternalPluginFormat::createInstanceFromDescription (const | |||
| if (desc.name == midiInDesc.name) | |||
| return new AudioProcessorGraph::AudioGraphIOProcessor (AudioProcessorGraph::AudioGraphIOProcessor::midiInputNode); | |||
| if (desc.name == midiOutDesc.name) | |||
| return new AudioProcessorGraph::AudioGraphIOProcessor (AudioProcessorGraph::AudioGraphIOProcessor::midiOutputNode); | |||
| return 0; | |||
| } | |||
| @@ -67,6 +75,7 @@ const PluginDescription* InternalPluginFormat::getDescriptionFor (const Internal | |||
| case audioInputFilter: return &audioInDesc; | |||
| case audioOutputFilter: return &audioOutDesc; | |||
| case midiInputFilter: return &midiInDesc; | |||
| case midiOutputFilter: return &midiOutDesc; | |||
| default: break; | |||
| } | |||
| @@ -45,6 +45,7 @@ public: | |||
| audioInputFilter = 0, | |||
| audioOutputFilter, | |||
| midiInputFilter, | |||
| midiOutputFilter, | |||
| endOfFilterTypes | |||
| }; | |||
| @@ -70,6 +71,7 @@ private: | |||
| PluginDescription audioInDesc; | |||
| PluginDescription audioOutDesc; | |||
| PluginDescription midiInDesc; | |||
| PluginDescription midiOutDesc; | |||
| }; | |||
| @@ -22,7 +22,6 @@ | |||
| ============================================================================== | |||
| */ | |||
| #include "juce_gui_basics.h" | |||
| #include "MainHostWindow.h" | |||
| #include "InternalFilters.h" | |||
| @@ -36,25 +35,27 @@ public: | |||
| DocumentWindow::minimiseButton | DocumentWindow::closeButton), | |||
| owner (owner_) | |||
| { | |||
| const File deadMansPedalFile (getAppProperties().getUserSettings() | |||
| ->getFile().getSiblingFile ("RecentlyCrashedPluginsList")); | |||
| const File deadMansPedalFile (owner.appProperties.getUserSettings() | |||
| ->getFile().getSiblingFile ("RecentlyCrashedPluginsList")); | |||
| setContentOwned (new PluginListComponent (formatManager, | |||
| owner.knownPluginList, | |||
| deadMansPedalFile, | |||
| getAppProperties().getUserSettings()), true); | |||
| owner.appProperties.getUserSettings()), true); | |||
| setOpaque (true); | |||
| setResizable (true, false); | |||
| setResizeLimits (300, 400, 800, 1500); | |||
| setTopLeftPosition (60, 60); | |||
| restoreWindowStateFromString (getAppProperties().getUserSettings()->getValue ("listWindowPos")); | |||
| restoreWindowStateFromString (owner.appProperties.getUserSettings()->getValue ("listWindowPos")); | |||
| setUsingNativeTitleBar (true); | |||
| setVisible (true); | |||
| } | |||
| ~PluginListWindow() | |||
| { | |||
| getAppProperties().getUserSettings()->setValue ("listWindowPos", getWindowStateAsString()); | |||
| owner.appProperties.getUserSettings()->setValue ("listWindowPos", getWindowStateAsString()); | |||
| clearContentComponent(); | |||
| } | |||
| @@ -71,44 +72,42 @@ private: | |||
| }; | |||
| //============================================================================== | |||
| MainHostWindow::MainHostWindow() | |||
| : DocumentWindow (JUCEApplication::getInstance()->getApplicationName(), Colours::lightgrey, | |||
| DocumentWindow::allButtons) | |||
| MainHostWindow::MainHostWindow (AudioPluginFormatManager& fm, FilterGraph& graph, ApplicationProperties& ap) | |||
| : DocumentWindow ("Juce Patchbay", Colours::lightgrey, DocumentWindow::allButtons), | |||
| formatManager (fm), | |||
| appProperties (ap), | |||
| closed (false) | |||
| { | |||
| formatManager.addDefaultFormats(); | |||
| formatManager.addFormat (new InternalPluginFormat()); | |||
| ScopedPointer<XmlElement> savedAudioState (getAppProperties().getUserSettings() | |||
| ->getXmlValue ("audioDeviceState")); | |||
| //deviceManager.initialise (256, 256, savedAudioState, true); | |||
| LookAndFeel::setDefaultLookAndFeel (&lookAndFeel); | |||
| setOpaque (true); | |||
| setResizable (true, false); | |||
| setResizeLimits (500, 400, 10000, 10000); | |||
| centreWithSize (800, 600); | |||
| //setContentOwned (new GraphDocumentComponent (formatManager, &deviceManager), false); | |||
| setContentOwned (new GraphDocumentComponent (graph), false); | |||
| setUsingNativeTitleBar (true); | |||
| restoreWindowStateFromString (getAppProperties().getUserSettings()->getValue ("mainWindowPos")); | |||
| restoreWindowStateFromString (appProperties.getUserSettings()->getValue ("mainWindowPos")); | |||
| setVisible (true); | |||
| InternalPluginFormat internalFormat; | |||
| internalFormat.getAllTypes (internalTypes); | |||
| ScopedPointer<XmlElement> savedPluginList (getAppProperties().getUserSettings()->getXmlValue ("pluginList")); | |||
| ScopedPointer<XmlElement> savedPluginList (appProperties.getUserSettings()->getXmlValue ("pluginList")); | |||
| if (savedPluginList != nullptr) | |||
| knownPluginList.recreateFromXml (*savedPluginList); | |||
| pluginSortMethod = (KnownPluginList::SortMethod) getAppProperties().getUserSettings() | |||
| pluginSortMethod = (KnownPluginList::SortMethod) appProperties.getUserSettings() | |||
| ->getIntValue ("pluginSortMethod", KnownPluginList::sortByManufacturer); | |||
| knownPluginList.addChangeListener (this); | |||
| addKeyListener (getCommandManager().getKeyMappings()); | |||
| addKeyListener (commandManager.getKeyMappings()); | |||
| Process::setPriority (Process::HighPriority); | |||
| //Process::setPriority (Process::HighPriority); | |||
| #if JUCE_MAC | |||
| setMacMainMenu (this); | |||
| @@ -116,7 +115,10 @@ MainHostWindow::MainHostWindow() | |||
| setMenuBar (this); | |||
| #endif | |||
| getCommandManager().setFirstCommandTarget (this); | |||
| commandManager.setFirstCommandTarget (this); | |||
| commandManager.registerAllCommandsForTarget (this); | |||
| menuItemsChanged(); | |||
| } | |||
| MainHostWindow::~MainHostWindow() | |||
| @@ -131,27 +133,17 @@ MainHostWindow::~MainHostWindow() | |||
| knownPluginList.removeChangeListener (this); | |||
| getAppProperties().getUserSettings()->setValue ("mainWindowPos", getWindowStateAsString()); | |||
| appProperties.getUserSettings()->setValue ("mainWindowPos", getWindowStateAsString()); | |||
| clearContentComponent(); | |||
| } | |||
| void MainHostWindow::closeButtonPressed() | |||
| { | |||
| tryToQuitApplication(); | |||
| LookAndFeel::setDefaultLookAndFeel (nullptr); | |||
| } | |||
| bool MainHostWindow::tryToQuitApplication() | |||
| void MainHostWindow::closeButtonPressed() | |||
| { | |||
| PluginWindow::closeAllCurrentlyOpenWindows(); | |||
| getGraphEditor()->closeAllCurrentlyOpenWindows(); | |||
| if (getGraphEditor() == nullptr | |||
| || getGraphEditor()->graph.saveIfNeededAndUserAgrees() == FileBasedDocument::savedOk) | |||
| { | |||
| JUCEApplication::quit(); | |||
| return true; | |||
| } | |||
| return false; | |||
| closed = true; | |||
| } | |||
| void MainHostWindow::changeListenerCallback (ChangeBroadcaster*) | |||
| @@ -164,8 +156,8 @@ void MainHostWindow::changeListenerCallback (ChangeBroadcaster*) | |||
| if (savedPluginList != nullptr) | |||
| { | |||
| getAppProperties().getUserSettings()->setValue ("pluginList", savedPluginList); | |||
| getAppProperties().saveIfNeeded(); | |||
| appProperties.getUserSettings()->setValue ("pluginList", savedPluginList); | |||
| appProperties.saveIfNeeded(); | |||
| } | |||
| } | |||
| @@ -183,20 +175,18 @@ PopupMenu MainHostWindow::getMenuForIndex (int topLevelMenuIndex, const String& | |||
| if (topLevelMenuIndex == 0) | |||
| { | |||
| // "File" menu | |||
| menu.addCommandItem (&getCommandManager(), CommandIDs::open); | |||
| menu.addCommandItem (&commandManager, CommandIDs::open); | |||
| RecentlyOpenedFilesList recentFiles; | |||
| recentFiles.restoreFromString (getAppProperties().getUserSettings() | |||
| recentFiles.restoreFromString (appProperties.getUserSettings() | |||
| ->getValue ("recentFilterGraphFiles")); | |||
| PopupMenu recentFilesMenu; | |||
| recentFiles.createPopupMenuItems (recentFilesMenu, 100, true, true); | |||
| menu.addSubMenu ("Open recent file", recentFilesMenu); | |||
| menu.addCommandItem (&getCommandManager(), CommandIDs::save); | |||
| menu.addCommandItem (&getCommandManager(), CommandIDs::saveAs); | |||
| menu.addSeparator(); | |||
| menu.addCommandItem (&getCommandManager(), StandardApplicationCommandIDs::quit); | |||
| menu.addCommandItem (&commandManager, CommandIDs::save); | |||
| menu.addCommandItem (&commandManager, CommandIDs::saveAs); | |||
| } | |||
| else if (topLevelMenuIndex == 1) | |||
| { | |||
| @@ -211,7 +201,7 @@ PopupMenu MainHostWindow::getMenuForIndex (int topLevelMenuIndex, const String& | |||
| { | |||
| // "Options" menu | |||
| menu.addCommandItem (&getCommandManager(), CommandIDs::showPluginListEditor); | |||
| menu.addCommandItem (&commandManager, CommandIDs::showPluginListEditor); | |||
| PopupMenu sortTypeMenu; | |||
| sortTypeMenu.addItem (200, "List plugins in default order", true, pluginSortMethod == KnownPluginList::defaultOrder); | |||
| @@ -222,7 +212,7 @@ PopupMenu MainHostWindow::getMenuForIndex (int topLevelMenuIndex, const String& | |||
| menu.addSubMenu ("Plugin menu type", sortTypeMenu); | |||
| menu.addSeparator(); | |||
| menu.addCommandItem (&getCommandManager(), CommandIDs::aboutBox); | |||
| menu.addCommandItem (&commandManager, CommandIDs::aboutBox); | |||
| } | |||
| return menu; | |||
| @@ -240,7 +230,7 @@ void MainHostWindow::menuItemSelected (int menuItemID, int /*topLevelMenuIndex*/ | |||
| else if (menuItemID >= 100 && menuItemID < 200) | |||
| { | |||
| RecentlyOpenedFilesList recentFiles; | |||
| recentFiles.restoreFromString (getAppProperties().getUserSettings() | |||
| recentFiles.restoreFromString (appProperties.getUserSettings() | |||
| ->getValue ("recentFilterGraphFiles")); | |||
| if (graphEditor != nullptr && graphEditor->graph.saveIfNeededAndUserAgrees() == FileBasedDocument::savedOk) | |||
| @@ -254,7 +244,7 @@ void MainHostWindow::menuItemSelected (int menuItemID, int /*topLevelMenuIndex*/ | |||
| else if (menuItemID == 203) pluginSortMethod = KnownPluginList::sortByManufacturer; | |||
| else if (menuItemID == 204) pluginSortMethod = KnownPluginList::sortByFileSystemLocation; | |||
| getAppProperties().getUserSettings()->setValue ("pluginSortMethod", (int) pluginSortMethod); | |||
| appProperties.getUserSettings()->setValue ("pluginSortMethod", (int) pluginSortMethod); | |||
| menuItemsChanged(); | |||
| } | |||
| @@ -437,3 +427,8 @@ GraphDocumentComponent* MainHostWindow::getGraphEditor() const | |||
| { | |||
| return dynamic_cast <GraphDocumentComponent*> (getContentComponent()); | |||
| } | |||
| bool MainHostWindow::wasClosedByUser() const noexcept | |||
| { | |||
| return closed; | |||
| } | |||
| @@ -36,7 +36,7 @@ namespace CommandIDs | |||
| static const int save = 0x30001; | |||
| static const int saveAs = 0x30002; | |||
| static const int showPluginListEditor = 0x30100; | |||
| static const int aboutBox = 0x30300; | |||
| static const int aboutBox = 0x30200; | |||
| } | |||
| //============================================================================== | |||
| @@ -50,7 +50,7 @@ class MainHostWindow : public DocumentWindow, | |||
| { | |||
| public: | |||
| //============================================================================== | |||
| MainHostWindow(); | |||
| MainHostWindow (AudioPluginFormatManager& formatManager, FilterGraph& graph, ApplicationProperties& appProperties); | |||
| ~MainHostWindow(); | |||
| //============================================================================== | |||
| @@ -71,8 +71,6 @@ public: | |||
| void getCommandInfo (CommandID commandID, ApplicationCommandInfo& result); | |||
| bool perform (const InvocationInfo& info); | |||
| bool tryToQuitApplication(); | |||
| void createPlugin (const PluginDescription* desc, int x, int y); | |||
| void addPluginsToMenu (PopupMenu& m) const; | |||
| @@ -80,10 +78,11 @@ public: | |||
| GraphDocumentComponent* getGraphEditor() const; | |||
| bool wasClosedByUser() const noexcept; | |||
| private: | |||
| //============================================================================== | |||
| //AudioDeviceManager deviceManager; | |||
| AudioPluginFormatManager formatManager; | |||
| AudioPluginFormatManager& formatManager; | |||
| OwnedArray <PluginDescription> internalTypes; | |||
| KnownPluginList knownPluginList; | |||
| @@ -92,6 +91,12 @@ private: | |||
| class PluginListWindow; | |||
| ScopedPointer <PluginListWindow> pluginListWindow; | |||
| ApplicationCommandManager commandManager; | |||
| ApplicationProperties& appProperties; | |||
| LookAndFeel_V3 lookAndFeel; | |||
| bool closed; | |||
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MainHostWindow) | |||
| }; | |||
| @@ -20,8 +20,6 @@ | |||
| #include "juce_audio_processors.h" | |||
| #include "juce_gui_extra.h" | |||
| #include "JucePluginWindow.hpp" | |||
| using namespace juce; | |||
| // ----------------------------------------------------------------------- | |||
| @@ -29,6 +27,7 @@ using namespace juce; | |||
| #include "juce-host/FilterGraph.h" | |||
| #include "juce-host/InternalFilters.h" | |||
| #include "juce-host/GraphEditorPanel.h" | |||
| #include "juce-host/MainHostWindow.h" | |||
| // ----------------------------------------------------------------------- | |||
| @@ -40,9 +39,17 @@ public: | |||
| graph(formatManager), | |||
| fAudioBuffer(1, 0) | |||
| { | |||
| PropertiesFile::Options options; | |||
| options.applicationName = "Juce Audio Plugin Host"; | |||
| options.filenameSuffix = "settings"; | |||
| options.osxLibrarySubFolder = "Preferences"; | |||
| fAppProperties = new ApplicationProperties(); | |||
| fAppProperties->setStorageParameters (options); | |||
| formatManager.addDefaultFormats(); | |||
| formatManager.addFormat(new InternalPluginFormat()); | |||
| graph.ready(); | |||
| graph.ready(fAppProperties); | |||
| graph.getGraph().setPlayConfigDetails(2, 2, getSampleRate(), static_cast<int>(getBufferSize())); | |||
| @@ -52,6 +59,7 @@ public: | |||
| ~JucePatchbayPlugin() override | |||
| { | |||
| fAppProperties = nullptr; | |||
| } | |||
| protected: | |||
| @@ -70,13 +78,40 @@ protected: | |||
| graph.getGraph().releaseResources(); | |||
| } | |||
| void process(float** inBuffer, float** const outBuffer, const uint32_t frames, const NativeMidiEvent* const, const uint32_t) override | |||
| void process(float** inBuffer, float** const outBuffer, const uint32_t frames, const NativeMidiEvent* const midiEvents, const uint32_t midiEventCount) override | |||
| { | |||
| fAudioBuffer.copyFrom(0, 0, inBuffer[0], static_cast<int>(frames)); | |||
| fAudioBuffer.copyFrom(1, 0, inBuffer[1], static_cast<int>(frames)); | |||
| fMidiBuffer.clear(); | |||
| for (uint32_t i=0; i < midiEventCount; ++i) | |||
| { | |||
| const NativeMidiEvent* const midiEvent(&midiEvents[i]); | |||
| fMidiBuffer.addEvent(midiEvent->data, midiEvent->size, midiEvent->time); | |||
| } | |||
| graph.getGraph().processBlock(fAudioBuffer, fMidiBuffer); | |||
| MidiBuffer::Iterator outBufferIterator(fMidiBuffer); | |||
| const uint8_t* midiData; | |||
| int numBytes; | |||
| int sampleNumber; | |||
| NativeMidiEvent tmpEvent; | |||
| tmpEvent.port = 0; | |||
| for (; outBufferIterator.getNextEvent(midiData, numBytes, sampleNumber);) | |||
| { | |||
| if (numBytes <= 0 || numBytes > 4) | |||
| continue; | |||
| tmpEvent.size = numBytes; | |||
| tmpEvent.time = sampleNumber; | |||
| std::memcpy(tmpEvent.data, midiData, sizeof(uint8_t)*tmpEvent.size); | |||
| writeMidiEvent(&tmpEvent); | |||
| } | |||
| FloatVectorOperations::copy(outBuffer[0], fAudioBuffer.getSampleData(0), static_cast<int>(frames)); | |||
| FloatVectorOperations::copy(outBuffer[1], fAudioBuffer.getSampleData(1), static_cast<int>(frames)); | |||
| } | |||
| @@ -90,24 +125,14 @@ protected: | |||
| { | |||
| if (fWindow == nullptr) | |||
| { | |||
| fWindow = new JucePluginWindow(); | |||
| fWindow = new MainHostWindow(formatManager, graph, *fAppProperties); | |||
| fWindow->setName(getUiName()); | |||
| fWindow->setResizable(true, false); | |||
| } | |||
| if (fComponent == nullptr) | |||
| { | |||
| fComponent = new GraphDocumentComponent(graph); | |||
| fComponent->setSize(300, 300); | |||
| } | |||
| fWindow->show(fComponent); | |||
| fWindow->toFront(true); | |||
| } | |||
| else if (fWindow != nullptr) | |||
| { | |||
| fWindow->hide(); | |||
| fComponent = nullptr; | |||
| fWindow->setVisible(false); | |||
| fWindow = nullptr; | |||
| } | |||
| } | |||
| @@ -131,12 +156,8 @@ private: | |||
| AudioSampleBuffer fAudioBuffer; | |||
| MidiBuffer fMidiBuffer; | |||
| ScopedPointer<GraphDocumentComponent> fComponent; | |||
| ScopedPointer<JucePluginWindow> fWindow; | |||
| //OwnedArray <PluginDescription> internalTypes; | |||
| //KnownPluginList knownPluginList; | |||
| //KnownPluginList::SortMethod pluginSortMethod; | |||
| ScopedPointer<ApplicationProperties> fAppProperties; | |||
| ScopedPointer<MainHostWindow> fWindow; | |||
| PluginClassEND(JucePatchbayPlugin) | |||
| CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(JucePatchbayPlugin) | |||
| @@ -177,5 +198,6 @@ void carla_register_native_plugin_jucePatchbay() | |||
| #include "juce-host/FilterGraph.cpp" | |||
| #include "juce-host/InternalFilters.cpp" | |||
| #include "juce-host/GraphEditorPanel.cpp" | |||
| #include "juce-host/MainHostWindow.cpp" | |||
| // ----------------------------------------------------------------------- | |||
| @@ -312,7 +312,7 @@ protected: | |||
| NativeMidiEvent tmpEvent; | |||
| tmpEvent.port = 0; | |||
| while (outBufferIterator.getNextEvent(midiData, numBytes, sampleNumber)) | |||
| for (; outBufferIterator.getNextEvent(midiData, numBytes, sampleNumber);) | |||
| { | |||
| if (numBytes <= 0 || numBytes > 4) | |||
| continue; | |||