Our plugins read some preferences regarding a default editor layout from a preference file on processor construction. If a first fresh instance is loaded in an empty project, this works well. If I change the default preference through the first instances editor, the preference gets successfully written to the preference file.
Now if a second instance of the plugin is added to the same track, I see the following behaviour with the debugger attached:
Processor gets constructed. It reads the correct state from the preference file and sets an according state in the ValueTree used to manage our state
Now the Pro Tools automation thread kicks in and calls setStateInformation. There is no previous call to getStateInformation, so it seems to apply a cached “default” state. This state contains the previous preference the first instance read when being created
After this is done, the editor is constructed and reads the preference state from the ValueTree. Result: It does not read the state the processor just wrote to the value tree but an outdated state.
So what’s happening here? I’m extremely confused as this behaviour doesn’t make that much sense. Anyone that came across the same?
That is correct. Avid, for some reason, decided that Pro Tools would query and cache the session state of the first instance of the plugin to be created, and apply that state to every subsequent instance, even though plugin developers set their own default state, sometimes based on a preferences file (as you and I are both doing).
A couple ways to deal with that. Knowing that (in AAX) the first call to GetChunk() (the AAX function that leads to getStateInformation() in JUCE) is always the call to get this supposed “default” data to be cached and applied to subsequent instances, you can add a boolean flag to the data that says whether this is the first “defaults” chunk data (based on a shared global variable that says whether the GetChunk() function has ever been called in any instance yet).
You can use that information to tell subsequent instances whether to ignore the rest of (or some of) the SetChunk() data when loading that data later. You can also, in GetChunk(), set the content of the returned data to be the defaults that you DO want to use across all subsequent instances, if there is data like that you want to preserve rather than ignore. We do that, ignoring some data but using certain global defaults from this “default” chunk when reading in the data.
But I have not implemented this in JUCE yet. You need to be sure that this applies only to AAX instances. And if Avid ever decides to change that behavior, this fix would break.
There is also apparently an AAX property that you can set to prevent Pro Tools from loading its own cached “default state” for a plug-in. However, the JUCE AAX wrapper doesn’t currently have a macro to set this property (as it does for, say, JucePlugin_AAXDisableDynamicProcessing).
Looking at the AAX wrapper, it looks like it would be easy enough to add, but since there is a non-disclosure agreement to the AAX SDK, I don’t think I should post that here.
We also read this announcement from the Avid Developer Newsletter and we’ll be definitely adding this flag to our in house JUCE fork to finally get AAX plugins behave consistently with the other formats in the long run. Would be great if this option made it into the main JUCE repository
It’s actually used for the compare function. The default is user setable in the Pro Tools plugin header as well. There are some chunk functions in the SDK you can check out (CompareActiveChunk)… but they’re not handled in the JUCE wrapper.
Does anyone know if setting AAX_eProperty_Constraint_DoNotApplyDefaultSetting to true also breaks user-created default settings (created via the Pro Tools preset menu)?
I’m trying to implement a feature where a user can set a custom “Init” preset in my plug-in’s internal preset system. This “Init” preset is loaded on instantiation (in the plugin’s AudioProcessor), and can of course contain different parameter values than the default value declared for each parameter when my AudioProcessorValueTreeState is created.
I’m trying to utilize the JucePlugin_AAXDisableDefaultSettingsChunks flag such that Pro Tools doesn’t force my plugin to load the default value for each parameter (declared in AudioProcessorValueTreeState). However, even after enabling the aforementioned flag and clearing my Pro Tools prefs, the default parameter values are still being loaded, overriding the param values in the “Init” preset. It seems that while the flag bypasses the GetChunk() and SetChunk() calls, Pro Tools still grabs the default parameter value for each parameter on instantiation (separately of GetChunk()), and then sets the parameter value to the default (separately of SetChunk(). This happens regardless of if the flag is enabled or not.
Does anyone know if this is a known limitation, or am I misunderstanding the purpose of this flag? It certainly seems like there is no way to reliably load my own, custom “Init” state that differs from the default state of the parameters.
FWIW, in the past I have checked this very same thing and in my case I am pretty sure that the JucePlugin_AAXDisableDefaultSettingsChunks macro disabled the default chunk and also prevented the automated parameters from being set to the default value recorded by Pro Tools upon first instantiation of the plug-in. Maybe things have changed with the latest version of Pro Tools?
Are you definitely sure that the values of the parameter you see after the plug-in has completed instantiation, come from Pro Tools itself and not from some other source?
To debug that, I had to sprinkle some DBGs in the code and then launch Pro Tools from the Terminal in order to see the output printed by them.
I recently had to remove “user definable init state” functionality in a plugin project specifically for AAX, because JucePlugin_AAXDisableDefaultSettingsChunks didn’t help…
While I can see in the debugger that the SetChunk() call is bypassed, Pro Tools is still sending me a value of 0.5 (the default value) for the “gain” parameter upon instantiation. Also, changing the default value for “gain” (to e.g. 0.2) results in my plugin launching with the different default value (0.2).
AFAICT, there’s nothing to be done on JUCE’s end to remedy this. It seems like the flag does do something (disables the AAX SetChunk() call), but it doesn’t solve the problem of trying to load an “Init” preset with parameter values differing from the default plugin state. I’ll have to find some other workaround.
Ah… thank you for checking, that proves me wrong at least for the current version of Pro Tools.
At this point, it doesn’t matter much whether the behaviour was different at the time I tested it… looks like I’ll have to hack something to deal with this.
Would this work?: load the Init preset before defining the parameters, and use the values from that preset when building the parameter list to set their default values to those values instead?
Uhm, that’s good, but I think it leaves one corner case still open:
the default values are read by Pro Tools when the first instance of the plug-in is created, so if the user changes them using the first plug-in instance, and then opens a second instance in the same session, the second instance will still open with the original initial values, and not with the most up to date ones that the user expects.
Have you considered just loading a default factory preset after init. That way you can change the defaults at any time just by adjusting the default preset and maybe even letting the users save their own default settings.
@HowardAntares good suggestion, though in addition to the point @yfede makes, I’d also like to have my parameter defaults be something sensible for a double-click “reset” (typically a unity value for the parameter).
@railjonrogut to make sure I understand correctly, you mean load a default (“init”) preset in my internal preset system, after my AudioProcessorParameters are declared? I’m currently doing this in my AudioProcessor constructor, but Pro Tools still forces all parameters to their default values after the AudioProcessor is constructed (regardless of the JucePlugin_AAXDisableDefaultSettingsChunks flag), so this doesn’t work. But perhaps I’m misunderstanding your suggestion.
Thanks! The Timer is a good suggestion, but I’d still need to do a decent bit of logic to ensure it fires after the first SetChunk() call happens (with the default state from PT) but before a second SetChunk() call comes with any session-saved state (if reloading a session).
I ended up getting this to work using a similar approach described by @HowardAntares earlier in this thread:
In getStateInformation(), detect if this is the first time getStateInformation() has been called. If it is, then write a special flag into the state. A few gotchas:
Pro Tools will call getStateInformation() to retrieve the default chunk for the first instance of the plugin for each BusesLayout in the session. So e.g. a mono-in → mono-out and stereo-in → stereo-out instance each get their own call requesting default state. So you can’t just track a single shared/global flag for it being the first instance, rather you need to track a shared/global vector or map of BusesLayouts.
If the user adds a plugin, then removes it, then adds it again (assuming the BusesLayout is the same), there is not a call to getStateInformation(), since Pro Tools has already retrieved the default chunk. To workaround this, you have to also keep track of if setStateInformation() has received the default chunk.
In setStateInformation(), detect if it’s the default chunk, and if it is, load our desired preset values instead. We also set a member variable specifying the default chunk has been recieved from Pro Tools, so we can prevent the above case where the user might have already added and removed the plugin.