Browse Source

AU Client: Prevent parameter change messages being sent during state restoration

This is intended to fix two issues:
- In REAPER, setting automation recording to 'Latch', recording some
  automation, saving and reloading the project, then starting playback causes
  automation data to be overwritten. This appears to be because REAPER
  interprets parameter change messages sent during state restoration as
  originating from the user.
- In Ableton Live, automation lanes are sometimes disabled when loading
  projects. This also seems to be because the setStateInformation call
  may send parameter change messages back to the host.

According to the docs for kAudioUnitProperty_ClassInfo, the host is
required to notify all parameter listeners that the parameter values may
have changed, implying that the plugin need not send its own parameter
change notifications during state restoration.
pull/22/head
reuk 3 years ago
parent
commit
0f16d2dded
No known key found for this signature in database GPG Key ID: 9ADCD339CFC98A11
1 changed files with 8 additions and 2 deletions
  1. +8
    -2
      modules/juce_audio_plugin_client/AU/juce_AU_Wrapper.mm

+ 8
- 2
modules/juce_audio_plugin_client/AU/juce_AU_Wrapper.mm View File

@@ -724,6 +724,8 @@ public:
ComponentResult RestoreState (CFPropertyListRef inData) override ComponentResult RestoreState (CFPropertyListRef inData) override
{ {
const ScopedValueSetter<bool> scope { restoringState, true };
{ {
// Remove the data entry from the state to prevent the superclass loading the parameters // Remove the data entry from the state to prevent the superclass loading the parameters
CFUniquePtr<CFMutableDictionaryRef> copyWithoutData (CFDictionaryCreateMutableCopy (nullptr, 0, (CFDictionaryRef) inData)); CFUniquePtr<CFMutableDictionaryRef> copyWithoutData (CFDictionaryCreateMutableCopy (nullptr, 0, (CFDictionaryRef) inData));
@@ -1151,6 +1153,9 @@ public:
void sendAUEvent (const AudioUnitEventType type, const int juceParamIndex) void sendAUEvent (const AudioUnitEventType type, const int juceParamIndex)
{ {
if (restoringState)
return;
auEvent.mEventType = type; auEvent.mEventType = type;
auEvent.mArgument.mParameter.mParameterID = getAUParameterIDForIndex (juceParamIndex); auEvent.mArgument.mParameter.mParameterID = getAUParameterIDForIndex (juceParamIndex);
AUEventListenerNotify (nullptr, nullptr, &auEvent); AUEventListenerNotify (nullptr, nullptr, &auEvent);
@@ -1186,7 +1191,8 @@ public:
// this will only ever be called by the bypass parameter // this will only ever be called by the bypass parameter
void parameterValueChanged (int, float) override void parameterValueChanged (int, float) override
{ {
PropertyChanged (kAudioUnitProperty_BypassEffect, kAudioUnitScope_Global, 0);
if (! restoringState)
PropertyChanged (kAudioUnitProperty_BypassEffect, kAudioUnitScope_Global, 0);
} }
void parameterGestureChanged (int, bool) override {} void parameterGestureChanged (int, bool) override {}
@@ -1811,7 +1817,7 @@ private:
//============================================================================== //==============================================================================
AudioUnitHelpers::CoreAudioBufferList audioBuffer; AudioUnitHelpers::CoreAudioBufferList audioBuffer;
MidiBuffer midiEvents, incomingEvents; MidiBuffer midiEvents, incomingEvents;
bool prepared = false, isBypassed = false;
bool prepared = false, isBypassed = false, restoringState = false;
//============================================================================== //==============================================================================
#if JUCE_FORCE_USE_LEGACY_PARAM_IDS #if JUCE_FORCE_USE_LEGACY_PARAM_IDS


Loading…
Cancel
Save