63f35fa58d
Pure OwnedFileManifest (relative paths, dedup, JSON round-trip) persisted under sibling owned_files ext-state key; both capture commit paths record; joins the R-B undo-reload set. Phase R prune consumes it later.
339 lines
19 KiB
CMake
339 lines
19 KiB
CMake
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) 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 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 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)
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# 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(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)
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# 4) The REAPER extension — a loadable module (dlopen'd by REAPER, not linked).
|
|
# ---------------------------------------------------------------------------
|
|
# LICE sources the bank_panel draws with: lice.cpp (LICE_SysBitmap, FillRect,
|
|
# Clear, Blit) + lice_line.cpp (Line, DrawRect). lice_line.cpp's bezier helpers
|
|
# call LICE_FillCircle from lice_arc.cpp, so that TU is required to link even
|
|
# though the panel draws no arcs. 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
|
|
)
|
|
|
|
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/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/guid_diff.cpp
|
|
src/lane_keys.cpp
|
|
src/item_read.cpp
|
|
src/actions.cpp
|
|
src/bank_book.cpp
|
|
src/owned_manifest.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 tail_control realtime_record bank_book wav_trim owned_manifest)
|
|
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. 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()
|