diff --git a/CLAUDE.md b/CLAUDE.md index 99672dd..9a71588 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→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 only (multi-file, bank-fill; no `assignment_request` written, no effect on any live instance's selection — the bank-generation bump is retained so open instances' browsers refresh). Only surface (1) writes the `assignment_request` ext-state wire via `ingestAssignActiveInstance`. 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. +- `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→instrument on the SELECTED TRACK (bindable action, single-file via `MediaExplorerGetLastPlayedFileInfo`; adds RS9k to the user's currently selected track via `loadInstrumentOntoTrack` — no new track created, no routing changed; if no track is selected the sound still lands in the bank but no instrument is placed, with a console message; no `assignment_request` written), (3) file drop onto the bank panel→bank only (multi-file, bank-fill; no `assignment_request` written, no effect on any live instance's selection — the bank-generation bump is retained so open instances' browsers refresh). Only surface (1) writes the `assignment_request` ext-state wire via `ingestAssignActiveInstance`. 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 two entry points: `loadInstrumentOntoTrack` (FX add+inject, no own undo block — the shared inner half used by callers that own the undo grouping; also the ME-import placement path), `performInstrumentDrop` (wraps `loadInstrumentOntoTrack` in its own undo block — the S17 drag-drop gesture 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 a645a71..0359127 100644 --- a/CONTEXT.md +++ b/CONTEXT.md @@ -1586,17 +1586,18 @@ 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 → new instrument.** The Media-Explorer surface is **thin**: +- **Media Explorer import → bank → instrument on selected track.** 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. **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. + while a file is selected in the ME — not a push/drop from inside the ME. **Shipped behavior:** + after importing the file into the active bank, the action adds a ReaSampler 9000 instrument to + the user's **currently selected track** via `loadInstrumentOntoTrack` in `instrument_drop_win` + — no new track is created and no routing is changed ("new sound, existing track"). If no track + is selected the sound still lands in the bank but no instrument is placed and a console message + explains why. No `assignment_request` is written; it never touches a live instance's selection. + Undo-wrapped: 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