From c40458fc53a4878c420241774358a927223d5f31 Mon Sep 17 00:00:00 2001 From: daniel-c-harvey Date: Mon, 27 Jul 2026 13:42:14 -0400 Subject: [PATCH] =?UTF-8?q?docs:=20reflect=20ME-import=20=E2=86=92=20new-i?= =?UTF-8?q?nstrument=20behavior?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Update ingest surface (2) + instrument_drop_win entry points in CLAUDE.md; update the Ingest-through-the-bank spec in CONTEXT.md to shipped behavior. --- CLAUDE.md | 4 ++-- CONTEXT.md | 11 +++++++---- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index b557aa0..5477f8d 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -141,8 +141,8 @@ There is no hot-reload. Copy the built binary into REAPER's `UserPlugins/` folde - `track_guid` — shared `MediaTrack*` → canonical GUID-string formatter; single source of truth for membership keys used by both the view shell and the actions layer. - `provenance_shell` — FX-chain identity queries via `TrackFX_*` / `TakeFX_*` APIs; collects source-item paths and parent-detection inputs to feed the pure `provenance` fingerprint builder. Stamps `Sample.provenance` on capture when every resolving source item maps by exact normalized path (case-folded on Windows) to exactly one bank sample; ambiguous/mixed cases record nothing conservatively. - `drag_out_win` — M11 OS drag-out shell: Windows OLE `DoDragDrop` / `CF_HDROP`, copy-only structurally (`DROPEFFECT_MOVE` not offered, no source-deletion path); macOS/Linux via `SWELL_InitiateDragDropOfFileList` (copy-semantics caveat documented — SWELL does not expose a drop-effect query). Driven by the `drag_out` pure module. -- `ingest` — Phase S ingest-through-the-bank shell (S8) on the EXTENSION side: three surfaces — (1) arrange capture→bank→assign (bindable action), (2) Media-Explorer import→bank→assign (bindable action, single-file via `MediaExplorerGetLastPlayedFileInfo`), (3) file drop onto the bank panel→bank→assign (multi-file, assigns the first). All three write the `assignment_request` ext-state wire; ingest NEVER inserts a timeline item. -- `instrument_drop_win` — Phase S FX-button drop shell (S17): (a) resolves a screen point to a track + its TCP FX-button hotspot via REAPER's hit-test API (`GetThingFromPoint`, `TrackFX_*`), and (b) on release adds a ReaSampler 9000 instance to that track and injects the dragged capture as its component state via `TrackFX_SetNamedConfigParm` "vst_chunk"; wraps the whole operation in one REAPER undo block. Never captures, never writes the bank, never inserts a timeline item. +- `ingest` — Phase S ingest-through-the-bank shell (S8) on the EXTENSION side: three surfaces — (1) arrange capture→bank→assign (bindable action), (2) Media-Explorer import→bank→new instrument on a new track (bindable action, single-file via `MediaExplorerGetLastPlayedFileInfo`; RS5k "load into a new sampler" parity — no `assignment_request` written; calls `createTrackWithInstrument`), (3) file drop onto the bank panel→bank→assign (multi-file, assigns the first). Surfaces (1) and (3) write the `assignment_request` ext-state wire via `ingestAssignActiveInstance`; surface (2) does not. ingest NEVER inserts a timeline item. +- `instrument_drop_win` — Phase S FX-button drop shell (S17): (a) resolves a screen point to a track + its TCP FX-button hotspot via REAPER's hit-test API (`GetThingFromPoint`, `TrackFX_*`), and (b) on release adds a ReaSampler 9000 instance to that track and injects the dragged capture as its component state via `TrackFX_SetNamedConfigParm` "vst_chunk". Exposes three entry points: `loadInstrumentOntoTrack` (FX add+inject, no own undo block — the shared inner half used by callers that own the undo grouping), `performInstrumentDrop` (wraps `loadInstrumentOntoTrack` in its own undo block — the S17 drag-drop gesture path), and `createTrackWithInstrument` (appends a new track, names it, then calls `loadInstrumentOntoTrack`; rolls back via `DeleteTrack` on failure — the ME-import new-instrument path). Never captures, never writes the bank, never inserts a timeline item. - `draw_kit` — Phase L shared LICE draw shell (L1): `fillSurface` (micro-gradient + inner highlight/shadow), `drawButton`/`drawSlider`/`drawListRow`/`drawWaveform`, cached-font `text()` over four `LICE_CachedFont`s (kit-owned lifecycle), full interaction-state model, double-buffer preserved. Consumes `theme` + `component_geometry`. First consumer: `bank_panel` (GDI `DrawText` path retired in L1). - `actions` — registers the capture/placement/slot action family, the Design View action family (toggle active mode, activate Arrange/Design, tag/untag selected tracks, show-both), the multi-bank action family (create/rename/reorder/delete bank, evacuate, activate, move/copy/remove selected samples), and the Phase R prune action (`BANK_PRUNE_FOLDER` — dry-run-first, confirm-with-manifest, then `pruneDeletePlan`-guarded deletion; **the ONLY file-deletion authority in the system**); routes each to the modules above via the `command_id`/`gaccel`/`hookcommand` contract. 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 writes no ext state and opens no undo point (file deletion is not REAPER-undoable). diff --git a/CONTEXT.md b/CONTEXT.md index bbb716b..f4b6418 100644 --- a/CONTEXT.md +++ b/CONTEXT.md @@ -1586,14 +1586,17 @@ headers):** capture inputs) and assigns the resulting `Sample` id to the target instance. **It never inserts a timeline item** — the capture/placement separation is load-bearing; assignment is a bank-index + instance-selection act, not a placement. -- **Media Explorer import → bank → assign.** The Media-Explorer surface is **thin**: +- **Media Explorer import → bank → new instrument.** The Media-Explorer surface is **thin**: `OpenMediaExplorer` (open/select a file) and `MediaExplorerGetLastPlayedFileInfo` (read the *one* last-played/selected file path + its selection range/pitch/vol/rate) are the whole contract. There is **no** enumerate-selected-files and **no** register-a-drop-handler-on- the-Media-Explorer API. So ME import is **single-file, pull-on-action** — an action fired - while a file is selected in the ME — not a push/drop from inside the ME. **Spike:** confirm - `MediaExplorerGetLastPlayedFileInfo` returns a usable path+range for a merely-*selected* - (not-yet-played) file, or whether a play is required first. + while a file is selected in the ME — not a push/drop from inside the ME. **Shipped behavior + (RS5k parity):** after importing the file into the active bank, the action stands up a NEW + ReaSampler 9000 instrument on a NEW track (named after the sound) pre-loaded with just that + sound (`createTrackWithInstrument` in `instrument_drop_win`). No `assignment_request` is + written; it never touches a live instance's selection. Undo-wrapped: track-create + persist + + FX-add + inject = one Ctrl-Z. - **Drag-and-drop onto ReaSampler surfaces.** REAPER exposes **no** drag-drop registration API. Drop handling is on ReaSampler's *own* HWNDs via SWELL/Win32 (`WM_DROPFILES` / `IDropTarget` on the docked `bank_panel` HWND — the surface the panel already owns) → ingest