Fix drag-handoff bugs: gate FX re-resolve on outside-panel, cache unresolvable OS-drag verdict, block double FX-add retry

This commit is contained in:
2026-07-30 00:09:00 -04:00
parent 0800760833
commit 875d5b4632
9 changed files with 110 additions and 75 deletions
+13 -6
View File
@@ -104,16 +104,23 @@ bool loadInstrumentOntoTrack(MediaTrack* track, const std::vector<std::uint8_t>&
const std::string fxName = "VST3:" + vstPluginName();
// An EXPLICIT top-level insertion position (instantiate <= -1000 IS the position, -1000
// = first in chain), not the bare -1. Both always create a new instance; the bare form
// additionally leaves placement to REAPER's ambient FX-chain insert point, which a drop
// onto an FX container/chain-window moves — so the index handed to TrackFX_SetPreset and
// the instance just created stop denoting the same FX and the capture never lands. The
// bare-form retry keeps the reference path alive if the positional form is ever refused.
// = first in chain), not the bare -1 — this form is documented in the SDK header. Both
// always create a new instance; the bare form additionally leaves placement to REAPER's
// ambient FX-chain insert point, which a drop onto an FX container/chain-window is
// suspected (unconfirmed by experiment) to move — if so, the index handed to
// TrackFX_SetPreset and the instance just created would stop denoting the same FX and the
// capture would never land. The bare-form retry keeps the reference path alive if the
// positional form is ever refused.
// recFX = false: a normal track FX chain instance, not a record/monitoring FX.
const int insertPos = TrackFX_GetCount(track);
int fxIndex = TrackFX_AddByName(track, fxName.c_str(), /*recFX=*/false,
/*instantiate=*/-1000 - insertPos);
if (fxIndex < 0)
// Only retry with the bare form when the chain is PROVABLY unchanged (count still
// insertPos): a negative return with the count grown means the positional add DID create
// an instance and just reported -1 — retrying then would add a SECOND instance, leaving
// the first orphaned (no preset applied, unreachable for rollback), which is exactly the
// all-or-nothing violation this contract forbids.
if (fxIndex < 0 && TrackFX_GetCount(track) == insertPos)
fxIndex = TrackFX_AddByName(track, fxName.c_str(), /*recFX=*/false, /*instantiate=*/-1);
// u8string() gives UTF-8 bytes on MSVC (not ACP-converted), so a temp dir under