From 697ca8615a170b021bf06ef636a7fcbc33b44fc7 Mon Sep 17 00:00:00 2001 From: jules Date: Thu, 4 Oct 2007 10:56:58 +0000 Subject: [PATCH] --- .../wrapper/formats/VST/juce_VstWrapper.cpp | 241 +++++++++++++----- .../components/buttons/juce_TextButton.cpp | 19 +- .../lookandfeel/juce_LookAndFeel.cpp | 22 ++ .../components/lookandfeel/juce_LookAndFeel.h | 6 + src/juce_core/containers/juce_PropertySet.cpp | 9 +- 5 files changed, 211 insertions(+), 86 deletions(-) diff --git a/extras/audio plugins/wrapper/formats/VST/juce_VstWrapper.cpp b/extras/audio plugins/wrapper/formats/VST/juce_VstWrapper.cpp index 751c8cb4fe..26658a84a1 100644 --- a/extras/audio plugins/wrapper/formats/VST/juce_VstWrapper.cpp +++ b/extras/audio plugins/wrapper/formats/VST/juce_VstWrapper.cpp @@ -95,7 +95,7 @@ kVstMaxShortLabelLen = 8, kVstMaxCategLabelLen = 24, kVstMaxFileNameLen = 100 - }; + }; #endif //============================================================================== @@ -155,8 +155,8 @@ static HWND findMDIParentOf (HWND w) RECT parentPos; GetWindowRect (parent, &parentPos); - int dw = (parentPos.right - parentPos.left) - (windowPos.right - windowPos.left); - int dh = (parentPos.bottom - parentPos.top) - (windowPos.bottom - windowPos.top); + const int dw = (parentPos.right - parentPos.left) - (windowPos.right - windowPos.left); + const int dh = (parentPos.bottom - parentPos.top) - (windowPos.bottom - windowPos.top); if (dw > 100 || dh > 100) break; @@ -328,6 +328,19 @@ public: filter_->getNumParameters()), filter (filter_) { + editorComp = 0; + outgoingEvents = 0; + outgoingEventSize = 0; + chunkMemoryTime = 0; + isProcessing = false; + firstResize = true; + hasShutdown = false; + channels = 0; + +#if JUCE_MAC || JUCE_LINUX + hostWindow = 0; +#endif + filter->setPlayConfigDetails (JucePlugin_MaxNumInputChannels, JucePlugin_MaxNumOutputChannels, 0, 0); @@ -335,22 +348,10 @@ public: filter_->setPlayHead (this); filter_->addListener (this); - editorComp = 0; - outgoingEvents = 0; - outgoingEventSize = 0; - chunkMemoryTime = 0; - isProcessing = false; - firstResize = true; - channels = 0; - -#if JUCE_MAC || JUCE_LINUX - hostWindow = 0; -#endif - cEffect.flags |= effFlagsHasEditor; + cEffect.version = (long) (JucePlugin_VersionCode); setUniqueID ((int) (JucePlugin_VSTUniqueID)); - getAeffect()->version = (long) (JucePlugin_VersionCode); #if JucePlugin_WantsMidiInput && ! JUCE_USE_VSTSDK_2_4 wantEvents(); @@ -379,6 +380,8 @@ public: stopTimer(); deleteEditor(); + hasShutdown = true; + delete filter; filter = 0; @@ -393,12 +396,13 @@ public: jassert (editorComp == 0); + juce_free (channels); + channels = 0; + deleteTempChannels(); + jassert (activePlugins.contains (this)); activePlugins.removeValue (this); - juce_free (channels); - -#if JUCE_MAC || JUCE_LINUX if (activePlugins.size() == 0) { #if JUCE_LINUX @@ -406,7 +410,6 @@ public: #endif shutdownJuce_GUI(); } -#endif } void open() @@ -474,11 +477,8 @@ public: result = -1; #endif } - else if (strcmp (text, "receiveVstTimeInfo") == 0) - { - result = 1; - } - else if (strcmp (text, "conformsToWindowRules") == 0) + else if (strcmp (text, "receiveVstTimeInfo") == 0 + || strcmp (text, "conformsToWindowRules") == 0) { result = 1; } @@ -493,6 +493,9 @@ public: bool getInputProperties (VstInt32 index, VstPinProperties* properties) { + if (filter == 0 || index >= filter->getNumInputChannels()) + return false; + const String name (filter->getInputChannelName ((int) index)); name.copyToBuffer (properties->label, kVstMaxLabelLen - 1); @@ -510,6 +513,9 @@ public: bool getOutputProperties (VstInt32 index, VstPinProperties* properties) { + if (filter == 0 || index >= filter->getNumOutputChannels()) + return false; + const String name (filter->getOutputChannelName ((int) index)); name.copyToBuffer (properties->label, kVstMaxLabelLen - 1); @@ -569,7 +575,6 @@ public: void processReplacing (float** inputs, float** outputs, VstInt32 numSamples) { - //process (inputs, outputs, numSamples, false); // if this fails, the host hasn't called resume() before processing jassert (isProcessing); @@ -589,12 +594,11 @@ public: const int numIn = filter->getNumInputChannels(); const int numOut = filter->getNumOutputChannels(); - const int totalChans = jmax (numIn, numOut); if (filter->isSuspended()) { for (int i = 0; i < numOut; ++i) - zeromem (outputs [i], sizeof (float) * numSamples); + zeromem (outputs[i], sizeof (float) * numSamples); } else { @@ -602,17 +606,25 @@ public: int i; for (i = 0; i < numOut; ++i) { - channels[i] = outputs [i]; + // if some output channels are disabled, the host may pass the same dummy buffer + // pointer for all of these outputs - and that means that we'd be copying all our + // input channels into the same place... so in this case, we use an internal dummy + // buffer which has enough channels for each input. + float* chan = (float*) tempChannels.getUnchecked(i); + if (chan == 0) + chan = outputs[i]; - if (i < numIn && inputs != outputs) - memcpy (outputs [i], inputs[i], sizeof (float) * numSamples); + if (i < numIn && chan != inputs[i]) + memcpy (chan, inputs[i], sizeof (float) * numSamples); + + channels[i] = chan; } for (; i < numIn; ++i) - channels [i] = inputs [i]; + channels[i] = inputs[i]; } - AudioSampleBuffer chans (channels, totalChans, numSamples); + AudioSampleBuffer chans (channels, jmax (numIn, numOut), numSamples); filter->processBlock (chans, midiEvents); } @@ -669,9 +681,12 @@ public: //============================================================================== void resume() { + if (filter == 0) + return; + isProcessing = true; juce_free (channels); - channels = (float**) juce_calloc (sizeof (float*) * jmax (filter->getNumInputChannels(), filter->getNumOutputChannels())); + channels = (float**) juce_calloc (sizeof (float*) * (filter->getNumInputChannels() + filter->getNumOutputChannels())); double rate = getSampleRate(); jassert (rate > 0); @@ -685,6 +700,14 @@ public: JucePlugin_MaxNumOutputChannels, rate, blockSize); + deleteTempChannels(); + + // any inputs where the output channel is disabled will need our own internal dummy + // buffer, because we can't rely on the host to supply different buffers for each channel + for (int i = 0; i < JucePlugin_MaxNumOutputChannels; ++i) + if (! isOutputConnected (i)) + tempChannels.set (i, juce_malloc (sizeof (float) * blockSize * 2)); + filter->prepareToPlay (rate, blockSize); midiEvents.clear(); @@ -703,6 +726,9 @@ public: void suspend() { + if (filter == 0) + return; + AudioEffectX::suspend(); filter->releaseResources(); @@ -711,6 +737,8 @@ public: isProcessing = false; juce_free (channels); channels = 0; + + deleteTempChannels(); } bool getCurrentPosition (AudioPlayHead::CurrentPositionInfo& info) @@ -756,10 +784,57 @@ public: if ((ti->flags & kVstSmpteValid) != 0) { - info.frameRate = (AudioPlayHead::FrameRateType) (int) ti->smpteFrameRate; + AudioPlayHead::FrameRateType rate = AudioPlayHead::fpsUnknown; + double fps = 1.0; - const double fpsDivisors[] = { 24.0, 25.0, 30.0, 30.0, 30.0, 30.0, 1.0 }; - info.editOriginTime = (ti->smpteOffset / (80.0 * fpsDivisors [(int) info.frameRate])); + switch (info.frameRate) + { + case kVstSmpte24fps: + rate = AudioPlayHead::fps24; + fps = 24.0; + break; + + case kVstSmpte25fps: + rate = AudioPlayHead::fps25; + fps = 25.0; + break; + + case kVstSmpte2997fps: + rate = AudioPlayHead::fps2997; + fps = 29.97; + break; + + case kVstSmpte30fps: + rate = AudioPlayHead::fps30; + fps = 30.0; + break; + + case kVstSmpte2997dfps: + rate = AudioPlayHead::fps2997drop; + fps = 29.97; + break; + + case kVstSmpte30dfps: + rate = AudioPlayHead::fps30drop; + fps = 30.0; + break; + + case kVstSmpteFilm16mm: + case kVstSmpteFilm35mm: + fps = 24.0; + break; + + case kVstSmpte239fps: fps = 23.976; break; + case kVstSmpte249fps: fps = 24.976; break; + case kVstSmpte599fps: fps = 59.94; break; + case kVstSmpte60fps: fps = 60; break; + + default: + jassertfalse // unknown frame-rate.. + } + + info.frameRate = rate; + info.editOriginTime = ti->smpteOffset / (80.0 * fps); } else { @@ -776,27 +851,30 @@ public: //============================================================================== VstInt32 getProgram() { - return filter->getCurrentProgram(); + return filter != 0 ? filter->getCurrentProgram() : 0; } void setProgram (VstInt32 program) { - filter->setCurrentProgram (program); + if (filter != 0) + filter->setCurrentProgram (program); } void setProgramName (char* name) { - filter->changeProgramName (filter->getCurrentProgram(), name); + if (filter != 0) + filter->changeProgramName (filter->getCurrentProgram(), name); } void getProgramName (char* name) { - filter->getProgramName (filter->getCurrentProgram()).copyToBuffer (name, 24); + if (filter != 0) + filter->getProgramName (filter->getCurrentProgram()).copyToBuffer (name, 24); } bool getProgramNameIndexed (VstInt32 category, VstInt32 index, char* text) { - if (index >= 0 && index < filter->getNumPrograms()) + if (index >= 0 && filter != 0 && index < filter->getNumPrograms()) { filter->getProgramName (index).copyToBuffer (text, 24); return true; @@ -808,26 +886,38 @@ public: //============================================================================== float getParameter (VstInt32 index) { + if (filter == 0) + return 0.0f; + jassert (index >= 0 && index < filter->getNumParameters()); return filter->getParameter (index); } void setParameter (VstInt32 index, float value) { - jassert (index >= 0 && index < filter->getNumParameters()); - filter->setParameter (index, value); + if (filter != 0) + { + jassert (index >= 0 && index < filter->getNumParameters()); + filter->setParameter (index, value); + } } void getParameterDisplay (VstInt32 index, char* text) { - jassert (index >= 0 && index < filter->getNumParameters()); - filter->getParameterText (index).copyToBuffer (text, 24); // length should technically be kVstMaxParamStrLen, which is 8, but hosts will normally allow a bit more. + if (filter != 0) + { + jassert (index >= 0 && index < filter->getNumParameters()); + filter->getParameterText (index).copyToBuffer (text, 24); // length should technically be kVstMaxParamStrLen, which is 8, but hosts will normally allow a bit more. + } } void getParameterName (VstInt32 index, char* text) { - jassert (index >= 0 && index < filter->getNumParameters()); - filter->getParameterName (index).copyToBuffer (text, 16); // length should technically be kVstMaxParamStrLen, which is 8, but hosts will normally allow a bit more. + if (filter != 0) + { + jassert (index >= 0 && index < filter->getNumParameters()); + filter->getParameterName (index).copyToBuffer (text, 16); // length should technically be kVstMaxParamStrLen, which is 8, but hosts will normally allow a bit more. + } } void audioProcessorParameterChanged (AudioProcessor*, int index, float newValue) @@ -852,12 +942,15 @@ public: bool canParameterBeAutomated (VstInt32 index) { - return filter->isParameterAutomatable ((int) index); + return filter != 0 && filter->isParameterAutomatable ((int) index); } //============================================================================== VstInt32 getChunk (void** data, bool onlyStoreCurrentProgramData) { + if (filter == 0) + return 0; + chunkMemory.setSize (0); if (onlyStoreCurrentProgramData) filter->getCurrentProgramStateInformation (chunkMemory); @@ -875,6 +968,9 @@ public: VstInt32 setChunk (void* data, VstInt32 byteSize, bool onlyRestoreCurrentProgramData) { + if (filter == 0) + return 0; + chunkMemory.setSize (0); chunkMemoryTime = 0; @@ -923,26 +1019,27 @@ public: void doIdleCallback() { // (wavelab calls this on a separate thread and causes a deadlock).. - if (MessageManager::getInstance()->isThisTheMessageThread()) + if (MessageManager::getInstance()->isThisTheMessageThread() + && ! recursionCheck) { - if (! recursionCheck) - { - const MessageManagerLock mml; + const MessageManagerLock mml; - recursionCheck = true; + recursionCheck = true; - juce_callAnyTimersSynchronously(); + juce_callAnyTimersSynchronously(); - for (int i = ComponentPeer::getNumPeers(); --i >= 0;) - ComponentPeer::getPeer (i)->performAnyPendingRepaintsNow(); + for (int i = ComponentPeer::getNumPeers(); --i >= 0;) + ComponentPeer::getPeer (i)->performAnyPendingRepaintsNow(); - recursionCheck = false; - } + recursionCheck = false; } } void createEditorComp() { + if (hasShutdown || filter == 0) + return; + if (editorComp == 0) { #if JUCE_LINUX @@ -996,6 +1093,9 @@ public: VstIntPtr dispatcher (VstInt32 opCode, VstInt32 index, VstIntPtr value, void* ptr, float opt) { + if (hasShutdown) + return 0; + if (opCode == effEditIdle) { doIdleCallback(); @@ -1218,8 +1318,22 @@ private: int outgoingEventSize; bool isProcessing; bool firstResize; + bool hasShutdown; int diffW, diffH; float** channels; + VoidArray tempChannels; // see note in processReplacing() + + void deleteTempChannels() + { + int i; + for (i = tempChannels.size(); --i >= 0;) + juce_free (tempChannels.getUnchecked(i)); + + tempChannels.clear(); + + if (filter != 0) + tempChannels.insertMultiple (0, 0, filter->getNumInputChannels() + filter->getNumOutputChannels()); + } void ensureOutgoingEventSize (int numEvents) { @@ -1294,9 +1408,7 @@ extern AudioProcessor* JUCE_CALLTYPE createPluginFilter(); //============================================================================== static AEffect* pluginEntryPoint (audioMasterCallback audioMaster) { -#if JUCE_MAC || JUCE_LINUX initialiseJuce_GUI(); -#endif MessageManager::getInstance()->setTimeBeforeShowingWaitCursor (0); @@ -1375,14 +1487,7 @@ extern "C" __declspec (dllexport) void* main (audioMasterCallback audioMaster) BOOL WINAPI DllMain (HINSTANCE instance, DWORD dwReason, LPVOID) { if (dwReason == DLL_PROCESS_ATTACH) - { PlatformUtilities::setCurrentModuleInstanceHandle (instance); - initialiseJuce_GUI(); - } - else if (dwReason == DLL_PROCESS_DETACH) - { - shutdownJuce_GUI(); - } return TRUE; } diff --git a/src/juce_appframework/gui/components/buttons/juce_TextButton.cpp b/src/juce_appframework/gui/components/buttons/juce_TextButton.cpp index 33f36fc031..f4ed54a4d1 100644 --- a/src/juce_appframework/gui/components/buttons/juce_TextButton.cpp +++ b/src/juce_appframework/gui/components/buttons/juce_TextButton.cpp @@ -59,22 +59,9 @@ void TextButton::paintButton (Graphics& g, isMouseOverButton, isButtonDown); - const int yIndent = jmin (4, proportionOfHeight (0.3f)); - const int cornerSize = jmin (getHeight(), getWidth()) / 2; - - g.setFont (getFont()); - g.setColour (findColour (textColourId).withMultipliedAlpha (isEnabled() ? 1.0f : 0.5f)); - - const int fontHeight = roundFloatToInt (g.getCurrentFont().getHeight() * 0.6f); - const int leftIndent = jmin (fontHeight, 2 + cornerSize / (isConnectedOnLeft() ? 4 : 2)); - const int rightIndent = jmin (fontHeight, 2 + cornerSize / (isConnectedOnRight() ? 4 : 2)); - - g.drawFittedText (getButtonText(), - leftIndent, - yIndent, - getWidth() - leftIndent - rightIndent, - getHeight() - yIndent * 2, - Justification::centred, 2); + getLookAndFeel().drawButtonText (g, *this, + isMouseOverButton, + isButtonDown); } void TextButton::colourChanged() diff --git a/src/juce_appframework/gui/components/lookandfeel/juce_LookAndFeel.cpp b/src/juce_appframework/gui/components/lookandfeel/juce_LookAndFeel.cpp index ffe428539c..d4b8c425e7 100644 --- a/src/juce_appframework/gui/components/lookandfeel/juce_LookAndFeel.cpp +++ b/src/juce_appframework/gui/components/lookandfeel/juce_LookAndFeel.cpp @@ -308,6 +308,28 @@ void LookAndFeel::drawButtonBackground (Graphics& g, button.isConnectedOnBottom()); } +void LookAndFeel::drawButtonText (Graphics& g, TextButton& button, + bool /*isMouseOverButton*/, bool /*isButtonDown*/) +{ + g.setFont (button.getFont()); + g.setColour (button.findColour (TextButton::textColourId) + .withMultipliedAlpha (button.isEnabled() ? 1.0f : 0.5f)); + + const int yIndent = jmin (4, button.proportionOfHeight (0.3f)); + const int cornerSize = jmin (button.getHeight(), button.getWidth()) / 2; + + const int fontHeight = roundFloatToInt (g.getCurrentFont().getHeight() * 0.6f); + const int leftIndent = jmin (fontHeight, 2 + cornerSize / (button.isConnectedOnLeft() ? 4 : 2)); + const int rightIndent = jmin (fontHeight, 2 + cornerSize / (button.isConnectedOnRight() ? 4 : 2)); + + g.drawFittedText (button.getButtonText(), + leftIndent, + yIndent, + button.getWidth() - leftIndent - rightIndent, + button.getHeight() - yIndent * 2, + Justification::centred, 2); +} + void LookAndFeel::drawTickBox (Graphics& g, Component& component, int x, int y, int w, int h, diff --git a/src/juce_appframework/gui/components/lookandfeel/juce_LookAndFeel.h b/src/juce_appframework/gui/components/lookandfeel/juce_LookAndFeel.h index 5b38cd4588..519093ea55 100644 --- a/src/juce_appframework/gui/components/lookandfeel/juce_LookAndFeel.h +++ b/src/juce_appframework/gui/components/lookandfeel/juce_LookAndFeel.h @@ -38,6 +38,7 @@ #include "../layout/juce_TabbedComponent.h" class ToggleButton; +class TextButton; class AlertWindow; class TextLayout; class ScrollBar; @@ -130,6 +131,11 @@ public: bool isMouseOverButton, bool isButtonDown); + /** Draws the text for a TextButton. */ + virtual void drawButtonText (Graphics& g, + TextButton& button, + bool isMouseOverButton, + bool isButtonDown); /** Draws the contents of a standard ToggleButton. */ virtual void drawToggleButton (Graphics& g, diff --git a/src/juce_core/containers/juce_PropertySet.cpp b/src/juce_core/containers/juce_PropertySet.cpp index 248e604129..7094f01fde 100644 --- a/src/juce_core/containers/juce_PropertySet.cpp +++ b/src/juce_core/containers/juce_PropertySet.cpp @@ -137,8 +137,13 @@ void PropertySet::setValue (const String& keyName, { const ScopedLock sl (lock); - properties.set (keyName, value); - propertyChanged(); + const int index = properties.getAllKeys().indexOf (keyName, ignoreCaseOfKeys); + + if (index < 0 || properties.getAllValues() [index] != value) + { + properties.set (keyName, value); + propertyChanged(); + } } }