// insert_fx_action.cpp — see insert_fx_action.h. main.cpp owns the API pointers; this TU // gets them extern via the WANT list. #include "shell/actions/insert_fx_action.h" #include #include #include #include "core/ui/insert_fx_enable.h" // the refusal fold + its wording #include "core/wire/instrument_drop.h" // buildInstrumentDropPreset — the pure payload #include "shell/actions/instrument_drop_win.h" // performInstrumentDrop — the shared drop body #include "shell/panel/panel_bank_ops.h" // bankPanelSelectedSampleIds #include "reaper_plugin.h" #define REAPERAPI_MINIMAL #define REAPERAPI_WANT_GetSelectedTrack #define REAPERAPI_WANT_GetMasterTrack #define REAPERAPI_WANT_GetMediaTrackInfo_Value #define REAPERAPI_WANT_GetTrackName #define REAPERAPI_WANT_ShowConsoleMsg #include "reaper_plugin_functions.h" namespace reasampler { namespace { void report(const std::string& sentence) { if (ShowConsoleMsg) ShowConsoleMsg(("ReaSampler: " + sentence + "\n").c_str()); } // GetSelectedTrack ignores the master, so a master-only selection reads back as "no // track" -- distinguish it here for a clearer refusal (core/ui/insert_fx_enable.h). bool isMasterOnlySelected() { if (!GetMasterTrack || !GetMediaTrackInfo_Value) return false; MediaTrack* master = GetMasterTrack(nullptr); return master && GetMediaTrackInfo_Value(master, "I_SELECTED") != 0.0; } // "Track N" for an unnamed track, matching REAPER's own convention (GetTrackName, // not P_NAME, for the same reason scope_resolve::trackName picks it). std::string trackDisplayName(MediaTrack* tr) { std::vector buf(256, '\0'); if (GetTrackName && GetTrackName(tr, buf.data(), static_cast(buf.size()))) return std::string(buf.data()); return "the selected track"; } } // namespace void doInsertAsFx() { const std::vector selected = bankPanelSelectedSampleIds(); // seltrackidx 0 = the FIRST selected track, master excluded (SDK header) — the same // "the selected track" the Media-Explorer ingest surface targets. A multi-track // selection therefore loads onto the first, rather than refusing or fanning out. MediaTrack* track = GetSelectedTrack ? GetSelectedTrack(nullptr, 0) : nullptr; const ui::InsertFxRefusal refusal = ui::insertFxRefusal(static_cast(selected.size()), track != nullptr, !track && isMasterOnlySelected()); if (refusal != ui::InsertFxRefusal::None) { report(ui::insertFxRefusalMessage(refusal)); return; } // performInstrumentDrop opens its own undo block (one Ctrl-Z) and rolls the FX back // itself if the preset never applies — there is nothing here to group with it, so no // second block is opened around it. if (!performInstrumentDrop(track, wire::buildInstrumentDropPreset(selected.front()))) report("could not add ReaSampler 9000 to the selected track -- check the plug-in " "is installed and scanned"); else report("added ReaSampler 9000 to \"" + trackDisplayName(track) + "\", loaded with the selected capture"); } } // namespace reasampler