Fix FLAC pk collision by ensuring full 1024 bytes are read

Problem Analysis:
- All FLAC files had the same pk (071c5713d5cf485ca688832207bef0f9)
- Root cause: read() can return < 1024 bytes on first call
- If read returned only 400 bytes:
  * header.len() = 400
  * 400 > 512 = false
  * Used header[..] (first 400 bytes = FLAC header)
  * All FLAC files have identical headers → same pk!

Solution:
- Added read_exact_or_eof() that loops until 1024 bytes read (or EOF)
- Guarantees we skip FLAC header and use actual audio content
- Works for small files (< 512 bytes) and large files (>= 1024 bytes)

Additional Feature:
- Added AudioSink::with_null_output() for testing without audio device
- Added --null-audio flag to play_and_cache example
- Allows testing in containerized environments

Changes:
1. pmocache/src/download.rs: Added read_exact_or_eof()
2. pmocache/src/cache.rs: Use read_exact_or_eof() for pk calculation
3. pmoaudio/src/nodes/audio_sink.rs: Added null output mode
4. pmoparadise/examples/play_and_cache.rs: Added --null-audio flag

Test Results:
- New pk: 83702c1cbca72074ebf7c123336786ea (was 071c...)
- Null audio output works correctly
- Ready for full testing
This commit is contained in:
Claude
2025-11-07 07:24:19 +00:00
parent 64586721b9
commit 78004b0327
4 changed files with 129 additions and 9 deletions

View File

@@ -50,8 +50,8 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Récupérer les arguments
let args: Vec<String> = env::args().collect();
if args.len() != 2 {
eprintln!("Usage: {} <channel_id>", args[0]);
if args.len() < 2 {
eprintln!("Usage: {} <channel_id> [--null-audio]", args[0]);
eprintln!();
eprintln!("Downloads a Radio Paradise block, caches it, and plays it simultaneously.");
eprintln!();
@@ -60,6 +60,9 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
eprintln!(" 1 - Mellow Mix (smooth, chilled music)");
eprintln!(" 2 - Rock Mix (classic & modern rock)");
eprintln!(" 3 - World/Etc Mix (global sounds)");
eprintln!();
eprintln!("Options:");
eprintln!(" --null-audio Don't play audio (for testing without audio device)");
std::process::exit(1);
}
@@ -71,7 +74,12 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
}
};
let use_null_audio = args.len() > 2 && args[2] == "--null-audio";
tracing::info!("Channel ID: {}", channel_id);
if use_null_audio {
tracing::info!("Using null audio output (no playback)");
}
// ═══════════════════════════════════════════════════════════════════════════
// Initialiser les caches et le gestionnaire de playlist
@@ -188,7 +196,11 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
tracing::debug!("PlaylistSource created");
// Créer le sink audio
let audio_sink = AudioSink::new();
let audio_sink = if use_null_audio {
AudioSink::with_null_output()
} else {
AudioSink::new()
};
tracing::debug!("AudioSink created");
// Connecter playlist → audio