use std::time::Duration;
use anyhow::{Context, Result, anyhow};
use clap::Args;
#[derive(Debug, Args)]
pub struct SnapshotArgs {
#[arg(default_value = "snapshot.png")]
pub path: String,
#[arg(long)]
pub camera: Option<String>,
}
pub fn run(args: SnapshotArgs) -> Result<()> {
let unique_id = match args.camera {
Some(id) => id,
None => openlogi_camera::enumerate_cameras()
.into_iter()
.next()
.map(|camera| camera.unique_id)
.ok_or_else(|| anyhow!("no Logitech camera found"))?,
};
println!("capturing one frame from {unique_id} …");
let frame = openlogi_camera::capture_frame(&unique_id, Duration::from_secs(5))
.map_err(|e| anyhow!("{e}"))?;
let mut rgba = frame.bgra;
for px in rgba.chunks_exact_mut(4) {
px.swap(0, 2);
}
write_png(&args.path, frame.width, frame.height, &rgba)
.with_context(|| format!("writing {}", args.path))?;
println!("wrote {}x{} → {}", frame.width, frame.height, args.path);
Ok(())
}
fn write_png(path: &str, width: u32, height: u32, rgba: &[u8]) -> Result<()> {
let file = std::fs::File::create(path)?;
let writer = std::io::BufWriter::new(file);
let mut encoder = png::Encoder::new(writer, width, height);
encoder.set_color(png::ColorType::Rgba);
encoder.set_depth(png::BitDepth::Eight);
encoder
.write_header()?
.write_image_data(rgba)
.context("encoding PNG")
}