5.0 KiB
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
Sampleid 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 theassignment_requestwire; 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
abortedUnreadableUsageand prints the offendingrsusage_*key names.
Modules
shell/actions(action_registry/design_view_actions/bank_actions/prune_action) — the bindable action families, all routed via thecommand_id/gaccel/hookcommandcontract.action_registryowns 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 oneActionTableRowarray — 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 promptlessshell/bank_opsverbs (bankOp*+persistBankOp, takingReaSamplerSession&), which the panel menus andbank_actionsconsume 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_FOLDERhalts onabortedUnreadableUsageand prints the offendingrsusage_*key names with clear instructions.drag_out_win— OS drag-out shell: Windows OLEDoDragDrop/CF_HDROP, copy-only (DROPEFFECT_MOVEnot offered); macOS/Linux viaSWELL_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 formerTrackFX_SetNamedConfigParm"vst_chunk" write was silently unappliable for VST3). ExposesloadInstrumentOntoTrack(inner half, no own undo block) andperformInstrumentDrop(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 theassignment_requestext-state wire. ingest NEVER inserts a timeline item.
Gotchas
- Structural wart, partly closed:
ingest.cpp/ingest.hnow live in this directory.ext_keys.handresource.hstill sit atsrc/root:ext_keys.his consumed mostly fromshell/instrument/, so it is not this directory's to claim, andresource.his a build input paired withsrc/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/IDropTargeton the dockedbank_panel). A drop onto the VST3 editor window relaying to the extension is an unproven spike, not a shipped path.