Route every extension bank-directory lookup through one bankRootOf seam

The pure bankRootFor(rppPath, unsavedRoot) and the shell bankRootOf(ReaProject*) replace eleven hand-rolled .rpp-parent derivations. No unsaved root is supplied yet, so behaviour and refusals are unchanged. Save-As relocation now reads the stored lastBankRoot_.
This commit is contained in:
2026-09-25 14:53:48 -04:00
parent c3e7556261
commit 43994e0d9d
27 changed files with 212 additions and 192 deletions
+1 -1
View File
@@ -48,7 +48,7 @@ Detail specific to these pure modules:
- `wav_codec` — chunk walker + layout parse + float32 build + size-field patch + the lossless mono collapse + content hashes; the single pure RIFF/WAV owner (`wav_trim` is retired; `wav_codec` is the sole owner).
- `capture_realtime` (`core/capture`, **renamed from `realtime_record` in Q-W3** — the Q-9 naming rider: pure module takes the stem, the shell takes the suffix, matching `drag_out`/`drag_out_win`) — the M8 realtime-record pure logic: capture scope + FX-tap point → `I_RECMODE`/`I_RECMODE_FLAGS` values, wet/dry → tap point, the recorded-file → `Sample` mapping, and the async record-phase state machine. Depends on `bank_model` for the plain `Sample`/`SourceMode` types. The transport/temp-track/send recipe lives in the shell (`shell/capture/capture_realtime_shell.cpp` + `capture_realtime_finalize.cpp`).
- `batch_capture` — pure batch-capture planner: maps source ranges to capture units and aggregates results.
- `capture_paths` — the REAPER-free path arithmetic behind offline capture: bank-subfolder + unique-filename derivation (`deriveBankPaths`, forward-slash form, no filesystem touch), the absolute-render-dir vs. project-relative-index-path split (`BankPaths`), the persist-side inverse (`resolveBankFile`, `projectDirOfRpp`), the Save-As bank-relocation plan (`deriveRelocationPlan`), and the GUID-primary project-identity classifier (`classifyProjectTransition` → `NoOp`/`Load`/`SaveAsRelocate`) the persist-poll timer drives.
- `capture_paths` — the REAPER-free path arithmetic behind offline capture: bank-subfolder + unique-filename derivation (`deriveBankPaths`, forward-slash form, no filesystem touch), the absolute-render-dir vs. project-relative-index-path split (`BankPaths`), the persist-side inverse (`resolveBankFile`, `projectDirOfRpp`), the bank-root rule (`bankRootFor(rppPath, unsavedRoot)` — the `.rpp`'s directory, else the unsaved root, else empty, both branches in `normalizeSlashes` form; reached from the extension only through `shell/persist`'s `bankRootOf` seam, while the VST3 instrument still calls `projectDirOfRpp` directly), the Save-As bank-relocation plan (`deriveRelocationPlan`), and the GUID-primary project-identity classifier (`classifyProjectTransition` → `NoOp`/`Load`/`SaveAsRelocate`) the persist-poll timer drives.
- `capture_name` — the REAPER-free composition of one capture's label + file-stem base from its source-track name(s), a local-calendar discriminator (`MM-DD HHMM`, from the shell's clock read), and an optional batch ordinal. The label and the stem deliberately diverge: the stem still passes through `capture_paths::sanitizeStem` (so a name that sanitizes to nothing files as `capture`), while the label keeps the source name verbatim. Stem uniqueness stays entirely `makeUniqueTag`'s — this module never disambiguates.
- `insert_plan` — the REAPER-free logic behind the `insert` shell (M6): computes the `InsertMedia` `mode` bitmask from an `InsertOptions` struct (placement target, tempo-conform ratio, preserve-pitch flag), guaranteeing the &4 stretch-to-time-selection bit is never set and that no tempo bits are set when `conform == None`.
- `render_settings` — the REAPER-free logic behind the capture action family: `SourceMode` → `RENDER_SETTINGS` bit mapping, `P_RAZOREDITS` string parsing + range-union bounds, razor-else-time range inference, the FX-scope bypass plan (`fxBypassPlanFor`), the one bounds mode a capture hands its window over on (`kRenderBoundsTimeSelection`) and the tail bit paired with it (`kTailFlagTimeSelection`), the tail-mode → `RENDER_TAILFLAG`/`RENDER_NORMALIZE`/`RENDER_TRIMEND` mapping (`tailRenderSettingsFor`) and its realtime-window analog (`realtimeRecordWindowEnd`), the capture-action taxonomy table (`captureActionTable`) `main.cpp` iterates to register the CAPTURE_ITEM/CAPTURE_TRACK family, and `renderSourceLabel` (the source named in the offline backend's bounds refusal).
+6
View File
@@ -106,6 +106,12 @@ std::string projectDirOfRpp(const std::string& rppPath) {
return normalizeSlashes(dir);
}
std::string bankRootFor(const std::string& rppPath, const std::string& unsavedRoot) {
const std::string projectDir = projectDirOfRpp(rppPath);
if (!projectDir.empty()) return projectDir;
return normalizeSlashes(unsavedRoot);
}
BankRelocation deriveRelocationPlan(const std::string& oldProjectDir,
const std::string& newProjectDir) {
BankRelocation r;
+8 -2
View File
@@ -1,7 +1,7 @@
#pragma once
// capture_paths — the REAPER-free path arithmetic behind offline capture. The
// capture shell resolves the current project directory via REAPER APIs, then
// hands the raw strings here. Forward-slash form throughout, no filesystem
// shell reads the .rpp path via REAPER APIs and resolves the bank root through
// bankRootFor, then hands the raw strings here. Forward-slash form throughout, no filesystem
// access; the bank subfolder name is a fixed constant.
#include <cstddef>
@@ -87,6 +87,12 @@ std::string resolveBankFile(const std::string& projectDir,
// same way persist does.
std::string projectDirOfRpp(const std::string& rppPath);
// The directory a project's bank lives under: the .rpp's directory when it has one,
// else `unsavedRoot` (where a never-saved project banks), else empty — never a
// default-location fallback. Either branch comes back in normalizeSlashes form, so a
// root compares the same whichever branch produced it.
std::string bankRootFor(const std::string& rppPath, const std::string& unsavedRoot);
// A relocation plan for the physical bank folder on Save-As to a new project
// location. The index's relative paths do NOT change (they are relative to the
// project dir, which moved with the .rpp), so relocation is purely a folder