From f85c0c22c76d87a2b0d0648773a29dc51fbd8652 Mon Sep 17 00:00:00 2001 From: Mollusk Date: Thu, 28 May 2026 15:40:05 -0400 Subject: [PATCH] refactor(audio): dedup Routing teardown into a shared cleanup() shutdown() and Drop had byte-identical bodies that had to be kept in sync. Extract a private cleanup(&mut self); shutdown() consumes self and calls it, Drop calls it as the backstop. Every step is a take(), so the second run is a no-op. Co-Authored-By: Claude Opus 4.8 --- src/host/audio.rs | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/src/host/audio.rs b/src/host/audio.rs index 518339e..1b2f096 100644 --- a/src/host/audio.rs +++ b/src/host/audio.rs @@ -141,7 +141,10 @@ impl Routing { /// Stop the stream router (if any), then unload loopback (if still /// loaded), then unload the null-sink. Order matters: PipeWire can /// leave zombie links if you destroy a sink with active inputs. - pub fn shutdown(mut self) { + /// + /// Every step is a `take()`, so this is idempotent — `Drop` calls it again + /// as a backstop and the second run is a no-op. + fn cleanup(&mut self) { if let Some(router) = self.stream_router.take() { router.shutdown(); } @@ -155,22 +158,17 @@ impl Routing { unload_module(id); } } + + /// Consume the routing and tear it all down now. `Drop` is the backstop; + /// the real work lives in [`cleanup`](Self::cleanup). + pub fn shutdown(mut self) { + self.cleanup(); + } } impl Drop for Routing { fn drop(&mut self) { - if let Some(router) = self.stream_router.take() { - router.shutdown(); - } - if let Some(task) = self.event_task.take() { - task.abort(); - } - if let Some(id) = self.loopback_module.lock().unwrap().take() { - unload_module(id); - } - if let Some(id) = self.sink_module.take() { - unload_module(id); - } + self.cleanup(); } }