fix(instrument_drop_win): make performInstrumentDrop all-or-nothing

On chunk-write failure, call TrackFX_Delete(track, fxIndex) to remove
the just-added empty FX instance before returning false. Signature
verified at reaper_plugin_functions.h:7236. Update the header comment
from "leaves at most the added FX" to the new all-or-nothing contract.
This commit is contained in:
2026-07-27 03:58:05 -04:00
parent 26e2bf2fc6
commit 3440ddb268
2 changed files with 12 additions and 4 deletions
+7
View File
@@ -15,6 +15,7 @@
#define REAPERAPI_MINIMAL
#define REAPERAPI_WANT_GetThingFromPoint
#define REAPERAPI_WANT_TrackFX_AddByName
#define REAPERAPI_WANT_TrackFX_Delete
#define REAPERAPI_WANT_TrackFX_SetNamedConfigParm
#define REAPERAPI_WANT_Undo_BeginBlock2
#define REAPERAPI_WANT_Undo_EndBlock2
@@ -73,6 +74,12 @@ bool performInstrumentDrop(MediaTrack* track, const std::string& chunkBase64) {
// (instrument_drop::buildInstrumentDropChunk -> sample_map::serializeComponentState),
// so these bytes are exactly what ReaSampler 9000's setState accepts.
ok = TrackFX_SetNamedConfigParm(track, fxIndex, "vst_chunk", chunkBase64.c_str());
if (!ok) {
// All-or-nothing: if the chunk write fails, remove the empty FX instance we just
// added so the track is left exactly as it was. TrackFX_Delete signature (verified
// in reaper_plugin_functions.h:7236): bool TrackFX_Delete(MediaTrack*, int fx).
TrackFX_Delete(track, fxIndex);
}
}
// The undo label reflects the placement-of-the-player framing (not a capture, not an insert).
+5 -4
View File
@@ -47,10 +47,11 @@ FxDropTarget resolveFxDropTarget(int screenX, int screenY);
// (the instrument_drop::buildInstrumentDropChunk output) as its component state so it plays
// the dragged capture. `chunkBase64` is the base64 vst_chunk. Wraps the add + inject in one
// REAPER undo block (mirrors the bank-verb undo discipline). Returns true on success (the FX
// was added and the chunk written), false on any failure (add returned -1, or the chunk write
// was rejected). A false return leaves at most the added FX (no partial-state confusion — the
// caller surfaces nothing; a failed add is visible by nothing happening). NEVER inserts a
// timeline item; the ONLY mutations are the FX instance + its state, both undoable.
// was added and the chunk written), false on any failure. All-or-nothing: if the chunk write
// fails after a successful add, the freshly-added FX instance is removed via TrackFX_Delete
// before returning false, leaving the track exactly as it was (no orphaned empty-state FX).
// NEVER inserts a timeline item; the ONLY mutations are the FX instance + its state, both
// undoable.
bool performInstrumentDrop(MediaTrack* track, const std::string& chunkBase64);
} // namespace reasampler