Ψ-W1-T2: disjoint per-mode solo surfaces and a playback-gated mode switch

Solo is cached, cleared and replayed per mode on a real switch only; the switch is refused visibly while the transport runs. The footer segment now routes through the activate actions, so a panel switch finally persists.
This commit is contained in:
2026-08-01 19:43:18 -04:00
parent 8bf6841f7b
commit 9c234c2e6b
23 changed files with 811 additions and 49 deletions
+15 -7
View File
@@ -3,12 +3,13 @@
## Scope
Pure, REAPER-free Design View model: mode/track membership, folder-derived
visibility, snapshot-based park/restore planning, new-content (GUID) detection,
and the managed/manual lane-identity convention that underlies per-item mode
separation (fixed lanes). Does **not** include: the actual DAW-side flag
application (hide, CPU-park, per-FX offline, restore via `B_SHOWINTCP` /
`B_SHOWINMIXER` / `B_MAINSEND` / `I_FXEN`) or the never-touch-master/mute/solo
enforcement — those live in `shell/view`.
visibility, snapshot-based park/restore planning, the per-mode solo cache and its
replay plan, new-content (GUID) detection, and the managed/manual lane-identity
convention that underlies per-item mode separation (fixed lanes). Does **not**
include: the actual DAW-side flag application (hide, CPU-park, per-FX offline,
restore via `B_SHOWINTCP` / `B_SHOWINMIXER` / `B_MAINSEND` / `I_FXEN`, solo
cache/clear/replay via `I_SOLO`) or the never-touch-master/mute enforcement —
those live in `shell/view`.
## Invariants
@@ -33,6 +34,12 @@ settled 2026-07-23):
from the snapshot, never to a hardcoded default. Round-trip (snapshot → park →
restore) returns every driven flag to its captured value — this is the
phase's trust anchor, the analog of the capture null test.
- **Disjoint solo surfaces, cached not destroyed.** Solo is per mode: a real
switch banks the outgoing mode's raw `I_SOLO` values, clears them, and replays
the incoming mode's verbatim. Same snapshot sense of non-destructive as the
bullet above — the tool never *loses* the user's solo, it parks it with the mode
it belongs to. `B_MUTE` and the master track stay untouched absolutely. A
reapply touches solo not at all.
- **GUID-keyed, reorder-safe.** Membership keys on track GUID (`GetTrackGUID`),
never track index; tolerates unknown/stale GUIDs (pruned on reconcile via
`ViewModeModel::reconcile(liveGuids)`).
@@ -84,7 +91,8 @@ settled 2026-07-23):
## Modules
- `view_mode_model` — Design View mode system: mode registry, GUID-keyed membership, folder-tree-aware visibility derivation, snapshot-based park/restore planner, JSON round-trip.
- `view_mode_model` — Design View mode system: mode registry, GUID-keyed membership, folder-tree-aware visibility derivation, snapshot-based park/restore planner, the per-mode `SoloCache` it owns, JSON round-trip.
- `solo_cache` — the per-mode solo surface: `SoloCache` (mode id → GUID → raw `I_SOLO`), the soloed-subset filter, and `planSoloRestore`, whose two drop rules (dead GUID, track parked in the incoming mode) and their reasoning live in its header.
- `view_tree` — pure `I_FOLDERDEPTH`→FolderTree helper for the Design View shell.
- `mode_switch` — REAPER-free segment layout + hit-test for the bank_panel's Design View mode switch.
- `guid_diff` — the pure, REAPER-free core of the D2 Wave-2 new-content detection: `newGuids(previous, current)` computes the GUIDs present in `current` but absent from `previous` (empty GUIDs ignored); `GuidBaseline` tracks the live GUID set across polls for one project, implementing the first-poll-after-open guard (the first `observe()` after construction/`reset()` records a baseline and reports nothing new, so pre-existing content is never mass-tagged) and re-arms via `reset()` on a detected project switch so detection never diffs across two unrelated projects.