Skip to content

AUv2: activation state, Render() flags and lock, and preset publication - #564

Merged
defiantnerd merged 3 commits into
nextfrom
fix-auv2-activation-render-presets
Sep 15, 2026
Merged

defiantnerd merged 3 commits into
nextfrom
fix-auv2-activation-render-presets

Conversation

@defiantnerd

Copy link
Copy Markdown
Collaborator

Closes #549, #550, #552. Three commits, in dependency order — all three live in wrapasauv2.cpp, which is why they are one PR.

1. Explicit CLAP activation state (#549). activateCLAP() ignored clap_plugin.activate()'s result and set _initialized = true regardless; deactivateCLAP() called stop_processing()/deactivate() guarded only by if (_plugin). A failed reactivation therefore left a later AU Uninitialize deactivating an already-inactive plugin, which CLAP forbids. New _clapActive (main-thread only, so no atomic) records the fact _initialized was being asked to stand in for — it conflated "CLAP is down" with "running but not initialized". activateCLAP() now propagates the failure, and tears its own process adapter back down on the way out so nothing queues on an adapter no flush will drain.

2. Render() (#550). Three parts:

  • The gate was inFlags == 0, so any host-set flag produced silencekAudioUnitRenderAction_DoNotCheckRenderArgs merely tells AUBase to skip argument checks, and an input marked silent upstream must still reach a plugin with a tail. Only kAudioOfflineUnitRenderAction_Preflight|Complete now refuse a render, and this is not an offline unit, so they should never arrive at all.
  • ProcessData::flags is passed by reference into PullInput, which ORs in whatever the upstream unit reports — so its OutputIsSilence could surface as this wrapper's output flag. The pull now gets a local copy, and the wrapper sets its own flag deliberately.
  • Render() spun on _processLock, which onIdle() can hold across clap_plugin_params.flush() — plugin code of unbounded duration. Now try_lock, falling into the existing zero-and-flag-silence path. Required adding a four-line additive try_lock() to detail/shared/spinlock.h; no existing behaviour changes.

3. Preset publication (#552). Note the issue text is misleading: the isComplete() gate it asks for already existed (b187f89, before the issue was filed). The actual defect is that rebuildPresetCache() still filled the cache from the partial list and numbered it, merely flagging it unbuilt. Since stable_sort runs only at the end of the crawl, a host reading mid-crawl saw names against numbers that resolve elsewhere once the sort lands. The cache now stays empty until the crawl completes, matching what PD-2/PD-4 (9617822) settled for VST3.

Follow-on, deliberately not fixed here: Plugin::start_processing() also returns a bool that is ignored, so a plugin that activates but refuses to start processing still gets _initialized = true and a process() call. Fixing that needs a second (processing) state, since stop_processing() would then be illegal too. Same family as #549, but not what it describes — worth its own issue.

Build-gated on clap-first-distortion_auv2 after each commit, clean. Not yet run through auval.

…t be deactivated twice

activateCLAP() now propagates clap_plugin.activate()'s failure, and deactivateCLAP() leaves an inactive plugin alone.
…wait on the process lock

Only the offline non-render phases refuse a render now; the input pull gets a copy of the flags, and Render() try_locks instead of spinning behind an idle flush.
rebuildPresetCache() no longer numbers a partial, unsorted list and leaves the cache empty until the index finishes.
@defiantnerd
defiantnerd merged commit d48f9c6 into next Sep 15, 2026
28 checks passed
@defiantnerd
defiantnerd deleted the fix-auv2-activation-render-presets branch September 15, 2026 04:56
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