mirror of
https://github.com/kilyabin/psysonic.git
synced 2026-07-22 14:35:41 +00:00
41e75663f1
Moves all audio playback code (Symphonia decode, rodio output, HTTP
streaming, gapless, previews, and the seven stream/ source-type
submodules from the prior split) out of the top crate into a new
psysonic-audio crate.
crates/psysonic-audio/ new lib crate, depends on
psysonic-core + psysonic-analysis
src/{engine,helpers,decode,…}.rs flattened layout (no more
extra audio/ namespace level)
src/stream/ seven submodules from M0
src/lib.rs re-exports macros from
psysonic-core and the public
API surface
The audio↔analysis edges identified in the dep survey are now real
crate deps (audio depends on analysis directly: AnalysisCache reads,
recommended_gain_for_target, submit_analysis_cpu_seed). Only the
analysis→audio back-edge goes through the PlaybackQueryHandle port
registered in M2.
Cross-crate ref migrations applied via batch sed:
crate::audio::* → crate::* (intra-crate)
crate::analysis_cache::* → psysonic_analysis::analysis_cache::*
crate::submit_analysis_cpu_seed → psysonic_analysis::analysis_runtime::*
crate::subsonic_wire_user_agent → psysonic_core::user_agent::*
Top crate keeps `crate::audio::*` paths working via
`pub use psysonic_audio as audio;` — lib_commands/cli callers untouched.
`stop_audio_engine` (mac process-exit cleanup) moved into the audio
crate as `pub fn stop_audio_engine` since it reaches AudioEngine
internals; tray.rs now re-exports the moved fn.
Two small visibility promotions in engine.rs:
pub(crate) fn analysis_track_id_is_current_playback → pub
pub(crate) fn ranged_loudness_backfill_should_defer → pub
Behaviour preserving. Cargo check + clippy --workspace clean.
83 lines
2.6 KiB
Rust
83 lines
2.6 KiB
Rust
//! Windows: `PowerRegisterSuspendResumeNotification` — resume from sleep without a default-device rename.
|
|
|
|
use std::ffi::c_void;
|
|
|
|
use tauri::AppHandle;
|
|
use windows::Win32::{
|
|
Foundation::{ERROR_SUCCESS, HANDLE},
|
|
System::Power::{PowerRegisterSuspendResumeNotification, DEVICE_NOTIFY_SUBSCRIBE_PARAMETERS},
|
|
UI::WindowsAndMessaging::{
|
|
DEVICE_NOTIFY_CALLBACK, PBT_APMRESUMEAUTOMATIC, PBT_APMRESUMESUSPEND, PBT_APMRESUMESTANDBY,
|
|
},
|
|
};
|
|
|
|
use super::power_resume::{debounce_allow_resume_reopen, reopen_audio_after_system_resume};
|
|
|
|
unsafe extern "system" fn power_suspend_resume_callback(
|
|
context: *const c_void,
|
|
event_type: u32,
|
|
_setting: *const c_void,
|
|
) -> u32 {
|
|
if context.is_null() {
|
|
return 0;
|
|
}
|
|
if !matches!(
|
|
event_type,
|
|
PBT_APMRESUMEAUTOMATIC | PBT_APMRESUMESUSPEND | PBT_APMRESUMESTANDBY
|
|
) {
|
|
return 0;
|
|
}
|
|
|
|
if !debounce_allow_resume_reopen() {
|
|
return 0;
|
|
}
|
|
|
|
let app = unsafe { &*(context as *const AppHandle) }.clone();
|
|
|
|
tauri::async_runtime::spawn(async move {
|
|
reopen_audio_after_system_resume(&app).await;
|
|
});
|
|
|
|
0
|
|
}
|
|
|
|
pub fn register(app: AppHandle) {
|
|
// Intentionally leaked for process lifetime: Win32 callback receives this pointer
|
|
// on each suspend/resume notification and may outlive this function scope.
|
|
let app_leak = Box::into_raw(Box::new(app));
|
|
|
|
let params = Box::new(DEVICE_NOTIFY_SUBSCRIBE_PARAMETERS {
|
|
Callback: Some(power_suspend_resume_callback),
|
|
Context: app_leak as *mut c_void,
|
|
});
|
|
// Intentionally leaked for process lifetime: the power subsystem keeps the
|
|
// subscribe-parameters pointer after successful registration.
|
|
let params_ptr = Box::into_raw(params);
|
|
|
|
let mut registration: *mut c_void = std::ptr::null_mut();
|
|
let err = unsafe {
|
|
PowerRegisterSuspendResumeNotification(
|
|
DEVICE_NOTIFY_CALLBACK,
|
|
HANDLE(params_ptr as *mut _),
|
|
&mut registration as *mut *mut c_void,
|
|
)
|
|
};
|
|
|
|
if err != ERROR_SUCCESS {
|
|
crate::app_eprintln!(
|
|
"[psysonic] PowerRegisterSuspendResumeNotification failed: {:?} — post-sleep audio recovery disabled",
|
|
err
|
|
);
|
|
unsafe {
|
|
drop(Box::from_raw(params_ptr));
|
|
drop(Box::from_raw(app_leak));
|
|
}
|
|
return;
|
|
}
|
|
|
|
crate::app_eprintln!("[psysonic] Windows power suspend/resume notifications registered for audio");
|
|
// `registration` is an opaque handle returned by Win32 API. It does not own
|
|
// Rust resources, so dropping the local copy is fine; callback context is
|
|
// intentionally leaked above for process-lifetime notifications.
|
|
}
|