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:
@@ -0,0 +1,62 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.19)
|
||||||
|
project(reaper_reasampler LANGUAGES CXX)
|
||||||
|
|
||||||
|
set(CMAKE_CXX_STANDARD 17)
|
||||||
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
|
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# Vendored dependencies — add as git submodules (see README):
|
||||||
|
# git submodule add https://github.com/justinfrankel/reaper-sdk vendor/reaper-sdk
|
||||||
|
# git submodule add https://github.com/justinfrankel/WDL vendor/WDL
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
set(SDK_INC ${CMAKE_CURRENT_SOURCE_DIR}/vendor/reaper-sdk/sdk)
|
||||||
|
set(WDL_INC ${CMAKE_CURRENT_SOURCE_DIR}/vendor/WDL/WDL)
|
||||||
|
set(SWELL ${WDL_INC}/swell)
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# 1) Pure model library — NO REAPER, NO SWELL. Builds & tests anywhere.
|
||||||
|
# The sampler's heart: Sample metadata + BankIndex (Milestone 1).
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
add_library(bank_model STATIC src/bank_model.cpp)
|
||||||
|
target_include_directories(bank_model PUBLIC src)
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# 2) Standalone tests for the model (run without launching REAPER).
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
enable_testing()
|
||||||
|
add_executable(bank_model_tests tests/test_bank_model.cpp)
|
||||||
|
target_link_libraries(bank_model_tests PRIVATE bank_model)
|
||||||
|
add_test(NAME bank_model_tests COMMAND bank_model_tests)
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# 3) The REAPER extension — a loadable module (dlopen'd by REAPER, not linked).
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
add_library(reaper_reasampler MODULE
|
||||||
|
src/main.cpp
|
||||||
|
)
|
||||||
|
target_link_libraries(reaper_reasampler PRIVATE bank_model)
|
||||||
|
target_include_directories(reaper_reasampler PRIVATE ${SDK_INC} ${WDL_INC})
|
||||||
|
set_target_properties(reaper_reasampler PROPERTIES PREFIX "" OUTPUT_NAME "reaper_reasampler")
|
||||||
|
|
||||||
|
if(WIN32)
|
||||||
|
# Native Win32. REAPER provides nothing extra to link.
|
||||||
|
# Dialog resources return with the docked bank_panel (Milestone 5).
|
||||||
|
|
||||||
|
elseif(APPLE)
|
||||||
|
# macOS: use REAPER's OWN SWELL at runtime via the modstub.
|
||||||
|
# Do NOT build full SWELL. SWELL_PROVIDED_BY_APP routes calls to the host.
|
||||||
|
target_sources(reaper_reasampler PRIVATE ${SWELL}/swell-modstub.mm)
|
||||||
|
target_compile_definitions(reaper_reasampler PRIVATE SWELL_PROVIDED_BY_APP)
|
||||||
|
target_link_libraries(reaper_reasampler PRIVATE "-framework AppKit")
|
||||||
|
set_target_properties(reaper_reasampler PROPERTIES SUFFIX ".dylib")
|
||||||
|
# Dialog: run SWELL resgen once (see README) and add the generated source.
|
||||||
|
|
||||||
|
else()
|
||||||
|
# Linux: REAPER's libSwell.so is used at runtime via the generic modstub.
|
||||||
|
# With SWELL_PROVIDED_BY_APP you can drop pkg-config / -lX11 entirely.
|
||||||
|
target_sources(reaper_reasampler PRIVATE ${SWELL}/swell-modstub-generic.cpp)
|
||||||
|
target_compile_definitions(reaper_reasampler PRIVATE SWELL_PROVIDED_BY_APP)
|
||||||
|
set_target_properties(reaper_reasampler PROPERTIES SUFFIX ".so")
|
||||||
|
# Dialog: run SWELL resgen once (see README) and add the generated source.
|
||||||
|
endif()
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
#include "bank_model.h"
|
||||||
|
|
||||||
|
namespace reasampler {
|
||||||
|
|
||||||
|
int bankModelVersion()
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace reasampler
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
#pragma once
|
||||||
|
// bank_model — the HEART of ReaSampler, deliberately free of any REAPER type so
|
||||||
|
// it compiles and unit-tests OUTSIDE the DAW. It owns the per-project sample
|
||||||
|
// bank: the `Sample` metadata struct and the `BankIndex` (add / remove / query /
|
||||||
|
// tier moves / dedup-by-hash + JSON round-trip).
|
||||||
|
//
|
||||||
|
// Milestone 0 placeholder: this is a minimal compiling stub sufficient to stand
|
||||||
|
// up the pure static lib and its CTest. The full data model (Sample field set,
|
||||||
|
// BankIndex operations, JSON) is Milestone 1 — see PLAN.md / CONTEXT.md §Data model.
|
||||||
|
|
||||||
|
namespace reasampler {
|
||||||
|
|
||||||
|
// M0 placeholder — replaced by the real `Sample` / `BankIndex` in Milestone 1.
|
||||||
|
// Returns the on-disk schema version the bank_model serializes to.
|
||||||
|
int bankModelVersion();
|
||||||
|
|
||||||
|
} // namespace reasampler
|
||||||
@@ -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
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
// Standalone tests for reasampler::bank_model — no REAPER, no test framework.
|
||||||
|
// This is the point of splitting the model out: iterate the hard logic here with
|
||||||
|
// a fast build/run loop instead of restarting REAPER.
|
||||||
|
//
|
||||||
|
// Milestone 0 placeholder: a single assertion proving the pure lib links and
|
||||||
|
// runs under CTest. The real round-trip / dedup / tier / relative-path tests
|
||||||
|
// arrive with the Milestone 1 data model (see TODO.md, PLAN.md).
|
||||||
|
|
||||||
|
#include "../src/bank_model.h"
|
||||||
|
#include <cstdio>
|
||||||
|
|
||||||
|
using namespace reasampler;
|
||||||
|
|
||||||
|
static int g_fail = 0;
|
||||||
|
#define CHECK(cond) do { if(!(cond)) { \
|
||||||
|
std::printf("FAIL line %d: %s\n", __LINE__, #cond); ++g_fail; } } while(0)
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
CHECK(bankModelVersion() == 1);
|
||||||
|
|
||||||
|
if (g_fail == 0) std::printf("All tests passed.\n");
|
||||||
|
return g_fail ? 1 : 0;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user