fix(drop-fx): inject via .vstpreset + TrackFX_SetPreset (vst_chunk is REAPER-framed, raw bytes silently no-op); FX hotspot now prefix tcp.fx*/mcp.fx*/fx_*
This commit is contained in:
+35
-31
@@ -1,20 +1,24 @@
|
||||
#pragma once
|
||||
// instrument_drop_win — the REAPER-facing shell half of S17 drop-and-load. The pure gesture
|
||||
// decision lives in drag_out (DragGesture::InstrumentDrop) and the pure blob construction in
|
||||
// instrument_drop; THIS is the platform shell that (a) resolves a screen point to a track +
|
||||
// its TCP FX-button hotspot via REAPER's hit-test API, and (b) on release adds a ReaSampler
|
||||
// 9000 instance to that track and injects the dragged capture as its component state.
|
||||
// decision lives in drag_out (DragGesture::InstrumentDrop) and the pure payload construction
|
||||
// in instrument_drop; THIS is the platform shell that (a) resolves a screen point to a track
|
||||
// + its FX-surface hotspot via REAPER's hit-test API, and (b) on release adds a ReaSampler
|
||||
// 9000 instance to that track and applies the dragged capture as its component state via a
|
||||
// temp .vstpreset + TrackFX_SetPreset (S-GA-DropFX: the earlier "vst_chunk" named-config-parm
|
||||
// write was silently unappliable — see instrument_drop.h for the diagnosis).
|
||||
//
|
||||
// Compiled into the reaper_reasampler MODULE. REAPER-facing (GetThingFromPoint, TrackFX_*,
|
||||
// Undo_*), so DAW-verified, not unit-tested; the pure decision + blob it drives are CTest'd.
|
||||
// Undo_*), so DAW-verified, not unit-tested; the pure decision + preset it drives are CTest'd.
|
||||
//
|
||||
// LOAD-BEARING (CONTEXT.md §Drop-and-load): this is an EXPLICIT user placement-of-the-player
|
||||
// gesture — it adds a READER of the bank on a track and points it at one already-captured
|
||||
// sample. It NEVER captures, NEVER writes the bank, and NEVER inserts a timeline item. The
|
||||
// only writes are: a new FX instance on the target track + that instance's own component
|
||||
// state — both REAPER-undoable, wrapped in one undo block so the whole gesture is one Ctrl-Z.
|
||||
// state — both REAPER-undoable, wrapped in one undo block so the whole gesture is one Ctrl-Z
|
||||
// — plus a transient .vstpreset in the OS temp dir, deleted before returning.
|
||||
|
||||
#include <string>
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
|
||||
// Opaque REAPER track handle at the boundary so includers don't need the SDK. The SDK
|
||||
// declares it as a class (reaper_plugin.h) — match that spelling so the mangled name agrees.
|
||||
@@ -26,40 +30,40 @@ namespace reasampler {
|
||||
struct FxDropTarget {
|
||||
MediaTrack* track = nullptr; // the track under the pointer (null if none / not a track)
|
||||
bool overReaperUi = false; // the point is over REAPER's own window/UI at all
|
||||
bool overFxHotspot = false; // specifically over this track's TCP FX-button/-chain region
|
||||
bool overFxHotspot = false; // specifically over this track's FX button/chain surface
|
||||
|
||||
// A valid drop target: a resolved track whose FX hotspot is under the pointer.
|
||||
bool valid() const { return track != nullptr && overFxHotspot; }
|
||||
};
|
||||
|
||||
// Hit-test a screen point (REAPER screen coords) to an FX drop target. Wraps
|
||||
// GetThingFromPoint, whose info string tells us what was hit ("tcp.fx"/"mcp.fx" for the TCP/MCP
|
||||
// FX button; "fx_chain"/"fx_N" for the FX-chain and floating-FX windows; bare "tcp"/"mcp" or
|
||||
// other "tcp.*"/"mcp.*" tokens for non-FX track-panel regions). `overReaperUi` is the
|
||||
// shell-supplied predicate the pure drag_out::decideGesture consumes (true when the point is
|
||||
// over REAPER's own UI — i.e. GetThingFromPoint returned a track OR a recognizable non-track
|
||||
// thing, false when the pointer has left REAPER entirely). `overFxHotspot` is true only when
|
||||
// the info string names a genuine FX-bearing surface ("tcp.fx", "mcp.fx", or "fx_*") —
|
||||
// decided by instrument_drop::infoNamesFxHotspot from the SDK's own hit-test string.
|
||||
// GetThingFromPoint, whose info string tells us what was hit ("tcp.fx*"/"mcp.fx*" for the
|
||||
// TCP/MCP FX button family; "fx_chain"/"fx_N" for the FX-chain and floating-FX windows; bare
|
||||
// "tcp"/"mcp" or other sub-element tokens for non-FX track-panel regions). `overReaperUi` is
|
||||
// the shell-supplied predicate the pure drag_out::decideGesture consumes (true when the point
|
||||
// is over REAPER's own UI — i.e. GetThingFromPoint returned a track OR a recognizable
|
||||
// non-track thing, false when the pointer has left REAPER entirely). `overFxHotspot` is true
|
||||
// only when the info string names a genuine FX-bearing surface — decided by the pure
|
||||
// instrument_drop::infoNamesFxHotspot from the SDK's own hit-test string.
|
||||
FxDropTarget resolveFxDropTarget(int screenX, int screenY);
|
||||
|
||||
// Perform the drop on `track`: add a fresh ReaSampler 9000 instance and inject `chunkBase64`
|
||||
// (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. 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);
|
||||
// Perform the drop on `track`: add a fresh ReaSampler 9000 instance and apply `presetBytes`
|
||||
// (the instrument_drop::buildInstrumentDropPreset output — a .vstpreset image) as its
|
||||
// component state so it plays the dragged capture. Wraps the add + apply in one REAPER undo
|
||||
// block (mirrors the bank-verb undo discipline). Returns true on success (the FX was added
|
||||
// and the preset applied), false on any failure. All-or-nothing: if the preset apply 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 persistent mutations are the FX instance + its
|
||||
// state, both undoable.
|
||||
bool performInstrumentDrop(MediaTrack* track, const std::vector<std::uint8_t>& presetBytes);
|
||||
|
||||
// Add a fresh ReaSampler 9000 instance to `track` and inject `chunkBase64` as its component
|
||||
// state. Same all-or-nothing add+inject contract as performInstrumentDrop (rolls the FX back
|
||||
// via TrackFX_Delete on inject failure), but does NOT open its own undo block — the caller owns
|
||||
// the undo grouping so the whole gesture (persist + FX-add + inject) collapses to
|
||||
// Add a fresh ReaSampler 9000 instance to `track` and apply `presetBytes` as its component
|
||||
// state. Same all-or-nothing add+apply contract as performInstrumentDrop (rolls the FX back
|
||||
// via TrackFX_Delete on apply failure), but does NOT open its own undo block — the caller owns
|
||||
// the undo grouping so the whole gesture (persist + FX-add + apply) collapses to
|
||||
// one Ctrl-Z. This is the shared inner half performInstrumentDrop wraps in its own block.
|
||||
// Returns true on success, false on any failure. NEVER inserts a timeline item.
|
||||
bool loadInstrumentOntoTrack(MediaTrack* track, const std::string& chunkBase64);
|
||||
bool loadInstrumentOntoTrack(MediaTrack* track, const std::vector<std::uint8_t>& presetBytes);
|
||||
|
||||
} // namespace reasampler
|
||||
|
||||
Reference in New Issue
Block a user