Bound the automation hold to the window the model has not caught up on, and make that authority model stated, enforced and tested
This commit is contained in:
+27
-7
@@ -1270,7 +1270,13 @@ value semantics, any deck geometry, or the bake's reset *membership* (W3-T2's).
|
||||
`stepCount` is asserted **zero on all 44**.
|
||||
- **A host automation lane moving a Live parameter moves a sounding note; a lane moving a
|
||||
NoteOnLatched parameter takes effect on the next note and does NOT trigger a reload or an
|
||||
engine rebuild** — assert the tier, not just the sound.
|
||||
engine rebuild** — assert the tier, not just the sound. All three NoteOnLatched controls now
|
||||
have a delivery test in `tests/test_live_delivery.cpp` (rate, key-track, Trigger length), each
|
||||
asserting BOTH halves: the sounding note byte-identical, the next note taking the value.
|
||||
- **A host automation point's AUTHORITY IS BOUNDED**, and its release is where both review passes
|
||||
went wrong: it outranks the model only until the UI thread has folded it in and republished.
|
||||
`shell/instrument/CLAUDE.md`'s Authority section states the model, `param_merge` enforces it,
|
||||
`test_param_merge` fails if a hold is never released or is released too early.
|
||||
- **No automation path reaches `reloadInstrument` or `rebuildVoiceEngine`.**
|
||||
- **A project saved before this change opens with every parameter reading the blob's value
|
||||
and sounds identical**; a project saved by this build opens in an older binary with its
|
||||
@@ -1309,10 +1315,23 @@ value semantics, any deck geometry, or the bake's reset *membership* (W3-T2's).
|
||||
`ProcessData::inputParameterChanges` in `process()` while also implementing
|
||||
`setParamNormalized`. **Both are serviced.** This was never a DAW question — the headers
|
||||
answer it, and building on the paragraph alone is exactly what the first pass did.
|
||||
(b) The ORDERING of `setState` against the first parameter block: no longer a question. An
|
||||
automation point held by the audio thread is re-applied over every merge, so a written lane
|
||||
outranks the restore whichever way round the two arrive — VST3's own rule. What survives as
|
||||
DAW work is recorded in `docs/TODO.md`, and none of it can change the frozen contract.
|
||||
(b) The ORDERING of `setState` against the first parameter block: no longer a question, but not
|
||||
for the reason the second pass gave. A point held by the audio thread is re-applied over every
|
||||
merge only until the UI thread has folded it into the model — the hold is bounded, and a lane
|
||||
that is genuinely DRIVING re-sends and so keeps outranking the restore, while a lane that sent
|
||||
one point and had it folded does not. That is the correct reading of the rule "a lane in
|
||||
read/write mode outranks a plug-in-side set" (stated in `docs/product/parameter-automation.md`
|
||||
§7 as reasoning from the host's replay behaviour, not from a header — the SDK does not spell it
|
||||
out). The second pass's unbounded latch made the claim true by making every later writer
|
||||
permanently deaf; `shell/instrument/CLAUDE.md`'s Authority section is the model now.
|
||||
(c) **STILL OPEN, and it is the half the bundled `[verify, FIRST]` originally asked**: that
|
||||
REAPER calls `setState` (not `setComponentState`) on a single-component plug-in — a state
|
||||
ENTRY-POINT question, not a delivery-channel one. Recorded in `docs/TODO.md` rather than closed:
|
||||
`vstsinglecomponenteffect.h:41-47` does collapse the names as §6.1 claims, our overrides land on
|
||||
the `IComponent` pair with `setEditorState`/`getEditorState` left at the base's `kNotImplemented`,
|
||||
and the blob has shipped through payload v1…v16, so the behaviour is very likely fine — but that
|
||||
is inference, not observation. The rest of the DAW work is in `docs/TODO.md` too, and none of it
|
||||
can change the frozen contract.
|
||||
- **[verify]** whether REAPER renders `ParameterInfo::units` beside the string
|
||||
`getParamStringByValue` returns, or shows the string alone. **We ship the SDK's own
|
||||
convention** — digits in the string, unit carried separately, which is what
|
||||
@@ -1328,8 +1347,9 @@ value semantics, any deck geometry, or the bake's reset *membership* (W3-T2's).
|
||||
structurally could not see it and id 1000 would have no-oped in both directions with no
|
||||
compile-time guard; both controls also had to reach the engine, which meant widening
|
||||
`LiveValues` and `foldLive`'s input and handing `Voice::start` the two latched values as
|
||||
arguments beside the rate. The guard that closes the class is `param::valueHomeFor`, asserted
|
||||
over the exposed set.
|
||||
arguments beside the rate. The guard that closes the class is `param::valueHomeFor` — asserted
|
||||
over the exposed set (every control has a home, the instance-scalar set has exactly two
|
||||
members) AND branched on by the shell's own read and write paths, so the three cannot drift.
|
||||
- **[propose at review]** whether to ship a default `IMidiMapping` CC table here or leave MIDI
|
||||
control to REAPER's host-side learn. Either is defensible; **skipping it silently is not.**
|
||||
- **[propose at review]** whether this track spends the reserved payload rung. §6.1 says
|
||||
|
||||
Reference in New Issue
Block a user