Skip to content

Commit

Permalink
Refactored to (hopefully) improve performance.
Browse files Browse the repository at this point in the history
Also fixed uninterruptible sleeps at high FPSes.
  • Loading branch information
MilesBHuff committed Apr 22, 2021
1 parent 09182a4 commit 69a608a
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 41 deletions.
2 changes: 1 addition & 1 deletion application/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "ambient-kb"
version = "1.2.0"
version = "1.3.0"
license = "LAGPL3"
authors = ["Miles B Huff <MilesBHuff@Users.NoReply.Github.com>"]
description = "Calculates the average color of the display, and sets the keyboard to that color."
Expand Down
98 changes: 58 additions & 40 deletions application/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
////////////////////////////////////////////////////////////////////////////////
use std::fs;
use std::io::ErrorKind::WouldBlock;
use std::mem::drop;
use std::thread;
use std::time::Duration;

Expand All @@ -29,75 +28,98 @@ struct ArgStruct {
verbose: bool,

/// Only processes every n pixels
#[structopt(short, long, default_value = "4")] // 30 works well at 1080p. Causes flickering when not a multiple of both display axes. Causes flickering when set too high.
#[structopt(short, long, default_value = "30")] // 30 works well at 1080p. Causes flickering when not a multiple of both display axes. Causes flickering when set too high.
divisor: usize,

/// Runs this many times per second
#[structopt(short, long, default_value = "4")] // 20 is smooth. Any lower risks creating a strobing effect. Everyone's eyes are different; YMMV.
#[structopt(short, long, default_value = "18")] // 20 is smooth. Any lower risks creating a strobing effect. Everyone's eyes are different; YMMV.
fps: f32,

/// The priority to run at
#[structopt(short, long, default_value = "19")] // 19 is the highest niceness possible
niceness: usize,
niceness: i32,
}

////////////////////////////////////////////////////////////////////////////////
fn main() {

// Get input
let args = ArgStruct::from_args();
let divisor = args.divisor;
let niceness = args.niceness;
let fps = args.fps;
let verbose = args.verbose;
drop(args);
let args = ArgStruct::from_args(); // Get input

// // // // // // // // // // // // // // // // // // // //

// Colors
let color_channels = 3usize;

let color_channels: usize = 3; // Could be a u8 if it weren't used for array indexing.
let color_channels_index: usize = color_channels - 1; // Could be a u8 if it weren't used for array indexing.

let mut color_totals = [0u32, 0u32, 0u32]; // Theoretical maximum of 528,768,000 for 1920x1080; so a large integer (ie, u32) is needed.
let mut color_averages = [0u8, 0u8, 0u8];
let mut color_averages = [0u8, 0u8, 0u8 ]; // Theoretical maximum of 256 each; so we only need 8 bits.

debug_assert_eq!(color_totals.len(), color_channels);
debug_assert_eq!(color_averages.len(), color_channels);

// // // // // // // // // // // // // // // // // // // //
// Display

let display = Display::primary().expect("Failed to load primary display.");
let mut capturer = Capturer::new(display).expect("Failed to capture screenshot.");

struct Dim {
w: usize,
h: usize,
} let dim = Dim {
w: capturer.width() / divisor,
h: capturer.height() / divisor,
}
let dim = Dim {
w: capturer.width() / args.divisor,
h: capturer.height() / args.divisor,
};
let pixels = dim.w * dim.h; // Theoretical maximum of 2,073,600 for 1920x1080; so a large integer (ie, u32) is needed.

// Reduce priority
unsafe {setpriority(PRIO_PROCESS, getpid() as u32, niceness as i32);}
// // // // // // // // // // // // // // // // // // // //
// Strides

struct Stride {
h: usize,
w: usize,
x: usize,
y: usize,
s: usize,
}
let mut stride = Stride {
h: 0,
w: 4 * args.divisor,
x: 0,
y: 0,
s: 0,
};

// // // // // // // // // // // // // // // // // // // //
// Misc

let frequency = Duration::from_millis((1000.0 / args.fps).round() as u64); // Set update frequency
unsafe {setpriority(PRIO_PROCESS, getpid() as u32, args.niceness);} // Reduce priority

// Core loop
let frequency = Duration::from_millis((1000.0 / fps).round() as u64);
// drop(fps);
////////////////////////////////////////////////////////////////////////////////
loop {
thread::sleep(frequency);
//TODO: Set keyboard backlight brightness to display backlight brightness

// // // // // // // // // // // // // // // // // // // //
// Take a screenshot
match capturer.frame() {
Ok(buffer) => {

// Reset certain re-used variables
color_totals = [0, 0, 0];
color_averages = [0, 0, 0];

// Loop through the screenshot
let stride = buffer.len() / dim.h;
stride.h = buffer.len() / dim.h;
for y in 0..dim.h {
let y_stride = stride * y;
stride.y = stride.h * y;
for x in 0..dim.w {
let x_stride = x * 4 * divisor;
let xy_stride = x_stride + y_stride;
// drop(x_stride);
stride.x = stride.w * x;

// Total the pixels
stride.s = stride.x + stride.y;
for i in 0..color_channels {
color_totals[(color_channels - 1) - i] += buffer[xy_stride + i] as u32;
color_totals[color_channels_index - i] += buffer[stride.s + i] as u32;
}
}
}
Expand All @@ -109,30 +131,26 @@ fn main() {

// Convert to hex and send to acpi
let hex: String = format!("{:02x}{:02x}{:02x}", color_averages[0], color_averages[1], color_averages[2]);
// Command::new("sys76-kb").arg("set").arg("-c").arg(format!("{}", hex)).spawn().expect("Error while executing `sys76-kb`.");
fs::write("/sys/class/leds/system76_acpi::kbd_backlight/color", hex.to_string()).expect("Unable to set keyboard color.");

// Debug text
if verbose {
if args.verbose {
println!("{} {}",
format!("#{}", hex),
format!("[{:03}, {:03}, {:03}]", color_averages[0], color_averages[1], color_averages[2]),
);
}

// Pause before taking another screenshot
thread::sleep(frequency);
},

// // // // // // // // // // // // // // // // // // // //
Err(error) => {
if error.kind() != WouldBlock {
panic!("Error: {}", error);
}
},
};

// Reset re-used variables
color_totals = [0, 0, 0];
color_averages = [0, 0, 0];

// // // // // // // // // // // // // // // // // // // //

//TODO: Set keyboard backlight brightness to display backlight brightness
}
}

0 comments on commit 69a608a

Please sign in to comment.