#pragma once // bank_panel — the docked grid window (M5, Wave A). REAPER-facing shell: it owns // a SWELL dialog docked via DockWindowAddEx, and paints the current project's // bank as a grid of LICE-drawn waveform thumbnails. The panel itself NEVER inserts // into the arrange or mutates the project/bank (CONTEXT.md §load-bearing // principle). Audition / multi-select / keyboard nav are Wave B. // // The header is REAPER-free as practical: main.cpp drives the panel through these // free functions, passing the live session so the panel reads the current bank. // All SWELL / LICE / PCM_source use is confined to bank_panel.cpp. The pure // layout math and cache keys live in bank_grid (unit-tested outside the DAW). #include #include #include "tail_control.h" // TailSetting — the panel's tail-mode toggle state namespace reasampler { class ReaSamplerSession; // Wires the panel into main.cpp's lifecycle. Called once after the API pointers // are loaded, BEFORE the toggle action is registered. `session` must outlive the // panel (it is the extension-lifetime g_session). Stores the session pointer the // panel reads on every repaint; does not create the window yet. void bankPanelInit(ReaSamplerSession* session); // Toggles the docked window: creates+docks it if hidden, hides+undocks it if // shown. Bound to the "toggle bank panel" action. Safe to call before the first // timer tick. void bankPanelToggle(); // Whether the panel window is currently open/visible. Feeds the action's // checked-state (toggleaction) so REAPER shows a tick next to the menu entry. bool bankPanelIsOpen(); // The stable ids of the currently-selected samples, in bank (insertion) order. // Empty when nothing is selected or the panel has never opened. This is the clean // seam the `insert` action reads to know WHAT to place — it returns ids (not grid // indices) so the caller resolves against the live bank and is unaffected by the // panel's internal index bookkeeping. READ of panel state only; no mutation. // // Note: the panel's selection is cleared on a bank change (capture / project // load), so a returned id always names a sample present in the current bank at // the moment of the call; the caller still tolerates an absent id gracefully. // // Phase B4 (vertical split): the selection lives in whichever REGION the user last // interacted with (the pool grid on top or a named-bank grid below), which is NOT // necessarily the active/capture-target bank. The returned ids therefore name // samples in the FOCUSED region's displayed bank — the bank the user visibly // selected in. Pair with bankPanelSelectedSourceBankId() to know which bank those // ids belong to (the move/copy source). std::vector bankPanelSelectedSampleIds(); // The bank id the current selection belongs to — the displayed bank of the region // the user last interacted with (pool region -> the pool id; named-banks region -> // the shown tab's bank id). This is the SOURCE bank for a move/copy of the current // selection, and it is distinct from the active/capture-target bank (active ≠ shown). // Returns the pool id when nothing is selected or the panel has never opened (a safe // default source). READ of panel state only; no mutation. std::string bankPanelSelectedSourceBankId(); // Requests a repaint if the bank changed since the last paint (generation bump). // Cheap when nothing changed. Driven by the timer so a capture / project load is // reflected without the panel diffing the bank itself. void bankPanelRefresh(); // Notifies the panel that persist just (re)loaded a project's view model (membership + // active mode). main.cpp calls this on the exact tick it drains persist's load signal // and reapplies the active mode. It re-arms the new-content detector so the just-loaded // project's PRE-EXISTING content is taken as the baseline (reported as nothing new), // never diffed against the previously-open project and mass-tagged into the active mode. // This coordinates the detector's project-identity signal with persist's authoritative // (GUID-primary) one — the two can no longer diverge on a recycled ReaProject* address, // which is what caused a project opened in Design to mis-tag its Arrange tracks. READ/ // arm of panel state only; no project or bank mutation. void bankPanelNotifyProjectLoaded(); // The panel's current tail-mode setting (mode + Manual length), read by the plain // CAPTURE_ITEM / CAPTURE_TRACK actions when building a CaptureRequest so a capture // applies whatever the panel toggle is set to. Default None (exact bounds) — a // capture with no explicit choice stays byte-identical to today. Extension-session // setting: persists across project loads and panel open/close within a REAPER session; // resets to None only when the extension unloads (fresh REAPER session). Project // persistence across REAPER restarts is a noted follow-on. // Safe to call before the panel has ever opened (returns the default). READ of panel // state only; the toggle is mutated by a click inside the panel, never here. TailSetting bankPanelTailSetting(); // The vertical-split full-height layout state (Phase B). The bank window splits // vertically — pool on top, named-banks region below — and two toggles collapse the // split: pool full-height (hide the named-banks region) and banks full-height (hide // the pool). The two are mutually exclusive with the default (both regions shown), // so one enum captures the whole state. // // This bit is B3-owned (the actions flip it); B4's panel RENDERS from it. It lives // here beside the tail setting — the other session-level view-layout bit the panel // reads — NOT in the persisted ReaSamplerSession: it is a UI-layout preference, not // project state, so it must not travel with the .rpp. In-memory for the extension's // lifetime; resets to Split on unload. enum class BankPanelFullHeight { Split, // default: pool region on top, named-banks region below PoolOnly, // pool full-height — named-banks region hidden BanksOnly, // banks full-height — pool region hidden }; // The current full-height layout state (default Split). READ by B4's panel to decide // which region(s) to draw. Safe before the panel has ever opened. BankPanelFullHeight bankPanelFullHeight(); // Toggles pool full-height: Split <-> PoolOnly. From PoolOnly returns to Split; from // either other state (Split or BanksOnly) enters PoolOnly. Bound to the "pool // full-height" action. Requests a repaint so an open panel reflects the change. void bankPanelToggledPoolFullHeight(); // Toggles banks full-height: Split <-> BanksOnly, symmetric to the pool toggle. // Bound to the "banks full-height" action. Requests a repaint. void bankPanelToggledBanksFullHeight(); // Tears the panel down on extension unload: destroys the window and releases any // cached thumbnails / PCM handles. Mirror of bankPanelInit; safe if never opened. void bankPanelShutdown(); } // namespace reasampler