Add additional anime cli commands for image types

This commit is contained in:
Luke D. Jones
2021-10-28 23:43:50 +13:00
parent a925cbaed5
commit 678505811d
8 changed files with 194 additions and 104 deletions

View File

@@ -101,4 +101,3 @@ fn do_led_notif(ledmode: &AuraEffect) -> Result<NotificationHandle, notify_rust:
fn do_charge_notif(limit: &u8) -> Result<NotificationHandle, notify_rust::error::Error> {
base_notification!(&format!("Battery charge limit changed to {}", limit))
}

View File

@@ -1,54 +1,4 @@
use gumdrop::Options;
use rog_aura::error::Error;
use std::str::FromStr;
#[derive(Copy, Clone, Debug)]
pub enum AnimeStatusValue {
On,
Off,
}
impl FromStr for AnimeStatusValue {
type Err = Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let s = s.to_lowercase();
match s.as_str() {
"on" => Ok(AnimeStatusValue::On),
"off" => Ok(AnimeStatusValue::Off),
_ => {
print!("Invalid argument, must be one of: on, off");
Err(Error::ParseAnime)
}
}
}
}
impl From<AnimeStatusValue> for bool {
fn from(value: AnimeStatusValue) -> Self {
match value {
AnimeStatusValue::On => true,
AnimeStatusValue::Off => false,
}
}
}
#[derive(Options)]
pub struct AnimeLeds {
#[options(help = "print help message")]
help: bool,
#[options(
no_long,
required,
short = "b",
meta = "",
help = "set all leds brightness value"
)]
led_brightness: u8,
}
impl AnimeLeds {
pub fn led_brightness(&self) -> u8 {
self.led_brightness
}
}
#[derive(Options)]
pub struct AnimeCommand {
@@ -56,21 +6,30 @@ pub struct AnimeCommand {
pub help: bool,
#[options(
meta = "",
help = "turn on/off the panel (accept/reject write requests)"
help = "enable/disable the panel LEDs (does not erase last image)"
)]
pub turn: Option<AnimeStatusValue>,
#[options(meta = "", help = "turn on/off the panel at boot (with Asus effect)")]
pub boot: Option<AnimeStatusValue>,
pub enable: Option<bool>,
#[options(
meta = "",
help = "enable/disable system animations (boot/sleep/shutdown)"
)]
pub boot_enable: Option<bool>,
#[options(meta = "", help = "set global AniMe brightness value")]
pub brightness: Option<f32>,
#[options(command)]
pub command: Option<AnimeActions>,
}
#[derive(Options)]
pub enum AnimeActions {
#[options(help = "change all leds brightness")]
Leds(AnimeLeds),
#[options(help = "display an image png")]
#[options(help = "display a PNG image")]
Image(AnimeImage),
#[options(help = "display a diagonal/pixel-perfect PNG")]
PixelImage(AnimeImageDiagonal),
#[options(help = "display an animated GIF")]
Gif(AnimeGif),
#[options(help = "display an animated diagonal/pixel-perfect GIF")]
PixelGif(AnimeGifDiagonal),
}
#[derive(Options)]
@@ -90,3 +49,53 @@ pub struct AnimeImage {
#[options(meta = "", default = "1.0", help = "brightness 0.0-1.0")]
pub bright: f32,
}
#[derive(Options)]
pub struct AnimeImageDiagonal {
#[options(help = "print help message")]
pub help: bool,
#[options(meta = "", help = "full path to the png to display")]
pub path: String,
#[options(meta = "", default = "1.0", help = "brightness 0.0-1.0")]
pub bright: f32,
}
#[derive(Options)]
pub struct AnimeGif {
#[options(help = "print help message")]
pub help: bool,
#[options(meta = "", help = "full path to the png to display")]
pub path: String,
#[options(meta = "", default = "1.0", help = "scale 1.0 == normal")]
pub scale: f32,
#[options(meta = "", default = "0.0", help = "x position (float)")]
pub x_pos: f32,
#[options(meta = "", default = "0.0", help = "y position (float)")]
pub y_pos: f32,
#[options(meta = "", default = "0.0", help = "the angle in radians")]
pub angle: f32,
#[options(meta = "", default = "1.0", help = "brightness 0.0-1.0")]
pub bright: f32,
#[options(
meta = "",
default = "1",
help = "how many loops to play - 0 is infinite"
)]
pub loops: u32,
}
#[derive(Options)]
pub struct AnimeGifDiagonal {
#[options(help = "print help message")]
pub help: bool,
#[options(meta = "", help = "full path to the png to display")]
pub path: String,
#[options(meta = "", default = "1.0", help = "brightness 0.0-1.0")]
pub bright: f32,
#[options(
meta = "",
default = "1",
help = "how many loops to play - 0 is infinite"
)]
pub loops: u32,
}

