use std::net::IpAddr;
use std::path::Path;
use framesmith::{ArtImage, Canvas, FileAuthTokenStore, FrameTv};
#[tokio::main]
async fn main() -> Result<(), framesmith::Error> {
tracing_subscriber::fmt()
.with_max_level(tracing::Level::DEBUG)
.with_target(false)
.init();
let args: Vec<String> = std::env::args().collect();
if args.len() < 3 {
eprintln!("Usage: {} <TV_IP> <IMAGE_PATH> [--center]", args[0]);
std::process::exit(1);
}
let ip: IpAddr = args[1].parse().expect("invalid IP address");
let image_path = Path::new(&args[2]);
let center = args.iter().any(|a| a == "--center");
if !image_path.exists() {
eprintln!("File not found: {}", image_path.display());
std::process::exit(1);
}
let token_path = std::env::temp_dir().join("framesmith_token.txt");
let tv = FrameTv::connection_builder(ip)
.auth_token_store(FileAuthTokenStore::new(&token_path))
.connect()
.await?;
println!("Connected to {ip}");
let ext = image_path
.extension()
.and_then(|e| e.to_str())
.map(|e| e.to_lowercase())
.unwrap_or_default();
let mut builder = ArtImage::builder();
builder = match ext.as_str() {
"jpg" | "jpeg" => builder.load_jpeg(image_path)?,
"png" => builder.load_png(image_path)?,
_ => {
eprintln!("Unsupported format '{ext}'. Use JPEG or PNG.");
std::process::exit(1);
}
};
if center {
let rotation = tv.get_display_rotation().await?;
let (tv_w, tv_h) = match rotation {
framesmith::DisplayRotation::Portrait => (2160, 3840),
_ => (3840, 2160),
};
println!("Centering image on {tv_w}x{tv_h} black canvas");
builder = builder.center_image(tv_w, tv_h, Canvas::black());
}
let image = builder.build()?;
println!(
"Uploading {} ({}x{})...",
image_path.display(),
image.width(),
image.height()
);
let uploaded = tv.upload_and_select_art_image(image).await?;
println!("Done! Image ID: {}", uploaded.id());
if !tv.is_artmode_enabled().await? {
tv.enable_artmode().await?;
println!("Art Mode enabled");
}
Ok(())
}