feat(view): D2 Wave 2 — apply managed-lane ops + timer-diff auto-tag new content
Drives fixed-lane C_LANEPLAYS for managed lanes only (name-keyed, ordinal-renumber safe) in the view shell; diffs live track/item GUIDs on the panel timer to auto-tag new content to the active mode, first-poll-guarded. Pure guid_diff + lane_keys modules unit-tested; folds in Wave-1 polish.
This commit is contained in:
@@ -0,0 +1,61 @@
|
||||
#pragma once
|
||||
// lane_keys — the pure, REAPER-free convention that maps a REAPER fixed lane's
|
||||
// durable NAME (P_LANENAME:n) to the opaque lane-key the pure view_mode_model uses,
|
||||
// and the managed/manual heuristic that rides on it.
|
||||
//
|
||||
// PURE MODULE (CLAUDE.md §load-bearing split): NO REAPER types, NO SWELL. std only.
|
||||
// Unit-tested outside the DAW. The shell (view.cpp) reads each lane's P_LANENAME:n
|
||||
// string from REAPER and asks this module whether the lane is tool-managed and what
|
||||
// its stable lane-key is; the shell never re-derives the prefix rule itself.
|
||||
//
|
||||
// -- Design point #2 (lane-identity robustness) resolution --------------------
|
||||
//
|
||||
// REAPER exposes no durable per-lane GUID. The only lane identity is the ordinal
|
||||
// I_FIXEDLANE, which REAPER RENUMBERS when lanes are reordered or deleted — so keying
|
||||
// the ownership index by raw ordinal would silently corrupt managed/manual ownership
|
||||
// on any reorder. REAPER DOES expose a writable, durable lane NAME (P_LANENAME:n) that
|
||||
// travels with the lane across renumber. So the tool names each lane it mints with a
|
||||
// stable, prefixed identity ("reasampler:<mode>") and keys the ownership index by that
|
||||
// NAME, not the ordinal. On each apply the shell walks the track's lanes by current
|
||||
// ordinal, reads each name, and reconciles ordinal<->laneKey — so a C_LANEPLAYS:N
|
||||
// write always targets the lane's CURRENT ordinal for a given durable key even after a
|
||||
// reorder. A lane WITHOUT the prefix was not minted by the tool: it is manual and
|
||||
// off-limits (the fixed-lane analog of "never touch mute/solo").
|
||||
//
|
||||
// -- Design point #1 (manual-lane exemption) resolution -----------------------
|
||||
//
|
||||
// The SAME prefix rule is the manual/managed heuristic for auto-tag: an item on a lane
|
||||
// whose name lacks the "reasampler:" prefix is on a manual lane and is EXEMPT from
|
||||
// auto-tag. isManagedLaneName is the single predicate both the toggle-apply path and
|
||||
// the new-content detection path consult, so the boundary is defined in one place and
|
||||
// unit-tested.
|
||||
|
||||
#include <optional>
|
||||
#include <string>
|
||||
|
||||
namespace reasampler {
|
||||
|
||||
// The prefix the tool stamps on every lane NAME it mints. A lane name carrying this
|
||||
// prefix is a managed lane the tool created; any other name (or an empty/unnamed lane)
|
||||
// is a user-minted manual lane. Stable-forever: changing it would strand the ownership
|
||||
// of every lane in every already-saved project, so treat it like an action id string.
|
||||
inline constexpr const char* kManagedLanePrefix = "reasampler:";
|
||||
|
||||
// True iff `laneName` is a tool-minted managed-lane name (carries kManagedLanePrefix).
|
||||
// This is the load-bearing managed/manual predicate for BOTH design points #1 and #2.
|
||||
bool isManagedLaneName(const std::string& laneName);
|
||||
|
||||
// The opaque lane-key the pure model keys by, for a lane with REAPER name `laneName`.
|
||||
// For a managed lane the key IS the durable name (stable across ordinal renumber). For
|
||||
// a manual/unnamed lane there is no managed key: returns std::nullopt so the caller
|
||||
// treats the lane as manual (never driven, items on it exempt from auto-tag).
|
||||
std::optional<std::string> managedLaneKey(const std::string& laneName);
|
||||
|
||||
// The lane NAME the tool mints for the lane owned by `modeId` (kManagedLanePrefix +
|
||||
// modeId). The inverse of managedLaneKey for a managed lane: managedLaneKey(
|
||||
// laneNameForMode(m)) == kManagedLanePrefix + m. Exposed for the Wave-3 lane-minting
|
||||
// path and for tests; the apply path in this wave only READS names, but the round-trip
|
||||
// contract is asserted here so minting and reading cannot drift.
|
||||
std::string laneNameForMode(const std::string& modeId);
|
||||
|
||||
} // namespace reasampler
|
||||
Reference in New Issue
Block a user