Cut core/wire and shell/persist comment bloat ~46% (comments only, zero code change)
This commit is contained in:
@@ -1,20 +1,14 @@
|
||||
// usage_scan.cpp — see usage_scan.h. The REAPER reads behind the pS-usage prune
|
||||
// protection; every decision is in the pure sample_usage module, this TU only reads.
|
||||
// usage_scan.cpp — see usage_scan.h. The REAPER reads behind the instance-usage
|
||||
// prune protection; every decision is in the pure sample_usage module, this TU
|
||||
// only reads.
|
||||
//
|
||||
// Compiled into the reaper_reasampler MODULE. Includes reaper_plugin_functions.h
|
||||
// WITHOUT REAPERAPI_IMPLEMENT — main.cpp is the one TU that defines the API pointers
|
||||
// (CLAUDE.md §contract). Every REAPER symbol used here is verified against
|
||||
// vendor/reaper-sdk/sdk/reaper_plugin_functions.h:
|
||||
// * EnumProjExtState(proj, extname, idx, keyOut, sz, valOut, sz) -> bool (~1272)
|
||||
// * GetProjExtState(proj, extname, key, valOut, sz) -> int (~2591)
|
||||
// * CountTracks / GetTrack / GetMasterTrack (track scan)
|
||||
// * TrackFX_GetCount(MediaTrack*) / TrackFX_GetRecCount(MediaTrack*) (~7283/7570)
|
||||
// * TrackFX_GetNamedConfigParm(MediaTrack*, int, parm, buf, sz) -> bool (~7377)
|
||||
// * CountMediaItems / GetMediaItem (~423/1964)
|
||||
// * CountTakes(MediaItem*) / GetMediaItemTake(MediaItem*, int) (~471/2029)
|
||||
// * GetMediaItemTrack(MediaItem*) (~2133)
|
||||
// * TakeFX_GetCount / TakeFX_GetNamedConfigParm (~6710/6774)
|
||||
// * guidToString (via track_guid::guidString)
|
||||
// Compiled into the reaper_reasampler module. Includes reaper_plugin_functions.h
|
||||
// WITHOUT REAPERAPI_IMPLEMENT — main.cpp is the one TU that defines the API
|
||||
// pointers (CLAUDE.md §contract). REAPER symbols used here (EnumProjExtState,
|
||||
// GetProjExtState, CountTracks/GetTrack/GetMasterTrack, TrackFX_GetCount/
|
||||
// GetRecCount/GetNamedConfigParm, CountMediaItems/GetMediaItem, CountTakes/
|
||||
// GetMediaItemTake, GetMediaItemTrack, TakeFX_GetCount/GetNamedConfigParm) are
|
||||
// verified against vendor/reaper-sdk/sdk/reaper_plugin_functions.h.
|
||||
|
||||
#include "shell/persist/usage_scan.h"
|
||||
|
||||
@@ -26,11 +20,11 @@
|
||||
#include <vector>
|
||||
|
||||
#include "core/version/app_version.h" // vstPluginName / vstOutputName (channel name needles)
|
||||
#include "core/wire/ext_state_read.h" // readProjExtStateGrowing (T2-04: the ONE grow-loop policy)
|
||||
#include "core/wire/ext_state_read.h" // readProjExtStateGrowing — the shared grow-loop policy
|
||||
#include "ext_keys.h" // kProjExtNamespace / kProjExtUsageKeyPrefix
|
||||
#include "core/wire/instrument_drop.h" // vstClassIdHex — the frozen channel class-UID hex
|
||||
#include "core/wire/sample_usage.h" // identityMatches, foldUsageRecords (the pure decisions)
|
||||
#include "shell/capture/track_guid.h" // guidString — the ONE canonical GUID key formatter
|
||||
#include "shell/capture/track_guid.h" // guidString — the canonical GUID key formatter
|
||||
|
||||
#define REAPERAPI_MINIMAL
|
||||
#define REAPERAPI_WANT_EnumProjExtState
|
||||
@@ -52,10 +46,9 @@
|
||||
|
||||
namespace reasampler {
|
||||
|
||||
// Real-namespace-home using-directive (Q-W6: the namespaces.h shim is retired):
|
||||
// this TU speaks the sample_usage wire vocabulary wholesale (UsageRecord /
|
||||
// decodeUsageRecord / foldUsageRecords / identityMatches / toUpperAscii) plus the
|
||||
// channel-identity accessors + the preset class-id hex.
|
||||
// This TU speaks the sample_usage wire vocabulary wholesale (UsageRecord /
|
||||
// decodeUsageRecord / foldUsageRecords / identityMatches / toUpperAscii) plus
|
||||
// the channel-identity accessors + the preset class-id hex.
|
||||
using namespace reasampler::wire;
|
||||
using version::vstOutputName;
|
||||
using version::vstPluginName;
|
||||
@@ -76,16 +69,15 @@ struct FxIdentityNeedles {
|
||||
using FxParmGetter =
|
||||
std::function<std::string(int fxId, const char* parm)>;
|
||||
|
||||
// True if any FX in the (possibly container-nested) sub-chain rooted at `fxId` is a
|
||||
// ReaSampler 9000. BOTH fx_ident and original_name are checked on BOTH chain kinds (a
|
||||
// renamed instance may keep its original_name; fx_ident carries the module path — the
|
||||
// primary identification net is the module filename base via fx_ident, which holds even
|
||||
// after a user renames the FX instance). Containers are walked via
|
||||
// the documented container_count / container_item.X addressing (v7.06+); on a chain
|
||||
// kind or REAPER version without containers the parm read returns empty and recursion
|
||||
// is a no-op. `depth` bounds pathological nesting. fx_ident is queried per FX — chain
|
||||
// enumeration is chunk-level, so OFFLINE instances match too (load-bearing: a
|
||||
// Design-View-parked instance must keep protecting its holds).
|
||||
// True if any FX in the (possibly container-nested) sub-chain rooted at
|
||||
// `fxId` is a ReaSampler 9000. Both fx_ident and original_name are checked (a
|
||||
// renamed instance may keep its original_name; fx_ident carries the module
|
||||
// path and survives a rename). Containers are walked via the documented
|
||||
// container_count / container_item.X addressing (v7.06+); on a chain kind or
|
||||
// REAPER version without containers the parm read returns empty and
|
||||
// recursion is a no-op. `depth` bounds pathological nesting. fx_ident is
|
||||
// queried per FX — chain enumeration is chunk-level, so OFFLINE instances
|
||||
// match too (a Design-View-parked instance must keep protecting its holds).
|
||||
bool fxSubtreeHasInstance(const FxParmGetter& parm, int fxId,
|
||||
const FxIdentityNeedles& id, int depth) {
|
||||
if (identityMatches(parm(fxId, "fx_ident"), id.uidHexUpper, id.nameUpper,
|
||||
@@ -96,12 +88,9 @@ bool fxSubtreeHasInstance(const FxParmGetter& parm, int fxId,
|
||||
const std::string countStr = parm(fxId, "container_count");
|
||||
if (countStr.empty()) return false; // not a container; no children to miss
|
||||
if (depth <= 0) {
|
||||
// This node IS a container but we have exhausted our descent budget. We cannot
|
||||
// prove that none of its children is a ReaSampler 9000 instance — treat the
|
||||
// incomplete walk as a positive identification (the protect direction). This is
|
||||
// defense-in-depth: kMaxContainerDepth = 32 should prevent reaching this branch
|
||||
// in any real project, but if it IS reached the fail-safe fires rather than
|
||||
// silently missing a live nested instance.
|
||||
// Descent budget exhausted on a node that IS a container: we cannot
|
||||
// prove none of its children is an instance, so treat the incomplete
|
||||
// walk as a positive identification (protect direction).
|
||||
return true;
|
||||
}
|
||||
const int n = std::atoi(countStr.c_str());
|
||||
@@ -116,9 +105,9 @@ bool fxSubtreeHasInstance(const FxParmGetter& parm, int fxId,
|
||||
return false;
|
||||
}
|
||||
|
||||
// Raised from 8 to 32 (defense in depth against truncation). Real-world FX containers
|
||||
// are typically 2–4 levels deep; 32 is unreachable in practice while remaining finite.
|
||||
// Even at 32, the truncation→protect-all guard below is the primary protection.
|
||||
// Real-world FX containers are typically 2-4 levels deep; 32 is unreachable
|
||||
// in practice while remaining finite. The truncation->protect-all guard above
|
||||
// is the primary protection even at this depth.
|
||||
constexpr int kMaxContainerDepth = 32;
|
||||
|
||||
std::string trackFxParm(MediaTrack* tr, int fxId, const char* parm) {
|
||||
@@ -153,11 +142,9 @@ bool trackHasInstance(MediaTrack* tr, const FxIdentityNeedles& id) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// True if any take FX on `item` is a ReaSampler 9000 (all takes, not just active — a
|
||||
// non-active take's instance still exists in the project and reactivates with the
|
||||
// take). The SAME identity walk as the track path: fx_ident + original_name + container
|
||||
// recursion (an unrecognized exotic still lands in the pure protect-all net — records
|
||||
// with zero identified instances protect everything rather than nothing).
|
||||
// True if any take FX on `item` is a ReaSampler 9000 (all takes, not just
|
||||
// active — a non-active take's instance still exists and reactivates with
|
||||
// the take). Same identity walk as the track path.
|
||||
bool itemHasInstance(MediaItem* item, const FxIdentityNeedles& id) {
|
||||
const int takes = CountTakes(item);
|
||||
for (int t = 0; t < takes; ++t) {
|
||||
@@ -174,15 +161,11 @@ bool itemHasInstance(MediaItem* item, const FxIdentityNeedles& id) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Growing GetProjExtState read: the usage record scales with the hold count, so a
|
||||
// fixed buffer risks a truncated decode. The retry policy is the SHARED pure
|
||||
// wire::readProjExtStateGrowing (T2-04 — one loop for persist, this
|
||||
// prune-safety-adjacent read, and the VST bridge; the rules cannot drift).
|
||||
// Returns nullopt when the key cannot be read WHOLE — absent-after-enumeration
|
||||
// (rv <= 0) or pathologically large (> 16 MB give-up). The caller only queries keys
|
||||
// the enumeration just listed, so a nullopt here is a PRESENT-BUT-UNREADABLE record:
|
||||
// it folds to abortPrune (fail-safe — silently reduced protection is the delete
|
||||
// direction).
|
||||
// The usage record scales with the hold count, so a fixed buffer risks a
|
||||
// truncated decode; uses the shared grow-loop policy. Returns nullopt when
|
||||
// the key cannot be read whole (absent, or > 16 MB give-up). The caller only
|
||||
// queries keys the enumeration just listed, so nullopt here is a
|
||||
// present-but-unreadable record: it folds to abortPrune.
|
||||
std::optional<std::string> readExtStateValue(ReaProject* proj, const char* key) {
|
||||
const GrowingExtStateRead read = readProjExtStateGrowing(
|
||||
[&](char* buf, int cap) {
|
||||
@@ -198,10 +181,8 @@ UsageScanResult liveInstanceHeldPaths(void* projOpaque) {
|
||||
ReaProject* proj = static_cast<ReaProject*>(projOpaque);
|
||||
UsageScanResult result;
|
||||
|
||||
// 1. Enumerate the rsusage_* keys and read+decode each record. Key names first
|
||||
// (values via the growing reader — EnumProjExtState's fixed val buffer could
|
||||
// truncate a large record). A nullopt element = present-but-unreadable/
|
||||
// undecodable -> the pure fold ABORTS the prune.
|
||||
// Enumerate rsusage_* keys, then read+decode via the growing reader
|
||||
// (EnumProjExtState's fixed val buffer could truncate a large record).
|
||||
std::vector<std::string> usageKeys;
|
||||
{
|
||||
const std::string prefix = kProjExtUsageKeyPrefix; // hoisted: one alloc, not N
|
||||
@@ -232,8 +213,8 @@ UsageScanResult liveInstanceHeldPaths(void* projOpaque) {
|
||||
decoded.push_back(rec); // undecodable nullopt -> abort
|
||||
}
|
||||
|
||||
// 2. Enumerate live ReaSampler 9000 hosts. One channel-frozen needle set drives
|
||||
// every match; a track needs only ONE instance to keep all its records live.
|
||||
// Enumerate live ReaSampler 9000 hosts; a track needs only one instance to
|
||||
// keep all its records live.
|
||||
FxIdentityNeedles id;
|
||||
id.uidHexUpper = toUpperAscii(vstClassIdHex());
|
||||
id.outputNameUpper = toUpperAscii(vstOutputName());
|
||||
@@ -270,14 +251,12 @@ UsageScanResult liveInstanceHeldPaths(void* projOpaque) {
|
||||
}
|
||||
}
|
||||
|
||||
// 3. The pure fold decides: abort on any unreadable record; protect-all when zero
|
||||
// instances were identified; otherwise the per-record liveness rule.
|
||||
// The pure fold decides: abort on any unreadable record; protect-all when
|
||||
// zero instances were identified; otherwise the per-record liveness rule.
|
||||
const UsageFoldResult fold = foldUsageRecords(decoded, liveTrackGuids, anyLive);
|
||||
result.abortPrune = fold.abortPrune;
|
||||
result.heldPaths = fold.heldPaths;
|
||||
// offendingKeys already populated above (unreadable + undecodable entries);
|
||||
// clear it on success so callers see it only when abortPrune is set.
|
||||
if (!result.abortPrune) result.offendingKeys.clear();
|
||||
if (!result.abortPrune) result.offendingKeys.clear(); // only meaningful on abort
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user