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