2d040d6896
Rename view_model -> view_mode_model across Design View spec docs; archive D1 to COMPLETED.md; add view_mode_model_tests to CLAUDE.md targets table and pure-core list.
191 lines
9.7 KiB
Markdown
191 lines
9.7 KiB
Markdown
# PLAN.md — ReaSampler milestone roadmap
|
||
|
||
Living milestone roadmap for ReaSampler. Derived from CONTEXT.md's 11-step build
|
||
order; CONTEXT.md remains the authoritative spec — this file is the tickable
|
||
checklist, not a re-statement of the spec. When a point lands, doc-keeper removes
|
||
it here and appends it to `COMPLETED.md`.
|
||
|
||
**Conventions**
|
||
- One checkbox `- [ ]` = one discrete, independently-landable point.
|
||
- Each milestone opens with a **Goal** (one line) and a **Verify** criterion
|
||
(the acceptance gate; precision invariants pulled in where one applies).
|
||
- Verify-in-DAW points require a manual REAPER run; pure points are gated by CTest.
|
||
- "See CONTEXT.md §…" points at the authoritative detail — do not duplicate it here.
|
||
|
||
---
|
||
|
||
## Milestone 5 — bank_panel (docked grid)
|
||
**Goal:** Docked LICE-drawn grid: thumbnails (from `peaks`), audition,
|
||
multi-select, keyboard navigation. Reuses the docking setup from the retired
|
||
`mpe_view.cpp`. CONTEXT.md §bank_panel.
|
||
**Verify (in DAW):** Grid docks; thumbnails render from computed peaks; audition
|
||
plays selected sample; multi-select + keyboard nav work.
|
||
|
||
- [ ] Docked window + LICE grid render loop.
|
||
- [ ] Thumbnail draw from `peaks` bins.
|
||
- [ ] Audition (play selected sample) + stop.
|
||
- [ ] Multi-select + keyboard navigation.
|
||
|
||
## Milestone 6 — insert (placement)
|
||
**Goal:** "Insert selected sample at edit cursor" via `InsertMedia`. CONTEXT.md
|
||
§insert, Build order 6.
|
||
**Verify (in DAW):** Selected sample inserts at the edit cursor wrapped in
|
||
`Undo_BeginBlock2` / `Undo_EndBlock2`; conform-to-tempo is an explicit flag —
|
||
**no silent time-stretch** when off.
|
||
|
||
- [ ] `InsertMedia(path, mode)` at edit cursor (verify mode bits against SDK).
|
||
- [ ] Conform-to-project-tempo vs literal as an explicit flag (never silent).
|
||
- [ ] Undo-block wrapping.
|
||
|
||
## Milestone 7 — capture action family
|
||
**Goal:** Bindable capture actions for master / selected tracks / selected items /
|
||
razor area, each with wet-dry + tail options. CONTEXT.md §actions, Build order 7.
|
||
**Verify (in DAW):** Each action registered (bindable in Actions list), routes to
|
||
the offline backend, and honors wet/dry + tail. **Load-bearing principle:** none
|
||
auto-inserts into the arrange.
|
||
|
||
- [ ] Source resolvers: master mix, selected tracks, selected items, razor area
|
||
(`GetSet_LoopTimeRange`, `P_RAZOREDITS`, `CountSelectedMediaItems`, etc.).
|
||
- [ ] Register each as a bindable action (`command_id`/`gaccel`/`hookcommand`).
|
||
- [ ] Wet-dry + tail options per action.
|
||
- [ ] Review gate: confirm no capture path touches the timeline.
|
||
|
||
## Milestone 8 — RealtimeRecordBackend
|
||
**Goal:** Realtime record behind the same `ICaptureBackend`, producing identical
|
||
bank entries. CONTEXT.md §capture (realtime), §Precision invariants.
|
||
**Verify (in DAW):** Hidden temp track resamples wet output; recorded file moves
|
||
into the bank; **non-destructive** — temp track removed cleanly, source routing
|
||
and user monitoring restored unchanged.
|
||
|
||
**Note (from M3):** The realtime backend captures during playback and does NOT invoke the offline-render path, so it is inherently dialog-free (no render-progress window) — a secondary benefit beyond hardware/performed-FX capture.
|
||
|
||
- [ ] Hidden-track resample recipe (`I_RECMODE`/`I_RECINPUT`/`I_RECARM`,
|
||
`CSurf_OnRecord`/`CSurf_OnStop`); verify record-mode values against SDK.
|
||
- [ ] Resolve wet-master routing that does not alter user monitoring (open
|
||
question).
|
||
- [ ] Move recorded source into bank; populate identical `Sample`; clean teardown.
|
||
|
||
## Milestone 9 — slots (MPC-style)
|
||
**Goal:** "Capture to slot N" / "insert slot N", MIDI-bindable. CONTEXT.md
|
||
Build order 9.
|
||
**Verify (in DAW):** Slot capture and slot insert fire from MIDI bindings; slot
|
||
state persists via the index.
|
||
|
||
- [ ] Slot model + slot↔sample assignment.
|
||
- [ ] "Capture to slot N" / "insert slot N" actions, MIDI-bindable.
|
||
|
||
## Milestone 10 — provenance + null-test verify action
|
||
**Goal:** Provenance (parent sample id + FX-chain snapshot) and "re-capture from
|
||
source"; ship the null-test verification action. CONTEXT.md §Precision invariants,
|
||
Build order 10.
|
||
**Verify (in DAW):** **Null test** — a dry offline capture of a range, re-inserted
|
||
at its source position, nulls to silence against the source. This action is the
|
||
tool's trust anchor and must pass.
|
||
|
||
- [ ] Provenance fields populated on resample-from-sample (parent id + FX-chain
|
||
snapshot string).
|
||
- [ ] "Re-capture from source" action.
|
||
- [ ] Null-test verification action (capture → re-insert at source pos → assert
|
||
silence sum).
|
||
|
||
## Milestone 11 — polish
|
||
**Goal:** Batch capture (per selected item / per razor area),
|
||
resample-and-mute-source, conform-on-insert, native OS drag-out. CONTEXT.md
|
||
Build order 11, §Non-goals (drag-out deferred to last).
|
||
**Verify (in DAW):** Each polish action works without regressing the precision
|
||
invariants; drag-out places a valid file in the OS target.
|
||
|
||
- [ ] Batch capture: per selected item / per razor area.
|
||
- [ ] Resample-and-mute-source.
|
||
- [ ] Conform-on-insert (explicit).
|
||
- [ ] Native OS drag-out (deferred final; `InsertMedia` path must already work).
|
||
|
||
---
|
||
|
||
## Open questions to resolve during build
|
||
Carried from CONTEXT.md §Open questions — keep visible until each is closed by a
|
||
landed milestone.
|
||
|
||
- **Realtime wet-master routing** that captures master output without altering the
|
||
user's monitoring. (blocks M8)
|
||
- **Thumbnail cache:** recompute peaks vs store peak bins alongside the index.
|
||
(touches M2/M4/M5)
|
||
- **`parseInt` narrowing hardening:** `src/bank_model.cpp` `parseInt` casts
|
||
`int64_t → int` via `static_cast` without a range check; integers that fit
|
||
in int64 but exceed `INT_MAX` are implementation-defined. Hardening candidate
|
||
— add bounds check before the cast when integer-field validation is in scope.
|
||
|
||
---
|
||
|
||
# Phase D — Design View (parallel to the M0–M11 capture roadmap)
|
||
|
||
> **Separate phase namespace.** The M-numbers belong to the capture pillar
|
||
> (M0–M11, M4 in flight). Design View is an orthogonal feature on its own track,
|
||
> so it uses a **lettered** namespace (D1, D2, …) rather than extending the M-line.
|
||
> This keeps the two roadmaps from colliding on numbering and reads correctly:
|
||
> Phase D is not "the twelfth capture step," it's a different pillar. Authoritative
|
||
> spec: **CONTEXT.md §Design View**. Product framing: `docs/product/design-view.md`.
|
||
> When a point lands, doc-keeper moves it to `COMPLETED.md`.
|
||
|
||
## D2 — view shell (apply flags in the DAW)
|
||
**Goal:** Read the folder tree and drive REAPER flags per the planner.
|
||
CONTEXT.md §Design View (view shell, REAPER API surface).
|
||
**Verify (in DAW):** Toggling active mode hides + parks inactive leaves
|
||
(`B_SHOWINTCP`/`B_SHOWINMIXER`/`B_MAINSEND`/`I_FXEN` + per-FX offline) and restores
|
||
active ones from snapshot. **Master untouched. `B_MUTE`/`I_SOLO` untouched.**
|
||
Untagged tracks untouched. Parents follow their tagged descendants.
|
||
|
||
- [ ] Build parent↔child tree from `I_FOLDERDEPTH`; feed to `view_mode_model`.
|
||
- [ ] Snapshot prior flag values (`GetMediaTrackInfo_Value`) before parking.
|
||
- [ ] Apply park/restore ops (`SetMediaTrackInfo_Value` for the four flags;
|
||
`TrackFX_GetCount` + per-FX `TrackFX_SetOffline`). Verify flag names/signatures.
|
||
- [ ] GUID resolution: `GetTrackGUID` / `guidToString` / `stringToGuid` (never index).
|
||
- [ ] Review gate: no path touches master visibility or `B_MUTE`/`I_SOLO`, or any
|
||
untagged track's owned flags.
|
||
|
||
## D3 — persist slice (view state ↔ project ext state)
|
||
**Goal:** Serialize the view section into the `"reasampler"` namespace alongside the
|
||
bank; reapply the active mode on project open. CONTEXT.md §Design View (persist).
|
||
**Verify (in DAW):** Membership + active mode + snapshots survive Save / Save As /
|
||
close+reopen; on open, the active mode's visibility + processing is reapplied.
|
||
Saved-while-parked project restores parked tracks from persisted snapshots (not to a
|
||
guessed "on").
|
||
|
||
- [ ] Serialize/deserialize the view section under `"reasampler"` (shared blob,
|
||
distinct section from the bank index).
|
||
- [ ] Reapply active mode on project open (rebuild tree, run the planner).
|
||
- [ ] Confirm survival across Save / Save As; snapshot durability across
|
||
save-while-parked.
|
||
|
||
## D4 — actions
|
||
**Goal:** Bindable action set for the mode workflow. CONTEXT.md §Design View
|
||
(actions). **Verify (in DAW):** Each action registered (bindable in Actions list);
|
||
toggle + mode-jumps MIDI-bindable; tag/untag acts on the current track selection.
|
||
|
||
- [ ] Toggle active mode (cycle; extensible to cycle-all for >2 modes).
|
||
- [ ] Activate mode: Arrange / Activate mode: Design (direct jumps).
|
||
- [ ] Tag selected tracks → Design / → Arrange; Untag selected (= → Arrange).
|
||
- [ ] Show-both for selected tracks (toggle).
|
||
- [ ] Register each (`command_id`/`gaccel`/`hookcommand`); toggle + jumps MIDI-bindable.
|
||
|
||
## D5 — in-window toggle affordance (UI)
|
||
**Goal:** The segmented mode switch in the ReaSampler / bank_panel window header.
|
||
CONTEXT.md §Design View (UI). **Verify (in DAW):** Segmented control shows current
|
||
mode (lit segment), one click flips modes via the D4 toggle action, per-mode
|
||
membership count visible, offlined-FX caveat surfaced as a tooltip.
|
||
|
||
- [ ] Segmented mode switch `[ Arrange | Design ]` in the window header; active lit.
|
||
- [ ] Wire the switch to the toggle/activate actions from D4.
|
||
- [ ] Per-mode membership count display.
|
||
- [ ] Offlined-FX re-init caveat as a tooltip on the switch.
|
||
|
||
## Phase D open questions
|
||
- **Snapshot durability across save-while-parked** — persisted here by decision;
|
||
lean alternative is force-restore-to-Arrange on save (product notes item 4).
|
||
(touches D3)
|
||
- **Reconcile on delete/restructure** — tagged leaf deleted or folder restructured
|
||
while parked leaves a stale GUID; ignore-and-prune on next toggle/open.
|
||
(touches D1/D2)
|
||
- **Screenset coexistence** — Design View drives the same flags a screenset recall
|
||
would; confirm last-writer-wins is not surprising. (touches D2)
|