use dotmax::media::{detect_format, GifPlayer, MediaFormat, MediaPlayer};
use std::env;
use std::io::stdout;
use std::time::{Duration, Instant};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let args: Vec<String> = env::args().collect();
let path = args
.get(1)
.map(String::as_str)
.unwrap_or("tests/fixtures/media/animated.gif");
println!("Animated GIF Player - dotmax Story 9.2");
println!("=====================================\n");
if !std::path::Path::new(path).exists() {
eprintln!("Error: File not found: {}", path);
eprintln!("\nUsage: cargo run --example animated_gif --features image -- <gif_path>");
std::process::exit(1);
}
let format = detect_format(path)?;
println!("Detected format: {}", format);
match format {
MediaFormat::AnimatedGif => {
println!("✓ Animated GIF detected!\n");
play_with_manual_control(path)?;
}
MediaFormat::StaticImage(_) => {
println!("⚠ This is a static image (single frame)");
println!(" Use show_file() for static images.");
}
_ => {
println!("⚠ Not a GIF file: {}", format);
}
}
Ok(())
}
fn play_with_manual_control(path: &str) -> Result<(), Box<dyn std::error::Error>> {
use crossterm::event::{self, Event, KeyCode};
use crossterm::terminal::{self, EnterAlternateScreen, LeaveAlternateScreen};
use crossterm::{cursor, execute};
let mut player = GifPlayer::new(path)?;
println!("GIF Info:");
println!(" Canvas: {}x{} pixels", player.canvas_width(), player.canvas_height());
println!(
" Loop count: {}",
match player.loop_count() {
Some(0) => "infinite".to_string(),
Some(n) => format!("{} times", n),
None => "once".to_string(),
}
);
println!("\nPress Enter to start playback (any key to stop)...");
let _ = std::io::stdin().read_line(&mut String::new());
terminal::enable_raw_mode()?;
let mut stdout = stdout();
execute!(stdout, EnterAlternateScreen, cursor::Hide)?;
let mut renderer = dotmax::TerminalRenderer::new()?;
let mut frame_number = 0;
let start_time = Instant::now();
let result: Result<(), Box<dyn std::error::Error>> = (|| {
loop {
match player.next_frame() {
Some(Ok((grid, delay))) => {
renderer.render(&grid)?;
frame_number += 1;
let deadline = Instant::now() + delay;
while Instant::now() < deadline {
if event::poll(Duration::from_millis(10))? {
if let Event::Key(key) = event::read()? {
if !matches!(key.code, KeyCode::Modifier(_)) {
return Ok(());
}
}
}
}
}
Some(Err(e)) => {
eprintln!("Frame error: {:?}", e);
}
None => {
break;
}
}
}
Ok(())
})();
execute!(stdout, cursor::Show, LeaveAlternateScreen)?;
terminal::disable_raw_mode()?;
let elapsed = start_time.elapsed();
println!("\nPlayback complete!");
println!(" Frames displayed: {}", frame_number);
println!(" Total time: {:.2?}", elapsed);
if frame_number > 0 {
println!(
" Average FPS: {:.1}",
frame_number as f64 / elapsed.as_secs_f64()
);
}
result?;
Ok(())
}