1f24c4b095
Split root CLAUDE.md into 19 per-directory files scoped to their source area. Roll v0 history into docs/ARCHIVE.md; retire CONTEXT.md, CONTEXT-ARCHIVE.md, PLAN.md, COMPLETED.md. Move plan docs under docs/. Rescue 9 live deferrals into docs/TODO.md.
7.3 KiB
7.3 KiB
src/core/view — pure Design View mode model
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.
Invariants
Design View — additive phase spec (settled decisions; Two-canvas sub-phase, settled 2026-07-23):
- Membership. Default = Arrange; every untagged leaf belongs to it. Leaves opt in to Design (or any mode). No track appears in two modes at once except via an explicit show-both toggle or parent/folder derivation.
- Parents are derived, never tagged. A parent/folder track is visible in mode M if either any descendant leaf is visible in M, or the parent belongs to M by its own membership; an untagged parent is an Arrange member by default. A parent is never parked in any mode it is visible in. Master track is always visible and never touched.
- N-mode model, two-mode UI. The data model carries arbitrarily many modes; the UI ships Arrange + Design. A mode is (stable id, display name, ordinal).
- Persistence. Membership index + last-active mode + per-track flag
snapshots ride in the existing
"reasampler"project ext-state namespace and travel with the.rpp. - Non-destructive restore (enforced in the pure layer). For every flag the tool drives, snapshot the prior value before parking; on toggle-back, restore 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.
- GUID-keyed, reorder-safe. Membership keys on track GUID (
GetTrackGUID), never track index; tolerates unknown/stale GUIDs (pruned on reconcile viaViewModeModel::reconcile(liveGuids)). - Relative/portable state only in the persisted view section (GUID strings, mode ids — no absolute paths, no index positions).
- Show-both semantics. A per-track "pin visible across modes" flag that re-enables processing whenever shown. A show-both leaf appears in every mode's visible set and is never parked — its driven flags stay at snapshot/restored values. Stored on the membership record; persists; togglable per selection.
- Non-goals / guardrails: No literal second canvas — a second window or
duplicated project stays rejected; subproject/second-project-file approaches
and overloading item
D_POSITIONwith mode semantics (timebase-offset regions) are rejected paths (the latter collides with the capture null test). Every leaf is managed: an untagged leaf is an Arrange member and, when the active mode is not Arrange, is fully parked and snapshot-restored exactly like a tagged leaf; show-both is the only way to opt a leaf out of parking. Restore from snapshot, never to a default: no hardcoded "on" restores.
Two-canvas sub-phase (Phase D2/E) — settled and landed parts only:
- Mechanism: fixed item lanes. Map mode → lane; toggle drives per-lane play/show so only the active mode's lane is present. Items keep their real position and real track — nothing is moved in time or deleted.
- Membership: adoption rule for new items; active mode for new tracks. New tracks are tagged to the active mode at creation. New items follow an adoption rule: if the item's track has pre-existing managed-eligible content spanning exactly one mode, the item adopts that mode; the active-mode fallback applies only when the track is empty or already spans multiple modes. Items in manual lanes are excluded from the prior-mode computation and are not auto-tagged at all. Membership is exclusive per item except via show-both.
- Managed vs. manual lanes — indexed and distinct. The tool maintains a
lane-ownership index — per (track GUID, lane): managed (which mode owns it)
vs. manual (user-minted, outside the mode system). Mode operations touch only
managed lanes; manual lanes are never shown, hidden, silenced, or re-laned by
a toggle, and their
C_LANEPLAYSstays exactly as the user set it. The ownership index rides in"reasampler"view_statealongside the membership index, GUID-keyed and portable. New invariant — mode operations touch only managed lanes: "the 'which lanes may this toggle touch' decision is a pure query over the ownership index; only reading REAPER's live lane state is shell." - REAPER floor: v7 for this sub-phase (fixed lanes shipped in v7); no version-gate branch — below v7 the sub-phase is simply unavailable.
- Precision invariants (null test, bit-identical repeats, non-destructive,
exact bounds, relative-paths-only) are entirely unaffected by this
sub-phase — no capture path changes; lane assignment and
C_LANEPLAYSare reversible flags, never a destructive operation.
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_tree— pureI_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 incurrentbut absent fromprevious(empty GUIDs ignored);GuidBaselinetracks the live GUID set across polls for one project, implementing the first-poll-after-open guard (the firstobserve()after construction/reset()records a baseline and reports nothing new, so pre-existing content is never mass-tagged) and re-arms viareset()on a detected project switch so detection never diffs across two unrelated projects.lane_keys— the pure, REAPER-free convention mapping a fixed lane's durable REAPER name (P_LANENAME:n) to the opaque lane-keyview_mode_modelkeys by, plus the managed/manual heuristic both the toggle-apply path and the new-content/auto-tag exemption path share:kManagedLanePrefix("reasampler:") stamps every lane the tool mints;isManagedLaneName/managedLaneKey/laneNameForMode/modeIdFromLaneNameround-trip a lane name ↔ its owning mode id;isOnManualLaneis the single predicate governing which lanes a toggle may drive and which items are exempt from auto-tag.
Gotchas
- REAPER exposes no durable per-lane GUID — the only lane identity is the
ordinal
I_FIXEDLANE, which REAPER renumbers on reorder/delete. Lane identity must ride on the durableP_LANENAME(lane_keys), never the raw ordinal, or a reorder will silently corrupt managed/manual ownership. kManagedLanePrefix("reasampler:") is stable-forever like an action-id string — changing it strands the ownership of every already-minted lane in every already-saved project.guid_diff::GuidBaselinemust havereset()called on every detected project switch, or the nextobserve()will diff across two unrelated projects and mass-tag (or miss) content.