Files
reasampler/src/shell/actions/ingest.h
T

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