Pure-function helpers used by the upcoming track-mix sampler: - normalize_title strips parens/brackets, dash suffixes, feat patterns, punctuation, and diacritics. - normalize_artist keeps parens (band suffixes carry meaning) and just lowercases + strips diacritics. - token_set_ratio implements the RapidFuzz-style token-set similarity in [0.0, 1.0] using strsim's normalized Levenshtein. Promotes strsim from transitive to direct dep. 18 unit tests cover the core normalization and similarity behaviors. cc
179 lines
5.6 KiB
TOML
179 lines
5.6 KiB
TOML
[package]
|
|
name = "qbz-nix"
|
|
version = "1.2.8"
|
|
description = "Native high-fidelity client for Qobuz™ subscribers on Linux with Hi-Fi audio support (uses the Qobuz API; not certified by Qobuz)"
|
|
authors = ["blitzkriegfc"]
|
|
edition = "2021"
|
|
|
|
[lib]
|
|
name = "qbz_nix_lib"
|
|
crate-type = ["staticlib", "cdylib", "rlib"]
|
|
|
|
[[bin]]
|
|
name = "qbz"
|
|
path = "src/main.rs"
|
|
|
|
[build-dependencies]
|
|
tauri-build = { version = "2", features = [] }
|
|
|
|
[features]
|
|
default = ["updater"]
|
|
# Enables the in-app auto-updater (tauri-plugin-updater + tauri-plugin-process).
|
|
# Disabled for sandboxed packaging targets (Flatpak, Snap) which have their own
|
|
# update channels and whose store policies prohibit competing updaters.
|
|
updater = ["dep:tauri-plugin-updater", "dep:tauri-plugin-process"]
|
|
|
|
[dependencies]
|
|
# QBZ Crates (extracted core functionality)
|
|
qbz-models = { path = "../crates/qbz-models" }
|
|
qbz-audio = { path = "../crates/qbz-audio" }
|
|
qbz-player = { path = "../crates/qbz-player" }
|
|
qbz-qobuz = { path = "../crates/qbz-qobuz" }
|
|
qbz-core = { path = "../crates/qbz-core" }
|
|
qbz-integrations = { path = "../crates/qbz-integrations" }
|
|
qbz-cache = { path = "../crates/qbz-cache" }
|
|
qbz-library = { path = "../crates/qbz-library" }
|
|
qbz-cast = { path = "../crates/qbz-cast" }
|
|
qbz-cmaf = { path = "../crates/qbz-cmaf" }
|
|
qbz-secrets = { path = "../crates/qbz-secrets" }
|
|
mdns-sd = "0.11"
|
|
qconnect-app = { path = "../crates/qconnect-app" }
|
|
qconnect-core = { path = "../crates/qconnect-core" }
|
|
qconnect-transport-ws = { path = "../crates/qconnect-transport-ws" }
|
|
|
|
# Tauri
|
|
tauri = { version = "2", features = ["protocol-asset", "tray-icon", "macos-private-api"] }
|
|
tauri-plugin-opener = "2"
|
|
tauri-plugin-os = "2"
|
|
tauri-plugin-single-instance = { version = "2", features = ["deep-link"] }
|
|
tauri-plugin-deep-link = "2"
|
|
tauri-plugin-updater = { version = "2", optional = true }
|
|
tauri-plugin-process = { version = "2", optional = true }
|
|
|
|
# Serialization
|
|
serde = { version = "1", features = ["derive"] }
|
|
serde_json = "1"
|
|
|
|
# HTTP Client
|
|
reqwest = { version = "0.12", features = ["json", "cookies", "rustls-tls", "native-tls", "stream", "blocking", "multipart"], default-features = false }
|
|
|
|
# Async Runtime
|
|
tokio = { version = "1", features = ["full"] }
|
|
async-trait = "0.1"
|
|
tokio-stream = { version = "0.1", features = ["sync"] }
|
|
|
|
# Local API server
|
|
axum = { version = "0.8", features = ["ws"] }
|
|
axum-server = { version = "0.8", features = ["tls-rustls"] }
|
|
rustls = { version = "0.23", default-features = false, features = ["aws-lc-rs"] }
|
|
tower-http = { version = "0.5", features = ["cors"] }
|
|
qrcode-generator = "5.0"
|
|
rcgen = "0.14"
|
|
|
|
# Crypto (for API signatures and credential encryption)
|
|
md-5 = "0.10"
|
|
base64 = "0.22"
|
|
aes-gcm = "0.10"
|
|
sha2 = "0.10"
|
|
|
|
# Regex (for bundle parsing)
|
|
regex = "1"
|
|
lazy_static = "1.4"
|
|
|
|
# Time
|
|
chrono = "0.4"
|
|
|
|
# Error handling
|
|
thiserror = "2"
|
|
anyhow = "1"
|
|
|
|
# Logging
|
|
log = "0.4"
|
|
env_logger = "0.11"
|
|
|
|
# Random number generation (for shuffle)
|
|
rand = "0.10"
|
|
|
|
# Fuzzy string similarity (for track-mix dedup)
|
|
strsim = "0.11"
|
|
|
|
# Audio playback
|
|
rodio = { version = "0.22", features = ["symphonia-all"] }
|
|
symphonia = { version = "0.5", features = ["all"] }
|
|
|
|
# Audio visualization (FFT)
|
|
spectrum-analyzer = "1.5"
|
|
|
|
# EBU R128 loudness measurement (real-time normalization)
|
|
ebur128 = "0.1"
|
|
|
|
# Media controls (MPRIS on Linux)
|
|
souvlaki = "0.8"
|
|
|
|
# Desktop notifications → ashpd in [target.linux] deps below
|
|
|
|
# Image processing (tray icon + thumbnails)
|
|
image = { version = "0.25", default-features = false, features = ["png", "jpeg", "webp"] }
|
|
|
|
# PDF rendering with MuPDF engine (high-quality rasterization for booklet viewer)
|
|
# NOTE: On Linux, use sys-lib-* for zlib/harfbuzz/freetype to avoid symbol
|
|
# conflicts with GTK/GdkPixbuf. But NOT libjpeg — Ubuntu ships libjpeg8 while
|
|
# Debian/Fedora ship libjpeg62-turbo. Let mupdf vendor its own libjpeg to avoid
|
|
# cross-distro breakage (GitHub #161, #162).
|
|
# On macOS, let mupdf vendor everything (no GTK conflicts, and system libs
|
|
# don't support x86_64 cross-compilation from Apple Silicon).
|
|
mupdf = { version = "0.6", default-features = false, features = ["system-fonts"] }
|
|
|
|
# URL opening
|
|
open = "5"
|
|
|
|
# Local library
|
|
walkdir = "2"
|
|
lofty = "0.23"
|
|
rusqlite = { version = "0.31", features = ["bundled"] }
|
|
dirs = "6"
|
|
filetime = "0.2"
|
|
glob = "0.3"
|
|
uuid = { version = "1", features = ["v4", "serde"] }
|
|
|
|
# File dialogs - platform specific (see target dependencies below)
|
|
|
|
# URL encoding
|
|
urlencoding = "2"
|
|
|
|
# Environment variables
|
|
dotenvy = "0.15"
|
|
|
|
# Secure credential storage (system keyring: GNOME Keyring, KDE Wallet, macOS Keychain)
|
|
keyring = { version = "3", features = ["async-secret-service", "crypto-rust"] }
|
|
|
|
# Clipboard
|
|
tauri-plugin-clipboard-manager = "2"
|
|
|
|
# Casting: qbz-cast crate provides all casting functionality
|
|
# (Chromecast via rust_cast, DLNA via rupnp)
|
|
|
|
# Async utilities (used across codebase)
|
|
futures-util = "0.3"
|
|
|
|
# Platform-specific dependencies
|
|
[target.'cfg(target_os = "linux")'.dependencies]
|
|
tauri-plugin-dialog = { version = "2.7.0" }
|
|
ashpd = { version = "0.13", default-features = false, features = ["tokio", "notification", "inhibit", "secret"] }
|
|
mupdf = { version = "0.6", features = ["sys-lib-zlib", "sys-lib-harfbuzz", "sys-lib-freetype"] }
|
|
# Linux tray via StatusNotifierItem with primary-activate support.
|
|
# Tauri's built-in tray uses libayatana-appindicator which does not dispatch
|
|
# left-click events to clients (by design — primary click always shows the
|
|
# menu). ksni is a pure-Rust SNI impl that exposes Activate. See issue #310.
|
|
ksni = { version = "0.3", features = ["blocking"] }
|
|
|
|
[target.'cfg(target_os = "macos")'.dependencies]
|
|
tauri-plugin-dialog = { version = "2.7.0" }
|
|
notify-rust = "4.16.0"
|
|
|
|
[target.'cfg(target_os = "windows")'.dependencies]
|
|
tauri-plugin-dialog = { version = "2.7.0" }
|
|
|
|
[dev-dependencies]
|
|
tempfile = "3"
|