Anime: Enabled setting builtin animations

This commit is contained in:
Luke D. Jones
2023-06-21 13:34:08 +12:00
parent a0529e0efd
commit cd5daa17d0
15 changed files with 420 additions and 247 deletions

View File

@@ -10,11 +10,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Support for GL503V LED modes - Support for GL503V LED modes
- Support the Rear Glow on some laptops - Support the Rear Glow on some laptops
- Support for GV601VI LED modes - Support for GV601VI LED modes
- Support most of M16 AniMe Matrix - Support M16 matrix display
- Custom images
- Pixel gifs
- Power options
- Builtin animations
### Changed ### Changed
- Move FX506HC to FX506H in arua DB to catch full series of this range - Move FX506HC to FX506H in arua DB to catch full series of this range
- Move FX506LH to FX506L in arua DB to catch full series of this range - Move FX506LH to FX506L in arua DB to catch full series of this range
- Rmeove notification handle tracking limit, fixes KDE issue with profile notif - Rmeove notification handle tracking limit, fixes KDE issue with profile notif
### BREAKING
- All Anime related DBUS methods/notifs are changed
## [v4.6.2] ## [v4.6.2]
- Fix rog-control-center not reopening if `startup_in_background` is set - Fix rog-control-center not reopening if `startup_in_background` is set

View File

@@ -1,20 +1,14 @@
use gumdrop::Options; use gumdrop::Options;
use rog_anime::usb::Brightness; use rog_anime::usb::{AnimAwake, AnimBooting, AnimShutdown, AnimSleeping, Brightness};
#[derive(Options)] #[derive(Options)]
pub struct AnimeCommand { pub struct AnimeCommand {
#[options(help = "print help message")] #[options(help = "print help message")]
pub help: bool, pub help: bool,
#[options( #[options(meta = "", help = "enable/disable the display")]
meta = "", pub enable_display: Option<bool>,
help = "enable/disable the panel LEDs (does not erase last image)" #[options(meta = "", help = "enable/disable the builtin run/powersave animation")]
)] pub enable_powersave_anim: Option<bool>,
pub enable: Option<bool>,
#[options(
meta = "",
help = "enable/disable system animations (boot/sleep/shutdown)"
)]
pub boot_enable: Option<bool>,
#[options( #[options(
meta = "", meta = "",
help = "set global base brightness value <Off, Low, Med, High>" help = "set global base brightness value <Off, Low, Med, High>"
@@ -38,6 +32,24 @@ pub enum AnimeActions {
Gif(AnimeGif), Gif(AnimeGif),
#[options(help = "display an animated diagonal/pixel-perfect GIF")] #[options(help = "display an animated diagonal/pixel-perfect GIF")]
PixelGif(AnimeGifDiagonal), PixelGif(AnimeGifDiagonal),
#[options(help = "change which builtin animations are shown")]
SetBuiltins(Builtins),
}
#[derive(Options)]
pub struct Builtins {
#[options(help = "print help message")]
pub help: bool,
#[options(meta = "", help = " <GlitchConstruction, StaticEmergence>")]
pub boot: AnimBooting,
#[options(meta = "", help = "<BinaryBannerScroll, RogLogoGlitch>")]
pub awake: AnimAwake,
#[options(meta = "", help = "<BannerSwipe, Starfield>")]
pub sleep: AnimSleeping,
#[options(meta = "", help = "<GlitchOut, SeeYa>")]
pub shutdown: AnimShutdown,
#[options(meta = "", help = "set/apply the animations")]
pub set: Option<bool>,
} }
#[derive(Options)] #[derive(Options)]

View File

@@ -223,8 +223,8 @@ fn handle_anime(
cmd: &AnimeCommand, cmd: &AnimeCommand,
) -> Result<(), Box<dyn std::error::Error>> { ) -> Result<(), Box<dyn std::error::Error>> {
if (cmd.command.is_none() if (cmd.command.is_none()
&& cmd.enable.is_none() && cmd.enable_display.is_none()
&& cmd.boot_enable.is_none() && cmd.enable_powersave_anim.is_none()
&& cmd.brightness.is_none() && cmd.brightness.is_none()
&& cmd.image_brightness.is_none() && cmd.image_brightness.is_none()
&& !cmd.clear) && !cmd.clear)
@@ -235,11 +235,11 @@ fn handle_anime(
println!("\n{}", lst); println!("\n{}", lst);
} }
} }
if let Some(anime_turn) = cmd.enable { if let Some(enable) = cmd.enable_display {
dbus.proxies().anime().set_awake_enabled(anime_turn)?; dbus.proxies().anime().set_enable_display(enable)?;
} }
if let Some(anime_boot) = cmd.boot_enable { if let Some(enable) = cmd.enable_powersave_anim {
dbus.proxies().anime().set_animation_enabled(anime_boot)?; dbus.proxies().anime().set_builtins_enabled(enable)?;
} }
if let Some(bright) = cmd.brightness { if let Some(bright) = cmd.brightness {
dbus.proxies().anime().set_brightness(bright)?; dbus.proxies().anime().set_brightness(bright)?;
@@ -367,6 +367,23 @@ fn handle_anime(
} }
} }
} }
AnimeActions::SetBuiltins(builtins) => {
if builtins.help_requested() || builtins.set.is_none() {
println!("\nAny unspecified args will be set to default (first shown var)\n");
println!("\n{}", builtins.self_usage());
if let Some(lst) = builtins.self_command_list() {
println!("\n{}", lst);
}
return Ok(());
}
dbus.proxies().anime().set_builtin_animations(
builtins.boot,
builtins.awake,
builtins.sleep,
builtins.shutdown,
)?;
}
} }
} }
Ok(()) Ok(())

View File

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

View File

