mirror of
https://gitlab.com/asus-linux/asusctl.git
synced 2026-01-22 17:33:19 +01:00
anime: prep rog-anime for publish, rename *all* AniMe~ to Anime
This commit is contained in:
103
Cargo.lock
generated
103
Cargo.lock
generated
@@ -250,7 +250,7 @@ checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote 1.0.9",
|
||||
"syn 1.0.68",
|
||||
"syn 1.0.69",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -302,7 +302,7 @@ checksum = "946ee94e3dbf58fdd324f9ce245c7b238d46a66f00e86a020b71996349e46cce"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote 1.0.9",
|
||||
"syn 1.0.68",
|
||||
"syn 1.0.69",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -328,7 +328,7 @@ dependencies = [
|
||||
"proc-macro2",
|
||||
"quote 1.0.9",
|
||||
"rustversion",
|
||||
"syn 1.0.68",
|
||||
"syn 1.0.69",
|
||||
"synstructure",
|
||||
]
|
||||
|
||||
@@ -343,9 +343,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "futures"
|
||||
version = "0.3.13"
|
||||
version = "0.3.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7f55667319111d593ba876406af7c409c0ebb44dc4be6132a783ccf163ea14c1"
|
||||
checksum = "a9d5813545e459ad3ca1bff9915e9ad7f1a47dc6a91b627ce321d5863b7dd253"
|
||||
dependencies = [
|
||||
"futures-channel",
|
||||
"futures-core",
|
||||
@@ -358,9 +358,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "futures-channel"
|
||||
version = "0.3.13"
|
||||
version = "0.3.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8c2dd2df839b57db9ab69c2c9d8f3e8c81984781937fe2807dc6dcf3b2ad2939"
|
||||
checksum = "ce79c6a52a299137a6013061e0cf0e688fce5d7f1bc60125f520912fdb29ec25"
|
||||
dependencies = [
|
||||
"futures-core",
|
||||
"futures-sink",
|
||||
@@ -368,15 +368,15 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "futures-core"
|
||||
version = "0.3.13"
|
||||
version = "0.3.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "15496a72fabf0e62bdc3df11a59a3787429221dd0710ba8ef163d6f7a9112c94"
|
||||
checksum = "098cd1c6dda6ca01650f1a37a794245eb73181d0d4d4e955e2f3c37db7af1815"
|
||||
|
||||
[[package]]
|
||||
name = "futures-executor"
|
||||
version = "0.3.13"
|
||||
version = "0.3.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "891a4b7b96d84d5940084b2a37632dd65deeae662c114ceaa2c879629c9c0ad1"
|
||||
checksum = "10f6cb7042eda00f0049b1d2080aa4b93442997ee507eb3828e8bd7577f94c9d"
|
||||
dependencies = [
|
||||
"futures-core",
|
||||
"futures-task",
|
||||
@@ -385,9 +385,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "futures-io"
|
||||
version = "0.3.13"
|
||||
version = "0.3.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d71c2c65c57704c32f5241c1223167c2c3294fd34ac020c807ddbe6db287ba59"
|
||||
checksum = "365a1a1fb30ea1c03a830fdb2158f5236833ac81fa0ad12fe35b29cddc35cb04"
|
||||
|
||||
[[package]]
|
||||
name = "futures-lite"
|
||||
@@ -406,33 +406,33 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "futures-macro"
|
||||
version = "0.3.13"
|
||||
version = "0.3.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ea405816a5139fb39af82c2beb921d52143f556038378d6db21183a5c37fbfb7"
|
||||
checksum = "668c6733a182cd7deb4f1de7ba3bf2120823835b3bcfbeacf7d2c4a773c1bb8b"
|
||||
dependencies = [
|
||||
"proc-macro-hack",
|
||||
"proc-macro2",
|
||||
"quote 1.0.9",
|
||||
"syn 1.0.68",
|
||||
"syn 1.0.69",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "futures-sink"
|
||||
version = "0.3.13"
|
||||
version = "0.3.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "85754d98985841b7d4f5e8e6fbfa4a4ac847916893ec511a2917ccd8525b8bb3"
|
||||
checksum = "5c5629433c555de3d82861a7a4e3794a4c40040390907cfbfd7143a92a426c23"
|
||||
|
||||
[[package]]
|
||||
name = "futures-task"
|
||||
version = "0.3.13"
|
||||
version = "0.3.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fa189ef211c15ee602667a6fcfe1c1fd9e07d42250d2156382820fba33c9df80"
|
||||
checksum = "ba7aa51095076f3ba6d9a1f702f74bd05ec65f555d70d2033d55ba8d69f581bc"
|
||||
|
||||
[[package]]
|
||||
name = "futures-util"
|
||||
version = "0.3.13"
|
||||
version = "0.3.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1812c7ab8aedf8d6f2701a43e1243acdbcc2b36ab26e2ad421eb99ac963d96d1"
|
||||
checksum = "3c144ad54d60f23927f0a6b6d816e4271278b64f005ad65e4e35291d2de9c025"
|
||||
dependencies = [
|
||||
"futures-channel",
|
||||
"futures-core",
|
||||
@@ -471,12 +471,11 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "glam"
|
||||
version = "0.13.1"
|
||||
version = "0.14.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "70155b56080764b8b758e91e4c63d06da0262c0c939f2cd991cd1382087147df"
|
||||
checksum = "333928d5eb103c5d4050533cec0384302db6be8ef7d3cebd30ec6a35350353da"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"spirv-std",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -496,7 +495,7 @@ checksum = "915ef07c710d84733522461de2a734d4d62a3fd39a4d4f404c2f385ef8618d05"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote 1.0.9",
|
||||
"syn 1.0.68",
|
||||
"syn 1.0.69",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -551,12 +550,6 @@ version = "0.2.93"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9385f66bf6105b241aa65a61cb923ef20efc665cb9f9bb50ac2f0c4b7f378d41"
|
||||
|
||||
[[package]]
|
||||
name = "libm"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c7d73b3f436185384286bd8098d17ec07c9a7d2388a6599f824d8502b529702a"
|
||||
|
||||
[[package]]
|
||||
name = "libudev-sys"
|
||||
version = "0.1.4"
|
||||
@@ -703,7 +696,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"libm",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -818,7 +810,7 @@ dependencies = [
|
||||
"proc-macro-error-attr",
|
||||
"proc-macro2",
|
||||
"quote 1.0.9",
|
||||
"syn 1.0.68",
|
||||
"syn 1.0.69",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
@@ -905,7 +897,7 @@ checksum = "24d5f089152e60f62d28b835fbff2cd2e8dc0baf1ac13343bef92ab7eed84548"
|
||||
|
||||
[[package]]
|
||||
name = "rog_anime"
|
||||
version = "1.0.0"
|
||||
version = "1.0.2"
|
||||
dependencies = [
|
||||
"gif",
|
||||
"glam",
|
||||
@@ -954,9 +946,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rusb"
|
||||
version = "0.7.0"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c470dc7dc6e4710b6f85e9c4aa4650bc742260b39a36328180578db76fa258c1"
|
||||
checksum = "12f3264859095257507e4c011ab420ff9b2d9cc3349c6c08a1d3a019260bb437"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"libusb1-sys",
|
||||
@@ -1009,7 +1001,7 @@ checksum = "b093b7a2bb58203b5da3056c05b4ec1fed827dcfdb37347a8841695263b3d06d"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote 1.0.9",
|
||||
"syn 1.0.68",
|
||||
"syn 1.0.69",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1031,7 +1023,7 @@ checksum = "2dc6b7951b17b051f3210b063f12cc17320e2fe30ae05b0fe2a3abb068551c76"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote 1.0.9",
|
||||
"syn 1.0.68",
|
||||
"syn 1.0.69",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1048,7 +1040,7 @@ checksum = "133659a15339456eeeb07572eb02a91c91e9815e9cbc89566944d2c8d3efdbf6"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote 1.0.9",
|
||||
"syn 1.0.68",
|
||||
"syn 1.0.69",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1061,27 +1053,6 @@ dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "spirv-std"
|
||||
version = "0.4.0-alpha.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6de6f1b80004dfc3e9e02fdf8eb32c663f3b85e3942f39d02b6540ed0d2460dd"
|
||||
dependencies = [
|
||||
"num-traits",
|
||||
"spirv-std-macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "spirv-std-macros"
|
||||
version = "0.4.0-alpha.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f4972082b5236fd57a46cc47fbc315ad78b5ad07b33e51077c688a2fe28d6f2d"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote 1.0.9",
|
||||
"syn 1.0.68",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "strum"
|
||||
version = "0.8.0"
|
||||
@@ -1111,9 +1082,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.68"
|
||||
version = "1.0.69"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3ce15dd3ed8aa2f8eeac4716d6ef5ab58b6b9256db41d7e1a0224c2788e8fd87"
|
||||
checksum = "48fe99c6bd8b1cc636890bcc071842de909d902c81ac7dab53ba33c421ab8ffb"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote 1.0.9",
|
||||
@@ -1137,7 +1108,7 @@ checksum = "b834f2d66f734cb897113e34aaff2f1ab4719ca946f9a7358dba8f8064148701"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote 1.0.9",
|
||||
"syn 1.0.68",
|
||||
"syn 1.0.69",
|
||||
"unicode-xid 0.2.1",
|
||||
]
|
||||
|
||||
@@ -1371,7 +1342,7 @@ dependencies = [
|
||||
"proc-macro-crate",
|
||||
"proc-macro2",
|
||||
"quote 1.0.9",
|
||||
"syn 1.0.68",
|
||||
"syn 1.0.69",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1395,5 +1366,5 @@ dependencies = [
|
||||
"proc-macro-crate",
|
||||
"proc-macro2",
|
||||
"quote 1.0.9",
|
||||
"syn 1.0.68",
|
||||
"syn 1.0.69",
|
||||
]
|
||||
|
||||
@@ -18,6 +18,6 @@ yansi-term = "^0.1"
|
||||
|
||||
[dev-dependencies]
|
||||
tinybmp = "^0.2.3"
|
||||
glam = "*"
|
||||
glam = "0.14.0"
|
||||
rog_dbus = { path = "../rog-dbus" }
|
||||
gif = "^0.11.2"
|
||||
@@ -1,6 +1,6 @@
|
||||
use std::{env, error::Error, path::Path, process::exit};
|
||||
|
||||
use rog_anime::{AniMeDataBuffer, AniMeDiagonal};
|
||||
use rog_anime::{AnimeDataBuffer, AnimeDiagonal};
|
||||
use rog_dbus::AuraDbusClient;
|
||||
|
||||
fn main() -> Result<(), Box<dyn Error>> {
|
||||
@@ -14,12 +14,12 @@ fn main() -> Result<(), Box<dyn Error>> {
|
||||
}
|
||||
|
||||
let matrix =
|
||||
AniMeDiagonal::from_png(Path::new(&args[1]), None, args[2].parse::<f32>().unwrap())?;
|
||||
AnimeDiagonal::from_png(Path::new(&args[1]), None, args[2].parse::<f32>().unwrap())?;
|
||||
|
||||
client
|
||||
.proxies()
|
||||
.anime()
|
||||
.write(<AniMeDataBuffer>::from(&matrix))
|
||||
.write(<AnimeDataBuffer>::from(&matrix))
|
||||
.unwrap();
|
||||
|
||||
Ok(())
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use std::{thread::sleep, time::Duration};
|
||||
|
||||
use rog_anime::{AniMeDataBuffer, AniMeDiagonal};
|
||||
use rog_anime::{AnimeDataBuffer, AnimeDiagonal};
|
||||
use rog_dbus::AuraDbusClient;
|
||||
|
||||
// In usable data:
|
||||
@@ -12,7 +12,7 @@ fn main() {
|
||||
let (client, _) = AuraDbusClient::new().unwrap();
|
||||
|
||||
for step in (2..50).rev() {
|
||||
let mut matrix = AniMeDiagonal::new(None);
|
||||
let mut matrix = AnimeDiagonal::new(None);
|
||||
for c in (0..60).into_iter().step_by(step) {
|
||||
for i in matrix.get_mut().iter_mut() {
|
||||
i[c] = 50;
|
||||
@@ -25,7 +25,7 @@ fn main() {
|
||||
}
|
||||
}
|
||||
|
||||
let m = <AniMeDataBuffer>::from(&matrix);
|
||||
let m = <AnimeDataBuffer>::from(&matrix);
|
||||
client.proxies().anime().write(m).unwrap();
|
||||
sleep(Duration::from_millis(300));
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use rog_anime::{AniMeDataBuffer, AniMeGrid};
|
||||
use rog_anime::{AnimeDataBuffer, AnimeGrid};
|
||||
use rog_dbus::AuraDbusClient;
|
||||
|
||||
// In usable data:
|
||||
@@ -8,7 +8,7 @@ use rog_dbus::AuraDbusClient;
|
||||
|
||||
fn main() {
|
||||
let (client, _) = AuraDbusClient::new().unwrap();
|
||||
let mut matrix = AniMeGrid::new(None);
|
||||
let mut matrix = AnimeGrid::new(None);
|
||||
let tmp = matrix.get_mut();
|
||||
|
||||
let mut i = 0;
|
||||
@@ -38,7 +38,7 @@ fn main() {
|
||||
}
|
||||
}
|
||||
|
||||
let matrix = <AniMeDataBuffer>::from(matrix);
|
||||
let matrix = <AnimeDataBuffer>::from(matrix);
|
||||
|
||||
client.proxies().anime().write(matrix).unwrap();
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use rog_anime::AniMeDataBuffer;
|
||||
use rog_anime::AnimeDataBuffer;
|
||||
use rog_dbus::AuraDbusClient;
|
||||
|
||||
// In usable data:
|
||||
@@ -6,7 +6,7 @@ use rog_dbus::AuraDbusClient;
|
||||
|
||||
fn main() {
|
||||
let (client, _) = AuraDbusClient::new().unwrap();
|
||||
let mut matrix = AniMeDataBuffer::new();
|
||||
let mut matrix = AnimeDataBuffer::new();
|
||||
matrix.get_mut()[1] = 100; // start = 1
|
||||
for n in matrix.get_mut()[2..32].iter_mut() {
|
||||
*n = 250;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use std::{env, error::Error, path::Path, process::exit};
|
||||
|
||||
use rog_anime::{
|
||||
AniMeDataBuffer, {AniMeImage, Vec2},
|
||||
AnimeDataBuffer, {AnimeImage, Vec2},
|
||||
};
|
||||
use rog_dbus::AuraDbusClient;
|
||||
|
||||
@@ -15,7 +15,7 @@ fn main() -> Result<(), Box<dyn Error>> {
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
let matrix = AniMeImage::from_png(
|
||||
let matrix = AnimeImage::from_png(
|
||||
Path::new(&args[1]),
|
||||
args[2].parse::<f32>().unwrap(),
|
||||
args[3].parse::<f32>().unwrap(),
|
||||
@@ -29,7 +29,7 @@ fn main() -> Result<(), Box<dyn Error>> {
|
||||
client
|
||||
.proxies()
|
||||
.anime()
|
||||
.write(<AniMeDataBuffer>::from(&matrix))
|
||||
.write(<AnimeDataBuffer>::from(&matrix))
|
||||
.unwrap();
|
||||
|
||||
Ok(())
|
||||
|
||||
@@ -3,7 +3,7 @@ use std::{
|
||||
};
|
||||
|
||||
use rog_anime::{
|
||||
AniMeDataBuffer, {AniMeImage, Vec2},
|
||||
AnimeDataBuffer, {AnimeImage, Vec2},
|
||||
};
|
||||
use rog_dbus::AuraDbusClient;
|
||||
|
||||
@@ -17,7 +17,7 @@ fn main() -> Result<(), Box<dyn Error>> {
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
let mut matrix = AniMeImage::from_png(
|
||||
let mut matrix = AnimeImage::from_png(
|
||||
Path::new(&args[1]),
|
||||
args[2].parse::<f32>().unwrap(),
|
||||
args[3].parse::<f32>().unwrap(),
|
||||
@@ -38,7 +38,7 @@ fn main() -> Result<(), Box<dyn Error>> {
|
||||
client
|
||||
.proxies()
|
||||
.anime()
|
||||
.write(<AniMeDataBuffer>::from(&matrix))
|
||||
.write(<AnimeDataBuffer>::from(&matrix))
|
||||
.unwrap();
|
||||
sleep(Duration::from_micros(500));
|
||||
}
|
||||
|
||||
@@ -3,18 +3,18 @@ use rog_types::error::AuraError;
|
||||
use std::str::FromStr;
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub enum AniMeStatusValue {
|
||||
pub enum AnimeStatusValue {
|
||||
On,
|
||||
Off,
|
||||
}
|
||||
impl FromStr for AniMeStatusValue {
|
||||
impl FromStr for AnimeStatusValue {
|
||||
type Err = AuraError;
|
||||
|
||||
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),
|
||||
"on" => Ok(AnimeStatusValue::On),
|
||||
"off" => Ok(AnimeStatusValue::Off),
|
||||
_ => {
|
||||
print!("Invalid argument, must be one of: on, off");
|
||||
Err(AuraError::ParseAnime)
|
||||
@@ -22,17 +22,17 @@ impl FromStr for AniMeStatusValue {
|
||||
}
|
||||
}
|
||||
}
|
||||
impl From<AniMeStatusValue> for bool {
|
||||
fn from(value: AniMeStatusValue) -> Self {
|
||||
impl From<AnimeStatusValue> for bool {
|
||||
fn from(value: AnimeStatusValue) -> Self {
|
||||
match value {
|
||||
AniMeStatusValue::On => true,
|
||||
AniMeStatusValue::Off => false,
|
||||
AnimeStatusValue::On => true,
|
||||
AnimeStatusValue::Off => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Options)]
|
||||
pub struct AniMeLeds {
|
||||
pub struct AnimeLeds {
|
||||
#[options(help = "print help message")]
|
||||
help: bool,
|
||||
#[options(
|
||||
@@ -44,37 +44,37 @@ pub struct AniMeLeds {
|
||||
)]
|
||||
led_brightness: u8,
|
||||
}
|
||||
impl AniMeLeds {
|
||||
impl AnimeLeds {
|
||||
pub fn led_brightness(&self) -> u8 {
|
||||
self.led_brightness
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Options)]
|
||||
pub struct AniMeCommand {
|
||||
pub struct AnimeCommand {
|
||||
#[options(help = "print help message")]
|
||||
pub help: bool,
|
||||
#[options(
|
||||
meta = "",
|
||||
help = "turn on/off the panel (accept/reject write requests)"
|
||||
)]
|
||||
pub turn: Option<AniMeStatusValue>,
|
||||
pub turn: Option<AnimeStatusValue>,
|
||||
#[options(meta = "", help = "turn on/off the panel at boot (with Asus effect)")]
|
||||
pub boot: Option<AniMeStatusValue>,
|
||||
pub boot: Option<AnimeStatusValue>,
|
||||
#[options(command)]
|
||||
pub command: Option<AniMeActions>,
|
||||
pub command: Option<AnimeActions>,
|
||||
}
|
||||
|
||||
#[derive(Options)]
|
||||
pub enum AniMeActions {
|
||||
pub enum AnimeActions {
|
||||
#[options(help = "change all leds brightness")]
|
||||
Leds(AniMeLeds),
|
||||
Leds(AnimeLeds),
|
||||
#[options(help = "display an 8bit greyscale png")]
|
||||
Image(AniMeImage),
|
||||
Image(AnimeImage),
|
||||
}
|
||||
|
||||
#[derive(Options)]
|
||||
pub struct AniMeImage {
|
||||
pub struct AnimeImage {
|
||||
#[options(help = "print help message")]
|
||||
pub help: bool,
|
||||
#[options(meta = "", help = "full path to the png to display")]
|
||||
|
||||
@@ -2,9 +2,9 @@ mod anime_cli;
|
||||
mod aura_cli;
|
||||
|
||||
use crate::aura_cli::{LedBrightness, SetAuraBuiltin};
|
||||
use anime_cli::{AniMeActions, AniMeCommand};
|
||||
use anime_cli::{AnimeActions, AnimeCommand};
|
||||
use gumdrop::{Opt, Options};
|
||||
use rog_anime::{AniMeDataBuffer, AniMeImage, Vec2, ANIME_DATA_LEN};
|
||||
use rog_anime::{AnimeDataBuffer, AnimeImage, Vec2, ANIME_DATA_LEN};
|
||||
use rog_dbus::AuraDbusClient;
|
||||
use rog_types::{
|
||||
aura_modes::{self, AuraEffect, AuraModeNum},
|
||||
@@ -49,7 +49,7 @@ enum CliCommand {
|
||||
#[options(help = "Set the graphics mode")]
|
||||
Graphics(GraphicsCommand),
|
||||
#[options(name = "anime", help = "Manage AniMe Matrix")]
|
||||
AniMe(AniMeCommand),
|
||||
Anime(AnimeCommand),
|
||||
#[options(help = "Change bios settings")]
|
||||
Bios(BiosCommand),
|
||||
}
|
||||
@@ -145,7 +145,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
Some(CliCommand::LedMode(mode)) => handle_led_mode(&dbus, &supported.keyboard_led, &mode)?,
|
||||
Some(CliCommand::Profile(cmd)) => handle_profile(&dbus, &supported.fan_cpu_ctrl, &cmd)?,
|
||||
Some(CliCommand::Graphics(cmd)) => do_gfx(&dbus, &supported.rog_bios_ctrl, cmd)?,
|
||||
Some(CliCommand::AniMe(cmd)) => {
|
||||
Some(CliCommand::Anime(cmd)) => {
|
||||
if (cmd.command.is_none() && cmd.boot.is_none() && cmd.turn.is_none()) || cmd.help {
|
||||
println!("Missing arg or command\n\n{}", cmd.self_usage());
|
||||
if let Some(lst) = cmd.self_command_list() {
|
||||
@@ -160,13 +160,13 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
}
|
||||
if let Some(action) = cmd.command {
|
||||
match action {
|
||||
AniMeActions::Leds(anime_leds) => {
|
||||
let data = AniMeDataBuffer::from_vec(
|
||||
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) => {
|
||||
AnimeActions::Image(image) => {
|
||||
if image.help_requested() {
|
||||
println!("Missing arg or command\n\n{}", image.self_usage());
|
||||
if let Some(lst) = image.self_command_list() {
|
||||
@@ -175,7 +175,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
std::process::exit(1);
|
||||
}
|
||||
|
||||
let matrix = AniMeImage::from_png(
|
||||
let matrix = AnimeImage::from_png(
|
||||
Path::new(&image.path),
|
||||
image.scale,
|
||||
image.angle,
|
||||
@@ -185,7 +185,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
|
||||
dbus.proxies()
|
||||
.anime()
|
||||
.write(<AniMeDataBuffer>::from(&matrix))
|
||||
.write(<AnimeDataBuffer>::from(&matrix))
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
14
daemon-user/README.md
Normal file
14
daemon-user/README.md
Normal file
@@ -0,0 +1,14 @@
|
||||
# daemon-user
|
||||
|
||||
This crate is for the binary of `asusd-user` and its helper lib.
|
||||
|
||||
The purpose of `asusd-user` is to run in userland and provide the user + third-party apps an interface for such things as creating AniMe sequences (and more in future, see todo list).
|
||||
|
||||
`asusd-user` should try to be as simple as possible while allowing a decent degree of control.
|
||||
|
||||
## TODO
|
||||
|
||||
- [ ] CLI for basic settings/interaction
|
||||
- [ ] RGB keyboard per-key programs
|
||||
- [ ] User profiles (fan, cpu etc). These would be replacing the system-daemon profiles only when the user is active, otherwise system-daemon defaults to system settings.
|
||||
- [ ] Audio EQ visualiser - for use with anime + keyboard lighting
|
||||
@@ -21,7 +21,7 @@ path = "src/daemon.rs"
|
||||
rog_anime = { path = "../rog-anime" }
|
||||
rog_types = { path = "../rog-types" }
|
||||
rog_dbus = { path = "../rog-dbus" }
|
||||
rusb = "^0.7"
|
||||
rusb = "^0.8"
|
||||
udev = "^0.6"
|
||||
|
||||
# cli and logging
|
||||
|
||||
@@ -1,20 +1,11 @@
|
||||
const INIT_STR: &str = "ASUS Tech.Inc.";
|
||||
const PACKET_SIZE: usize = 640;
|
||||
|
||||
// Only these two packets must be 17 bytes
|
||||
const DEV_PAGE: u8 = 0x5e;
|
||||
// These bytes are in [1] position of the array
|
||||
const WRITE: u8 = 0xc0;
|
||||
const INIT: u8 = 0xc2;
|
||||
const SET: u8 = 0xc3;
|
||||
const APPLY: u8 = 0xc4;
|
||||
|
||||
// Used to turn the panel on and off
|
||||
// The next byte can be 0x03 for "on" and 0x00 for "off"
|
||||
const ON_OFF: u8 = 0x04;
|
||||
|
||||
use log::{error, info, warn};
|
||||
use rog_anime::{AniMeDataBuffer, AniMePacketType};
|
||||
use rog_anime::{
|
||||
usb::{
|
||||
pkt_for_apply, pkt_for_flush, pkt_for_set_boot, pkt_for_set_on, pkts_for_init, PROD_ID,
|
||||
VENDOR_ID,
|
||||
},
|
||||
AnimeDataBuffer, AnimePacketType,
|
||||
};
|
||||
use rog_types::supported::AnimeSupportedFunctions;
|
||||
use rusb::{Device, DeviceHandle};
|
||||
use std::error::Error;
|
||||
@@ -28,7 +19,7 @@ impl GetSupported for CtrlAnimeDisplay {
|
||||
type A = AnimeSupportedFunctions;
|
||||
|
||||
fn get_supported() -> Self::A {
|
||||
AnimeSupportedFunctions(CtrlAnimeDisplay::get_device(0x0b05, 0x193b).is_ok())
|
||||
AnimeSupportedFunctions(CtrlAnimeDisplay::get_device(VENDOR_ID, PROD_ID).is_ok())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,16 +27,6 @@ pub struct CtrlAnimeDisplay {
|
||||
handle: DeviceHandle<rusb::GlobalContext>,
|
||||
}
|
||||
|
||||
//AnimatrixWrite
|
||||
pub trait Dbus {
|
||||
/// Write a direct stream of data
|
||||
fn write(&self, input: AniMeDataBuffer);
|
||||
|
||||
fn set_on_off(&self, status: bool);
|
||||
|
||||
fn set_boot_on_off(&self, status: bool);
|
||||
}
|
||||
|
||||
impl crate::ZbusAdd for CtrlAnimeDisplay {
|
||||
fn add_to_server(self, server: &mut zbus::ObjectServer) {
|
||||
server
|
||||
@@ -62,30 +43,19 @@ impl crate::ZbusAdd for CtrlAnimeDisplay {
|
||||
}
|
||||
|
||||
#[dbus_interface(name = "org.asuslinux.Daemon")]
|
||||
impl Dbus for CtrlAnimeDisplay {
|
||||
impl CtrlAnimeDisplay {
|
||||
/// Writes a data stream of length
|
||||
fn write(&self, input: AniMeDataBuffer) {
|
||||
fn write(&self, input: AnimeDataBuffer) {
|
||||
self.write_data_buffer(input);
|
||||
}
|
||||
|
||||
fn set_on_off(&self, status: bool) {
|
||||
let mut buffer = [0u8; PACKET_SIZE];
|
||||
buffer[0] = DEV_PAGE;
|
||||
buffer[1] = WRITE;
|
||||
buffer[2] = ON_OFF;
|
||||
|
||||
if status {
|
||||
buffer[3] = 0x03;
|
||||
} else {
|
||||
buffer[3] = 0x00;
|
||||
}
|
||||
|
||||
self.write_bytes(&buffer);
|
||||
self.write_bytes(&pkt_for_set_on(status));
|
||||
}
|
||||
|
||||
fn set_boot_on_off(&self, status: bool) {
|
||||
self.do_set_boot(status);
|
||||
self.do_apply();
|
||||
fn set_boot_on_off(&self, on: bool) {
|
||||
self.write_bytes(&pkt_for_set_boot(on));
|
||||
self.write_bytes(&pkt_for_apply());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -115,7 +85,6 @@ impl CtrlAnimeDisplay {
|
||||
Ok(ctrl)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn get_device(vendor: u16, product: u16) -> Result<Device<rusb::GlobalContext>, rusb::Error> {
|
||||
for device in rusb::devices()?.iter() {
|
||||
let device_desc = device.device_descriptor()?;
|
||||
@@ -126,8 +95,6 @@ impl CtrlAnimeDisplay {
|
||||
Err(rusb::Error::NoDevice)
|
||||
}
|
||||
|
||||
/// Should only be used if the bytes you are writing are verified correct
|
||||
#[inline]
|
||||
fn write_bytes(&self, message: &[u8]) {
|
||||
match self.handle.write_control(
|
||||
0x21, // request_type
|
||||
@@ -144,63 +111,18 @@ impl CtrlAnimeDisplay {
|
||||
},
|
||||
}
|
||||
}
|
||||
#[inline]
|
||||
fn write_data_buffer(&self, buffer: AniMeDataBuffer) {
|
||||
let data = AniMePacketType::from(buffer);
|
||||
|
||||
fn write_data_buffer(&self, buffer: AnimeDataBuffer) {
|
||||
let data = AnimePacketType::from(buffer);
|
||||
for row in data.iter() {
|
||||
self.write_bytes(row);
|
||||
}
|
||||
self.do_flush();
|
||||
self.write_bytes(&pkt_for_flush());
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn do_initialization(&self) {
|
||||
let mut init = [0; PACKET_SIZE];
|
||||
init[0] = DEV_PAGE; // This is the USB page we're using throughout
|
||||
for (idx, byte) in INIT_STR.as_bytes().iter().enumerate() {
|
||||
init[idx + 1] = *byte
|
||||
}
|
||||
self.write_bytes(&init);
|
||||
|
||||
// clear the init array and write other init message
|
||||
for ch in init.iter_mut() {
|
||||
*ch = 0;
|
||||
}
|
||||
init[0] = DEV_PAGE; // write it to be sure?
|
||||
init[1] = INIT;
|
||||
|
||||
self.write_bytes(&init);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn do_flush(&self) {
|
||||
let mut flush = [0; PACKET_SIZE];
|
||||
flush[0] = DEV_PAGE;
|
||||
flush[1] = WRITE;
|
||||
flush[2] = 0x03;
|
||||
|
||||
self.write_bytes(&flush);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn do_set_boot(&self, status: bool) {
|
||||
let mut flush = [0; PACKET_SIZE];
|
||||
flush[0] = DEV_PAGE;
|
||||
flush[1] = SET;
|
||||
flush[2] = 0x01;
|
||||
flush[3] = if status { 0x00 } else { 0x80 };
|
||||
|
||||
self.write_bytes(&flush);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn do_apply(&self) {
|
||||
let mut flush = [0; PACKET_SIZE];
|
||||
flush[0] = DEV_PAGE;
|
||||
flush[1] = APPLY;
|
||||
flush[2] = 0x01;
|
||||
flush[3] = 0x80;
|
||||
|
||||
self.write_bytes(&flush);
|
||||
let pkts = pkts_for_init();
|
||||
self.write_bytes(&pkts[0]);
|
||||
self.write_bytes(&pkts[1]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,12 +62,6 @@ impl DbusKbdBacklight {
|
||||
}
|
||||
}
|
||||
|
||||
trait Dbus {
|
||||
fn set_led(&mut self, data: String);
|
||||
fn ledmode(&self) -> String;
|
||||
fn notify_led(&self, data: &str) -> zbus::Result<()>;
|
||||
}
|
||||
|
||||
impl crate::ZbusAdd for DbusKbdBacklight {
|
||||
fn add_to_server(self, server: &mut zbus::ObjectServer) {
|
||||
server
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
See https://blog.joshwalsh.me/asus-anime-matrix/ for details on how
|
||||
the diagonal layout works.
|
||||
|
||||
`diagonal-template.*` is provided from the website above. It is best to
|
||||
export the final file to 36px height - no scaling is done in asusd or
|
||||
rog-anime crate for diagonal displays.
|
||||
@@ -1,28 +1,31 @@
|
||||
[package]
|
||||
name = "rog_anime"
|
||||
version = "1.0.0"
|
||||
version = "1.0.2"
|
||||
license = "MPL-2.0"
|
||||
readme = "README.md"
|
||||
authors = ["Luke <luke@ljones.dev>"]
|
||||
repository = "https://gitlab.com/asus-linux/asus-nb-ctrl"
|
||||
homepage = "https://gitlab.com/asus-linux/asus-nb-ctrl"
|
||||
documentation = "https://docs.rs/rog-anime"
|
||||
description = "Types useful for translating images and other data for display on the ASUS AniMe Matrix display"
|
||||
keywords = ["ROG", "ASUS", "AniMe"]
|
||||
edition = "2018"
|
||||
exclude = ["data"]
|
||||
|
||||
[features]
|
||||
default = ["dbus"]
|
||||
dbus = ["zbus", "zvariant", "zvariant_derive"]
|
||||
|
||||
[dependencies]
|
||||
png_pong = "^0.8.0"
|
||||
pix = "0.13"
|
||||
gif = "^0.11.2"
|
||||
|
||||
|
||||
serde = "^1.0"
|
||||
serde_derive = "^1.0"
|
||||
zbus = "^1.9.1"
|
||||
zvariant = "^2.5"
|
||||
zvariant_derive = "^2.5"
|
||||
|
||||
glam = { version = "*", features = ["serde"] }
|
||||
glam = { version = "0.14.0", features = ["serde"] }
|
||||
|
||||
[features]
|
||||
default = ["z"]
|
||||
z = []
|
||||
zbus = { version = "^1.9.1", optional = true }
|
||||
zvariant = { version = "^2.6", optional = true }
|
||||
zvariant_derive = { version = "^2.6", optional = true }
|
||||
|
||||
@@ -1,56 +1,97 @@
|
||||
# rog-anime
|
||||
|
||||
## Features
|
||||
`rog-anime` is a crate for use with ASUS laptops that have an AniMe matrix display built in to them. The crate can be used with zbus to communicate with the `asusd` daemon from the project this crate is part of, or it can be used standalone to write the data directly to USB by transforming the data to USB HID packets using builtin functions.
|
||||
|
||||
`zbus` is enabled by default.
|
||||
Supported so far is:
|
||||
- Sequences of data,
|
||||
- Data can be:
|
||||
+ Image<scale, rotate, position>
|
||||
+ ASUS style gif
|
||||
+ Plain image type gif
|
||||
+ Pause
|
||||
- Create USB HID packets for writing to the device
|
||||
|
||||
This crate is mostly purpose built for use with [`asus-nb-ctrl`](https://gitlab.com/asus-linux/asus-nb-ctrl) which is a complete daemon and toolset for Linux on ASUS ROG/TUF machines, but can be used in general for example building a new controller for Windows OS.
|
||||
|
||||
## Feature enablement
|
||||
|
||||
`dbus` is enabled by default - this uses `zvariant` to enable sending some types over dbus interfaces.
|
||||
|
||||
## Example
|
||||
|
||||
```rust
|
||||
use std::{env, error::Error, path::Path, process::exit};
|
||||
|
||||
use rog_dbus::AuraDbusClient;
|
||||
use rog_anime::{
|
||||
anime_data::AniMeDataBuffer,
|
||||
anime_image::{AnimeImage, Vec2},
|
||||
use std::{
|
||||
env, error::Error, f32::consts::PI, path::Path, process::exit, thread::sleep, time::Duration,
|
||||
};
|
||||
|
||||
use rog_anime::{
|
||||
AniMeDataBuffer, {AniMeImage, Vec2},
|
||||
};
|
||||
use rog_dbus::AuraDbusClient;
|
||||
|
||||
fn main() -> Result<(), Box<dyn Error>> {
|
||||
let (client, _) = AuraDbusClient::new().unwrap();
|
||||
|
||||
let args: Vec<String> = env::args().into_iter().collect();
|
||||
if args.len() != 8 {
|
||||
println!(
|
||||
"Usage: <filepath> <x scale> <y scale> <angle> <x pos> <y pos> <fineness> <brightness>"
|
||||
);
|
||||
println!("e.g, asusctl/examples/doom_large.png 0.9 0.9 0.4 0.0 0.0, 0.8");
|
||||
println!("All args except path and fineness are floats");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
let image = AnimeImage::from_png(
|
||||
Path::new(&args[1]),
|
||||
Vec2::new(
|
||||
args[2].parse::<f32>().unwrap(),
|
||||
args[3].parse::<f32>().unwrap(),
|
||||
),
|
||||
args[4].parse::<f32>().unwrap(),
|
||||
Vec2::new(
|
||||
args[5].parse::<f32>().unwrap(),
|
||||
args[6].parse::<f32>().unwrap(),
|
||||
),
|
||||
args[7].parse::<f32>().unwrap(),
|
||||
let mut image = AniMeImage::from_png(
|
||||
Path::new("./doom.png"),
|
||||
0.9, // scale
|
||||
0.0, // rotation
|
||||
Vec2::new(0.0, 0.0), // position
|
||||
0.3, // brightness
|
||||
)?;
|
||||
|
||||
/// This data can also be written direct to the USB device by transforming with
|
||||
let data = AniMePacketType::from(image);
|
||||
let data = <AniMeDataBuffer>::from(&image);
|
||||
client
|
||||
.proxies()
|
||||
.anime()
|
||||
.write(data)
|
||||
.unwrap();
|
||||
loop {
|
||||
image.angle += 0.05;
|
||||
if image.angle > PI * 2.0 {
|
||||
image.angle = 0.0
|
||||
}
|
||||
image.update();
|
||||
|
||||
Ok(())
|
||||
client
|
||||
.proxies()
|
||||
.anime()
|
||||
.write(<AniMeDataBuffer>::from(&image))
|
||||
.unwrap();
|
||||
sleep(Duration::from_micros(500));
|
||||
}
|
||||
}
|
||||
```
|
||||
```
|
||||
|
||||
## Example, USB HID
|
||||
```rust
|
||||
let mut image = AniMeImage::from_png(
|
||||
Path::new("./doom.png"),
|
||||
0.9, // scale
|
||||
0.0, // rotation
|
||||
Vec2::new(0.0, 0.0), // position
|
||||
0.3, // brightness
|
||||
)?;
|
||||
|
||||
// convert to intermediate packet format
|
||||
let buffer = <AniMeDataBuffer>::from(&image)
|
||||
// then to USB HID
|
||||
let data = AniMePacketType::from(buffer);
|
||||
// and then write direct
|
||||
for packet in data.iter() {
|
||||
write_usb(packet); // some usb call here
|
||||
}
|
||||
```
|
||||
|
||||
## data
|
||||
|
||||
- `data/controller.gif` is an example ASUS diagonally orientated gif.
|
||||
- `data/diagonal-template.*` are templates for diagonal images or gifs.
|
||||
|
||||
See https://blog.joshwalsh.me/asus-anime-matrix/ for details on how
|
||||
the diagonal layout works.
|
||||
|
||||
`diagonal-template.*` is provided from the website above. It is best to
|
||||
export the final file to 36px height - no scaling is done in asusd or
|
||||
rog-anime crate for diagonal displays.
|
||||
|
||||
## TODO:
|
||||
- Diagonal font and text
|
||||
- General font and text
|
||||
- System info for Linux and Windows
|
||||
- Audio EQ visual for Linux and Windows
|
||||
- Time+Date display
|
||||
|
Before Width: | Height: | Size: 7.2 KiB After Width: | Height: | Size: 7.2 KiB |
|
Before Width: | Height: | Size: 323 KiB After Width: | Height: | Size: 323 KiB |
@@ -1,5 +1,5 @@
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
#[cfg(feature = "z")]
|
||||
#[cfg(feature = "dbus")]
|
||||
use zvariant_derive::Type;
|
||||
|
||||
/// The first 7 bytes of a USB packet are accounted for by `USB_PREFIX1` and `USB_PREFIX2`
|
||||
@@ -16,40 +16,51 @@ 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 = "z", derive(Type))]
|
||||
#[cfg_attr(feature = "dbus", derive(Type))]
|
||||
#[derive(Debug, Clone, Deserialize, Serialize)]
|
||||
pub struct AniMeDataBuffer(Vec<u8>);
|
||||
pub struct AnimeDataBuffer(Vec<u8>);
|
||||
|
||||
impl Default for AniMeDataBuffer {
|
||||
impl Default for AnimeDataBuffer {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl AniMeDataBuffer {
|
||||
impl AnimeDataBuffer {
|
||||
#[inline]
|
||||
pub fn new() -> Self {
|
||||
AniMeDataBuffer(vec![0u8; ANIME_DATA_LEN])
|
||||
AnimeDataBuffer(vec![0u8; ANIME_DATA_LEN])
|
||||
}
|
||||
|
||||
/// Get the inner data buffer
|
||||
#[inline]
|
||||
pub fn get(&self) -> &[u8] {
|
||||
&self.0
|
||||
}
|
||||
|
||||
/// Get a mutable slice of the inner buffer
|
||||
#[inline]
|
||||
pub fn get_mut(&mut self) -> &mut [u8] {
|
||||
&mut self.0
|
||||
}
|
||||
|
||||
/// Create from a vector of bytes
|
||||
///
|
||||
/// # Panics
|
||||
/// Will panic if the vector length is not `ANIME_DATA_LEN`
|
||||
#[inline]
|
||||
pub fn from_vec(input: Vec<u8>) -> Self {
|
||||
assert_eq!(input.len(), ANIME_DATA_LEN);
|
||||
Self(input)
|
||||
}
|
||||
}
|
||||
|
||||
/// The two packets to be written to USB
|
||||
pub type AniMePacketType = [[u8; 640]; 2];
|
||||
pub type AnimePacketType = [[u8; 640]; 2];
|
||||
|
||||
impl From<AniMeDataBuffer> for AniMePacketType {
|
||||
impl From<AnimeDataBuffer> for AnimePacketType {
|
||||
#[inline]
|
||||
fn from(anime: AniMeDataBuffer) -> Self {
|
||||
fn from(anime: AnimeDataBuffer) -> Self {
|
||||
assert!(anime.0.len() == ANIME_DATA_LEN);
|
||||
let mut buffers = [[0; 640]; 2];
|
||||
for (idx, chunk) in anime.0.as_slice().chunks(PANE_LEN).enumerate() {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use std::{path::Path, time::Duration};
|
||||
|
||||
use crate::{
|
||||
data::{AniMeDataBuffer, ANIME_DATA_LEN},
|
||||
data::{AnimeDataBuffer, ANIME_DATA_LEN},
|
||||
error::AnimeError,
|
||||
};
|
||||
|
||||
@@ -10,19 +10,22 @@ const HEIGHT: usize = 36;
|
||||
|
||||
/// Mostly intended to be used with ASUS gifs, but can be used for other purposes (like images)
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct AniMeDiagonal([[u8; WIDTH]; HEIGHT], Option<Duration>);
|
||||
pub struct AnimeDiagonal([[u8; WIDTH]; HEIGHT], Option<Duration>);
|
||||
|
||||
impl Default for AniMeDiagonal {
|
||||
impl Default for AnimeDiagonal {
|
||||
#[inline]
|
||||
fn default() -> Self {
|
||||
Self::new(None)
|
||||
}
|
||||
}
|
||||
|
||||
impl AniMeDiagonal {
|
||||
impl AnimeDiagonal {
|
||||
#[inline]
|
||||
pub fn new(duration: Option<Duration>) -> Self {
|
||||
Self([[0u8; WIDTH]; HEIGHT], duration)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn get_mut(&mut self) -> &mut [[u8; WIDTH]; HEIGHT] {
|
||||
&mut self.0
|
||||
}
|
||||
@@ -39,6 +42,7 @@ impl AniMeDiagonal {
|
||||
|
||||
/// Generate the base image from inputs. The result can be displayed as is or
|
||||
/// updated via scale, position, or angle then displayed again after `update()`.
|
||||
#[inline]
|
||||
pub fn from_png(
|
||||
path: &Path,
|
||||
duration: Option<Duration>,
|
||||
@@ -50,7 +54,7 @@ impl AniMeDiagonal {
|
||||
let decoder = png_pong::Decoder::new(data)?.into_steps();
|
||||
let png_pong::Step { raster, delay: _ } = decoder.last().ok_or(AnimeError::NoFrames)??;
|
||||
|
||||
let mut matrix = AniMeDiagonal::new(duration);
|
||||
let mut matrix = AnimeDiagonal::new(duration);
|
||||
|
||||
let width;
|
||||
match raster {
|
||||
@@ -70,11 +74,11 @@ impl AniMeDiagonal {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&AniMeDiagonal> for AniMeDataBuffer {
|
||||
/// Do conversion from the nested Vec in AniMeMatrix to the two required
|
||||
impl From<&AnimeDiagonal> for AnimeDataBuffer {
|
||||
/// Do conversion from the nested Vec in AnimeMatrix to the two required
|
||||
/// packets suitable for sending over USB
|
||||
#[inline]
|
||||
fn from(anime: &AniMeDiagonal) -> Self {
|
||||
fn from(anime: &AnimeDiagonal) -> Self {
|
||||
let mut buf = vec![0u8; ANIME_DATA_LEN];
|
||||
|
||||
buf[1..=32].copy_from_slice(&anime.get_row(0, 3, 32));
|
||||
@@ -133,6 +137,6 @@ impl From<&AniMeDiagonal> for AniMeDataBuffer {
|
||||
buf[1226..=1234].copy_from_slice(&anime.get_row(50, 0, 9));
|
||||
buf[1236..=1244].copy_from_slice(&anime.get_row(51, 0, 9));
|
||||
|
||||
AniMeDataBuffer::from_vec(buf)
|
||||
AnimeDataBuffer::from_vec(buf)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ use png_pong::decode::Error as PngError;
|
||||
use std::error::Error;
|
||||
use std::fmt;
|
||||
|
||||
#[cfg(feature = "z")]
|
||||
#[cfg(feature = "dbus")]
|
||||
use zbus::fdo;
|
||||
|
||||
#[derive(Debug)]
|
||||
@@ -15,12 +15,12 @@ pub enum AnimeError {
|
||||
Format,
|
||||
/// The input was incorrect size, expected size is `IncorrectSize(width, height)`
|
||||
IncorrectSize(u32, u32),
|
||||
#[cfg(feature = "z")]
|
||||
#[cfg(feature = "dbus")]
|
||||
Zbus(fdo::Error)
|
||||
}
|
||||
|
||||
impl fmt::Display for AnimeError {
|
||||
// This trait requires `fmt` with this exact signature.
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
AnimeError::NoFrames => write!(f, "No frames in PNG"),
|
||||
@@ -33,7 +33,7 @@ impl fmt::Display for AnimeError {
|
||||
"The input image size is incorrect, expected {}x{}",
|
||||
width, height
|
||||
),
|
||||
#[cfg(feature = "z")]
|
||||
#[cfg(feature = "dbus")]
|
||||
AnimeError::Zbus(e) => write!(f, "ZBUS error: {}", e),
|
||||
}
|
||||
}
|
||||
@@ -42,25 +42,29 @@ impl fmt::Display for AnimeError {
|
||||
impl Error for AnimeError {}
|
||||
|
||||
impl From<std::io::Error> for AnimeError {
|
||||
#[inline]
|
||||
fn from(err: std::io::Error) -> Self {
|
||||
AnimeError::Io(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<PngError> for AnimeError {
|
||||
#[inline]
|
||||
fn from(err: PngError) -> Self {
|
||||
AnimeError::Png(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<DecodingError> for AnimeError {
|
||||
#[inline]
|
||||
fn from(err: DecodingError) -> Self {
|
||||
AnimeError::Gif(err)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "z")]
|
||||
#[cfg(feature = "dbus")]
|
||||
impl From<AnimeError> for fdo::Error {
|
||||
#[inline]
|
||||
fn from(err: AnimeError) -> Self {
|
||||
fdo::Error::Failed(format!("{}", err))
|
||||
}
|
||||
|
||||
@@ -2,35 +2,43 @@ use glam::Vec2;
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use std::{fs::File, path::Path, time::Duration};
|
||||
|
||||
use crate::{error::AnimeError, AniMeDataBuffer, AniMeDiagonal, AniMeImage, Pixel};
|
||||
use crate::{error::AnimeError, AnimeDataBuffer, AnimeDiagonal, AnimeImage, Pixel};
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, Serialize)]
|
||||
pub struct AniMeFrame {
|
||||
pub struct AnimeFrame {
|
||||
/// Precomputed data for the frame. This can be transferred directly to the
|
||||
/// the `asusd` daemon over dbus or converted to USB packet with `AniMePacketType::from(buffer)`
|
||||
data: AniMeDataBuffer,
|
||||
/// the `asusd` daemon over dbus or converted to USB packet with `AnimePacketType::from(buffer)`
|
||||
data: AnimeDataBuffer,
|
||||
delay: Duration,
|
||||
}
|
||||
|
||||
impl AniMeFrame {
|
||||
pub fn frame(&self) -> &AniMeDataBuffer {
|
||||
impl AnimeFrame {
|
||||
/// Get the inner data buffer of the gif frame
|
||||
#[inline]
|
||||
pub fn frame(&self) -> &AnimeDataBuffer {
|
||||
&self.data
|
||||
}
|
||||
|
||||
/// Get the `Duration` of the delay for this frame
|
||||
#[inline]
|
||||
pub fn delay(&self) -> Duration {
|
||||
self.delay
|
||||
}
|
||||
}
|
||||
|
||||
/// Defines the time or animation cycle count to use for a gif
|
||||
#[derive(Debug, Copy, Clone, Deserialize, Serialize)]
|
||||
pub enum AnimTime {
|
||||
/// Time in milliseconds for animation to run
|
||||
Time(Duration),
|
||||
/// How many full animation loops to run
|
||||
Cycles(u32),
|
||||
/// Run for infinite time
|
||||
Infinite,
|
||||
}
|
||||
|
||||
impl Default for AnimTime {
|
||||
#[inline]
|
||||
fn default() -> Self {
|
||||
Self::Infinite
|
||||
}
|
||||
@@ -39,16 +47,17 @@ 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)]
|
||||
pub struct AniMeGif(Vec<AniMeFrame>, AnimTime);
|
||||
pub struct AnimeGif(Vec<AnimeFrame>, AnimTime);
|
||||
|
||||
impl AniMeGif {
|
||||
impl AnimeGif {
|
||||
/// Create an animation using the 74x36 ASUS gif format
|
||||
#[inline]
|
||||
pub fn create_diagonal_gif(
|
||||
file_name: &Path,
|
||||
duration: AnimTime,
|
||||
brightness: f32,
|
||||
) -> Result<Self, AnimeError> {
|
||||
let mut matrix = AniMeDiagonal::new(None);
|
||||
let mut matrix = AnimeDiagonal::new(None);
|
||||
|
||||
let mut decoder = gif::DecodeOptions::new();
|
||||
// Configure the decoder such that it will expand the image to RGBA.
|
||||
@@ -74,8 +83,8 @@ impl AniMeGif {
|
||||
}
|
||||
}
|
||||
|
||||
frames.push(AniMeFrame {
|
||||
data: <AniMeDataBuffer>::from(&matrix),
|
||||
frames.push(AnimeFrame {
|
||||
data: <AnimeDataBuffer>::from(&matrix),
|
||||
delay: Duration::from_millis(wait as u64),
|
||||
});
|
||||
}
|
||||
@@ -84,6 +93,7 @@ impl AniMeGif {
|
||||
|
||||
/// Create an animation using a gif of any size. This method must precompute the
|
||||
/// result.
|
||||
#[inline]
|
||||
pub fn create_png_gif(
|
||||
file_name: &Path,
|
||||
scale: f32,
|
||||
@@ -105,7 +115,7 @@ impl AniMeGif {
|
||||
let width = decoder.width();
|
||||
let pixels: Vec<Pixel> =
|
||||
vec![Pixel::default(); (decoder.width() as u32 * decoder.height() as u32) as usize];
|
||||
let mut image = AniMeImage::new(
|
||||
let mut image = AnimeImage::new(
|
||||
Vec2::new(scale, scale),
|
||||
angle,
|
||||
translation,
|
||||
@@ -119,7 +129,7 @@ impl AniMeGif {
|
||||
if matches!(frame.dispose, gif::DisposalMethod::Background) {
|
||||
let pixels: Vec<Pixel> =
|
||||
vec![Pixel::default(); (width as u32 * height as u32) as usize];
|
||||
image = AniMeImage::new(
|
||||
image = AnimeImage::new(
|
||||
Vec2::new(scale, scale),
|
||||
angle,
|
||||
translation,
|
||||
@@ -144,18 +154,22 @@ impl AniMeGif {
|
||||
}
|
||||
image.update();
|
||||
|
||||
frames.push(AniMeFrame {
|
||||
data: <AniMeDataBuffer>::from(&image),
|
||||
frames.push(AnimeFrame {
|
||||
data: <AnimeDataBuffer>::from(&image),
|
||||
delay: Duration::from_millis(wait as u64),
|
||||
});
|
||||
}
|
||||
Ok(Self(frames, duration))
|
||||
}
|
||||
|
||||
pub fn frames(&self) -> &[AniMeFrame] {
|
||||
/// Get a slice of the frames this gif has
|
||||
#[inline]
|
||||
pub fn frames(&self) -> &[AnimeFrame] {
|
||||
&self.0
|
||||
}
|
||||
|
||||
/// Get the time/count for this gif
|
||||
#[inline]
|
||||
pub fn duration(&self) -> AnimTime {
|
||||
self.1
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use std::time::Duration;
|
||||
|
||||
use crate::data::{AniMeDataBuffer, ANIME_DATA_LEN};
|
||||
use crate::data::{AnimeDataBuffer, ANIME_DATA_LEN};
|
||||
use crate::image::LED_IMAGE_POSITIONS;
|
||||
|
||||
const WIDTH: usize = 33;
|
||||
@@ -8,35 +8,45 @@ const HEIGHT: usize = 55;
|
||||
|
||||
/// Helper structure for writing images.
|
||||
///
|
||||
/// See the examples for ways to write an image to `AniMeMatrix` format.
|
||||
/// See the examples for ways to write an image to `AnimeMatrix` format.
|
||||
/// Width = 33
|
||||
/// height = 55
|
||||
///
|
||||
/// **Note:** the columns in each odd row are offset by half a pixel left
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct AniMeGrid([[u8; WIDTH]; HEIGHT], Option<Duration>);
|
||||
pub struct AnimeGrid([[u8; WIDTH]; HEIGHT], Option<Duration>);
|
||||
|
||||
impl Default for AniMeGrid {
|
||||
impl Default for AnimeGrid {
|
||||
#[inline]
|
||||
fn default() -> Self {
|
||||
Self::new(None)
|
||||
}
|
||||
}
|
||||
|
||||
impl AniMeGrid {
|
||||
impl AnimeGrid {
|
||||
#[inline]
|
||||
pub fn new(duration: Option<Duration>) -> Self {
|
||||
AniMeGrid([[0u8; WIDTH]; HEIGHT], duration)
|
||||
AnimeGrid([[0u8; WIDTH]; HEIGHT], duration)
|
||||
}
|
||||
|
||||
/// Set a position in the grid with a brightness value
|
||||
#[inline]
|
||||
pub fn set(&mut self, x: usize, y: usize, b: u8) {
|
||||
self.0[y][x] = b;
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn get(&self) -> &[[u8; WIDTH]; HEIGHT] {
|
||||
&self.0
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn get_mut(&mut self) -> &mut [[u8; WIDTH]; HEIGHT] {
|
||||
&mut self.0
|
||||
}
|
||||
|
||||
/// Fill the grid with a value
|
||||
#[inline]
|
||||
pub fn fill_with(&mut self, fill: u8) {
|
||||
for row in self.0.iter_mut() {
|
||||
for x in row.iter_mut() {
|
||||
@@ -79,11 +89,11 @@ impl AniMeGrid {
|
||||
// }
|
||||
}
|
||||
|
||||
impl From<AniMeGrid> for AniMeDataBuffer {
|
||||
impl From<AnimeGrid> for AnimeDataBuffer {
|
||||
/// Do conversion from the nested Vec in AniMeMatrix to the two required
|
||||
/// packets suitable for sending over USB
|
||||
#[inline]
|
||||
fn from(anime: AniMeGrid) -> Self {
|
||||
fn from(anime: AnimeGrid) -> Self {
|
||||
let mut buf = vec![0u8; ANIME_DATA_LEN];
|
||||
|
||||
for (idx, pos) in LED_IMAGE_POSITIONS.iter().enumerate() {
|
||||
@@ -93,7 +103,7 @@ impl From<AniMeGrid> for AniMeDataBuffer {
|
||||
buf[idx + 1] = anime.0[y][x];
|
||||
}
|
||||
}
|
||||
AniMeDataBuffer::from_vec(buf)
|
||||
AnimeDataBuffer::from_vec(buf)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -103,7 +113,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn check_data_alignment() {
|
||||
let mut matrix = AniMeGrid::new(None);
|
||||
let mut matrix = AnimeGrid::new(None);
|
||||
{
|
||||
let tmp = matrix.get_mut();
|
||||
for row in tmp.iter_mut() {
|
||||
@@ -112,7 +122,7 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
let matrix = <AniMeDataBuffer>::from(matrix);
|
||||
let matrix = <AnimeDataBuffer>::from(matrix);
|
||||
|
||||
let data_cmp = [
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
|
||||
@@ -4,12 +4,13 @@ pub use glam::Vec2;
|
||||
use glam::{Mat3, Vec3};
|
||||
|
||||
use crate::{
|
||||
data::{AniMeDataBuffer, ANIME_DATA_LEN},
|
||||
data::{AnimeDataBuffer, ANIME_DATA_LEN},
|
||||
error::AnimeError,
|
||||
};
|
||||
|
||||
const LED_PIXEL_LEN: usize = 1244;
|
||||
|
||||
/// A single greyscale + alpha pixel in the image
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub(crate) struct Pixel {
|
||||
pub color: u32,
|
||||
@@ -17,6 +18,7 @@ pub(crate) struct Pixel {
|
||||
}
|
||||
|
||||
impl Default for Pixel {
|
||||
#[inline]
|
||||
fn default() -> Self {
|
||||
Pixel {
|
||||
color: 0,
|
||||
@@ -58,10 +60,11 @@ impl Led {
|
||||
/// Container of `Led`, each of which specifies a position within the image
|
||||
/// The main use of this is to position and sample colours for the final image
|
||||
/// to show on AniMe
|
||||
pub struct AniMeImage {
|
||||
pub struct AnimeImage {
|
||||
pub scale: Vec2,
|
||||
/// Angle in radians
|
||||
pub angle: f32,
|
||||
/// Position of the image ont he display
|
||||
pub translation: Vec2,
|
||||
/// Brightness of final image, `0.0` = off, `1.0` = full
|
||||
pub bright: f32,
|
||||
@@ -69,10 +72,11 @@ pub struct AniMeImage {
|
||||
led_pos: [Option<Led>; LED_PIXEL_LEN],
|
||||
/// THe image data for sampling
|
||||
img_pixels: Vec<Pixel>,
|
||||
/// width of the image
|
||||
width: u32,
|
||||
}
|
||||
|
||||
impl AniMeImage {
|
||||
impl AnimeImage {
|
||||
pub(crate) const fn new(
|
||||
scale: Vec2,
|
||||
angle: f32,
|
||||
@@ -119,6 +123,7 @@ impl AniMeImage {
|
||||
36 - (y + 1) / 2
|
||||
}
|
||||
|
||||
/// Physical display width
|
||||
fn phys_width() -> f32 {
|
||||
(32.0 - -0.5 + 1.0) * Self::scale_x()
|
||||
}
|
||||
@@ -128,10 +133,12 @@ impl AniMeImage {
|
||||
55
|
||||
}
|
||||
|
||||
/// Physical display height
|
||||
fn phys_height() -> f32 {
|
||||
(54.0 + 1.0) * Self::scale_y()
|
||||
}
|
||||
|
||||
/// Find the actual width of the data including the dead pixels
|
||||
const fn pitch(y: u32) -> u32 {
|
||||
match y {
|
||||
0 | 2 | 4 => 33,
|
||||
@@ -145,12 +152,13 @@ impl AniMeImage {
|
||||
}
|
||||
|
||||
/// Really only used to generate the output for including as a full const in `LED_IMAGE_POSITIONS`
|
||||
#[inline]
|
||||
pub fn generate() -> Vec<Option<Led>> {
|
||||
(0..AniMeImage::height())
|
||||
(0..AnimeImage::height())
|
||||
.flat_map(|y| {
|
||||
(0..AniMeImage::pitch(y)).map(move |l| {
|
||||
if l < AniMeImage::width(y) {
|
||||
let x = AniMeImage::first_x(y) + l;
|
||||
(0..AnimeImage::pitch(y)).map(move |l| {
|
||||
if l < AnimeImage::width(y) {
|
||||
let x = AnimeImage::first_x(y) + l;
|
||||
Some(Led::new(x as f32 - 0.5 * (y % 2) as f32, y as f32))
|
||||
} else {
|
||||
None
|
||||
@@ -163,6 +171,7 @@ impl AniMeImage {
|
||||
/// Called after setting new angle, position, or scale to refresh the image
|
||||
/// samples, the result can then been transformed to the appropriate data
|
||||
/// for displaying
|
||||
#[inline]
|
||||
pub fn update(&mut self) {
|
||||
let width = self.width as i32;
|
||||
let height = self.img_pixels.len() as i32 / width;
|
||||
@@ -204,12 +213,13 @@ impl AniMeImage {
|
||||
}
|
||||
}
|
||||
|
||||
/// Put the render window in place on the image
|
||||
fn put(&self, bmp_w: f32, bmp_h: f32) -> Mat3 {
|
||||
// Center of image
|
||||
let center = Mat3::from_translation(Vec2::new(-0.5 * bmp_w, -0.5 * bmp_h));
|
||||
// Find the scale required for cleanly showing the image
|
||||
let h = AniMeImage::phys_height() / bmp_h;
|
||||
let mut base_scale = AniMeImage::phys_width() / bmp_w;
|
||||
let h = AnimeImage::phys_height() / bmp_h;
|
||||
let mut base_scale = AnimeImage::phys_width() / bmp_w;
|
||||
if base_scale > h {
|
||||
base_scale = h;
|
||||
}
|
||||
@@ -217,8 +227,8 @@ impl AniMeImage {
|
||||
let cm_from_px = Mat3::from_scale(Vec2::new(base_scale, base_scale));
|
||||
|
||||
let led_from_cm = Mat3::from_scale(Vec2::new(
|
||||
1.0 / AniMeImage::scale_x(),
|
||||
1.0 / AniMeImage::scale_y(),
|
||||
1.0 / AnimeImage::scale_x(),
|
||||
1.0 / AnimeImage::scale_y(),
|
||||
));
|
||||
|
||||
let transform =
|
||||
@@ -233,6 +243,7 @@ impl AniMeImage {
|
||||
|
||||
/// Generate the base image from inputs. The result can be displayed as is or
|
||||
/// updated via scale, position, or angle then displayed again after `update()`.
|
||||
#[inline]
|
||||
pub fn from_png(
|
||||
path: &Path,
|
||||
scale: f32,
|
||||
@@ -261,7 +272,7 @@ impl AniMeImage {
|
||||
_ => return Err(AnimeError::Format),
|
||||
};
|
||||
|
||||
let mut matrix = AniMeImage::new(
|
||||
let mut matrix = AnimeImage::new(
|
||||
Vec2::new(scale, scale),
|
||||
angle,
|
||||
translation,
|
||||
@@ -275,11 +286,11 @@ impl AniMeImage {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&AniMeImage> for AniMeDataBuffer {
|
||||
impl From<&AnimeImage> for AnimeDataBuffer {
|
||||
/// Do conversion from the nested Vec in AniMeMatrix to the two required
|
||||
/// packets suitable for sending over USB
|
||||
#[inline]
|
||||
fn from(leds: &AniMeImage) -> Self {
|
||||
fn from(leds: &AnimeImage) -> Self {
|
||||
let mut l: Vec<u8> = leds
|
||||
.led_pos
|
||||
.iter()
|
||||
@@ -289,7 +300,7 @@ impl From<&AniMeImage> for AniMeDataBuffer {
|
||||
v.push(0);
|
||||
v.append(&mut l);
|
||||
v.append(&mut vec![0u8; 9]);
|
||||
AniMeDataBuffer::from_vec(v)
|
||||
AnimeDataBuffer::from_vec(v)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1550,7 +1561,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn led_positions() {
|
||||
let leds = AniMeImage::generate();
|
||||
let leds = AnimeImage::generate();
|
||||
assert_eq!(leds[0], Some(Led(0.0, 0.0, 0)));
|
||||
assert_eq!(leds[1], Some(Led(1.0, 0.0, 0)));
|
||||
assert_eq!(leds[2], Some(Led(2.0, 0.0, 0)));
|
||||
@@ -1579,7 +1590,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn led_positions_const() {
|
||||
let leds = AniMeImage::generate();
|
||||
let leds = AnimeImage::generate();
|
||||
assert_eq!(leds[1], LED_IMAGE_POSITIONS[1]);
|
||||
assert_eq!(leds[34], LED_IMAGE_POSITIONS[34]);
|
||||
assert_eq!(leds[69], LED_IMAGE_POSITIONS[69]);
|
||||
@@ -1593,44 +1604,44 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn row_starts() {
|
||||
assert_eq!(AniMeImage::first_x(5), 0);
|
||||
assert_eq!(AniMeImage::first_x(6), 0);
|
||||
assert_eq!(AniMeImage::first_x(7), 1);
|
||||
assert_eq!(AniMeImage::first_x(8), 1);
|
||||
assert_eq!(AniMeImage::first_x(9), 2);
|
||||
assert_eq!(AniMeImage::first_x(10), 2);
|
||||
assert_eq!(AniMeImage::first_x(11), 3);
|
||||
assert_eq!(AnimeImage::first_x(5), 0);
|
||||
assert_eq!(AnimeImage::first_x(6), 0);
|
||||
assert_eq!(AnimeImage::first_x(7), 1);
|
||||
assert_eq!(AnimeImage::first_x(8), 1);
|
||||
assert_eq!(AnimeImage::first_x(9), 2);
|
||||
assert_eq!(AnimeImage::first_x(10), 2);
|
||||
assert_eq!(AnimeImage::first_x(11), 3);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn row_widths() {
|
||||
assert_eq!(AniMeImage::width(5), 33);
|
||||
assert_eq!(AniMeImage::width(6), 33);
|
||||
assert_eq!(AniMeImage::width(7), 32);
|
||||
assert_eq!(AniMeImage::width(8), 32);
|
||||
assert_eq!(AniMeImage::width(9), 31);
|
||||
assert_eq!(AniMeImage::width(10), 31);
|
||||
assert_eq!(AniMeImage::width(11), 30);
|
||||
assert_eq!(AniMeImage::width(12), 30);
|
||||
assert_eq!(AniMeImage::width(13), 29);
|
||||
assert_eq!(AniMeImage::width(14), 29);
|
||||
assert_eq!(AniMeImage::width(15), 28);
|
||||
assert_eq!(AniMeImage::width(16), 28);
|
||||
assert_eq!(AniMeImage::width(17), 27);
|
||||
assert_eq!(AniMeImage::width(18), 27);
|
||||
assert_eq!(AnimeImage::width(5), 33);
|
||||
assert_eq!(AnimeImage::width(6), 33);
|
||||
assert_eq!(AnimeImage::width(7), 32);
|
||||
assert_eq!(AnimeImage::width(8), 32);
|
||||
assert_eq!(AnimeImage::width(9), 31);
|
||||
assert_eq!(AnimeImage::width(10), 31);
|
||||
assert_eq!(AnimeImage::width(11), 30);
|
||||
assert_eq!(AnimeImage::width(12), 30);
|
||||
assert_eq!(AnimeImage::width(13), 29);
|
||||
assert_eq!(AnimeImage::width(14), 29);
|
||||
assert_eq!(AnimeImage::width(15), 28);
|
||||
assert_eq!(AnimeImage::width(16), 28);
|
||||
assert_eq!(AnimeImage::width(17), 27);
|
||||
assert_eq!(AnimeImage::width(18), 27);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn row_pitch() {
|
||||
assert_eq!(AniMeImage::pitch(5), 34);
|
||||
assert_eq!(AniMeImage::pitch(6), 33);
|
||||
assert_eq!(AniMeImage::pitch(7), 33);
|
||||
assert_eq!(AniMeImage::pitch(8), 32);
|
||||
assert_eq!(AniMeImage::pitch(9), 32);
|
||||
assert_eq!(AniMeImage::pitch(10), 31);
|
||||
assert_eq!(AniMeImage::pitch(11), 31);
|
||||
assert_eq!(AniMeImage::pitch(12), 30);
|
||||
assert_eq!(AniMeImage::pitch(13), 30);
|
||||
assert_eq!(AniMeImage::pitch(14), 29);
|
||||
assert_eq!(AnimeImage::pitch(5), 34);
|
||||
assert_eq!(AnimeImage::pitch(6), 33);
|
||||
assert_eq!(AnimeImage::pitch(7), 33);
|
||||
assert_eq!(AnimeImage::pitch(8), 32);
|
||||
assert_eq!(AnimeImage::pitch(9), 32);
|
||||
assert_eq!(AnimeImage::pitch(10), 31);
|
||||
assert_eq!(AnimeImage::pitch(11), 31);
|
||||
assert_eq!(AnimeImage::pitch(12), 30);
|
||||
assert_eq!(AnimeImage::pitch(13), 30);
|
||||
assert_eq!(AnimeImage::pitch(14), 29);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
/// The main data conversion for transfering in shortform over dbus or other,
|
||||
/// or writing directly to the USB device
|
||||
mod data;
|
||||
|
||||
pub use data::*;
|
||||
|
||||
/// Useful for specialised effects that required a grid of data
|
||||
/// Useful for specialised effects that require a grid of data
|
||||
mod grid;
|
||||
pub use grid::*;
|
||||
|
||||
@@ -12,14 +11,23 @@ pub use grid::*;
|
||||
mod image;
|
||||
pub use image::*;
|
||||
|
||||
/// A grid of data that is intended to be read out and displayed on the ANiMe as
|
||||
/// a diagonal
|
||||
mod diagonal;
|
||||
pub use diagonal::*;
|
||||
|
||||
/// A gif. Can be created from the ASUS gifs which are diagonal layout, or from
|
||||
/// any standard gif
|
||||
mod gif;
|
||||
pub use crate::gif::*;
|
||||
|
||||
/// A container of images/grids/gifs/pauses which can be iterated over to generate
|
||||
/// cool effects
|
||||
mod sequencer;
|
||||
pub use sequencer::*;
|
||||
|
||||
/// Base errors that are possible
|
||||
pub mod error;
|
||||
|
||||
/// Provides const methods to create the USB HID control packets
|
||||
pub mod usb;
|
||||
@@ -6,8 +6,10 @@ use std::{
|
||||
use glam::Vec2;
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
|
||||
use crate::{error::AnimeError, AniMeDataBuffer, AniMeGif, AniMeImage, AnimTime};
|
||||
use crate::{error::AnimeError, AnimeDataBuffer, AnimeGif, AnimeImage, AnimTime};
|
||||
|
||||
/// All the possible AniMe actions that can be used. This enum is intended to be
|
||||
/// a helper for loading up `ActionData`.
|
||||
#[derive(Debug, Clone, Deserialize, Serialize)]
|
||||
pub enum AnimeAction {
|
||||
/// Full gif sequence. Immutable.
|
||||
@@ -36,13 +38,14 @@ pub enum AnimeAction {
|
||||
Pause(Duration),
|
||||
}
|
||||
|
||||
///
|
||||
/// All the possible AniMe actions that can be used. The enum is intended to be
|
||||
/// used in a array allowing the user to cycle through a series of actions.
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
pub enum ActionData {
|
||||
/// Full gif sequence. Immutable.
|
||||
Animation(AniMeGif),
|
||||
Animation(AnimeGif),
|
||||
/// Basic image, can have properties changed and image updated via those properties
|
||||
Image(Box<AniMeDataBuffer>),
|
||||
Image(Box<AnimeDataBuffer>),
|
||||
/// A pause to be used between sequences
|
||||
Pause(Duration),
|
||||
/// Placeholder
|
||||
@@ -55,15 +58,19 @@ pub enum ActionData {
|
||||
Matrix,
|
||||
}
|
||||
|
||||
/// An optimised precomputed set of actions
|
||||
/// An optimised precomputed set of actions that the user can cycle through
|
||||
#[derive(Debug, Deserialize, Serialize, Default)]
|
||||
pub struct Sequences(Vec<ActionData>);
|
||||
|
||||
impl Sequences {
|
||||
#[inline]
|
||||
pub fn new() -> Self {
|
||||
Self(Vec::new())
|
||||
}
|
||||
|
||||
/// Use a base `AnimeAction` to generate the precomputed data and insert in to
|
||||
/// the run buffer
|
||||
#[inline]
|
||||
pub fn insert(&mut self, index: usize, action: &AnimeAction) -> Result<(), AnimeError> {
|
||||
match action {
|
||||
AnimeAction::AsusAnimation {
|
||||
@@ -99,6 +106,10 @@ impl Sequences {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Remove an item at this position from the run buffer. If the `index` supplied
|
||||
/// is not in range then `None` is returned, otherwise the `ActionData` at that location
|
||||
/// is yeeted and returned.
|
||||
#[inline]
|
||||
pub fn remove_item(&mut self, index: usize) -> Option<ActionData> {
|
||||
if index < self.0.len() {
|
||||
return Some(self.0.remove(index));
|
||||
@@ -116,7 +127,7 @@ impl Sequences {
|
||||
if index > self.0.len() {
|
||||
index = self.0.len() - 1;
|
||||
}
|
||||
let frames = AniMeGif::create_diagonal_gif(file, duration, brightness)?;
|
||||
let frames = AnimeGif::create_diagonal_gif(file, duration, brightness)?;
|
||||
self.0.insert(index, ActionData::Animation(frames));
|
||||
Ok(())
|
||||
}
|
||||
@@ -133,8 +144,8 @@ impl Sequences {
|
||||
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);
|
||||
let image = AnimeImage::from_png(file, scale, angle, translation, brightness)?;
|
||||
let data = <AnimeDataBuffer>::from(&image);
|
||||
self.0.insert(index, ActionData::Image(Box::new(data)));
|
||||
Ok(())
|
||||
}
|
||||
@@ -154,7 +165,7 @@ impl Sequences {
|
||||
index = self.0.len() - 1;
|
||||
}
|
||||
let frames =
|
||||
AniMeGif::create_png_gif(file, scale, angle, translation, duration, brightness)?;
|
||||
AnimeGif::create_png_gif(file, scale, angle, translation, duration, brightness)?;
|
||||
self.0.insert(index, ActionData::Animation(frames));
|
||||
Ok(())
|
||||
}
|
||||
@@ -174,6 +185,7 @@ impl Sequences {
|
||||
}
|
||||
}
|
||||
|
||||
/// Iteractor helper for iterating over all the actions in `Sequences`
|
||||
pub struct ActionIterator<'a> {
|
||||
actions: &'a Sequences,
|
||||
next_idx: usize,
|
||||
@@ -182,6 +194,7 @@ pub struct ActionIterator<'a> {
|
||||
impl<'a> Iterator for ActionIterator<'a> {
|
||||
type Item = &'a ActionData;
|
||||
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<&'a ActionData> {
|
||||
if self.next_idx == self.actions.0.len() {
|
||||
self.next_idx = 0;
|
||||
|
||||
79
rog-anime/src/usb.rs
Normal file
79
rog-anime/src/usb.rs
Normal file
@@ -0,0 +1,79 @@
|
||||
//! Utils for writing to the AniMe USB device
|
||||
//!
|
||||
//! Use of the device requires a few steps:
|
||||
//! 1. Initialise the device by writing the two packets from `get_init_packets()`
|
||||
//! 2. Write data from `AnimePacketType`
|
||||
//! 3. Write the packet from `get_flush_packet()`, which tells the device to display the data from step 2
|
||||
//!
|
||||
//! Step 1 need to applied only on fresh system boot.
|
||||
|
||||
const INIT_STR: [u8; 15] = [
|
||||
0x5e, b'A', b'S', b'U', b'S', b' ', b'T', b'E', b'C', b'H', b'.', b'I', b'N', b'C', b'.',
|
||||
];
|
||||
const PACKET_SIZE: usize = 640;
|
||||
const DEV_PAGE: u8 = 0x5e;
|
||||
pub const VENDOR_ID: u16 = 0x0b05;
|
||||
pub const PROD_ID: u16 = 0x193b;
|
||||
|
||||
/// Get the two device initialization packets. These are required for device start
|
||||
/// after the laptop boots.
|
||||
#[inline]
|
||||
pub const fn pkts_for_init() -> [[u8; PACKET_SIZE]; 2] {
|
||||
let mut packets = [[0; PACKET_SIZE]; 2];
|
||||
packets[0][0] = DEV_PAGE; // This is the USB page we're using throughout
|
||||
let mut count = 0;
|
||||
while count < INIT_STR.len() {
|
||||
packets[0][count] = INIT_STR[count];
|
||||
count +=1;
|
||||
}
|
||||
//
|
||||
packets[1][0] = DEV_PAGE; // write it to be sure?
|
||||
packets[1][1] = 0xc2;
|
||||
packets
|
||||
}
|
||||
|
||||
/// Should be written to the device after writing the two main data packets that
|
||||
/// make up the display data packet
|
||||
#[inline]
|
||||
pub const fn pkt_for_flush() -> [u8; PACKET_SIZE] {
|
||||
let mut pkt = [0; PACKET_SIZE];
|
||||
pkt[0] = DEV_PAGE;
|
||||
pkt[1] = 0xc0;
|
||||
pkt[2] = 0x03;
|
||||
pkt
|
||||
}
|
||||
|
||||
/// Get the packet required for setting the device to on, on boot. Requires
|
||||
/// pkt_for_apply()` to be written after.
|
||||
#[inline]
|
||||
pub const fn pkt_for_set_boot(status: bool) -> [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.
|
||||
#[inline]
|
||||
pub const fn pkt_for_set_on(on: bool) -> [u8; PACKET_SIZE] {
|
||||
let mut pkt = [0; PACKET_SIZE];
|
||||
pkt[0] = DEV_PAGE;
|
||||
pkt[1] = 0xc0;
|
||||
pkt[2] = 0x04;
|
||||
pkt[3] = if on { 0x03 } else { 0x00 };
|
||||
pkt
|
||||
}
|
||||
|
||||
/// Packet required to apply a device setting
|
||||
#[inline]
|
||||
pub const fn pkt_for_apply() -> [u8; PACKET_SIZE] {
|
||||
let mut pkt = [0; PACKET_SIZE];
|
||||
pkt[0] = DEV_PAGE;
|
||||
pkt[1] = 0xc4;
|
||||
pkt[2] = 0x01;
|
||||
pkt[3] = 0x80;
|
||||
pkt
|
||||
}
|
||||
@@ -19,7 +19,7 @@
|
||||
//!
|
||||
//! …consequently `zbus-xmlgen` did not generate code for the above interfaces.
|
||||
|
||||
use rog_anime::AniMeDataBuffer;
|
||||
use rog_anime::AnimeDataBuffer;
|
||||
use zbus::{dbus_proxy, Connection, Result};
|
||||
|
||||
#[dbus_proxy(
|
||||
@@ -60,7 +60,7 @@ impl<'a> AnimeProxy<'a> {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn write(&self, input: AniMeDataBuffer) -> Result<()> {
|
||||
pub fn write(&self, input: AnimeDataBuffer) -> Result<()> {
|
||||
self.0.write(input.get())
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user