From 3103bac791f6e721c7d15621df24019497691c6e Mon Sep 17 00:00:00 2001 From: Ednunp <29843396+Ednunp@users.noreply.github.com> Date: Wed, 15 Jul 2026 23:55:33 +0100 Subject: [PATCH] ASIO: park the driver on switch-away instead of closing it (Ed's fix) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- src/RemSound.Sender/AudioSender.cs | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/RemSound.Sender/AudioSender.cs b/src/RemSound.Sender/AudioSender.cs index 8ec013f..3556035 100644 --- a/src/RemSound.Sender/AudioSender.cs +++ b/src/RemSound.Sender/AudioSender.cs @@ -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()); } catch { /* ignore */ } } return; }