Extend the park trust test to the FX chain, name the refused tracks, and stop reprinting an unchanged refusal

This commit is contained in:
2026-08-05 17:10:19 -04:00
parent 203961f41c
commit 5376ab085c
8 changed files with 318 additions and 86 deletions
+14 -21
View File
@@ -31,7 +31,6 @@
#define REAPERAPI_WANT_SetMediaTrackInfo_Value
#define REAPERAPI_WANT_GetSetMediaTrackInfo_String
#define REAPERAPI_WANT_PreventUIRefresh
#define REAPERAPI_WANT_ShowConsoleMsg
#define REAPERAPI_WANT_Undo_BeginBlock2
#define REAPERAPI_WANT_Undo_EndBlock2
#define REAPERAPI_WANT_TrackList_AdjustWindows
@@ -152,11 +151,14 @@ MediaTrack* resolve(const TrackByGuid& byGuid, const std::string& guid) {
// The FX half is snapshotFxOffline's — only it knows when the live chain has
// stopped being a trustworthy source.
TrackSnapshot snapshotTrack(MediaTrack* tr, const std::vector<FxOfflineOp>& cancelledRestore) {
auto read = [tr](Flag f) {
return static_cast<int>(GetMediaTrackInfo_Value(tr, trackFlagParm(f)));
};
TrackSnapshot snap;
snap.showInTcp = static_cast<int>(GetMediaTrackInfo_Value(tr, "B_SHOWINTCP"));
snap.showInMixer = static_cast<int>(GetMediaTrackInfo_Value(tr, "B_SHOWINMIXER"));
snap.mainSend = static_cast<int>(GetMediaTrackInfo_Value(tr, "B_MAINSEND"));
snap.fxEnable = static_cast<int>(GetMediaTrackInfo_Value(tr, "I_FXEN"));
snap.showInTcp = read(Flag::ShowInTcp);
snap.showInMixer = read(Flag::ShowInMixer);
snap.mainSend = read(Flag::MainSend);
snap.fxEnable = read(Flag::FxEnable);
PreParkFx fx = snapshotFxOffline(tr, cancelledRestore);
snap.fxOffline = std::move(fx.states);
@@ -440,7 +442,7 @@ bool applyMode(ViewModeModel& model, const std::string& targetModeId, ReaProject
int undoMask = kApplyUndoMask;
bool laneModeChanged = false;
int refusedParks = 0;
std::vector<MediaTrack*> refusedParks;
Undo_BeginBlock2(proj);
{
@@ -462,16 +464,10 @@ bool applyMode(ViewModeModel& model, const std::string& targetModeId, ReaProject
MediaTrack* tr = resolve(trackByGuid, guid);
if (!tr) continue; // stale GUID — prune
// Full contract at decidePark. Only an absent snapshot can refuse, so
// the short-circuit cannot change the answer (ParkOnly ignores the
// second term); a first park still pays the four reads, a reapply's
// re-park of a still-parked track does not.
const bool haveSnapshot = model.snapshot(guid) != nullptr;
const ParkAction action = decidePark(
haveSnapshot,
!haveSnapshot &&
parkFlagsAlreadyApplied(tp.flags, readParkFlagValues(tr, tp.flags)));
if (action == ParkAction::Refuse) { ++refusedParks; continue; }
// Full contract at decidePark; view_fx_park owns the live reads.
const ParkAction action =
decideParkForTrack(tr, model.snapshot(guid) != nullptr, tp.flags);
if (action == ParkAction::Refuse) { refusedParks.push_back(tr); continue; }
// Enqueued FIRST: a park landing on this track's own pending restore
// cancels it, and those ops are then the only surviving record of the
@@ -542,11 +538,8 @@ bool applyMode(ViewModeModel& model, const std::string& targetModeId, ReaProject
Undo_EndBlock2(proj, undoLabel.c_str(), undoMask);
// After the undo block and the UI hold: a refusal is a report, not a project
// write, and it must not join what a Ctrl-Z rolls back. "!SHOW:" so an
// unattended project-load reapply cannot force the console open
// (reaper_plugin_functions.h:6536), same as the drain's drop report.
const std::string refusedMsg = describeRefusedParks(refusedParks);
if (!refusedMsg.empty()) ShowConsoleMsg(("!SHOW:" + refusedMsg).c_str());
// write, and it must not join what a Ctrl-Z rolls back.
reportRefusedParks(proj, refusedParks);
return true;
}