@@ -2,78 +2,12 @@ use std::time::Duration;
use config_traits::{StdConfig, StdConfigLoad2}; use config_traits::{StdConfig, StdConfigLoad2};
use rog_anime::error::AnimeError; use rog_anime::error::AnimeError;
use rog_anime::{ActionData, ActionLoader, AnimTime, AnimeType, Fade, Vec2}; use rog_anime::usb::Brightness;
use rog_anime::{ActionData, ActionLoader, AnimTime, Animations, AnimeType, Fade, Vec2};
use serde_derive::{Deserialize, Serialize}; use serde_derive::{Deserialize, Serialize};
const CONFIG_FILE: &str = "anime.ron"; const CONFIG_FILE: &str = "anime.ron";
#[derive(Deserialize, Serialize)]
pub struct AnimeConfigV341 {
pub system: Option<ActionLoader>,
pub boot: Option<ActionLoader>,
pub suspend: Option<ActionLoader>,
pub shutdown: Option<ActionLoader>,
}
impl From<AnimeConfigV341> for AnimeConfig {
fn from(c: AnimeConfigV341) -> AnimeConfig {
AnimeConfig {
system: if let Some(ani) = c.system {
vec![ani]
} else {
vec![]
},
boot: if let Some(ani) = c.boot {
vec![ani]
} else {
vec![]
},
wake: if let Some(ani) = c.suspend {
vec![ani]
} else {
vec![]
},
shutdown: if let Some(ani) = c.shutdown.clone() {
vec![ani]
} else {
vec![]
},
sleep: if let Some(ani) = c.shutdown.clone() {
vec![ani]
} else {
vec![]
},
brightness: 1.0,
awake_enabled: true,
boot_anim_enabled: true,
}
}
}
#[derive(Deserialize, Serialize)]
pub struct AnimeConfigV352 {
pub system: Vec<ActionLoader>,
pub boot: Vec<ActionLoader>,
pub wake: Vec<ActionLoader>,
pub shutdown: Vec<ActionLoader>,
pub brightness: f32,
}
impl From<AnimeConfigV352> for AnimeConfig {
fn from(c: AnimeConfigV352) -> AnimeConfig {
AnimeConfig {
system: c.system,
boot: c.boot,
wake: c.wake,
sleep: c.shutdown.clone(),
shutdown: c.shutdown,
brightness: 1.0,
awake_enabled: true,
boot_anim_enabled: true,
}
}
}
#[derive(Deserialize, Serialize)] #[derive(Deserialize, Serialize)]
pub struct AnimeConfigV460 { pub struct AnimeConfigV460 {
pub system: Vec<ActionLoader>, pub system: Vec<ActionLoader>,
@@ -92,9 +26,32 @@ impl From<AnimeConfigV460> for AnimeConfig {
wake: c.wake, wake: c.wake,
sleep: c.sleep, sleep: c.sleep,
shutdown: c.shutdown, shutdown: c.shutdown,
brightness: 1.0, ..Default::default()
awake_enabled: true, }
boot_anim_enabled: true, }
}
#[derive(Deserialize, Serialize, Debug)]
pub struct AnimeConfigV5 {
pub system: Vec<ActionLoader>,
pub boot: Vec<ActionLoader>,
pub wake: Vec<ActionLoader>,
pub sleep: Vec<ActionLoader>,
pub shutdown: Vec<ActionLoader>,
pub brightness: f32,
pub awake_enabled: bool,
pub boot_anim_enabled: bool,
}
impl From<AnimeConfigV5> for AnimeConfig {
fn from(c: AnimeConfigV5) -> AnimeConfig {
AnimeConfig {
system: c.system,
boot: c.boot,
wake: c.wake,
sleep: c.sleep,
shutdown: c.shutdown,
..Default::default()
} }
} }
} }
@@ -156,8 +113,10 @@ pub struct AnimeConfig {
pub sleep: Vec<ActionLoader>, pub sleep: Vec<ActionLoader>,
pub shutdown: Vec<ActionLoader>, pub shutdown: Vec<ActionLoader>,
pub brightness: f32, pub brightness: f32,
pub awake_enabled: bool, pub display_enabled: bool,
pub boot_anim_enabled: bool, pub display_brightness: Brightness,
pub builtin_anims_enabled: bool,
pub builtin_anims: Animations,
} }
impl Default for AnimeConfig { impl Default for AnimeConfig {
@@ -169,8 +128,10 @@ impl Default for AnimeConfig {
sleep: Vec::new(), sleep: Vec::new(),
shutdown: Vec::new(), shutdown: Vec::new(),
brightness: 1.0, brightness: 1.0,
awake_enabled: true, display_enabled: true,
boot_anim_enabled: true, display_brightness: Brightness::Med,
builtin_anims_enabled: true,
builtin_anims: Animations::default(),
} }
} }
} }
@@ -189,7 +150,7 @@ impl StdConfig for AnimeConfig {
} }
} }
impl StdConfigLoad2<AnimeConfigV341, AnimeConfigV352> for AnimeConfig {} impl StdConfigLoad2<AnimeConfigV460, AnimeConfigV5> for AnimeConfig {}
impl AnimeConfig { impl AnimeConfig {
// fn clamp_config_brightness(mut config: &mut AnimeConfig) { // fn clamp_config_brightness(mut config: &mut AnimeConfig) {
@@ -247,8 +208,7 @@ impl AnimeConfig {
time: AnimTime::Infinite, time: AnimTime::Infinite,
}], }],
brightness: 1.0, brightness: 1.0,
awake_enabled: true, ..Default::default()
boot_anim_enabled: true,
} }
} }
} }

View File

