Completes the JACK output on top of the foundation (fbc03f41):
- StreamType::Jack + the player dispatch (backend==Jack -> JackStream).
- PlaybackEngine::Jack: a feeder thread (mirrors AlsaDirect) that resamples each
source to the JACK graph rate (UniformSourceIterator, stereo) and writes it to
a lock-free f32 SPSC ring (ringbuf); wired at the 4 engine-creation sites.
- jack_backend.rs: f32-native ring (fixes a byte-alignment white-noise bug) plus
auto-connect of qbz:out_FL/FR to the physical playback on activation, so audio
reaches the hardware without a patchbay (a user may re-patch freely).
- Re-enabled the available_backends push (JACK is now offered in the selector).
Verified on hardware: select JACK -> QBZ registers as client 'qbz' with stable
ports qbz:out_FL/FR (client.api=jack) -> music plays through the DAC, resampled
to the graph rate (NOT bit-perfect; BitPerfectMode::Disabled, as designed). The
ALSA-exclusive / DAC-passthrough bit-perfect paths are untouched.
Slice 3.2 (pending, separate): JACK<->passthrough/exclusive mutual-exclusion UI,
the bit-perfect-OFF note, runtime graph-rate-change callback, mono/multichannel.
cc
64 lines
2.0 KiB
TOML
64 lines
2.0 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"
|
|
|
|
# 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"
|