diff --git a/src/arg_handler.rs b/src/arg_handler.rs index 6080c02..e44f0a0 100644 --- a/src/arg_handler.rs +++ b/src/arg_handler.rs @@ -1,19 +1,16 @@ extern crate clap; extern crate num_cpus; -use clap::{Arg, ArgMatches, App}; +use clap::{App, Arg, ArgMatches}; use app::*; - - /// CLI argument handler. pub struct ArgHandler<'a> { matches: ArgMatches<'a>, } impl<'a: 'b, 'b> ArgHandler<'a> { - /// Parse CLI arguments. pub fn parse() -> ArgHandler<'a> { // Handle/parse arguments @@ -21,88 +18,95 @@ impl<'a: 'b, 'b> ArgHandler<'a> { .version(APP_VERSION) .author(APP_AUTHOR) .about(APP_ABOUT) - .arg(Arg::with_name("HOST") - .help("The host to pwn \"host:port\"") - .required(true) - .index(1)) - .arg(Arg::with_name("image") - .short("i") - .long("image") - .alias("images") - .value_name("PATH") - .help("Image paths") - .required(true) - .multiple(true) - .display_order(1) - .takes_value(true)) - .arg(Arg::with_name("width") - .short("w") - .long("width") - .value_name("PIXELS") - .help("Draw width (def: screen width)") - .display_order(2) - .takes_value(true)) - .arg(Arg::with_name("height") - .short("h") - .long("height") - .value_name("PIXELS") - .help("Draw height (def: screen height)") - .display_order(3) - .takes_value(true)) - .arg(Arg::with_name("x") - .short("x") - .value_name("PIXELS") - .help("Draw X offset (def: 0)") - .display_order(4) - .takes_value(true)) - .arg(Arg::with_name("y") - .short("y") - .value_name("PIXELS") - .help("Draw Y offset (def: 0)") - .display_order(5) - .takes_value(true)) - .arg(Arg::with_name("count") - .short("c") - .long("count") - .alias("thread") - .alias("threads") - .value_name("COUNT") - .help("Number of concurrent threads (def: CPUs)") - .display_order(6) - .takes_value(true)) - .arg(Arg::with_name("fps") - .short("r") - .long("fps") - .value_name("RATE") - .help("Frames per second with multiple images (def: 1)") - .display_order(7) - .takes_value(true)) - .get_matches(); + .arg( + Arg::with_name("HOST") + .help("The host to pwn \"host:port\"") + .required(true) + .index(1), + ).arg( + Arg::with_name("image") + .short("i") + .long("image") + .alias("images") + .value_name("PATH") + .help("Image paths") + .required(true) + .multiple(true) + .display_order(1) + .takes_value(true), + ).arg( + Arg::with_name("width") + .short("w") + .long("width") + .value_name("PIXELS") + .help("Draw width (def: screen width)") + .display_order(2) + .takes_value(true), + ).arg( + Arg::with_name("height") + .short("h") + .long("height") + .value_name("PIXELS") + .help("Draw height (def: screen height)") + .display_order(3) + .takes_value(true), + ).arg( + Arg::with_name("x") + .short("x") + .value_name("PIXELS") + .help("Draw X offset (def: 0)") + .display_order(4) + .takes_value(true), + ).arg( + Arg::with_name("y") + .short("y") + .value_name("PIXELS") + .help("Draw Y offset (def: 0)") + .display_order(5) + .takes_value(true), + ).arg( + Arg::with_name("count") + .short("c") + .long("count") + .alias("thread") + .alias("threads") + .value_name("COUNT") + .help("Number of concurrent threads (def: CPUs)") + .display_order(6) + .takes_value(true), + ).arg( + Arg::with_name("fps") + .short("r") + .long("fps") + .value_name("RATE") + .help("Frames per second with multiple images (def: 1)") + .display_order(7) + .takes_value(true), + ).get_matches(); // Instantiate - ArgHandler { - matches, - } + ArgHandler { matches } } /// Get the host property. pub fn host(&'a self) -> &'b str { - self.matches.value_of("HOST") + self.matches + .value_of("HOST") .expect("Please specify a host") } /// Get the thread count. pub fn count(&self) -> usize { - self.matches.value_of("count") - .map(|count| count.parse::() - .expect("Invalid count specified") - ) + self.matches + .value_of("count") + .map(|count| count.parse::().expect("Invalid count specified")) .unwrap_or(num_cpus::get()) } /// Get the image paths. pub fn image_paths(&'a self) -> Vec<&'b str> { - self.matches.values_of("image") + self.matches + .values_of("image") .expect("Please specify an image paths") .collect() } @@ -111,45 +115,36 @@ impl<'a: 'b, 'b> ArgHandler<'a> { /// Use the given default value if not set. pub fn size(&self, def: Option<(u32, u32)>) -> (u32, u32) { ( - self.matches.value_of("width") - .map(|width| width.parse() - .expect("Invalid image width") - ) - .unwrap_or( - def.expect("No screen width set or known").0 - ), - self.matches.value_of("height") - .map(|height| height.parse() - .expect("Invalid image height") - ) - .unwrap_or( - def.expect("No screen height set or known").1 - ), + self.matches + .value_of("width") + .map(|width| width.parse().expect("Invalid image width")) + .unwrap_or(def.expect("No screen width set or known").0), + self.matches + .value_of("height") + .map(|height| height.parse().expect("Invalid image height")) + .unwrap_or(def.expect("No screen height set or known").1), ) } /// Get the image offset. pub fn offset(&self) -> (u32, u32) { ( - self.matches.value_of("x") - .map(|x| x.parse::() - .expect("Invalid X offset") - ) + self.matches + .value_of("x") + .map(|x| x.parse::().expect("Invalid X offset")) .unwrap_or(0), - self.matches.value_of("y") - .map(|y| y.parse::() - .expect("Invalid Y offset") - ) + self.matches + .value_of("y") + .map(|y| y.parse::().expect("Invalid Y offset")) .unwrap_or(0), ) } /// Get the FPS. pub fn fps(&self) -> u32 { - self.matches.value_of("fps") - .map(|fps| fps.parse::() - .expect("Invalid frames per second rate") - ) + self.matches + .value_of("fps") + .map(|fps| fps.parse::().expect("Invalid frames per second rate")) .unwrap_or(DEFAULT_IMAGE_FPS) } } diff --git a/src/color.rs b/src/color.rs index 265ef4a..2a648db 100644 --- a/src/color.rs +++ b/src/color.rs @@ -9,16 +9,11 @@ pub struct Color { } impl Color { - /// Constructor. /// /// The color channels must be between 0 and 255. pub fn from(r: u8, g: u8, b: u8) -> Color { - Color { - r, - g, - b, - } + Color { r, g, b } } /// Get a hexadecimal representation of the color, diff --git a/src/image_manager.rs b/src/image_manager.rs index d5bc1e4..24c207f 100644 --- a/src/image_manager.rs +++ b/src/image_manager.rs @@ -7,8 +7,6 @@ use image::{DynamicImage, FilterType}; use pix::canvas::Canvas; - - /// A manager that manages all images to print. pub struct ImageManager { images: Vec, @@ -33,11 +31,8 @@ impl ImageManager { println!("Load and process {} image(s)...", paths.len()); // Load the images from the paths - let image_manager = ImageManager::from( - paths.iter() - .map(|path| load_image(path, &size)) - .collect() - ); + let image_manager = + ImageManager::from(paths.iter().map(|path| load_image(path, &size)).collect()); // TODO: process the image slices @@ -58,9 +53,7 @@ impl ImageManager { } // Get the image to use - let image = &mut self.images[ - self.index as usize % bound - ]; + let image = &mut self.images[self.index as usize % bound]; // Update the image on the canvas canvas.update_image(image); @@ -83,15 +76,11 @@ impl ImageManager { self.tick(canvas); // Sleep until we need to show the next image - sleep(Duration::from_millis( - (1000f32 / (fps as f32)) as u64 - )); + sleep(Duration::from_millis((1000f32 / (fps as f32)) as u64)); } } } - - /// Load the image at the given path, and size it correctly fn load_image(path: &str, size: &(u32, u32)) -> DynamicImage { // Create a path instance @@ -106,9 +95,5 @@ fn load_image(path: &str, size: &(u32, u32)) -> DynamicImage { let image = image::open(&path).unwrap(); // Resize the image to fit the screen - image.resize_exact( - size.0, - size.1, - FilterType::Gaussian, - ) + image.resize_exact(size.0, size.1, FilterType::Gaussian) } diff --git a/src/main.rs b/src/main.rs index e17151a..7194d0e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -16,8 +16,6 @@ use image_manager::ImageManager; use pix::canvas::Canvas; use pix::client::Client; - - /// Main application entrypoint. fn main() { // Parse CLI arguments @@ -33,8 +31,8 @@ fn start<'a>(arg_handler: &ArgHandler<'a>) { println!("Starting... (use CTRL+C to stop)"); // Gather facts about the host - let screen_size = gather_host_facts(&arg_handler) - .expect("Failed to gather facts about pixelflut server"); + let screen_size = + gather_host_facts(&arg_handler).expect("Failed to gather facts about pixelflut server"); // Determine the size to use let size = arg_handler.size(Some(screen_size)); @@ -48,10 +46,7 @@ fn start<'a>(arg_handler: &ArgHandler<'a>) { ); // Load the image manager - let mut image_manager = ImageManager::load( - arg_handler.image_paths(), - &size, - ); + let mut image_manager = ImageManager::load(arg_handler.image_paths(), &size); // Start the work in the image manager, to walk through the frames image_manager.work(&mut canvas, arg_handler.fps()); @@ -60,9 +55,7 @@ fn start<'a>(arg_handler: &ArgHandler<'a>) { /// Gather important facts about the host. fn gather_host_facts(arg_handler: &ArgHandler) -> Result<(u32, u32), Error> { // Set up a client, and get the screen size - let size = Client::connect( - arg_handler.host().to_string(), - )?.read_screen_size()?; + let size = Client::connect(arg_handler.host().to_string())?.read_screen_size()?; // Print status println!("Gathered screen size: {}x{}", size.0, size.1); diff --git a/src/painter/handle.rs b/src/painter/handle.rs index ddfd6f9..6568ab2 100644 --- a/src/painter/handle.rs +++ b/src/painter/handle.rs @@ -7,8 +7,6 @@ use image::DynamicImage; use rect::Rect; - - /// A handle to a painter thread. /// /// This also holds a channel to the painter thread, @@ -33,16 +31,12 @@ impl Handle { /// Push an image update. pub fn update_image(&self, full_image: &mut DynamicImage) { // Crop the image to the area - let image = full_image.crop( - self.area.x, - self.area.y, - self.area.w, - self.area.h, - ); + let image = full_image.crop(self.area.x, self.area.y, self.area.w, self.area.h); // Push a new image to the thread // TODO: return this result - self.image_sender.send(image) + self.image_sender + .send(image) .expect("Failed to send image update to painter"); } } diff --git a/src/painter/mod.rs b/src/painter/mod.rs index 72c957a..c2c077b 100644 --- a/src/painter/mod.rs +++ b/src/painter/mod.rs @@ -1,3 +1,3 @@ // Reexport modules -pub mod painter; pub mod handle; +pub mod painter; diff --git a/src/painter/painter.rs b/src/painter/painter.rs index 8450a9f..388053f 100644 --- a/src/painter/painter.rs +++ b/src/painter/painter.rs @@ -7,8 +7,6 @@ use color::Color; use pix::client::Client; use rect::Rect; - - /// A painter that paints on a pixelflut panel. pub struct Painter { client: Client, @@ -19,7 +17,12 @@ pub struct Painter { impl Painter { /// Create a new painter. - pub fn new(client: Client, area: Rect, offset: (u32, u32), image: Option) -> Painter { + pub fn new( + client: Client, + area: Rect, + offset: (u32, u32), + image: Option, + ) -> Painter { Painter { client, area, @@ -61,15 +64,11 @@ impl Painter { // Get the pixel at this location let pixel = image.get_pixel(x, y); - // Get the channels - let channels = pixel.channels(); + // Get the channels + let channels = pixel.channels(); - // Define the color - let color = Color::from( - channels[0], - channels[1], - channels[2], - ); + // Define the color + let color = Color::from(channels[0], channels[1], channels[2]); // Set the pixel self.client.write_pixel( diff --git a/src/pix/canvas.rs b/src/pix/canvas.rs index b1d1eba..b66dbfb 100644 --- a/src/pix/canvas.rs +++ b/src/pix/canvas.rs @@ -1,16 +1,14 @@ use std::sync::mpsc; -use std::sync::mpsc::{Sender, Receiver}; +use std::sync::mpsc::{Receiver, Sender}; use std::thread; use image::DynamicImage; -use painter::painter::Painter; use painter::handle::Handle; +use painter::painter::Painter; use pix::client::Client; use rect::Rect; - - /// A pixflut instance pub struct Canvas { host: String, @@ -22,12 +20,7 @@ pub struct Canvas { impl Canvas { /// Create a new pixelflut canvas. - pub fn new( - host: &str, - painter_count: usize, - size: (u32, u32), - offset: (u32, u32), - ) -> Canvas { + pub fn new(host: &str, painter_count: usize, size: (u32, u32), offset: (u32, u32)) -> Canvas { // Initialize the object let mut canvas = Canvas { host: host.to_string(), @@ -51,19 +44,14 @@ impl Canvas { fn spawn_painters(&mut self) { // Spawn some painters for i in 0..self.painter_count { - // Determine the slice width - let width = self.size.0 / (self.painter_count as u32); + // Determine the slice width + let width = self.size.0 / (self.painter_count as u32); - // Define the area to paint per thread - let painter_area = Rect::from( - (i as u32) * width, - 0, - width, - self.size.1, - ); + // Define the area to paint per thread + let painter_area = Rect::from((i as u32) * width, 0, width, self.size.1); - // Spawn the painter - self.spawn_painter(painter_area); + // Spawn the painter + self.spawn_painter(painter_area); } } @@ -76,38 +64,24 @@ impl Canvas { let offset = (self.offset.0, self.offset.1); // Create a channel to push new images - let (tx, rx): (Sender, Receiver) - = mpsc::channel(); + let (tx, rx): (Sender, Receiver) = mpsc::channel(); // Create the painter thread let thread = thread::spawn(move || { // Create a new client - let client = Client::connect(host) - .expect("failed to open stream to pixelflut"); + let client = Client::connect(host).expect("failed to open stream to pixelflut"); // Create a painter - let mut painter = Painter::new( - client, - area, - offset, - None, - ); + let mut painter = Painter::new(client, area, offset, None); // Do some work loop { - painter.work(&rx) - .expect("Painter failed to perform work"); + painter.work(&rx).expect("Painter failed to perform work"); } }); // Create a new painter handle, pust it to the list - self.painter_handles.push( - Handle::new( - thread, - area, - tx, - ) - ); + self.painter_handles.push(Handle::new(thread, area, tx)); } // Update the image that is being rendered for all painters. diff --git a/src/pix/client.rs b/src/pix/client.rs index e42ec0d..186d29a 100644 --- a/src/pix/client.rs +++ b/src/pix/client.rs @@ -1,8 +1,8 @@ extern crate bufstream; extern crate regex; -use std::io::{Error, ErrorKind}; use std::io::prelude::*; +use std::io::{Error, ErrorKind}; use std::net::TcpStream; use self::bufstream::BufStream; @@ -10,18 +10,13 @@ use self::regex::Regex; use color::Color; - - // The default buffer size for reading the client stream. // - Big enough so we don't have to expand // - Small enough to not take up to much memory const CMD_READ_BUFFER_SIZE: usize = 32; // The response format of the screen size from a pixelflut server. -const PIX_SERVER_SIZE_REGEX: &'static str = - r"^(?i)\s*SIZE\s+([[:digit:]]+)\s+([[:digit:]]+)\s*$"; - - +const PIX_SERVER_SIZE_REGEX: &'static str = r"^(?i)\s*SIZE\s+([[:digit:]]+)\s+([[:digit:]]+)\s*$"; /// A pixelflut client. /// @@ -45,19 +40,13 @@ impl Client { /// Create a new client instane from the given host, and connect to it. pub fn connect(host: String) -> Result { // Create a new stream, and instantiate the client - Ok( - Client::new( - create_stream(host)? - ) - ) + Ok(Client::new(create_stream(host)?)) } /// Write a pixel to the given stream. pub fn write_pixel(&mut self, x: u32, y: u32, color: &Color) -> Result<(), Error> { // Write the command to set a pixel - self.write_command( - format!("PX {} {} {}", x, y, color.as_hex()), - ) + self.write_command(format!("PX {} {} {}", x, y, color.as_hex())) } /// Read the size of the screen. @@ -73,12 +62,17 @@ impl Client { // Find captures in the data, return the result match re.captures(&data) { Some(matches) => Ok(( - matches[1].parse::().expect("Failed to parse screen width, received malformed data"), - matches[2].parse::().expect("Failed to parse screen height, received malformed data"), + matches[1] + .parse::() + .expect("Failed to parse screen width, received malformed data"), + matches[2] + .parse::() + .expect("Failed to parse screen height, received malformed data"), + )), + None => Err(Error::new( + ErrorKind::Other, + "Failed to parse screen size, received malformed data", )), - None => Err( - Error::new(ErrorKind::Other, "Failed to parse screen size, received malformed data") - ), } } @@ -92,7 +86,8 @@ impl Client { // TODO: only flush each 100 pixels? // TODO: make flushing configurable? // TODO: make buffer size configurable? - self.stream.flush() + self.stream + .flush() .expect("failed to flush write buffer to server"); // Everything seems to be ok @@ -124,8 +119,6 @@ impl Drop for Client { } } - - /// Create a stream to talk to the pixelflut server. /// /// The stream is returned as result. diff --git a/src/rect.rs b/src/rect.rs index 5d18a50..baadf2c 100644 --- a/src/rect.rs +++ b/src/rect.rs @@ -10,11 +10,6 @@ pub struct Rect { impl Rect { pub fn from(x: u32, y: u32, w: u32, h: u32) -> Rect { - Rect { - x, - y, - w, - h, - } + Rect { x, y, w, h } } }