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(); } }