mirror of
https://github.com/kilyabin/psysonic.git
synced 2026-07-22 06:25:41 +00:00
184e87a469
* fix(audio): release idle output stream after 60s (#1071) Lazy-open CPAL on first playback and close the device handle after one minute without active audio so Windows can sleep; emit output-released for cold resume and skip post-wake reopen when idle. * docs: CHANGELOG and credits for idle audio stream fix (PR #1073) * fix(audio): satisfy clippy if-same-then-else in idle watcher * fix(audio): silence rodio DeviceSink drop unless logging is debug Gate log_on_drop(false) on runtime should_log_debug() so normal/off logging modes avoid stderr noise from intentional idle stream release. * feat(audio): cold-start paused restore and silent engine prepare After getPlayQueue on startup, apply saved seek position to the UI, prefetch the current track to hot cache, and load the engine paused via new audio_play startPaused so playback does not audibly start before pause. Shared engineLoadTrackAtPosition with queue-undo restore. * fix(audio): satisfy clippy too_many_arguments on stream arm helper Bundle spawn_legacy_stream_start_when_armed parameters into LegacyStreamStartWhenArmed so workspace clippy passes. * fix(audio): release output stream immediately on stop (#1071) Stop and natural queue end call audio_stop; close the CPAL device right away instead of waiting for the 60s idle timer. Pause keeps the grace period for warm resume. * fix(audio): keep waveform mounted after stop (#1071) Stop preserves currentTrack, so its cached analysis waveform stays valid. Stop no longer nulls waveformBins for the still-shown track and re-hydrates them from the analysis DB, instead of dropping to flat placeholder bars. * test(audio): cover output_stream_is_needed branches; harden audio_play arg (#1071) - Add unit tests for the idle-keepalive decision: empty/playing/paused main sink, preview and fading-out sinks, and radio playing/paused. Players are built device-less via rodio's Player::new + a Zero source, so empty()/state are exercised without an audio device. - Make audio_play's `start_paused` an Option<bool> defaulting to false, so the new field is strictly additive (omitting startPaused no longer fails serde). - Drop the unused `_engine` parameter from start_stream_idle_watcher; it resolves the engine from the AppHandle each poll. * refactor(audio): extract sink-swap lifecycle into sink_swap module (#1071) Move SinkSwapInputs/swap_in_new_sink and the legacy stream-arm helper (LegacyStreamStartWhenArmed/spawn_legacy_stream_start_when_armed) out of play_input.rs into a focused sink_swap.rs, so source selection and source building stay separate from sink lifecycle. play_input.rs drops from 953 to 799 lines. No behavior change.
69 lines
2.2 KiB
Rust
69 lines
2.2 KiB
Rust
//! `psysonic-audio` — Symphonia decode, rodio output, HTTP radio/streaming,
|
|
//! gapless, previews. Submodules (`sources`, `decode`, `stream`, `commands`, …)
|
|
//! preserve the historical single `audio.rs` partitioning.
|
|
|
|
// Re-export the logging facade so submodules can keep using
|
|
// `crate::app_eprintln!()` / `crate::app_deprintln!()`.
|
|
pub use psysonic_core::{app_deprintln, app_eprintln, logging};
|
|
|
|
pub mod autoeq_commands;
|
|
mod analysis_dispatch;
|
|
mod codec;
|
|
pub mod commands;
|
|
mod decode;
|
|
mod dev_io;
|
|
pub mod device_commands;
|
|
pub mod mix_commands;
|
|
mod play_input;
|
|
pub mod playback_rate;
|
|
mod sink_swap;
|
|
mod preserve_worker;
|
|
pub mod preload_commands;
|
|
pub(crate) mod progress_task;
|
|
pub mod radio_commands;
|
|
pub mod transport_commands;
|
|
mod device_resume;
|
|
mod device_watcher;
|
|
mod engine;
|
|
mod stream_idle;
|
|
#[cfg(any(target_os = "windows", target_os = "linux"))]
|
|
mod power_resume;
|
|
#[cfg(target_os = "windows")]
|
|
mod power_notify_win;
|
|
#[cfg(target_os = "linux")]
|
|
mod power_notify_linux;
|
|
mod helpers;
|
|
mod ipc;
|
|
pub mod preview;
|
|
mod sources;
|
|
mod state;
|
|
mod stream;
|
|
|
|
pub use device_commands::{audio_default_output_device_name, audio_list_devices_for_engine};
|
|
pub use device_watcher::start_device_watcher;
|
|
pub use stream_idle::start_stream_idle_watcher;
|
|
pub use engine::{create_engine, refresh_http_user_agent, AudioEngine};
|
|
pub use helpers::{
|
|
cleanup_orphan_stream_spill_dir, take_stream_completed_for_url,
|
|
take_stream_completed_spill_for_url,
|
|
};
|
|
|
|
/// Register platform-specific listeners so the output stream is reopened after sleep/resume
|
|
/// when the device name may be unchanged (Windows WASAPI, Linux PipeWire, …).
|
|
pub fn register_post_sleep_audio_recovery(app: tauri::AppHandle) {
|
|
#[cfg(target_os = "windows")]
|
|
power_notify_win::register(app);
|
|
#[cfg(target_os = "linux")]
|
|
power_notify_linux::register(app);
|
|
// macOS intentionally falls through for now: we only ship native resume hooks
|
|
// where we have verified regressions (Windows WASAPI, Linux logind/PipeWire).
|
|
// macOS currently relies on the generic device watcher path.
|
|
#[cfg(all(
|
|
not(target_os = "windows"),
|
|
not(target_os = "linux")
|
|
))]
|
|
let _ = app;
|
|
}
|
|
|
|
pub use engine::{analysis_track_id_is_current_playback, ranged_loudness_backfill_should_defer, stop_audio_engine};
|