Files
reasampler/src/shell/capture/scope_resolve.h
T

88 lines
4.3 KiB
C++

#pragma once
// Scope/source resolution shared by every capture entry point. Three concerns:
// * range inference — razor union else time selection, orthogonal to scope;
// * source-track collection — selected tracks (Track scope) or selected items'
// owning tracks (Item scope), deduped, with canonical GUIDs;
// * provenance-assembly inputs — 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. The .cpp includes reaper_plugin_functions.h WITHOUT
// REAPERAPI_IMPLEMENT (main.cpp owns the API pointers). 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;
std::vector<std::string> trackGuids;
// Parallel to sourceTracks (one entry per track, in the same order) — the names the
// capture is labeled and filed after. trackGuids is NOT parallel: an unreadable GUID
// is dropped there, while an unreadable name still holds its track's slot.
std::vector<std::string> trackNames;
// Item scope only: does the selected items' own extent already print
// [startSeconds, endSeconds)? Feeds sourceModeForScope. Defaults false so a
// hand-built source fails closed to the time-bounded render — a caller whose
// range IS the item extent (batch item capture) says so explicitly.
bool itemExtentIsWindow = false;
};
// Reads every track's P_RAZOREDITS and returns the union of parsed track-audio
// areas. Reads only — never clears the razor selection.
bool resolveRazorRange(double& start, double& end);
// Infers the render range for any scope: razor union when present, else the time
// selection. 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 + names.
bool collectSelectedTracks(ResolvedSource& out);
// The track's display name. GetTrackName (SDK header ~3626) is used rather than P_NAME
// because it already answers REAPER's own convention for an unnamed track ("Track N"),
// which is exactly the deterministic fallback a capture label wants; P_NAME would hand
// back an empty string instead. `[verify]` the SDK header states neither that the read is
// non-mutating nor what a `false` return means; the call site treats it as read-only and
// treats `false` (or a `true` with an untouched buffer) the same way — an empty name, which
// falls through to the scope literal fallback either way, so both readings are safe.
// Callers that build a ResolvedSource by hand (batch capture) use this directly.
std::string trackName(MediaTrack* tr);
// 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 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