View File

@@ -1,14 +1,12 @@
mod anime_cli;
mod aura_cli;
mod cli_opts;
mod profiles_cli;
use std::process::Command;
use std::thread::sleep;
use std::{env::args, path::Path};
use crate::aura_cli::{LedBrightness, SetAuraBuiltin};
use crate::cli_opts::*;
use anime_cli::{AnimeActions, AnimeCommand};
use gumdrop::{Opt, Options};
use anime_cli::{AnimeActions, AnimeCommand};
use profiles_cli::{FanCurveCommand, ProfileCommand};
use rog_anime::{AnimeDataBuffer, AnimeImage, Vec2, ANIME_DATA_LEN};
use rog_anime::{AnimTime, AnimeDataBuffer, AnimeDiagonal, AnimeGif, AnimeImage, Vec2};
use rog_aura::{self, AuraEffect};
use rog_dbus::RogDbusClient;
use rog_profiles::error::ProfileError;
@@ -17,8 +15,14 @@ use rog_supported::{
AnimeSupportedFunctions, LedSupportedFunctions, PlatformProfileFunctions,
RogBiosSupportedFunctions,
};
use std::process::Command;
use std::{env::args, path::Path};
use crate::aura_cli::{LedBrightness, SetAuraBuiltin};
use crate::cli_opts::*;
mod anime_cli;
mod aura_cli;
mod cli_opts;
mod profiles_cli;
const CONFIG_ADVICE: &str = "A config file need to be removed so a new one can be generated";
@@ -167,7 +171,7 @@ fn do_parsed(
match brightness.level() {
None => {
let level = dbus.proxies().led().get_led_brightness()?;
println!("Current keyboard led brightness: {}", level.to_string());
println!("Current keyboard led brightness: {}", level);
}
Some(level) => dbus
.proxies()
@@ -206,28 +210,28 @@ fn handle_anime(
_supported: &AnimeSupportedFunctions,
cmd: &AnimeCommand,
) -> Result<(), Box<dyn std::error::Error>> {
if (cmd.command.is_none() && cmd.boot.is_none() && cmd.turn.is_none()) || cmd.help {
if (cmd.command.is_none()
&& cmd.enable.is_none()
&& cmd.boot_enable.is_none()
&& cmd.brightness.is_none())
|| cmd.help
{
println!("Missing arg or command\n\n{}", cmd.self_usage());
if let Some(lst) = cmd.self_command_list() {
println!("\n{}", lst);
}
}
if let Some(anime_turn) = cmd.turn {
dbus.proxies().anime().set_led_power(anime_turn.into())?
if let Some(anime_turn) = cmd.enable {
dbus.proxies().anime().set_on_off(anime_turn)?
}
if let Some(anime_boot) = cmd.boot {
dbus.proxies()
.anime()
.set_system_animations(anime_boot.into())?
if let Some(anime_boot) = cmd.boot_enable {
dbus.proxies().anime().set_boot_on_off(anime_boot)?
}
if let Some(bright) = cmd.brightness {
dbus.proxies().anime().set_brightness(bright as f32)?
}
if let Some(action) = cmd.command.as_ref() {
match action {
AnimeActions::Leds(anime_leds) => {
let data = AnimeDataBuffer::from_vec(
[anime_leds.led_brightness(); ANIME_DATA_LEN].to_vec(),
);
dbus.proxies().anime().write(data)?;
}
AnimeActions::Image(image) => {
if image.help_requested() || image.path.is_empty() {
println!("Missing arg or command\n\n{}", image.self_usage());
@@ -249,6 +253,82 @@ fn handle_anime(
.anime()
.write(<AnimeDataBuffer>::from(&matrix))?;
}
AnimeActions::PixelImage(image) => {
if image.help_requested() || image.path.is_empty() {
println!("Missing arg or command\n\n{}", image.self_usage());
if let Some(lst) = image.self_command_list() {
println!("\n{}", lst);
}
std::process::exit(1);
}
let matrix = AnimeDiagonal::from_png(Path::new(&image.path), None, image.bright)?;
dbus.proxies()
.anime()
.write(<AnimeDataBuffer>::from(&matrix))?;
}
AnimeActions::Gif(gif) => {
if gif.help_requested() || gif.path.is_empty() {
println!("Missing arg or command\n\n{}", gif.self_usage());
if let Some(lst) = gif.self_command_list() {
println!("\n{}", lst);
}
std::process::exit(1);
}
let matrix = AnimeGif::from_gif(
Path::new(&gif.path),
gif.scale,
gif.angle,
Vec2::new(gif.x_pos, gif.y_pos),
AnimTime::Count(1),
gif.bright,
)?;
let mut loops = gif.loops as i32;
loop {
for frame in matrix.frames() {
dbus.proxies().anime().write(frame.frame().clone())?;
sleep(frame.delay());
}
if loops >= 0 {
loops -= 1;
}
if loops == 0 {
break;
}
}
}
AnimeActions::PixelGif(gif) => {
if gif.help_requested() || gif.path.is_empty() {
println!("Missing arg or command\n\n{}", gif.self_usage());
if let Some(lst) = gif.self_command_list() {
println!("\n{}", lst);
}
std::process::exit(1);
}
let matrix = AnimeGif::from_diagonal_gif(
Path::new(&gif.path),
AnimTime::Count(1),
gif.bright,
)?;
let mut loops = gif.loops as i32;
loop {
for frame in matrix.frames() {
dbus.proxies().anime().write(frame.frame().clone())?;
sleep(frame.delay());
}
if loops >= 0 {
loops -= 1;
}
if loops == 0 {
break;
}
}
}
}
}
Ok(())

View File

@@ -353,13 +353,13 @@ impl CtrlAnime<'static> {
pub fn set_state(&mut self, on: bool) -> zbus::fdo::Result<()> {
// Operations here need to be in specific order
if on {
self.client.proxies().anime().set_led_power(on)?;
self.client.proxies().anime().set_on_off(on)?;
// Let the inner loop run
self.inner_early_return.store(false, Ordering::SeqCst);
} else {
// Must make the inner run loop return early
self.inner_early_return.store(true, Ordering::SeqCst);
self.client.proxies().anime().set_led_power(on)?;
self.client.proxies().anime().set_on_off(on)?;
}
Ok(())
}

View File

@@ -88,7 +88,7 @@ pub struct AnimeGif(Vec<AnimeFrame>, AnimTime);
impl AnimeGif {
/// Create an animation using the 74x36 ASUS gif format
#[inline]
pub fn create_diagonal_gif(
pub fn from_diagonal_gif(
file_name: &Path,
duration: AnimTime,
brightness: f32,
@@ -130,7 +130,7 @@ impl AnimeGif {
/// Create an animation using the 74x36 ASUS gif format from a png
#[inline]
pub fn create_diagonal_png(
pub fn from_diagonal_png(
file_name: &Path,
duration: AnimTime,
brightness: f32,
@@ -159,7 +159,7 @@ impl AnimeGif {
/// Create an animation using a gif of any size. This method must precompute the
/// result.
#[inline]
pub fn create_png_gif(
pub fn from_gif(
file_name: &Path,
scale: f32,
angle: f32,
@@ -231,7 +231,7 @@ impl AnimeGif {
/// will be 1 second long. If `AnimTime::Cycles` is specified for `duration` then this can
/// be considered how many seconds the image will show for.
#[inline]
pub fn create_png_static(
pub fn from_png(
file_name: &Path,
scale: f32,
angle: f32,

View File

@@ -69,7 +69,7 @@ impl ActionData {
file,
time,
brightness,
} => ActionData::Animation(AnimeGif::create_diagonal_gif(file, *time, *brightness)?),
} => ActionData::Animation(AnimeGif::from_diagonal_gif(file, *time, *brightness)?),
ActionLoader::AsusImage {
file,
time,
@@ -80,9 +80,7 @@ impl ActionData {
let data = <AnimeDataBuffer>::from(&image);
ActionData::Image(Box::new(data))
}
_ => {
ActionData::Animation(AnimeGif::create_diagonal_png(file, *time, *brightness)?)
}
_ => ActionData::Animation(AnimeGif::from_diagonal_png(file, *time, *brightness)?),
},
ActionLoader::ImageAnimation {
file,
@@ -94,7 +92,7 @@ impl ActionData {
} => {
if let Some(ext) = file.extension() {
if ext.to_string_lossy().to_lowercase() == "png" {
return Ok(ActionData::Animation(AnimeGif::create_png_static(
return Ok(ActionData::Animation(AnimeGif::from_png(
file,
*scale,
*angle,
@@ -104,7 +102,7 @@ impl ActionData {
)?));
}
}
ActionData::Animation(AnimeGif::create_png_gif(
ActionData::Animation(AnimeGif::from_gif(
file,
*scale,
*angle,
@@ -129,7 +127,7 @@ impl ActionData {
let data = <AnimeDataBuffer>::from(&image);
ActionData::Image(Box::new(data))
}
_ => ActionData::Animation(AnimeGif::create_png_static(
_ => ActionData::Animation(AnimeGif::from_png(
file,
*scale,
*angle,

View File

@@ -45,18 +45,23 @@ impl<'a> AnimeProxy<'a> {
&self.0
}
/// Set whether the AniMe will show boot, suspend, or off animations
#[inline]
pub fn set_system_animations(&self, on: bool) -> Result<()> {
self.0.set_boot_on_off(on)
}
/// Set whether the AniMe is displaying images/data
#[inline]
pub fn set_led_power(&self, on: bool) -> Result<()> {
pub fn set_on_off(&self, on: bool) -> Result<()> {
self.0.set_on_off(on)
}
/// Set the global AniMe brightness
pub fn set_brightness(&self, bright: f32) -> Result<()> {
self.0.set_brightness(bright)
}
/// Set whether the AniMe will show boot, suspend, or off animations
#[inline]
pub fn set_boot_on_off(&self, on: bool) -> Result<()> {
self.0.set_boot_on_off(on)
}
/// Writes a data stream of length. Will force system thread to exit until it is restarted
#[inline]
pub fn write(&self, input: AnimeDataBuffer) -> Result<()> {

View File

@@ -37,8 +37,7 @@ impl fmt::Display for ProfileError {
),
ProfileError::ParseFanCurvePercentOver100(value) => {
write!(f, "Invalid percentage, {} is higher than 100", value)
}
// Error::Zbus(detail) => write!(f, "Zbus error: {}", detail),
} // Error::Zbus(detail) => write!(f, "Zbus error: {}", detail),
}
}
}