mirror of
https://gitlab.com/asus-linux/asusctl.git
synced 2026-02-06 00:15:04 +01:00
Basic fade in/out of gifs
This commit is contained in:
@@ -1,6 +1,5 @@
|
||||
use rog_anime::{ActionData, AnimTime, AnimeAction, Sequences, Vec2};
|
||||
use rog_anime::{ActionData, ActionLoader, AnimTime, Fade, Sequences, Vec2};
|
||||
use rog_dbus::RogDbusClient;
|
||||
//use crate::dbus::DbusEvents;
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use std::time::Duration;
|
||||
use std::{
|
||||
@@ -17,6 +16,44 @@ use zvariant_derive::Type;
|
||||
|
||||
use crate::{error::Error, user_config::UserAnimeConfig};
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, Serialize, Type)]
|
||||
pub struct Timer {
|
||||
type_of: TimeType,
|
||||
/// If time type is Timer then this is milliseonds, otherwise it is animation loop count
|
||||
count: u64,
|
||||
/// Used only for `TimeType::Timer`, milliseonds to fade the image in for
|
||||
fade_in: Option<u64>,
|
||||
/// Used only for `TimeType::Timer`, milliseonds to fade the image out for
|
||||
fade_out: Option<u64>,
|
||||
}
|
||||
|
||||
impl From<Timer> for AnimTime {
|
||||
fn from(time: Timer) -> Self {
|
||||
match time.type_of {
|
||||
TimeType::Timer => {
|
||||
if time.fade_in.is_some() || time.fade_out.is_some() {
|
||||
let fade_in = time
|
||||
.fade_in
|
||||
.map_or(Duration::from_secs(0), Duration::from_millis);
|
||||
let fade_out = time
|
||||
.fade_out
|
||||
.map_or(Duration::from_secs(0), Duration::from_millis);
|
||||
let show_for = if time.count != 0 {
|
||||
Some(Duration::from_millis(time.count))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
AnimTime::Fade(Fade::new(fade_in, show_for, fade_out))
|
||||
} else {
|
||||
AnimTime::Time(Duration::from_millis(time.count))
|
||||
}
|
||||
}
|
||||
TimeType::Count => AnimTime::Count(time.count as u32),
|
||||
TimeType::Infinite => AnimTime::Infinite,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, Serialize, Type)]
|
||||
pub enum TimeType {
|
||||
Timer,
|
||||
@@ -29,14 +66,14 @@ pub enum TimeType {
|
||||
pub struct CtrlAnimeInner<'a> {
|
||||
sequences: Sequences,
|
||||
client: RogDbusClient<'a>,
|
||||
do_early_return: &'a AtomicBool,
|
||||
do_early_return: Arc<AtomicBool>,
|
||||
}
|
||||
|
||||
impl<'a> CtrlAnimeInner<'static> {
|
||||
pub fn new(
|
||||
sequences: Sequences,
|
||||
client: RogDbusClient<'static>,
|
||||
do_early_return: &'static AtomicBool,
|
||||
do_early_return: Arc<AtomicBool>,
|
||||
) -> Result<Self, Error> {
|
||||
Ok(Self {
|
||||
sequences,
|
||||
@@ -45,7 +82,7 @@ impl<'a> CtrlAnimeInner<'static> {
|
||||
})
|
||||
}
|
||||
/// To be called on each main loop iteration to pump out commands to the anime
|
||||
pub fn run(&self) -> Result<(), Error> {
|
||||
pub fn run(&'a self) -> Result<(), Error> {
|
||||
if self.do_early_return.load(Ordering::SeqCst) {
|
||||
return Ok(());
|
||||
}
|
||||
@@ -53,32 +90,10 @@ impl<'a> CtrlAnimeInner<'static> {
|
||||
for action in self.sequences.iter() {
|
||||
match action {
|
||||
ActionData::Animation(frames) => {
|
||||
let mut count = 0;
|
||||
let start = Instant::now();
|
||||
'animation: loop {
|
||||
for frame in frames.frames() {
|
||||
if self.do_early_return.load(Ordering::SeqCst) {
|
||||
return Ok(());
|
||||
}
|
||||
self.client
|
||||
.proxies()
|
||||
.anime()
|
||||
.write(frame.frame().clone())
|
||||
.unwrap();
|
||||
if let AnimTime::Time(time) = frames.duration() {
|
||||
if Instant::now().duration_since(start) > time {
|
||||
break 'animation;
|
||||
}
|
||||
}
|
||||
sleep(frame.delay());
|
||||
}
|
||||
if let AnimTime::Cycles(times) = frames.duration() {
|
||||
count += 1;
|
||||
if count >= times {
|
||||
break 'animation;
|
||||
}
|
||||
}
|
||||
}
|
||||
rog_anime::run_animation(frames, self.do_early_return.clone(), &|output| {
|
||||
self.client.proxies().anime().write(output).unwrap()
|
||||
})
|
||||
.unwrap();
|
||||
}
|
||||
ActionData::Image(image) => {
|
||||
self.client
|
||||
@@ -115,7 +130,7 @@ pub struct CtrlAnime<'a> {
|
||||
client: RogDbusClient<'a>,
|
||||
inner: Arc<Mutex<CtrlAnimeInner<'a>>>,
|
||||
/// Must be the same Atomic as in CtrlAnimeInner
|
||||
inner_early_return: &'a AtomicBool,
|
||||
inner_early_return: Arc<AtomicBool>,
|
||||
}
|
||||
|
||||
impl<'a> CtrlAnime<'static> {
|
||||
@@ -123,7 +138,7 @@ impl<'a> CtrlAnime<'static> {
|
||||
config: Arc<Mutex<UserAnimeConfig>>,
|
||||
inner: Arc<Mutex<CtrlAnimeInner<'static>>>,
|
||||
client: RogDbusClient<'static>,
|
||||
inner_early_return: &'static AtomicBool,
|
||||
inner_early_return: Arc<AtomicBool>,
|
||||
) -> Result<Self, Error> {
|
||||
Ok(CtrlAnime {
|
||||
config,
|
||||
@@ -159,18 +174,13 @@ impl CtrlAnime<'static> {
|
||||
&mut self,
|
||||
index: u32,
|
||||
file: String,
|
||||
time: TimeType,
|
||||
count: u32,
|
||||
time: Timer,
|
||||
brightness: f32,
|
||||
) -> zbus::fdo::Result<String> {
|
||||
if let Ok(mut config) = self.config.try_lock() {
|
||||
let time: AnimTime = match time {
|
||||
TimeType::Timer => AnimTime::Time(Duration::from_millis(count as u64)),
|
||||
TimeType::Count => AnimTime::Cycles(count),
|
||||
TimeType::Infinite => AnimTime::Infinite,
|
||||
};
|
||||
let time: AnimTime = time.into();
|
||||
let file = Path::new(&file);
|
||||
let action = AnimeAction::AsusAnimation {
|
||||
let action = ActionLoader::AsusAnimation {
|
||||
file: file.into(),
|
||||
brightness,
|
||||
time,
|
||||
@@ -205,19 +215,14 @@ impl CtrlAnime<'static> {
|
||||
scale: f32,
|
||||
angle: f32,
|
||||
xy: (f32, f32),
|
||||
time: TimeType,
|
||||
count: u32,
|
||||
time: Timer,
|
||||
brightness: f32,
|
||||
) -> zbus::fdo::Result<String> {
|
||||
if let Ok(mut config) = self.config.try_lock() {
|
||||
let time: AnimTime = match time {
|
||||
TimeType::Timer => AnimTime::Time(Duration::from_millis(count as u64)),
|
||||
TimeType::Count => AnimTime::Cycles(count),
|
||||
TimeType::Infinite => AnimTime::Infinite,
|
||||
};
|
||||
let time: AnimTime = time.into();
|
||||
let file = Path::new(&file);
|
||||
let translation = Vec2::new(xy.0, xy.1);
|
||||
let action = AnimeAction::ImageAnimation {
|
||||
let action = ActionLoader::ImageAnimation {
|
||||
file: file.into(),
|
||||
scale,
|
||||
angle,
|
||||
@@ -248,6 +253,7 @@ impl CtrlAnime<'static> {
|
||||
Err(zbus::fdo::Error::Failed("UserConfig lock fail".into()))
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn insert_image(
|
||||
&mut self,
|
||||
index: u32,
|
||||
@@ -255,16 +261,19 @@ impl CtrlAnime<'static> {
|
||||
scale: f32,
|
||||
angle: f32,
|
||||
xy: (f32, f32),
|
||||
time: Option<Timer>,
|
||||
brightness: f32,
|
||||
) -> zbus::fdo::Result<String> {
|
||||
if let Ok(mut config) = self.config.try_lock() {
|
||||
let file = Path::new(&file);
|
||||
let action = AnimeAction::Image {
|
||||
let time = time.map(|time| time.into());
|
||||
let action = ActionLoader::Image {
|
||||
file: file.into(),
|
||||
scale,
|
||||
angle,
|
||||
translation: Vec2::new(xy.0, xy.1),
|
||||
brightness,
|
||||
time,
|
||||
};
|
||||
|
||||
// Must make the inner run loop return early
|
||||
@@ -291,7 +300,7 @@ impl CtrlAnime<'static> {
|
||||
|
||||
pub fn insert_pause(&mut self, index: u32, millis: u64) -> zbus::fdo::Result<String> {
|
||||
if let Ok(mut config) = self.config.try_lock() {
|
||||
let action = AnimeAction::Pause(Duration::from_millis(millis));
|
||||
let action = ActionLoader::Pause(Duration::from_millis(millis));
|
||||
// Must make the inner run loop return early
|
||||
self.inner_early_return.store(true, Ordering::SeqCst);
|
||||
|
||||
|
||||
@@ -11,9 +11,6 @@ use zbus::{fdo, Connection};
|
||||
|
||||
use std::sync::atomic::AtomicBool;
|
||||
|
||||
/// The anime loop needs an atomic to make it exit early if required
|
||||
static ANIME_INNER_EARLY_RETURN: AtomicBool = AtomicBool::new(false);
|
||||
|
||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
println!(" user daemon v{}", rog_user::VERSION);
|
||||
println!(" rog-anime v{}", rog_anime::VERSION);
|
||||
@@ -39,20 +36,16 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
|
||||
// Set up the anime data and run loop/thread
|
||||
if supported.anime_ctrl.0 {
|
||||
let early_return = Arc::new(AtomicBool::new(false));
|
||||
// Inner behind mutex required for thread safety
|
||||
let inner = Arc::new(Mutex::new(CtrlAnimeInner::new(
|
||||
anime,
|
||||
client,
|
||||
&ANIME_INNER_EARLY_RETURN,
|
||||
early_return.clone(),
|
||||
)?));
|
||||
// Need new client object for dbus control part
|
||||
let (client, _) = RogDbusClient::new().unwrap();
|
||||
let anime_control = CtrlAnime::new(
|
||||
anime_config,
|
||||
inner.clone(),
|
||||
client,
|
||||
&ANIME_INNER_EARLY_RETURN,
|
||||
)?;
|
||||
let anime_control = CtrlAnime::new(anime_config, inner.clone(), client, early_return)?;
|
||||
anime_control.add_to_server(&mut server);
|
||||
// Thread using inner
|
||||
let _anime_thread = thread::Builder::new()
|
||||
|
||||
@@ -4,7 +4,7 @@ use std::{
|
||||
time::Duration,
|
||||
};
|
||||
|
||||
use rog_anime::{AnimTime, AnimeAction, Sequences, Vec2};
|
||||
use rog_anime::{ActionLoader, AnimTime, Fade, Sequences, Vec2};
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
|
||||
use crate::error::Error;
|
||||
@@ -12,7 +12,7 @@ use crate::error::Error;
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
pub struct UserAnimeConfig {
|
||||
pub name: String,
|
||||
pub anime: Vec<AnimeAction>,
|
||||
pub anime: Vec<ActionLoader>,
|
||||
}
|
||||
|
||||
impl UserAnimeConfig {
|
||||
@@ -95,34 +95,47 @@ impl Default for UserAnimeConfig {
|
||||
Self {
|
||||
name: "default".to_string(),
|
||||
anime: vec![
|
||||
AnimeAction::AsusAnimation {
|
||||
ActionLoader::AsusAnimation {
|
||||
file: "/usr/share/asusd/anime/asus/rog/Sunset.gif".into(),
|
||||
brightness: 0.5,
|
||||
time: AnimTime::Cycles(1),
|
||||
time: AnimTime::Fade(Fade::new(
|
||||
Duration::from_secs(6),
|
||||
None,
|
||||
Duration::from_secs(3),
|
||||
)),
|
||||
},
|
||||
AnimeAction::ImageAnimation {
|
||||
ActionLoader::ImageAnimation {
|
||||
file: "/usr/share/asusd/anime/custom/sonic-run.gif".into(),
|
||||
scale: 0.9,
|
||||
angle: 0.65,
|
||||
translation: Vec2::default(),
|
||||
brightness: 0.5,
|
||||
time: AnimTime::Time(Duration::from_secs(5)),
|
||||
time: AnimTime::Fade(Fade::new(
|
||||
Duration::from_secs(2),
|
||||
Some(Duration::from_secs(2)),
|
||||
Duration::from_secs(2),
|
||||
)),
|
||||
},
|
||||
AnimeAction::Image {
|
||||
ActionLoader::Image {
|
||||
file: "/usr/share/asusd/anime/custom/rust.png".into(),
|
||||
scale: 1.0,
|
||||
angle: 0.0,
|
||||
translation: Vec2::default(),
|
||||
time: Some(AnimTime::Fade(Fade::new(
|
||||
Duration::from_secs(2),
|
||||
Some(Duration::from_secs(1)),
|
||||
Duration::from_secs(2),
|
||||
))),
|
||||
brightness: 0.6,
|
||||
},
|
||||
AnimeAction::Pause(Duration::from_secs(6)),
|
||||
AnimeAction::ImageAnimation {
|
||||
ActionLoader::Pause(Duration::from_secs(1)),
|
||||
ActionLoader::ImageAnimation {
|
||||
file: "/usr/share/asusd/anime/custom/sonic-wait.gif".into(),
|
||||
scale: 0.9,
|
||||
angle: 0.0,
|
||||
translation: Vec2::new(3.0, 2.0),
|
||||
brightness: 0.5,
|
||||
time: AnimTime::Cycles(2),
|
||||
time: AnimTime::Count(2),
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user