| @@ -74,6 +74,11 @@ public: | |||||
| ~PluginWindow() | ~PluginWindow() | ||||
| { | { | ||||
| if (owner.activeGenericUI == this) | |||||
| owner.activeGenericUI = 0; | |||||
| else | |||||
| owner.activeUI = 0; | |||||
| setContentComponent (0); | setContentComponent (0); | ||||
| } | } | ||||
| @@ -85,7 +90,6 @@ public: | |||||
| void closeButtonPressed() | void closeButtonPressed() | ||||
| { | { | ||||
| owner.activeUI = 0; | |||||
| delete this; | delete this; | ||||
| } | } | ||||
| @@ -100,7 +104,8 @@ FilterInGraph::FilterInGraph (FilterGraph& owner_, AudioPluginInstance* const fi | |||||
| filter (filter_), | filter (filter_), | ||||
| uid (0), | uid (0), | ||||
| processedAudio (1, 1), | processedAudio (1, 1), | ||||
| activeUI (0) | |||||
| activeUI (0), | |||||
| activeGenericUI (0) | |||||
| { | { | ||||
| lastX = 100 + Random::getSystemRandom().nextInt (400); | lastX = 100 + Random::getSystemRandom().nextInt (400); | ||||
| lastY = 100 + Random::getSystemRandom().nextInt (400); | lastY = 100 + Random::getSystemRandom().nextInt (400); | ||||
| @@ -108,6 +113,7 @@ FilterInGraph::FilterInGraph (FilterGraph& owner_, AudioPluginInstance* const fi | |||||
| FilterInGraph::~FilterInGraph() | FilterInGraph::~FilterInGraph() | ||||
| { | { | ||||
| delete activeGenericUI; | |||||
| delete activeUI; | delete activeUI; | ||||
| delete filter; | delete filter; | ||||
| } | } | ||||
| @@ -118,21 +124,37 @@ void FilterInGraph::setPosition (double newX, double newY) throw() | |||||
| y = jlimit (0.0, 1.0, newY); | y = jlimit (0.0, 1.0, newY); | ||||
| } | } | ||||
| void FilterInGraph::showUI() | |||||
| void FilterInGraph::showUI (bool useGenericUI) | |||||
| { | { | ||||
| if (activeUI == 0) | |||||
| if (! useGenericUI) | |||||
| { | { | ||||
| Component* ui = filter->createEditorIfNeeded(); | |||||
| if (activeUI == 0) | |||||
| { | |||||
| Component* ui = filter->createEditorIfNeeded(); | |||||
| if (ui == 0) | |||||
| ui = new GenericAudioFilterEditor (filter); | |||||
| if (ui == 0) | |||||
| return showUI (true); | |||||
| ui->setName (filter->getName()); | |||||
| activeUI = new PluginWindow (ui, *this); | |||||
| ui->setName (filter->getName()); | |||||
| activeUI = new PluginWindow (ui, *this); | |||||
| } | |||||
| if (activeUI != 0) | |||||
| activeUI->toFront (true); | |||||
| } | } | ||||
| else | |||||
| { | |||||
| if (activeGenericUI == 0) | |||||
| { | |||||
| Component* ui = new GenericAudioFilterEditor (filter); | |||||
| ui->setName (filter->getName()); | |||||
| activeGenericUI = new PluginWindow (ui, *this); | |||||
| } | |||||
| if (activeUI != 0) | |||||
| activeUI->toFront (true); | |||||
| if (activeGenericUI != 0) | |||||
| activeGenericUI->toFront (true); | |||||
| } | |||||
| } | } | ||||
| void FilterInGraph::prepareBuffers (int blockSize) | void FilterInGraph::prepareBuffers (int blockSize) | ||||
| @@ -87,7 +87,7 @@ public: | |||||
| uint32 uid; | uint32 uid; | ||||
| //============================================================================== | //============================================================================== | ||||
| void showUI(); | |||||
| void showUI (bool useGenericUI); | |||||
| double getX() const throw() { return x; } | double getX() const throw() { return x; } | ||||
| double getY() const throw() { return y; } | double getY() const throw() { return y; } | ||||
| @@ -111,6 +111,7 @@ private: | |||||
| friend class PluginWindow; | friend class PluginWindow; | ||||
| Component* activeUI; | Component* activeUI; | ||||
| Component* activeGenericUI; | |||||
| int lastX, lastY; | int lastX, lastY; | ||||
| MidiBuffer outputMidi; | MidiBuffer outputMidi; | ||||
| @@ -145,6 +145,9 @@ public: | |||||
| PopupMenu m; | PopupMenu m; | ||||
| m.addItem (1, "Delete this filter"); | m.addItem (1, "Delete this filter"); | ||||
| m.addItem (2, "Disconnect all pins"); | m.addItem (2, "Disconnect all pins"); | ||||
| m.addSeparator(); | |||||
| m.addItem (3, "Show plugin UI"); | |||||
| m.addItem (4, "Show all parameters"); | |||||
| const int r = m.show(); | const int r = m.show(); | ||||
| @@ -157,6 +160,13 @@ public: | |||||
| { | { | ||||
| graph.disconnectFilter (filterID); | graph.disconnectFilter (filterID); | ||||
| } | } | ||||
| else if (r == 3 || r == 4) | |||||
| { | |||||
| const FilterInGraph::Ptr f (graph.getFilterForUID (filterID)); | |||||
| if (f != 0) | |||||
| f->showUI (r == 4); | |||||
| } | |||||
| } | } | ||||
| } | } | ||||
| @@ -189,7 +199,7 @@ public: | |||||
| const FilterInGraph::Ptr f (graph.getFilterForUID (filterID)); | const FilterInGraph::Ptr f (graph.getFilterForUID (filterID)); | ||||
| if (f != 0) | if (f != 0) | ||||
| f->showUI(); | |||||
| f->showUI (false); | |||||
| } | } | ||||
| else if (! e.mouseWasClicked()) | else if (! e.mouseWasClicked()) | ||||
| { | { | ||||
| @@ -127,6 +127,8 @@ MainHostWindow::MainHostWindow() | |||||
| knownPluginList.addChangeListener (this); | knownPluginList.addChangeListener (this); | ||||
| addKeyListener (commandManager->getKeyMappings()); | addKeyListener (commandManager->getKeyMappings()); | ||||
| Process::setPriority (Process::HighPriority); | |||||
| } | } | ||||
| MainHostWindow::~MainHostWindow() | MainHostWindow::~MainHostWindow() | ||||
| @@ -36,10 +36,56 @@ | |||||
| #include "../../../audio plugins/wrapper/juce_AudioFilterBase.cpp" | #include "../../../audio plugins/wrapper/juce_AudioFilterBase.cpp" | ||||
| #include "../../../audio plugins/wrapper/juce_AudioFilterEditor.cpp" | #include "../../../audio plugins/wrapper/juce_AudioFilterEditor.cpp" | ||||
| #include "juce_AudioPluginInstance.h" | |||||
| //============================================================================== | //============================================================================== | ||||
| #include "juce_AudioPluginInstance.h" | |||||
| AudioPluginInstance::AudioPluginInstance() | |||||
| { | |||||
| internalAsyncUpdater = new InternalAsyncUpdater (*this); | |||||
| initialiseInternal (this); | |||||
| } | |||||
| AudioPluginInstance::~AudioPluginInstance() | |||||
| { | |||||
| delete internalAsyncUpdater; | |||||
| } | |||||
| void AudioPluginInstance::addListener (AudioPluginParameterListener* const newListener) throw() | |||||
| { | |||||
| listeners.addIfNotAlreadyThere (newListener); | |||||
| } | |||||
| void AudioPluginInstance::removeListener (AudioPluginParameterListener* const listenerToRemove) throw() | |||||
| { | |||||
| listeners.removeValue (listenerToRemove); | |||||
| } | |||||
| void AudioPluginInstance::internalAsyncCallback() | |||||
| { | |||||
| changedParamLock.enter(); | |||||
| Array <int> changed; | |||||
| changed.swapWithArray (changedParams); | |||||
| changedParamLock.exit(); | |||||
| for (int j = 0; j < changed.size(); ++j) | |||||
| { | |||||
| const int paramIndex = changed.getUnchecked (j); | |||||
| for (int i = listeners.size(); --i >= 0;) | |||||
| { | |||||
| AudioPluginParameterListener* const l = (AudioPluginParameterListener*) listeners.getUnchecked(i); | |||||
| if (paramIndex >= 0) | |||||
| l->audioPluginParameterChanged (this, paramIndex); | |||||
| else | |||||
| l->audioPluginChanged (this); | |||||
| i = jmin (i, listeners.size()); | |||||
| } | |||||
| } | |||||
| } | |||||
| //============================================================================== | //============================================================================== | ||||
| bool JUCE_CALLTYPE AudioPluginInstance::getCurrentPositionInfo (AudioFilterBase::CurrentPositionInfo& info) | bool JUCE_CALLTYPE AudioPluginInstance::getCurrentPositionInfo (AudioFilterBase::CurrentPositionInfo& info) | ||||
| @@ -76,7 +122,34 @@ bool JUCE_CALLTYPE AudioPluginInstance::getCurrentPositionInfo (AudioFilterBase: | |||||
| return true; | return true; | ||||
| } | } | ||||
| void JUCE_CALLTYPE AudioPluginInstance::informHostOfParameterChange (int /*index*/, float /*newValue*/) | |||||
| void JUCE_CALLTYPE AudioPluginInstance::informHostOfParameterChange (int index, float /*newValue*/) | |||||
| { | |||||
| queueChangeMessage (index); | |||||
| } | |||||
| void JUCE_CALLTYPE AudioPluginInstance::updateHostDisplay() | |||||
| { | { | ||||
| queueChangeMessage (-1); | |||||
| } | |||||
| void AudioPluginInstance::queueChangeMessage (const int index) throw() | |||||
| { | |||||
| const ScopedLock sl (changedParamLock); | |||||
| changedParams.addIfNotAlreadyThere (index); | |||||
| if (! internalAsyncUpdater->isTimerRunning()) | |||||
| internalAsyncUpdater->startTimer (1); | |||||
| } | } | ||||
| //============================================================================== | |||||
| AudioPluginInstance::InternalAsyncUpdater::InternalAsyncUpdater (AudioPluginInstance& owner_) | |||||
| : owner (owner_) | |||||
| { | |||||
| } | |||||
| void AudioPluginInstance::InternalAsyncUpdater::timerCallback() | |||||
| { | |||||
| stopTimer(); | |||||
| owner.internalAsyncCallback(); | |||||
| } | |||||
| @@ -33,6 +33,27 @@ | |||||
| #define __JUCE_AUDIOPLUGININSTANCE_JUCEHEADER__ | #define __JUCE_AUDIOPLUGININSTANCE_JUCEHEADER__ | ||||
| #include "../../../audio plugins/wrapper/juce_AudioFilterBase.h" | #include "../../../audio plugins/wrapper/juce_AudioFilterBase.h" | ||||
| class AudioPluginInstance; | |||||
| //============================================================================== | |||||
| class AudioPluginParameterListener | |||||
| { | |||||
| public: | |||||
| //============================================================================== | |||||
| /** Destructor. */ | |||||
| virtual ~AudioPluginParameterListener() {} | |||||
| //============================================================================== | |||||
| /** Receives a callback when a parameter is changed. */ | |||||
| virtual void audioPluginParameterChanged (AudioPluginInstance* plugin, | |||||
| int parameterIndex) = 0; | |||||
| /** Called to indicate that something else in the plugin has changed, like its | |||||
| program, number of parameters, etc. | |||||
| */ | |||||
| virtual void audioPluginChanged (AudioPluginInstance* plugin) = 0; | |||||
| }; | |||||
| //============================================================================== | //============================================================================== | ||||
| @@ -55,7 +76,7 @@ public: | |||||
| Make sure that you delete any UI components that belong to this plugin before | Make sure that you delete any UI components that belong to this plugin before | ||||
| deleting the plugin. | deleting the plugin. | ||||
| */ | */ | ||||
| virtual ~AudioPluginInstance() {} | |||||
| virtual ~AudioPluginInstance(); | |||||
| //============================================================================== | //============================================================================== | ||||
| /** Returns the plugin's name. */ | /** Returns the plugin's name. */ | ||||
| @@ -109,14 +130,45 @@ public: | |||||
| */ | */ | ||||
| virtual int getSamplesLatency() const = 0; | virtual int getSamplesLatency() const = 0; | ||||
| //============================================================================== | |||||
| /** Adds a listener that will be called when one of this plugin's parameters changes. */ | |||||
| void addListener (AudioPluginParameterListener* const newListener) throw(); | |||||
| /** Removes a previously added listener. */ | |||||
| void removeListener (AudioPluginParameterListener* const listenerToRemove) throw(); | |||||
| //============================================================================== | //============================================================================== | ||||
| juce_UseDebuggingNewOperator | juce_UseDebuggingNewOperator | ||||
| protected: | protected: | ||||
| AudioPluginInstance() {} | |||||
| VoidArray listeners; | |||||
| CriticalSection changedParamLock; | |||||
| Array <int> changedParams; | |||||
| class InternalAsyncUpdater : public Timer | |||||
| { | |||||
| public: | |||||
| InternalAsyncUpdater (AudioPluginInstance& owner); | |||||
| ~InternalAsyncUpdater() {} | |||||
| void timerCallback(); | |||||
| juce_UseDebuggingNewOperator | |||||
| private: | |||||
| AudioPluginInstance& owner; | |||||
| }; | |||||
| InternalAsyncUpdater* internalAsyncUpdater; | |||||
| void internalAsyncCallback(); | |||||
| void queueChangeMessage (const int index) throw(); | |||||
| AudioPluginInstance(); | |||||
| bool JUCE_CALLTYPE getCurrentPositionInfo (AudioFilterBase::CurrentPositionInfo& info); | bool JUCE_CALLTYPE getCurrentPositionInfo (AudioFilterBase::CurrentPositionInfo& info); | ||||
| void JUCE_CALLTYPE informHostOfParameterChange (int index, float newValue); | void JUCE_CALLTYPE informHostOfParameterChange (int index, float newValue); | ||||
| void JUCE_CALLTYPE updateHostDisplay(); | |||||
| }; | }; | ||||
| @@ -34,20 +34,24 @@ | |||||
| //============================================================================== | //============================================================================== | ||||
| class FilterParameterPropertyComp : public PropertyComponent | |||||
| class FilterParameterPropertyComp : public PropertyComponent, | |||||
| public AudioPluginParameterListener | |||||
| { | { | ||||
| public: | public: | ||||
| FilterParameterPropertyComp (AudioPluginInstance* const filter_, | |||||
| FilterParameterPropertyComp (const String& name, | |||||
| AudioPluginInstance* const filter_, | |||||
| const int index_) | const int index_) | ||||
| : PropertyComponent (filter_->getParameterName (index_)), | |||||
| : PropertyComponent (name), | |||||
| filter (filter_), | filter (filter_), | ||||
| index (index_) | index (index_) | ||||
| { | { | ||||
| addAndMakeVisible (slider = new PluginSlider (filter_, index_)); | addAndMakeVisible (slider = new PluginSlider (filter_, index_)); | ||||
| filter->addListener (this); | |||||
| } | } | ||||
| ~FilterParameterPropertyComp() | ~FilterParameterPropertyComp() | ||||
| { | { | ||||
| filter->removeListener (this); | |||||
| deleteAllChildren(); | deleteAllChildren(); | ||||
| } | } | ||||
| @@ -56,6 +60,16 @@ public: | |||||
| slider->setValue (filter->getParameter (index), false); | slider->setValue (filter->getParameter (index), false); | ||||
| } | } | ||||
| void audioPluginChanged (AudioPluginInstance*) | |||||
| { | |||||
| } | |||||
| void audioPluginParameterChanged (AudioPluginInstance*, int parameterIndex) | |||||
| { | |||||
| if (parameterIndex == index) | |||||
| refresh(); | |||||
| } | |||||
| //============================================================================== | //============================================================================== | ||||
| juce_UseDebuggingNewOperator | juce_UseDebuggingNewOperator | ||||
| @@ -76,6 +90,7 @@ private: | |||||
| setRange (0.0, 1.0, 0.0); | setRange (0.0, 1.0, 0.0); | ||||
| setSliderStyle (Slider::LinearBar); | setSliderStyle (Slider::LinearBar); | ||||
| setTextBoxIsEditable (false); | setTextBoxIsEditable (false); | ||||
| setScrollWheelEnabled (false); | |||||
| } | } | ||||
| ~PluginSlider() | ~PluginSlider() | ||||
| @@ -120,7 +135,11 @@ GenericAudioFilterEditor::GenericAudioFilterEditor (AudioPluginInstance* const f | |||||
| for (int i = 0; i < numParams; ++i) | for (int i = 0; i < numParams; ++i) | ||||
| { | { | ||||
| FilterParameterPropertyComp* const pc = new FilterParameterPropertyComp (filter, i); | |||||
| String name (filter->getParameterName (i)); | |||||
| if (name.trim().isEmpty()) | |||||
| name = "Unnamed"; | |||||
| FilterParameterPropertyComp* const pc = new FilterParameterPropertyComp (name, filter, i); | |||||
| params.add (pc); | params.add (pc); | ||||
| totalHeight += pc->getPreferredHeight(); | totalHeight += pc->getPreferredHeight(); | ||||
| } | } | ||||
| @@ -48,6 +48,10 @@ | |||||
| #define _clearfp() | #define _clearfp() | ||||
| #endif | #endif | ||||
| BEGIN_JUCE_NAMESPACE | |||||
| extern void juce_callAnyTimersSynchronously(); | |||||
| END_JUCE_NAMESPACE | |||||
| //============================================================================== | //============================================================================== | ||||
| const int fxbVersionNum = 1; | const int fxbVersionNum = 1; | ||||
| @@ -288,15 +292,17 @@ public: | |||||
| void close() | void close() | ||||
| { | { | ||||
| _fpreset(); // (doesn't do any harm) | |||||
| if (hModule != 0) | if (hModule != 0) | ||||
| { | { | ||||
| try | |||||
| __try | |||||
| { | { | ||||
| _fpreset(); // (doesn't do any harm) | |||||
| FreeLibrary (hModule); | FreeLibrary (hModule); | ||||
| } | } | ||||
| catch (...) | |||||
| {} | |||||
| __finally | |||||
| { | |||||
| } | |||||
| } | } | ||||
| } | } | ||||
| @@ -612,6 +618,7 @@ VSTPluginInstance::~VSTPluginInstance() | |||||
| {} | {} | ||||
| } | } | ||||
| module = 0; | |||||
| effect = 0; | effect = 0; | ||||
| } | } | ||||
| @@ -1409,7 +1416,9 @@ AudioFilterEditor* JUCE_CALLTYPE VSTPluginInstance::createEditor() | |||||
| //============================================================================== | //============================================================================== | ||||
| void VSTPluginInstance::handleAsyncUpdate() | void VSTPluginInstance::handleAsyncUpdate() | ||||
| { | { | ||||
| // called asynchronously to indicate that the plugin's parameters have changed.. | |||||
| // indicates that something about the plugin has changed.. | |||||
| if (callbacks != 0) | |||||
| callbacks->updateHostDisplay(); | |||||
| } | } | ||||
| //============================================================================== | //============================================================================== | ||||
| @@ -1786,7 +1795,8 @@ VstIntPtr VSTPluginInstance::handleCallback (VstInt32 opcode, VstInt32 index, Vs | |||||
| switch (opcode) | switch (opcode) | ||||
| { | { | ||||
| case audioMasterAutomate: | case audioMasterAutomate: | ||||
| // index = param num, opt = value | |||||
| if (callbacks != 0) | |||||
| callbacks->informHostOfParameterChange (index, opt); | |||||
| break; | break; | ||||
| case audioMasterProcessEvents: | case audioMasterProcessEvents: | ||||
| @@ -1807,14 +1817,24 @@ VstIntPtr VSTPluginInstance::handleCallback (VstInt32 opcode, VstInt32 index, Vs | |||||
| break; | break; | ||||
| case audioMasterIdle: | case audioMasterIdle: | ||||
| Thread::sleep (1); | |||||
| if (! isTimerRunning()) | |||||
| startTimer (50); | |||||
| if (insideVSTCallback == 0 && MessageManager::getInstance()->isThisTheMessageThread()) | |||||
| { | |||||
| ++insideVSTCallback; | |||||
| #if JUCE_MAC | #if JUCE_MAC | ||||
| if (getActiveEditor() != 0) | |||||
| dispatch (effEditIdle, 0, 0, 0, 0); | |||||
| if (getActiveEditor() != 0) | |||||
| dispatch (effEditIdle, 0, 0, 0, 0); | |||||
| #endif | #endif | ||||
| const MessageManagerLock mml; | |||||
| juce_callAnyTimersSynchronously(); | |||||
| handleUpdateNowIfNeeded(); | |||||
| for (int i = ComponentPeer::getNumPeers(); --i >= 0;) | |||||
| ComponentPeer::getPeer (i)->performAnyPendingRepaintsNow(); | |||||
| --insideVSTCallback; | |||||
| } | |||||
| break; | break; | ||||
| case audioMasterUpdateDisplay: | case audioMasterUpdateDisplay: | ||||
| @@ -845,6 +845,11 @@ protected: | |||||
| SetControlValue (index + 2, floatToLong (newValue)); | SetControlValue (index + 2, floatToLong (newValue)); | ||||
| } | } | ||||
| void JUCE_CALLTYPE updateHostDisplay() | |||||
| { | |||||
| // xxx is there an RTAS equivalent? | |||||
| } | |||||
| //============================================================================== | //============================================================================== | ||||
| private: | private: | ||||
| AudioFilterBase* juceFilter; | AudioFilterBase* juceFilter; | ||||
| @@ -144,6 +144,10 @@ void AudioFilterStreamer::informHostOfParameterChange (int index, float newValue | |||||
| } | } | ||||
| void JUCE_CALLTYPE AudioFilterStreamer::updateHostDisplay() | |||||
| { | |||||
| } | |||||
| //============================================================================== | //============================================================================== | ||||
| AudioFilterStreamingDeviceManager::AudioFilterStreamingDeviceManager() | AudioFilterStreamingDeviceManager::AudioFilterStreamingDeviceManager() | ||||
| @@ -73,6 +73,7 @@ public: | |||||
| bool JUCE_CALLTYPE getCurrentPositionInfo (AudioFilterBase::CurrentPositionInfo& info); | bool JUCE_CALLTYPE getCurrentPositionInfo (AudioFilterBase::CurrentPositionInfo& info); | ||||
| void JUCE_CALLTYPE informHostOfParameterChange (int index, float newValue); | void JUCE_CALLTYPE informHostOfParameterChange (int index, float newValue); | ||||
| void JUCE_CALLTYPE updateHostDisplay(); | |||||
| juce_UseDebuggingNewOperator | juce_UseDebuggingNewOperator | ||||
| @@ -101,9 +101,7 @@ static uint32 lastMasterIdleCall = 0; | |||||
| BEGIN_JUCE_NAMESPACE | BEGIN_JUCE_NAMESPACE | ||||
| extern void juce_callAnyTimersSynchronously(); | extern void juce_callAnyTimersSynchronously(); | ||||
| #if JUCE_MAC | |||||
| extern void juce_macDoPendingRepaintsNow(); | |||||
| #elif JUCE_LINUX | |||||
| #if JUCE_LINUX | |||||
| extern Display* display; | extern Display* display; | ||||
| extern bool juce_postMessageToSystemQueue (void* message); | extern bool juce_postMessageToSystemQueue (void* message); | ||||
| #endif | #endif | ||||
| @@ -809,6 +807,11 @@ public: | |||||
| setParameterAutomated (index, newValue); | setParameterAutomated (index, newValue); | ||||
| } | } | ||||
| void JUCE_CALLTYPE updateHostDisplay() | |||||
| { | |||||
| updateDisplay(); | |||||
| } | |||||
| bool canParameterBeAutomated (VstInt32 index) | bool canParameterBeAutomated (VstInt32 index) | ||||
| { | { | ||||
| return filter->isParameterAutomatable ((int) index); | return filter->isParameterAutomatable ((int) index); | ||||
| @@ -38,8 +38,8 @@ AudioFilterBase::AudioFilterBase() | |||||
| blockSize (0), | blockSize (0), | ||||
| numInputChannels (0), | numInputChannels (0), | ||||
| numOutputChannels (0), | numOutputChannels (0), | ||||
| suspended (false), | |||||
| callbacks (0), | callbacks (0), | ||||
| suspended (false), | |||||
| activeEditor (0) | activeEditor (0) | ||||
| { | { | ||||
| } | } | ||||
| @@ -67,6 +67,12 @@ void AudioFilterBase::setParameterNotifyingHost (const int parameterIndex, | |||||
| setParameter (parameterIndex, newValue); | setParameter (parameterIndex, newValue); | ||||
| } | } | ||||
| void JUCE_CALLTYPE AudioFilterBase::updateHostDisplay() | |||||
| { | |||||
| if (callbacks != 0) | |||||
| callbacks->updateHostDisplay(); | |||||
| } | |||||
| bool AudioFilterBase::isParameterAutomatable (int /*index*/) const | bool AudioFilterBase::isParameterAutomatable (int /*index*/) const | ||||
| { | { | ||||
| return true; | return true; | ||||
| @@ -407,6 +407,13 @@ public: | |||||
| */ | */ | ||||
| virtual bool isParameterAutomatable (int index) const; | virtual bool isParameterAutomatable (int index) const; | ||||
| /** The filter can call this when something (apart from a parameter value) has changed. | |||||
| It sends a hint to the host that something like the program, number of parameters, | |||||
| etc, has changed, and that it should update itself. | |||||
| */ | |||||
| void JUCE_CALLTYPE updateHostDisplay(); | |||||
| //============================================================================== | //============================================================================== | ||||
| /** Returns the number of preset programs the filter supports. | /** Returns the number of preset programs the filter supports. | ||||
| @@ -492,6 +499,10 @@ public: | |||||
| virtual ~FilterNativeCallbacks() {} | virtual ~FilterNativeCallbacks() {} | ||||
| virtual bool JUCE_CALLTYPE getCurrentPositionInfo (CurrentPositionInfo& info) = 0; | virtual bool JUCE_CALLTYPE getCurrentPositionInfo (CurrentPositionInfo& info) = 0; | ||||
| virtual void JUCE_CALLTYPE informHostOfParameterChange (int index, float newValue) = 0; | virtual void JUCE_CALLTYPE informHostOfParameterChange (int index, float newValue) = 0; | ||||
| /** Callback to indicate that something (other than a parameter) has changed in the | |||||
| filter, such as its current program, parameter list, etc. */ | |||||
| virtual void JUCE_CALLTYPE updateHostDisplay() = 0; | |||||
| }; | }; | ||||
| @@ -534,6 +545,8 @@ protected: | |||||
| double sampleRate; | double sampleRate; | ||||
| /** @internal */ | /** @internal */ | ||||
| int blockSize, numInputChannels, numOutputChannels; | int blockSize, numInputChannels, numOutputChannels; | ||||
| /** @internal */ | |||||
| FilterNativeCallbacks* callbacks; | |||||
| private: | private: | ||||
| friend class JuceVSTWrapper; | friend class JuceVSTWrapper; | ||||
| @@ -546,8 +559,6 @@ private: | |||||
| CriticalSection callbackLock; | CriticalSection callbackLock; | ||||
| bool suspended; | bool suspended; | ||||
| FilterNativeCallbacks* callbacks; | |||||
| AudioFilterEditor* activeEditor; | AudioFilterEditor* activeEditor; | ||||
| }; | }; | ||||
| @@ -271,7 +271,7 @@ FileBasedDocument::SaveResult FileBasedDocument::saveAsInteractive (const bool w | |||||
| if (chosen.getFileExtension().isEmpty()) | if (chosen.getFileExtension().isEmpty()) | ||||
| chosen = chosen.withFileExtension (fileExtension); | chosen = chosen.withFileExtension (fileExtension); | ||||
| return saveAs (f, false, false, true); | |||||
| return saveAs (chosen, false, false, true); | |||||
| } | } | ||||
| return userCancelledSave; | return userCancelledSave; | ||||
| @@ -128,6 +128,7 @@ Slider::Slider (const String& name) | |||||
| popupDisplayEnabled (false), | popupDisplayEnabled (false), | ||||
| menuEnabled (false), | menuEnabled (false), | ||||
| menuShown (false), | menuShown (false), | ||||
| scrollWheelEnabled (true), | |||||
| valueBox (0), | valueBox (0), | ||||
| incButton (0), | incButton (0), | ||||
| decButton (0), | decButton (0), | ||||
| @@ -298,13 +299,13 @@ void Slider::hideTextBox (const bool discardCurrentEditorContents) | |||||
| } | } | ||||
| } | } | ||||
| void Slider::setChangeNotificationOnlyOnRelease (const bool onlyNotifyOnRelease) | |||||
| void Slider::setChangeNotificationOnlyOnRelease (const bool onlyNotifyOnRelease) throw() | |||||
| { | { | ||||
| sendChangeOnlyOnRelease = onlyNotifyOnRelease; | sendChangeOnlyOnRelease = onlyNotifyOnRelease; | ||||
| } | } | ||||
| void Slider::setPopupDisplayEnabled (const bool enabled, | void Slider::setPopupDisplayEnabled (const bool enabled, | ||||
| Component* const parentComponentToUse) | |||||
| Component* const parentComponentToUse) throw() | |||||
| { | { | ||||
| popupDisplayEnabled = enabled; | popupDisplayEnabled = enabled; | ||||
| parentForPopupDisplay = parentComponentToUse; | parentForPopupDisplay = parentComponentToUse; | ||||
| @@ -534,13 +535,13 @@ void Slider::setMaxValue (double newValue, const bool sendUpdateMessage, const b | |||||
| } | } | ||||
| void Slider::setDoubleClickReturnValue (const bool isDoubleClickEnabled, | void Slider::setDoubleClickReturnValue (const bool isDoubleClickEnabled, | ||||
| const double valueToSetOnDoubleClick) | |||||
| const double valueToSetOnDoubleClick) throw() | |||||
| { | { | ||||
| doubleClickToValue = isDoubleClickEnabled; | doubleClickToValue = isDoubleClickEnabled; | ||||
| doubleClickReturnValue = valueToSetOnDoubleClick; | doubleClickReturnValue = valueToSetOnDoubleClick; | ||||
| } | } | ||||
| double Slider::getDoubleClickReturnValue (bool& isEnabled_) const | |||||
| double Slider::getDoubleClickReturnValue (bool& isEnabled_) const throw() | |||||
| { | { | ||||
| isEnabled_ = doubleClickToValue; | isEnabled_ = doubleClickToValue; | ||||
| return doubleClickReturnValue; | return doubleClickReturnValue; | ||||
| @@ -622,11 +623,16 @@ void Slider::enablementChanged() | |||||
| repaint(); | repaint(); | ||||
| } | } | ||||
| void Slider::setPopupMenuEnabled (const bool menuEnabled_) | |||||
| void Slider::setPopupMenuEnabled (const bool menuEnabled_) throw() | |||||
| { | { | ||||
| menuEnabled = menuEnabled_; | menuEnabled = menuEnabled_; | ||||
| } | } | ||||
| void Slider::setScrollWheelEnabled (const bool enabled) throw() | |||||
| { | |||||
| scrollWheelEnabled = enabled; | |||||
| } | |||||
| //============================================================================== | //============================================================================== | ||||
| void Slider::labelTextChanged (Label* label) | void Slider::labelTextChanged (Label* label) | ||||
| { | { | ||||
| @@ -1268,28 +1274,33 @@ void Slider::mouseDoubleClick (const MouseEvent&) | |||||
| } | } | ||||
| } | } | ||||
| void Slider::mouseWheelMove (const MouseEvent&, float wheelIncrementX, float wheelIncrementY) | |||||
| void Slider::mouseWheelMove (const MouseEvent& e, float wheelIncrementX, float wheelIncrementY) | |||||
| { | { | ||||
| if (isEnabled() | |||||
| && (maximum > minimum) | |||||
| && ! isMouseButtonDownAnywhere()) | |||||
| if (scrollWheelEnabled && isEnabled()) | |||||
| { | { | ||||
| if (valueBox != 0) | |||||
| valueBox->hideEditor (false); | |||||
| if (maximum > minimum && ! isMouseButtonDownAnywhere()) | |||||
| { | |||||
| if (valueBox != 0) | |||||
| valueBox->hideEditor (false); | |||||
| const double proportionDelta = (wheelIncrementX != 0 ? -wheelIncrementX : wheelIncrementY) * 0.15f; | |||||
| const double currentPos = valueToProportionOfLength (currentValue); | |||||
| const double newValue = proportionOfLengthToValue (jlimit (0.0, 1.0, currentPos + proportionDelta)); | |||||
| const double proportionDelta = (wheelIncrementX != 0 ? -wheelIncrementX : wheelIncrementY) * 0.15f; | |||||
| const double currentPos = valueToProportionOfLength (currentValue); | |||||
| const double newValue = proportionOfLengthToValue (jlimit (0.0, 1.0, currentPos + proportionDelta)); | |||||
| double delta = (newValue != currentValue) | |||||
| ? jmax (fabs (newValue - currentValue), interval) : 0; | |||||
| double delta = (newValue != currentValue) | |||||
| ? jmax (fabs (newValue - currentValue), interval) : 0; | |||||
| if (currentValue > newValue) | |||||
| delta = -delta; | |||||
| if (currentValue > newValue) | |||||
| delta = -delta; | |||||
| sendDragStart(); | |||||
| setValue (snapValue (currentValue + delta, false), true, true); | |||||
| sendDragEnd(); | |||||
| sendDragStart(); | |||||
| setValue (snapValue (currentValue + delta, false), true, true); | |||||
| sendDragEnd(); | |||||
| } | |||||
| } | |||||
| else | |||||
| { | |||||
| Component::mouseWheelMove (e, wheelIncrementX, wheelIncrementY); | |||||
| } | } | ||||
| } | } | ||||
| @@ -427,7 +427,7 @@ public: | |||||
| @see getDoubleClickReturnValue | @see getDoubleClickReturnValue | ||||
| */ | */ | ||||
| void setDoubleClickReturnValue (const bool isDoubleClickEnabled, | void setDoubleClickReturnValue (const bool isDoubleClickEnabled, | ||||
| const double valueToSetOnDoubleClick); | |||||
| const double valueToSetOnDoubleClick) throw(); | |||||
| /** Returns the values last set by setDoubleClickReturnValue() method. | /** Returns the values last set by setDoubleClickReturnValue() method. | ||||
| @@ -436,7 +436,7 @@ public: | |||||
| @see setDoubleClickReturnValue | @see setDoubleClickReturnValue | ||||
| */ | */ | ||||
| double getDoubleClickReturnValue (bool& isEnabled) const; | |||||
| double getDoubleClickReturnValue (bool& isEnabled) const throw(); | |||||
| //============================================================================== | //============================================================================== | ||||
| /** Tells the slider whether to keep sending change messages while the user | /** Tells the slider whether to keep sending change messages while the user | ||||
| @@ -447,7 +447,7 @@ public: | |||||
| will be continuously sent as they drag it while the mouse button is still | will be continuously sent as they drag it while the mouse button is still | ||||
| held down. | held down. | ||||
| */ | */ | ||||
| void setChangeNotificationOnlyOnRelease (const bool onlyNotifyOnRelease); | |||||
| void setChangeNotificationOnlyOnRelease (const bool onlyNotifyOnRelease) throw(); | |||||
| /** If enabled, this gives the slider a pop-up bubble which appears while the | /** If enabled, this gives the slider a pop-up bubble which appears while the | ||||
| slider is being dragged. | slider is being dragged. | ||||
| @@ -462,7 +462,7 @@ public: | |||||
| you'll have to add it to a parent component instead). | you'll have to add it to a parent component instead). | ||||
| */ | */ | ||||
| void setPopupDisplayEnabled (const bool isEnabled, | void setPopupDisplayEnabled (const bool isEnabled, | ||||
| Component* const parentComponentToUse); | |||||
| Component* const parentComponentToUse) throw(); | |||||
| /** If this is set to true, then right-clicking on the slider will pop-up | /** If this is set to true, then right-clicking on the slider will pop-up | ||||
| a menu to let the user change the way it works. | a menu to let the user change the way it works. | ||||
| @@ -471,7 +471,13 @@ public: | |||||
| things like velocity sensitivity, and for rotary sliders, whether they | things like velocity sensitivity, and for rotary sliders, whether they | ||||
| use a linear or rotary mouse-drag to move them. | use a linear or rotary mouse-drag to move them. | ||||
| */ | */ | ||||
| void setPopupMenuEnabled (const bool menuEnabled); | |||||
| void setPopupMenuEnabled (const bool menuEnabled) throw(); | |||||
| /** This can be used to stop the mouse scroll-wheel from moving the slider. | |||||
| By default it's enabled. | |||||
| */ | |||||
| void setScrollWheelEnabled (const bool enabled) throw(); | |||||
| //============================================================================== | //============================================================================== | ||||
| /** Callback to indicate that the user is about to start dragging the slider. | /** Callback to indicate that the user is about to start dragging the slider. | ||||
| @@ -682,7 +688,7 @@ private: | |||||
| bool editableText : 1, doubleClickToValue : 1; | bool editableText : 1, doubleClickToValue : 1; | ||||
| bool isVelocityBased : 1, rotaryStop : 1, incDecButtonsSideBySide : 1; | bool isVelocityBased : 1, rotaryStop : 1, incDecButtonsSideBySide : 1; | ||||
| bool sendChangeOnlyOnRelease : 1, popupDisplayEnabled : 1; | bool sendChangeOnlyOnRelease : 1, popupDisplayEnabled : 1; | ||||
| bool menuEnabled : 1, menuShown : 1, mouseWasHidden : 1, incDecDragged : 1; | |||||
| bool menuEnabled : 1, menuShown : 1, mouseWasHidden : 1, incDecDragged : 1, scrollWheelEnabled : 1; | |||||
| Font font; | Font font; | ||||
| Label* valueBox; | Label* valueBox; | ||||
| Button* incButton; | Button* incButton; | ||||