refactor: Remove obsolete streaming API (stream.rs, track.rs, per-track feature)

The old streaming API has been completely replaced by RadioParadiseStreamSource
which integrates directly with the pmoaudio pipeline.

Removed:
- src/stream.rs (179 lines) - BlockStream, stream_block(), download_block()
- src/track.rs - Per-track extraction functionality
- examples/stream_block.rs - Obsolete streaming example
- examples/extract_track.rs - Per-track extraction example
- Feature "per-track" and dependencies (hound, tempfile)

Updated:
- Cargo.toml: Removed per-track feature and obsolete examples
- lib.rs: Removed module declarations and re-exports

The new RadioParadiseStreamSource provides:
- Direct integration with pmoaudio pipeline
- FLAC decoding via pmoflac
- Automatic TrackBoundary insertion
- Better performance and lower latency
This commit is contained in:
Claude
2025-11-05 09:15:11 +00:00
parent 9b45be87d6
commit 69831a17df
7 changed files with 0 additions and 831 deletions

View File

@@ -1,120 +0,0 @@
//! Example: Extract individual tracks from a FLAC block (requires `per-track` feature)
//!
//! This example demonstrates:
//! - Per-track extraction from FLAC blocks
//! - Exporting tracks to WAV files
//! - Alternative player-based seeking (recommended)
//!
//! **Warning**: This approach downloads and decodes entire blocks.
//! For most use cases, player-based seeking is more efficient.
//!
//! Run with: cargo run --example extract_track --features per-track
#[cfg(feature = "per-track")]
use pmoparadise::{RadioParadiseClient, Result};
#[cfg(feature = "per-track")]
use std::path::Path;
#[cfg(feature = "per-track")]
#[tokio::main]
async fn main() -> Result<()> {
// Initialize logging
#[cfg(feature = "logging")]
tracing_subscriber::fmt::init();
println!("Radio Paradise - Per-Track Extraction Demo");
println!("===========================================\n");
println!("WARNING: This feature downloads entire blocks (50-100MB)");
println!(" and performs CPU-intensive FLAC decoding.");
println!(" For most use cases, player-based seeking is better.\n");
// Create client
let client = RadioParadiseClient::new().await?;
// Get current block
let block = client.get_block(None).await?;
println!("Block Information:");
println!(" Event: {}", block.event);
println!(" Songs: {}", block.song_count());
println!(" URL: {}\n", block.url);
// Display all tracks
println!("Available Tracks:");
for (index, song) in block.songs_ordered() {
println!(
" {}. {} - {} ({:.1}s)",
index,
song.artist,
song.title,
song.duration as f64 / 1000.0
);
}
println!();
// Extract first track
let track_index = 0;
if let Some((_, song)) = block.songs_ordered().first() {
println!("Extracting Track {}:", track_index);
println!(" Artist: {}", song.artist);
println!(" Title: {}", song.title);
println!(" Album: {}\n", song.album);
println!("Downloading and decoding... (this may take a while)");
// Open track stream
let mut track_stream = client.open_track_stream(&block, track_index).await?;
println!("Track Metadata:");
println!(" Sample Rate: {} Hz", track_stream.metadata.sample_rate);
println!(" Channels: {}", track_stream.metadata.channels);
println!(
" Bits Per Sample: {}",
track_stream.metadata.bits_per_sample
);
println!(" Total Samples: {}", track_stream.metadata.total_samples);
println!();
// Export to WAV
let output_path = Path::new("track.wav");
println!("Exporting to {:?}...", output_path);
track_stream.export_wav(output_path)?;
println!("✓ Export complete!\n");
}
// Show alternative: player-based seeking
println!("RECOMMENDED ALTERNATIVE: Player-Based Seeking");
println!("=============================================\n");
for (index, song) in block.songs_ordered().into_iter().take(3) {
let (start, duration) = client.track_position_seconds(&block, index)?;
println!("Track {}: {} - {}", index, song.artist, song.title);
println!(" mpv command:");
println!(
" mpv --start={:.3} --length={:.3} '{}'",
start, duration, block.url
);
println!(" ffmpeg command (extract to file):");
println!(
" ffmpeg -ss {:.3} -t {:.3} -i '{}' -c copy track_{}.flac",
start, duration, block.url, index
);
println!();
}
println!("These methods are much more efficient as they:");
println!(" - Don't download the entire block");
println!(" - Use the player's optimized seeking");
println!(" - Start playback immediately");
println!(" - Preserve original quality (with -c copy)");
Ok(())
}
#[cfg(not(feature = "per-track"))]
fn main() {
eprintln!("ERROR: This example requires the 'per-track' feature.");
eprintln!("Run with: cargo run --example extract_track --features per-track");
std::process::exit(1);
}

