mirror of
https://gitlab.com/asus-linux/asusctl.git
synced 2026-02-06 00:15:04 +01:00
anime: add zbus methods
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
#[cfg(feature = "zbus")]
|
||||
#[cfg(feature = "z")]
|
||||
use zvariant_derive::Type;
|
||||
|
||||
/// The first 7 bytes of a USB packet are accounted for by `USB_PREFIX1` and `USB_PREFIX2`
|
||||
@@ -16,7 +16,7 @@ const USB_PREFIX2: [u8; 7] = [0x5e, 0xc0, 0x02, 0x74, 0x02, 0x73, 0x02];
|
||||
|
||||
/// The minimal serializable data that can be transferred over wire types.
|
||||
/// Other data structures in `rog_anime` will convert to this.
|
||||
#[cfg_attr(feature = "zbus", derive(Type))]
|
||||
#[cfg_attr(feature = "z", derive(Type))]
|
||||
#[derive(Debug, Clone, Deserialize, Serialize)]
|
||||
pub struct AniMeDataBuffer(Vec<u8>);
|
||||
|
||||
|
||||
@@ -3,6 +3,9 @@ use png_pong::decode::Error as PngError;
|
||||
use std::error::Error;
|
||||
use std::fmt;
|
||||
|
||||
#[cfg(feature = "z")]
|
||||
use zbus::fdo;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum AnimeError {
|
||||
NoFrames,
|
||||
@@ -12,6 +15,8 @@ pub enum AnimeError {
|
||||
Format,
|
||||
/// The input was incorrect size, expected size is `IncorrectSize(width, height)`
|
||||
IncorrectSize(u32, u32),
|
||||
#[cfg(feature = "z")]
|
||||
Zbus(fdo::Error)
|
||||
}
|
||||
|
||||
impl fmt::Display for AnimeError {
|
||||
@@ -28,6 +33,8 @@ impl fmt::Display for AnimeError {
|
||||
"The input image size is incorrect, expected {}x{}",
|
||||
width, height
|
||||
),
|
||||
#[cfg(feature = "z")]
|
||||
AnimeError::Zbus(e) => write!(f, "ZBUS error: {}", e),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -51,3 +58,10 @@ impl From<DecodingError> for AnimeError {
|
||||
AnimeError::Gif(err)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "z")]
|
||||
impl From<AnimeError> for fdo::Error {
|
||||
fn from(err: AnimeError) -> Self {
|
||||
fdo::Error::Failed(format!("{}", err))
|
||||
}
|
||||
}
|
||||
@@ -24,6 +24,7 @@ impl AniMeFrame {
|
||||
|
||||
#[derive(Debug, Copy, Clone, Deserialize, Serialize)]
|
||||
pub enum AnimTime {
|
||||
/// Time in milliseconds for animation to run
|
||||
Time(Duration),
|
||||
Cycles(u32),
|
||||
Infinite,
|
||||
@@ -35,7 +36,6 @@ impl Default for AnimTime {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// A gif animation. This is a collection of frames from the gif, and a duration
|
||||
/// that the animation should be shown for.
|
||||
#[derive(Debug, Clone, Deserialize, Serialize)]
|
||||
|
||||
@@ -1,13 +1,44 @@
|
||||
use std::{path::Path, time::Duration};
|
||||
use std::{
|
||||
path::{Path, PathBuf},
|
||||
time::Duration,
|
||||
};
|
||||
|
||||
use glam::Vec2;
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
|
||||
use crate::{AniMeDataBuffer, AniMeGif, AniMeImage, AnimTime, error::AnimeError};
|
||||
use crate::{error::AnimeError, AniMeDataBuffer, AniMeGif, AniMeImage, AnimTime};
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, Serialize)]
|
||||
pub enum AnimeAction {
|
||||
/// Full gif sequence. Immutable.
|
||||
AsusAnimation {
|
||||
file: PathBuf,
|
||||
time: AnimTime,
|
||||
brightness: f32,
|
||||
},
|
||||
/// Basic image, can have properties changed
|
||||
ImageAnimation {
|
||||
file: PathBuf,
|
||||
scale: f32,
|
||||
angle: f32,
|
||||
translation: Vec2,
|
||||
time: AnimTime,
|
||||
brightness: f32,
|
||||
},
|
||||
Image {
|
||||
file: PathBuf,
|
||||
scale: f32,
|
||||
angle: f32,
|
||||
translation: Vec2,
|
||||
brightness: f32,
|
||||
},
|
||||
/// A pause to be used between sequences
|
||||
Pause(Duration),
|
||||
}
|
||||
|
||||
///
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
pub enum Action {
|
||||
pub enum ActionData {
|
||||
/// Full gif sequence. Immutable.
|
||||
Animation(AniMeGif),
|
||||
/// Basic image, can have properties changed and image updated via those properties
|
||||
@@ -26,40 +57,92 @@ pub enum Action {
|
||||
|
||||
/// An optimised precomputed set of actions
|
||||
#[derive(Debug, Deserialize, Serialize, Default)]
|
||||
pub struct Sequences(Vec<Action>);
|
||||
pub struct Sequences(Vec<ActionData>);
|
||||
|
||||
impl Sequences {
|
||||
pub fn new() -> Self {
|
||||
Self(Vec::new())
|
||||
}
|
||||
|
||||
pub fn add_asus_gif(
|
||||
pub fn insert(&mut self, index: usize, action: &AnimeAction) -> Result<(), AnimeError> {
|
||||
match action {
|
||||
AnimeAction::AsusAnimation {
|
||||
file,
|
||||
time: duration,
|
||||
brightness,
|
||||
} => self.insert_asus_gif(index, &file, *duration, *brightness)?,
|
||||
AnimeAction::ImageAnimation {
|
||||
file,
|
||||
scale,
|
||||
angle,
|
||||
translation,
|
||||
time: duration,
|
||||
brightness,
|
||||
} => self.insert_image_gif(
|
||||
index,
|
||||
&file,
|
||||
*scale,
|
||||
*angle,
|
||||
*translation,
|
||||
*duration,
|
||||
*brightness,
|
||||
)?,
|
||||
AnimeAction::Image {
|
||||
file,
|
||||
scale,
|
||||
angle,
|
||||
translation,
|
||||
brightness,
|
||||
} => self.insert_png(index, &file, *scale, *angle, *translation, *brightness)?,
|
||||
AnimeAction::Pause(duration) => self.insert_pause(index, *duration),
|
||||
};
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn remove_item(&mut self, index: usize) -> Option<ActionData> {
|
||||
if index < self.0.len() {
|
||||
return Some(self.0.remove(index));
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
fn insert_asus_gif(
|
||||
&mut self,
|
||||
mut index: usize,
|
||||
file: &Path,
|
||||
duration: AnimTime,
|
||||
brightness: f32,
|
||||
) -> Result<(), AnimeError> {
|
||||
if index > self.0.len() {
|
||||
index = self.0.len() - 1;
|
||||
}
|
||||
let frames = AniMeGif::create_diagonal_gif(file, duration, brightness)?;
|
||||
self.0.push(Action::Animation(frames));
|
||||
self.0.insert(index, ActionData::Animation(frames));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn add_png(
|
||||
fn insert_png(
|
||||
&mut self,
|
||||
mut index: usize,
|
||||
file: &Path,
|
||||
scale: f32,
|
||||
angle: f32,
|
||||
translation: Vec2,
|
||||
brightness: f32,
|
||||
) -> Result<(), AnimeError> {
|
||||
if index > self.0.len() {
|
||||
index = self.0.len() - 1;
|
||||
}
|
||||
let image = AniMeImage::from_png(file, scale, angle, translation, brightness)?;
|
||||
let data = <AniMeDataBuffer>::from(&image);
|
||||
self.0.push(Action::Image(Box::new(data)));
|
||||
self.0.insert(index, ActionData::Image(Box::new(data)));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn add_image_gif(
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
fn insert_image_gif(
|
||||
&mut self,
|
||||
mut index: usize,
|
||||
file: &Path,
|
||||
scale: f32,
|
||||
angle: f32,
|
||||
@@ -67,15 +150,20 @@ impl Sequences {
|
||||
duration: AnimTime,
|
||||
brightness: f32,
|
||||
) -> Result<(), AnimeError> {
|
||||
if index > self.0.len() {
|
||||
index = self.0.len() - 1;
|
||||
}
|
||||
let frames =
|
||||
AniMeGif::create_png_gif(file, scale, angle, translation, duration, brightness)?;
|
||||
self.0.push(Action::Animation(frames));
|
||||
self.0.insert(index, ActionData::Animation(frames));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn add_pause(&mut self, duration: Duration) -> Result<(), AnimeError> {
|
||||
self.0.push(Action::Pause(duration));
|
||||
Ok(())
|
||||
fn insert_pause(&mut self, mut index: usize, duration: Duration) {
|
||||
if index > self.0.len() {
|
||||
index = self.0.len() - 1;
|
||||
}
|
||||
self.0.insert(index, ActionData::Pause(duration));
|
||||
}
|
||||
|
||||
pub fn iter(&self) -> ActionIterator {
|
||||
@@ -92,9 +180,9 @@ pub struct ActionIterator<'a> {
|
||||
}
|
||||
|
||||
impl<'a> Iterator for ActionIterator<'a> {
|
||||
type Item = &'a Action;
|
||||
type Item = &'a ActionData;
|
||||
|
||||
fn next(&mut self) -> Option<&'a Action> {
|
||||
fn next(&mut self) -> Option<&'a ActionData> {
|
||||
if self.next_idx == self.actions.0.len() {
|
||||
self.next_idx = 0;
|
||||
return None;
|
||||
|
||||
Reference in New Issue
Block a user