diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..001e703 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +debug/ +target/ +**/*.rs.bk +*.pdb \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index fe75aec..3c0106e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -379,6 +379,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3e5a21b8495e732f1b3c364c9949b201ca7bae518c502c80256c96ad79eaf6ac" dependencies = [ "clap_builder", + "clap_derive", ] [[package]] @@ -393,6 +394,18 @@ dependencies = [ "strsim", ] +[[package]] +name = "clap_derive" +version = "4.5.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "501d359d5f3dcaf6ecdeee48833ae73ec6e42723a1e52419c79abf9507eec0a0" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn 2.0.77", +] + [[package]] name = "clap_lex" version = "0.7.2" diff --git a/Cargo.toml b/Cargo.toml index f74bbce..5008f43 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,7 +8,7 @@ license = "GPL-3.0" readme = "README.md" [dependencies] -clap = { version = "4.5.17", features = ["cargo"] } +clap = { version = "4.5.17", features = ["derive"] } image = "0.25.2" piston = "1.0.0" piston2d-graphics = "0.44.0" diff --git a/src/fileparser.rs b/src/fileparser.rs index 12d0d34..a3f77d3 100644 --- a/src/fileparser.rs +++ b/src/fileparser.rs @@ -1,15 +1,15 @@ -use std::fs::{self, read, File}; -use image::ImageReader; +use std::{ffi::OsStr, fs::{self, read, File}, os::raw, path::Path}; +use image::{ImageFormat, ImageReader}; use unreal_asset::{asset::AssetTrait, cast, engine_version::EngineVersion, exports::{self, normal_export::NormalExport, Export, ExportBaseTrait}, properties::{array_property::ArrayProperty, color_property::ColorProperty, struct_property::StructProperty, Property}, types::{fname::FNameContainer, PackageIndex}, Asset}; -pub fn rawrgb(path: &str) -> Result, String> { +fn rawrgb(path: &str) -> Result, String> { match fs::read(path) { Ok(res) => Ok(res), Err(e) => Err(e.to_string()), } } -pub fn image(path: &str) -> Result, String> { +fn image(path: &str) -> Result, String> { match image::ImageReader::open(path) { Ok(res) => { match res.decode() { @@ -23,8 +23,8 @@ pub fn image(path: &str) -> Result, String> { } } - -pub fn uasset(path: &str) -> Result, String> { +//Shitty formats = Shitty code +fn uasset(path: &str) -> Result, String> { let Some(path) = path.strip_suffix(".uasset") else { return Err("File not .uasset".to_string()) }; @@ -77,3 +77,18 @@ pub fn uasset(path: &str) -> Result, String> { } Ok(output) } + +pub fn parse(path: &str) -> Result, String> { + match Path::new(path).extension().and_then(OsStr::to_str) { + Some(s) => { + if s == "uasset" { + uasset(path) + } else if ImageFormat::from_extension(s).is_some() { + image(path) + } else { + rawrgb(path) + } + }, + None => rawrgb(path), + } +} \ No newline at end of file diff --git a/src/input.rs b/src/input.rs index c45a198..08a1cb2 100644 --- a/src/input.rs +++ b/src/input.rs @@ -1,5 +1,5 @@ +#![allow(non_camel_case_types)] use std::{io::Read, net::UdpSocket, sync::mpsc::{self, Receiver, Sender}, thread, time::{Duration, Instant}}; - use crate::{ parser, fileparser }; pub fn stdin(tx: Sender>) { @@ -23,7 +23,7 @@ pub fn stdin(tx: Sender>) { let _ = tx.send(r); }, Err(_) => { - std::process::exit(0x0100); + std::process::exit(0); }, }; } @@ -42,9 +42,9 @@ pub fn realtimeudp(tx: Sender>) { }); } -pub fn file(tx: Sender>) { +pub fn file(tx: Sender>, path: String) { thread::spawn( move || { - let Ok(rawbytes) = fileparser::rawrgb("out.raw.lily") else { + let Ok(rawbytes) = fileparser::parse(&path) else { std::process::exit(1) }; for frame in rawbytes.chunks(720) { @@ -58,3 +58,10 @@ pub fn file(tx: Sender>) { std::process::exit(0); }); } + +#[derive(clap::ValueEnum, Clone, Debug)] +pub enum Input { + stdin, + realtimeudp, + file, +} diff --git a/src/main.rs b/src/main.rs index 7111b38..dde15e8 100644 --- a/src/main.rs +++ b/src/main.rs @@ -6,9 +6,27 @@ mod utils; mod fileparser; use std::sync::mpsc::{self, Receiver, Sender}; -use clap::{command, Parser}; +use clap::{command, error::{self, ContextKind, ContextValue, ErrorKind}, Parser}; + +#[derive(Parser, Debug)] +#[command(version, about, long_about = None)] +struct Args { + /// Name of the person to greet + #[arg(short, long)] + input: input::Input, + + #[arg(required(false), short, long, requires = "input")] + file: Option, + + #[arg(short, long)] + output: output::Output, + + #[arg(required(false), short, long, requires = "output")] + destip: Option, +} fn main() { + let args = Args::parse(); // let mut arg = clap::command!() // .arg(clap::arg!(-o --output "The output file to write to. Use - for stdout.")) // .arg_required_else_help(true); @@ -19,8 +37,27 @@ fn main() { // } else { // input::realtimeudp(tx) // } - input::file(tx); - output::realtimeudp(rx) - - + match args.input { + input::Input::stdin => input::stdin(tx), + input::Input::realtimeudp => input::realtimeudp(tx), + input::Input::file => { + if args.file.is_some() { + input::file(tx, args.file.unwrap()); + } else { + utils::err_missing_args(vec!["--file".to_owned()]) + } + }, + } + // input::file(tx); + // output::piston(rx) 21324 + match args.output { + output::Output::piston => output::piston(rx), + output::Output::realtimeudp => { + if args.destip.is_some() { + output::realtimeudp(rx, args.destip.unwrap()) + } else { + utils::err_missing_args(vec!["--destip".to_owned()]) + } + }, + } } diff --git a/src/output.rs b/src/output.rs index d97098a..15d9678 100644 --- a/src/output.rs +++ b/src/output.rs @@ -1,3 +1,4 @@ +#![allow(non_camel_case_types)] extern crate piston_window; use graphics; @@ -31,7 +32,7 @@ pub fn piston(rx: Receiver>) { } } -pub fn realtimeudp(rx: Receiver>) { +pub fn realtimeudp(rx: Receiver>, addr: String) { let socket = UdpSocket::bind("0.0.0.0:0").unwrap(); loop { let leds = rx.recv().unwrap(); @@ -41,6 +42,18 @@ pub fn realtimeudp(rx: Receiver>) { packet.push((led[1]*255.0) as u8); packet.push((led[2]*255.0) as u8); } - let _ = socket.send_to(&packet, SocketAddr::from(([204, 2, 68, 140 ], 21324))).unwrap(); + match socket.send_to(&packet, &addr) { + Ok(_) => (), + Err(err) => { + println!("Error while sending trying to send data: {}", err); + std::process::exit(1); + }, + }; } } + +#[derive(clap::ValueEnum, Clone, Debug)] +pub enum Output { + piston, + realtimeudp, +} \ No newline at end of file diff --git a/src/utils.rs b/src/utils.rs index b5a4c8c..7eccf4e 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,3 +1,5 @@ +use clap::error::{ContextKind, ContextValue, ErrorKind}; + pub fn compare(a: f64, b: f64) -> f64 { if a > b { b @@ -16,4 +18,11 @@ pub fn offset(n: i16, max: i16, offset: i16) -> i16 { pub fn scaleu8tof32(old_value: u8) -> f32 { // Convert a u8 between 0 and 255 to a f32 between 0.0 and 1.0 for piston colors (((old_value as f32 - 0.0) * (0.0 - 1.0)) / (0.0 - 255.0)) + 0.0 +} + +pub fn err_missing_args(args: Vec) { + let mut err = clap::Error::new(ErrorKind::MissingRequiredArgument); + err.insert(ContextKind::InvalidArg, ContextValue::Strings(args)); + let _ = err.print(); + std::process::exit(1); } \ No newline at end of file