mirror of
https://github.com/Psychotoxical/psysonic.git
synced 2026-07-22 07:15:47 +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.
91 lines
2.5 KiB
Rust
91 lines
2.5 KiB
Rust
//! Linux: subscribe to logind `PrepareForSleep` on the system bus — `start == false` means resume
|
|
//! completed (systemd says the boolean is true when going to sleep, false when waking).
|
|
|
|
use tauri::AppHandle;
|
|
|
|
use super::power_resume::{debounce_allow_resume_reopen, reopen_audio_after_system_resume};
|
|
|
|
pub fn register(app: AppHandle) {
|
|
let res = std::thread::Builder::new()
|
|
.name("psysonic-logind-sleep".into())
|
|
.spawn(move || run_listener(app));
|
|
|
|
if let Err(e) = res {
|
|
crate::app_eprintln!("[psysonic] could not spawn logind listener: {e}");
|
|
}
|
|
}
|
|
|
|
fn run_listener(app: AppHandle) {
|
|
use zbus::blocking::{Connection, MessageIterator};
|
|
use zbus::message::Type;
|
|
use zbus::MatchRule;
|
|
|
|
let conn = match Connection::system() {
|
|
Ok(c) => c,
|
|
Err(e) => {
|
|
crate::app_eprintln!(
|
|
"[psysonic] D-Bus system bus unavailable — post-sleep audio recovery disabled: {e}"
|
|
);
|
|
return;
|
|
}
|
|
};
|
|
|
|
let rule: zbus::MatchRule = match (|| -> zbus::Result<_> {
|
|
Ok(MatchRule::builder()
|
|
.msg_type(Type::Signal)
|
|
.path("/org/freedesktop/login1")?
|
|
.interface("org.freedesktop.login1.Manager")?
|
|
.member("PrepareForSleep")?
|
|
.build())
|
|
})() {
|
|
Ok(r) => r,
|
|
Err(e) => {
|
|
crate::app_eprintln!(
|
|
"[psysonic] MatchRule for logind PrepareForSleep failed: {e}"
|
|
);
|
|
return;
|
|
}
|
|
};
|
|
|
|
let mut iter = match MessageIterator::for_match_rule(rule, &conn, Some(32)) {
|
|
Ok(i) => i,
|
|
Err(e) => {
|
|
crate::app_eprintln!("[psysonic] logind signal subscription failed: {e}");
|
|
return;
|
|
}
|
|
};
|
|
|
|
crate::app_eprintln!("[psysonic] logind PrepareForSleep listener registered (post-sleep audio recovery)");
|
|
|
|
loop {
|
|
let Some(result) = iter.next() else {
|
|
break;
|
|
};
|
|
let msg = match result {
|
|
Ok(m) => m,
|
|
Err(e) => {
|
|
crate::app_eprintln!("[psysonic] logind message stream error: {e}");
|
|
break;
|
|
}
|
|
};
|
|
|
|
let start: bool = match msg.body().deserialize() {
|
|
Ok(b) => b,
|
|
Err(_) => continue,
|
|
};
|
|
|
|
if start {
|
|
continue;
|
|
}
|
|
|
|
if !debounce_allow_resume_reopen() {
|
|
continue;
|
|
}
|
|
|
|
let app = app.clone();
|
|
tauri::async_runtime::spawn(async move {
|
|
reopen_audio_after_system_resume(&app).await;
|
|
});
|
|
}
|
|
}
|