#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 #include #include 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 newGuids(const std::set& previous, const std::set& 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 observe(const std::set& 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 baseline_; bool primed_ = false; // false ⇒ next observe() sets the baseline }; } // namespace reasampler