diff --git a/src/instrument_drop_win.cpp b/src/instrument_drop_win.cpp index 63793e6..a0245c1 100644 --- a/src/instrument_drop_win.cpp +++ b/src/instrument_drop_win.cpp @@ -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). diff --git a/src/instrument_drop_win.h b/src/instrument_drop_win.h index ee40975..fba0cce 100644 --- a/src/instrument_drop_win.h +++ b/src/instrument_drop_win.h @@ -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