Files
reasampler/src/core/view/CLAUDE.md
T
daniel 1f24c4b095 docs: 1.0 documentation restructure
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.
2026-07-29 15:09:48 -04:00

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 via ViewModeModel::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_POSITION with 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_LANEPLAYS stays exactly as the user set it. The ownership index rides in "reasampler" view_state alongside 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_LANEPLAYS are 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 — 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.
  • lane_keys — the pure, REAPER-free convention mapping a fixed lane's durable REAPER name (P_LANENAME:n) to the opaque lane-key view_mode_model keys 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/modeIdFromLaneName round-trip a lane name ↔ its owning mode id; isOnManualLane is 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 durable P_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::GuidBaseline must have reset() called on every detected project switch, or the next observe() will diff across two unrelated projects and mass-tag (or miss) content.