| @@ -598,11 +598,7 @@ public: | |||||
| void cleanup() | void cleanup() | ||||
| { | { | ||||
| #if JUCE_MAC | #if JUCE_MAC | ||||
| if (eventListenerRef != nullptr) | |||||
| { | |||||
| AUListenerDispose (eventListenerRef); | |||||
| eventListenerRef = nullptr; | |||||
| } | |||||
| disposeEventListener(); | |||||
| #endif | #endif | ||||
| if (prepared) | if (prepared) | ||||
| @@ -618,7 +614,11 @@ public: | |||||
| setRateAndBufferSizeDetails (rate, blockSize); | setRateAndBufferSizeDetails (rate, blockSize); | ||||
| setLatencySamples (0); | setLatencySamples (0); | ||||
| refreshParameterList(); | refreshParameterList(); | ||||
| createPluginCallbacks(); | |||||
| setPluginCallbacks(); | |||||
| #if JUCE_MAC | |||||
| createEventListener(); | |||||
| #endif | |||||
| return true; | return true; | ||||
| } | } | ||||
| @@ -1001,6 +1001,8 @@ public: | |||||
| if (! haveParameterList) | if (! haveParameterList) | ||||
| refreshParameterList(); | refreshParameterList(); | ||||
| setPluginCallbacks(); | |||||
| if (! syncBusLayouts (getBusesLayout(), true, ignore)) | if (! syncBusLayouts (getBusesLayout(), true, ignore)) | ||||
| { | { | ||||
| prepared = false; | prepared = false; | ||||
| @@ -1666,7 +1668,7 @@ private: | |||||
| bool lastProcessBlockCallWasBypass = false, auSupportsBypass = false; | bool lastProcessBlockCallWasBypass = false, auSupportsBypass = false; | ||||
| bool haveParameterList = false; | bool haveParameterList = false; | ||||
| void createPluginCallbacks() | |||||
| void setPluginCallbacks() | |||||
| { | { | ||||
| if (audioUnit != nullptr) | if (audioUnit != nullptr) | ||||
| { | { | ||||
| @@ -1684,52 +1686,65 @@ private: | |||||
| } | } | ||||
| #endif | #endif | ||||
| { | |||||
| HostCallbackInfo info; | |||||
| zerostruct (info); | |||||
| HostCallbackInfo info; | |||||
| zerostruct (info); | |||||
| info.hostUserData = this; | |||||
| info.beatAndTempoProc = getBeatAndTempoCallback; | |||||
| info.musicalTimeLocationProc = getMusicalTimeLocationCallback; | |||||
| info.transportStateProc = getTransportStateCallback; | |||||
| info.hostUserData = this; | |||||
| info.beatAndTempoProc = getBeatAndTempoCallback; | |||||
| info.musicalTimeLocationProc = getMusicalTimeLocationCallback; | |||||
| info.transportStateProc = getTransportStateCallback; | |||||
| AudioUnitSetProperty (audioUnit, kAudioUnitProperty_HostCallbacks, | |||||
| kAudioUnitScope_Global, 0, &info, sizeof (info)); | |||||
| } | |||||
| #if JUCE_MAC | |||||
| AUEventListenerCreate (eventListenerCallback, this, CFRunLoopGetMain(), | |||||
| kCFRunLoopDefaultMode, 0, 0, &eventListenerRef); | |||||
| AudioUnitSetProperty (audioUnit, kAudioUnitProperty_HostCallbacks, | |||||
| kAudioUnitScope_Global, 0, &info, sizeof (info)); | |||||
| } | |||||
| } | |||||
| for (auto* param : getParameters()) | |||||
| { | |||||
| if (auto* auParam = dynamic_cast<AUInstanceParameter*> (param)) | |||||
| { | |||||
| AudioUnitEvent event; | |||||
| event.mArgument.mParameter.mAudioUnit = audioUnit; | |||||
| event.mArgument.mParameter.mParameterID = auParam->paramID; | |||||
| event.mArgument.mParameter.mScope = kAudioUnitScope_Global; | |||||
| event.mArgument.mParameter.mElement = 0; | |||||
| #if JUCE_MAC | |||||
| void disposeEventListener() | |||||
| { | |||||
| if (eventListenerRef != nullptr) | |||||
| { | |||||
| AUListenerDispose (eventListenerRef); | |||||
| eventListenerRef = nullptr; | |||||
| } | |||||
| } | |||||
| event.mEventType = kAudioUnitEvent_ParameterValueChange; | |||||
| AUEventListenerAddEventType (eventListenerRef, nullptr, &event); | |||||
| void createEventListener() | |||||
| { | |||||
| if (audioUnit == nullptr) | |||||
| return; | |||||
| event.mEventType = kAudioUnitEvent_BeginParameterChangeGesture; | |||||
| AUEventListenerAddEventType (eventListenerRef, nullptr, &event); | |||||
| disposeEventListener(); | |||||
| event.mEventType = kAudioUnitEvent_EndParameterChangeGesture; | |||||
| AUEventListenerAddEventType (eventListenerRef, nullptr, &event); | |||||
| } | |||||
| } | |||||
| AUEventListenerCreate (eventListenerCallback, this, CFRunLoopGetMain(), | |||||
| kCFRunLoopDefaultMode, 0, 0, &eventListenerRef); | |||||
| addPropertyChangeListener (kAudioUnitProperty_PresentPreset); | |||||
| addPropertyChangeListener (kAudioUnitProperty_ParameterList); | |||||
| addPropertyChangeListener (kAudioUnitProperty_Latency); | |||||
| addPropertyChangeListener (kAudioUnitProperty_BypassEffect); | |||||
| #endif | |||||
| for (auto* param : getParameters()) | |||||
| { | |||||
| jassert (dynamic_cast<AUInstanceParameter*> (param) != nullptr); | |||||
| AudioUnitEvent event; | |||||
| event.mArgument.mParameter.mAudioUnit = audioUnit; | |||||
| event.mArgument.mParameter.mParameterID = static_cast<AUInstanceParameter*> (param)->paramID; | |||||
| event.mArgument.mParameter.mScope = kAudioUnitScope_Global; | |||||
| event.mArgument.mParameter.mElement = 0; | |||||
| event.mEventType = kAudioUnitEvent_ParameterValueChange; | |||||
| AUEventListenerAddEventType (eventListenerRef, nullptr, &event); | |||||
| event.mEventType = kAudioUnitEvent_BeginParameterChangeGesture; | |||||
| AUEventListenerAddEventType (eventListenerRef, nullptr, &event); | |||||
| event.mEventType = kAudioUnitEvent_EndParameterChangeGesture; | |||||
| AUEventListenerAddEventType (eventListenerRef, nullptr, &event); | |||||
| } | } | ||||
| addPropertyChangeListener (kAudioUnitProperty_PresentPreset); | |||||
| addPropertyChangeListener (kAudioUnitProperty_ParameterList); | |||||
| addPropertyChangeListener (kAudioUnitProperty_Latency); | |||||
| addPropertyChangeListener (kAudioUnitProperty_BypassEffect); | |||||
| } | } | ||||
| #if JUCE_MAC | |||||
| void addPropertyChangeListener (AudioUnitPropertyID type) const | void addPropertyChangeListener (AudioUnitPropertyID type) const | ||||
| { | { | ||||
| AudioUnitEvent event; | AudioUnitEvent event; | ||||