View File

@@ -1,100 +0,0 @@
//! Example: Stream a Radio Paradise block with prefetching
//!
//! This example demonstrates:
//! - Streaming block audio data
//! - Writing to a file or piping to a player
//! - Prefetching the next block for gapless playback
//! - Continuous playback loop
//!
//! Run with: cargo run --example stream_block
//!
//! To play directly with mpv:
//! cargo run --example stream_block | mpv --no-cache --demuxer=+lavf -
use futures::StreamExt;
use pmoparadise::{RadioParadiseClient, Result};
use std::io::Write;
#[tokio::main]
async fn main() -> Result<()> {
// Initialize logging (optional)
#[cfg(feature = "logging")]
tracing_subscriber::fmt::init();
eprintln!("Radio Paradise - Block Streaming Demo");
eprintln!("======================================\n");
// Create client
let mut client = RadioParadiseClient::builder().build().await?;
eprintln!("Client configured for FLAC streaming\n");
// Get current block
let current_block = client.get_block(None).await?;
eprintln!("Current Block:");
eprintln!(" Event: {}", current_block.event);
eprintln!(" Songs: {}", current_block.song_count());
eprintln!(
" Duration: {:.1} minutes",
current_block.length as f64 / 60000.0
);
eprintln!(" URL: {}\n", current_block.url);
// Display tracklist
eprintln!("Tracklist:");
for (index, song) in current_block.songs_ordered() {
eprintln!(" {}. {} - {}", index + 1, song.artist, song.title);
}
eprintln!();
// Prefetch next block in advance
eprintln!("Prefetching next block...");
client.prefetch_next(&current_block).await?;
eprintln!(
"Next block prefetched: {}\n",
client.next_block_url().unwrap()
);
// Stream the block
eprintln!("Streaming block... (writing to stdout)");
eprintln!("Tip: Pipe to a player like: cargo run --example stream_block | mpv -\n");
let mut stream = client.stream_block_from_metadata(&current_block).await?;
let mut total_bytes = 0u64;
let mut stdout = std::io::stdout();
while let Some(chunk_result) = stream.next().await {
let chunk = chunk_result?;
total_bytes += chunk.len() as u64;
// Write to stdout (can be piped to a player)
stdout.write_all(&chunk)?;
stdout.flush()?;
// Progress indicator (to stderr so it doesn't interfere with piped audio)
if total_bytes % (1024 * 1024) == 0 {
eprintln!(
" Downloaded: {:.1} MB",
total_bytes as f64 / 1024.0 / 1024.0
);
}
}
eprintln!("\nBlock streaming complete!");
eprintln!(
"Total downloaded: {:.2} MB",
total_bytes as f64 / 1024.0 / 1024.0
);
// In a real application, you would now:
// 1. Get the next block using prefetched metadata
// 2. Stream it seamlessly
// 3. Prefetch the following block
// 4. Repeat for continuous playback
eprintln!("\nFor continuous playback, you would now stream the next block:");
eprintln!(" Event: {}", current_block.end_event);
Ok(())
}