26e2bf2fc6
S17: drag_out InstrumentDrop gesture + instrument_drop blob reusing the instrument's own serializer; bank_panel FX hover-track + add-VST/vst_chunk inject. S13 relay deferred (read-only bridge) — editor shows drop affordance.
1028 lines
63 KiB
CMake
1028 lines
63 KiB
CMake
cmake_minimum_required(VERSION 3.19)
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# Version — SINGLE SOURCE OF TRUTH (Phase V, V1). Edit REASAMPLER_VERSION here and
|
||
# nowhere else: it flows to the binary constant, the ext-state writing-version stamp,
|
||
# and the "show version" action via a configure_file'd header (below). The string is
|
||
# authoritative verbatim — leading zero preserved (Daniel-fixed: exactly "0.9.01",
|
||
# two-digit zero-padded patch). We deliberately do NOT reconstruct the display string
|
||
# from project(VERSION)'s numeric components, since CMake may normalize a numeric patch
|
||
# field; the string variable is what renders. project(VERSION ...) is still set (with a
|
||
# normalized 0.9.1 triple) for CMake hygiene / any downstream numeric use, but it is NOT
|
||
# the rendered source of truth.
|
||
set(REASAMPLER_VERSION "0.9.01")
|
||
|
||
project(reaper_reasampler VERSION 0.9.1 LANGUAGES CXX)
|
||
|
||
set(CMAKE_CXX_STANDARD 17)
|
||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# Channel — SINGLE SOURCE OF TRUTH for beta-in-isolation (Phase V, V4). One flag,
|
||
# `-DREASAMPLER_CHANNEL=beta`, forks the whole channel identity from one build tree:
|
||
# absent (or `stable`) = today's build with BYTE-IDENTICAL identity (binary name,
|
||
# ext-state namespace, command-id strings, version render); `beta` = a fully isolated
|
||
# `reaper_reasampler_beta` that coexists with stable in one REAPER. The flag reduces to
|
||
# ONE bit (REASAMPLER_CHANNEL_IS_BETA) threaded through the SAME configure_file'd header
|
||
# as the version string, so the pure app_version module derives every channel-qualified
|
||
# identity from it — no scattered #ifdefs. Any value other than exactly `beta` is treated
|
||
# as stable (a typo must not silently produce a half-forked build), and we hard-error on
|
||
# an unrecognized non-empty value so a misspelled `-DREASAMPLER_CHANNEL=betaa` is caught
|
||
# at configure time rather than shipping stable identity under a beta intent.
|
||
set(REASAMPLER_CHANNEL "stable" CACHE STRING "Build channel: stable (default) or beta")
|
||
if(REASAMPLER_CHANNEL STREQUAL "beta")
|
||
set(REASAMPLER_CHANNEL_IS_BETA 1)
|
||
set(REASAMPLER_OUTPUT_NAME "reaper_reasampler_beta")
|
||
# The VST3 instrument's on-disk name forks the same way (S18) — must match
|
||
# app_version::vstOutputName() so the artifact name and the in-binary self-id agree.
|
||
set(REASAMPLER_VST_OUTPUT_NAME "reasampler_9000_beta")
|
||
elseif(REASAMPLER_CHANNEL STREQUAL "stable")
|
||
set(REASAMPLER_CHANNEL_IS_BETA 0)
|
||
set(REASAMPLER_OUTPUT_NAME "reaper_reasampler")
|
||
set(REASAMPLER_VST_OUTPUT_NAME "reasampler_9000")
|
||
else()
|
||
message(FATAL_ERROR
|
||
"REASAMPLER_CHANNEL must be 'stable' or 'beta' (got '${REASAMPLER_CHANNEL}')")
|
||
endif()
|
||
|
||
# Generate version_generated.h from the one REASAMPLER_VERSION variable + the channel bit.
|
||
# Regenerated at configure time whenever either changes; the exact string is substituted
|
||
# verbatim and the channel bit fans out through app_version.
|
||
configure_file(
|
||
${CMAKE_CURRENT_SOURCE_DIR}/src/version_generated.h.in
|
||
${CMAKE_CURRENT_BINARY_DIR}/generated/version_generated.h
|
||
@ONLY)
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# 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) Pure peaks library — NO REAPER, NO SWELL. Waveform min/max thumbnails from
|
||
# raw PCM (Milestone 2). A sibling pure lib, kept distinct from bank_model.
|
||
# ---------------------------------------------------------------------------
|
||
add_library(peaks STATIC src/peaks.cpp)
|
||
target_include_directories(peaks PUBLIC src)
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# 2b) Pure capture-path arithmetic — NO REAPER, NO SWELL. Bank-folder / unique
|
||
# file-name / project-relative path derivation for the capture shell (M3).
|
||
# Split out so the fiddly path logic is unit-tested outside the DAW.
|
||
# ---------------------------------------------------------------------------
|
||
add_library(capture_paths STATIC src/capture_paths.cpp)
|
||
target_include_directories(capture_paths PUBLIC src)
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# 2c) Pure bank-grid layout — NO REAPER, NO SWELL. Grid tiling math (panel WxH +
|
||
# cell size + N -> cell rects, wrapping, partial last row) and the thumbnail
|
||
# cache key for the docked bank_panel (M5). Split out so the layout logic is
|
||
# unit-tested outside the DAW; the panel shell (SWELL/LICE/PCM) is DAW-verified.
|
||
# ---------------------------------------------------------------------------
|
||
add_library(bank_grid STATIC src/bank_grid.cpp)
|
||
target_include_directories(bank_grid PUBLIC src)
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# 2c') Pure mode_switch layout — NO REAPER, NO SWELL. The Design-View mode-switch
|
||
# geometry (D5): header rect + N modes -> N equal segment rects (exact tiling),
|
||
# and point -> segment hit-test. Split out so the switch's layout math is
|
||
# unit-tested outside the DAW; the bank_panel header strip that draws it and
|
||
# routes clicks to view::applyMode is DAW-verified. Mirror of bank_grid.
|
||
# ---------------------------------------------------------------------------
|
||
add_library(mode_switch STATIC src/mode_switch.cpp)
|
||
target_include_directories(mode_switch PUBLIC src)
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# 2c'') Pure tab_strip layout — NO REAPER, NO SWELL. The named-banks tab-strip
|
||
# geometry (B4): strip rect + N tabs at a fixed tab width + scroll offset ->
|
||
# per-tab rects (overflow-clipped), overflow chevron reservation + maxScroll,
|
||
# and point -> tab / chevron hit-test. Split out so the strip's layout +
|
||
# overflow/scroll math is unit-tested outside the DAW; the bank_panel region
|
||
# that draws it and routes clicks is DAW-verified. Mirror of mode_switch.
|
||
# ---------------------------------------------------------------------------
|
||
add_library(tab_strip STATIC src/tab_strip.cpp)
|
||
target_include_directories(tab_strip PUBLIC src)
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# 2d) Pure view_mode_model library — NO REAPER, NO SWELL. The Design View heart
|
||
# (Phase D1): mode registry + GUID-keyed membership index + folder-tree-aware
|
||
# visibility derivation + parking/restore planner + JSON round-trip. Mirror of
|
||
# bank_model; the folder tree is an INPUT supplied by the D2 shell.
|
||
# ---------------------------------------------------------------------------
|
||
add_library(view_mode_model STATIC src/view_mode_model.cpp)
|
||
target_include_directories(view_mode_model PUBLIC src)
|
||
# The pure lane-minting decision (planLaneMinting) names managed lanes via the ONE
|
||
# durable-key convention in lane_keys (laneNameForMode), so the model depends on that
|
||
# pure sibling. PUBLIC so every consumer (tests + module) resolves the symbol.
|
||
target_link_libraries(view_mode_model PUBLIC lane_keys)
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# 2d) Pure view_tree library — NO REAPER, NO SWELL. The one testable-outside-DAW
|
||
# piece of the D2 view shell: turning REAPER's linear I_FOLDERDEPTH stream into
|
||
# the parent<->child FolderTree the model consumes. The REAPER reads stay in
|
||
# view.cpp; this fiddly folder-depth walk is unit-tested here (mirrors
|
||
# capture_paths splitting the path math out of the capture shell).
|
||
# ---------------------------------------------------------------------------
|
||
add_library(view_tree STATIC src/view_tree.cpp)
|
||
target_include_directories(view_tree PUBLIC src)
|
||
target_link_libraries(view_tree PUBLIC view_mode_model)
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# 2d'') Pure guid_diff library — NO REAPER, NO SWELL. The D2 Wave-2 new-content
|
||
# detection core: current \ previous GUID diff + the first-poll-after-open
|
||
# baseline guard (and per-project reset). Split out so the fiddly baseline/diff
|
||
# logic is unit-tested outside the DAW; the bank_panel timer that reads REAPER's
|
||
# live track/item GUID set and applies the tags is DAW-verified. Mirror of
|
||
# view_tree splitting the folder-depth walk out of view.cpp.
|
||
# ---------------------------------------------------------------------------
|
||
add_library(guid_diff STATIC src/guid_diff.cpp)
|
||
target_include_directories(guid_diff PUBLIC src)
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# 2d''') Pure lane_keys library — NO REAPER, NO SWELL. The managed/manual fixed-lane
|
||
# heuristic (D2 Wave-2): a lane whose durable P_LANENAME:n carries the
|
||
# "reasampler:" prefix is tool-managed and keyed by that stable name; any other
|
||
# lane is user-minted manual and off-limits. Resolves design point #1 (auto-tag
|
||
# exemption) and #2 (name-keyed identity survives ordinal renumber). Split out
|
||
# so the prefix rule is unit-tested; view.cpp reads the names from REAPER.
|
||
# ---------------------------------------------------------------------------
|
||
add_library(lane_keys STATIC src/lane_keys.cpp)
|
||
target_include_directories(lane_keys PUBLIC src)
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# 2e) Pure insert_plan library — NO REAPER, NO SWELL. The InsertMedia `mode`
|
||
# bitmask arithmetic behind the `insert` shell (M6). Split out so the
|
||
# load-bearing bit computation (no silent stretch, opt-in conform) is
|
||
# unit-tested outside the DAW; the InsertMedia call itself is DAW-verified.
|
||
# ---------------------------------------------------------------------------
|
||
add_library(insert_plan STATIC src/insert_plan.cpp)
|
||
target_include_directories(insert_plan PUBLIC src)
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# 2f) Pure render_settings library — NO REAPER, NO SWELL. The M7 capture-family
|
||
# logic: source-mode + wet/dry -> RENDER_SETTINGS bit value, P_RAZOREDITS
|
||
# string -> time ranges + union bound, and the capture-action taxonomy table.
|
||
# Split out so the fiddly bit-mapping / razor-parsing is unit-tested outside
|
||
# the DAW; the render-driving + selection reads stay in capture.cpp / main.cpp.
|
||
# Depends on bank_model for the pure SourceMode enum.
|
||
# ---------------------------------------------------------------------------
|
||
add_library(render_settings STATIC src/render_settings.cpp)
|
||
target_include_directories(render_settings PUBLIC src)
|
||
target_link_libraries(render_settings PUBLIC bank_model)
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# 2f'') Pure batch_capture library — NO REAPER, NO SWELL. The M11 batch-capture
|
||
# logic: an ordered list of source ranges (one per selected item / per razor
|
||
# area) -> validated, ordinal-assigned capture units (empty/inverted dropped),
|
||
# plus order-preserving per-unit result aggregation into a mixed-result summary
|
||
# line. Split out so the plan/aggregate/summary is unit-tested outside the DAW;
|
||
# the selection read, transient re-selection, and render loop stay in main.cpp.
|
||
# No dependency on bank_model — it takes plain ranges/values at its boundary.
|
||
# ---------------------------------------------------------------------------
|
||
add_library(batch_capture STATIC src/batch_capture.cpp)
|
||
target_include_directories(batch_capture PUBLIC src)
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# 2f') Pure tail_control library — NO REAPER, NO SWELL. The docked bank_panel's
|
||
# tail-mode toggle logic (T1 exposure): TailSetting state, cycle order
|
||
# (None->Auto->Manual->None), the manual-length clamp to the 8 s cap, and the
|
||
# toggle label text. Split out so the toggle's cycle/clamp/label is unit-tested
|
||
# outside the DAW; the bank_panel footer that draws it + routes clicks is
|
||
# DAW-verified. Depends on render_settings for the pure TailMode enum + caps.
|
||
# ---------------------------------------------------------------------------
|
||
add_library(tail_control STATIC src/tail_control.cpp)
|
||
target_include_directories(tail_control PUBLIC src)
|
||
target_link_libraries(tail_control PUBLIC render_settings)
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# 2g') Pure bank_book library — NO REAPER, NO SWELL. The multi-bank phase heart
|
||
# (Phase B1): an ordered registry of banks (pool seeded as bank-zero + named
|
||
# banks), each wrapping a BankIndex; create/rename/reorder/delete named banks,
|
||
# pool privileges enforced in-model, active-bank id, index-only move/copy of a
|
||
# sample between banks, JSON round-trip + legacy-bank_index→pool migration.
|
||
# Mirror of bank_model / view_mode_model; wraps BankIndex (bank_model untouched).
|
||
# ---------------------------------------------------------------------------
|
||
add_library(bank_book STATIC src/bank_book.cpp)
|
||
target_include_directories(bank_book PUBLIC src)
|
||
target_link_libraries(bank_book PUBLIC bank_model)
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# 2g'') Pure owned_manifest library — NO REAPER, NO SWELL. The owned-file manifest
|
||
# seam (Phase B B-cap): the set of project-relative files the capture path
|
||
# itself created, so Phase R prune can tell the bank system's own orphans from
|
||
# hand-dropped files. Deliberately DECOUPLED from bank_book — it tracks files
|
||
# CREATED, not index membership (sample-remove is not manifest-remove). Small
|
||
# pure type + JSON round-trip; mirror of wav_trim / tab_strip. B-cap writes +
|
||
# persists it; Phase R (R1/R2) consumes it — no prune logic here.
|
||
# ---------------------------------------------------------------------------
|
||
add_library(owned_manifest STATIC src/owned_manifest.cpp)
|
||
target_include_directories(owned_manifest PUBLIC src)
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# 2g''') Pure prune_reconcile library — NO REAPER, NO SWELL, NO filesystem. The
|
||
# Phase R (Reclaim) Wave-1 safety-critical decision: given the files present
|
||
# in the bank folder, the union of files referenced across every bank, and the
|
||
# owned-file manifest, compute the orphan set (owned ∩ present) − referenced.
|
||
# Mirror of view_mode_model::reconcile one level down (files, not GUIDs). Small
|
||
# pure function; R2/R3 wrap the two ends (folder enumeration + deletion) in the
|
||
# shell. Standalone — depends only on the standard library.
|
||
# ---------------------------------------------------------------------------
|
||
add_library(prune_reconcile STATIC src/prune_reconcile.cpp)
|
||
target_include_directories(prune_reconcile PUBLIC src)
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# 2g'''') Pure prune_button layout — NO REAPER, NO SWELL. The Phase R (Reclaim)
|
||
# Wave-3 (R3, fork R-E) prune-button geometry: footer rect -> right-anchored
|
||
# button rect (suppressed when the footer is too narrow), and point -> in/out
|
||
# hit-test. Split out so the button's placement + hit-test math is unit-tested
|
||
# outside the DAW; the bank_panel footer that draws it and dispatches the
|
||
# "Prune bank folder" command is DAW-verified. Mirror of mode_switch / tab_strip.
|
||
# ---------------------------------------------------------------------------
|
||
add_library(prune_button STATIC src/prune_button.cpp)
|
||
target_include_directories(prune_button PUBLIC src)
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# 2g) Pure realtime_record library — NO REAPER, NO SWELL. The M8 realtime-record
|
||
# logic: capture scope + FX-tap point -> I_RECMODE / I_RECMODE_FLAGS values,
|
||
# wet/dry -> tap point, and the recorded-file -> Sample mapping. Split out so
|
||
# the fiddly record-mode bit values + Sample population are unit-tested outside
|
||
# the DAW; the transport/temp-track/send/file-move recipe stays in capture.cpp.
|
||
# Depends on bank_model for the pure Sample / SourceMode types.
|
||
# ---------------------------------------------------------------------------
|
||
add_library(realtime_record STATIC src/realtime_record.cpp)
|
||
target_include_directories(realtime_record PUBLIC src)
|
||
target_link_libraries(realtime_record PUBLIC bank_model)
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# 2h) Pure wav_trim library — NO REAPER, NO SWELL. The realtime tail's (T2) PCM
|
||
# decay-scan trim needs to TRUNCATE the recorded 32-bit-float WAV at a frame
|
||
# boundary without corrupting the RIFF container. This module holds the fiddly,
|
||
# easy-to-get-wrong part unit-tested outside the DAW: parse the WAV geometry
|
||
# (fmt/data chunk walk + 32-bit-float verification), extract the tail-region
|
||
# floats to scan, and compute the truncate plan (kept byte length + the two
|
||
# patched RIFF/data size fields). The file read/write/truncate I/O stays in the
|
||
# realtime shell. Depends on peaks for the AudioSample float alias.
|
||
# ---------------------------------------------------------------------------
|
||
add_library(wav_trim STATIC src/wav_trim.cpp)
|
||
target_include_directories(wav_trim PUBLIC src)
|
||
target_link_libraries(wav_trim PUBLIC peaks)
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# 2i) Pure app_version library — NO REAPER, NO SWELL. The Phase V (V1) version-identity
|
||
# core: re-exports the ONE CMake-sourced version string (via the configure_file'd
|
||
# version_generated.h) and owns the pure parse/compare/classify logic — the semver
|
||
# ordering a within-channel forward migration needs, and the three-way writing-version
|
||
# classification (PreVersioning / Unknown / Stamped) persist reads back from ext state.
|
||
# Split out so the exact-string fidelity + parse/compare are unit-tested outside the
|
||
# DAW; the ext-state write/read (persist) and the show-version action (main) are shell.
|
||
# Depends on the generated header in the build tree (PUBLIC so every consumer sees it).
|
||
# ---------------------------------------------------------------------------
|
||
add_library(app_version STATIC src/app_version.cpp)
|
||
target_include_directories(app_version PUBLIC src ${CMAKE_CURRENT_BINARY_DIR}/generated)
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# 2j) Pure provenance library — NO REAPER, NO SWELL. The Milestone 10 core: the
|
||
# recorded capture recipe (CaptureRecipe) + the thin drift-fingerprint that
|
||
# rides in Provenance.fxChainSnapshot (P1=a), its build/parse round-trip, the
|
||
# FX-chain identity fold, and the pure parent-detection decision (resample-from-
|
||
# sample by resolved file path). Split out so the encoding + decision logic are
|
||
# unit-tested outside the DAW; the FX-chain query, capture re-run, and action
|
||
# registration stay in the shell (main.cpp / actions.cpp). No dependency on
|
||
# bank_model — it takes plain strings/values at its boundary.
|
||
# ---------------------------------------------------------------------------
|
||
add_library(provenance STATIC src/provenance.cpp)
|
||
target_include_directories(provenance PUBLIC src)
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# 2j') Pure assignment_request library — NO REAPER, NO SWELL, NO VST3. The S8 ingest
|
||
# assignment-request wire format: the (bankId, sampleId, generation) value the
|
||
# EXTENSION writes to "reasampler" ext-state after an ingest-with-assign, decoded by
|
||
# the VST3 instrument in a later dispatch. Only the wire (build/parse round-trip)
|
||
# lives here — writing it is the persist shell's job, reading it the instrument's.
|
||
# Split out (mirror of provenance / owned_manifest) so the format both artifacts
|
||
# depend on is unit-tested outside the DAW; the reader lands in a separate artifact,
|
||
# so the round-trip test is the contract guard. No dependency — plain strings + int64.
|
||
# ---------------------------------------------------------------------------
|
||
add_library(assignment_request STATIC src/assignment_request.cpp)
|
||
target_include_directories(assignment_request PUBLIC src)
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# 2k) Pure action_buttons library — NO REAPER, NO SWELL. The Milestone 11
|
||
# action-trigger button strip: strip rect + N buttons at a minimum width ->
|
||
# per-button rects (equal tiling; overflow HIDES excess on a narrow panel
|
||
# rather than clipping), point -> button hit-test, and the button label format
|
||
# (action name + SDK binding string -> label, with the unbound/blank case
|
||
# degraded to an explicit marker and an over-long binding truncated). Split out
|
||
# so the layout + label math is unit-tested outside the DAW; the bank_panel
|
||
# draw + NamedCommandLookup/Main_OnCommand dispatch + kbd_getTextFromCmd query
|
||
# are DAW-verified. Mirror of mode_switch / tab_strip.
|
||
# ---------------------------------------------------------------------------
|
||
add_library(action_buttons STATIC src/action_buttons.cpp)
|
||
target_include_directories(action_buttons PUBLIC src)
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# 2l) Pure drag_out library — NO REAPER, NO SWELL, NO OS/OLE. The Milestone 11
|
||
# native-OS-drag-out decision core: the gesture-boundary decision (drag state +
|
||
# pointer + panel rect -> internal drag / OS drag / none — the invariant-#4 seam
|
||
# that keeps the internal bank-to-bank drag byte-identical) and the drag path-list
|
||
# assembly (resolved sample paths -> de-duped, existing-only absolute path list with
|
||
# an explicit skip-missing / skip-unresolved policy). Split out so the boundary +
|
||
# set algebra are unit-tested outside the DAW; the OLE DoDragDrop / SWELL file-list
|
||
# initiation (drag_out_win) and the bank_panel gesture hook are DAW-verified. Mirror
|
||
# of action_buttons / mode_switch.
|
||
# ---------------------------------------------------------------------------
|
||
add_library(drag_out STATIC src/drag_out.cpp)
|
||
target_include_directories(drag_out PUBLIC src)
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# 2l') Pure instrument_drop library — NO REAPER, NO SWELL, NO VST3 SDK. The S17
|
||
# drop-and-load blob-construction core: turn the dragged capture id into the
|
||
# base64 "vst_chunk" the extension injects via TrackFX_SetNamedConfigParm so a
|
||
# freshly-added ReaSampler 9000 plays that capture. Reuses the instrument's OWN
|
||
# serializer (sample_map::serializeComponentState) — NOT a parallel byte writer —
|
||
# so the cross-artifact blob contract cannot drift; links sample_map (which pulls
|
||
# bank_book/wav_trim/sampler_core transitively) and NEITHER SDK. The round-trip
|
||
# test decodes back through the instrument's own reader. Mirror of assignment_request.
|
||
# ---------------------------------------------------------------------------
|
||
add_library(instrument_drop STATIC src/instrument_drop.cpp)
|
||
target_include_directories(instrument_drop PUBLIC src src/vst)
|
||
target_link_libraries(instrument_drop PUBLIC sample_map)
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# 2m) Pure theme library — NO REAPER, NO SWELL, NO LICE. The Phase L (L1) palette
|
||
# core of the shared drawing kit: a ROLE-based color model (bg/base..warn), the
|
||
# interaction-state transform (rest/hover/active/pressed/dragging/focus/disabled),
|
||
# the Direction C spectral hue ramp, and the WCAG contrast math that lets a unit
|
||
# test prove every text-on-surface pair clears its floor ("punch to the floor").
|
||
# THE SINGLE POINT OF CHANGE (DS-2): one direction constants block feeds roleColor;
|
||
# switching the visual direction is a one-file edit. The draw shell (draw_kit) turns
|
||
# a KitColor into a LICE_pixel at the boundary. Mirror of mode_switch — pure.
|
||
# ---------------------------------------------------------------------------
|
||
add_library(theme STATIC src/theme.cpp)
|
||
target_include_directories(theme PUBLIC src)
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# 2n) Pure component_geometry library — NO REAPER, NO SWELL, NO LICE. The Phase L (L1)
|
||
# generic component geometry the kit draws against: button box (inset + graceful
|
||
# suppression), horizontal slider track/handle/filled geometry + value<->px inverse,
|
||
# and list-row rect + hover hit-test. The kit-level primitives that don't already
|
||
# have a pure owner (bank_grid/mode_switch/tab_strip/action_buttons/prune_button
|
||
# stay the source of truth for THEIR surfaces). Names KitBox/KitButtonBox/
|
||
# SliderGeometry/ListRowBox avoid the existing ButtonRect/CellRect collisions.
|
||
# Mirror of prune_button — pure, CTest-covered.
|
||
# ---------------------------------------------------------------------------
|
||
add_library(component_geometry STATIC src/component_geometry.cpp)
|
||
target_include_directories(component_geometry PUBLIC src)
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# 2o) Pure action_bar library — NO REAPER, NO SWELL, NO LICE. The Phase L (L2)
|
||
# dock-panel layout redesign core: the TASK-GROUPED action bar geometry that
|
||
# supersedes the flat M11 action_buttons strip for the panel's action inventory —
|
||
# clusters (capture / placement / maintenance) tile the bar at a fixed button
|
||
# width with intra/inter-cluster gaps, each button carrying a label + keybinding
|
||
# micro sub-rect, whole trailing buttons dropped (never clipped) on a narrow panel,
|
||
# and point -> flat action index hit-test. Split out so the layout + hit-test math
|
||
# is unit-tested outside the DAW; the bank_panel L1-kit draw + NamedCommandLookup/
|
||
# Main_OnCommand dispatch + kbd_getTextFromCmd query are DAW-verified. Mirror of
|
||
# mode_switch / action_buttons / prune_button.
|
||
# ---------------------------------------------------------------------------
|
||
add_library(action_bar STATIC src/action_bar.cpp)
|
||
target_include_directories(action_bar PUBLIC src)
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# 2p) Pure footer_bar layout — NO REAPER, NO SWELL, NO LICE. The Phase L (L4)
|
||
# dock-panel button-layout enhancement's footer LEFT group: the narrowed
|
||
# [Arrange|Design] mode toggle, its compact per-mode count label, and the Tail
|
||
# button, laid out left-to-right with greedy right-reserve suppression (the RIGHT
|
||
# Prune button stays owned by prune_button). Point -> Toggle/Tail/None hit-test.
|
||
# Split out so the footer's new multi-affordance row math is unit-tested outside
|
||
# the DAW; the bank_panel L1-kit draw + tail-cycle/mode-activate dispatch are
|
||
# DAW-verified. Reuses prune_button's FooterRect input type. Mirror of action_bar /
|
||
# mode_switch / prune_button.
|
||
# ---------------------------------------------------------------------------
|
||
add_library(footer_bar STATIC src/footer_bar.cpp)
|
||
target_include_directories(footer_bar PUBLIC src)
|
||
target_link_libraries(footer_bar PUBLIC prune_button)
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# 2q) Pure overflow_menu layout — NO REAPER, NO SWELL, NO LICE. The Phase L (L5,
|
||
# refinement 1) top-toolbar "⋯" More-button geometry: band rect -> right-anchored
|
||
# menu-button rect (suppressed when the band is too narrow) + the horizontal reserve
|
||
# the action_bar must leave for it, and point -> in/out hit-test. Split out so the
|
||
# button placement + reserve math is unit-tested outside the DAW; the bank_panel
|
||
# L1-kit draw + TrackPopupMenu popup + NamedCommandLookup/Main_OnCommand dispatch are
|
||
# DAW-verified. Mirror of prune_button / mode_switch.
|
||
# ---------------------------------------------------------------------------
|
||
add_library(overflow_menu STATIC src/overflow_menu.cpp)
|
||
target_include_directories(overflow_menu PUBLIC src)
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# 2r) Pure mode_enable predicate — NO REAPER, NO SWELL, NO LICE. The Phase L (L5,
|
||
# refinement 3) opposite-mode tag-button enablement: (active mode id, button target
|
||
# mode) -> live/disabled, so only the buttons for the OPPOSITE of the active mode are
|
||
# clickable. Split out so both active modes are covered by CTest (not only whichever a
|
||
# DAW pass sat in); the bank_panel reads the active mode from view().activeModeId() and
|
||
# draws disabled buttons in the kit Disabled state. Depends on view_mode_model for the
|
||
# seed mode-id constants (kArrangeModeId / kDesignModeId — ONE home for the ids).
|
||
# ---------------------------------------------------------------------------
|
||
add_library(mode_enable STATIC src/mode_enable.cpp)
|
||
target_include_directories(mode_enable PUBLIC src)
|
||
target_link_libraries(mode_enable PUBLIC view_mode_model)
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# 2s) Pure tooltip layout — NO REAPER, NO SWELL, NO LICE. The Phase L (L5, refinement 2)
|
||
# custom hover-delay tooltip's placement geometry (anchor rect + text extent + client
|
||
# bounds -> tooltip box, preferring below, flipping above near the bottom edge, clamped
|
||
# to the client) + the action DISPLAY-PREFIX strip helper. Split out so placement + the
|
||
# prefix strip are unit-tested outside the DAW; the bank_panel hover timer + LICE overlay
|
||
# draw are DAW-verified. Mirror of prune_button / component_geometry.
|
||
# ---------------------------------------------------------------------------
|
||
add_library(tooltip STATIC src/tooltip.cpp)
|
||
target_include_directories(tooltip PUBLIC src)
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# 2t) Pure card_meta formatters — NO REAPER, NO SWELL, NO LICE. The Phase L (L7)
|
||
# decorative card metadata overlay's formatting: bars.beats.subdivisions from a
|
||
# capture-time tempo + meter stamp (F1) and seconds.milliseconds from length. Split
|
||
# out so the musical/wall-clock string derivation (with its bar-boundary + unstamped
|
||
# edge cases) is unit-tested outside the DAW; the bank_panel kit-text overlay draw is
|
||
# DAW-verified. Mirror of tooltip's prefix-strip helper — pure, CTest-covered.
|
||
# ---------------------------------------------------------------------------
|
||
add_library(card_meta STATIC src/card_meta.cpp)
|
||
target_include_directories(card_meta PUBLIC src)
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# 2u) Pure card_drag gesture — NO REAPER, NO SWELL, NO LICE, NO OS. The Phase L (L7)
|
||
# in-grid reorder drag decision logic: the F3 gesture precedence (leave-client ->
|
||
# OS-drag; else other-bank -> move/copy; else same-bank grid -> reorder/replace),
|
||
# the resolved-gesture -> cursor-cue map, and the sparse-aware slot rect layout +
|
||
# point -> slot hit-test (empties included). Split out so the precedence + slot math
|
||
# is unit-tested outside the DAW; the SWELL wiring + SetCursor call + drop-target draw
|
||
# are DAW-verified. Reuses drag_out's PanelClientRect/DragState + bank_grid's CellRect/
|
||
# GridSpec. Mirror of drag_out::decideGesture / bank_grid.
|
||
# ---------------------------------------------------------------------------
|
||
add_library(card_drag STATIC src/card_drag.cpp)
|
||
target_include_directories(card_drag PUBLIC src)
|
||
target_link_libraries(card_drag PUBLIC drag_out bank_grid)
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# 2v) Pure sampler_core library — NO VST3, NO REAPER, NO SWELL. The HEART of the
|
||
# Phase S MIDI-playback instrument (S3 / D3): polyphonic voice allocation with
|
||
# bounded stealing, an ADSR amplitude envelope, a key/velocity keymap with
|
||
# (note, velocity) -> zone resolution, and repitch/interpolation from a root note
|
||
# with loop-point-aware sustain. The mirror of bank_model / peaks / bank_book,
|
||
# tested hard outside any host. Lives under src/vst/ (it is instrument code) but
|
||
# links NEITHER SDK — the plain-data boundary is enforced structurally: the test
|
||
# target below links only sampler_core (+ its peaks dep for the AudioSample alias,
|
||
# the one house precedent wav_trim also relies on). The VST3 shell (src/vst/
|
||
# reasampler_processor.cpp) marshals MIDI/audio to/from it and is DAW-verified.
|
||
# ---------------------------------------------------------------------------
|
||
# pitch_shift (S16) — the pure duration-preserving PitchShifter (Preserve-engine DSP core).
|
||
# NO VST3/REAPER/SWELL/vendor: a hand-rolled OLA shifter chosen over WDL_SimplePitchShifter
|
||
# because that header drags <windows.h> (via wdltypes.h) into any TU that includes it, which
|
||
# cannot enter the pure sampler_core. Links only peaks (the AudioSample alias). sampler_core
|
||
# depends on it (Voice owns two PitchShifters).
|
||
add_library(pitch_shift STATIC src/vst/pitch_shift.cpp)
|
||
target_include_directories(pitch_shift PUBLIC src src/vst)
|
||
target_link_libraries(pitch_shift PUBLIC peaks)
|
||
|
||
add_library(sampler_core STATIC src/vst/sampler_core.cpp)
|
||
target_include_directories(sampler_core PUBLIC src src/vst)
|
||
target_link_libraries(sampler_core PUBLIC peaks pitch_shift)
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# 3) Standalone tests for the pure modules (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)
|
||
|
||
add_executable(peaks_tests tests/test_peaks.cpp)
|
||
target_link_libraries(peaks_tests PRIVATE peaks)
|
||
add_test(NAME peaks_tests COMMAND peaks_tests)
|
||
|
||
add_executable(capture_paths_tests tests/test_capture_paths.cpp)
|
||
target_link_libraries(capture_paths_tests PRIVATE capture_paths)
|
||
add_test(NAME capture_paths_tests COMMAND capture_paths_tests)
|
||
|
||
add_executable(bank_grid_tests tests/test_bank_grid.cpp)
|
||
target_link_libraries(bank_grid_tests PRIVATE bank_grid)
|
||
add_test(NAME bank_grid_tests COMMAND bank_grid_tests)
|
||
|
||
add_executable(mode_switch_tests tests/test_mode_switch.cpp)
|
||
target_link_libraries(mode_switch_tests PRIVATE mode_switch)
|
||
add_test(NAME mode_switch_tests COMMAND mode_switch_tests)
|
||
|
||
add_executable(tab_strip_tests tests/test_tab_strip.cpp)
|
||
target_link_libraries(tab_strip_tests PRIVATE tab_strip)
|
||
add_test(NAME tab_strip_tests COMMAND tab_strip_tests)
|
||
|
||
add_executable(view_mode_model_tests tests/test_view_mode_model.cpp)
|
||
target_link_libraries(view_mode_model_tests PRIVATE view_mode_model)
|
||
add_test(NAME view_mode_model_tests COMMAND view_mode_model_tests)
|
||
|
||
add_executable(view_tree_tests tests/test_view_tree.cpp)
|
||
target_link_libraries(view_tree_tests PRIVATE view_tree)
|
||
add_test(NAME view_tree_tests COMMAND view_tree_tests)
|
||
|
||
add_executable(guid_diff_tests tests/test_guid_diff.cpp)
|
||
target_link_libraries(guid_diff_tests PRIVATE guid_diff)
|
||
add_test(NAME guid_diff_tests COMMAND guid_diff_tests)
|
||
|
||
add_executable(lane_keys_tests tests/test_lane_keys.cpp)
|
||
target_link_libraries(lane_keys_tests PRIVATE lane_keys)
|
||
add_test(NAME lane_keys_tests COMMAND lane_keys_tests)
|
||
|
||
add_executable(insert_plan_tests tests/test_insert_plan.cpp)
|
||
target_link_libraries(insert_plan_tests PRIVATE insert_plan)
|
||
add_test(NAME insert_plan_tests COMMAND insert_plan_tests)
|
||
|
||
add_executable(render_settings_tests tests/test_render_settings.cpp)
|
||
target_link_libraries(render_settings_tests PRIVATE render_settings)
|
||
add_test(NAME render_settings_tests COMMAND render_settings_tests)
|
||
|
||
add_executable(batch_capture_tests tests/test_batch_capture.cpp)
|
||
target_link_libraries(batch_capture_tests PRIVATE batch_capture)
|
||
add_test(NAME batch_capture_tests COMMAND batch_capture_tests)
|
||
|
||
add_executable(tail_control_tests tests/test_tail_control.cpp)
|
||
target_link_libraries(tail_control_tests PRIVATE tail_control)
|
||
add_test(NAME tail_control_tests COMMAND tail_control_tests)
|
||
|
||
add_executable(realtime_record_tests tests/test_realtime_record.cpp)
|
||
target_link_libraries(realtime_record_tests PRIVATE realtime_record)
|
||
add_test(NAME realtime_record_tests COMMAND realtime_record_tests)
|
||
|
||
add_executable(bank_book_tests tests/test_bank_book.cpp)
|
||
target_link_libraries(bank_book_tests PRIVATE bank_book)
|
||
add_test(NAME bank_book_tests COMMAND bank_book_tests)
|
||
|
||
add_executable(wav_trim_tests tests/test_wav_trim.cpp)
|
||
target_link_libraries(wav_trim_tests PRIVATE wav_trim)
|
||
add_test(NAME wav_trim_tests COMMAND wav_trim_tests)
|
||
|
||
add_executable(owned_manifest_tests tests/test_owned_manifest.cpp)
|
||
target_link_libraries(owned_manifest_tests PRIVATE owned_manifest)
|
||
add_test(NAME owned_manifest_tests COMMAND owned_manifest_tests)
|
||
|
||
add_executable(prune_reconcile_tests tests/test_prune_reconcile.cpp)
|
||
target_link_libraries(prune_reconcile_tests PRIVATE prune_reconcile bank_book)
|
||
add_test(NAME prune_reconcile_tests COMMAND prune_reconcile_tests)
|
||
|
||
add_executable(prune_button_tests tests/test_prune_button.cpp)
|
||
target_link_libraries(prune_button_tests PRIVATE prune_button)
|
||
add_test(NAME prune_button_tests COMMAND prune_button_tests)
|
||
|
||
add_executable(app_version_tests tests/test_app_version.cpp)
|
||
target_link_libraries(app_version_tests PRIVATE app_version)
|
||
add_test(NAME app_version_tests COMMAND app_version_tests)
|
||
|
||
# The provenance test links bank_model too — it proves the recorded recipe survives
|
||
# the Sample-JSON round-trip (Provenance.fxChainSnapshot), the M1 seam M10 rides on.
|
||
add_executable(provenance_tests tests/test_provenance.cpp)
|
||
target_link_libraries(provenance_tests PRIVATE provenance bank_model)
|
||
add_test(NAME provenance_tests COMMAND provenance_tests)
|
||
|
||
add_executable(action_buttons_tests tests/test_action_buttons.cpp)
|
||
target_link_libraries(action_buttons_tests PRIVATE action_buttons)
|
||
add_test(NAME action_buttons_tests COMMAND action_buttons_tests)
|
||
|
||
add_executable(drag_out_tests tests/test_drag_out.cpp)
|
||
target_link_libraries(drag_out_tests PRIVATE drag_out)
|
||
add_test(NAME drag_out_tests COMMAND drag_out_tests)
|
||
|
||
# instrument_drop (S17): the drop-and-load vst_chunk blob builder. The round-trip test
|
||
# decodes the base64 back through the instrument's OWN reader (deserializeComponentState) to
|
||
# prove the extension injects exactly what setState accepts — the cross-artifact contract guard.
|
||
add_executable(instrument_drop_tests tests/test_instrument_drop.cpp)
|
||
target_link_libraries(instrument_drop_tests PRIVATE instrument_drop)
|
||
add_test(NAME instrument_drop_tests COMMAND instrument_drop_tests)
|
||
|
||
add_executable(theme_tests tests/test_theme.cpp)
|
||
target_link_libraries(theme_tests PRIVATE theme)
|
||
add_test(NAME theme_tests COMMAND theme_tests)
|
||
|
||
add_executable(component_geometry_tests tests/test_component_geometry.cpp)
|
||
target_link_libraries(component_geometry_tests PRIVATE component_geometry)
|
||
add_test(NAME component_geometry_tests COMMAND component_geometry_tests)
|
||
|
||
add_executable(action_bar_tests tests/test_action_bar.cpp)
|
||
target_link_libraries(action_bar_tests PRIVATE action_bar)
|
||
add_test(NAME action_bar_tests COMMAND action_bar_tests)
|
||
|
||
add_executable(footer_bar_tests tests/test_footer_bar.cpp)
|
||
target_link_libraries(footer_bar_tests PRIVATE footer_bar)
|
||
add_test(NAME footer_bar_tests COMMAND footer_bar_tests)
|
||
|
||
add_executable(overflow_menu_tests tests/test_overflow_menu.cpp)
|
||
target_link_libraries(overflow_menu_tests PRIVATE overflow_menu)
|
||
add_test(NAME overflow_menu_tests COMMAND overflow_menu_tests)
|
||
|
||
add_executable(mode_enable_tests tests/test_mode_enable.cpp)
|
||
target_link_libraries(mode_enable_tests PRIVATE mode_enable)
|
||
add_test(NAME mode_enable_tests COMMAND mode_enable_tests)
|
||
|
||
add_executable(tooltip_tests tests/test_tooltip.cpp)
|
||
target_link_libraries(tooltip_tests PRIVATE tooltip)
|
||
add_test(NAME tooltip_tests COMMAND tooltip_tests)
|
||
|
||
add_executable(card_meta_tests tests/test_card_meta.cpp)
|
||
target_link_libraries(card_meta_tests PRIVATE card_meta)
|
||
add_test(NAME card_meta_tests COMMAND card_meta_tests)
|
||
|
||
add_executable(card_drag_tests tests/test_card_drag.cpp)
|
||
target_link_libraries(card_drag_tests PRIVATE card_drag)
|
||
add_test(NAME card_drag_tests COMMAND card_drag_tests)
|
||
|
||
add_executable(assignment_request_tests tests/test_assignment_request.cpp)
|
||
target_link_libraries(assignment_request_tests PRIVATE assignment_request)
|
||
add_test(NAME assignment_request_tests COMMAND assignment_request_tests)
|
||
|
||
# sampler_core: the S3 heart. Links ONLY sampler_core (+ its peaks dep) — NEITHER the
|
||
# VST3 SDK nor the REAPER SDK — which is the structural proof of the plain-data
|
||
# boundary (a VST3/REAPER type in the core would fail to compile/link here).
|
||
# pitch_shift (S16): the pure Preserve-engine OLA shifter. Links ONLY pitch_shift (+ peaks) —
|
||
# NEITHER SDK — the same plain-data-boundary proof, and specifically the compile-time proof it
|
||
# does NOT drag in the WDL <windows.h> chain the built-in WDL shifter would.
|
||
add_executable(pitch_shift_tests tests/test_pitch_shift.cpp)
|
||
target_link_libraries(pitch_shift_tests PRIVATE pitch_shift)
|
||
add_test(NAME pitch_shift_tests COMMAND pitch_shift_tests)
|
||
|
||
add_executable(sampler_core_tests tests/test_sampler_core.cpp)
|
||
target_link_libraries(sampler_core_tests PRIVATE sampler_core)
|
||
add_test(NAME sampler_core_tests COMMAND sampler_core_tests)
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# 2i) Pure VST3-instrument helpers (Phase S1) — NO VST3, NO REAPER, NO SWELL/LICE.
|
||
# editor_geometry: the IPlugView LICE editor's rectangle layout + hit-test math
|
||
# (mirror of mode_switch/bank_grid). bridge_marshal: the REAPER VST-host bridge
|
||
# read marshalling — GetProjExtState result decode + a small JSON string-field
|
||
# reader (mirror of capture_paths/wav_trim). Both are unit-tested outside the DAW;
|
||
# the VST3 shell (src/vst/*) that draws/routes/invokes is DAW-verified.
|
||
# ---------------------------------------------------------------------------
|
||
add_library(editor_geometry STATIC src/vst/editor_geometry.cpp)
|
||
target_include_directories(editor_geometry PUBLIC src/vst)
|
||
|
||
add_library(bridge_marshal STATIC src/vst/bridge_marshal.cpp)
|
||
target_include_directories(bridge_marshal PUBLIC src/vst)
|
||
|
||
# embed_strip (Phase S6) — PURE layout + hit-test for the embedded TCP/MCP strip: the
|
||
# 128-key span -> zone-segment rects, point -> zone selection, and the level-band fill.
|
||
# The mirror of editor_geometry (whose Rect + contains() it reuses); unit-tested outside
|
||
# the DAW, while the embed shell (src/vst/reasampler_embed.cpp) marshals REAPER's embed
|
||
# messages (paint bitmap + mouse coords) into it. Links editor_geometry for the shared Rect.
|
||
add_library(embed_strip STATIC src/vst/embed_strip.cpp)
|
||
target_include_directories(embed_strip PUBLIC src/vst)
|
||
target_link_libraries(embed_strip PUBLIC editor_geometry)
|
||
|
||
# sample_map (Phase S4) — PURE mapping logic for the Tier-0 instrument: the live bank
|
||
# blob -> selected sample (via the SHARED bank_book JSON parse, NOT a second parser),
|
||
# interleaved->mono downmix (the Tier-0 channel policy), the Tier-0 chromatic keymap
|
||
# build, and the selected-sample instance-state (de)serialization. Links the three pure
|
||
# modules it composes — bank_book (shared JSON), wav_trim (shared WAV parse), and
|
||
# sampler_core (the Keymap/SampleData it yields) — and NEITHER SDK. The VST3 shell
|
||
# (reasampler_processor.cpp) does the bridge read + file I/O off the audio thread, then
|
||
# calls these; the process callback stays allocation-free.
|
||
add_library(sample_map STATIC src/vst/sample_map.cpp)
|
||
target_include_directories(sample_map PUBLIC src/vst src)
|
||
target_link_libraries(sample_map PUBLIC bank_book wav_trim sampler_core)
|
||
|
||
# capture_browser (Phase S10) — PURE card-grid + bank-filter-tab layout + hit-test for the
|
||
# capture-first editor's default face. The mirror of mode_switch/editor_geometry: the fiddly
|
||
# grid/tab arithmetic lives here, unit-tested outside the DAW; the editor shell draws each
|
||
# card's peak thumbnail + name + badge and routes clicks into it. Links editor_geometry for
|
||
# the shared Rect + contains(). NEITHER SDK.
|
||
add_library(capture_browser STATIC src/vst/capture_browser.cpp)
|
||
target_include_directories(capture_browser PUBLIC src/vst)
|
||
target_link_libraries(capture_browser PUBLIC editor_geometry)
|
||
|
||
# keyboard_strip (Phase S10) — PURE key-span<->pixel mapping, root marker, zone-bar rects +
|
||
# edge-grab hit regions, and the drag-delta note resolver for the capture-first editor's
|
||
# keyboard strip (single-capture root-set) and the opt-in Zones panel (S10-Z). The mirror of
|
||
# embed_strip; links editor_geometry for the shared Rect. NEITHER SDK.
|
||
add_library(keyboard_strip STATIC src/vst/keyboard_strip.cpp)
|
||
target_include_directories(keyboard_strip PUBLIC src/vst)
|
||
target_link_libraries(keyboard_strip PUBLIC editor_geometry)
|
||
|
||
# waveform_view (Phase S11) — PURE frame<->pixel mapping, marker grab regions, drag-delta
|
||
# frame resolver, and the zero-crossing snap for the capture-first editor's waveform surface
|
||
# (draggable start + loop markers over the picked capture's decoded PCM). The mirror of
|
||
# keyboard_strip; links editor_geometry for the shared Rect and peaks for the AudioSample
|
||
# alias the snap scans. NEITHER SDK.
|
||
add_library(waveform_view STATIC src/vst/waveform_view.cpp)
|
||
target_include_directories(waveform_view PUBLIC src/vst src)
|
||
target_link_libraries(waveform_view PUBLIC editor_geometry peaks)
|
||
|
||
# bank_sync (Phase S9/S8 reader) — PURE decision logic for the instrument's off-audio-thread
|
||
# poll: parse/compare the S9 bank-generation stamp, and the S8 assignment-request CONSUME
|
||
# decision (new-and-resolvable-and-target -> apply; unresolvable -> drop-and-mark; non-target
|
||
# -> stay eligible). The shell owns the timer cadence + side effects (reloadFromBank,
|
||
# setSelectedSampleId, component-state marker); this owns only the yes/no maths, unit-tested
|
||
# outside the DAW. Links assignment_request for the decoded AssignmentRequest it consumes.
|
||
# NEITHER SDK.
|
||
add_library(bank_sync STATIC src/vst/bank_sync.cpp)
|
||
target_include_directories(bank_sync PUBLIC src/vst src)
|
||
target_link_libraries(bank_sync PUBLIC assignment_request)
|
||
|
||
# browser_scroll (Phase S12) — PURE scroll-window + scrollbar-thumb + type-to-filter-search
|
||
# geometry LAYERED over the S10 capture_browser: the visible-card window, thumb rect +
|
||
# thumb-drag<->offset mapping, and the name-substring filter that composes with the bank
|
||
# filter. The mirror of capture_browser; links capture_browser (for BrowserLayout + the card
|
||
# metrics/cell rect) which pulls editor_geometry transitively. NEITHER SDK.
|
||
add_library(browser_scroll STATIC src/vst/browser_scroll.cpp)
|
||
target_include_directories(browser_scroll PUBLIC src/vst)
|
||
target_link_libraries(browser_scroll PUBLIC capture_browser)
|
||
|
||
# note_entry (Phase S12) — PURE text->clamped-MIDI-note parse for the direct numeric entry of
|
||
# a zone's low/high/root (decimal integer OR note name under the C4==60 convention, clamped to
|
||
# [0,127]). No dependency beyond the standard library. NEITHER SDK.
|
||
add_library(note_entry STATIC src/vst/note_entry.cpp)
|
||
target_include_directories(note_entry PUBLIC src/vst)
|
||
|
||
# param_slider (Phase S12 + the S15/S16 control surfaces deferred here) — PURE control-surface
|
||
# layout + hit-test + normalized value<->pixel mapping for the editor parameter panel (the
|
||
# Gate|Trigger + Varispeed|Preserve toggles and the AHDSR / Trigger / pitch-env sliders). The
|
||
# mirror of keyboard_strip; links editor_geometry for the shared Rect. Deliberately engine-free
|
||
# (no sampler_core types) — the shell owns the control-id -> param binding + the value DOMAIN
|
||
# mapping. NEITHER SDK.
|
||
add_library(param_slider STATIC src/vst/param_slider.cpp)
|
||
target_include_directories(param_slider PUBLIC src/vst)
|
||
target_link_libraries(param_slider PUBLIC editor_geometry)
|
||
|
||
add_executable(editor_geometry_tests tests/test_editor_geometry.cpp)
|
||
target_link_libraries(editor_geometry_tests PRIVATE editor_geometry)
|
||
add_test(NAME editor_geometry_tests COMMAND editor_geometry_tests)
|
||
|
||
add_executable(bridge_marshal_tests tests/test_bridge_marshal.cpp)
|
||
target_link_libraries(bridge_marshal_tests PRIVATE bridge_marshal)
|
||
add_test(NAME bridge_marshal_tests COMMAND bridge_marshal_tests)
|
||
|
||
add_executable(embed_strip_tests tests/test_embed_strip.cpp)
|
||
target_link_libraries(embed_strip_tests PRIVATE embed_strip)
|
||
add_test(NAME embed_strip_tests COMMAND embed_strip_tests)
|
||
|
||
# sample_map: the S4 mapping heart. Links ONLY sample_map (+ its pure deps) — NEITHER
|
||
# the VST3 SDK nor the REAPER SDK — the same structural plain-data-boundary proof the
|
||
# sampler_core test enforces.
|
||
add_executable(sample_map_tests tests/test_sample_map.cpp)
|
||
target_link_libraries(sample_map_tests PRIVATE sample_map)
|
||
add_test(NAME sample_map_tests COMMAND sample_map_tests)
|
||
|
||
add_executable(capture_browser_tests tests/test_capture_browser.cpp)
|
||
target_link_libraries(capture_browser_tests PRIVATE capture_browser)
|
||
add_test(NAME capture_browser_tests COMMAND capture_browser_tests)
|
||
|
||
add_executable(keyboard_strip_tests tests/test_keyboard_strip.cpp)
|
||
target_link_libraries(keyboard_strip_tests PRIVATE keyboard_strip)
|
||
add_test(NAME keyboard_strip_tests COMMAND keyboard_strip_tests)
|
||
|
||
# waveform_view (S11): the pure marker geometry + zero-crossing snap. Links ONLY waveform_view
|
||
# (+ its pure editor_geometry/peaks deps) — NEITHER SDK — the same plain-data-boundary proof.
|
||
add_executable(waveform_view_tests tests/test_waveform_view.cpp)
|
||
target_link_libraries(waveform_view_tests PRIVATE waveform_view)
|
||
add_test(NAME waveform_view_tests COMMAND waveform_view_tests)
|
||
|
||
# bank_sync (S9/S8 reader): the pure generation-parse + assignment-consume decision. Links
|
||
# ONLY bank_sync (+ its assignment_request dep) — NEITHER SDK — the plain-data-boundary proof.
|
||
add_executable(bank_sync_tests tests/test_bank_sync.cpp)
|
||
target_link_libraries(bank_sync_tests PRIVATE bank_sync)
|
||
add_test(NAME bank_sync_tests COMMAND bank_sync_tests)
|
||
|
||
# browser_scroll (S12): the pure scroll-window/thumb + search geometry over capture_browser.
|
||
add_executable(browser_scroll_tests tests/test_browser_scroll.cpp)
|
||
target_link_libraries(browser_scroll_tests PRIVATE browser_scroll)
|
||
add_test(NAME browser_scroll_tests COMMAND browser_scroll_tests)
|
||
|
||
# note_entry (S12): the pure text->clamped-MIDI-note parse for direct numeric entry.
|
||
add_executable(note_entry_tests tests/test_note_entry.cpp)
|
||
target_link_libraries(note_entry_tests PRIVATE note_entry)
|
||
add_test(NAME note_entry_tests COMMAND note_entry_tests)
|
||
|
||
# param_slider (S12 + S15/S16 control surfaces): the pure control-panel layout + slider/toggle
|
||
# value<->pixel mapping the editor parameter surface draws + routes against.
|
||
add_executable(param_slider_tests tests/test_param_slider.cpp)
|
||
target_link_libraries(param_slider_tests PRIVATE param_slider)
|
||
add_test(NAME param_slider_tests COMMAND param_slider_tests)
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# 4) The REAPER extension — a loadable module (dlopen'd by REAPER, not linked).
|
||
# ---------------------------------------------------------------------------
|
||
# LICE sources the bank_panel + draw_kit draw with: lice.cpp (LICE_SysBitmap, FillRect,
|
||
# GradRect, Clear, Blit) + lice_line.cpp (Line, DrawRect, RoundRect). lice_line.cpp's
|
||
# bezier helpers call LICE_FillCircle from lice_arc.cpp, so that TU is required to link.
|
||
# lice_textnew.cpp provides LICE_CachedFont (the kit's AA cached-font engine, Phase L L1 —
|
||
# the "temple os -> modern" text lever; see draw_kit.cpp). NOTE the "new" variant: it is the
|
||
# TU that implements the LICE_CachedFont CLASS (lice_text.cpp is the legacy bitmap-font
|
||
# renderer with no class and would not resolve the symbols). LICE routes GDI through native
|
||
# Win32 or, on mac/linux, the host SWELL (SWELL_PROVIDED_BY_APP).
|
||
set(LICE_SRC
|
||
${WDL_INC}/lice/lice.cpp
|
||
${WDL_INC}/lice/lice_line.cpp
|
||
${WDL_INC}/lice/lice_arc.cpp
|
||
${WDL_INC}/lice/lice_textnew.cpp
|
||
)
|
||
|
||
add_library(reaper_reasampler MODULE
|
||
src/main.cpp
|
||
src/capture.cpp
|
||
src/capture_realtime.cpp
|
||
src/realtime_record.cpp
|
||
src/persist.cpp
|
||
src/bank_panel.cpp
|
||
src/draw_kit.cpp
|
||
src/mode_switch.cpp
|
||
src/tab_strip.cpp
|
||
src/insert.cpp
|
||
src/insert_plan.cpp
|
||
${LICE_SRC}
|
||
src/view_mode_model.cpp
|
||
src/view_tree.cpp
|
||
src/view.cpp
|
||
src/track_guid.cpp
|
||
src/provenance_shell.cpp
|
||
src/guid_diff.cpp
|
||
src/lane_keys.cpp
|
||
src/item_read.cpp
|
||
src/actions.cpp
|
||
src/ingest.cpp
|
||
src/bank_book.cpp
|
||
src/owned_manifest.cpp
|
||
src/drag_out_win.cpp
|
||
src/instrument_drop_win.cpp
|
||
src/action_bar.cpp
|
||
src/footer_bar.cpp
|
||
src/overflow_menu.cpp
|
||
src/mode_enable.cpp
|
||
src/tooltip.cpp
|
||
src/card_meta.cpp
|
||
src/card_drag.cpp
|
||
)
|
||
target_link_libraries(reaper_reasampler PRIVATE bank_model capture_paths peaks bank_grid mode_switch tab_strip view_mode_model insert_plan render_settings batch_capture tail_control realtime_record bank_book wav_trim owned_manifest prune_reconcile prune_button app_version provenance action_buttons drag_out instrument_drop theme component_geometry action_bar footer_bar overflow_menu mode_enable tooltip card_meta card_drag assignment_request bank_sync)
|
||
target_include_directories(reaper_reasampler PRIVATE ${SDK_INC} ${WDL_INC})
|
||
# OUTPUT_NAME is channel-derived (Phase V, V4): "reaper_reasampler" (stable, default) or
|
||
# "reaper_reasampler_beta" (beta). REAPER dlopen's any reaper_* module, so both channels'
|
||
# artifacts load side-by-side. The CMake TARGET name stays "reaper_reasampler" for both
|
||
# configs — one source tree, one target; only the emitted file name forks by channel.
|
||
set_target_properties(reaper_reasampler PROPERTIES PREFIX "" OUTPUT_NAME "${REASAMPLER_OUTPUT_NAME}")
|
||
|
||
if(WIN32)
|
||
# Native Win32. REAPER provides nothing extra to link. The bank_panel dialog
|
||
# template (M5) is compiled from src/resource.rc by the platform RC compiler.
|
||
target_sources(reaper_reasampler PRIVATE src/resource.rc)
|
||
|
||
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")
|
||
# bank_panel dialog (M5): SWELL can't read a Win32 .rc directly. Run resgen
|
||
# once to turn src/resource.rc into a C++ source, then add it here:
|
||
# php ${WDL_INC}/swell/mac_resgen.php src/resource.rc
|
||
# target_sources(reaper_reasampler PRIVATE src/resource.rc_mac_dlg.h) # generated
|
||
|
||
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")
|
||
# bank_panel dialog (M5): reuse the macOS resgen output (see README /
|
||
# CLAUDE.md §SWELL dialog resources), then add the generated source:
|
||
# php ${WDL_INC}/swell/mac_resgen.php src/resource.rc
|
||
# target_sources(reaper_reasampler PRIVATE src/resource.rc_mac_dlg.h) # generated
|
||
endif()
|
||
|
||
# ===========================================================================
|
||
# 5) The ReaSampler VST3 instrument — the SECOND build artifact (Phase S1).
|
||
#
|
||
# Windows-only, VST3-only, REAPER-only (D5). A separate native VST3 plugin the user
|
||
# instantiates on an instrument track. Additive: the reaper_reasampler target above
|
||
# builds unchanged. This is the S1 opening spike — a silent-but-loading
|
||
# SingleComponentEffect skeleton, an IPlugView<->LICE editor, and the REAPER VST-host
|
||
# bridge read — not yet a sampler.
|
||
#
|
||
# ONE-TIME SDK SUBMODULE SETUP (see README / .gitmodules): the vst3sdk superproject is
|
||
# vendored pinned to tag v3.7.9_build_61; only three of its sub-submodules are needed
|
||
# (VSTGUI/examples/tests are NOT). After `git submodule update --init vendor/vst3sdk`:
|
||
# cd vendor/vst3sdk && git submodule update --init pluginterfaces base public.sdk
|
||
# ===========================================================================
|
||
set(VST3_SDK ${CMAKE_CURRENT_SOURCE_DIR}/vendor/vst3sdk)
|
||
# The VST3 module needs the nested vst3sdk slice (pluginterfaces / base / public.sdk)
|
||
# checked out — the one-time step documented above. When it is absent (a fresh clone
|
||
# that ran only the top-level `git submodule update --init`), skip the module rather than
|
||
# fail configure on missing sources: the pure geometry/mapping libraries + their CTest
|
||
# targets still build and test without the SDK. Probe one representative source file.
|
||
if(WIN32 AND EXISTS "${VST3_SDK}/public.sdk/source/main/pluginfactory.cpp")
|
||
|
||
# --- 5a) The bounded slice of the Steinberg VST3 SDK this spike needs. --------
|
||
# Enumerated (not add_subdirectory of the whole SDK) to keep the build hermetic and
|
||
# lean, matching the project's two-submodule discipline: no VSTGUI, no examples, no
|
||
# SDK-global CMake helpers/install machinery. Pinned to tag v3.7.9_build_61, so the
|
||
# list is fixed. If the SDK tag is bumped, re-verify this set.
|
||
add_library(vst3_sdk STATIC
|
||
# pluginterfaces/base — FUnknown, IIDs, string table, ustring.
|
||
${VST3_SDK}/pluginterfaces/base/funknown.cpp
|
||
${VST3_SDK}/pluginterfaces/base/coreiids.cpp
|
||
${VST3_SDK}/pluginterfaces/base/conststringtable.cpp
|
||
${VST3_SDK}/pluginterfaces/base/ustring.cpp
|
||
# base/source — FObject, strings, buffers, streamer, debug, IIDs, update handler.
|
||
${VST3_SDK}/base/source/fobject.cpp
|
||
${VST3_SDK}/base/source/fstring.cpp
|
||
${VST3_SDK}/base/source/fbuffer.cpp
|
||
${VST3_SDK}/base/source/fstreamer.cpp
|
||
${VST3_SDK}/base/source/fdebug.cpp
|
||
${VST3_SDK}/base/source/baseiids.cpp
|
||
${VST3_SDK}/base/source/updatehandler.cpp
|
||
${VST3_SDK}/base/thread/source/flock.cpp
|
||
# public.sdk/source/vst — the SingleComponentEffect base + its deps. NOTE:
|
||
# vstsinglecomponenteffect.cpp #includes vsteditcontroller.cpp (unity-style), so
|
||
# vsteditcontroller.cpp must NOT be listed separately (double definition).
|
||
${VST3_SDK}/public.sdk/source/vst/vstsinglecomponenteffect.cpp
|
||
${VST3_SDK}/public.sdk/source/vst/vstcomponentbase.cpp
|
||
${VST3_SDK}/public.sdk/source/vst/vstbus.cpp
|
||
${VST3_SDK}/public.sdk/source/vst/vstparameters.cpp
|
||
${VST3_SDK}/public.sdk/source/vst/vstinitiids.cpp
|
||
# public.sdk/source/common — CPluginView (IPlugView base) + IIDs.
|
||
${VST3_SDK}/public.sdk/source/common/pluginview.cpp
|
||
${VST3_SDK}/public.sdk/source/common/commoniids.cpp
|
||
# public.sdk/source/main — the class-factory (GetPluginFactory) support. NOTE:
|
||
# dllmain.cpp + moduleinit.cpp (which carry the InitDll/ExitDll dll exports) are
|
||
# compiled into the MODULE target directly, NOT here: their SMTG_EXPORT_SYMBOL
|
||
# functions have no internal referrer, so the linker strips them from a static
|
||
# lib. Compiling them into the module keeps the exports.
|
||
${VST3_SDK}/public.sdk/source/main/pluginfactory.cpp
|
||
)
|
||
target_include_directories(vst3_sdk PUBLIC ${VST3_SDK})
|
||
# The SDK requires exactly one of RELEASE / DEVELOPMENT (fdebug.cpp keys off it).
|
||
target_compile_definitions(vst3_sdk PUBLIC $<IF:$<CONFIG:Debug>,DEVELOPMENT=1,RELEASE=1>)
|
||
|
||
# --- 5b) The VST3 module (loadable .vst3 DLL). -------------------------------
|
||
add_library(reasampler_vst MODULE
|
||
src/vst/vst_entry.cpp
|
||
src/vst/reasampler_processor.cpp
|
||
src/vst/reasampler_editor.cpp
|
||
src/vst/reasampler_embed.cpp
|
||
src/vst/reaper_bridge.cpp
|
||
# SDK module entry — compiled into the module (not the static lib) so the
|
||
# InitDll/ExitDll dll exports survive the link (see vst3_sdk note above).
|
||
${VST3_SDK}/public.sdk/source/main/dllmain.cpp
|
||
${VST3_SDK}/public.sdk/source/main/moduleinit.cpp
|
||
${LICE_SRC}
|
||
)
|
||
# editor_geometry + bridge_marshal: the pure spike helpers. sample_map (S4): the pure
|
||
# bank->keymap mapping + state (de)ser the processor drives off the audio thread;
|
||
# linking it pulls its pure deps (bank_book, wav_trim, sampler_core, bank_model,
|
||
# peaks) transitively. capture_paths: the shared M4 path resolution (resolveBankFile /
|
||
# projectDirOfRpp) the bridge + processor use. Its PUBLIC include dirs (src, src/vst)
|
||
# give the shell TUs their headers (ext_keys.h, bank_book.h, sampler_core.h, ...).
|
||
# embed_strip (S6): the pure inline-strip layout + hit-test the embed shell marshals
|
||
# into; it links editor_geometry transitively (shared Rect).
|
||
# app_version: ext_keys.h's channel-derived namespace accessor (V4) delegates to it, so
|
||
# the instrument reads the SAME namespace the extension writes; its PUBLIC include dir
|
||
# (build/generated) carries version_generated.h for the channel bit.
|
||
# capture_browser + keyboard_strip (S10): the pure card-grid/tab + keyboard-strip
|
||
# geometry the capture-first editor draws + hit-tests against; both link editor_geometry
|
||
# transitively (shared Rect).
|
||
# waveform_view (S11): the pure frame<->pixel marker geometry + zero-crossing snap the
|
||
# editor's waveform surface draws + hit-tests against; links editor_geometry + peaks
|
||
# transitively (shared Rect + AudioSample).
|
||
# bank_sync (S9/S8 reader): the pure generation-compare + assignment-consume decision the
|
||
# processor's off-thread poll runs; links assignment_request transitively (the decoded
|
||
# request it consumes) — the same key the extension writes, shared via the pure module.
|
||
# browser_scroll + note_entry + param_slider (S12 + S15/S16 control surfaces): the pure
|
||
# scroll/search geometry over the capture browser, the numeric-note-entry parse, and the
|
||
# control-panel layout + slider/toggle value<->pixel mapping the editor's parameter surface
|
||
# draws + routes against. browser_scroll pulls capture_browser transitively; param_slider +
|
||
# note_entry link editor_geometry / the stdlib only. All engine-free, DAW-verified in the shell.
|
||
target_link_libraries(reasampler_vst PRIVATE vst3_sdk editor_geometry bridge_marshal
|
||
sample_map capture_paths embed_strip app_version capture_browser keyboard_strip
|
||
waveform_view bank_sync browser_scroll note_entry param_slider)
|
||
# SDK_INC gives reaper_vst3_interfaces.h + reaper_plugin_functions.h for the bridge;
|
||
# WDL_INC gives LICE for the editor. The VST3 SDK headers come from vst3_sdk PUBLIC.
|
||
target_include_directories(reasampler_vst PRIVATE ${SDK_INC} ${WDL_INC})
|
||
# A .vst3 is a DLL with a .vst3 extension and no lib-prefix. OUTPUT_NAME is the on-disk
|
||
# product name, channel-forked (S18): reasampler_9000.vst3 (stable, byte-identical to
|
||
# pre-S18) / reasampler_9000_beta.vst3 (beta) — driven by REASAMPLER_VST_OUTPUT_NAME set
|
||
# from the ONE channel decision above, mirroring the extension's REASAMPLER_OUTPUT_NAME
|
||
# and matching app_version::vstOutputName(). The two channels install side-by-side; the
|
||
# per-channel VST3 class UID (reasampler_vst.h) keeps a saved instance rebinding to its
|
||
# own channel (save-rename-reopen is a DAW-verify).
|
||
set_target_properties(reasampler_vst PROPERTIES PREFIX "" SUFFIX ".vst3"
|
||
OUTPUT_NAME "${REASAMPLER_VST_OUTPUT_NAME}")
|
||
endif()
|