diff --git a/CLAUDE.md b/CLAUDE.md index c9e6460..568db5a 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -131,6 +131,12 @@ There is no hot-reload. Copy the built binary into REAPER's `UserPlugins/` folde 3. `rec->Register("hookcommand", ...)` — receives every action fired; claim only your own id, return `false` otherwise. 4. On unload (`rec == nullptr`), mirror-unregister everything with the same strings prefixed by `'-'`. +## Product design docs + +`docs/product/` holds the product-design reasoning behind each phase — the "why we chose this" that predates the spec. They are large and are cited by section from `CONTEXT.md` and `PLAN.md`; **grep for the cited section rather than reading a file whole**. `docs/cmake-cheatsheet.md` is a standalone build-system reference. + +Files: `capture-tail.md`, `code-organization.md`, `design-view.md`, `midi-playback.md`, `multi-bank.md`, `provenance.md`, `removal-and-prune.md`, `versioning-and-release.md`, `visual-design-language.md`. + ## The load-bearing principle **Capture and placement are separate acts.** Capturing audio writes a file to the bank and adds an index entry. It **never** puts an item in the arrange view. Placement is a distinct, on-demand action (`insert` module / `InsertMedia`). Any code path that auto-inserts a capture into the timeline violates the purpose of the tool and **must be rejected in review**. diff --git a/COMPLETED.md b/COMPLETED.md index b263fa5..d68b938 100644 --- a/COMPLETED.md +++ b/COMPLETED.md @@ -248,7 +248,7 @@ membership count visible, offlined-FX caveat surfaced as a tooltip. - [x] Segmented mode switch `[ Arrange | Design ]` in the window header; active lit. - [x] Wire the switch to the toggle/activate actions from D4. - [x] Per-mode membership count display. -- [x] Offlined-FX re-init caveat as a tooltip on the switch. +- [ ] Offlined-FX re-init caveat as a tooltip on the switch. (Not built — no trace in source; did not survive the Phase L panel redesign.) **Notes/decisions:** - New PURE module `src/mode_switch.{h,cpp}` — REAPER-free layout math for the @@ -298,8 +298,9 @@ mass-tag on the first poll after open). **Depends on:** D2-W1. - [x] Apply managed-lane ops in the view shell (`I_FREEMODE`/`I_FIXEDLANE`/ - `C_LANEPLAYS`/`B_FIXEDLANE_HIDDEN` via the item/track info setters; - `UpdateTimeline()` after `I_FREEMODE`); **managed lanes only, never manual**. + `C_LANEPLAYS` via the item/track info setters; `UpdateTimeline()` after `I_FREEMODE`); + **managed lanes only, never manual**. `B_FIXEDLANE_HIDDEN` is read-only per the SDK and + is not written — lane visibility follows from `C_LANEPLAYS`. Verify every flag name/signature against the SDK header. - [x] New-content detection on the bank_panel timer: diff the live track/item GUID set against the previous poll; tag any GUID new since the last poll to the @@ -1450,7 +1451,7 @@ never auto-insert (the buttons only fire the existing, unchanged actions). - **Maintenance cluster restored to top toolbar** (Daniel's directive during L4 build): the initial L4 spec described the top toolbar as "capture + placement" only; the landed implementation includes re-capture and cancel-realtime in a Maintenance cluster on the same - top toolbar. CONTEXT.md and CLAUDE.md updated to reflect the actual layout. + top toolbar. CLAUDE.md updated to reflect the actual layout. - New pure module `src/footer_bar.{h,cpp}`: footer layout/hit-test (narrow mode toggle + Tail button + Prune); no LICE or REAPER types. New CTest target `footer_bar_tests`. - `action_bar` gained `ActionCluster::Tagging` and `ActionCluster::Switching` for the @@ -1913,7 +1914,7 @@ default. The keyboard-strip drag machinery is still built here, but in service o capture-first layout. All layout/hit-test math is **pure geometry** (new `keyboard_strip` + a `capture_browser` layout module — mirrors of `mode_switch`/`editor_geometry`); the LICE draw + drag-state machine is the editor shell. RT discipline untouched (edits commit -off-thread via `commitMapAndReload`); the instrument stays a **read-only bank consumer**. +off-thread via `commitAndReload`); the instrument stays a **read-only bank consumer**. CONTEXT-ARCHIVE.md §Phase S (ReaSampler 9000 UX — capture-first editor). **Policy reversal — fresh instance is SILENT, nothing auto-selected (was S4).** The S4 @@ -1975,7 +1976,7 @@ source of drawing). The drag machine's `WM_MOUSEMOVE` tracking also lights the k boundary rounding). Mirror of `mode_switch`/`editor_geometry`. - [ ] Editor shell drag-state machine: `WM_LBUTTONDOWN` grabs a card / a key / a zone edge-or-body, `WM_MOUSEMOVE` updates the in-flight edit against the pure resolver, - `WM_LBUTTONUP` commits via the existing `commitMapAndReload` (off-thread reload; RT path + `WM_LBUTTONUP` commits via the existing `commitAndReload` (off-thread reload; RT path untouched). Live visual feedback while dragging; a single undo-coherent edit on release. ### S10-Z — Zones panel (opt-in multi-zone keymap editing; demoted from the default face) @@ -2000,7 +2001,7 @@ the next held note); zone add/select/delete work; the ±1 nudge row is gone. residual). - [ ] Zone edit via the shared strip: draw the keyboard strip + zone bars in LICE, drive the shared drag-state machine (edge = resize, body = move, key = root), commit via - `commitMapAndReload`. Zone add/select/delete as single affordances; ±1 nudge row gone. + `commitAndReload`. Zone add/select/delete as single affordances; ±1 nudge row gone. --- @@ -2043,7 +2044,7 @@ zero-crossing snap is a small pure helper over the decoded PCM. house style; draw the loop markers over it. Reuses the S10 drag-state machine. - [ ] Loop-point edit → performance-map override: a dragged loop writes a per-zone loop override (seeded from the S2 bank intrinsic, D-B), committed off-thread via - `commitMapAndReload`; the bank intrinsic is never written back (instrument is a read-only + `commitAndReload`; the bank intrinsic is never written back (instrument is a read-only bank consumer). Extends `PerformanceZone` with an optional loop override (additive, same shape as `rootOverride`) + its component-state (de)serialize (version bump, back-compat with S5's v2 map blob — a truncated/older blob defaults the override absent). @@ -2174,9 +2175,9 @@ Gate/ADSR behavior is unchanged when hold=0 (regression). `PerformanceZone` the mode + params attach to), S11 (Gate loop-point UI; Trigger's waveform shows start + %-length + fades on the same waveform surface). Independent of S7. -- [x] Core: `PlayMode { Gate, Trigger }` on the voice + the envelope split. **Gate** grows - `AdsrParams` → `AhdsrParams` (add `holdFrames` between attack and decay; hold=0 is the - exact current ADSR — back-compat). **Trigger** is a distinct envelope: play `[start, +- [x] Core: `PlayMode { Gate, Trigger }` on the voice + the envelope split. **Gate**: `AdsrParams` + gains `holdFrames` in place (AHDSR hold stage between attack and decay; `holdFrames == 0` is + the exact pre-S15 ADSR — back-compat; no type rename). **Trigger** is a distinct envelope: play `[start, start + lengthFraction·(frames−start))` with a **fade-in** ramp (0→1 over `fadeInFrames`) and a **fade-out** ramp (1→0 over `fadeOutFrames` ending at the play-length end), **ignoring note-off** (release is a no-op in Trigger). Fade curve default **equal-power** @@ -2199,7 +2200,7 @@ shows start + %-length + fades on the same waveform surface). Independent of S7. markers** (S11's loop UI); **Trigger** shows **start + %-length end + fade-in/out** handles on the same waveform. A **mode toggle** per capture/zone in the guided setup (S10) / Zones panel (S10-Z). Marker/handle geometry is pure; commits off-thread via - `commitMapAndReload`. The instrument stays a **read-only bank consumer**. **Editor control + `commitAndReload`. The instrument stays a **read-only bank consumer**. **Editor control surface deferred to S12 tier (spec-sanctioned).** --- @@ -2324,9 +2325,11 @@ save/reopen rebinds by the correct UID; nothing plays differently (identity/pair **Depends on:** V4 (`app_version` channel-identity single-source), S1 (VST3 factory identity). - [x] **Beta VST3 class UID (the permanent commitment).** Second FOREVER-STABLE class UID - (`REASAMPLER_PROC_UID_BETA_1..4` + `kReaSamplerProcessorUIDBeta`) alongside the existing - stable UID in `reasampler_vst.h`. The channel bit selects which UID the factory registers - (`DEF_CLASS2`) — compile-time, one class per binary. Both UIDs frozen forever. + (`REASAMPLER_PROC_UID_BETA_1..4`) alongside the existing stable UID in `reasampler_vst.h`. + A `#if REASAMPLER_CHANNEL_IS_BETA` block selects `REASAMPLER_ACTIVE_UID_*`, which feeds the + single `kReaSamplerProcessorUID` — no separate beta-named constant. The channel bit selects + which UID the factory registers (`DEF_CLASS2`) — compile-time, one class per binary. Both UIDs + frozen forever. - [x] **Channel-derived binary + display identity (no scattered `#ifdef`s).** Binary name: CMake VST3 target `OUTPUT_NAME` forks by channel — `reasampler_9000` (stable) / `reasampler_9000_beta` (beta) — via `REASAMPLER_VST_OUTPUT_NAME`. Display name: factory diff --git a/CONTEXT-ARCHIVE.md b/CONTEXT-ARCHIVE.md index 61490e3..a2f4207 100644 --- a/CONTEXT-ARCHIVE.md +++ b/CONTEXT-ARCHIVE.md @@ -564,7 +564,7 @@ where RS5K is one-shot, and bank-integrated ingest where RS5K is file-at-a-time. change — D-A settled); **all layout/hit-test math in pure geometry modules** (mirror of `mode_switch` / `editor_geometry` / `embed_strip`), the draw + drag-state machine in the shell; RT discipline untouched (every edit commits **off** the audio thread via the -existing `commitMapAndReload` → off-thread `reloadFromBank` → atomic swap); the instrument +existing `commitAndReload` → off-thread `reloadFromBank` → atomic swap); the instrument stays a **read-only bank consumer** (loop/root/ADSR edits are the instrument's *performance map*, D-B — never written back to the bank); component-state persistence and read-only-over-bank stay settled. diff --git a/CONTEXT.md b/CONTEXT.md index 74048c3..e2667d1 100644 --- a/CONTEXT.md +++ b/CONTEXT.md @@ -1027,7 +1027,7 @@ S10's single-capture setup surface shape. markers**; Trigger shows **start + %-length end + fade-in/out** handles — same waveform, same pure `frame↔pixel` + marker-grab geometry module (S11), mode switches which markers draw. A **mode toggle** per capture/zone sits in the S10 guided setup / S10-Z Zones panel. Every edit -commits **off-thread** via `commitMapAndReload`; the instrument stays a **read-only bank +commits **off-thread** via `commitAndReload`; the instrument stays a **read-only bank consumer** (mode/params are performance map, never written to `Sample` or the bank). ### Pitch engine modes — Varispeed vs Preserve (S16) @@ -1876,7 +1876,7 @@ face without scrolling, and cannot be resized below the constraint floor. compat surface in S-VIEW and is the substance of fork R10-F1. `keyTrack` and `previewVelocity` remain fully bit-identical on lift. No existing field changes. - **RT discipline (unchanged).** The preview-trigger fires a note through the existing voice engine - via the off-audio-thread commit path (`commitMapAndReload` idiom); no new `process`-thread work, + via the off-audio-thread commit path (`commitAndReload` idiom); no new `process`-thread work, no allocation on the audio thread. - **VST3 class UID unchanged.** A view reorganization + additive param is **not** a compat event; saved instances rebind and restore. The UID stays the S-NAME-1/S18 forever-locked identity. @@ -1919,7 +1919,7 @@ preview velocity **persists** via envelope-v6 `ComponentState`; the envelope ove - **Drop-to-FX** — `TrackFX_AddByName` / `TrackFX_SetNamedConfigParm` / `GetThingFromPoint` all **verified present** in `reaper_plugin_functions.h`; the remaining work is **runtime diagnosis** (name match, gesture routing, blob format), not an SDK question. -- **Preview note through the voice engine off-thread** — confirm the existing `commitMapAndReload` +- **Preview note through the voice engine off-thread** — confirm the existing `commitAndReload` / off-thread reload idiom is the right seam to fire a one-shot preview note without touching `process` on the UI thread; no torn state on the atomic voice-engine pointer. - **Preview-velocity persistence seam (S-VIEW-F1)** — the envelope-v6 `ComponentState` field is the