Skip to content

Sync patchmanager UI selection with host-driven setStateInformation - #264

Open
AxidentDK wants to merge 1 commit into
dsp56300:mainfrom
AxidentDK:apc-state-sync-pm
Open

Sync patchmanager UI selection with host-driven setStateInformation#264
AxidentDK wants to merge 1 commit into
dsp56300:mainfrom
AxidentDK:apc-state-sync-pm

Conversation

@AxidentDK

Copy link
Copy Markdown

Summary

When a VST3 host (e.g. Native Instruments Komplete Kontrol loading an NKS preset) calls setStateInformation, the audio engine correctly restores the new patch via Plugin::setState, but the patchmanager UI keeps showing whatever was previously selected (or nothing). The selection state is set only from manual UI clicks via setSelectedPatch, never from the state-restore path.

This PR fixes that with a small generic mechanism that benefits every gearmulator-based plugin (Microwave XT, Virus, microQ, JD-800, Nord Lead 2X) without per-plugin code changes.

Implementation

  • New parameterless event Processor::evStateLoaded (jucePluginLib).
  • Fired at the end of Processor::setState, on both the synchronous and async device-recreate paths.
  • PatchManager subscribes in its constructor and, on the message thread, hashes whatever the audio engine is currently playing on the active part (via the existing requestPatchForPart convenience overload, which already computes the per-plugin MD5 hash) and then linear-scans loaded data sources for a matching content hash.
  • A match drives setSelectedPatch. No match leaves selection unchanged (clearing it would surprise users who manually loaded one-off SysEx imports).

The hash-lookup approach means no per-plugin code change is required — each subclass already implements requestPatchForPart and initializePatch which together provide the canonical hash for the active patch.

How was this discovered

While building Automated Preview Creator (APC), a tool that generates NKS preview files for VST3 plugins so musicians can browse and load presets directly from NI hardware. APC's generated NKS files correctly cause the audio engine to play the right patch (verified with both setstate-getstate round-trip and live audio rendering), but the plugin's patchmanager UI stayed empty after KK loaded the preset. Investigation traced this to setSelectedPatch only being reachable from UI click paths, never from setStateInformation.

Test plan

  • Build with each plugin variant (XT, Virus, microQ, JD-800, NL2X).
  • Manual: load a known-cached patch via NKS / external host setStateInformation; patchmanager UI should highlight the matching entry.
  • Manual: load a foreign SysEx (no match in cache); patchmanager UI selection should remain unchanged (no false clear).
  • Manual: ensure manual-click selection still works as before (regression check).
  • Verify no thread issues — the listener defers to the JUCE message thread via juce::MessageManager::callAsync and re-checks the instance is still alive (same pattern used by the existing program-change router subscription).

When a host (e.g. Native Instruments Komplete Kontrol loading an NKS
preset) calls setStateInformation, the audio engine correctly restores
the new patch via Plugin::setState, but the patchmanager UI keeps
showing whatever was previously selected (or nothing). The selection
state is set only from manual UI clicks via setSelectedPatch, never
from a state-restore path.

Introduce a parameterless event Processor::evStateLoaded that fires at
the end of Processor::setState (both the synchronous and async device-
recreate paths). PatchManager subscribes in its constructor and, on
the message thread, hashes whatever the audio engine is currently
playing on the active part (via the existing requestPatchForPart
convenience overload, which already computes the per-plugin MD5 hash)
then linear-scans loaded data sources for a matching content hash.
A match drives setSelectedPatch so the UI lights up the right entry.

If no loaded patch matches the hash (e.g. the host loaded an entirely
foreign SysEx) the selection is left unchanged — clearing it would
surprise users who'd manually loaded one-off SysEx imports.

This means VST3 hosts that drive setStateInformation now leave the
patchmanager UI in a coherent state across all gearmulator-based
plugins (Microwave XT/Xenia, Virus, microQ/Vavra, JD-800/JE8086,
Nord Lead 2X/NodalRed2x). No per-plugin code change is required —
each plugin already implements requestPatchForPart and initializePatch
which together provide the canonical hash for the active patch.

Discovered while building Automated Preview Creator (APC), a tool that
generates NKS preview files for VST3 plugins so musicians can browse
and load presets directly from NI hardware. APC's generated NKS files
correctly cause the audio engine to play the right patch, but the
plugin's patchmanager UI stayed empty after KK loaded the preset.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant