Commit Graph

5 Commits

Author SHA1 Message Date
Claude
b25a4f9fb3 Add StreamingFlacSink for multi-client HTTP streaming
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)
2025-11-11 19:27:39 +00:00
Claude
bf1de53952 fix: Correct play_and_cache example API usage
Corrections pour que l'exemple utilise les bonnes API:
- Utilisation directe de Cache::new() au lieu de méthodes de config
- Suppression des appels à root() qui n'existent pas
- Utilisation du singleton PlaylistManager() au lieu de new()
- Ajout de cache-sink comme dépendance de playlist feature dans pmoaudio-ext

L'exemple devrait maintenant compiler correctement avec:
cargo run --example play_and_cache --features full -- <channel_id>
2025-11-05 15:55:57 +00:00
Claude
6a7ba01102 feat: Add PlaylistSource and ResamplingNode for playlist playback
This commit implements a new audio source that reads from pmoplaylist
and streams tracks continuously, along with a resampling node to
normalize sample rates.

## New Components

### PlaylistSource (pmoaudio-ext)
- New source in pmoaudio-ext/src/sources/playlist_source.rs
- Reads from pmoplaylist ReadHandle
- Decodes tracks from audio cache (pmoaudiocache)
- Emits PCM with heterogeneous sample_rate and bit_depth
- Polls playlist when empty (configurable interval, default 100ms)
- Emits TrackBoundary markers between tracks
- Graceful shutdown with EndOfStream on stop
- Gated behind 'playlist' feature flag

**Design Philosophy:**
- Keeps each node simple (single responsibility)
- Emits raw PCM without format normalization
- Pipeline designer chooses how to handle heterogeneity
- Ideal for Radio Paradise (homogeneous streams)
- Requires ResamplingNode + ToI24Node for mixed playlists

### ResamplingNode (pmoaudio)
- Generic resampling node in pmoaudio/src/nodes/resampling_node.rs
- Normalizes variable sample rates to a target rate
- Uses libsoxr for high-quality resampling
- Automatically detects sample rate changes
- Recreates resampler as needed
- Preserves chunk type (I16/I24/I32/F32/F64)
- Quality adapts to bit depth (Medium/High/Very High)

## Architecture

PlaylistSource is placed in pmoaudio-ext to avoid circular dependencies:
- pmoaudio-ext depends on: pmoaudio, pmoplaylist, pmoaudiocache
- No reverse dependencies = clean dependency graph

## Configuration

### pmoaudio-ext/Cargo.toml
- Updated 'playlist' feature to include pmoaudiocache, pmocache, pmoflac
- Added sources module export

### pmoaudio
- Added resampling_node module
- Public export: ResamplingNode

## System Requirements

⚠️ **IMPORTANT**: libsoxr-dev must be installed for compilation

See INSTALL_NOTES.md for installation instructions per platform.

## Usage Example

```rust
// Radio Paradise (homogeneous 44.1kHz/16bit)
let mut source = PlaylistSource::new(playlist, cache);
let to_i24 = ToI24Node::new();
source.register(Box::new(to_i24));

// Mixed playlist (needs normalization)
let mut source = PlaylistSource::new(playlist, cache);
let mut resampler = ResamplingNode::new(48000);  // Force 48kHz
let to_i24 = ToI24Node::new();
source.register(Box::new(resampler));
resampler.register(Box::new(to_i24));
```

## Files Changed
- pmoaudio-ext/Cargo.toml: Update playlist feature
- pmoaudio-ext/src/lib.rs: Add sources module
- pmoaudio-ext/src/sources/mod.rs: New sources module
- pmoaudio-ext/src/sources/playlist_source.rs: New PlaylistSource (580 lines)
- pmoaudio/src/nodes/resampling_node.rs: New ResamplingNode (350 lines)
- pmoaudio/src/nodes/mod.rs: Register resampling_node
- pmoaudio/src/lib.rs: Export ResamplingNode
- INSTALL_NOTES.md: System requirements documentation

## Future Work
- GapInsertionNode (inserts silence between tracks)
- CrossfadeNode (fade-in/fade-out mixing)
- Examples (deferred until implementation validated)
2025-11-05 13:44:24 +00:00
83d7520840 Ajout de la gestion des couvertures d'albums par le FlacCacheSink 2025-11-03 20:48:58 +01:00
40950164e9 Ajout d'un noeud puis vers le cache audio 2025-11-03 14:45:37 +01:00