feat(windows): keep the system awake while a track plays
Linux holds a logind inhibitor fd; Windows has SetThreadExecutionState, and nothing was calling it. The plan asked for the call to sit in `set_playback`. It cannot: that API is PER-THREAD -- Windows drops a thread's requests when it exits -- and this module's own contract says outbound calls are "free from any thread" (media_controls_qt.rs:34). In practice they arrive on the mpris-server thread, a tokio worker, or the GUI thread, whichever pushed. A request made from a pool worker would evaporate with it, silently. So the state is owned by one thread that lives as long as the process and receives a bool. ES_SYSTEM_REQUIRED without ES_DISPLAY_REQUIRED: an audio player keeps the MACHINE awake, not the screen. No ES_AWAYMODE_REQUIRED either -- that is for media-centre appliances and it suppresses the sleep the user asked for. Exposed as a free function rather than a `PlatformHandle` method, and called BEFORE the `handle()` early return on both publishers. Hanging it off the handle tied it to SMTC: a failed souvlaki init, or an HWND that never arrived, would have left playback working and the machine falling asleep mid-track -- two unrelated features failing together for no reason. `held` is updated only after the API succeeds, so a failed release cannot leave Windows inhibited while later `false` messages are skipped as no-ops. cc
This commit is contained in:
4 files changed
+111
No files matched your search
@@ -217,6 +217,10 @@ pub(crate) fn push_now_playing(track: &qbz_models::QueueTrack, title: &str, albu
|
||||
// smaller set of users.
|
||||
maybe_notify(track, title, album);
|
||||
push_metadata(track, title, album);
|
||||
// BEFORE the early return, and for the same reason `maybe_notify` is:
|
||||
// keeping the machine awake has nothing to do with whether the OS media
|
||||
// integration started, and a track is about to play either way.
|
||||
qbz_media_controls::set_sleep_inhibit(true);
|
||||
let Some(mc) = handle() else {
|
||||
return;
|
||||
};
|
||||
@@ -299,6 +303,7 @@ pub(crate) fn clear_now_playing() {
|
||||
/// transitions the MPRIS `Position` getter answers from the last value pushed
|
||||
/// here — the same behaviour as the Slint build.
|
||||
pub(crate) fn push_playback_state(is_playing: bool, position_secs: u64) {
|
||||
qbz_media_controls::set_sleep_inhibit(is_playing);
|
||||
let Some(mc) = handle() else {
|
||||
return;
|
||||
};
|
||||
|
||||
Reference in new issue
Block a user