This commit implements full OGG container support for FLAC streaming,
wrapping FLAC frames in proper OGG pages with CRC32 validation.
## Changes
### pmoaudio-ext/src/sinks/streaming_ogg_flac_sink.rs
- Implemented `broadcast_ogg_flac_stream()` with actual OGG wrapping
- Added `OggPageWriter` struct for generating OGG pages with proper:
- BOS (Beginning of Stream) flag for stream start
- EOS (End of Stream) flag for stream end
- Page segmentation (255-byte chunks)
- CRC32 checksum calculation
- Added `read_flac_header()` to extract FLAC header for OGG BOS packet
- Added `create_empty_vorbis_comment()` for metadata block
- Header caching: BOS + Vorbis Comment pages sent to late-joining clients
- Streaming architecture: FLAC frames wrapped in ~4KB OGG pages
### pmoparadise/examples/stream_block.rs
- Added dual pipeline support (FLAC + OGG-FLAC)
- Added `/test/stream-ogg` endpoint for OGG-FLAC streaming
- Updated help messages and documentation
- Both pipelines run in parallel with separate sources
### pmoaudio-ext/Cargo.toml
- Added `rand = "0.8"` dependency for OGG stream serial generation
## Architecture
```
PCM Input → FLAC Encoder → OGG Wrapper → Broadcast
↓ ↓ ↓
FLAC frames OGG pages HTTP clients
```
## OGG-FLAC Format
1. BOS page: Contains FLAC identification ("fLaC" + STREAMINFO)
2. Comment page: Contains Vorbis Comment block (metadata)
3. Data pages: Contain FLAC audio frames (~4KB per page)
4. EOS page: Marks end of logical bitstream
## Testing
Verified with Radio Paradise streaming:
- OGG-FLAC encoder initializes correctly (44100 Hz)
- FLAC header extracted (86 bytes)
- OGG header cached (176 bytes: BOS + Comment)
- Stream generates proper OGG pages (654KB test stream)
## Endpoints
- `/test/stream` - Pure FLAC
- `/test/stream-ogg` - OGG-FLAC container (NEW)
- `/test/stream-icy` - FLAC + ICY metadata
- `/test/metadata` - JSON metadata
## TODO (Deferred)
OGG chaining on TrackBoundary: Would require encoder restart and new
logical bitstream per track. Currently metadata is served via
`/test/metadata` endpoint for real-time updates.
Développement de l'application PMOMusic en RUST
🚀 Démarrage rapide
Installation des dépendances (environnement sans sudo)
Pour compiler PMOMusic dans un environnement sans privilèges sudo (comme Claude Code) :
# 1. Installation automatique de libsoxr et libasound2 (une seule fois)
./setup-deps.sh
# 2. Créer le fichier setup-env.sh (une seule fois, voir INSTALL_LIBSOXR.md pour le contenu)
cat > setup-env.sh << 'EOF'
#!/bin/bash
export PKG_CONFIG_PATH="$HOME/.local/usr/lib/x86_64-linux-gnu/pkgconfig:$PKG_CONFIG_PATH"
export LD_LIBRARY_PATH="$HOME/.local/usr/lib/x86_64-linux-gnu:$LD_LIBRARY_PATH"
export RUSTFLAGS="-L $HOME/.local/usr/lib/x86_64-linux-gnu"
echo "Variables d'environnement configurées pour PMOMusic"
EOF
# 3. Configuration de l'environnement (à chaque nouvelle session)
source setup-env.sh
# 4. Compilation
cargo build
# 5. Test de l'exemple Radio Paradise
cargo run --package pmoparadise --example play_and_cache --features full -- 0
⚠️ Note : Le fichier setup-env.sh est dans .gitignore car il contient une configuration locale.
Documentation
- INSTALL_NOTES.md - Guide d'installation général
- INSTALL_LIBSOXR.md - Installation détaillée de libsoxr et ALSA
Création de la structure
mkdir pizzicato
cd pizzicato
jj git init
touch Readme.md
Maintenant on peu créer l'application PMOMusic
cargo new PMOMusic
On ajoute un fichier Cargo.toml décrivant le workspace pizzicato qui ne contient que notre nouvelle application
[workspace]
members = ["PMOMusic"]
On crée le package pmoupnp
cargo new pmoupnp --lib
Cela modifie automatiquement le fichier Cargo.toml créé juste avant.
Dans ce package un sous module statevariable
cd pmoupnp/src
mkdir statevariable
Petite expériences jujutsu
- Je veux voir l'historique
jj log
@ lkmlpmnk eric@coissac.eu 2025-09-12 09:48:38 a27b6a9a
│ On commence les states variables
○ mzvokmpk eric@coissac.eu 2025-09-12 09:32:27 926827f3
│ Retire le répertoir target du suivi
○ skknrvut eric@coissac.eu 2025-09-12 09:05:27 cbad5c34
│ Initialisation des l'arborescence de répertoires
◆ zzzzzzzz root() 00000000
- Je veux me mettre dans un commit:
jj edit mzvokmpk
je veux créer un nouveau commit à la suite d'un autre et m'y placer
jj new mzvokmpk
mzvokmpk peut être @ pour dans le commit courant ou @- pour dans le parent
- je veux arreter de suivre
- un fichier
jj file untrack <filename>
- un répertoire
find dirname -type f -exec jj file untrack {} \;
Dans tous les cas ne pas oublier d'inscrire le fichier ou le repertoire dans le .gitignore
- je veux déplacer un commit comme un sous commit d'un aute
jj rebase -d destination -r source
eventuellement faire un
jj resolve --all
jj rebase --continue
pour résoudre les conflits
Installer rust sur mac
brew install rustup-init
rustup-init
rustup default stable