64 lines
3.3 KiB
C++
64 lines
3.3 KiB
C++
#pragma once
|
|
// ingest — the "ingest through the bank" shell (EXTENSION side). REAPER-facing
|
|
// (PCM_Source metadata reads, Media-Explorer query, ext-state assignment write,
|
|
// action registration), so DAW-verified, not unit-tested; the pure serialization it
|
|
// drives lives in assignment_request (CTest).
|
|
//
|
|
// Loading a sample into the sampler is ONE gesture: capture/import-into-bank AND
|
|
// auto-assign to the active sampler instance. The EXTENSION owns ingest (arrange
|
|
// access, Media-Explorer access, drop-target surface); the instrument stays a
|
|
// READ-ONLY bank consumer. Three surfaces: (1) arrange capture -> bank -> assign,
|
|
// (2) Media-Explorer import -> bank -> assign (single-file, pull-on-action), (3)
|
|
// drop-onto-panel -> bank -> assign (multi-file: import all, assign the first).
|
|
//
|
|
// LOAD-BEARING: ingest NEVER inserts a timeline item — capture writes a file + index
|
|
// entry, import copies a file + adds an index entry, assignment is a bank-index +
|
|
// instance-selection act, not a placement. Any InsertMedia call here is a bug.
|
|
//
|
|
// Import is a FILE COPY into the project-relative bank folder + an index add
|
|
// (relative-paths-only, hash-dedup). If the active bank already holds the content
|
|
// (by hash), the import collapses onto the existing sample instead of duplicating.
|
|
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
// Forward declarations keep this header REAPER-free (the .cpp pulls the SDK).
|
|
struct reaper_plugin_info_t;
|
|
|
|
namespace reasampler {
|
|
|
|
class ReaSamplerSession;
|
|
|
|
// FOREVER-STABLE command-id suffixes — NEVER change after ship; user keybindings key off
|
|
// the composed ids. Two, because the Media-Explorer import publishes into two action
|
|
// sections and a custom_action idStr must be unique across all of them. Exposed here so
|
|
// the id-composition contract is assertable without linking this REAPER-facing TU.
|
|
inline constexpr const char* kIngestImportMediaExplorerId = "INGEST_IMPORT_MEDIA_EXPLORER";
|
|
inline constexpr const char* kIngestImportMediaExplorerMxId = "INGEST_IMPORT_MEDIA_EXPLORER_MX";
|
|
|
|
// `session` is shared with the capture / bank / Design-View families; main.cpp's two
|
|
// dispatch hooks route fired ids back through the two handlers below. Both registration
|
|
// mechanisms are specified in root CLAUDE.md §"REAPER extension contract".
|
|
void ingestRegisterActions(reaper_plugin_info_t* rec, ReaSamplerSession* session);
|
|
|
|
// Main-section dispatch ("hookcommand").
|
|
bool ingestHandleCommand(int command);
|
|
|
|
// Non-main-section dispatch ("hookcommand2"). Claims only ids this family published
|
|
// outside the Main section, so the two hooks never both claim one command.
|
|
bool ingestHandleSectionCommand(int command);
|
|
|
|
void ingestUnregisterActions(reaper_plugin_info_t* rec);
|
|
|
|
// "The active sampler instance should now play (bankId, sampleId)." Called by EVERY
|
|
// ingest surface after the sample lands in the bank. No-op-safe: an unsaved/no-active
|
|
// project silently drops the write; `sampleId` empty -> no write.
|
|
void ingestAssignActiveInstance(const std::string& bankId, const std::string& sampleId);
|
|
|
|
// Called by the bank_panel's WM_DROPFILES handler. Imports EVERY file into the
|
|
// active bank (hash-dedup) and assigns the FIRST successfully-imported sample to the
|
|
// active instance. No-op on an empty list or an unsaved/no-active project.
|
|
void ingestDroppedFiles(const std::vector<std::string>& absolutePaths);
|
|
|
|
} // namespace reasampler
|