1
0
Fork 0
mirror of https://github.com/juce-framework/JUCE.git synced 2026-01-10 23:44:24 +00:00

Fixes to VST3 wrapper to handle different numbers of input/output channels.

This commit is contained in:
jules 2014-02-11 10:22:12 +00:00
parent 699a09f224
commit 5c74ca9896
3 changed files with 143 additions and 146 deletions

View file

@ -623,10 +623,7 @@ public:
addEventBusTo (eventOutputs, TRANS("MIDI Output"));
#endif
{
const ScopedLock sl (contextLock);
processContext.sampleRate = processSetup.sampleRate;
}
processContext.sampleRate = processSetup.sampleRate;
preparePlugin (processSetup.sampleRate, (int) processSetup.maxSamplesPerBlock);
@ -735,16 +732,16 @@ public:
double sampleRate = getPluginInstance().getSampleRate();
int bufferSize = getPluginInstance().getBlockSize();
{
const ScopedLock sl (contextLock);
sampleRate = processSetup.sampleRate > 0.0
? processSetup.sampleRate
: sampleRate;
sampleRate = processSetup.sampleRate > 0.0
? processSetup.sampleRate
: sampleRate;
bufferSize = processSetup.maxSamplesPerBlock > 0
? (int) processSetup.maxSamplesPerBlock
: bufferSize;
}
bufferSize = processSetup.maxSamplesPerBlock > 0
? (int) processSetup.maxSamplesPerBlock
: bufferSize;
channelList.clear();
channelList.insertMultiple (0, nullptr, jmax (JucePlugin_MaxNumInputChannels, JucePlugin_MaxNumOutputChannels) + 1);
preparePlugin (sampleRate, bufferSize);
}
@ -921,8 +918,6 @@ public:
//==============================================================================
bool getCurrentPosition (CurrentPositionInfo& info) override
{
const ScopedLock sl (contextLock);
info.timeInSamples = jmax ((juce::int64) 0, processContext.projectTimeSamples);
info.timeInSeconds = processContext.projectTimeMusic;
info.bpm = jmax (1.0, processContext.tempo);
@ -1089,17 +1084,16 @@ public:
tresult PLUGIN_API process (Vst::ProcessData& data) override
{
if (pluginInstance == nullptr || processContext.sampleRate <= 0.0)
return kResultFalse;
if (data.processContext != nullptr)
processContext = *data.processContext;
else
zerostruct (processContext);
midiBuffer.clear();
{
const ScopedLock sl (contextLock);
if (data.processContext != nullptr)
processContext = *data.processContext;
else
zerostruct (processContext);
}
#if JucePlugin_WantsMidiInput
if (data.inputEvents != nullptr)
MidiEventList::toMidiBuffer (midiBuffer, *data.inputEvents);
@ -1109,42 +1103,47 @@ public:
const int numMidiEventsComingIn = midiBuffer.getNumEvents();
#endif
if (pluginInstance != nullptr
&& data.inputs != nullptr
&& data.outputs != nullptr
&& processContext.sampleRate > 0.0)
const int numInputChans = data.inputs != nullptr ? (int) data.inputs[0].numChannels : 0;
const int numOutputChans = data.outputs != nullptr ? (int) data.outputs[0].numChannels : 0;
int totalChans = 0;
while (totalChans < numInputChans)
{
channelList.set (totalChans, data.inputs[0].channelBuffers32[totalChans]);
++totalChans;
}
while (totalChans < numOutputChans)
{
channelList.set (totalChans, data.outputs[0].channelBuffers32[totalChans]);
++totalChans;
}
AudioSampleBuffer buffer (channelList.getRawDataPointer(), totalChans, (int) data.numSamples);
{
const ScopedLock sl (pluginInstance->getCallbackLock());
pluginInstance->setNonRealtime (data.processMode == Vst::kOffline);
if (Vst::IParameterChanges* const paramChanges = data.inputParameterChanges)
processParameterChanges (*paramChanges);
const int numSamples = (int) data.numSamples;
const int numChannels = (int) data.inputs[0].numChannels;
AudioSampleBuffer buffer (data.inputs[0].channelBuffers32, numChannels, numSamples);
int startBusOffset = 1;
if (data.inputParameterChanges != nullptr)
processParameterChanges (*data.inputParameterChanges);
if (pluginInstance->isSuspended())
startBusOffset = 0;
buffer.clear();
else
pluginInstance->processBlock (buffer, midiBuffer);
}
// Copy the audio:
for (int i = 0; i < numChannels; ++i)
FloatVectorOperations::copy (data.outputs[0].channelBuffers32[i], buffer.getSampleData (i), numSamples);
for (int i = 0; i < numOutputChans; ++i)
FloatVectorOperations::copy (data.outputs[0].channelBuffers32[i], buffer.getSampleData (i), (int) data.numSamples);
// Clear the other busses:
for (int i = startBusOffset; i < data.numOutputs; ++i)
// clear extra busses..
if (data.outputs != nullptr)
for (int i = 1; i < data.numOutputs; ++i)
for (int f = 0; f < data.outputs[i].numChannels; ++f)
FloatVectorOperations::clear (data.outputs[i].channelBuffers32[f], numSamples);
}
else
{
return kResultFalse;
}
FloatVectorOperations::clear (data.outputs[i].channelBuffers32[f], (int) data.numSamples);
#if JucePlugin_ProducesMidiOutput
if (data.outputEvents != nullptr)
@ -1183,12 +1182,12 @@ private:
Since VST3 does not provide a way of knowing the buffer size and sample rate at any point,
this object needs to be copied on every call to process() to be up-to-date...
*/
CriticalSection contextLock; //Not sure how necessary this is...
Vst::ProcessContext processContext;
Vst::ProcessSetup processSetup;
Vst::BusList audioInputs, audioOutputs, eventInputs, eventOutputs;
MidiBuffer midiBuffer;
Array<float*> channelList;
const JuceLibraryRefCount juceCount;
@ -1210,11 +1209,8 @@ private:
Vst::BusList* getBusListFor (Vst::MediaType type, Vst::BusDirection dir)
{
if (type == Vst::kAudio)
return dir == Vst::kInput ? &audioInputs : &audioOutputs;
if (type == Vst::kEvent)
return dir == Vst::kInput ? &eventInputs : &eventOutputs;
if (type == Vst::kAudio) return dir == Vst::kInput ? &audioInputs : &audioOutputs;
if (type == Vst::kEvent) return dir == Vst::kInput ? &eventInputs : &eventOutputs;
return nullptr;
}

View file

@ -83,29 +83,7 @@ namespace juce
JUCE_AUTORELEASEPOOL
{
#if JUCE_64BIT
NSView* parentView = (NSView*) windowRef;
#if JucePlugin_EditorRequiresKeyboardFocus
comp->addToDesktop (0, parentView);
#else
comp->addToDesktop (ComponentPeer::windowIgnoresKeyPresses, parentView);
#endif
// (this workaround is because Wavelab provides a zero-size parent view..)
if ([parentView frame].size.height == 0)
[((NSView*) comp->getWindowHandle()) setFrameOrigin: NSZeroPoint];
comp->setVisible (true);
comp->toFront (false);
[[parentView window] setAcceptsMouseMovedEvents: YES];
return parentView;
#else
//treat NSView like 64bit
if (! isHIView)
{
#if JUCE_64BIT
NSView* parentView = (NSView*) windowRef;
#if JucePlugin_EditorRequiresKeyboardFocus
@ -123,75 +101,96 @@ namespace juce
[[parentView window] setAcceptsMouseMovedEvents: YES];
return parentView;
#else
//treat NSView like 64bit
if (! isHIView)
{
NSView* parentView = (NSView*) windowRef;
#if JucePlugin_EditorRequiresKeyboardFocus
comp->addToDesktop (0, parentView);
#else
comp->addToDesktop (ComponentPeer::windowIgnoresKeyPresses, parentView);
#endif
// (this workaround is because Wavelab provides a zero-size parent view..)
if ([parentView frame].size.height == 0)
[((NSView*) comp->getWindowHandle()) setFrameOrigin: NSZeroPoint];
comp->setVisible (true);
comp->toFront (false);
[[parentView window] setAcceptsMouseMovedEvents: YES];
return parentView;
}
NSWindow* hostWindow = [[NSWindow alloc] initWithWindowRef: windowRef];
[hostWindow retain];
[hostWindow setCanHide: YES];
[hostWindow setReleasedWhenClosed: YES];
HIViewRef parentView = nullptr;
WindowAttributes attributes;
GetWindowAttributes ((WindowRef) windowRef, &attributes);
if ((attributes & kWindowCompositingAttribute) != 0)
{
HIViewRef root = HIViewGetRoot ((WindowRef) windowRef);
HIViewFindByID (root, kHIViewWindowContentID, &parentView);
if (parentView == nullptr)
parentView = root;
}
else
{
GetRootControl ((WindowRef) windowRef, (ControlRef*) &parentView);
if (parentView == nullptr)
CreateRootControl ((WindowRef) windowRef, (ControlRef*) &parentView);
}
// It seems that the only way to successfully position our overlaid window is by putting a dummy
// HIView into the host's carbon window, and then catching events to see when it gets repositioned
HIViewRef dummyView = 0;
HIImageViewCreate (0, &dummyView);
HIRect r = { {0, 0}, { (float) comp->getWidth(), (float) comp->getHeight()} };
HIViewSetFrame (dummyView, &r);
HIViewAddSubview (parentView, dummyView);
comp->getProperties().set ("dummyViewRef", String::toHexString ((pointer_sized_int) (void*) dummyView));
EventHandlerRef ref;
const EventTypeSpec kControlBoundsChangedEvent = { kEventClassControl, kEventControlBoundsChanged };
InstallEventHandler (GetControlEventTarget (dummyView), NewEventHandlerUPP (viewBoundsChangedEvent), 1, &kControlBoundsChangedEvent, (void*) comp, &ref);
comp->getProperties().set ("boundsEventRef", String::toHexString ((pointer_sized_int) (void*) ref));
updateComponentPos (comp);
#if ! JucePlugin_EditorRequiresKeyboardFocus
comp->addToDesktop (ComponentPeer::windowIsTemporary | ComponentPeer::windowIgnoresKeyPresses);
#else
comp->addToDesktop (ComponentPeer::windowIsTemporary);
#endif
comp->setVisible (true);
comp->toFront (false);
NSView* pluginView = (NSView*) comp->getWindowHandle();
NSWindow* pluginWindow = [pluginView window];
[pluginWindow setExcludedFromWindowsMenu: YES];
[pluginWindow setCanHide: YES];
[hostWindow addChildWindow: pluginWindow
ordered: NSWindowAbove];
[hostWindow orderFront: nil];
[pluginWindow orderFront: nil];
attachWindowHidingHooks (comp, (WindowRef) windowRef, hostWindow);
return hostWindow;
#endif
}
NSWindow* hostWindow = [[NSWindow alloc] initWithWindowRef: windowRef];
[hostWindow retain];
[hostWindow setCanHide: YES];
[hostWindow setReleasedWhenClosed: YES];
HIViewRef parentView = nullptr;
WindowAttributes attributes;
GetWindowAttributes ((WindowRef) windowRef, &attributes);
if ((attributes & kWindowCompositingAttribute) != 0)
{
HIViewRef root = HIViewGetRoot ((WindowRef) windowRef);
HIViewFindByID (root, kHIViewWindowContentID, &parentView);
if (parentView == nullptr)
parentView = root;
}
else
{
GetRootControl ((WindowRef) windowRef, (ControlRef*) &parentView);
if (parentView == nullptr)
CreateRootControl ((WindowRef) windowRef, (ControlRef*) &parentView);
}
// It seems that the only way to successfully position our overlaid window is by putting a dummy
// HIView into the host's carbon window, and then catching events to see when it gets repositioned
HIViewRef dummyView = 0;
HIImageViewCreate (0, &dummyView);
HIRect r = { {0, 0}, { (float) comp->getWidth(), (float) comp->getHeight()} };
HIViewSetFrame (dummyView, &r);
HIViewAddSubview (parentView, dummyView);
comp->getProperties().set ("dummyViewRef", String::toHexString ((pointer_sized_int) (void*) dummyView));
EventHandlerRef ref;
const EventTypeSpec kControlBoundsChangedEvent = { kEventClassControl, kEventControlBoundsChanged };
InstallEventHandler (GetControlEventTarget (dummyView), NewEventHandlerUPP (viewBoundsChangedEvent), 1, &kControlBoundsChangedEvent, (void*) comp, &ref);
comp->getProperties().set ("boundsEventRef", String::toHexString ((pointer_sized_int) (void*) ref));
updateComponentPos (comp);
#if ! JucePlugin_EditorRequiresKeyboardFocus
comp->addToDesktop (ComponentPeer::windowIsTemporary | ComponentPeer::windowIgnoresKeyPresses);
#else
comp->addToDesktop (ComponentPeer::windowIsTemporary);
#endif
comp->setVisible (true);
comp->toFront (false);
NSView* pluginView = (NSView*) comp->getWindowHandle();
NSWindow* pluginWindow = [pluginView window];
[pluginWindow setExcludedFromWindowsMenu: YES];
[pluginWindow setCanHide: YES];
[hostWindow addChildWindow: pluginWindow
ordered: NSWindowAbove];
[hostWindow orderFront: nil];
[pluginWindow orderFront: nil];
attachWindowHidingHooks (comp, (WindowRef) windowRef, hostWindow);
return hostWindow;
#endif
}
}
static void detachComponentFromWindowRef (Component* comp, void* nsWindow, bool isHIView)

View file

@ -225,7 +225,9 @@ public:
//==============================================================================
static void toMidiBuffer (MidiBuffer& result, Steinberg::Vst::IEventList& eventList)
{
for (Steinberg::int32 i = 0; i < eventList.getEventCount(); ++i)
const int32 numEvents = eventList.getEventCount();
for (Steinberg::int32 i = 0; i < numEvents; ++i)
{
Steinberg::Vst::Event e;