Cut shell/actions, bank_ops, app comment bloat ~48% (comments only, zero code change)
This commit is contained in:
@@ -1,16 +1,11 @@
|
||||
// bank_ops.cpp — the promptless bank-verb seam (Q-W6 lift; see bank_ops.h for the
|
||||
// contract). The ONE implementation home of the bank verbs (create / rename /
|
||||
// delete / evacuate / activate / move / copy / remove): each mutates the given
|
||||
// session's book() then persists via persistBankOp() (one bank op = one Ctrl-Z; a
|
||||
// true index no-op opens NO undo point). It DOES mutate the bank BOOK — but only
|
||||
// the index/model + ext-state, never the arrange, never a sample file on disk
|
||||
// (bank ops are index-only; files stay put — CONTEXT.md §Multi-bank).
|
||||
// REFERENCE-INVALIDATION GUARDRAIL: after a STRUCTURAL mutation any
|
||||
// Bank*/BankModel& is invalid — verbs take ids and resolve fresh per model call.
|
||||
// bank_ops.cpp — see bank_ops.h for the contract. The ONE implementation home of the
|
||||
// bank verbs: each mutates the given session's book() then persists via
|
||||
// persistBankOp() (one bank op = one Ctrl-Z; a true index no-op opens NO undo
|
||||
// point). Index/model + ext-state only — never the arrange, never a file on disk.
|
||||
// REFERENCE-INVALIDATION GUARDRAIL: after a STRUCTURAL mutation any Bank*/BankModel&
|
||||
// is invalid — verbs take ids and resolve fresh per model call.
|
||||
//
|
||||
// Compiled into the reaper_reasampler MODULE. Includes reaper_plugin_functions.h
|
||||
// WITHOUT REAPERAPI_IMPLEMENT — main.cpp owns the API pointers; here they are
|
||||
// extern (CLAUDE.md §contract). DAW-verified, not unit tested.
|
||||
// main.cpp owns the API pointers; this TU gets them extern. DAW-verified, not unit tested.
|
||||
|
||||
#include "shell/bank_ops/bank_ops.h"
|
||||
|
||||
@@ -31,9 +26,7 @@ namespace reasampler {
|
||||
|
||||
namespace {
|
||||
|
||||
// Mints a fresh, genuine REAPER GUID string as a stable bank id (the B2/model
|
||||
// design: ids are caller-supplied and stable; the model stays pure and mints none).
|
||||
// Distinct from a track GUID by origin only — both are canonical guidToString output.
|
||||
// Ids are caller-supplied and stable; the model stays pure and mints none.
|
||||
std::string mintBankId() {
|
||||
GUID g{};
|
||||
genGuid(&g);
|
||||
@@ -44,35 +37,20 @@ std::string mintBankId() {
|
||||
|
||||
} // namespace
|
||||
|
||||
// Persists a completed bank-index verb as a SINGLE batched REAPER undo point (R-B) —
|
||||
// one bank op = one Ctrl-Z.
|
||||
// WHY THIS WRAPS: a bank verb mutates ONLY our project ext-state, which REAPER's
|
||||
// undo system captures iff UNDO_STATE_MISCCFG is set (the SDK documents MISCCFG as
|
||||
// covering extensions' project ext-state). We pass exactly UNDO_STATE_MISCCFG, not
|
||||
// -1/UNDO_STATE_ALL — a bank verb touches no tracks/FX/items, so snapshotting them
|
||||
// would be both heavier and wrong. Persist runs INSIDE the block so the post-mutation
|
||||
// ext-state is the block's "after" image.
|
||||
//
|
||||
// WHY THIS WRAPS AND saveToActiveProject() DOES NOT: a bank verb mutates ONLY our
|
||||
// project ext-state (SetProjExtState under "reasampler"), which REAPER's undo system
|
||||
// captures iff UNDO_STATE_MISCCFG is set in the Undo_EndBlock2 flags — the SDK
|
||||
// documents MISCCFG as covering "extensions!" project ext-state (reaper_plugin.h
|
||||
// ~1544, ~1199). We pass exactly UNDO_STATE_MISCCFG (not -1 / UNDO_STATE_ALL as the
|
||||
// item-move family does): a bank verb touches no tracks, FX, items, or envelopes, so
|
||||
// snapshotting them would be both heavier and semantically wrong. The persist runs
|
||||
// INSIDE the block so the post-mutation ext-state is the block's "after" image.
|
||||
//
|
||||
// UNSAVED-PROJECT GUARDRAIL: on an unsaved / no-active project saveToActiveProject()
|
||||
// no-ops (nothing is written to ext state). We must still CLOSE the block we opened,
|
||||
// but with an EMPTY label and a zero flag so REAPER DISCARDS the point instead of
|
||||
// recording a no-effect undo entry — mirroring view.cpp's empty-plan close. The
|
||||
// in-session model change stands and persists on the user's next save; it just earns
|
||||
// no undo point until there is a project to persist into (undo of an unsaved bank op
|
||||
// has nothing to roll back to anyway). The Begin/End must still be balanced, hence
|
||||
// the close-either-way. (Quiet persist by design — mirrors the CAPTURE path, NOT the
|
||||
// Design-View path; deliberately NO Save-As prompt.)
|
||||
// UNSAVED-PROJECT GUARDRAIL: on an unsaved/no-active project saveToActiveProject()
|
||||
// no-ops; we still CLOSE the block, but with an empty label + zero flag so REAPER
|
||||
// discards the point instead of recording a no-effect undo entry. Quiet persist by
|
||||
// design (mirrors capture, not Design-View) — deliberately no Save-As prompt.
|
||||
void persistBankOp(ReaSamplerSession& session, const char* label,
|
||||
bool bumpGeneration) {
|
||||
Undo_BeginBlock2(nullptr);
|
||||
// S9: bump the bank-generation counter INSIDE the block, before the persist, so the
|
||||
// fresh generation rides the same ext-state write (saveToActiveProject() stamps
|
||||
// bankGeneration()). Bumped only for content-changing verbs (the caller decides); a
|
||||
// pure-organizational verb passes false and leaves the counter be, so a
|
||||
// rename/activate does not needlessly refresh live instances.
|
||||
if (bumpGeneration) session.bumpBankGeneration();
|
||||
const bool persisted = session.saveToActiveProject();
|
||||
if (persisted)
|
||||
@@ -109,7 +87,6 @@ bool bankOpDelete(ReaSamplerSession& session, const std::string& bankId,
|
||||
|
||||
bool bankOpEvacuate(ReaSamplerSession& session, const std::string& bankId) {
|
||||
if (!session.book().evacuate(bankId)) return false; // pool is a destination, not a source
|
||||
// S9: evacuate moves members between banks (bank membership changes) -> bump.
|
||||
persistBankOp(session, "ReaSampler: evacuate bank", /*bumpGeneration=*/true);
|
||||
return true;
|
||||
}
|
||||
@@ -120,14 +97,10 @@ bool bankOpActivate(ReaSamplerSession& session, const std::string& bankId) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// NO-OP GUARDRAIL — VERB-AWARE (a collapse means different things per verb):
|
||||
// * MOVE collapse: the source entry WAS removed (bank_book moveSample removes
|
||||
// unconditionally before the dest add collapses on hash), so the index DID
|
||||
// mutate — it counts toward opening an undo point.
|
||||
// * COPY collapse: the source is left intact AND the dest already held the hash,
|
||||
// so NOTHING changed — a true index no-op. It must NOT open an undo point.
|
||||
// Hence: copy counts only real gains; move counts gains OR collapses. Ids pass
|
||||
// straight to the model op — no BankModel& cached across the loop's mutations.
|
||||
// NO-OP GUARDRAIL, verb-aware: a MOVE collapse still removed the source entry (the
|
||||
// index DID mutate), but a COPY collapse left the source intact AND the dest already
|
||||
// held the hash (a true no-op) — so copy counts only real gains, move counts gains
|
||||
// OR collapses.
|
||||
bool bankOpTransfer(ReaSamplerSession& session,
|
||||
const std::vector<std::string>& sampleIds,
|
||||
const std::string& srcBankId, const std::string& destBankId,
|
||||
@@ -151,18 +124,14 @@ bool bankOpTransfer(ReaSamplerSession& session,
|
||||
}
|
||||
const bool mutated = copy ? (ok > 0) : (ok > 0 || collapsed > 0);
|
||||
if (!mutated) return false; // nothing changed — no persist, no undo point
|
||||
// S9: a move/copy changes bank membership (a sample arrives in / leaves a bank an
|
||||
// instance may reference) -> bump so assigned instances refresh hands-free.
|
||||
persistBankOp(session,
|
||||
copy ? "ReaSampler: copy sample(s)" : "ReaSampler: move sample(s)",
|
||||
/*bumpGeneration=*/true);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Index-only, this-bank scope (fork R-A: the sole surfaced verb; RemoveScope::AllBanks
|
||||
// stays latent in the model). Non-destructive to the file: a last-reference remove
|
||||
// leaves the file on disk, orphaned until Phase R prune — remove NEVER deletes bytes
|
||||
// (the manifest is untouched). Silent: recoverability is the batched undo (R-B).
|
||||
// Index-only, this-bank scope; non-destructive to the file (a last-reference remove
|
||||
// leaves the file orphaned until prune). Silent: recoverability is the batched undo.
|
||||
bool bankOpRemove(ReaSamplerSession& session,
|
||||
const std::vector<std::string>& sampleIds,
|
||||
const std::string& srcBankId) {
|
||||
@@ -174,8 +143,6 @@ bool bankOpRemove(ReaSamplerSession& session,
|
||||
RemoveResult::Removed)
|
||||
++removed;
|
||||
if (removed == 0) return false; // every id already absent — no undo point
|
||||
// S9: a remove drops a sample from a bank (an instance referencing it must refresh —
|
||||
// it will resolve to silence, per the stale-id policy) -> bump.
|
||||
persistBankOp(session, "ReaSampler: remove sample(s)", /*bumpGeneration=*/true);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1,22 +1,14 @@
|
||||
#pragma once
|
||||
// bank_ops — the promptless bank-verb seam (Q-W6 lift of the Q-W4 single-owner
|
||||
// verbs out of shell/panel/panel_bank_ops into a NON-UI home). Each verb is a model
|
||||
// op on the given session's BankBook + persistBankOp (undo-batched ext-state
|
||||
// persist) — NO prompts, NO message boxes, NO panel-state nudges, NO panel-global
|
||||
// reads. The two UX surfaces consume these as thin skins:
|
||||
// bank_ops — the promptless bank-verb seam. Each verb is a model op on the given
|
||||
// session's BankBook + persistBankOp (undo-batched ext-state persist) — NO prompts,
|
||||
// NO message boxes, NO panel-state nudges. Two UX surfaces consume these as thin
|
||||
// skins: shell/panel/panel_bank_ops (menu prompts/confirms/repaints) and
|
||||
// shell/actions/bank_actions (bindable family, text prompts/console feedback).
|
||||
//
|
||||
// * shell/panel/panel_bank_ops — the panel's menu handlers (prompts / confirms /
|
||||
// repaints), passing the panel's live session.
|
||||
// * shell/actions/bank_actions — the bindable family (text prompts / console
|
||||
// feedback), passing its registered session.
|
||||
//
|
||||
// The session arrives BY REFERENCE: there is exactly one session pointer question
|
||||
// per call site (the caller's), so a missing session can never be half-reported as
|
||||
// a model rejection from in here (the Q-W4 review's fail-safe-collapse concern).
|
||||
// Every verb returns whether the model accepted the mutation — a rejected op
|
||||
// persists nothing and opens no undo point.
|
||||
//
|
||||
// REAPER-facing (persist + undo blocks + GUID minting) but SDK-free in this header.
|
||||
// The session arrives BY REFERENCE, so a missing session can never be
|
||||
// half-reported as a model rejection from in here. Every verb returns whether the
|
||||
// model accepted the mutation — a rejected op persists nothing and opens no undo
|
||||
// point. REAPER-facing (persist + undo blocks + GUID minting) but SDK-free header.
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
@@ -25,58 +17,47 @@ namespace reasampler {
|
||||
|
||||
class ReaSamplerSession;
|
||||
|
||||
// Mints a stable GUID bank id, creates `name` in the book. Returns the new bank id,
|
||||
// or "" when the model rejects the name (duplicate, trimmed + case-insensitive).
|
||||
// Create is purely organizational — no generation bump.
|
||||
// Returns "" when the model rejects the name (duplicate, trimmed + case-insensitive).
|
||||
// Purely organizational — no generation bump.
|
||||
std::string bankOpCreate(ReaSamplerSession& session, const std::string& name);
|
||||
|
||||
// Renames `bankId`. False when the model rejects (pool un-renamable / name in use).
|
||||
// False when the model rejects (pool un-renamable / name in use).
|
||||
bool bankOpRename(ReaSamplerSession& session, const std::string& bankId,
|
||||
const std::string& newName);
|
||||
|
||||
// Deletes `bankId`. False when the model rejects (pool un-deletable). The caller
|
||||
// passes `bumpGeneration` from the member count it read BEFORE any evacuate/delete
|
||||
// (an evacuate-then-delete flow must still bump on the ORIGINAL membership).
|
||||
// False when the model rejects (pool un-deletable). `bumpGeneration` should be the
|
||||
// member count read BEFORE any evacuate/delete (an evacuate-then-delete flow must
|
||||
// still bump on the ORIGINAL membership).
|
||||
bool bankOpDelete(ReaSamplerSession& session, const std::string& bankId,
|
||||
bool bumpGeneration);
|
||||
|
||||
// Evacuates `bankId`'s members to the pool. False when the model rejects (the pool
|
||||
// itself). Bumps the generation (membership changed).
|
||||
// False when the model rejects (the pool itself). Bumps the generation.
|
||||
bool bankOpEvacuate(ReaSamplerSession& session, const std::string& bankId);
|
||||
|
||||
// Activates `bankId` as the capture target. False on an unknown id. No bump.
|
||||
// False on an unknown id. No bump.
|
||||
bool bankOpActivate(ReaSamplerSession& session, const std::string& bankId);
|
||||
|
||||
// Moves (copy=false) or copies (copy=true) `sampleIds` from `srcBankId` to
|
||||
// `destBankId` (index-only; files never relocate). Returns whether the index
|
||||
// actually mutated — the verb-aware no-op guardrail: a COPY collapse changes
|
||||
// nothing (no undo point); a MOVE collapse did remove the source entry (counts).
|
||||
// Persists ONE undo point ("move/copy sample(s)") only when mutated.
|
||||
// Index-only; files never relocate. Returns whether the index actually mutated — a
|
||||
// COPY collapse changes nothing (no undo point), a MOVE collapse did remove the
|
||||
// source entry (counts). Persists one undo point only when mutated.
|
||||
bool bankOpTransfer(ReaSamplerSession& session,
|
||||
const std::vector<std::string>& sampleIds,
|
||||
const std::string& srcBankId, const std::string& destBankId,
|
||||
bool copy);
|
||||
|
||||
// Removes `sampleIds` from `srcBankId` (index-only, this-bank scope; never deletes
|
||||
// bytes). Returns whether anything was removed; persists one undo point when so.
|
||||
// Index-only, this-bank scope; never deletes bytes. Persists one undo point when
|
||||
// anything was removed.
|
||||
bool bankOpRemove(ReaSamplerSession& session,
|
||||
const std::vector<std::string>& sampleIds,
|
||||
const std::string& srcBankId);
|
||||
|
||||
// Persists a completed bank-index verb as a single REAPER undo point (R-B).
|
||||
// Wraps the session persist (SetProjExtState) in a Begin/End block with
|
||||
// UNDO_STATE_MISCCFG so the bank op is one Ctrl-Z. On an unsaved / no-active project
|
||||
// the persist no-ops and the block is closed with an empty label + zero flag (REAPER
|
||||
// discards it). Callers must invoke this ONLY after a successful/effective mutation —
|
||||
// rejected ops (duplicate name, un-deletable pool, etc.) must return before reaching
|
||||
// here so no empty undo point is ever opened for a no-op.
|
||||
// Wraps the session persist in a Begin/End undo block (UNDO_STATE_MISCCFG) so the
|
||||
// bank op is one Ctrl-Z; on an unsaved/no-active project the block closes empty
|
||||
// (REAPER discards it). Call ONLY after an effective mutation.
|
||||
//
|
||||
// S9 bank-generation bump: pass `bumpGeneration = true` for a verb that changes what a
|
||||
// live instance would PLAY — move / copy / remove / evacuate / delete-with-members. Leave
|
||||
// it false (the default) for a PURELY ORGANIZATIONAL verb — create / rename / activate /
|
||||
// reorder. The bump (when requested) happens INSIDE the block, BEFORE the persist, so
|
||||
// the stamped counter rides the same ext-state write and undo captures the pre/post
|
||||
// generation with the rest of the blob.
|
||||
// `bumpGeneration = true` for a verb that changes what a live instance would PLAY;
|
||||
// leave false for a purely organizational verb. The bump happens INSIDE the block,
|
||||
// before the persist, so the stamped counter rides the same ext-state write.
|
||||
void persistBankOp(ReaSamplerSession& session, const char* label,
|
||||
bool bumpGeneration = false);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user