Skip to content

VST3: two context-menu bridge fixes - #542

Merged
defiantnerd merged 2 commits into
free-audio:nextfrom
defiantnerd:vst3-context-menu-fixes
Sep 13, 2026
Merged

VST3: two context-menu bridge fixes#542
defiantnerd merged 2 commits into
free-audio:nextfrom
defiantnerd:vst3-context-menu-fixes

Conversation

@defiantnerd

@defiantnerd defiantnerd commented Sep 13, 2026

Copy link
Copy Markdown
Collaborator

Two independent correctness fixes on the VST3 context-menu bridge, one commit each. Found while implementing clap.context-menu consumption in a plugin — i.e. the plugin draws its own menu and merges the host's entries into it.

1. A null target dereferences

clap/ext/context-menu.h carries "If target is null, assume global context." on all five function pointers, and has since CLAP 1.1.4 — before context-menu support landed here. ClapAsVst3::context_menu_populate dereferenced it unconditionally while deciding which menu to create, taking the host down.

Now treated as what it means. An unrecognised kind still creates no menu, as before. This was the only dereference of target in the tree: context_menu_perform ignores it (its action ids are the indices it handed out, so the target adds nothing), Plugin::context_menu_populate only forwards the pointer, and the other four flavours return false without touching it.

2. The context-menu parameter id is not masked

createParameter() publishes every parameter as info->id & 0x7FFFFFFF, but createContextMenu() was handed the raw clap_id. For a parameter whose id has the top bit set, the host is asked for a menu for an id it never saw, so it cannot offer that parameter's own entries.

The mask is the SDK's own rule, not a local convention: pluginterfaces/vst/vsttypes.h documents ParamID as "value in range [0, 0x7FFFFFFF]" and names kMaxParamId. Every other clap_idParamID conversion in the wrapper already applies it — param_clear, the queued editvalue, and the three in detail/vst3/process.cpp — so this call was the only one out of step. It introduces no new collision: two ids differing only in bit 31 already collide in the parameters table that this menu request now names.


Verified against Cubase on macOS with a CLAP plugin consuming clap_host_context_menu through the VST3 wrapper: host entries reach the plugin's menu with nested submenus and disabled items intact, and selecting one performs the host's action.

That plugin avoids both paths above by construction — it never sends a null target and its only parameter id is below 2^31 — which is how they were found rather than hit.

clap_plugin_context_menu::populate documents target == nullptr as the
global context, so a plugin that passes it is conforming. The wrapper
dereferenced it unconditionally while deciding which menu to create,
which takes the host down.

Treat it as the global context, which is what it means. An unrecognised
kind still creates no menu, as before.
@defiantnerd
defiantnerd force-pushed the vst3-context-menu-fixes branch from e7a35d1 to 72cf961 Compare September 13, 2026 08:22
@defiantnerd defiantnerd changed the title VST3: three context-menu bridge fixes VST3: two context-menu bridge fixes Sep 13, 2026
createParameter() publishes a parameter as `info->id & 0x7FFFFFFF`, but
createContextMenu() was handed the raw clap_id. For any parameter whose
id has the top bit set the host is asked for a menu for an id it never
saw, so it cannot offer the parameter's own entries.

The mask is not a convention: pluginterfaces/vst/vsttypes.h documents
ParamID as "value in range [0, 0x7FFFFFFF]" and names the bound
kMaxParamId. Every other clap_id -> ParamID conversion in the wrapper
already applies it - param_clear, the queued editvalue, and the three
in detail/vst3/process.cpp - so this call was the only one out of step.
@defiantnerd
defiantnerd force-pushed the vst3-context-menu-fixes branch from 72cf961 to f79bfa6 Compare September 13, 2026 08:35
@defiantnerd
defiantnerd merged commit ebe4aad into free-audio:next Sep 13, 2026
28 checks passed
@defiantnerd
defiantnerd deleted the vst3-context-menu-fixes branch September 13, 2026 09:55
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