mirror of
https://github.com/Psychotoxical/psysonic.git
synced 2026-07-22 15:25:46 +00:00
refactor: introduce cargo workspace + psysonic-core crate (M1/7)
First milestone of the workspace crate split. Sets up the workspace
skeleton and extracts shared logging + cross-crate port traits into a
new psysonic-core crate.
src-tauri/Cargo.toml now defines [workspace]; top package
becomes the workspace root.
crates/psysonic-core/ new lib crate, no Tauri-handler code:
src/logging.rs full logging facade (was src/logging.rs)
src/ports.rs PlaybackQuery + AnalysisOrchestrator
trait declarations (no impls yet)
The top crate re-exports `psysonic_core::logging` and the
`app_eprintln!` / `app_deprintln!` macros so every existing
`crate::logging::*` and `crate::app_eprintln!` callsite keeps working
unchanged.
Port traits intentionally take `tauri::AppHandle` — psysonic-core is a
workspace-internal crate, so depending on Tauri here is a feature, not
a leak. Implementers will register themselves as
`Arc<dyn PlaybackQuery>` / `Arc<dyn AnalysisOrchestrator>` Tauri State
in M2/M3.
Behaviour preserving. Cargo check + clippy --workspace clean.
This commit is contained in:
Generated
+10
@@ -3608,6 +3608,7 @@ dependencies = [
|
|||||||
"libc",
|
"libc",
|
||||||
"lofty",
|
"lofty",
|
||||||
"md5",
|
"md5",
|
||||||
|
"psysonic-core",
|
||||||
"reqwest",
|
"reqwest",
|
||||||
"ringbuf",
|
"ringbuf",
|
||||||
"rodio",
|
"rodio",
|
||||||
@@ -3637,6 +3638,15 @@ dependencies = [
|
|||||||
"zbus 5.15.0",
|
"zbus 5.15.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "psysonic-core"
|
||||||
|
version = "1.46.0-dev"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"serde",
|
||||||
|
"tauri",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pxfm"
|
name = "pxfm"
|
||||||
version = "0.1.29"
|
version = "0.1.29"
|
||||||
|
|||||||
+13
-3
@@ -1,13 +1,22 @@
|
|||||||
|
[workspace]
|
||||||
|
members = ["crates/*"]
|
||||||
|
resolver = "2"
|
||||||
|
|
||||||
|
[workspace.package]
|
||||||
|
version = "1.46.0-dev"
|
||||||
|
edition = "2021"
|
||||||
|
rust-version = "1.89"
|
||||||
|
|
||||||
[package]
|
[package]
|
||||||
name = "psysonic"
|
name = "psysonic"
|
||||||
version = "1.46.0-dev"
|
version.workspace = true
|
||||||
description = "Psysonic Desktop Music Player"
|
description = "Psysonic Desktop Music Player"
|
||||||
authors = []
|
authors = []
|
||||||
license = ""
|
license = ""
|
||||||
repository = ""
|
repository = ""
|
||||||
default-run = "psysonic"
|
default-run = "psysonic"
|
||||||
edition = "2021"
|
edition.workspace = true
|
||||||
rust-version = "1.89"
|
rust-version.workspace = true
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
name = "psysonic_lib"
|
name = "psysonic_lib"
|
||||||
@@ -21,6 +30,7 @@ path = "src/main.rs"
|
|||||||
tauri-build = { version = "2", features = [] }
|
tauri-build = { version = "2", features = [] }
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
psysonic-core = { path = "crates/psysonic-core" }
|
||||||
tauri = { version = "2", features = ["tray-icon", "image-png"] }
|
tauri = { version = "2", features = ["tray-icon", "image-png"] }
|
||||||
tauri-plugin-single-instance = "2"
|
tauri-plugin-single-instance = "2"
|
||||||
tauri-plugin-shell = "2"
|
tauri-plugin-shell = "2"
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
[package]
|
||||||
|
name = "psysonic-core"
|
||||||
|
version.workspace = true
|
||||||
|
edition.workspace = true
|
||||||
|
rust-version.workspace = true
|
||||||
|
publish = false
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
tauri = { version = "2" }
|
||||||
|
serde = { version = "1", features = ["derive"] }
|
||||||
|
|
||||||
|
[target.'cfg(unix)'.dependencies]
|
||||||
|
libc = "0.2"
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
//! `psysonic-core` — workspace-internal shared primitives.
|
||||||
|
//!
|
||||||
|
//! Hosts the runtime logging facade (with `app_eprintln!` / `app_deprintln!`
|
||||||
|
//! macros) and the cross-crate port traits used to break dependency cycles
|
||||||
|
//! between `psysonic-audio`, `psysonic-analysis`, and other domain crates.
|
||||||
|
|
||||||
|
pub mod logging;
|
||||||
|
pub mod ports;
|
||||||
@@ -1,3 +1,10 @@
|
|||||||
|
//! Runtime logging facade.
|
||||||
|
//!
|
||||||
|
//! Provides level-gated `eprintln!` macros (`app_eprintln!` / `app_deprintln!`)
|
||||||
|
//! that also append to a bounded in-memory ring buffer and a CLI-readable
|
||||||
|
//! per-runtime log file. Live mode toggling at runtime via
|
||||||
|
//! `set_logging_mode_from_str("off"|"normal"|"debug")`.
|
||||||
|
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
use libc;
|
use libc;
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
@@ -98,7 +105,7 @@ pub fn export_logs_to_file(path: &str) -> Result<usize, String> {
|
|||||||
Ok(lines)
|
Ok(lines)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn log_timestamp_local() -> String {
|
pub fn log_timestamp_local() -> String {
|
||||||
let now = ::std::time::SystemTime::now()
|
let now = ::std::time::SystemTime::now()
|
||||||
.duration_since(::std::time::UNIX_EPOCH)
|
.duration_since(::std::time::UNIX_EPOCH)
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
//! Cross-crate port traits.
|
||||||
|
//!
|
||||||
|
//! These traits exist purely to break dependency cycles that would otherwise
|
||||||
|
//! force `psysonic-audio` ↔ `psysonic-analysis` to depend on each other in
|
||||||
|
//! both directions. Implementers register themselves as Tauri State on app
|
||||||
|
//! bootstrap; consumers look them up via `app.try_state::<Arc<dyn _>>()`.
|
||||||
|
//!
|
||||||
|
//! Layout:
|
||||||
|
//! - `AnalysisOrchestrator` — implemented in `psysonic-analysis`, called from
|
||||||
|
//! `psysonic-audio` to enqueue full-buffer loudness/waveform analysis.
|
||||||
|
//! - `PlaybackQuery` — implemented in `psysonic-audio` on `AudioEngine`,
|
||||||
|
//! called from `psysonic-analysis` to ask "is this track currently playing?".
|
||||||
|
|
||||||
|
use std::future::Future;
|
||||||
|
use std::pin::Pin;
|
||||||
|
|
||||||
|
use tauri::AppHandle;
|
||||||
|
|
||||||
|
/// Read-only queries about the live playback session. Implemented on
|
||||||
|
/// `AudioEngine` in `psysonic-audio`.
|
||||||
|
///
|
||||||
|
/// Registered as `Arc<dyn PlaybackQuery>` in Tauri State so non-audio crates
|
||||||
|
/// can query without taking a hard dep on the audio crate.
|
||||||
|
pub trait PlaybackQuery: Send + Sync + 'static {
|
||||||
|
/// `true` if `track_id` is the track currently being decoded/played.
|
||||||
|
fn is_track_currently_playing(&self, track_id: &str) -> bool;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Triggers full-buffer analysis on already-captured track bytes. Implemented
|
||||||
|
/// on `AnalysisRuntime` in `psysonic-analysis`.
|
||||||
|
///
|
||||||
|
/// Registered as `Arc<dyn AnalysisOrchestrator>` in Tauri State so audio
|
||||||
|
/// callsites (`stream::ranged_http`, `stream::track_stream`, `helpers`,
|
||||||
|
/// `play_input`, `preload_commands`) can submit without depending on
|
||||||
|
/// `psysonic-analysis`.
|
||||||
|
pub trait AnalysisOrchestrator: Send + Sync + 'static {
|
||||||
|
/// Enqueue a CPU-seed analysis pass for `track_id` over the given byte
|
||||||
|
/// buffer. `high_priority` mirrors the HTTP-backfill head-insertion
|
||||||
|
/// behaviour for the currently playing track.
|
||||||
|
///
|
||||||
|
/// Errors are stringified — audio callers only care about pass/fail.
|
||||||
|
fn submit_cpu_seed<'a>(
|
||||||
|
&'a self,
|
||||||
|
app: AppHandle,
|
||||||
|
track_id: String,
|
||||||
|
bytes: Vec<u8>,
|
||||||
|
high_priority: bool,
|
||||||
|
) -> Pin<Box<dyn Future<Output = Result<(), String>> + Send + 'a>>;
|
||||||
|
}
|
||||||
@@ -6,8 +6,10 @@ mod analysis_cache;
|
|||||||
mod analysis_runtime;
|
mod analysis_runtime;
|
||||||
pub mod cli;
|
pub mod cli;
|
||||||
mod discord;
|
mod discord;
|
||||||
pub(crate) mod logging;
|
|
||||||
mod lib_commands;
|
mod lib_commands;
|
||||||
|
|
||||||
|
pub use psysonic_core::logging;
|
||||||
|
pub use psysonic_core::{app_eprintln, app_deprintln};
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
mod taskbar_win;
|
mod taskbar_win;
|
||||||
mod tray_runtime;
|
mod tray_runtime;
|
||||||
|
|||||||
Reference in New Issue
Block a user