Q-W3: main.cpp → pointers+entry+dispatch via 4 capture hoists; one pure wav_codec RIFF owner; ICaptureBackend deleted; capture_realtime rename + finalize split; shared stampCaptureSample; makeUniqueTag gains monotonic counter (fixes same-second batch collisions). 60/60 green.

This commit is contained in:
2026-07-29 10:56:11 -04:00
parent d7d7f7e084
commit 09f7173db2
29 changed files with 2972 additions and 2426 deletions
+71
View File
@@ -0,0 +1,71 @@
#pragma once
// scope_resolve — scope/source resolution for the capture action family (Q-W3
// hoist out of main.cpp). The three concerns every capture entry point shares:
// * RANGE inference — razor union else time selection (razor-else-time),
// orthogonal to scope;
// * SOURCE-TRACK collection — the selected tracks (Track scope) or the selected
// items' owning tracks (Item scope), deduped, with canonical GUIDs;
// * PROVENANCE ASSEMBLY inputs — the M10 resample-from-sample detection + the
// thin capture-recipe fingerprint built from the LIVE (un-bypassed) chain.
//
// All reads are non-destructive: selection, razor, and time selection are read,
// never mutated. REAPER-facing: the .cpp includes reaper_plugin_functions.h
// WITHOUT REAPERAPI_IMPLEMENT (main.cpp owns the API pointers — CLAUDE.md
// §contract). MediaTrack is forward-declared (via capture.h) so this header stays
// SDK-lite.
#include <optional>
#include <string>
#include <vector>
#include "shell/capture/capture.h" // CaptureRequest, MediaTrack fwd
#include "core/capture/render_settings.h" // CaptureScope
#include "core/model/provenance.h" // model::Provenance
namespace reasampler {
class BankBook;
}
namespace reasampler::capture {
// The resolved source: exact bounds + the source tracks (for FX-bypass + Sample
// provenance GUIDs). `sourceTracks` holds the item-owning tracks (Item scope) or the
// selected tracks (Track scope).
struct ResolvedSource
{
double startSeconds = 0.0;
double endSeconds = 0.0;
std::vector<MediaTrack*> sourceTracks; // item-owning tracks / selected tracks
std::vector<std::string> trackGuids; // canonical GUIDs of sourceTracks
};
// Reads every track's P_RAZOREDITS, parses the track-audio areas (pure
// parseRazorEdits), and returns the union bound. Reads only — never clears the
// razor selection. Returns false when no track-audio razor area exists on any track.
bool resolveRazorRange(double& start, double& end);
// Infers the render RANGE for any scope: razor union when a razor area is present,
// else the time selection (pure inferRangeSource decides which). Orthogonal to
// scope. Returns false (with a reason) when neither yields a non-empty range.
bool resolveRange(double& start, double& end, std::string& why);
// Collects the selected tracks (Track scope) into out.sourceTracks + GUIDs.
bool collectSelectedTracks(ResolvedSource& out);
// Resolves the source for a scope: the selection tracks (item/track), plus the
// inferred range. Returns false with a reason on nothing to do.
bool ResolveScopeSource(CaptureScope scope, ResolvedSource& out, std::string& why);
// Current project's directory (parent of its .rpp), forward-slashed, no trailing
// slash. Empty for an unsaved project (no false parentage). Read-only.
std::string currentProjectDir();
// Builds the M10 provenance for a capture IF it genuinely resamples from a bank
// sample (detectParent over `book`'s resolved file refs), else returns nullopt (the
// common, non-resample case). Must run BEFORE the FxBypassGuard neutralizes the
// in-scope chain — the source FX-chain identity is read from the LIVE chain.
std::optional<model::Provenance> buildCaptureProvenance(
const BankBook& book, const CaptureRequest& req,
CaptureScope scope, const ResolvedSource& src);
} // namespace reasampler::capture