@@ -11,7 +11,7 @@ use std::thread::sleep;
use ::zbus::export::futures_util::lock::Mutex; use ::zbus::export::futures_util::lock::Mutex;
use log::{error, info, warn}; use log::{error, info, warn};
use rog_anime::error::AnimeError; use rog_anime::error::AnimeError;
use rog_anime::usb::{get_anime_type, pkt_for_flush, pkts_for_init}; use rog_anime::usb::{get_anime_type, pkt_flush, pkt_set_enable_powersave_anim, pkts_for_init};
use rog_anime::{ActionData, AnimeDataBuffer, AnimePacketType, AnimeType}; use rog_anime::{ActionData, AnimeDataBuffer, AnimePacketType, AnimeType};
use rog_platform::hid_raw::HidRaw; use rog_platform::hid_raw::HidRaw;
use rog_platform::supported::AnimeSupportedFunctions; use rog_platform::supported::AnimeSupportedFunctions;
@@ -72,12 +72,21 @@ impl CtrlAnime {
/// ///
/// Because this also writes to the usb device, other write tries (display /// Because this also writes to the usb device, other write tries (display
/// only) *must* get the mutex lock and set the `thread_exit` atomic. /// only) *must* get the mutex lock and set the `thread_exit` atomic.
fn run_thread(inner: Arc<Mutex<CtrlAnime>>, actions: Vec<ActionData>, mut once: bool) { async fn run_thread(inner: Arc<Mutex<CtrlAnime>>, actions: Vec<ActionData>, mut once: bool) {
if actions.is_empty() { if actions.is_empty() {
warn!("AniMe system actions was empty"); warn!("AniMe system actions was empty");
return; return;
} }
if let Some(lock) = inner.try_lock() {
lock.node
.write_bytes(&pkt_set_enable_powersave_anim(false))
.map_err(|err| {
warn!("rog_anime::run_animation:callback {}", err);
})
.ok();
}
// Loop rules: // Loop rules:
// - Lock the mutex **only when required**. That is, the lock must be held for // - Lock the mutex **only when required**. That is, the lock must be held for
// the shortest duration possible. // the shortest duration possible.
@@ -211,7 +220,7 @@ impl CtrlAnime {
for row in &data { for row in &data {
self.node.write_bytes(row)?; self.node.write_bytes(row)?;
} }
self.node.write_bytes(&pkt_for_flush())?; self.node.write_bytes(&pkt_flush())?;
Ok(()) Ok(())
} }

View File

@@ -5,10 +5,10 @@ use async_trait::async_trait;
use config_traits::StdConfig; use config_traits::StdConfig;
use log::warn; use log::warn;
use rog_anime::usb::{ use rog_anime::usb::{
pkt_for_enable_animation, pkt_for_set_awake_enabled, pkt_for_set_boot, pkt_for_set_brightness, pkt_set_brightness, pkt_set_builtin_animations, pkt_set_enable_display,
Brightness, pkt_set_enable_powersave_anim, AnimAwake, AnimBooting, AnimShutdown, AnimSleeping, Brightness,
}; };
use rog_anime::{AnimeDataBuffer, AnimePowerStates}; use rog_anime::{AnimeDataBuffer, DeviceState};
use zbus::export::futures_util::lock::Mutex; use zbus::export::futures_util::lock::Mutex;
use zbus::{dbus_interface, Connection, SignalContext}; use zbus::{dbus_interface, Connection, SignalContext};
@@ -65,83 +65,125 @@ impl CtrlAnimeZbus {
#[zbus(signal_context)] ctxt: SignalContext<'_>, #[zbus(signal_context)] ctxt: SignalContext<'_>,
brightness: Brightness, brightness: Brightness,
) { ) {
let lock = self.0.lock().await; let mut lock = self.0.lock().await;
lock.node lock.node
.write_bytes(&pkt_for_set_brightness(brightness)) .write_bytes(&pkt_set_brightness(brightness))
.map_err(|err| { .map_err(|err| {
warn!("rog_anime::run_animation:callback {}", err); warn!("rog_anime::run_animation:callback {}", err);
}) })
.ok(); .ok();
// lock.config.write(); lock.config.display_brightness = brightness;
lock.config.write();
Self::notify_power_states( Self::notify_device_state(
&ctxt, &ctxt,
AnimePowerStates { DeviceState {
brightness: lock.config.brightness.floor() as u8, display_enabled: lock.config.display_enabled,
enabled: lock.config.awake_enabled, display_brightness: lock.config.display_brightness,
boot_anim_enabled: lock.config.boot_anim_enabled, builtin_anims_enabled: lock.config.builtin_anims_enabled,
builtin_anims: lock.config.builtin_anims,
}, },
) )
.await .await
.ok(); .ok();
} }
/// Set whether the AniMe is displaying images/data /// Enable the builtin animations or not
async fn set_awake_enabled( async fn set_builtins_enabled(
&self, &self,
#[zbus(signal_context)] ctxt: SignalContext<'_>, #[zbus(signal_context)] ctxt: SignalContext<'_>,
status: bool, enabled: bool,
) { ) {
let mut lock = self.0.lock().await; let mut lock = self.0.lock().await;
lock.node lock.node
.write_bytes(&pkt_for_set_awake_enabled(status)) .write_bytes(&pkt_set_enable_powersave_anim(enabled))
.map_err(|err| { .map_err(|err| {
warn!("rog_anime::run_animation:callback {}", err); warn!("rog_anime::run_animation:callback {}", err);
}) })
.ok(); .ok();
lock.config.awake_enabled = status; lock.config.builtin_anims_enabled = enabled;
lock.config.write(); lock.config.write();
if enabled {
lock.thread_exit.store(true, Ordering::Release);
}
Self::notify_power_states( Self::notify_device_state(
&ctxt, &ctxt,
AnimePowerStates { DeviceState {
brightness: lock.config.brightness.floor() as u8, display_enabled: lock.config.display_enabled,
enabled: lock.config.awake_enabled, display_brightness: lock.config.display_brightness,
boot_anim_enabled: lock.config.boot_anim_enabled, builtin_anims_enabled: lock.config.builtin_anims_enabled,
builtin_anims: lock.config.builtin_anims,
}, },
) )
.await .await
.ok(); .ok();
} }
/// Set whether the AniMe will show boot, suspend, or off animations /// Set which builtin animation is used for each stage
async fn set_animation_enabled( async fn set_builtin_animations(
&self, &self,
#[zbus(signal_context)] ctxt: SignalContext<'_>, #[zbus(signal_context)] ctxt: SignalContext<'_>,
on: bool, boot: AnimBooting,
awake: AnimAwake,
sleep: AnimSleeping,
shutdown: AnimShutdown,
) { ) {
let mut lock = self.0.lock().await; let mut lock = self.0.lock().await;
lock.node lock.node
.write_bytes(&pkt_for_set_boot(on)) .write_bytes(&pkt_set_enable_powersave_anim(true))
.map_err(|err| { .map_err(|err| {
warn!("rog_anime::run_animation:callback {}", err); warn!("rog_anime::run_animation:callback {}", err);
}) })
.ok(); .ok();
lock.node lock.node
.write_bytes(&pkt_for_enable_animation()) .write_bytes(&pkt_set_builtin_animations(boot, awake, sleep, shutdown))
.map_err(|err| { .map_err(|err| {
warn!("rog_anime::run_animation:callback {}", err); warn!("rog_anime::run_animation:callback {}", err);
}) })
.ok(); .ok();
lock.config.boot_anim_enabled = on; lock.config.builtin_anims.boot = boot;
lock.config.builtin_anims.sleep = sleep;
lock.config.builtin_anims.awake = awake;
lock.config.builtin_anims.shutdown = shutdown;
lock.config.write(); lock.config.write();
Self::notify_power_states( Self::notify_device_state(
&ctxt, &ctxt,
AnimePowerStates { DeviceState {
brightness: lock.config.brightness.floor() as u8, display_enabled: lock.config.display_enabled,
enabled: lock.config.awake_enabled, display_brightness: lock.config.display_brightness,
boot_anim_enabled: lock.config.boot_anim_enabled, builtin_anims_enabled: lock.config.builtin_anims_enabled,
builtin_anims: lock.config.builtin_anims,
},
)
.await
.ok();
}
/// Set whether the AniMe is enabled at all
async fn set_enable_display(
&self,
#[zbus(signal_context)] ctxt: SignalContext<'_>,
enabled: bool,
) {
let mut lock = self.0.lock().await;
lock.node
.write_bytes(&pkt_set_enable_display(enabled))
.map_err(|err| {
warn!("rog_anime::run_animation:callback {}", err);
})
.ok();
lock.config.display_enabled = enabled;
lock.config.write();
Self::notify_device_state(
&ctxt,
DeviceState {
display_enabled: lock.config.display_enabled,
display_brightness: lock.config.display_brightness,
builtin_anims_enabled: lock.config.builtin_anims_enabled,
builtin_anims: lock.config.builtin_anims,
}, },
) )
.await .await
@@ -154,31 +196,26 @@ impl CtrlAnimeZbus {
if start { if start {
let lock = self.0.lock().await; let lock = self.0.lock().await;
lock.thread_exit.store(true, Ordering::SeqCst); lock.thread_exit.store(true, Ordering::SeqCst);
CtrlAnime::run_thread(self.0.clone(), lock.cache.system.clone(), false); CtrlAnime::run_thread(self.0.clone(), lock.cache.system.clone(), false).await;
} }
} }
/// Get status of if the AniMe LEDs are on/displaying while system is awake /// Get the device state as stored by asusd
#[dbus_interface(property)] // #[dbus_interface(property)]
async fn awake_enabled(&self) -> bool { async fn device_state(&self) -> DeviceState {
let lock = self.0.lock().await; let lock = self.0.lock().await;
lock.config.awake_enabled DeviceState {
} display_enabled: lock.config.display_enabled,
display_brightness: lock.config.display_brightness,
/// Get the status of if factory system-status animations are enabled builtin_anims_enabled: lock.config.builtin_anims_enabled,
#[dbus_interface(property)] builtin_anims: lock.config.builtin_anims,
async fn animation_enabled(&self) -> bool { }
let lock = self.0.lock().await;
lock.config.boot_anim_enabled
} }
/// Notify listeners of the status of AniMe LED power and factory /// Notify listeners of the status of AniMe LED power and factory
/// system-status animations /// system-status animations
#[dbus_interface(signal)] #[dbus_interface(signal)]
async fn notify_power_states( async fn notify_device_state(ctxt: &SignalContext<'_>, data: DeviceState) -> zbus::Result<()>;
ctxt: &SignalContext<'_>,
data: AnimePowerStates,
) -> zbus::Result<()>;
} }
#[async_trait] #[async_trait]
@@ -198,7 +235,7 @@ impl crate::CtrlTask for CtrlAnimeZbus {
let inner1 = inner1.clone(); let inner1 = inner1.clone();
async move { async move {
let lock = inner1.lock().await; let lock = inner1.lock().await;
CtrlAnime::run_thread(inner1.clone(), lock.cache.sleep.clone(), true); CtrlAnime::run_thread(inner1.clone(), lock.cache.sleep.clone(), true).await;
} }
}, },
move || { move || {
@@ -206,7 +243,7 @@ impl crate::CtrlTask for CtrlAnimeZbus {
let inner2 = inner2.clone(); let inner2 = inner2.clone();
async move { async move {
let lock = inner2.lock().await; let lock = inner2.lock().await;
CtrlAnime::run_thread(inner2.clone(), lock.cache.wake.clone(), true); CtrlAnime::run_thread(inner2.clone(), lock.cache.wake.clone(), true).await;
} }
}, },
move || { move || {
@@ -214,7 +251,7 @@ impl crate::CtrlTask for CtrlAnimeZbus {
let inner3 = inner3.clone(); let inner3 = inner3.clone();
async move { async move {
let lock = inner3.lock().await; let lock = inner3.lock().await;
CtrlAnime::run_thread(inner3.clone(), lock.cache.shutdown.clone(), true); CtrlAnime::run_thread(inner3.clone(), lock.cache.shutdown.clone(), true).await;
} }
}, },
move || { move || {
@@ -222,7 +259,7 @@ impl crate::CtrlTask for CtrlAnimeZbus {
let inner4 = inner4.clone(); let inner4 = inner4.clone();
async move { async move {
let lock = inner4.lock().await; let lock = inner4.lock().await;
CtrlAnime::run_thread(inner4.clone(), lock.cache.boot.clone(), true); CtrlAnime::run_thread(inner4.clone(), lock.cache.boot.clone(), true).await;
} }
}, },
) )
@@ -236,14 +273,26 @@ impl crate::CtrlTask for CtrlAnimeZbus {
impl crate::Reloadable for CtrlAnimeZbus { impl crate::Reloadable for CtrlAnimeZbus {
async fn reload(&mut self) -> Result<(), RogError> { async fn reload(&mut self) -> Result<(), RogError> {
if let Some(lock) = self.0.try_lock() { if let Some(lock) = self.0.try_lock() {
// TODO: restore new settings let anim = &lock.config.builtin_anims;
// lock.node
// .write_bytes(&pkt_for_set_brightness(lock.config.awake_enabled))?;
lock.node lock.node
.write_bytes(&pkt_for_set_boot(lock.config.boot_anim_enabled))?; .write_bytes(&pkt_set_enable_display(lock.config.display_enabled))?;
lock.node.write_bytes(&pkt_set_enable_powersave_anim(
lock.config.builtin_anims_enabled,
))?;
lock.node.write_bytes(&pkt_set_builtin_animations(
anim.boot,
anim.awake,
anim.sleep,
anim.shutdown,
))?;
if lock.config.builtin_anims_enabled && !lock.cache.boot.is_empty() {
lock.node
.write_bytes(&pkt_set_enable_powersave_anim(false))
.ok();
}
let action = lock.cache.boot.clone(); let action = lock.cache.boot.clone();
CtrlAnime::run_thread(self.0.clone(), action, true); CtrlAnime::run_thread(self.0.clone(), action, true).await;
} }
Ok(()) Ok(())
} }

View File

@@ -8,6 +8,7 @@ use serde_derive::{Deserialize, Serialize};
use zbus::zvariant::Type; use zbus::zvariant::Type;
use crate::error::{AnimeError, Result}; use crate::error::{AnimeError, Result};
use crate::usb::{AnimAwake, AnimBooting, AnimShutdown, AnimSleeping, Brightness};
use crate::{AnimTime, AnimeGif}; use crate::{AnimTime, AnimeGif};
/// The first 7 bytes of a USB packet are accounted for by `USB_PREFIX1` and /// The first 7 bytes of a USB packet are accounted for by `USB_PREFIX1` and
@@ -25,12 +26,22 @@ pub const USB_PREFIX2: [u8; 7] = [0x5e, 0xc0, 0x02, 0x74, 0x02, 0x73, 0x02];
/// Third packet is for GA402 matrix /// Third packet is for GA402 matrix
pub const USB_PREFIX3: [u8; 7] = [0x5e, 0xc0, 0x02, 0xe7, 0x04, 0x73, 0x02]; pub const USB_PREFIX3: [u8; 7] = [0x5e, 0xc0, 0x02, 0xe7, 0x04, 0x73, 0x02];
#[cfg_attr(feature = "dbus", derive(Type))]
#[derive(Default, Deserialize, PartialEq, Eq, Clone, Copy, Serialize, Debug)]
pub struct Animations {
pub boot: AnimBooting,
pub awake: AnimAwake,
pub sleep: AnimSleeping,
pub shutdown: AnimShutdown,
}
#[cfg_attr(feature = "dbus", derive(Type))] #[cfg_attr(feature = "dbus", derive(Type))]
#[derive(Debug, PartialEq, Eq, Copy, Clone, Deserialize, Serialize)] #[derive(Debug, PartialEq, Eq, Copy, Clone, Deserialize, Serialize)]
pub struct AnimePowerStates { pub struct DeviceState {
pub brightness: u8, pub display_enabled: bool,
pub enabled: bool, pub display_brightness: Brightness,
pub boot_anim_enabled: bool, pub builtin_anims_enabled: bool,
pub builtin_anims: Animations,
} }
#[cfg_attr(feature = "dbus", derive(Type))] #[cfg_attr(feature = "dbus", derive(Type))]

View File

@@ -24,12 +24,14 @@ pub enum AnimeError {
DataBufferLength, DataBufferLength,
PixelGifWidth(usize), PixelGifWidth(usize),
PixelGifHeight(usize), PixelGifHeight(usize),
ParseError(String),
} }
impl fmt::Display for AnimeError { impl fmt::Display for AnimeError {
#[inline] #[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self { match self {
AnimeError::ParseError(e) => write!(f, "Could not parse {e}"),
AnimeError::NoFrames => write!(f, "No frames in PNG"), AnimeError::NoFrames => write!(f, "No frames in PNG"),
AnimeError::Io(e) => write!(f, "Could not open: {}", e), AnimeError::Io(e) => write!(f, "Could not open: {}", e),
AnimeError::Png(e) => write!(f, "PNG error: {}", e), AnimeError::Png(e) => write!(f, "PNG error: {}", e),

View File

@@ -23,11 +23,12 @@ pub const VENDOR_ID: u16 = 0x0b05;
pub const PROD_ID: u16 = 0x193b; pub const PROD_ID: u16 = 0x193b;
#[cfg_attr(feature = "dbus", derive(Type))] #[cfg_attr(feature = "dbus", derive(Type))]
#[derive(Debug, PartialEq, Eq, Copy, Clone, Deserialize, Serialize)] #[derive(Debug, Default, PartialEq, Eq, Copy, Clone, Deserialize, Serialize)]
/// Base LED brightness of the display /// Base LED brightness of the display
pub enum Brightness { pub enum Brightness {
Off, Off,
Low, Low,
#[default]
Med, Med,
High, High,
} }
@@ -46,6 +47,97 @@ impl FromStr for Brightness {
} }
} }
impl From<u8> for Brightness {
fn from(v: u8) -> Brightness {
match v {
0 => Brightness::Off,
2 => Brightness::Low,
3 => Brightness::High,
_ => Brightness::Med,
}
}
}
#[cfg_attr(feature = "dbus", derive(Type))]
#[derive(Debug, Default, PartialEq, Eq, Copy, Clone, Deserialize, Serialize)]
pub enum AnimBooting {
#[default]
GlitchConstruction,
StaticEmergence,
}
impl FromStr for AnimBooting {
type Err = AnimeError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"GlitchConstruction" => Ok(Self::GlitchConstruction),
"StaticEmergence" => Ok(Self::StaticEmergence),
_ => Err(AnimeError::ParseError(s.to_owned())),
}
}
}
#[cfg_attr(feature = "dbus", derive(Type))]
#[derive(Debug, Default, PartialEq, Eq, Copy, Clone, Deserialize, Serialize)]
pub enum AnimAwake {
#[default]
BinaryBannerScroll,
RogLogoGlitch,
}
impl FromStr for AnimAwake {
type Err = AnimeError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"BinaryBannerScroll" => Ok(Self::BinaryBannerScroll),
"RogLogoGlitch" => Ok(Self::RogLogoGlitch),
_ => Err(AnimeError::ParseError(s.to_owned())),
}
}
}
#[cfg_attr(feature = "dbus", derive(Type))]
#[derive(Debug, Default, PartialEq, Eq, Copy, Clone, Deserialize, Serialize)]
pub enum AnimSleeping {
#[default]
BannerSwipe,
Starfield,
}
impl FromStr for AnimSleeping {
type Err = AnimeError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"BannerSwipe" => Ok(Self::BannerSwipe),
"Starfield" => Ok(Self::Starfield),
_ => Err(AnimeError::ParseError(s.to_owned())),
}
}
}
#[cfg_attr(feature = "dbus", derive(Type))]
#[derive(Debug, Default, PartialEq, Eq, Copy, Clone, Deserialize, Serialize)]
pub enum AnimShutdown {
#[default]
GlitchOut,
SeeYa,
}
impl FromStr for AnimShutdown {
type Err = AnimeError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"GlitchOut" => Ok(Self::GlitchOut),
"SeeYa" => Ok(Self::SeeYa),
_ => Err(AnimeError::ParseError(s.to_owned())),
}
}
}
/// `get_anime_type` is very broad, matching on part of the laptop board name /// `get_anime_type` is very broad, matching on part of the laptop board name
/// only. For this reason `find_node()` must be used also to verify if the USB /// only. For this reason `find_node()` must be used also to verify if the USB
/// device is available. /// device is available.
@@ -89,7 +181,7 @@ pub const fn pkts_for_init() -> [[u8; PACKET_SIZE]; 2] {
/// Should be written to the device after writing the two main data packets that /// Should be written to the device after writing the two main data packets that
/// make up the display data packet /// make up the display data packet
#[inline] #[inline]
pub const fn pkt_for_flush() -> [u8; PACKET_SIZE] { pub const fn pkt_flush() -> [u8; PACKET_SIZE] {
let mut pkt = [0; PACKET_SIZE]; let mut pkt = [0; PACKET_SIZE];
pkt[0] = DEV_PAGE; pkt[0] = DEV_PAGE;
pkt[1] = 0xc0; pkt[1] = 0xc0;
@@ -97,23 +189,10 @@ pub const fn pkt_for_flush() -> [u8; PACKET_SIZE] {
pkt pkt
} }
/// Get the packet required for setting the device to on, on boot. Requires /// Packet for setting the brightness (0-3). Requires
/// `pkt_for_apply()` to be written after. /// `pkt_for_apply()` to be written after.
#[inline] #[inline]
pub const fn pkt_for_set_boot(status: bool) -> [u8; PACKET_SIZE] { pub const fn pkt_set_brightness(brightness: Brightness) -> [u8; PACKET_SIZE] {
let mut pkt = [0; PACKET_SIZE];
pkt[0] = DEV_PAGE;
pkt[1] = 0xc3;
pkt[2] = 0x01;
pkt[3] = if status { 0x00 } else { 0x80 };
pkt
}
/// Get the packet required for setting the device to on. Requires
/// `pkt_for_apply()` to be written after.
// TODO: change the users of this method
#[inline]
pub const fn pkt_for_set_brightness(brightness: Brightness) -> [u8; PACKET_SIZE] {
let mut pkt = [0; PACKET_SIZE]; let mut pkt = [0; PACKET_SIZE];
pkt[0] = DEV_PAGE; pkt[0] = DEV_PAGE;
pkt[1] = 0xc0; pkt[1] = 0xc0;
@@ -122,23 +201,42 @@ pub const fn pkt_for_set_brightness(brightness: Brightness) -> [u8; PACKET_SIZE]
pkt pkt
} }
/// Enable the display?
#[inline] #[inline]
pub const fn pkt_for_set_awake_enabled(enable: bool) -> [u8; PACKET_SIZE] { pub const fn pkt_set_enable_display(status: bool) -> [u8; PACKET_SIZE] {
let mut pkt = [0; PACKET_SIZE]; let mut pkt = [0; PACKET_SIZE];
pkt[0] = DEV_PAGE; pkt[0] = DEV_PAGE;
pkt[1] = 0xc3; pkt[1] = 0xc3;
pkt[2] = 0x01; pkt[2] = 0x01;
pkt[3] = if !enable { 0x80 } else { 0x00 }; pkt[3] = if status { 0x00 } else { 0x80 };
pkt pkt
} }
/// Packet required to apply a device setting /// Enable builtin animations?
#[inline] #[inline]
pub const fn pkt_for_enable_animation() -> [u8; PACKET_SIZE] { pub const fn pkt_set_enable_powersave_anim(status: bool) -> [u8; PACKET_SIZE] {
let mut pkt = [0; PACKET_SIZE]; let mut pkt = [0; PACKET_SIZE];
pkt[0] = DEV_PAGE; pkt[0] = DEV_PAGE;
pkt[1] = 0xc4; pkt[1] = 0xc4;
pkt[2] = 0x01; pkt[2] = 0x01;
pkt[3] = 0x80; pkt[3] = if status { 0x00 } else { 0x80 };
pkt
}
/// Set which animations are shown for each stage
#[inline]
pub const fn pkt_set_builtin_animations(
boot: AnimBooting,
awake: AnimAwake,
sleep: AnimSleeping,
shutdown: AnimShutdown,
) -> [u8; PACKET_SIZE] {
let mut pkt = [0; PACKET_SIZE];
pkt[0] = DEV_PAGE;
pkt[1] = 0xc5;
pkt[2] = (awake as u8)
| ((sleep as u8) << 0x01)
| ((shutdown as u8) << 0x02)
| ((boot as u8) << 0x03);
pkt pkt
} }

View File

@@ -5,6 +5,8 @@ use std::time::SystemTime;
use egui::Vec2; use egui::Vec2;
use log::error; use log::error;
use rog_anime::usb::Brightness;
use rog_anime::Animations;
use rog_aura::layouts::KeyLayout; use rog_aura::layouts::KeyLayout;
use rog_aura::usb::AuraPowerDev; use rog_aura::usb::AuraPowerDev;
use rog_aura::{AuraEffect, AuraModeNum}; use rog_aura::{AuraEffect, AuraModeNum};
@@ -194,29 +196,25 @@ impl AuraState {
#[derive(Clone, Debug, Default)] #[derive(Clone, Debug, Default)]
pub struct AnimeState { pub struct AnimeState {
pub bright: u8, pub display_enabled: bool,
pub boot: bool, pub display_brightness: Brightness,
pub awake: bool, pub builtin_anims_enabled: bool,
pub sleep: bool, pub builtin_anims: Animations,
} }
impl AnimeState { impl AnimeState {
pub fn new(supported: &SupportedFunctions, dbus: &RogDbusClientBlocking<'_>) -> Result<Self> { pub fn new(supported: &SupportedFunctions, dbus: &RogDbusClientBlocking<'_>) -> Result<Self> {
Ok(Self { if supported.anime_ctrl.0 {
boot: if supported.anime_ctrl.0 { let device_state = dbus.proxies().anime().device_state()?;
dbus.proxies().anime().animation_enabled()? Ok(Self {
} else { display_enabled: device_state.display_enabled,
false display_brightness: device_state.display_brightness,
}, builtin_anims_enabled: device_state.builtin_anims_enabled,
awake: if supported.anime_ctrl.0 { builtin_anims: device_state.builtin_anims,
dbus.proxies().anime().awake_enabled()? })
} else { } else {
false Ok(Default::default())
}, }
// TODO:
sleep: false,
bright: 200,
})
} }
} }
@@ -429,12 +427,7 @@ impl Default for SystemState {
wave_green: Default::default(), wave_green: Default::default(),
wave_blue: Default::default(), wave_blue: Default::default(),
}, },
anime: AnimeState { anime: AnimeState::default(),
bright: Default::default(),
boot: Default::default(),
awake: Default::default(),
sleep: Default::default(),
},
profiles: ProfilesState { profiles: ProfilesState {
list: Default::default(), list: Default::default(),
current: Default::default(), current: Default::default(),

View File

@@ -269,7 +269,7 @@ pub fn start_notifications(
e e
}) })
.unwrap(); .unwrap();
if let Ok(p) = proxy.receive_power_states().await { if let Ok(p) = proxy.receive_device_state().await {
info!("Started zbus signal thread: receive_power_states"); info!("Started zbus signal thread: receive_power_states");
p.for_each(|_| { p.for_each(|_| {
if let Ok(_lock) = page_states1.lock() { if let Ok(_lock) = page_states1.lock() {

View File

@@ -1,4 +1,5 @@
use egui::{RichText, Ui}; use egui::{RichText, Ui};
use rog_anime::usb::Brightness;
use rog_platform::supported::SupportedFunctions; use rog_platform::supported::SupportedFunctions;
use crate::system_state::SystemState; use crate::system_state::SystemState;
@@ -7,42 +8,50 @@ pub fn anime_power_group(_supported: &SupportedFunctions, states: &mut SystemSta
ui.heading("AniMe Matrix Settings"); ui.heading("AniMe Matrix Settings");
ui.label("Options are incomplete. Awake + Boot should work"); ui.label("Options are incomplete. Awake + Boot should work");
let mut changed = false; let mut brightness = states.anime.display_brightness as u8;
ui.horizontal_wrapped(|ui| { ui.horizontal_wrapped(|ui| {
ui.vertical(|ui| { ui.vertical(|ui| {
let h = 16.0; let h = 16.0;
ui.set_row_height(22.0); ui.set_row_height(22.0);
ui.horizontal_wrapped(|ui| { ui.horizontal_wrapped(|ui| {
ui.label(RichText::new("Brightness").size(h)); ui.label(RichText::new("Display brightness").size(h));
}); });
ui.horizontal_wrapped(|ui| { ui.horizontal_wrapped(|ui| {
ui.label(RichText::new("Boot").size(h)); ui.label(RichText::new("Display enabled").size(h));
}); });
ui.horizontal_wrapped(|ui| { ui.horizontal_wrapped(|ui| {
ui.label(RichText::new("Awake").size(h)); ui.label(RichText::new("Animations enabled").size(h));
});
ui.horizontal_wrapped(|ui| {
ui.label(RichText::new("Sleep").size(h));
}); });
// ui.horizontal_wrapped(|ui| {
// ui.label(RichText::new("Sleep").size(h));
// });
}); });
ui.vertical(|ui| { ui.vertical(|ui| {
ui.set_row_height(22.0); ui.set_row_height(22.0);
ui.horizontal_wrapped(|ui| {
if ui.add(egui::Slider::new(&mut brightness, 0..=3)).changed() {
states
.asus_dbus
.proxies()
.anime()
.set_brightness(Brightness::from(brightness))
.map_err(|err| {
states.error = Some(err.to_string());
})
.ok();
}
});
ui.horizontal_wrapped(|ui| { ui.horizontal_wrapped(|ui| {
if ui if ui
.add(egui::Slider::new(&mut states.anime.bright, 0..=254)) .checkbox(&mut states.anime.display_enabled, "Enable")
.changed() .changed()
{ {
changed = true;
}
});
ui.horizontal_wrapped(|ui| {
if ui.checkbox(&mut states.anime.boot, "Enable").changed() {
states states
.asus_dbus .asus_dbus
.proxies() .proxies()
.anime() .anime()
.set_animation_enabled(states.anime.boot) .set_enable_display(states.anime.display_enabled)
.map_err(|err| { .map_err(|err| {
states.error = Some(err.to_string()); states.error = Some(err.to_string());
}) })
@@ -50,23 +59,26 @@ pub fn anime_power_group(_supported: &SupportedFunctions, states: &mut SystemSta
} }
}); });
ui.horizontal_wrapped(|ui| { ui.horizontal_wrapped(|ui| {
if ui.checkbox(&mut states.anime.awake, "Enable").changed() { if ui
.checkbox(&mut states.anime.builtin_anims_enabled, "Enable")
.changed()
{
states states
.asus_dbus .asus_dbus
.proxies() .proxies()
.anime() .anime()
.set_awake_enabled(states.anime.awake) .set_builtins_enabled(states.anime.builtin_anims_enabled)
.map_err(|err| { .map_err(|err| {
states.error = Some(err.to_string()); states.error = Some(err.to_string());
}) })
.ok(); .ok();
} }
}); });
ui.horizontal_wrapped(|ui| { // ui.horizontal_wrapped(|ui| {
if ui.checkbox(&mut states.anime.sleep, "Enable").changed() { // if ui.checkbox(&mut states.anime.sleep, "Enable").changed() {
changed = true; // changed = true;
} // }
}); // });
}); });
}); });
} }

View File

@@ -10,7 +10,7 @@ description = "dbus interface methods for asusctl"
edition = "2021" edition = "2021"
[dependencies] [dependencies]
rog_anime = { path = "../rog-anime" } rog_anime = { path = "../rog-anime", features = ["dbus"] }
rog_aura = { path = "../rog-aura" } rog_aura = { path = "../rog-aura" }
rog_profiles = { path = "../rog-profiles" } rog_profiles = { path = "../rog-profiles" }
rog_platform = { path = "../rog-platform" } rog_platform = { path = "../rog-platform" }

View File

@@ -1,5 +1,5 @@
use rog_anime::usb::Brightness; use rog_anime::usb::{AnimAwake, AnimBooting, AnimShutdown, AnimSleeping, Brightness};
use rog_anime::{AnimeDataBuffer, AnimePowerStates}; use rog_anime::{AnimeDataBuffer, DeviceState as AnimeDeviceState};
use zbus::dbus_proxy; use zbus::dbus_proxy;
#[dbus_proxy( #[dbus_proxy(
@@ -7,32 +7,36 @@ use zbus::dbus_proxy;
default_path = "/org/asuslinux/Anime" default_path = "/org/asuslinux/Anime"
)] )]
trait Anime { trait Anime {
/// Set whether the AniMe will show boot, suspend, or off animations /// Set the global (image) brightness
fn set_animation_enabled(&self, status: bool) -> zbus::Result<()>; fn set_image_brightness(&self, bright: f32) -> zbus::Result<()>;
/// Set the global base brightness /// Set the global base brightness
fn set_brightness(&self, bright: Brightness) -> zbus::Result<()>; fn set_brightness(&self, bright: Brightness) -> zbus::Result<()>;
/// Set the global (image) brightness /// Set whether the AniMe will show boot, suspend, or off animations
fn set_image_brightness(&self, bright: f32) -> zbus::Result<()>; fn set_builtins_enabled(&self, enabled: bool) -> zbus::Result<()>;
/// Set which builtin animation is used for each stage
fn set_builtin_animations(
&self,
boot: AnimBooting,
awake: AnimAwake,
sleep: AnimSleeping,
shutdown: AnimShutdown,
) -> zbus::Result<()>;
/// Set whether the AniMe is displaying images/data /// Set whether the AniMe is displaying images/data
fn set_awake_enabled(&self, status: bool) -> zbus::Result<()>; fn set_enable_display(&self, status: bool) -> zbus::Result<()>;
/// Writes a data stream of length. Will force system thread to exit until /// Writes a data stream of length. Will force system thread to exit until
/// it is restarted /// it is restarted
fn write(&self, input: AnimeDataBuffer) -> zbus::Result<()>; fn write(&self, input: AnimeDataBuffer) -> zbus::Result<()>;
/// Get status of if the AniMe LEDs are on // #[dbus_proxy(property)]
#[dbus_proxy(property)] fn device_state(&self) -> zbus::Result<AnimeDeviceState>;
fn awake_enabled(&self) -> zbus::Result<bool>;
/// Get the status of if factory system-status animations are enabled
#[dbus_proxy(property)]
fn animation_enabled(&self) -> zbus::Result<bool>;
/// Notify listeners of the status of AniMe LED power and factory /// Notify listeners of the status of AniMe LED power and factory
/// system-status animations /// system-status animations
#[dbus_proxy(signal)] #[dbus_proxy(signal)]
fn power_states(&self, data: AnimePowerStates) -> zbus::Result<()>; fn device_state(&self, data: AnimeDeviceState) -> zbus::Result<()>;
} }