Files
reasampler/src/shell/actions/CLAUDE.md
T

5.0 KiB

src/shell/actions — bindable REAPER actions, drag/drop shells, ingest

Scope

The bindable action families routed through REAPER's command_id/gaccel/ hookcommand contract (Design View toggle actions, bank actions, the prune action, and the shared registration plumbing/table), plus the OS drag-out and FX-drop shells, plus the extension-side ingest-through-the-bank shell. This is where user-facing REAPER actions and OS-level drag/drop live; the underlying mutation logic (bank verbs, prune's orphan computation, view-mode reconciliation) is owned by other directories and only skinned here.

Invariants

  • Ingest is an extension act; the instrument is a read-only bank consumer. Any instrument code path that captures, imports, inserts a timeline item, or writes back into the bank is a bug — the instrument reads and plays only.
  • Ingest NEVER inserts a timeline item. Arrange capture→bank→assign reuses the existing capture add-path and assigns the resulting Sample id to the target instance; it never places anything on the timeline — capture/placement separation is load-bearing here same as everywhere else. Only the arrange-capture surface writes the assignment_request wire; Media-Explorer import and file-drop onto the bank panel do not, and neither affects a live instance's selection.
  • Every bank index verb wraps its mutation in a batched REAPER undo point (Undo_BeginBlock2/EndBlock2, UNDO_STATE_MISCCFG) so one bank operation is one Ctrl-Z.
  • The prune action is the ONLY file-deletion action in the system; it opens no undo point (file deletion is not REAPER-undoable). It halts on abortedUnreadableUsage and prints the offending rsusage_* key names.

Modules

  • shell/actions (action_registry / design_view_actions / bank_actions / prune_action) — the bindable action families, all routed via the command_id/gaccel/hookcommand contract. action_registry owns the shared registration plumbing (interned channel-qualified id strings; register and mirror-unregister present the identical pointer) and the Q-W6 registration TABLE: main.cpp's own family (capture scopes, panel toggle, insert, batch, realtime, recapture, version) is one ActionTableRow array — suffix, phrase, flat function-pointer handler — that registration, hookcommand dispatch, and the unload mirror-unregister all iterate, so adding an action touches the table only (OCP). Bank mutations flow through the promptless shell/bank_ops verbs (bankOp* + persistBankOp, taking ReaSamplerSession&), which the panel menus and bank_actions consume as thin UX skins. Every bank index verb wraps its mutation in a batched REAPER undo point (Undo_BeginBlock2/EndBlock2, UNDO_STATE_MISCCFG) so one bank operation is one Ctrl-Z. The prune action (prune_action, BANK_PRUNE_FOLDER) is the ONLY file-deletion action in the system; it opens no undo point (file deletion is not REAPER-undoable). pS-usage: BANK_PRUNE_FOLDER halts on abortedUnreadableUsage and prints the offending rsusage_* key names with clear instructions.
  • drag_out_win — OS drag-out shell: Windows OLE DoDragDrop/CF_HDROP, copy-only (DROPEFFECT_MOVE not offered); macOS/Linux via SWELL_InitiateDragDropOfFileList.
  • instrument_drop_win — FX-button drop shell: resolves a screen point to a track + FX-surface hotspot, then adds a ReaSampler 9000 instance and applies the dragged capture's state via a transient .vstpreset + TrackFX_SetPreset (the former TrackFX_SetNamedConfigParm "vst_chunk" write was silently unappliable for VST3). Exposes loadInstrumentOntoTrack (inner half, no own undo block) and performInstrumentDrop (wraps in its own undo block). Never captures, never writes the bank, never inserts a timeline item.
  • ingest — ingest-through-the-bank shell on the EXTENSION side: three surfaces — (1) arrange capture→bank→assign (bindable action), (2) Media-Explorer import→bank→instrument on the selected track, (3) file drop onto the bank panel→bank only. Only surface (1) writes the assignment_request ext-state wire. ingest NEVER inserts a timeline item.

Gotchas

  • Structural wart, partly closed: ingest.cpp / ingest.h now live in this directory. ext_keys.h and resource.h still sit at src/ root: ext_keys.h is consumed mostly from shell/instrument/, so it is not this directory's to claim, and resource.h is a build input paired with src/resource.rc (the SWELL resgen step) rather than a shell module.
  • Media-Explorer import is single-file, pull-on-action (OpenMediaExplorer + MediaExplorerGetLastPlayedFileInfo) — there is no enumerate-selected-files or register-a-drop-handler API on the Media Explorer surface.
  • REAPER exposes no drag-drop registration API; drop handling is only on ReaSampler's own HWNDs (WM_DROPFILES/IDropTarget on the docked bank_panel). A drop onto the VST3 editor window relaying to the extension is an unproven spike, not a shipped path.