Refuse to park a track whose pre-park snapshot is gone, rather than re-snapshotting the already-parked chain as the user's state
This commit is contained in:
@@ -30,6 +30,15 @@ decide membership or mode rules.
|
||||
(hide both panels), `B_MAINSEND=0` (out of mix), `I_FXEN=0` (FX bypassed), and
|
||||
`TrackFX_SetOffline(track, fx, true)` for each FX (reclaim CPU) — full CPU-park,
|
||||
not mix-removal-only.
|
||||
- **A snapshot is only ever taken from a chain no park has touched.** An absent
|
||||
snapshot is NOT evidence of a clean chain — `discardDeferredFxParks` drops
|
||||
intents whose flag writes already landed, so a reloaded model and an
|
||||
already-parked project routinely coexist. A park meeting that pair REFUSES:
|
||||
no flag write, no FX-offline enqueue, no snapshot, and one console line naming
|
||||
the hand recovery. Leaving the track as found is the only non-destructive
|
||||
answer once the pre-park truth is gone — snapshotting there would record park
|
||||
state as the user's state and every later restore would faithfully write it
|
||||
back. Decision at `view_fx_park`'s `decidePark`.
|
||||
- **Non-destructive restore.** For every flag the tool drives, snapshot the prior
|
||||
value BEFORE parking; on toggle-back restore FROM the snapshot, never to a
|
||||
hardcoded "on." Round-trip (snapshot → park → restore) returns every driven flag
|
||||
@@ -107,7 +116,7 @@ applies the resulting lane state to live tracks.
|
||||
## Modules
|
||||
|
||||
- `view` — Design View shell: snapshots flag values before parking, drives hide + CPU-park on inactive-mode leaves (`B_SHOWINTCP`/`B_SHOWINMIXER`/`B_MAINSEND`/`I_FXEN`, with per-FX offline deferred to `view_fx_park`), restores from snapshot. Owns the one discriminator (`target != active`) that separates a real switch from a reapply, and with it both the playback gate (`transportBlocksModeSwitch`) and the solo cache/clear/restore seams. **Never touches master or `B_MUTE`.**
|
||||
- `view_fx_park` — the per-FX offline surface: the `TrackFX_GetFXGUID` identity read snapshot/park/restore share, the deferred intent queue that keeps `TrackFX_SetOffline` off the switch's synchronous path (at most one intent per track GUID, latest wins, an intent landing on its own pending inverse cancels it), and the idle-tick drain `main.cpp`'s `OnTimer` calls. **The drain owns no model state.** A snapshot is dropped where the restore is PLANNED — the flags are back at their captured values from that moment, and a model that still described the track as parked would let a persist or a reapply inside the drain window replan a restore over whatever the user changed since. What the deferral costs instead is that the live FX chain stops being a trustworthy snapshot source while an intent is pending: a park that CANCELS a pending restore takes the pre-park FX states from that restore's ops (`preParkFxFromCancelledRestore`), because the chain still reads the parked values and the cancel means no drain will ever fix them.
|
||||
- `view_fx_park` — the park surface: the `TrackFX_GetFXGUID` identity read snapshot/park/restore share, the deferred intent queue that keeps `TrackFX_SetOffline` off the switch's synchronous path (at most one intent per track GUID, latest wins, an intent landing on its own pending inverse cancels it), the idle-tick drain `main.cpp`'s `OnTimer` calls, and the pure per-track park decision (`decidePark` over "does the model hold a snapshot" × "does the chain already read parked", plus `trackFlagParm` — the ONE `Flag` → REAPER-parameter mapping park's live read and restore's write both address). **The drain owns no model state.** A snapshot is dropped where the restore is PLANNED — the flags are back at their captured values from that moment, and a model that still described the track as parked would let a persist or a reapply inside the drain window replan a restore over whatever the user changed since. What the deferral costs instead is that the live FX chain stops being a trustworthy snapshot source while an intent is pending: a park that CANCELS a pending restore takes the pre-park FX states from that restore's ops (`preParkFxFromCancelledRestore`), because the chain still reads the parked values and the cancel means no drain will ever fix them.
|
||||
- `view_solo` — the `I_SOLO` read/write pair behind the per-mode solo surface, plus `clearTrackSolos`/`restoreTrackSolos`, the outgoing-clear and incoming-replay entry points `view` drives them through. Holds no policy: what to cache, clear, or replay is `core/view/solo_cache`.
|
||||
|
||||
## Gotchas
|
||||
@@ -130,7 +139,9 @@ applies the resulting lane state to live tracks.
|
||||
over the reloaded model, re-planning a park for every inactive leaf, so parked
|
||||
FX converge on the following drain. The one case that does not self-heal is a
|
||||
track whose reloaded model carries no snapshot — nothing plans its restore, so
|
||||
FX left offline stay offline. Full contract at `discardDeferredFxParks`.
|
||||
FX left offline stay offline, and its next park REFUSES rather than
|
||||
re-snapshotting the parked chain (snapshot-source invariant above). Stuck, but
|
||||
never falsely committed. Full contract at `discardDeferredFxParks`.
|
||||
- `fx_offline`'s identity keying (`TrackFX_GetFXGUID`) assumes the GUID stays
|
||||
attached to its plugin across a chain mutation while parked. That is
|
||||
`[verify — DAW]` (see `fxGuidString` in `view_fx_park.cpp`) and SWS issue #802 is a
|
||||
|
||||
Reference in New Issue
Block a user