diff --git a/src/main.rs b/src/main.rs index 5274c04..94f606f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -171,7 +171,7 @@ unsafe extern "system" fn wndproc( LRESULT(0) } notify::WM_DEVICES_CHANGED => { - with_app(App::refresh_outputs); + with_app(|app| app.refresh_outputs(&app.enumerator.clone())); LRESULT(0) } WM_SETTINGCHANGE => { @@ -208,9 +208,13 @@ impl App { /// The hotkey press. fn advance(&mut self) { self.reload_config_if_changed(); - self.refresh_outputs(); - let current = audio::default_output(&self.enumerator); + // A fresh enumerator per press: the one created at startup can go stale (the audio + // service restarting is enough) and would keep reporting the devices from back then. + let enumerator = audio::enumerator().unwrap_or_else(|_| self.enumerator.clone()); + self.refresh_outputs(&enumerator); + + let current = audio::default_output(&enumerator); let candidates = cycle::candidates(&self.outputs, &self.config.devices); let Some(target) = cycle::next(&candidates, current.as_ref().map(|c| c.id.as_str())) else { @@ -224,14 +228,13 @@ impl App { } // Report what Windows actually ended up with, not what we asked for. - let confirmed = audio::default_output(&self.enumerator).unwrap_or(target); + let confirmed = audio::default_output(&enumerator).unwrap_or(target); self.osd.show(&confirmed.name, confirmed.form); } - fn refresh_outputs(&mut self) { - if let Ok(outputs) = audio::outputs(&self.enumerator) { - self.outputs = outputs; - } + /// A failed enumeration empties the list: an old list would offer an unplugged device. + fn refresh_outputs(&mut self, enumerator: &IMMDeviceEnumerator) { + self.outputs = audio::outputs(enumerator).unwrap_or_default(); } /// Picks up edits to the config file without a restart, but only re-reads when the