Throttle new-content enumeration to 500ms, off the 30/s OnTimer tick

This commit is contained in:
2026-08-03 14:40:50 -04:00
parent 93d6fd0271
commit 170b2e4994
2 changed files with 37 additions and 13 deletions
+20 -9
View File
@@ -135,8 +135,9 @@ void enumerateLiveGuids(ReaProject* proj, std::set<std::string>& allGuids,
}
// One detection tick: REAPER exposes no "item/track added" callback, so this diffs live
// GUIDs against the baseline and auto-tags the new ones into the active mode. Runs every
// timer tick regardless of panel open/close. READ-ONLY on the project; mutates only the
// GUIDs against the baseline and auto-tags the new ones into the active mode. Called every
// timer tick regardless of panel open/close, but the enumeration itself is throttled to
// kDetectIntervalMs (see the gate below). READ-ONLY on the project; mutates only the
// in-memory membership index — deliberately OUTSIDE any Undo block (auto-tag is a
// background metadata update, not a destructive edit; an Undo block here would flood
// REAPER's history with an entry per tick that sees new content).
@@ -146,6 +147,14 @@ void enumerateLiveGuids(ReaProject* proj, std::set<std::string>& allGuids,
bool detectNewContent() {
if (!g_panel.session) return false;
// Throttles the enumeration (O(T+I) REAPER calls + allocations) to kDetectIntervalMs,
// independent of how often the caller ticks. A skipped tick leaves reloadPending/the
// baseline untouched, so the guards below still run before the NEXT diff whenever this
// gate next opens — only the diff's cadence changes, not its correctness.
const unsigned int now = GetTickCount();
if (now - g_panel.lastDetectTick < kDetectIntervalMs) return false;
g_panel.lastDetectTick = now;
ReaProject* proj = EnumProjects(-1, nullptr, 0);
// A project (re)load re-arms the first-poll guard so we never diff across two
@@ -538,17 +547,19 @@ void unregisterAccel() {
namespace reasampler {
void bankPanelNotifyProjectLoaded() {
// Arms the new-content detector to re-baseline on its next tick so the just-loaded
// project's pre-existing content is the baseline (nothing new) rather than diffed
// against the previous project and mass-tagged. A flag, not an inline reset, because
// detectNewContent owns the baseline and runs later in the SAME OnTimer tick.
// Arms the new-content detector to re-baseline on its next ENUMERATING tick (the flag
// persists across any throttled/skipped ticks in between) so the just-loaded project's
// pre-existing content is the baseline (nothing new) rather than diffed against the
// previous project and mass-tagged. A flag, not an inline reset, because detectNewContent
// owns the baseline and drains this before its own diff.
panel::g_panel.reloadPending = true;
}
void bankPanelRefresh() {
// New-content auto-tag detection runs EVERY tick regardless of panel open/close:
// tracks/items are created in the arrange view, not the panel. READ-ONLY on the
// project; only mutates the in-memory membership index.
// New-content auto-tag detection is CALLED every tick regardless of panel open/close
// (tracks/items are created in the arrange view, not the panel), but the enumeration
// it drives is throttled — see kDetectIntervalMs. READ-ONLY on the project; only
// mutates the in-memory membership index.
const bool tagged = panel::detectNewContent();
// Lane minting runs ONLY when detection just tagged new content — a track can only