Make an FX reclaim step one whole track's chain: drop the resume cursor, yield only between tracks

This commit is contained in:
2026-08-06 20:48:17 -04:00
parent 5a35b71dc0
commit f04c704353
6 changed files with 134 additions and 274 deletions
+6 -35
View File
@@ -7,32 +7,9 @@ namespace reasampler::view {
namespace {
// Everything up to and including the resume point is already done. An empty
// `resumeAfterFxGuid` is ambiguous by itself — "nothing done yet" and "the last
// completed op had no identity" look identical — so an empty guid falls back to
// matching by slot instead; `resumeAfterSlot < 0` is what actually means
// "nothing done yet". Not found ⇒ nothing dropped: the resume point left the
// chain between ticks, and re-walking a compare-before-write list beats
// trusting a cursor that no longer points at anything.
std::vector<FxOfflineOp> remainingAfter(const std::vector<FxOfflineOp>& ops,
const std::string& resumeAfterFxGuid,
int resumeAfterSlot) {
if (resumeAfterFxGuid.empty() && resumeAfterSlot < 0) return ops;
for (std::size_t i = 0; i < ops.size(); ++i) {
const bool isResumePoint = resumeAfterFxGuid.empty()
? ops[i].slot == resumeAfterSlot
: ops[i].fxGuid == resumeAfterFxGuid;
if (isResumePoint)
return std::vector<FxOfflineOp>(ops.begin() + static_cast<std::ptrdiff_t>(i) + 1,
ops.end());
}
return ops;
}
// Slot keying, deliberately: the live chain IS the target set, so its positions
// are current by construction. Identity keying would drop an FX REAPER reports no
// GUID for, and reclaim has to reach those too — the fxGuid rides along only so
// the resume point has something to match.
// GUID for, and reclaim has to reach those too.
std::vector<FxOfflineOp> offlineTargets(const std::string& trackGuid,
const std::vector<std::string>& liveFxGuids) {
std::vector<FxOfflineOp> ops;
@@ -70,14 +47,13 @@ std::vector<FxTrackWork> desiredFxState(const ViewModeModel& model,
if (liveTrackGuids.count(guid) == 0) continue; // dead track — nothing to write
if (!model.leafBelongsToMode(guid, targetMode)) {
offline.push_back(FxTrackWork{guid, FxWorkKind::Offline, {}, {}});
offline.push_back(FxTrackWork{guid, FxWorkKind::Offline, {}});
continue;
}
// Active with the FX half already released: the chain is back online and
// the record is only waiting on its flags. Nothing owed either way.
if (!snap.fxHeld) continue;
online.push_back(
FxTrackWork{guid, FxWorkKind::Online, fxRestoreTargets(model, guid), {}});
online.push_back(FxTrackWork{guid, FxWorkKind::Online, fxRestoreTargets(model, guid)});
}
online.reserve(online.size() + offline.size());
@@ -87,14 +63,9 @@ std::vector<FxTrackWork> desiredFxState(const ViewModeModel& model,
FxRestoreResolution resolveFxWork(const FxTrackWork& work,
const std::vector<std::string>& liveFxGuids) {
if (work.kind == FxWorkKind::Offline) {
return resolveFxRestore(
remainingAfter(offlineTargets(work.trackGuid, liveFxGuids), work.resumeAfterFxGuid,
work.resumeAfterSlot),
liveFxGuids);
}
return resolveFxRestore(
remainingAfter(work.targets, work.resumeAfterFxGuid, work.resumeAfterSlot), liveFxGuids);
if (work.kind == FxWorkKind::Offline)
return resolveFxRestore(offlineTargets(work.trackGuid, liveFxGuids), liveFxGuids);
return resolveFxRestore(work.targets, liveFxGuids);
}
} // namespace reasampler::view