namespace ytLive.Services; /// /// Pure show/hide state machine for the game audio bar (TASK 4 game audio). /// SHOW: a full-screen foreground app has been producing desktop audio for at /// least — "a working game with sound". HIDE: the /// app leaves fullscreen/foreground for — the /// game is no longer up in the preview. Silence NEVER hides an active bar; it /// only matters for the initial show. No timers; is fed by /// the caller with a clock. /// public sealed class GameAudioHysteresis { private readonly TimeSpan _showAfterSound = TimeSpan.FromMilliseconds(500); private readonly TimeSpan _hideAfterWindowed = TimeSpan.FromSeconds(1); private DateTime? _soundSince; private DateTime? _windowedSince; public bool IsActive { get; private set; } public void Update(bool isFullScreen, bool hasSound, DateTime now) { if (isFullScreen) { _windowedSince = null; if (IsActive) return; if (!hasSound) { _soundSince = null; return; } _soundSince ??= now; if (now - _soundSince >= _showAfterSound) IsActive = true; } else { _soundSince = null; if (!IsActive) { _windowedSince = null; return; } _windowedSince ??= now; if (now - _windowedSince >= _hideAfterWindowed) { IsActive = false; _windowedSince = null; } } } }