11 files changed
+484
-43
No files matched your search
@@ -12,4 +12,5 @@ hidapi = "2.6.6"
|
|||||||
|
|
||||||
[features]
|
[features]
|
||||||
access_hid_wrapper = []
|
access_hid_wrapper = []
|
||||||
|
preset_file_saving = []
|
||||||
fast_controller_experimental = []
|
fast_controller_experimental = []
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
#[derive(Default)]
|
#[derive(Default, PartialEq, Debug)]
|
||||||
pub struct Color {
|
pub struct Color {
|
||||||
pub red: u8,
|
pub red: u8,
|
||||||
pub green: u8,
|
pub green: u8,
|
||||||
|
|||||||
@@ -2,6 +2,8 @@ mod color;
|
|||||||
mod hid_wrapper;
|
mod hid_wrapper;
|
||||||
mod keymap;
|
mod keymap;
|
||||||
mod rgb_controller;
|
mod rgb_controller;
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests;
|
||||||
|
|
||||||
pub use color::Color;
|
pub use color::Color;
|
||||||
pub use hid_wrapper::HidWrapperError;
|
pub use hid_wrapper::HidWrapperError;
|
||||||
@@ -11,6 +13,12 @@ pub use rgb_controller::effect_info::{
|
|||||||
DirectionPolicy, EFFECTS, EffectInfo, HorizontalDirections, VerticalDirections,
|
DirectionPolicy, EFFECTS, EffectInfo, HorizontalDirections, VerticalDirections,
|
||||||
};
|
};
|
||||||
pub use rgb_controller::effects::Effects;
|
pub use rgb_controller::effects::Effects;
|
||||||
|
pub use rgb_controller::preset::Preset;
|
||||||
|
|
||||||
|
#[cfg(feature = "preset_file_saving")]
|
||||||
|
mod save_preset;
|
||||||
|
#[cfg(feature = "preset_file_saving")]
|
||||||
|
pub use save_preset::{LoadPresetError, SavePresetError};
|
||||||
|
|
||||||
#[cfg(feature = "access_hid_wrapper")]
|
#[cfg(feature = "access_hid_wrapper")]
|
||||||
pub use hid_wrapper::HidWrapper;
|
pub use hid_wrapper::HidWrapper;
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
pub mod controller;
|
pub mod controller;
|
||||||
pub mod effect_info;
|
pub mod effect_info;
|
||||||
pub mod effects;
|
pub mod effects;
|
||||||
|
pub mod preset;
|
||||||
@@ -2,8 +2,8 @@ use crate::Color;
|
|||||||
use crate::Effects;
|
use crate::Effects;
|
||||||
use crate::HidWrapperError;
|
use crate::HidWrapperError;
|
||||||
use crate::Keymap;
|
use crate::Keymap;
|
||||||
|
use crate::Preset;
|
||||||
use crate::hid_wrapper::HidWrapper;
|
use crate::hid_wrapper::HidWrapper;
|
||||||
use crate::rgb_controller::effects::Effect;
|
|
||||||
|
|
||||||
pub struct RGBController {
|
pub struct RGBController {
|
||||||
hid_wrapper: HidWrapper,
|
hid_wrapper: HidWrapper,
|
||||||
@@ -225,7 +225,7 @@ impl RGBController {
|
|||||||
speed: u8,
|
speed: u8,
|
||||||
direction: u8,
|
direction: u8,
|
||||||
keymap: Option<[[u8; 3]; 144]>,
|
keymap: Option<[[u8; 3]; 144]>,
|
||||||
) -> Result<Effect, HidWrapperError> {
|
) -> Result<Preset, HidWrapperError> {
|
||||||
self.hid_wrapper.open_device()?;
|
self.hid_wrapper.open_device()?;
|
||||||
|
|
||||||
self.prepare_device()?;
|
self.prepare_device()?;
|
||||||
@@ -264,7 +264,7 @@ impl RGBController {
|
|||||||
|
|
||||||
self.hid_wrapper.close_device();
|
self.hid_wrapper.close_device();
|
||||||
|
|
||||||
Ok(Effect {
|
Ok(Preset {
|
||||||
effect,
|
effect,
|
||||||
color,
|
color,
|
||||||
full_color,
|
full_color,
|
||||||
@@ -280,7 +280,7 @@ impl RGBController {
|
|||||||
color: Color,
|
color: Color,
|
||||||
brightness: u8,
|
brightness: u8,
|
||||||
full_color: Option<bool>,
|
full_color: Option<bool>,
|
||||||
) -> Result<Effect, HidWrapperError> {
|
) -> Result<Preset, HidWrapperError> {
|
||||||
self.set_effect(
|
self.set_effect(
|
||||||
Effects::Static,
|
Effects::Static,
|
||||||
color,
|
color,
|
||||||
@@ -298,7 +298,7 @@ impl RGBController {
|
|||||||
brightness: u8,
|
brightness: u8,
|
||||||
speed: u8,
|
speed: u8,
|
||||||
full_color: Option<bool>,
|
full_color: Option<bool>,
|
||||||
) -> Result<Effect, HidWrapperError> {
|
) -> Result<Preset, HidWrapperError> {
|
||||||
self.set_effect(
|
self.set_effect(
|
||||||
Effects::SingleOff,
|
Effects::SingleOff,
|
||||||
color,
|
color,
|
||||||
@@ -316,7 +316,7 @@ impl RGBController {
|
|||||||
brightness: u8,
|
brightness: u8,
|
||||||
speed: u8,
|
speed: u8,
|
||||||
full_color: Option<bool>,
|
full_color: Option<bool>,
|
||||||
) -> Result<Effect, HidWrapperError> {
|
) -> Result<Preset, HidWrapperError> {
|
||||||
self.set_effect(
|
self.set_effect(
|
||||||
Effects::SingleOn,
|
Effects::SingleOn,
|
||||||
color,
|
color,
|
||||||
@@ -334,7 +334,7 @@ impl RGBController {
|
|||||||
brightness: u8,
|
brightness: u8,
|
||||||
speed: u8,
|
speed: u8,
|
||||||
full_color: Option<bool>,
|
full_color: Option<bool>,
|
||||||
) -> Result<Effect, HidWrapperError> {
|
) -> Result<Preset, HidWrapperError> {
|
||||||
self.set_effect(
|
self.set_effect(
|
||||||
Effects::Glittering,
|
Effects::Glittering,
|
||||||
color,
|
color,
|
||||||
@@ -352,7 +352,7 @@ impl RGBController {
|
|||||||
brightness: u8,
|
brightness: u8,
|
||||||
speed: u8,
|
speed: u8,
|
||||||
full_color: Option<bool>,
|
full_color: Option<bool>,
|
||||||
) -> Result<Effect, HidWrapperError> {
|
) -> Result<Preset, HidWrapperError> {
|
||||||
self.set_effect(
|
self.set_effect(
|
||||||
Effects::Rain,
|
Effects::Rain,
|
||||||
color,
|
color,
|
||||||
@@ -368,7 +368,7 @@ impl RGBController {
|
|||||||
&mut self,
|
&mut self,
|
||||||
brightness: u8,
|
brightness: u8,
|
||||||
speed: u8,
|
speed: u8,
|
||||||
) -> Result<Effect, HidWrapperError> {
|
) -> Result<Preset, HidWrapperError> {
|
||||||
self.set_effect(
|
self.set_effect(
|
||||||
Effects::Colorful,
|
Effects::Colorful,
|
||||||
Color::default(),
|
Color::default(),
|
||||||
@@ -386,7 +386,7 @@ impl RGBController {
|
|||||||
brightness: u8,
|
brightness: u8,
|
||||||
speed: u8,
|
speed: u8,
|
||||||
full_color: Option<bool>,
|
full_color: Option<bool>,
|
||||||
) -> Result<Effect, HidWrapperError> {
|
) -> Result<Preset, HidWrapperError> {
|
||||||
self.set_effect(
|
self.set_effect(
|
||||||
Effects::Breath,
|
Effects::Breath,
|
||||||
color,
|
color,
|
||||||
@@ -402,7 +402,7 @@ impl RGBController {
|
|||||||
&mut self,
|
&mut self,
|
||||||
brightness: u8,
|
brightness: u8,
|
||||||
speed: u8,
|
speed: u8,
|
||||||
) -> Result<Effect, HidWrapperError> {
|
) -> Result<Preset, HidWrapperError> {
|
||||||
self.set_effect(
|
self.set_effect(
|
||||||
Effects::Spectrum,
|
Effects::Spectrum,
|
||||||
Color::default(),
|
Color::default(),
|
||||||
@@ -420,7 +420,7 @@ impl RGBController {
|
|||||||
brightness: u8,
|
brightness: u8,
|
||||||
speed: u8,
|
speed: u8,
|
||||||
full_color: Option<bool>,
|
full_color: Option<bool>,
|
||||||
) -> Result<Effect, HidWrapperError> {
|
) -> Result<Preset, HidWrapperError> {
|
||||||
self.set_effect(
|
self.set_effect(
|
||||||
Effects::CentrifugalWave,
|
Effects::CentrifugalWave,
|
||||||
color,
|
color,
|
||||||
@@ -439,7 +439,7 @@ impl RGBController {
|
|||||||
speed: u8,
|
speed: u8,
|
||||||
direction: u8,
|
direction: u8,
|
||||||
full_color: Option<bool>,
|
full_color: Option<bool>,
|
||||||
) -> Result<Effect, HidWrapperError> {
|
) -> Result<Preset, HidWrapperError> {
|
||||||
self.set_effect(
|
self.set_effect(
|
||||||
Effects::VerticalWave,
|
Effects::VerticalWave,
|
||||||
color,
|
color,
|
||||||
@@ -458,7 +458,7 @@ impl RGBController {
|
|||||||
speed: u8,
|
speed: u8,
|
||||||
direction: u8,
|
direction: u8,
|
||||||
full_color: Option<bool>,
|
full_color: Option<bool>,
|
||||||
) -> Result<Effect, HidWrapperError> {
|
) -> Result<Preset, HidWrapperError> {
|
||||||
self.set_effect(
|
self.set_effect(
|
||||||
Effects::HorizontalWave,
|
Effects::HorizontalWave,
|
||||||
color,
|
color,
|
||||||
@@ -476,7 +476,7 @@ impl RGBController {
|
|||||||
brightness: u8,
|
brightness: u8,
|
||||||
speed: u8,
|
speed: u8,
|
||||||
full_color: Option<bool>,
|
full_color: Option<bool>,
|
||||||
) -> Result<Effect, HidWrapperError> {
|
) -> Result<Preset, HidWrapperError> {
|
||||||
self.set_effect(
|
self.set_effect(
|
||||||
Effects::Rotating,
|
Effects::Rotating,
|
||||||
color,
|
color,
|
||||||
@@ -494,7 +494,7 @@ impl RGBController {
|
|||||||
brightness: u8,
|
brightness: u8,
|
||||||
speed: u8,
|
speed: u8,
|
||||||
full_color: Option<bool>,
|
full_color: Option<bool>,
|
||||||
) -> Result<Effect, HidWrapperError> {
|
) -> Result<Preset, HidWrapperError> {
|
||||||
self.set_effect(
|
self.set_effect(
|
||||||
Effects::Explosion,
|
Effects::Explosion,
|
||||||
color,
|
color,
|
||||||
@@ -512,7 +512,7 @@ impl RGBController {
|
|||||||
brightness: u8,
|
brightness: u8,
|
||||||
speed: u8,
|
speed: u8,
|
||||||
full_color: Option<bool>,
|
full_color: Option<bool>,
|
||||||
) -> Result<Effect, HidWrapperError> {
|
) -> Result<Preset, HidWrapperError> {
|
||||||
self.set_effect(
|
self.set_effect(
|
||||||
Effects::Launch,
|
Effects::Launch,
|
||||||
color,
|
color,
|
||||||
@@ -530,7 +530,7 @@ impl RGBController {
|
|||||||
brightness: u8,
|
brightness: u8,
|
||||||
speed: u8,
|
speed: u8,
|
||||||
full_color: Option<bool>,
|
full_color: Option<bool>,
|
||||||
) -> Result<Effect, HidWrapperError> {
|
) -> Result<Preset, HidWrapperError> {
|
||||||
self.set_effect(
|
self.set_effect(
|
||||||
Effects::Ripples,
|
Effects::Ripples,
|
||||||
color,
|
color,
|
||||||
@@ -548,7 +548,7 @@ impl RGBController {
|
|||||||
brightness: u8,
|
brightness: u8,
|
||||||
speed: u8,
|
speed: u8,
|
||||||
full_color: Option<bool>,
|
full_color: Option<bool>,
|
||||||
) -> Result<Effect, HidWrapperError> {
|
) -> Result<Preset, HidWrapperError> {
|
||||||
self.set_effect(
|
self.set_effect(
|
||||||
Effects::Snake,
|
Effects::Snake,
|
||||||
color,
|
color,
|
||||||
@@ -566,7 +566,7 @@ impl RGBController {
|
|||||||
brightness: u8,
|
brightness: u8,
|
||||||
speed: u8,
|
speed: u8,
|
||||||
full_color: Option<bool>,
|
full_color: Option<bool>,
|
||||||
) -> Result<Effect, HidWrapperError> {
|
) -> Result<Preset, HidWrapperError> {
|
||||||
self.set_effect(
|
self.set_effect(
|
||||||
Effects::Pulse,
|
Effects::Pulse,
|
||||||
color,
|
color,
|
||||||
@@ -584,7 +584,7 @@ impl RGBController {
|
|||||||
brightness: u8,
|
brightness: u8,
|
||||||
speed: u8,
|
speed: u8,
|
||||||
full_color: Option<bool>,
|
full_color: Option<bool>,
|
||||||
) -> Result<Effect, HidWrapperError> {
|
) -> Result<Preset, HidWrapperError> {
|
||||||
self.set_effect(
|
self.set_effect(
|
||||||
Effects::Tilt,
|
Effects::Tilt,
|
||||||
color,
|
color,
|
||||||
@@ -602,7 +602,7 @@ impl RGBController {
|
|||||||
brightness: u8,
|
brightness: u8,
|
||||||
speed: u8,
|
speed: u8,
|
||||||
full_color: Option<bool>,
|
full_color: Option<bool>,
|
||||||
) -> Result<Effect, HidWrapperError> {
|
) -> Result<Preset, HidWrapperError> {
|
||||||
self.set_effect(
|
self.set_effect(
|
||||||
Effects::Shuttle,
|
Effects::Shuttle,
|
||||||
color,
|
color,
|
||||||
@@ -618,7 +618,7 @@ impl RGBController {
|
|||||||
&mut self,
|
&mut self,
|
||||||
brightness: u8,
|
brightness: u8,
|
||||||
keymap: Keymap,
|
keymap: Keymap,
|
||||||
) -> Result<Effect, HidWrapperError> {
|
) -> Result<Preset, HidWrapperError> {
|
||||||
self.set_effect(
|
self.set_effect(
|
||||||
Effects::StaticPerKey,
|
Effects::StaticPerKey,
|
||||||
Color::default(),
|
Color::default(),
|
||||||
|
|||||||
@@ -1,15 +1,17 @@
|
|||||||
use crate::Effects;
|
use crate::Effects;
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
pub struct EffectInfo<'a> {
|
pub struct EffectInfo<'a> {
|
||||||
name: &'a str,
|
pub name: &'a str,
|
||||||
effect: Effects,
|
pub effect: Effects,
|
||||||
can_set_color: bool,
|
pub can_set_color: bool,
|
||||||
can_set_speed: bool,
|
pub can_set_speed: bool,
|
||||||
can_set_direction: DirectionPolicy,
|
pub can_set_direction: DirectionPolicy,
|
||||||
can_set_full_color: bool,
|
pub can_set_full_color: bool,
|
||||||
requires_keymap: bool,
|
pub requires_keymap: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(PartialEq, Clone)]
|
||||||
pub enum DirectionPolicy {
|
pub enum DirectionPolicy {
|
||||||
None,
|
None,
|
||||||
Horizontal01,
|
Horizontal01,
|
||||||
|
|||||||
@@ -4,10 +4,10 @@ use Effects::{
|
|||||||
VerticalWave,
|
VerticalWave,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::Color;
|
|
||||||
|
|
||||||
/// Effects of the keyboard
|
/// Effects of the keyboard
|
||||||
|
#[derive(Clone, Default, PartialEq, Debug)]
|
||||||
pub enum Effects {
|
pub enum Effects {
|
||||||
|
#[default]
|
||||||
Static,
|
Static,
|
||||||
SingleOn,
|
SingleOn,
|
||||||
SingleOff,
|
SingleOff,
|
||||||
@@ -83,13 +83,3 @@ impl Effects {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Effect {
|
|
||||||
pub effect: Effects,
|
|
||||||
pub color: Color,
|
|
||||||
pub full_color: bool,
|
|
||||||
pub brightness: u8,
|
|
||||||
pub speed: u8,
|
|
||||||
pub direction: u8,
|
|
||||||
pub keymap: Option<[[u8; 3]; 144]>,
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
use crate::Color;
|
||||||
|
use crate::Effects;
|
||||||
|
|
||||||
|
#[derive(PartialEq, Debug)]
|
||||||
|
pub struct Preset {
|
||||||
|
pub effect: Effects,
|
||||||
|
pub color: Color,
|
||||||
|
pub full_color: bool,
|
||||||
|
pub brightness: u8,
|
||||||
|
pub speed: u8,
|
||||||
|
pub direction: u8,
|
||||||
|
pub keymap: Option<[[u8; 3]; 144]>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Preset {
|
||||||
|
pub fn new(
|
||||||
|
effect: Effects,
|
||||||
|
color: Color,
|
||||||
|
full_color: bool,
|
||||||
|
brightness: u8,
|
||||||
|
speed: u8,
|
||||||
|
direction: u8,
|
||||||
|
keymap: Option<[[u8; 3]; 144]>,
|
||||||
|
) -> Self {
|
||||||
|
Self {
|
||||||
|
effect,
|
||||||
|
color,
|
||||||
|
full_color,
|
||||||
|
brightness: brightness.clamp(0, 16),
|
||||||
|
speed: speed.clamp(1, 16),
|
||||||
|
direction: direction.clamp(0, 3),
|
||||||
|
keymap,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_valid(&self) -> bool {
|
||||||
|
self.brightness <= 16 && self.direction <= 3 && 1 <= self.speed && self.speed <= 16
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Preset {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::new(
|
||||||
|
Default::default(),
|
||||||
|
Default::default(),
|
||||||
|
Default::default(),
|
||||||
|
Default::default(),
|
||||||
|
Default::default(),
|
||||||
|
Default::default(),
|
||||||
|
Default::default(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,148 @@
|
|||||||
|
use crate::{DirectionPolicy, EFFECTS, EffectInfo, Effects, Preset};
|
||||||
|
use std::{
|
||||||
|
collections::VecDeque,
|
||||||
|
fs::File,
|
||||||
|
io::{Read, Write},
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum SavePresetError {
|
||||||
|
InvalidPreset,
|
||||||
|
FileError(std::io::Error),
|
||||||
|
NoKeymapGiven,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum LoadPresetError {
|
||||||
|
InvalidOrCorruptedFile,
|
||||||
|
OpenFileError(std::io::Error),
|
||||||
|
}
|
||||||
|
|
||||||
|
const MAGIC_NUMBER_1: u8 = 0b10100100;
|
||||||
|
const MAGIC_NUMBER_2: u8 = 0b00010000;
|
||||||
|
const VERSION: u8 = 1;
|
||||||
|
|
||||||
|
impl Preset {
|
||||||
|
pub fn save_to_file(&self, _file: &mut File) -> Result<(), SavePresetError> {
|
||||||
|
if !self.is_valid() {
|
||||||
|
return Err(SavePresetError::InvalidPreset);
|
||||||
|
}
|
||||||
|
match _file.write_all(&self._encode_to_buffer()?) {
|
||||||
|
Err(err) => Err(SavePresetError::FileError(err)),
|
||||||
|
_ => Ok(()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn _encode_to_buffer(&self) -> Result<Vec<u8>, SavePresetError> {
|
||||||
|
let effect_info: EffectInfo = EFFECTS[usize::from(self.effect.to_u8() - 1)].clone();
|
||||||
|
let mut buffer: Vec<u8> = vec![MAGIC_NUMBER_1, MAGIC_NUMBER_2, VERSION];
|
||||||
|
|
||||||
|
buffer
|
||||||
|
.push(self.effect.to_u8() + (u8::from(self.full_color) * 128) + (self.direction * 32)); //Effect id, full_color, and direction in a single byte
|
||||||
|
|
||||||
|
if !self.full_color && effect_info.can_set_color {
|
||||||
|
buffer.extend(&self.color.to_array());
|
||||||
|
}
|
||||||
|
|
||||||
|
if effect_info.can_set_speed {
|
||||||
|
buffer.push(self.speed);
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer.push(self.brightness);
|
||||||
|
|
||||||
|
if effect_info.requires_keymap {
|
||||||
|
for key_color in self.keymap.ok_or(SavePresetError::NoKeymapGiven)?.iter() {
|
||||||
|
buffer.extend(key_color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(buffer)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn load_from_file(_file: &mut File) -> Result<Self, LoadPresetError> {
|
||||||
|
let mut buffer: Vec<u8> = vec![];
|
||||||
|
match _file.read_to_end(&mut buffer) {
|
||||||
|
Ok(_) => {
|
||||||
|
let mut buffer: VecDeque<u8> = buffer.into();
|
||||||
|
|
||||||
|
Self::_decode_from_buffer(&mut buffer)
|
||||||
|
}
|
||||||
|
Err(err) => Err(LoadPresetError::OpenFileError(err)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn _decode_from_buffer(buffer: &mut VecDeque<u8>) -> Result<Self, LoadPresetError> {
|
||||||
|
let mut save: Preset = Default::default();
|
||||||
|
|
||||||
|
if buffer.pop_front() != Some(MAGIC_NUMBER_1) || buffer.pop_front() != Some(MAGIC_NUMBER_2)
|
||||||
|
{
|
||||||
|
return Err(LoadPresetError::InvalidOrCorruptedFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
if buffer
|
||||||
|
.pop_front()
|
||||||
|
.ok_or(LoadPresetError::InvalidOrCorruptedFile)?
|
||||||
|
!= VERSION
|
||||||
|
{
|
||||||
|
return Err(LoadPresetError::InvalidOrCorruptedFile);
|
||||||
|
//todo!("TOO BAD, Invalid VERSION")
|
||||||
|
}
|
||||||
|
|
||||||
|
let effect_byte = buffer
|
||||||
|
.pop_front()
|
||||||
|
.ok_or(LoadPresetError::InvalidOrCorruptedFile)?;
|
||||||
|
|
||||||
|
save.full_color = (effect_byte & 0b1000_0000) != 0;
|
||||||
|
let direction: u8 = (effect_byte >> 5) & 0b11;
|
||||||
|
let effect_id: u8 = effect_byte & 0b0001_1111;
|
||||||
|
|
||||||
|
save.effect = Effects::from_u8(effect_id).ok_or(LoadPresetError::InvalidOrCorruptedFile)?;
|
||||||
|
let effect_info: EffectInfo = EFFECTS[usize::from(save.effect.to_u8() - 1)].clone();
|
||||||
|
|
||||||
|
if !save.full_color && effect_info.can_set_color {
|
||||||
|
save.color.red = buffer
|
||||||
|
.pop_front()
|
||||||
|
.ok_or(LoadPresetError::InvalidOrCorruptedFile)?;
|
||||||
|
save.color.green = buffer
|
||||||
|
.pop_front()
|
||||||
|
.ok_or(LoadPresetError::InvalidOrCorruptedFile)?;
|
||||||
|
save.color.blue = buffer
|
||||||
|
.pop_front()
|
||||||
|
.ok_or(LoadPresetError::InvalidOrCorruptedFile)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
if effect_info.can_set_direction != DirectionPolicy::None {
|
||||||
|
save.direction = direction;
|
||||||
|
}
|
||||||
|
|
||||||
|
if effect_info.can_set_speed {
|
||||||
|
save.speed = buffer
|
||||||
|
.pop_front()
|
||||||
|
.ok_or(LoadPresetError::InvalidOrCorruptedFile)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
save.brightness = buffer
|
||||||
|
.pop_front()
|
||||||
|
.ok_or(LoadPresetError::InvalidOrCorruptedFile)?;
|
||||||
|
|
||||||
|
if effect_info.requires_keymap {
|
||||||
|
let mut keymap_buffer: [[u8; 3]; 144] = [[0; 3]; 144];
|
||||||
|
#[allow(clippy::needless_range_loop)]
|
||||||
|
for i in 0..keymap_buffer.len() {
|
||||||
|
keymap_buffer[i] = [
|
||||||
|
buffer
|
||||||
|
.pop_front()
|
||||||
|
.ok_or(LoadPresetError::InvalidOrCorruptedFile)?,
|
||||||
|
buffer
|
||||||
|
.pop_front()
|
||||||
|
.ok_or(LoadPresetError::InvalidOrCorruptedFile)?,
|
||||||
|
buffer
|
||||||
|
.pop_front()
|
||||||
|
.ok_or(LoadPresetError::InvalidOrCorruptedFile)?,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
save.keymap = Some(keymap_buffer);
|
||||||
|
}
|
||||||
|
Ok(save)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
#[cfg(feature = "preset_file_saving")]
|
||||||
|
mod preset_saving;
|
||||||
@@ -0,0 +1,236 @@
|
|||||||
|
#[allow(unused_imports)]
|
||||||
|
mod tests {
|
||||||
|
use std::collections::VecDeque;
|
||||||
|
|
||||||
|
use crate::{Keymap, Preset};
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_encode_decode() {
|
||||||
|
let preset = Preset::new(
|
||||||
|
crate::Effects::Static,
|
||||||
|
crate::Color {
|
||||||
|
red: 0,
|
||||||
|
green: 0,
|
||||||
|
blue: 0,
|
||||||
|
},
|
||||||
|
true,
|
||||||
|
6,
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
let mut buffer: VecDeque<u8> = preset._encode_to_buffer().expect("error encoding").into();
|
||||||
|
assert_eq!(
|
||||||
|
preset,
|
||||||
|
Preset::_decode_from_buffer(&mut buffer).expect("error decoding")
|
||||||
|
);
|
||||||
|
|
||||||
|
let preset = Preset::new(
|
||||||
|
crate::Effects::VerticalWave,
|
||||||
|
crate::Color {
|
||||||
|
red: 0,
|
||||||
|
green: 0,
|
||||||
|
blue: 0,
|
||||||
|
},
|
||||||
|
true,
|
||||||
|
2,
|
||||||
|
9,
|
||||||
|
2,
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
let mut buffer: VecDeque<u8> = preset._encode_to_buffer().expect("error encoding").into();
|
||||||
|
assert_eq!(
|
||||||
|
preset,
|
||||||
|
Preset::_decode_from_buffer(&mut buffer).expect("error decoding")
|
||||||
|
);
|
||||||
|
|
||||||
|
let preset = Preset::new(
|
||||||
|
crate::Effects::HorizontalWave,
|
||||||
|
crate::Color {
|
||||||
|
red: 67,
|
||||||
|
green: 69,
|
||||||
|
blue: 255,
|
||||||
|
},
|
||||||
|
false,
|
||||||
|
2,
|
||||||
|
9,
|
||||||
|
1,
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
let mut buffer: VecDeque<u8> = preset._encode_to_buffer().expect("error encoding").into();
|
||||||
|
assert_eq!(
|
||||||
|
preset,
|
||||||
|
Preset::_decode_from_buffer(&mut buffer).expect("error decoding")
|
||||||
|
);
|
||||||
|
|
||||||
|
let mut keymap: Keymap = Default::default();
|
||||||
|
keymap.set_all_keys(crate::Color {
|
||||||
|
red: 255,
|
||||||
|
green: 9,
|
||||||
|
blue: 7,
|
||||||
|
});
|
||||||
|
keymap.set_key(
|
||||||
|
crate::KeymapKeys::C,
|
||||||
|
crate::Color {
|
||||||
|
red: 111,
|
||||||
|
green: 222,
|
||||||
|
blue: 133,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
keymap.set_key(
|
||||||
|
crate::KeymapKeys::NumPlus,
|
||||||
|
crate::Color {
|
||||||
|
red: 112,
|
||||||
|
green: 223,
|
||||||
|
blue: 134,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
let preset = Preset::new(
|
||||||
|
crate::Effects::StaticPerKey,
|
||||||
|
crate::Color {
|
||||||
|
red: 0,
|
||||||
|
green: 0,
|
||||||
|
blue: 0,
|
||||||
|
},
|
||||||
|
false,
|
||||||
|
16,
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
Some(keymap.map()),
|
||||||
|
);
|
||||||
|
let mut buffer: VecDeque<u8> = preset._encode_to_buffer().expect("error encoding").into();
|
||||||
|
assert_eq!(
|
||||||
|
preset,
|
||||||
|
Preset::_decode_from_buffer(&mut buffer).expect("error decoding")
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
#[test]
|
||||||
|
fn test_save_load() {
|
||||||
|
use std::fs::{File};
|
||||||
|
use std::fs;
|
||||||
|
|
||||||
|
let preset = Preset::new(
|
||||||
|
crate::Effects::Static,
|
||||||
|
crate::Color {
|
||||||
|
red: 0,
|
||||||
|
green: 0,
|
||||||
|
blue: 0,
|
||||||
|
},
|
||||||
|
true,
|
||||||
|
6,
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
preset
|
||||||
|
.save_to_file(&mut File::create("/tmp/test_file.gk1k").expect("Failed to create file"))
|
||||||
|
.expect("failed to save");
|
||||||
|
assert_eq!(
|
||||||
|
preset,
|
||||||
|
Preset::load_from_file(
|
||||||
|
&mut File::open("/tmp/test_file.gk1k").expect("failed to open file")
|
||||||
|
)
|
||||||
|
.expect("error loading from file")
|
||||||
|
);
|
||||||
|
|
||||||
|
let preset = Preset::new(
|
||||||
|
crate::Effects::VerticalWave,
|
||||||
|
crate::Color {
|
||||||
|
red: 0,
|
||||||
|
green: 0,
|
||||||
|
blue: 0,
|
||||||
|
},
|
||||||
|
true,
|
||||||
|
2,
|
||||||
|
9,
|
||||||
|
2,
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
preset
|
||||||
|
.save_to_file(&mut File::create("/tmp/test_file.gk1k").expect("Failed to create file"))
|
||||||
|
.expect("failed to save");
|
||||||
|
assert_eq!(
|
||||||
|
preset,
|
||||||
|
Preset::load_from_file(
|
||||||
|
&mut File::open("/tmp/test_file.gk1k").expect("failed to open file")
|
||||||
|
)
|
||||||
|
.expect("error loading from file")
|
||||||
|
);
|
||||||
|
|
||||||
|
let preset = Preset::new(
|
||||||
|
crate::Effects::HorizontalWave,
|
||||||
|
crate::Color {
|
||||||
|
red: 67,
|
||||||
|
green: 69,
|
||||||
|
blue: 255,
|
||||||
|
},
|
||||||
|
false,
|
||||||
|
2,
|
||||||
|
9,
|
||||||
|
1,
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
preset
|
||||||
|
.save_to_file(&mut File::create("/tmp/test_file.gk1k").expect("Failed to create file"))
|
||||||
|
.expect("failed to save");
|
||||||
|
assert_eq!(
|
||||||
|
preset,
|
||||||
|
Preset::load_from_file(
|
||||||
|
&mut File::open("/tmp/test_file.gk1k").expect("failed to open file")
|
||||||
|
)
|
||||||
|
.expect("error loading from file")
|
||||||
|
);
|
||||||
|
|
||||||
|
let mut keymap: Keymap = Default::default();
|
||||||
|
keymap.set_all_keys(crate::Color {
|
||||||
|
red: 255,
|
||||||
|
green: 9,
|
||||||
|
blue: 7,
|
||||||
|
});
|
||||||
|
keymap.set_key(
|
||||||
|
crate::KeymapKeys::C,
|
||||||
|
crate::Color {
|
||||||
|
red: 111,
|
||||||
|
green: 222,
|
||||||
|
blue: 133,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
keymap.set_key(
|
||||||
|
crate::KeymapKeys::NumPlus,
|
||||||
|
crate::Color {
|
||||||
|
red: 112,
|
||||||
|
green: 223,
|
||||||
|
blue: 134,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
let preset = Preset::new(
|
||||||
|
crate::Effects::StaticPerKey,
|
||||||
|
crate::Color {
|
||||||
|
red: 0,
|
||||||
|
green: 0,
|
||||||
|
blue: 0,
|
||||||
|
},
|
||||||
|
false,
|
||||||
|
16,
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
Some(keymap.map()),
|
||||||
|
);
|
||||||
|
preset
|
||||||
|
.save_to_file(&mut File::create("/tmp/test_file.gk1k").expect("Failed to create file"))
|
||||||
|
.expect("failed to save");
|
||||||
|
assert_eq!(
|
||||||
|
preset,
|
||||||
|
Preset::load_from_file(
|
||||||
|
&mut File::open("/tmp/test_file.gk1k").expect("failed to open file")
|
||||||
|
)
|
||||||
|
.expect("error loading from file")
|
||||||
|
);
|
||||||
|
|
||||||
|
#[allow(unused_must_use)]
|
||||||
|
fs::remove_file("/tmp/test_file.gk1k");
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in new issue
Block a user