Retire MPE scaffold; stand up reaper_reasampler pure-core skeleton

Rename CMake project/module to reaper_reasampler, delete mpe_model/mpe_view,
add minimal pure bank_model lib + placeholder CTest. main.cpp loads, logs to
console, keeps the action-registration seam commented with the forever-stable
CEREBELLUM_REASAMPLER_ action-id prefix.
This commit is contained in:
2026-07-21 21:18:51 -04:00
parent bbc0b2c19e
commit acfc9daabc
5 changed files with 196 additions and 0 deletions
+83
View File
@@ -0,0 +1,83 @@
// main.cpp — the SINGLE translation unit that OWNS the REAPER API pointers.
//
// This file is the entire contract between REAPER and the extension:
// * At startup REAPER scans UserPlugins/ for reaper_*.dll|dylib|so and
// dlopen()s each one, then looks up ONE exported symbol: ReaperPluginEntry
// (that name is produced by the REAPER_PLUGIN_ENTRYPOINT macro).
// * REAPER calls it, handing over `rec` — a small dispatch struct.
// - rec->GetFunc(name) resolves any REAPER API function to a pointer
// - rec->Register(what,ptr) plugs OUR callbacks into REAPER
// * REAPERAPI_LoadAPI(rec->GetFunc) walks reaper_plugin_functions.h and
// fills in every global function pointer (ShowConsoleMsg, InsertMedia...).
//
// Exactly ONE .cpp defines REAPERAPI_IMPLEMENT (this one) — that allocates
// storage for those global pointers. Every other .cpp includes
// reaper_plugin_functions.h WITHOUT the define and gets `extern` declarations.
#define REAPERAPI_IMPLEMENT
#include "reaper_plugin.h"
#include "reaper_plugin_functions.h"
// Persistent action-id prefix for the ReaSampler action family.
// Every bindable action (capture / insert / slot / verify) mints its command id
// from a string beginning with this prefix, e.g. "CEREBELLUM_REASAMPLER_CAPTURE_MASTER".
// FOREVER-STABLE once shipped: user keybindings key off these strings, so the
// prefix and any minted id must never change after release.
#define REASAMPLER_ACTION_PREFIX "CEREBELLUM_REASAMPLER_"
// Globals other files reference via `extern`.
REAPER_PLUGIN_HINSTANCE g_hInst = nullptr; // this module's instance handle
reaper_plugin_info_t* g_rec = nullptr; // REAPER's dispatch struct
// ---- Action registration seam (reusable pattern, no action wired yet) ------
// The capture/insert/slot action family (PLAN.md M3+) reinstates the pattern
// below. Kept as a commented template so the shape is not re-derived each time.
//
// static int g_cmdCaptureMaster = 0;
//
// // REAPER calls this for EVERY action fired anywhere; claim only your own id,
// // return false otherwise so REAPER keeps looking.
// static bool OnHookCommand(int command, int /*flag*/)
// {
// if (command == 0) return false;
// if (command == g_cmdCaptureMaster) { /* route to capture module */ return true; }
// return false;
// }
//
// Registration, inside the load branch below:
// 1) g_cmdCaptureMaster =
// rec->Register("command_id", (void*)(REASAMPLER_ACTION_PREFIX "CAPTURE_MASTER"));
// 2) static gaccel_register_t sAccel{};
// sAccel.accel.cmd = g_cmdCaptureMaster;
// sAccel.desc = "ReaSampler: capture master mix";
// rec->Register("gaccel", (void*)&sAccel);
// 3) rec->Register("hookcommand", (void*)&OnHookCommand);
// On unload (rec == nullptr), mirror-unregister with the same strings prefixed '-'.
extern "C" REAPER_PLUGIN_DLL_EXPORT int REAPER_PLUGIN_ENTRYPOINT(
REAPER_PLUGIN_HINSTANCE hInstance, reaper_plugin_info_t* rec)
{
if (!rec)
{
// rec == nullptr => REAPER is UNLOADING us. Mirror-unregister every
// callback here (same strings prefixed with '-') once actions are wired.
g_rec = nullptr;
return 0;
}
// ABI guard: the struct layout we compiled against must match this REAPER.
if (rec->caller_version != REAPER_PLUGIN_VERSION)
return 0;
// Resolve every REAPER API function pointer. Returns the number that FAILED
// to load; 0 == success. Non-zero usually means REAPER is older than our SDK.
if (REAPERAPI_LoadAPI(rec->GetFunc) != 0)
return 0;
g_hInst = hInstance;
g_rec = rec;
ShowConsoleMsg("ReaSampler loaded.\n");
return 1; // success — REAPER keeps us loaded
}