VST3: order category tokens by meaning, map analyzers to Fx|Analyzer - #508
Merged
Conversation
clapCategoriesToVST3() once built the VST3 category string in the order the CLAP descriptor listed its features, and it collected every matching row of the translation table. Both got lost in 9a729a0 (ref: drive-by cleanups, free-audio#155): the table lookup became a find_if which only ever applies the first matching row, and the order preserving deduplication became std::sort + std::unique, which sorts the tokens alphabetically. Alphabetical is wrong for VST3. Hosts read the first token to file the plugin and the second one as its sub menu, so an ARA plugin advertised itself as "Fx|OnlyARA|Reverb" and an external instrument as "External|Instrument". It also discards the one thing the plugin author did tell us, namely which sub category they consider the important one. On top of that a combined attribute like "Instrument|Drum" was treated as one opaque string and could neither be deduplicated nor ordered against its own parts, so CLAP_PLUGIN_FEATURE_DRUM_MACHINE ended up as "Drum|Instrument". Every attribute is split into its tokens now, each token is kept once in the order it was first encountered, all matching table rows contribute again, and a stable sort only moves the two kinds of token that may not sit in the sub menu slot: a main category (Fx, Instrument) to the front, a trait rather than a category (OnlyARA, External, Mono, ...) to the end. Everything in between stays in the order the CLAP features were listed, so "audio-effect, reverb, chorus" yields "Fx|Reverb|Modulation" while "audio-effect, chorus, reverb" yields "Fx|Modulation|Reverb" - both collapsed to the latter before. CLAP_PLUGIN_FEATURE_ANALYZER maps to kFxAnalyzer instead of kAnalyzer. The latter is documented as "not selectable as insert plug-in", which kept CLAP analyzers out of the effect lists of hosts honouring that. Finally the length check for PClassInfo2::subCategories ignored the separators it appends, left no room for the terminating zero, and the trailing pop_back() cut the truncation marker off again - besides being undefined behaviour when no feature matched at all. Separators are prepended now and the budget is kSubCategoriesSize - 1, so truncation drops the categories the author ranked last. Fixes free-audio#409
defiantnerd
force-pushed
the
vst3-features
branch
from
August 8, 2026 20:05
1800cb6 to
341a0c6
Compare
Collaborator
|
Looks great and the sort logic is clear |
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.
VST3: order category tokens by meaning, map analyzers to Fx|Analyzer
clapCategoriesToVST3() once built the VST3 category string in the order
the CLAP descriptor listed its features, and it collected every matching
row of the translation table. Both got lost in 9a729a0 (ref: drive-by
cleanups, #155): the table lookup became a find_if which only ever
applies the first matching row, and the order preserving deduplication
became std::sort + std::unique, which sorts the tokens alphabetically.
Alphabetical is wrong for VST3. Hosts read the first token to file the
plugin and the second one as its sub menu, so an ARA plugin advertised
itself as "Fx|OnlyARA|Reverb" and an external instrument as
"External|Instrument". It also discards the one thing the plugin author
did tell us, namely which sub category they consider the important one.
On top of that a combined attribute like "Instrument|Drum" was treated
as one opaque string and could neither be deduplicated nor ordered
against its own parts, so CLAP_PLUGIN_FEATURE_DRUM_MACHINE ended up as
"Drum|Instrument".
Every attribute is split into its tokens now, each token is kept once in
the order it was first encountered, all matching table rows contribute
again, and a stable sort only moves the two kinds of token that may not
sit in the sub menu slot: a main category (Fx, Instrument) to the front,
a trait rather than a category (OnlyARA, External, Mono, ...) to the end.
Everything in between stays in the order the CLAP features were listed,
so "audio-effect, reverb, chorus" yields "Fx|Reverb|Modulation" while
"audio-effect, chorus, reverb" yields "Fx|Modulation|Reverb" - both
collapsed to the latter before.
CLAP_PLUGIN_FEATURE_ANALYZER maps to kFxAnalyzer instead of kAnalyzer.
The latter is documented as "not selectable as insert plug-in", which
kept CLAP analyzers out of the effect lists of hosts honouring that.
Finally the length check for PClassInfo2::subCategories ignored the
separators it appends, left no room for the terminating zero, and the
trailing pop_back() cut the truncation marker off again - besides being
undefined behaviour when no feature matched at all. Separators are
prepended now and the budget is kSubCategoriesSize - 1, so truncation
drops the categories the author ranked last.
Fixes #409