Service: start capturing immediately at boot (catch the Windows startup sound)

The boot log showed a 2.6s gap between the service OnStart and its first capture --
that is the resume-settle delay (2000ms), which exists to stop rapid app open/close
from thrashing the engine. But at boot the interactive app has NEVER been present, so
waiting it out is pure dead time in which the Windows startup tune plays uncaptured
(NVDA, which keeps talking, was caught once capture finally came up; the one-shot tune
was missed).

Fix: the settle now applies only AFTER the app has actually been present (a real
yield). The first-ever stint at boot starts capture immediately, ~2.6s sooner, giving
the startup sound a chance to be captured. Later app->absent transitions keep the
anti-thrash settle.

Gate: 40/40.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Ednunp
2026-07-17 14:48:30 +01:00
co-authored by Claude Opus 4.8
parent 4e15451e1d
commit b8d0fa5a65
+7 -1
View File
@@ -462,11 +462,13 @@ public sealed class ServiceSendHost : IDisposable
var appWasPresent = true; // force an initial evaluation
var absentSince = Environment.TickCount64;
var triedThisAbsence = false;
var haveSeenApp = false; // the settle delay only matters AFTER a real app yield
while (!ct.IsCancellationRequested)
{
var appPresent = isAppPresent();
if (appPresent)
{
haveSeenApp = true;
wantSending = false;
if (IsSending) Suspend();
absentSince = long.MaxValue;
@@ -475,7 +477,11 @@ public sealed class ServiceSendHost : IDisposable
else
{
if (appWasPresent) { absentSince = Environment.TickCount64; triedThisAbsence = false; } // app just left
if (Environment.TickCount64 - absentSince >= resumeSettleMs)
// The resume-settle delay exists to stop rapid app open/close from thrashing the engine —
// but ONLY once the app has actually been present. At BOOT the app has never run, so waiting
// it out is pure dead time in which the Windows startup sound plays uncaptured. Start
// immediately on the first-ever stint; apply the settle only on later app→absent transitions.
if (!haveSeenApp || Environment.TickCount64 - absentSince >= resumeSettleMs)
{
wantSending = true;
// One start attempt per absence. If capture isn't ready yet (audio stack still coming