@@ -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; | |||