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