S17 drop-and-load onto track FX button; S13 editor drop-accept (relay degraded)

S17: drag_out InstrumentDrop gesture + instrument_drop blob reusing the
instrument's own serializer; bank_panel FX hover-track + add-VST/vst_chunk
inject. S13 relay deferred (read-only bridge) — editor shows drop affordance.
This commit is contained in:
2026-07-27 03:52:26 -04:00
parent 06494c654e
commit 26e2bf2fc6
13 changed files with 779 additions and 54 deletions
+83
View File
@@ -0,0 +1,83 @@
// instrument_drop_win — the REAPER shell for S17 drop-and-load. See instrument_drop_win.h.
//
// Compiled into the reaper_reasampler MODULE. Includes reaper_plugin_functions.h WITHOUT
// REAPERAPI_IMPLEMENT (main.cpp owns the pointers; here they are extern via the WANT list).
#include "instrument_drop_win.h"
#include <cstring>
#include <string>
#include "app_version.h" // vstPluginName() — the CHANNEL-correct FX name (stable/beta pairing)
#include "reaper_plugin.h"
#define REAPERAPI_MINIMAL
#define REAPERAPI_WANT_GetThingFromPoint
#define REAPERAPI_WANT_TrackFX_AddByName
#define REAPERAPI_WANT_TrackFX_SetNamedConfigParm
#define REAPERAPI_WANT_Undo_BeginBlock2
#define REAPERAPI_WANT_Undo_EndBlock2
#include "reaper_plugin_functions.h"
namespace reasampler {
namespace {
// GetThingFromPoint's info string prefixes (verified against reaper_plugin_functions.h:
// "Updates infoOut with information such as 'arrange', 'fx_chain', 'fx_0' ... If a track
// panel is hit, string will begin with 'tcp' or 'mcp' or 'tcp.mute' etc"). The FX region
// reports "fx_chain" (the FX list area) or "fx_N" (a specific FX button). We treat either
// as the FX hotspot — the S17 drop target.
bool infoNamesFxHotspot(const char* info) {
return std::strncmp(info, "fx_", 3) == 0;
}
} // namespace
FxDropTarget resolveFxDropTarget(int screenX, int screenY) {
FxDropTarget out;
char info[256] = {0};
// GetThingFromPoint returns the track under the point (may be null for a non-track thing)
// and fills `info` with what was hit. A non-empty info OR a non-null track means the point
// is over REAPER's own UI; a null track with an empty info means the pointer has left
// REAPER entirely (over another app / the desktop) — the OsDrag boundary.
MediaTrack* track = GetThingFromPoint(screenX, screenY, info, sizeof(info));
out.track = track;
out.overReaperUi = (track != nullptr) || (info[0] != '\0');
out.overFxHotspot = (track != nullptr) && infoNamesFxHotspot(info);
return out;
}
bool performInstrumentDrop(MediaTrack* track, const std::string& chunkBase64) {
if (!track || chunkBase64.empty()) return false;
// The CHANNEL-correct FX name: "VST3:ReaSampler 9000" on stable, "VST3:ReaSampler 9000
// beta" on beta. Sourcing it from app_version::vstPluginName() (the same accessor the VST
// factory display name derives from) keeps the pairing invariant intact — a beta extension
// drops the beta VST, a stable extension the stable VST — with no literal to drift.
const std::string fxName = "VST3:" + vstPluginName();
// One undo point for the whole gesture (mirrors the bank-verb undo discipline). Both the
// FX add and the state write are REAPER-undoable, so Ctrl-Z removes the instance cleanly.
Undo_BeginBlock2(nullptr);
// Negative `instantiate` => always create a NEW instance (verified in the header). recFX
// = false: a normal track FX chain instance, not a record/monitoring FX.
const int fxIndex = TrackFX_AddByName(track, fxName.c_str(), /*recFX=*/false,
/*instantiate=*/-1);
bool ok = false;
if (fxIndex >= 0) {
// Inject the instrument's OWN component-state blob (the dragged capture pre-selected)
// via the documented vst_chunk write-parm. The blob was built by the shared writer
// (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());
}
// The undo label reflects the placement-of-the-player framing (not a capture, not an insert).
Undo_EndBlock2(nullptr, "ReaSampler: drop capture onto FX chain", -1);
return ok;
}
} // namespace reasampler