Commit Graph

5 Commits

Author SHA1 Message Date
Psychotoxical 98d8ea6353 refactor: extract psysonic-integration crate (M5/7)
Moves all outbound external-service bridges out of the top crate into a
new psysonic-integration crate.

  crates/psysonic-integration/
    src/discord.rs                     Rich Presence + iTunes artwork
    src/navidrome/{client,covers,...}  Native REST API admin (5 modules)
    src/remote.rs                      radio-browser, last.fm, ICY meta,
                                       generic CORS proxy (fetch_url_bytes
                                       / fetch_json_url / resolve_stream_url)
    src/bandsintown.rs                 events for an artist
    src/lib.rs                         module declarations + macro re-exports

Top crate keeps `crate::discord` working via
`pub use psysonic_integration::discord;`.

invoke_handler! in lib.rs uses full deepest paths
(`psysonic_integration::navidrome::users::nd_list_users`, etc.) so
Tauri's `__cmd__*` magic macros resolve at the right module — same
pattern audio + syncfs already use.

Cross-crate refs migrated:
  crate::subsonic_wire_user_agent → psysonic_core::user_agent::*
  pub(crate) → pub                  (cross-crate visibility)

Behaviour preserving. Cargo check + clippy --workspace clean.
2026-05-09 13:51:28 +02:00
Psychotoxical 9417d522f3 refactor: extract psysonic-syncfs crate (M4/7)
Moves all on-disk cache + device-sync code out of the top crate:

  crates/psysonic-syncfs/                      new lib crate
    src/cache/{offline,hot,downloads,fs_utils} unchanged behaviour
    src/sync/{batch,device}                    (no tray.rs — that's UI)
    src/file_transfer.rs                       shared HTTP helpers
    src/lib.rs                                 + DownloadSemaphore type
                                               + sync_cancel_flags fn

The shell crate keeps `lib_commands/sync/tray.rs` (OS tray icon — UI
concern, will move to shell-tauri at M7) but drops the rest of
`lib_commands/cache/` and the syncfs sibling files.

Tauri command quirk surfaced and resolved: `#[tauri::command]` puts its
`__cmd__*` and `__tauri_command_name_*` helper macros at the *exact*
module of the function, and `pub use` doesn't carry them across module
boundaries. invoke_handler! in lib.rs now references each syncfs
command via its full deepest path
(`psysonic_syncfs::cache::offline::download_track_offline`, etc.) so
Tauri's macros resolve at the right scope. Same approach the audio
crate already uses (`audio::commands::audio_play`).

Cross-crate ref migrations applied via batch sed:
  crate::audio::*               → psysonic_audio::*
  crate::analysis_runtime::*    → psysonic_analysis::analysis_runtime::*
  crate::analysis_cache::*      → psysonic_analysis::analysis_cache::*
  crate::subsonic_wire_user_agent → psysonic_core::user_agent::*
  super::super::file_transfer:: → crate::file_transfer::

Behaviour preserving. Cargo check + clippy --workspace clean.
2026-05-09 13:45:53 +02:00
Psychotoxical 41e75663f1 refactor: extract psysonic-audio crate (M3/7)
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.
2026-05-09 13:33:44 +02:00
Psychotoxical ff456dd823 refactor: extract psysonic-analysis crate (M2/7)
Moves analysis_cache + analysis_runtime out of the top crate into a new
psysonic-analysis crate, plus the runtime user-agent facade into
psysonic-core. The audio↔analysis dependency cycle is broken via a
PlaybackQueryHandle port registered as Tauri State.

  crates/psysonic-analysis/                new lib crate
    src/analysis_cache/{mod,store,compute} unchanged behaviour
    src/analysis_runtime.rs                + enqueue_analysis_seed (was
                                           in lib_commands/cache/offline)

  crates/psysonic-core/src/
    user_agent.rs                          subsonic_wire_user_agent +
                                           runtime/default helpers
                                           (was in top lib.rs)
    ports.rs                               PlaybackQueryHandle: closure
                                           wrapper, not Arc<dyn Trait>,
                                           so existing State<AudioEngine>
                                           callsites stay unchanged

The shell setup hook registers the real PlaybackQueryHandle once the
AppHandle is available; the closure captures it and re-resolves
AudioEngine via try_state at each call.

Top crate keeps `crate::analysis_cache`, `crate::analysis_runtime`,
`crate::subsonic_wire_user_agent`, and `crate::submit_analysis_cpu_seed`
working via re-exports — no audio/lib_commands callsite needed editing.

Behaviour preserving. Cargo check + clippy --workspace clean (only
pre-existing warnings carry over).
2026-05-09 13:25:04 +02:00
Psychotoxical 7718ac3ee5 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.
2026-05-09 13:06:28 +02:00