refactor(backend): Phase 0 - Initialize multi-crate workspace

Create the foundational workspace structure for the multi-crate
architecture refactor. This phase establishes placeholder crates
that will be populated in subsequent phases.

Crates created:
- qbz-models: Shared types, events, and traits (Tier 0)
- qbz-audio: Audio backend system (Tier 1)
- qbz-player: Playback engine and queue (Tier 1)
- qbz-qobuz: Qobuz API client (Tier 1)
- qbz-core: Orchestrator (Tier 3)

All crates compile successfully with placeholder implementations.
The workspace uses shared dependencies via workspace.dependencies.

cc
This commit is contained in:
vicrodh committed 2026-02-14 12:48:52 -06:00
1 parent 1c9bb8dfdb
commit 0911cf75df
12 files changed
+321

No files matched your search

+1
View File
@@ -71,3 +71,4 @@ qbz-nix-docs/
# AI agent instructions (untracked)
.github/copilot-instructions.md
/crates/target/
+61
View File
@@ -0,0 +1,61 @@
[workspace]
resolver = "2"
members = [
"qbz-models",
"qbz-audio",
"qbz-player",
"qbz-qobuz",
"qbz-core",
]
# Tier 2 crates (to be added later)
# "qbz-offlineplayback",
# "qbz-locallibrary",
# "qbz-cast",
# "qbz-scrobbling",
# "qbz-plex",
[workspace.package]
version = "0.1.0"
edition = "2021"
license = "MIT"
repository = "https://github.com/vicrodh/qbz"
[workspace.dependencies]
# Async runtime
tokio = { version = "1", features = ["full"] }
async-trait = "0.1"
futures-util = "0.3"
tokio-stream = { version = "0.1", features = ["sync"] }
# Serialization
serde = { version = "1", features = ["derive"] }
serde_json = "1"
# HTTP
reqwest = { version = "0.12", features = ["json", "rustls-tls", "cookies", "stream"] }
# Logging
log = "0.4"
tracing = "0.1"
# Error handling
thiserror = "2"
anyhow = "1"
# Crypto (Qobuz auth)
md-5 = "0.10"
base64 = "0.22"
# Time
chrono = "0.4"
# Regex
regex = "1"
# Audio
symphonia = { version = "0.5", features = ["all"] }
# Note: Linux-specific dependencies (alsa) go in individual crate Cargo.toml files
# because workspace manifests cannot have [target] sections
+25
View File
@@ -0,0 +1,25 @@
[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 }
# Error handling
thiserror = { workspace = true }
# Audio will use vendored rodio/cpal from qbz-player
# symphonia = { workspace = true }
[target.'cfg(target_os = "linux")'.dependencies]
alsa = "0.9"
+25
View File
@@ -0,0 +1,25 @@
//! QBZ Audio - Bit-perfect audio backend system
//!
//! This crate provides the audio backend abstraction for QBZ:
//! - AudioBackend trait
//! - PipeWire backend (Linux)
//! - ALSA backend (Linux)
//! - ALSA Direct backend (Linux, bit-perfect)
//!
//! # CRITICAL
//!
//! The audio backends in this crate are IMMUTABLE.
//! They have been extensively debugged and tested for bit-perfect playback.
//! DO NOT modify the logic - only imports may change.
// TODO: Phase 2 - Copy audio modules from qbz-nix
// pub mod backend;
// pub mod pipewire_backend;
// pub mod alsa_backend;
// pub mod alsa_direct;
// pub mod loudness;
// pub mod loudness_analyzer;
// pub mod loudness_cache;
// pub mod dynamic_amplify;
// pub mod analyzer_tap;
// pub mod diagnostic;
+33
View File
@@ -0,0 +1,33 @@
[package]
name = "qbz-core"
version.workspace = true
edition.workspace = true
license.workspace = true
description = "Core orchestrator for QBZ music player"
[dependencies]
qbz-models = { path = "../qbz-models" }
qbz-audio = { path = "../qbz-audio" }
qbz-player = { path = "../qbz-player" }
qbz-qobuz = { path = "../qbz-qobuz" }
# Async
tokio = { workspace = true }
async-trait = { workspace = true }
# Logging
log = { workspace = true }
# Error handling
thiserror = { workspace = true }
anyhow = { workspace = true }
[features]
default = []
# Tier 2 features (to be added later)
# offline = ["qbz-offlineplayback"]
# local-library = ["qbz-locallibrary"]
# cast = ["qbz-cast"]
# scrobbling = ["qbz-scrobbling"]
# plex = ["qbz-plex"]
# full = ["offline", "local-library", "cast", "scrobbling", "plex"]
+34
View File
@@ -0,0 +1,34 @@
//! QBZ Core - Orchestrator for QBZ music player
//!
//! This crate provides the main entry point for QBZ:
//! - QbzCore<A: FrontendAdapter>: Main orchestrator struct
//! - Connects all subsystems (audio, player, queue, API)
//! - Provides unified public API for frontends
//!
//! # Usage
//!
//! ```rust,ignore
//! use qbz_core::{QbzCore, FrontendAdapter, CoreEvent};
//!
//! struct MyAdapter;
//!
//! impl FrontendAdapter for MyAdapter {
//! async fn on_event(&self, event: CoreEvent) {
//! // Handle event, update UI
//! }
//! }
//!
//! let core = QbzCore::new(MyAdapter);
//! core.init().await?;
//! core.login("email", "password").await?;
//! core.play_track(track_id).await?;
//! ```
// TODO: Phase 5 - Implement core orchestrator
// pub mod core;
// pub mod error;
// Re-exports
// pub use qbz_models::*;
// pub use core::QbzCore;
// pub use error::CoreError;
+20
View File
@@ -0,0 +1,20 @@
[package]
name = "qbz-models"
version.workspace = true
edition.workspace = true
license.workspace = true
description = "Shared types, events, and traits for QBZ music player"
[dependencies]
# Serialization
serde = { workspace = true }
serde_json = { workspace = true }
# Async
async-trait = { workspace = true }
# Error handling
thiserror = { workspace = true }
# Time
chrono = { workspace = true }
+15
View File
@@ -0,0 +1,15 @@
//! QBZ Models - Shared types, events, and traits
//!
//! This crate provides the foundation for all QBZ crates:
//! - Type definitions (Track, Album, Artist, etc.)
//! - Event definitions (CoreEvent enum)
//! - Trait definitions (FrontendAdapter)
//! - Configuration types
// TODO: Phase 1 - Implement these modules
// pub mod types;
// pub mod playback;
// pub mod events;
// pub mod traits;
// pub mod config;
// pub mod error;
+29
View File
@@ -0,0 +1,29 @@
[package]
name = "qbz-player"
version.workspace = true
edition.workspace = true
license.workspace = true
description = "Playback engine and queue management for QBZ"
[dependencies]
qbz-models = { path = "../qbz-models" }
qbz-audio = { path = "../qbz-audio" }
# Async
tokio = { workspace = true }
async-trait = { workspace = true }
futures-util = { workspace = true }
tokio-stream = { workspace = true }
# Logging
log = { workspace = true }
# Error handling
thiserror = { workspace = true }
# Audio decoding
symphonia = { workspace = true }
# Vendored audio libraries (will be copied in Phase 3)
# rodio = { path = "./vendor/rodio", features = ["symphonia-all"] }
# cpal = { path = "./vendor/cpal" }
+21
View File
@@ -0,0 +1,21 @@
//! QBZ Player - Playback engine and queue management
//!
//! This crate provides:
//! - Player: Main playback control
//! - QueueManager: Track queue management
//! - StreamingSource: HTTP audio streaming
//! - PlaybackCache: In-memory prefetch cache
//!
//! The vendor/ directory contains modified versions of:
//! - rodio: High-level audio playback
//! - cpal: Cross-platform audio I/O
// TODO: Phase 3 - Copy player modules from qbz-nix
// pub mod player;
// pub mod queue;
// pub mod streaming_source;
// pub mod playback_engine;
// pub mod playback_cache;
// pub use player::Player;
// pub use queue::QueueManager;
+35
View File
@@ -0,0 +1,35 @@
[package]
name = "qbz-qobuz"
version.workspace = true
edition.workspace = true
license.workspace = true
description = "Qobuz API client for QBZ"
[dependencies]
qbz-models = { path = "../qbz-models" }
# Async
tokio = { workspace = true }
# HTTP
reqwest = { workspace = true }
# Serialization
serde = { workspace = true }
serde_json = { workspace = true }
# Crypto (for Qobuz auth)
md-5 = { workspace = true }
base64 = { workspace = true }
# Time
chrono = { workspace = true }
# Regex
regex = { workspace = true }
# Logging
log = { workspace = true }
# Error handling
thiserror = { workspace = true }
+22
View File
@@ -0,0 +1,22 @@
//! QBZ Qobuz - Qobuz API client
//!
//! This crate provides the Qobuz API client:
//! - QobuzClient: Main API interface
//! - Authentication and token management
//! - Search, catalog browsing, streaming URLs
//!
//! The client handles:
//! - Bundle token extraction
//! - Request signing
//! - Session management
// TODO: Phase 4 - Copy API modules from qbz-nix
// pub mod client;
// pub mod auth;
// pub mod endpoints;
// pub mod bundle;
// pub mod performers;
// pub mod error;
// pub use client::QobuzClient;
// pub use error::ApiError;