Implements a new sink for broadcasting FLAC audio to multiple concurrent
HTTP clients (UPnP renderers, web players, etc.) with dynamic metadata updates.
Key features:
- Lazy encoder initialization (auto-detects sample rate from first chunk)
- Broadcast architecture: one encoder, multiple concurrent clients
- Dual streaming modes:
* Pure FLAC mode (standard HTTP streaming)
* ICY metadata mode (Icecast/Shoutcast protocol with "Now Playing")
- Automatic lifecycle management (starts on first client, stops when last disconnects)
- Full metadata support via TrackBoundary sync markers
Architecture:
AudioSegments → PCM conversion → FLAC encoder → Broadcaster task
↓
broadcast::channel
↓
Multiple clients (FlacClientStream/IcyClientStream)
New components:
- StreamingFlacSink: Terminal sink node for audio pipeline
- StreamHandle: Clonable handle for HTTP handlers to subscribe clients
- FlacClientStream: Pure FLAC AsyncRead implementation
- IcyClientStream: ICY-wrapped FLAC with metadata injection
- MetadataSnapshot: Serializable metadata for SSE/JSON endpoints
Feature: http-stream (requires pmoflac, pmometadata, bytes, serde)
38 lines
1.1 KiB
TOML
38 lines
1.1 KiB
TOML
[package]
|
|
name = "pmoaudio-ext"
|
|
version = "0.1.0"
|
|
edition = "2021"
|
|
|
|
[dependencies]
|
|
# Core audio types
|
|
pmoaudio = { path = "../pmoaudio" }
|
|
pmocovers = { path = "../pmocovers"}
|
|
|
|
# Optional dependencies for cache-sink feature
|
|
pmoaudiocache = { path = "../pmoaudiocache", optional = true }
|
|
pmoflac = { path = "../pmoflac", optional = true }
|
|
pmometadata = { path = "../pmometadata", optional = true }
|
|
|
|
# Optional dependencies for playlist integration
|
|
pmoplaylist = { path = "../pmoplaylist", optional = true }
|
|
pmocache = { path = "../pmocache", optional = true }
|
|
|
|
# Async runtime
|
|
tokio = { version = "1.0", features = ["full"] }
|
|
tokio-util = { version = "0.7" }
|
|
async-trait = "0.1"
|
|
|
|
# Utilities
|
|
tracing = "0.1"
|
|
|
|
# HTTP streaming dependencies
|
|
bytes = { version = "1.0", optional = true }
|
|
serde = { version = "1.0", features = ["derive"], optional = true }
|
|
|
|
[features]
|
|
default = []
|
|
cache-sink = ["dep:pmoaudiocache", "dep:pmoflac", "dep:pmometadata"]
|
|
playlist = ["cache-sink", "dep:pmoplaylist", "dep:pmocache"]
|
|
http-stream = ["dep:pmoflac", "dep:pmometadata", "dep:bytes", "dep:serde"]
|
|
all = ["cache-sink", "playlist", "http-stream"]
|