ASIO: park the driver on switch-away instead of closing it (Ed's fix)

The 'set ASIO to none => app dies' crash is the native close inside the Audient
driver. Per Ed: don't tear it down, just stop using it. EnsurePersistentAsioLocked
now, when switching to WasapiOnly/none, keeps the persistent ASIO instance OPEN
but PARKED — rewires its callback to a no-op and drops it to zero active pairs
(UpdateSources([]), which explicitly never closes the driver). No native close =
no crash. It's reused instantly if ASIO is turned back on (also dodges the
close+reopen hang), and only truly closes on a driver change or app exit.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Ednunp
2026-07-15 23:55:33 +01:00
co-authored by Claude Opus 4.8
parent 0c67897448
commit 3103bac791
+8 -5
View File
@@ -358,13 +358,16 @@ public sealed class AudioSender : IDisposable
if (!willUseAsio)
{
// Mode no longer uses ASIO. Dispose the persistent instance so the driver
// releases (other apps may want it).
// Mode no longer uses ASIO. Ed's approach (2026-07-15): do NOT close the driver here — closing
// it is the native call that crashes Audient (the "ASIO -> none kills the app" bug). Instead
// keep the persistent instance OPEN but PARKED: rewire its callback to a no-op and drop it to
// zero active pairs. That stops it feeding any lane WITHOUT a native close, so no crash. It's
// reused instantly if the user turns ASIO back on, and only truly closes on a driver CHANGE
// (below) or app exit — where the OS reclaims it anyway.
if (persistentAsio is not null)
{
try { persistentAsio.Dispose(); } catch { /* ignore */ }
persistentAsio = null;
persistentAsioDriverName = null;
try { persistentAsio.SetCallback(static _ => { }); } catch { /* ignore */ }
try { persistentAsio.UpdateSources(Array.Empty<CaptureSourceSpec>()); } catch { /* ignore */ }
}
return;
}