Files
qbz/crates/qbz-audio/Cargo.toml
T
vicrodh 3adb517236 feat(slint): ImmersiveView base - reusable atmosphere + compact player + audio-transport lift
Foundation for the ImmersiveView Slint port. Authored by Codex and accepted by
the owner after live visual iteration; committed here so the panel work builds
on top of it. The Album Reactive foreground was intentionally left out (a prior
attempt was rejected) so it can be rebuilt cleanly on this base.

Audio-transport lift (slice 1):
- qbz-audio: VizFrame/VizSink trait + spawn_visualizer_thread; FFT producer
  lifted off tauri::AppHandle. Protected audio path untouched (seam =
  RingBuffer.snapshot).
- src-tauri: fft_processor gutted to a thin TauriVizSink emitting byte-identical
  viz:* events.
- qbz-app: AppRuntime::with_visualizer + visualizer_tap accessor.
- qbz-slint: SlintVizSink + install() publishing VisualizerState
  bars/spectral/energy/waveform/transient at 30fps, zero IPC.

Immersive base (slice 2a):
- immersive.rs: host-side atmosphere generation from decoded artwork
  (8x8 sample -> upscale -> blur -> saturate/contrast/normalize -> vignette),
  mirroring Tauri texture-loader.ts::generateAtmosphere; plus glow_color.
- ImmersiveAtmosphere.slint: reusable animated atmosphere (4 counter-drifting
  copies via animation-tick); usable static for Album/Artist headers later.
- ImmersiveView.slint: base overlay (atmosphere + auto-hide Tauri-shaped compact
  player only). Foreground panels are rebuilt on this base.
- AppShell mounts the overlay; ViewMode menu opens Immersive in PlayerBar/Small.

cc
2026-06-13 04:11:53 -06:00

67 lines
2.2 KiB
TOML

[package]
name = "qbz-audio"
version.workspace = true
edition.workspace = true
license.workspace = true
description = "Audio backend system for QBZ - bit-perfect playback"
[dependencies]
qbz-models = { path = "../qbz-models" }
# Async
tokio = { workspace = true }
async-trait = { workspace = true }
# Logging
log = { workspace = true }
# Serialization
serde = { workspace = true }
serde_json = { workspace = true }
# Error handling
thiserror = { workspace = true }
# Audio playback (f32 pipeline is now upstream in rodio 0.22)
rodio = { version = "0.22", features = ["symphonia-all"] }
# Audio analysis
symphonia = { workspace = true }
ebur128 = "0.1"
rustfft = "6.4"
# FFT spectrum helpers for the frontend-agnostic visualizer producer
# (Hann window, log-bar mapping). Kept in lockstep with the src-tauri dep.
spectrum-analyzer = "1.5"
# Database for loudness cache
rusqlite = { version = "0.31", features = ["bundled"] }
# System directories
dirs = "6"
# Lock-free SPSC ring buffer (f32-native) for the JACK feeder -> RT callback
# handoff (#263 Tier 3). f32 elements avoid any byte/alignment handling.
ringbuf = "0.4"
[target.'cfg(target_os = "linux")'.dependencies]
# ALSA for direct hardware access (bit-perfect)
alsa = "0.11"
# alsa-sys: direct FFI for snd_lib_error_set_handler (custom error routing).
# Kept in lockstep with alsa (0.11 -> alsa-sys 0.4); a single alsa-sys is
# required because of the `links = "alsa"` constraint shared with cpal.
alsa-sys = "0.4"
# zbus for org.freedesktop.ReserveDevice1 D-Bus client (device reservation).
# Pinned to v4 to share the transitive copy already pulled in by
# secret-service/souvlaki and avoid duplicate zbus compiles.
zbus = { version = "4", default-features = false, features = ["tokio"] }
# JACK native backend (#263 Tier 3): QBZ as a first-class JACK client with stable
# ports. Links libjack (provided by pipewire-jack on the rig). TODO(distribution):
# feature-gate for Flatpak/distro builds that may not ship libjack — not blocking
# while Tauri isn't being released.
jack = "0.13"
[target.'cfg(target_os = "macos")'.dependencies]
# CoreAudio for device probing, sample rate switching, and (future) hog mode / exclusive mode
coreaudio-rs = "0.14.1"
objc2-core-audio = "0.3.2"