Latest version of HISE breaks existing presets....
-
@Christoph-Hart When I open a project previously saved in a DAW using a plugin compiled with 2024 commit HISE (I only tried in Reaper and Logic on macOS), with the same plugin compiled with new HISE, the saved settings are not loaded in the DAW. The plugin is loaded with the default state.
-
@JulesV Are you using plugin parameters? And is this affecting only controls that are linked to plugin parameters or all values?
-
@Christoph-Hart In the plugin, all controls are set to plugin parameters. Also most of them are set to isMetaParameter. And all controls are initializing with default values
-
@Christoph-Hart said in Latest version of HISE breaks existing presets....:
@Lindon yes send over.
So your particular problem is that plugin parameters + macros + preset recall is not working (mastervolume +30 = 1.0 normalized)?
yes that about sums it up - I will send it over...
-
@Lindon Would it be possible that the single error that both you and @JulesV are experiencing is because of a drift between the plugin parameter value stored in the DAW project and the internal preset?
Whenever you save a DAW preset, it will
- create a .preset containing the plugin state (exactly as if you would save a user preset)
- store the values of all registered plugin parameters
and dump that into the binary data blob stored as DAW project.
In a "healthy" plugin, these values should not drift - the plugin parameter value is the value stored into the preset. But if there is a mismatch (either because of a new plugin parameter that wasn't stored or because of some initialisation error at startup, it might create these issues.
-
@Christoph-Hart I think not. As this is showing up in HISE as well as compiled plugins.... see my posts at the start about using Console.print to tell me whats happening...
Sent you the project link to your email
-
@Lindon Is it fixed on your side?
-
@JulesV I haven't heard back from Christoph so I assume not...
-
@Christoph-Hart - is there any chance of ever getting a fix for this?
-
@Lindon Without me having to read 4 pages of posts about this, what's the outstanding issue?
-
I've let the robot loose on it. "Read this topic and propose a fix. Make no mistake."
-
-
@Christoph-Hart said in Latest version of HISE breaks existing presets....:
Make no mistake
Proceeds to hack huggingface
-
@Lindon Looks like there's a related commit for this, have you tried with this commit in place?
e1fb54695(May 2026) — "fixed macro controller controlling first plugin parameter control inside HISE"
-
@Christoph-Hart Here's what 'my' Claude says:
The pattern so far
Since
a92a701de(the unified automation base class), every automation actor - host parameter, macro, MIDI automation, UI widget, script, preset restore - is both a reader and a writer of shared values, connected through the dispatch library. The regressions since then have all been the same bug wearing different hats: a listener can't tell an echo of its own write from a real change, so it feeds the value back around the loop. Each fix so far suppresses one specific edge:633626eeb- gaterefreshParameterValue()onenablePluginParameterUpdate, and switch MIDI automation'ssetAttributefrom async to sync notificatione1fb54695- carve the backend macro-to-parameter-slot routing out behindHISE_MACROS_ARE_PLUGIN_PARAMETERS
Alongside the pre-existing guards (
recursive,sendToHostper parameter,deferNotifyHostFlag, the exclusive-mode conditionals inloadUserPresetInternal()), that's now seven or so overlapping mechanisms all answering the same question by inference: "is this change an echo?"Why I think flags can't fully close this
Two structural limits:
- The global flag suppresses the wrong scope.
enablePluginParameterUpdateis one boolean for all parameters. While parameter A's update is dispatching (flag false), a legitimate concurrent change to parameter B hits the early return inrefreshParameterValue()and is silently dropped -the internal value updates but the host never hears it. I suspect this is exactly the DAW-project-vs-internal-preset drift you were hypothesizing about at the end of the thread. The guard isn't just failing to fix that bug, it's a source of it. - Scoped guards can't survive deferred dispatch. A
ScopedValueSetterprotects a call stack, but this system defers across threads by design. By the time an async-queued listener runs, the guard is long restored and the echo sails through. That's why633626eebhad to change MIDI automation to sync notification - to drag the callback inside the guard's scope. Changing threading semantics to make a boolean reachable feels like the approach hitting its ceiling.
Proposal: make provenance explicit
The class structure from the rewrite is good - I'd keep all of it. The change is to what a notification is: value plus origin, instead of value alone.
- Add a small source token (
Host,Macro,MidiAutomation,UI,Script,PresetRestore) toSlotSender::sendChangeMessage()and the listener callbacks, threaded throughCustomAutomationData::call(). Because the token travels with the queued message, it survives deferral and thread hops - the thing no scoped flag can do. - Each writer passes its own token and ignores incoming messages carrying it.
MacroPluginParameter::setValue()writes asHostand skipsHost-tagged notifications; same pattern inHisePluginParameterBase,MidiControllerAutomationHandler,CustomAutomationParameter. recursive,sendToHostand the globalenablePluginParameterUpdatethen become deletable. (deferNotifyHostFlagcan stay - batching host notifications is an optimization, not a correctness guard.)- Preset restore becomes a first-class source: "macros must not clobber freshly restored widget values" becomes a one-line filter rule instead of an ordering convention plus exclusive-mode conditionals, and the MIDI sync/async choice stops mattering for correctness.
For precedent: JUCE's own
ParameterAttachmentsolves the identical loop the same way - each attachment filters its own echoes at the attachment point. -


-
Alright, I've performed a bunch of fixes:
- there was in fact an issue where the macro restoring used the parameter index as raw macro control value which could have created some restore issues (although that was only in the HISE backend path and shouldn't affect compiled plugins.
- a few other low risk fixes that might cause other glitches
Lindon can you check if that still persists or if we're chasing ghosts? There have been a few fixes to this system this year so I'd like to know whether this still applies.
The analysis from Dan looks like a good redesign plan but it's a bit overly aggressive and I don't trust it to not yield any side effects that we'll chase a few months later down the line.
-
@Christoph-Hart yep, as soon as I can I will test it out, though I did send you a version of the project and I think the thread documents the problem well enough....
-
@dannytaurus said in Latest version of HISE breaks existing presets....:
@Christoph-Hart Here's what 'my' Claude says:
The pattern so far
Since
a92a701de(the unified automation base class), every automation actor - host parameter, macro, MIDI automation, UI widget, script, preset restore - is both a reader and a writer of shared values, connected through the dispatch library. The regressions since then have all been the same bug wearing different hats: a listener can't tell an echo of its own write from a real change, so it feeds the value back around the loop. Each fix so far suppresses one specific edge:633626eeb- gaterefreshParameterValue()onenablePluginParameterUpdate, and switch MIDI automation'ssetAttributefrom async to sync notificatione1fb54695- carve the backend macro-to-parameter-slot routing out behindHISE_MACROS_ARE_PLUGIN_PARAMETERS
Alongside the pre-existing guards (
recursive,sendToHostper parameter,deferNotifyHostFlag, the exclusive-mode conditionals inloadUserPresetInternal()), that's now seven or so overlapping mechanisms all answering the same question by inference: "is this change an echo?"Why I think flags can't fully close this
Two structural limits:
- The global flag suppresses the wrong scope.
enablePluginParameterUpdateis one boolean for all parameters. While parameter A's update is dispatching (flag false), a legitimate concurrent change to parameter B hits the early return inrefreshParameterValue()and is silently dropped -the internal value updates but the host never hears it. I suspect this is exactly the DAW-project-vs-internal-preset drift you were hypothesizing about at the end of the thread. The guard isn't just failing to fix that bug, it's a source of it. - Scoped guards can't survive deferred dispatch. A
ScopedValueSetterprotects a call stack, but this system defers across threads by design. By the time an async-queued listener runs, the guard is long restored and the echo sails through. That's why633626eebhad to change MIDI automation to sync notification - to drag the callback inside the guard's scope. Changing threading semantics to make a boolean reachable feels like the approach hitting its ceiling.
Proposal: make provenance explicit
The class structure from the rewrite is good - I'd keep all of it. The change is to what a notification is: value plus origin, instead of value alone.
- Add a small source token (
Host,Macro,MidiAutomation,UI,Script,PresetRestore) toSlotSender::sendChangeMessage()and the listener callbacks, threaded throughCustomAutomationData::call(). Because the token travels with the queued message, it survives deferral and thread hops - the thing no scoped flag can do. - Each writer passes its own token and ignores incoming messages carrying it.
MacroPluginParameter::setValue()writes asHostand skipsHost-tagged notifications; same pattern inHisePluginParameterBase,MidiControllerAutomationHandler,CustomAutomationParameter. recursive,sendToHostand the globalenablePluginParameterUpdatethen become deletable. (deferNotifyHostFlagcan stay - batching host notifications is an optimization, not a correctness guard.)- Preset restore becomes a first-class source: "macros must not clobber freshly restored widget values" becomes a one-line filter rule instead of an ordering convention plus exclusive-mode conditionals, and the MIDI sync/async choice stops mattering for correctness.
For precedent: JUCE's own
ParameterAttachmentsolves the identical loop the same way - each attachment filters its own echoes at the attachment point.Hmm, I must give this Claude malarky a bit of a go......
