Sync patchmanager UI selection with host-driven setStateInformation - #264
Open
AxidentDK wants to merge 1 commit into
Open
Sync patchmanager UI selection with host-driven setStateInformation#264AxidentDK wants to merge 1 commit into
AxidentDK wants to merge 1 commit into
Conversation
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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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 viaPlugin::setState, but the patchmanager UI keeps showing whatever was previously selected (or nothing). The selection state is set only from manual UI clicks viasetSelectedPatch, 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
Processor::evStateLoaded(jucePluginLib).Processor::setState, on both the synchronous and async device-recreate paths.PatchManagersubscribes in its constructor and, on the message thread, hashes whatever the audio engine is currently playing on the active part (via the existingrequestPatchForPartconvenience overload, which already computes the per-plugin MD5 hash) and then linear-scans loaded data sources for a matching content hash.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
requestPatchForPartandinitializePatchwhich 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
setSelectedPatchonly being reachable from UI click paths, never fromsetStateInformation.Test plan
juce::MessageManager::callAsyncand re-checks the instance is still alive (same pattern used by the existing program-change router subscription).