Reorganize extension-reaper-macos into per-module subfolders, add hello module
Splits socket/tracking into their own subdirectories and pulls the hello action registration out into its own module, matching the one-module-per- folder pattern; build.sh now outputs into build/macos instead of the repo root. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1 +1 @@
|
|||||||
*.dylib
|
build/
|
||||||
|
|||||||
@@ -3,7 +3,11 @@
|
|||||||
set -e
|
set -e
|
||||||
cd "$(dirname "$0")"
|
cd "$(dirname "$0")"
|
||||||
|
|
||||||
OUT="reaper_extension-reaper-macos.dylib"
|
NAME="reaper_extension-reaper-macos.dylib"
|
||||||
|
OUT_DIR="build/macos"
|
||||||
|
OUT="$OUT_DIR/$NAME"
|
||||||
|
|
||||||
|
mkdir -p "$OUT_DIR"
|
||||||
|
|
||||||
clang++ \
|
clang++ \
|
||||||
-std=c++17 \
|
-std=c++17 \
|
||||||
@@ -12,13 +16,15 @@ clang++ \
|
|||||||
-arch arm64 \
|
-arch arm64 \
|
||||||
-Ivendor/reaper-sdk/sdk \
|
-Ivendor/reaper-sdk/sdk \
|
||||||
-Ivendor/reaper-sdk/WDL \
|
-Ivendor/reaper-sdk/WDL \
|
||||||
|
-Isrc \
|
||||||
-o "$OUT" \
|
-o "$OUT" \
|
||||||
src/main.cpp \
|
src/main.cpp \
|
||||||
src/tracking.cpp \
|
src/hello/hello.cpp \
|
||||||
src/socket.cpp
|
src/tracking/tracking.cpp \
|
||||||
|
src/socket/socket.cpp
|
||||||
|
|
||||||
echo "Built $OUT"
|
echo "Built $OUT"
|
||||||
|
|
||||||
DEST="$HOME/Library/Application Support/REAPER/UserPlugins/$OUT"
|
DEST="$HOME/Library/Application Support/REAPER/UserPlugins/$NAME"
|
||||||
cp "$OUT" "$DEST"
|
cp "$OUT" "$DEST"
|
||||||
echo "Copied to $DEST (restart REAPER to reload)"
|
echo "Copied to $DEST (restart REAPER to reload)"
|
||||||
|
|||||||
@@ -0,0 +1,63 @@
|
|||||||
|
#define REAPERAPI_MINIMAL
|
||||||
|
#define REAPERAPI_WANT_ShowConsoleMsg
|
||||||
|
|
||||||
|
#include "reaper_plugin.h"
|
||||||
|
#include "reaper_plugin_functions.h"
|
||||||
|
|
||||||
|
#include <cstdio>
|
||||||
|
|
||||||
|
static bool isOurAction;
|
||||||
|
static bool handled;
|
||||||
|
|
||||||
|
static int helloActionId = 0;
|
||||||
|
static const char *kHelloActionIdStr = "EXTENSION_REAPER_MACOS_HELLO";
|
||||||
|
static const char *kHelloActionName = "Hello Action List Display Name";
|
||||||
|
|
||||||
|
static bool HelloAction(KbdSectionInfo *sec, int command, int val, int val2, int relmode, HWND hwnd);
|
||||||
|
|
||||||
|
void RegisterHello(reaper_plugin_info_t *rec)
|
||||||
|
{
|
||||||
|
custom_action_register_t actionDescription = {
|
||||||
|
0,
|
||||||
|
kHelloActionIdStr,
|
||||||
|
kHelloActionName,
|
||||||
|
NULL,
|
||||||
|
};
|
||||||
|
helloActionId = rec->Register("custom_action", &actionDescription);
|
||||||
|
|
||||||
|
char buf[128];
|
||||||
|
snprintf(buf, sizeof(buf), "[extension-reaper-macos] helloActionId = %d\n", helloActionId);
|
||||||
|
ShowConsoleMsg(buf);
|
||||||
|
|
||||||
|
rec->Register("hookcommand2", (void *)HelloAction);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void PerformHelloAction()
|
||||||
|
{
|
||||||
|
ShowConsoleMsg("[extension-reaper-macos] Hello action triggered\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void RunHelloActionLogic(int command)
|
||||||
|
{
|
||||||
|
char buf[128];
|
||||||
|
snprintf(buf, sizeof(buf), "[extension-reaper-macos] HelloAction called: command=%d helloActionId=%d\n", command, helloActionId);
|
||||||
|
ShowConsoleMsg(buf);
|
||||||
|
|
||||||
|
isOurAction = (command == helloActionId);
|
||||||
|
|
||||||
|
if (isOurAction == true)
|
||||||
|
{
|
||||||
|
PerformHelloAction();
|
||||||
|
handled = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ShowConsoleMsg("[extension-reaper-macos] ignored — not ours\n");
|
||||||
|
handled = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool HelloAction(KbdSectionInfo *sec, int command, int val, int val2, int relmode, HWND hwnd)
|
||||||
|
{
|
||||||
|
RunHelloActionLogic(command);
|
||||||
|
return handled;
|
||||||
|
}
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
#define REAPERAPI_MINIMAL
|
||||||
|
#define REAPERAPI_WANT_ShowConsoleMsg
|
||||||
|
|
||||||
|
#include "reaper_plugin.h"
|
||||||
|
#include "reaper_plugin_functions.h"
|
||||||
|
#include "hello/hello.h"
|
||||||
|
|
||||||
|
#include <cstdio>
|
||||||
|
|
||||||
|
static bool isOurAction;
|
||||||
|
static bool handled;
|
||||||
|
|
||||||
|
static int helloActionId = 0;
|
||||||
|
static const char *kHelloActionIdStr = "EXTENSION_REAPER_MACOS_HELLO";
|
||||||
|
static const char *kHelloActionName = "Hello Action List Display Name";
|
||||||
|
|
||||||
|
static bool HelloAction(KbdSectionInfo *sec, int command, int val, int val2, int relmode, HWND hwnd);
|
||||||
|
static void HandleHelloAction(int command);
|
||||||
|
static void RunHelloAction();
|
||||||
|
|
||||||
|
//step 1 register
|
||||||
|
void RegisterHello(reaper_plugin_info_t *rec)
|
||||||
|
{
|
||||||
|
custom_action_register_t actionDescription = {
|
||||||
|
0,
|
||||||
|
kHelloActionIdStr,
|
||||||
|
kHelloActionName,
|
||||||
|
NULL,
|
||||||
|
};
|
||||||
|
helloActionId = rec->Register("custom_action", &actionDescription);
|
||||||
|
|
||||||
|
char buf[128];
|
||||||
|
snprintf(buf, sizeof(buf), "[extension-reaper-macos] helloActionId = %d\n", helloActionId);
|
||||||
|
ShowConsoleMsg(buf);
|
||||||
|
|
||||||
|
rec->Register("hookcommand2", (void *)HelloAction);
|
||||||
|
}
|
||||||
|
|
||||||
|
//step 2 callback from REAPER
|
||||||
|
static bool HelloAction(KbdSectionInfo *sec, int command, int val, int val2, int relmode, HWND hwnd)
|
||||||
|
{
|
||||||
|
HandleHelloAction(command);
|
||||||
|
return handled;
|
||||||
|
}
|
||||||
|
//step 3 check whether the ID REAPER gave us is our registered action, and dispatch to step 4 if so
|
||||||
|
static void HandleHelloAction(int command)
|
||||||
|
{
|
||||||
|
char buf[128];
|
||||||
|
snprintf(buf, sizeof(buf), "[extension-reaper-macos] HelloAction called: command=%d helloActionId=%d\n", command, helloActionId);
|
||||||
|
ShowConsoleMsg(buf);
|
||||||
|
|
||||||
|
isOurAction = (command == helloActionId);
|
||||||
|
|
||||||
|
if (isOurAction == true)
|
||||||
|
{
|
||||||
|
RunHelloAction();
|
||||||
|
handled = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ShowConsoleMsg("[extension-reaper-macos] ignored — not ours\n");
|
||||||
|
handled = false;
|
||||||
|
}
|
||||||
|
//step 4 perform action
|
||||||
|
static void RunHelloAction()
|
||||||
|
{
|
||||||
|
ShowConsoleMsg("[extension-reaper-macos] Hello action triggered\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
// The "Hello" test action — the first thing built in this extension, to
|
||||||
|
// prove custom_action registration + hookcommand2 callbacks work end to
|
||||||
|
// end. Kept around as a working reference, not load-bearing for the real
|
||||||
|
// feature.
|
||||||
|
|
||||||
|
#ifndef EXTENSION_REAPER_MACOS_HELLO_H
|
||||||
|
#define EXTENSION_REAPER_MACOS_HELLO_H
|
||||||
|
|
||||||
|
#include "reaper_plugin.h"
|
||||||
|
|
||||||
|
// Call once from the entrypoint, after REAPERAPI_LoadAPI has succeeded.
|
||||||
|
void RegisterHello(reaper_plugin_info_t *rec);
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -1,27 +1,21 @@
|
|||||||
// extension-reaper-macos — bare-minimum REAPER extension.
|
// extension-reaper-macos — REAPER extension entry point.
|
||||||
//
|
//
|
||||||
// Loads, registers one test action ("extension-reaper-macos: Hello"), and
|
// This file's only job: establish REAPER_PLUGIN_ENTRYPOINT (the one
|
||||||
// prints a confirmation to the REAPER console.
|
// function name REAPER looks for), do the required load/unload/version
|
||||||
|
// checks, then delegate everything else to its own module — hello/,
|
||||||
|
// tracking/, socket/.
|
||||||
//
|
//
|
||||||
// Top-level story:
|
// Top-level story:
|
||||||
// - We tell the compiler which REAPER functions we need a box for.
|
// - We tell the compiler which REAPER functions we need a box for. This
|
||||||
|
// file has to cover everything used anywhere in the project, since it's
|
||||||
|
// the one with REAPERAPI_IMPLEMENT — the one that owns the real storage.
|
||||||
// - REAPER loads our .dylib and calls our one required function, once.
|
// - REAPER loads our .dylib and calls our one required function, once.
|
||||||
// - We check we're actually loading, not unloading, and the version matches.
|
// - We check we're actually loading, not unloading, and the version matches.
|
||||||
// - We fill our function box(es) with their real address.
|
// - We fill our function box(es) with their real address.
|
||||||
// - We describe a new action and hand it to REAPER — it creates it, gives
|
// - We delegate to each module's own Register___(rec) function.
|
||||||
// us back a number.
|
|
||||||
// - We subscribe our own function to REAPER's "every action, any trigger"
|
|
||||||
// stream.
|
|
||||||
// - We print "loaded successfully" — proof of everything up to that point,
|
// - We print "loaded successfully" — proof of everything up to that point,
|
||||||
// but NOT proof the action/subscription actually works.
|
// but NOT proof any individual module actually works.
|
||||||
// - Setup's done. We now just sit in memory, doing nothing.
|
|
||||||
// - Later, any action anywhere in REAPER (click, key, MIDI, OSC) calls our
|
|
||||||
// subscribed function.
|
|
||||||
// - It checks if the action was ours. If yes, react. If no, ignore.
|
|
||||||
|
|
||||||
// We tell the compiler which REAPER functions we need a box for. This file
|
|
||||||
// owns the real storage (REAPERAPI_IMPLEMENT), so this list has to cover
|
|
||||||
// everything used anywhere in the project, including tracking.cpp.
|
|
||||||
#define REAPERAPI_MINIMAL
|
#define REAPERAPI_MINIMAL
|
||||||
#define REAPERAPI_WANT_ShowConsoleMsg
|
#define REAPERAPI_WANT_ShowConsoleMsg
|
||||||
#define REAPERAPI_WANT_CountAutomationItems
|
#define REAPERAPI_WANT_CountAutomationItems
|
||||||
@@ -34,79 +28,76 @@
|
|||||||
|
|
||||||
#include "reaper_plugin.h"
|
#include "reaper_plugin.h"
|
||||||
#include "reaper_plugin_functions.h"
|
#include "reaper_plugin_functions.h"
|
||||||
#include "tracking.h"
|
#include "hello/hello.h"
|
||||||
#include "socket.h"
|
#include "tracking/tracking.h"
|
||||||
|
#include "socket/socket.h"
|
||||||
|
|
||||||
#include <cstdio>
|
// Return values REAPER expects back from us.
|
||||||
|
const int kUnloadOrIncompatible = 0;
|
||||||
|
const int kLoadedSuccessfully = 1;
|
||||||
|
|
||||||
static int action1_id = 0;
|
static bool CheckerExtLoadingOrUnloading(reaper_plugin_info_t *rec);
|
||||||
static const char *kAction1IdStr = "EXTENSION_REAPER_MACOS_HELLO";
|
static bool CheckerExtVersionMatches(reaper_plugin_info_t *rec);
|
||||||
static const char *kAction1Name = "Hello Action List Display Name";
|
static bool CheckerExtFunctionsLoaded(reaper_plugin_info_t *rec);
|
||||||
|
static void RegisterActions(reaper_plugin_info_t *rec);
|
||||||
// Testing hookcommand2 again (REAPER's docs specifically recommend it for
|
|
||||||
// custom_action-registered actions), this time with debug prints kept in.
|
|
||||||
static bool Action1(KbdSectionInfo *sec, int command, int val, int val2, int relmode, HWND hwnd)
|
|
||||||
{
|
|
||||||
// Unconditional — proves whether this callback is being reached at all,
|
|
||||||
// and for which command IDs, regardless of whether it's ours.
|
|
||||||
char buf[128];
|
|
||||||
snprintf(buf, sizeof(buf), "[extension-reaper-macos] Action1 called: command=%d action1_id=%d\n", command, action1_id);
|
|
||||||
ShowConsoleMsg(buf);
|
|
||||||
|
|
||||||
if (command == action1_id)
|
|
||||||
{
|
|
||||||
ShowConsoleMsg("[extension-reaper-macos] Hello action triggered\n");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
ShowConsoleMsg("[extension-reaper-macos] ignored — not ours\n");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// REAPER loads our .dylib and calls this once.
|
// REAPER loads our .dylib and calls this once.
|
||||||
extern "C" REAPER_PLUGIN_DLL_EXPORT int REAPER_PLUGIN_ENTRYPOINT(REAPER_PLUGIN_HINSTANCE hInstance, reaper_plugin_info_t *rec)
|
extern "C" REAPER_PLUGIN_DLL_EXPORT int REAPER_PLUGIN_ENTRYPOINT(REAPER_PLUGIN_HINSTANCE hInstance, reaper_plugin_info_t *rec)
|
||||||
{
|
{
|
||||||
// Check we're actually loading, not unloading, and the version matches.
|
if (CheckerExtLoadingOrUnloading(rec) == true)
|
||||||
if (!rec)
|
{
|
||||||
return 0;
|
return kUnloadOrIncompatible;
|
||||||
if (rec->caller_version != REAPER_PLUGIN_VERSION)
|
}
|
||||||
return 0;
|
|
||||||
|
|
||||||
// Fill our function box(es) with their real address.
|
if (CheckerExtVersionMatches(rec) == false)
|
||||||
if (REAPERAPI_LoadAPI(rec->GetFunc) != 0)
|
{
|
||||||
return 0;
|
return kUnloadOrIncompatible;
|
||||||
|
}
|
||||||
|
|
||||||
// Describe a new action and hand it to REAPER — it creates it, gives us
|
if (CheckerExtFunctionsLoaded(rec) == false)
|
||||||
// back a number, which we save.
|
{
|
||||||
custom_action_register_t actionDescription = {
|
return kUnloadOrIncompatible;
|
||||||
0,
|
}
|
||||||
kAction1IdStr,
|
|
||||||
kAction1Name,
|
|
||||||
NULL,
|
|
||||||
};
|
|
||||||
action1_id = rec->Register("custom_action", &actionDescription);
|
|
||||||
|
|
||||||
// Verify registration actually succeeded — Register returns 0 on failure,
|
RegisterActions(rec);
|
||||||
// and we've never checked that until now.
|
|
||||||
char buf[128];
|
|
||||||
snprintf(buf, sizeof(buf), "[extension-reaper-macos] action1_id = %d\n", action1_id);
|
|
||||||
ShowConsoleMsg(buf);
|
|
||||||
|
|
||||||
// Subscribe Action1 via hookcommand2 — REAPER's documented pairing for
|
// Prove we got this far — but NOT proof any individual module works.
|
||||||
// custom_action-registered actions specifically.
|
|
||||||
rec->Register("hookcommand2", (void *)Action1);
|
|
||||||
|
|
||||||
// Envelope/automation-item polling now lives in tracking.cpp.
|
|
||||||
RegisterTracking(rec);
|
|
||||||
|
|
||||||
// Basic UDP socket listener lives in socket.cpp.
|
|
||||||
RegisterSocket(rec);
|
|
||||||
|
|
||||||
// Print "loaded successfully" — proof of everything above, but NOT proof
|
|
||||||
// the action/subscription actually works.
|
|
||||||
ShowConsoleMsg("[extension-reaper-macos] loaded successfully\n");
|
ShowConsoleMsg("[extension-reaper-macos] loaded successfully\n");
|
||||||
|
|
||||||
// Setup's done. Return 1 = "keep me loaded." We now just sit in memory,
|
return kLoadedSuccessfully;
|
||||||
// doing nothing, until Action1 gets called later.
|
}
|
||||||
return 1;
|
|
||||||
|
// Checks whether REAPER is unloading us (rec is NULL) rather than loading
|
||||||
|
// us. Safe to call no matter what — this IS the check for whether rec is
|
||||||
|
// even safe to use for anything else.
|
||||||
|
static bool CheckerExtLoadingOrUnloading(reaper_plugin_info_t *rec)
|
||||||
|
{
|
||||||
|
bool isUnloading = (rec == NULL);
|
||||||
|
return isUnloading;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Checks whether this REAPER's plugin format matches what we expect. Only
|
||||||
|
// call after CheckerExtLoadingOrUnloading has confirmed rec is real.
|
||||||
|
static bool CheckerExtVersionMatches(reaper_plugin_info_t *rec)
|
||||||
|
{
|
||||||
|
bool versionMatches = (rec->caller_version == REAPER_PLUGIN_VERSION);
|
||||||
|
return versionMatches;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fetches every REAPER function we WANT'd above, and checks whether all of
|
||||||
|
// them were found. Only call once we know rec is real.
|
||||||
|
static bool CheckerExtFunctionsLoaded(reaper_plugin_info_t *rec)
|
||||||
|
{
|
||||||
|
int missingFunctionCount = REAPERAPI_LoadAPI(rec->GetFunc);
|
||||||
|
bool allFunctionsLoaded = (missingFunctionCount == 0);
|
||||||
|
return allFunctionsLoaded;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delegates to each module's own Register___(rec) function — one place
|
||||||
|
// that lists every module this extension is made of.
|
||||||
|
static void RegisterActions(reaper_plugin_info_t *rec)
|
||||||
|
{
|
||||||
|
RegisterHello(rec);
|
||||||
|
RegisterTracking(rec);
|
||||||
|
RegisterSocket(rec);
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -16,8 +16,8 @@
|
|||||||
|
|
||||||
#include "reaper_plugin.h"
|
#include "reaper_plugin.h"
|
||||||
#include "reaper_plugin_functions.h"
|
#include "reaper_plugin_functions.h"
|
||||||
#include "socket.h"
|
#include "socket/socket.h"
|
||||||
#include "tracking.h"
|
#include "tracking/tracking.h"
|
||||||
|
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
+1
-1
@@ -20,7 +20,7 @@
|
|||||||
|
|
||||||
#include "reaper_plugin.h"
|
#include "reaper_plugin.h"
|
||||||
#include "reaper_plugin_functions.h"
|
#include "reaper_plugin_functions.h"
|
||||||
#include "tracking.h"
|
#include "tracking/tracking.h"
|
||||||
|
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
Reference in New Issue
Block a user