af34143107
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.
63 lines
3.1 KiB
C++
63 lines
3.1 KiB
C++
#pragma once
|
|
// guid_diff — the pure, REAPER-free core of the D2 Wave-2 new-content detection.
|
|
//
|
|
// PURE MODULE (CLAUDE.md §load-bearing split): NO REAPER types, NO SWELL, NO
|
|
// vendor/ includes. Standard library only. Unit-tested outside the DAW.
|
|
//
|
|
// The shell (bank_panel timer) reads REAPER's live track/item GUID set each tick;
|
|
// this module owns the DECISION of "which GUIDs are new since the last tick" and the
|
|
// first-poll-after-open guard so pre-existing content is never mass-tagged. Keeping
|
|
// this here — rather than in the shell — means the fiddly baseline/diff logic is
|
|
// unit-tested, mirroring how view_tree splits the folder-depth walk out of view.cpp.
|
|
//
|
|
// The shell then hands the "new since last tick" GUIDs to the pure autoTagNewContent
|
|
// (view_mode_model) to produce the membership writes.
|
|
|
|
#include <set>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
namespace reasampler {
|
|
|
|
// The GUIDs present in `current` but absent from `previous` — i.e. new since the
|
|
// previous poll. Order is the set's ascending order (deterministic; the caller does
|
|
// not depend on discovery order). Empty GUIDs are ignored (a GUID read failure at the
|
|
// shell boundary must never be tagged).
|
|
std::vector<std::string> newGuids(const std::set<std::string>& previous,
|
|
const std::set<std::string>& current);
|
|
|
|
// Tracks the live GUID set across polls for ONE project, implementing the
|
|
// first-poll-after-open guard: the first observation after a (re)start establishes a
|
|
// BASELINE and reports NOTHING new, so pre-existing content stays at its default
|
|
// (Arrange) rather than being mass-tagged. Every subsequent observe() returns only the
|
|
// GUIDs created since the prior observe().
|
|
//
|
|
// Project switches are handled by reset(): the shell detects a project change (the
|
|
// active ReaProject* / project GUID changed) and calls reset() so the next observe()
|
|
// re-baselines against the newly-opened project instead of diffing across two
|
|
// unrelated projects (which would spuriously "detect" the entire new project as new
|
|
// content, or miss content because a same-GUID collision looked pre-existing).
|
|
class GuidBaseline {
|
|
public:
|
|
// Observes the current live GUID set. On the FIRST call after construction or
|
|
// reset() this records the baseline and returns {} (nothing is "new" at open).
|
|
// On every later call it returns the GUIDs added since the previous call and
|
|
// advances the baseline to `current`. Empty GUIDs are ignored.
|
|
std::vector<std::string> observe(const std::set<std::string>& current);
|
|
|
|
// Re-arms the first-poll guard: the next observe() re-baselines and reports
|
|
// nothing new. Called on a project switch so detection never diffs across
|
|
// projects.
|
|
void reset();
|
|
|
|
// True until the first observe() after construction/reset — exposed for the shell
|
|
// to reason about (and for tests) about whether a baseline is established yet.
|
|
bool primed() const { return primed_; }
|
|
|
|
private:
|
|
std::set<std::string> baseline_;
|
|
bool primed_ = false; // false ⇒ next observe() sets the baseline
|
|
};
|
|
|
|
} // namespace reasampler
|