ROGCC: effect visuals. daemon: support TUF RGB

This commit is contained in:
Luke D. Jones
2022-08-02 14:25:27 +12:00
parent ba4589f986
commit 3e244d7d3d
17 changed files with 525 additions and 194 deletions

View File

@@ -8,7 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added
- `rog-control-center` has now been moved in to the main workspace due to
the heavy dependencies on most of the rog crates
- Preliminary support of TUF RGB keyboards + power states
## [4.3.0] - 2022-07-21
### Added

View File

@@ -56,7 +56,6 @@ pub struct AuraEnabled {
// fn from_str(s: &str) -> Result<Self, Self::Err> {
// let s = s.to_lowercase();
// dbg!(s);
// Ok(Self {
// help: false,
// keyboard: None,

View File

@@ -11,7 +11,7 @@ use profiles_cli::{FanCurveCommand, ProfileCommand};
use rog_anime::usb::get_anime_type;
use rog_anime::{AnimTime, AnimeDataBuffer, AnimeDiagonal, AnimeGif, AnimeImage, Vec2};
use rog_aura::usb::{AuraDev1866, AuraDev19b6, AuraDevice, AuraPowerDev};
use rog_aura::usb::{AuraDev1866, AuraDev19b6, AuraDevTuf, AuraDevice, AuraPowerDev};
use rog_aura::{self, AuraEffect};
use rog_dbus::RogDbusClientBlocking;
use rog_profiles::error::ProfileError;
@@ -162,7 +162,10 @@ fn do_parsed(
for command in commands.iter().filter(|command| {
if !matches!(
supported.keyboard_led.prod_id,
AuraDevice::X1854 | AuraDevice::X1869 | AuraDevice::X1866
AuraDevice::X1854
| AuraDevice::X1869
| AuraDevice::X1866
| AuraDevice::Tuf
) && command.trim().starts_with("led-pow-1")
{
return false;
@@ -458,14 +461,27 @@ fn handle_led_power1(
return Ok(());
}
if !matches!(
if matches!(
supported.prod_id,
AuraDevice::X1854 | AuraDevice::X1869 | AuraDevice::X1866
) {
println!("These options are for keyboards of product ID 0x1866 only");
handle_led_power_1_do_1866(dbus, power)?;
return Ok(());
}
if matches!(supported.prod_id, AuraDevice::Tuf) {
handle_led_power_1_do_tuf(dbus, power)?;
return Ok(());
}
println!("These options are for keyboards of product ID 0x1866 or TUF only");
return Ok(());
}
fn handle_led_power_1_do_1866(
dbus: &RogDbusClientBlocking,
power: &LedPowerCommand1,
) -> Result<(), Box<dyn std::error::Error>> {
let mut enabled: Vec<AuraDev1866> = Vec::new();
let mut disabled: Vec<AuraDev1866> = Vec::new();
@@ -488,12 +504,54 @@ fn handle_led_power1(
let data = AuraPowerDev {
x1866: enabled,
x19b6: vec![],
tuf: vec![],
};
dbus.proxies().led().set_leds_power(data, true)?;
let data = AuraPowerDev {
x1866: disabled,
x19b6: vec![],
tuf: vec![],
};
dbus.proxies().led().set_leds_power(data, false)?;
Ok(())
}
fn handle_led_power_1_do_tuf(
dbus: &RogDbusClientBlocking,
power: &LedPowerCommand1,
) -> Result<(), Box<dyn std::error::Error>> {
let mut enabled: Vec<AuraDevTuf> = Vec::new();
let mut disabled: Vec<AuraDevTuf> = Vec::new();
let mut check = |e: Option<bool>, a: AuraDevTuf| {
if let Some(arg) = e {
if arg {
enabled.push(a);
} else {
disabled.push(a);
}
}
};
check(power.awake, AuraDevTuf::Awake);
check(power.boot, AuraDevTuf::Boot);
check(power.sleep, AuraDevTuf::Sleep);
check(power.keyboard, AuraDevTuf::Keyboard);
let data = AuraPowerDev {
x1866: vec![],
x19b6: vec![],
tuf: enabled,
};
dbg!(&data);
dbus.proxies().led().set_leds_power(data, true)?;
let data = AuraPowerDev {
x1866: vec![],
x19b6: vec![],
tuf: disabled,
};
dbus.proxies().led().set_leds_power(data, false)?;
@@ -570,6 +628,7 @@ fn handle_led_power2(
if !enabled.is_empty() {
let data = AuraPowerDev {
tuf: vec![],
x1866: vec![],
x19b6: enabled,
};
@@ -578,6 +637,7 @@ fn handle_led_power2(
if !disabled.is_empty() {
let data = AuraPowerDev {
tuf: vec![],
x1866: vec![],
x19b6: disabled,
};

View File

@@ -1,6 +1,6 @@
use crate::laptops::{LaptopLedData, ASUS_KEYBOARD_DEVICES};
use log::{error, warn};
use rog_aura::usb::{AuraDev1866, AuraDev19b6, AuraPowerDev};
use rog_aura::usb::{AuraDev1866, AuraDev19b6, AuraDevTuf, AuraDevice, AuraPowerDev};
use rog_aura::{AuraEffect, AuraModeNum, AuraZone, Direction, LedBrightness, Speed, GRADIENT};
use serde_derive::{Deserialize, Serialize};
use std::collections::{BTreeMap, HashSet};
@@ -16,13 +16,16 @@ pub static AURA_CONFIG_PATH: &str = "/etc/asusd/aura.conf";
/// booting.
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub enum AuraPowerConfig {
AuraDevTuf(HashSet<AuraDevTuf>),
AuraDev1866(HashSet<AuraDev1866>),
AuraDev19b6(HashSet<AuraDev19b6>),
}
impl AuraPowerConfig {
/// Invalid for TUF laptops
pub fn to_bytes(control: &Self) -> [u8; 3] {
match control {
AuraPowerConfig::AuraDevTuf(_) => [0, 0, 0],
AuraPowerConfig::AuraDev1866(c) => {
let c: Vec<AuraDev1866> = c.iter().map(|v| *v).collect();
AuraDev1866::to_bytes(&c)
@@ -34,6 +37,39 @@ impl AuraPowerConfig {
}
}
pub fn to_tuf_bool_array(control: &Self) -> Option<[bool; 5]> {
if let Self::AuraDevTuf(c) = control {
return Some([
true,
c.contains(&AuraDevTuf::Boot),
c.contains(&AuraDevTuf::Awake),
c.contains(&AuraDevTuf::Sleep),
c.contains(&AuraDevTuf::Keyboard),
]);
}
if let Self::AuraDev1866(c) = control {
return Some([
true,
c.contains(&AuraDev1866::Boot),
c.contains(&AuraDev1866::Awake),
c.contains(&AuraDev1866::Sleep),
c.contains(&AuraDev1866::Keyboard),
]);
}
None
}
pub fn set_tuf(&mut self, power: AuraDevTuf, on: bool) {
if let Self::AuraDevTuf(p) = self {
if on {
p.insert(power);
} else {
p.remove(&power);
}
}
}
pub fn set_0x1866(&mut self, power: AuraDev1866, on: bool) {
if let Self::AuraDev1866(p) = self {
if on {
@@ -58,11 +94,18 @@ impl AuraPowerConfig {
impl From<&AuraPowerConfig> for AuraPowerDev {
fn from(config: &AuraPowerConfig) -> Self {
match config {
AuraPowerConfig::AuraDevTuf(d) => AuraPowerDev {
tuf: d.iter().map(|o| *o).collect(),
x1866: vec![],
x19b6: vec![],
},
AuraPowerConfig::AuraDev1866(d) => AuraPowerDev {
tuf: vec![],
x1866: d.iter().map(|o| *o).collect(),
x19b6: vec![],
},
AuraPowerConfig::AuraDev19b6(d) => AuraPowerDev {
tuf: vec![],
x1866: vec![],
x19b6: d.iter().map(|o| *o).collect(),
},
@@ -83,15 +126,19 @@ pub struct AuraConfig {
impl Default for AuraConfig {
fn default() -> Self {
let mut prod_id = String::new();
let mut prod_id = AuraDevice::Unknown;
for prod in ASUS_KEYBOARD_DEVICES.iter() {
if let Ok(_) = CtrlKbdLed::find_led_node(prod) {
prod_id = prod.to_string();
prod_id = AuraDevice::from(*prod);
break;
}
}
let enabled = if prod_id == "19b6" {
if CtrlKbdLed::get_tuf_mode_path().is_some() {
prod_id = AuraDevice::Tuf;
}
let enabled = if prod_id == AuraDevice::X19B6 {
AuraPowerConfig::AuraDev19b6(HashSet::from([
AuraDev19b6::BootLogo,
AuraDev19b6::BootKeyb,
@@ -106,6 +153,13 @@ impl Default for AuraConfig {
AuraDev19b6::SleepBar,
AuraDev19b6::ShutdownBar,
]))
} else if prod_id == AuraDevice::Tuf {
AuraPowerConfig::AuraDevTuf(HashSet::from([
AuraDevTuf::Awake,
AuraDevTuf::Boot,
AuraDevTuf::Sleep,
AuraDevTuf::Keyboard,
]))
} else {
AuraPowerConfig::AuraDev1866(HashSet::from([
AuraDev1866::Awake,

View File

@@ -1,5 +1,7 @@
// Only these two packets must be 17 bytes
static KBD_BRIGHT_PATH: &str = "/sys/class/leds/asus::kbd_backlight/brightness";
static TUF_RGB_MODE_PATH: &str = "/sys/devices/platform/asus-nb-wmi/tuf_krgb_mode";
static TUF_RGB_STATE_PATH: &str = "/sys/devices/platform/asus-nb-wmi/tuf_krgb_state";
use crate::{
error::RogError,
@@ -40,16 +42,20 @@ impl GetSupported for CtrlKbdLed {
let multizone_led_mode = laptop.multizone;
let per_key_led_mode = laptop.per_key;
let mut prod_id = "";
let mut prod_id = AuraDevice::Unknown;
for prod in ASUS_KEYBOARD_DEVICES.iter() {
if let Ok(_) = Self::find_led_node(prod) {
prod_id = *prod;
prod_id = AuraDevice::from(*prod);
break;
}
}
if Self::get_tuf_mode_path().is_some() {
prod_id = AuraDevice::Tuf;
}
LedSupportedFunctions {
prod_id: AuraDevice::from(prod_id),
prod_id,
brightness_set: CtrlKbdLed::get_kbd_bright_path().is_some(),
stock_led_modes,
multizone_led_mode,
@@ -58,10 +64,17 @@ impl GetSupported for CtrlKbdLed {
}
}
#[derive(Debug, PartialEq, PartialOrd)]
pub enum LEDNode {
Tuf,
Rog(String),
None,
}
pub struct CtrlKbdLed {
// TODO: config stores the keyboard type as an AuraPower, use or update this
pub led_prod: Option<String>,
pub led_node: Option<String>,
pub led_node: LEDNode,
pub bright_node: String,
pub supported_modes: LaptopLedData,
pub flip_effect_write: bool,
@@ -194,7 +207,6 @@ impl CtrlKbdLedZbus {
impl CtrlKbdLed {
pub fn new(supported_modes: LaptopLedData, config: AuraConfig) -> Result<Self, RogError> {
// TODO: return error if *all* nodes are None
let mut led_prod = None;
let mut led_node = None;
for prod in ASUS_KEYBOARD_DEVICES.iter() {
@@ -210,11 +222,28 @@ impl CtrlKbdLed {
}
let bright_node = Self::get_kbd_bright_path();
let tuf_node = Self::get_tuf_mode_path().is_some() || Self::get_tuf_state_path().is_some();
if led_node.is_none() && bright_node.is_none() {
if led_node.is_none() && tuf_node && bright_node.is_none() {
let dmi = sysfs_class::DmiId::default();
if let Ok(prod_family) = dmi.product_family() {
if prod_family.contains("TUF") {
warn!("A kernel patch is in progress for TUF RGB support");
}
}
return Err(RogError::NoAuraKeyboard);
}
let led_node = if let Some(rog) = led_node {
info!("Found ROG USB keyboard");
LEDNode::Rog(rog)
} else if tuf_node {
info!("Found TUF keyboard");
LEDNode::Tuf
} else {
LEDNode::None
};
let ctrl = CtrlKbdLed {
led_prod,
led_node,
@@ -233,6 +262,20 @@ impl CtrlKbdLed {
None
}
pub fn get_tuf_mode_path() -> Option<String> {
if Path::new(TUF_RGB_MODE_PATH).exists() {
return Some(TUF_RGB_MODE_PATH.to_string());
}
None
}
fn get_tuf_state_path() -> Option<String> {
if Path::new(TUF_RGB_STATE_PATH).exists() {
return Some(TUF_RGB_STATE_PATH.to_string());
}
None
}
pub(super) fn get_brightness(&self) -> Result<u8, RogError> {
let mut file = OpenOptions::new()
.read(true)
@@ -290,13 +333,26 @@ impl CtrlKbdLed {
/// Set combination state for boot animation/sleep animation/all leds/keys leds/side leds LED active
pub(super) fn set_power_states(&self, config: &AuraConfig) -> Result<(), RogError> {
let bytes = AuraPowerConfig::to_bytes(&config.enabled);
let message = [0x5d, 0xbd, 0x01, bytes[0], bytes[1], bytes[2]];
if LEDNode::Tuf == self.led_node {
if let Some(path) = Self::get_tuf_state_path() {
let mut file = OpenOptions::new().write(true).open(path)?;
if let Some(pwr) = AuraPowerConfig::to_tuf_bool_array(&config.enabled) {
let buf = format!(
"1 {} {} {} {}",
pwr[1] as u8, pwr[2] as u8, pwr[3] as u8, pwr[4] as u8,
);
file.write_all(buf.as_bytes())?;
}
}
} else {
let bytes = AuraPowerConfig::to_bytes(&config.enabled);
let message = [0x5d, 0xbd, 0x01, bytes[0], bytes[1], bytes[2]];
self.write_bytes(&message)?;
self.write_bytes(&LED_SET)?;
// Changes won't persist unless apply is set
self.write_bytes(&LED_APPLY)?;
self.write_bytes(&message)?;
self.write_bytes(&LED_SET)?;
// Changes won't persist unless apply is set
self.write_bytes(&LED_APPLY)?;
}
Ok(())
}
@@ -360,7 +416,7 @@ impl CtrlKbdLed {
/// Should only be used if the bytes you are writing are verified correct
fn write_bytes(&self, message: &[u8]) -> Result<(), RogError> {
if let Some(led_node) = &self.led_node {
if let LEDNode::Rog(led_node) = &self.led_node {
if let Ok(mut file) = OpenOptions::new().write(true).open(led_node) {
// println!("write: {:02x?}", &message);
return file
@@ -422,11 +478,20 @@ impl CtrlKbdLed {
}
fn write_mode(&self, mode: &AuraEffect) -> Result<(), RogError> {
let bytes: [u8; LED_MSG_LEN] = mode.into();
self.write_bytes(&bytes)?;
self.write_bytes(&LED_SET)?;
// Changes won't persist unless apply is set
self.write_bytes(&LED_APPLY)?;
if LEDNode::Tuf == self.led_node {
let mut file = OpenOptions::new().write(true).open(TUF_RGB_MODE_PATH)?;
let buf = format!(
"1 {} {} {} {} {}",
mode.mode as u8, mode.colour1.0, mode.colour1.1, mode.colour1.2, mode.speed as u8,
);
file.write_all(buf.as_bytes())?;
} else {
let bytes: [u8; LED_MSG_LEN] = mode.into();
self.write_bytes(&bytes)?;
self.write_bytes(&LED_SET)?;
// Changes won't persist unless apply is set
self.write_bytes(&LED_APPLY)?;
}
Ok(())
}
@@ -498,7 +563,10 @@ impl CtrlKbdLed {
mod tests {
use rog_aura::{AuraEffect, AuraModeNum, AuraZone, Colour};
use crate::{ctrl_aura::config::AuraConfig, laptops::LaptopLedData};
use crate::{
ctrl_aura::{config::AuraConfig, controller::LEDNode},
laptops::LaptopLedData,
};
use super::CtrlKbdLed;
@@ -516,7 +584,7 @@ mod tests {
};
let mut controller = CtrlKbdLed {
led_prod: None,
led_node: None,
led_node: LEDNode::None,
bright_node: String::new(),
supported_modes,
flip_effect_write: false,
@@ -578,7 +646,7 @@ mod tests {
};
let mut controller = CtrlKbdLed {
led_prod: None,
led_node: None,
led_node: LEDNode::None,
bright_node: String::new(),
supported_modes,
flip_effect_write: false,
@@ -615,7 +683,7 @@ mod tests {
};
let mut controller = CtrlKbdLed {
led_prod: None,
led_node: None,
led_node: LEDNode::None,
bright_node: String::new(),
supported_modes,
flip_effect_write: false,

View File

@@ -66,6 +66,9 @@ impl CtrlKbdLedZbus {
) -> zbus::fdo::Result<()> {
let mut states = None;
if let Ok(mut ctrl) = self.0.try_lock() {
for p in options.tuf {
ctrl.config.enabled.set_tuf(p, enabled);
}
for p in options.x1866 {
ctrl.config.enabled.set_0x1866(p, enabled);
}

View File

@@ -1,3 +1,17 @@
[[led_data]]
prod_family = "TUF"
board_names = ["FA507"]
standard = ["Static", "Breathe", "Strobe", "Pulse"]
multizone = []
per_key = false
[[led_data]]
prod_family = "TUF Gaming"
board_names = ["FX505D"]
standard = ["Static", "Breathe", "Strobe", "Rainbow", "Pulse"]
multizone = []
per_key = false
[[led_data]]
prod_family = "Zephyrus S"
board_names = ["GX502", "GX701", "G531", "GL531", "G532"]
@@ -162,7 +176,7 @@ multizone = []
per_key = false
[[led_data]]
prod_family = "ROG Strix"
prod_family = "ROG Strix"
board_names = ["G513IC"]
standard = ["Static", "Breathe", "Strobe", "Rainbow", "Pulse"]
multizone = []

View File

@@ -150,8 +150,11 @@ impl FromStr for Direction {
/// Enum of modes that convert to the actual number required by a USB HID packet
#[cfg_attr(feature = "dbus", derive(Type))]
#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Copy, Deserialize, Serialize)]
#[derive(
Debug, Default, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Copy, Deserialize, Serialize,
)]
pub enum AuraModeNum {
#[default]
Static = 0,
Breathe = 1,
Strobe = 2,

View File

@@ -23,6 +23,7 @@ pub const fn aura_brightness_bytes(brightness: u8) -> [u8; 17] {
#[cfg_attr(feature = "dbus", derive(Type))]
#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize, Default)]
pub enum AuraDevice {
Tuf,
X1854,
X1869,
X1866,
@@ -34,6 +35,7 @@ pub enum AuraDevice {
impl From<&str> for AuraDevice {
fn from(s: &str) -> Self {
match s.to_lowercase().as_str() {
"tuf" => AuraDevice::Tuf,
"1866" => AuraDevice::X1866,
"1869" => AuraDevice::X1869,
"1854" => AuraDevice::X1854,
@@ -49,12 +51,29 @@ impl From<&str> for AuraDevice {
/// This struct is intended as a helper to pass args to generic dbus interface
#[cfg_attr(feature = "dbus", derive(Type))]
#[derive(Clone, Debug, Serialize, Deserialize)]
#[derive(Clone, Default, Debug, Serialize, Deserialize)]
pub struct AuraPowerDev {
pub tuf: Vec<AuraDevTuf>,
pub x1866: Vec<AuraDev1866>,
pub x19b6: Vec<AuraDev19b6>,
}
#[cfg_attr(feature = "dbus", derive(Type))]
#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)]
#[repr(u32)]
pub enum AuraDevTuf {
Boot,
Awake,
Sleep,
Keyboard,
}
impl AuraDevTuf {
pub const fn dev_id() -> &'static str {
"tuf"
}
}
/// # Bits for older 0x1866 keyboard model
///
/// Keybord and Lightbar require Awake, Boot and Sleep apply to both

View File

@@ -28,7 +28,9 @@ pub struct RogApp<'a> {
pub config: Config,
pub asus_dbus: RogDbusClientBlocking<'a>,
/// Oscillator in percentage
pub oscillator: Arc<AtomicU8>,
pub oscillator1: Arc<AtomicU8>,
pub oscillator2: Arc<AtomicU8>,
pub oscillator3: Arc<AtomicU8>,
/// Frequency of oscillation
pub oscillator_freq: Arc<AtomicU8>,
/// A toggle that toggles true/false when the oscillator reaches 0
@@ -49,8 +51,14 @@ impl<'a> RogApp<'a> {
// Set up an oscillator to run on a thread.
// Helpful for visual effects like colour pulse.
let oscillator = Arc::new(AtomicU8::new(0));
let oscillator1 = oscillator.clone();
let oscillator1 = Arc::new(AtomicU8::new(0));
let oscillator2 = Arc::new(AtomicU8::new(0));
let oscillator3 = Arc::new(AtomicU8::new(0));
let oscillator1_1 = oscillator1.clone();
let oscillator1_2 = oscillator2.clone();
let oscillator1_3 = oscillator3.clone();
let oscillator_freq = Arc::new(AtomicU8::new(5));
let oscillator_freq1 = oscillator_freq.clone();
let oscillator_toggle = Arc::new(AtomicBool::new(false));
@@ -62,19 +70,27 @@ impl<'a> RogApp<'a> {
let time = started.elapsed();
// 32 = slow, 16 = med, 8 = fast
let scale = oscillator_freq1.load(Ordering::SeqCst) as f64;
let elapsed = time.as_millis() as f64 / 10000.0;
let tmp = ((scale * elapsed * PI).cos()).abs();
if tmp <= 0.1 && !toggled {
let elapsed1 = (time.as_millis() as f64 + 333.0) / 10000.0;
let elapsed2 = (time.as_millis() as f64 + 666.0) / 10000.0;
let elapsed3 = (time.as_millis() as f64 + 999.0) / 10000.0;
let tmp1 = ((scale * elapsed1 * PI).cos()).abs();
let tmp2 = ((scale * 0.85 * elapsed2 * PI).cos()).abs();
let tmp3 = ((scale * 0.7 * elapsed3 * PI).cos()).abs();
if tmp1 <= 0.1 && !toggled {
let s = oscillator_toggle1.load(Ordering::SeqCst);
oscillator_toggle1.store(!s, Ordering::SeqCst);
toggled = true;
} else if tmp > 0.9 {
} else if tmp1 > 0.9 {
toggled = false;
}
let tmp = (255.0 * tmp * 100.0 / 255.0) as u8;
let tmp1 = (255.0 * tmp1 * 100.0 / 255.0) as u8;
let tmp2 = (255.0 * tmp2 * 100.0 / 255.0) as u8;
let tmp3 = (255.0 * tmp3 * 100.0 / 255.0) as u8;
oscillator1.store(tmp, Ordering::SeqCst);
oscillator1_1.store(tmp1, Ordering::SeqCst);
oscillator1_2.store(tmp2, Ordering::SeqCst);
oscillator1_3.store(tmp3, Ordering::SeqCst);
std::thread::sleep(Duration::from_millis(33));
}
});
@@ -87,7 +103,9 @@ impl<'a> RogApp<'a> {
running_in_bg: start_closed,
config,
asus_dbus: dbus,
oscillator,
oscillator1,
oscillator2,
oscillator3,
oscillator_toggle,
oscillator_freq,
})
@@ -168,8 +186,9 @@ impl<'a> eframe::App for RogApp<'a> {
self.system_page(ctx);
} else if page == Page::AuraEffects {
self.aura_page(ctx);
} else if page == Page::AnimeMatrix {
self.anime_page(ctx);
// TODO: Anime page is not complete
// } else if page == Page::AnimeMatrix {
// self.anime_page(ctx);
} else if page == Page::FanCurves {
self.fan_curve_page(ctx);
}

View File

@@ -147,6 +147,7 @@ impl Led {
}
pub fn leds_enabled(&self) -> Result<AuraPowerDev> {
Ok(AuraPowerDev {
tuf: vec![],
x1866: vec![],
x19b6: vec![
AuraDev19b6::BootKeyb,

View File

@@ -173,19 +173,19 @@ impl AuraState {
Ok(Self {
was_notified,
current_mode: if !supported.keyboard_led.stock_led_modes.is_empty() {
dbus.proxies().led().led_mode()?
dbus.proxies().led().led_mode().unwrap_or_default()
} else {
AuraModeNum::Static
},
modes: if !supported.keyboard_led.stock_led_modes.is_empty() {
dbus.proxies().led().led_modes()?
dbus.proxies().led().led_modes().unwrap_or_default()
} else {
BTreeMap::new()
},
enabled: dbus.proxies().led().leds_enabled()?,
enabled: dbus.proxies().led().leds_enabled().unwrap_or_default(),
bright: if !supported.keyboard_led.brightness_set {
dbus.proxies().led().led_brightness()?
dbus.proxies().led().led_brightness().unwrap_or_default()
} else {
2
},
@@ -196,7 +196,7 @@ impl AuraState {
}
/// Bump value in to the wave and surf all along.
pub fn nudge_wave(&mut self, value: u8) {
pub fn nudge_wave(&mut self, r: u8, g: u8, b: u8) {
for i in (0..self.wave_red.len()).rev() {
if i > 0 {
self.wave_red[i] = self.wave_red[i - 1];
@@ -204,18 +204,9 @@ impl AuraState {
self.wave_blue[i] = self.wave_blue[i - 1];
}
}
let mut g = value + 33;
if g > 100 {
g -= 100;
}
let mut b = value + 66;
if b > 100 {
b -= 100;
}
self.wave_red[0] = value;
self.wave_red[0] = r;
self.wave_green[0] = g;
self.wave_blue[0] = b;
dbg!(self.wave_blue);
}
}
@@ -356,6 +347,7 @@ impl Default for PageDataStates {
current_mode: AuraModeNum::Static,
modes: Default::default(),
enabled: AuraPowerDev {
tuf: vec![],
x1866: vec![],
x19b6: vec![],
},

View File

@@ -14,12 +14,17 @@ impl<'a> RogApp<'a> {
supported,
states,
asus_dbus: dbus,
oscillator,
oscillator1,
oscillator2,
oscillator3,
oscillator_freq,
..
} = self;
let osc = oscillator.load(Ordering::SeqCst) as u32;
states.aura.nudge_wave(osc as u8);
let red = oscillator1.load(Ordering::SeqCst) as u32;
let green = oscillator2.load(Ordering::SeqCst) as u32;
let blue = oscillator3.load(Ordering::SeqCst) as u32;
states.aura.nudge_wave(red as u8, green as u8, blue as u8);
// let osc = c.0 * 255 / osc;
// dbg!(osc);
let c1 = states
@@ -39,29 +44,35 @@ impl<'a> RogApp<'a> {
let mut colour = Color32::from_rgb(c1.0, c1.1, c1.2);
if states.aura.current_mode == AuraModeNum::Pulse {
colour = Color32::from_rgb(
(osc * c1.0 as u32 / 100) as u8,
(osc * c1.1 as u32 / 100) as u8,
(osc * c1.2 as u32 / 100) as u8,
(red * c1.0 as u32 / 100) as u8,
(red * c1.1 as u32 / 100) as u8,
(red * c1.2 as u32 / 100) as u8,
);
} else if states.aura.current_mode == AuraModeNum::Breathe {
if self.oscillator_toggle.load(Ordering::SeqCst) {
colour = Color32::from_rgb(
(osc * c2.0 as u32 / 100) as u8,
(osc * c2.1 as u32 / 100) as u8,
(osc * c2.2 as u32 / 100) as u8,
(red * c2.0 as u32 / 100) as u8,
(red * c2.1 as u32 / 100) as u8,
(red * c2.2 as u32 / 100) as u8,
);
} else {
colour = Color32::from_rgb(
(osc * c1.0 as u32 / 100) as u8,
(osc * c1.1 as u32 / 100) as u8,
(osc * c1.2 as u32 / 100) as u8,
(red * c1.0 as u32 / 100) as u8,
(red * c1.1 as u32 / 100) as u8,
(red * c1.2 as u32 / 100) as u8,
);
}
} else if states.aura.current_mode == AuraModeNum::Strobe {
colour = Color32::from_rgb(
(red * 255 / 100) as u8,
(green * 255 / 100) as u8,
(blue * 255 / 100) as u8,
);
}
// TODO: animation of colour changes/periods/blending
egui::CentralPanel::default().show(ctx, |ui| {
aura_modes_group(supported, states, dbus, ui);
aura_modes_group(supported, states, oscillator_freq, dbus, ui);
keyboard(ui, &states.keyboard_layout, &mut states.aura, colour);
});

View File

@@ -1,3 +1,8 @@
use std::sync::{
atomic::{AtomicU8, Ordering},
Arc,
};
use egui::{RichText, Ui};
use rog_aura::{AuraEffect, AuraModeNum, AuraZone, Colour, Speed};
use rog_supported::SupportedFunctions;
@@ -10,6 +15,7 @@ use crate::{
pub fn aura_modes_group(
supported: &SupportedFunctions,
states: &mut PageDataStates,
freq: &mut Arc<AtomicU8>,
dbus: &mut RogDbusClientBlocking,
ui: &mut Ui,
) {
@@ -55,7 +61,17 @@ pub fn aura_modes_group(
ui.selectable_value(&mut effect.zone, a, format!("{:?}", a));
};
let mut speed_button = |a: Speed, ui: &mut Ui| {
ui.selectable_value(&mut effect.speed, a, format!("{:?}", a));
if ui
.selectable_value(&mut effect.speed, a, format!("{:?}", a))
.clicked()
{
let val = match effect.speed {
Speed::Low => 6,
Speed::Med => 8,
Speed::High => 10,
};
freq.store(val, Ordering::SeqCst);
}
};
let mut dir_button = |a: rog_aura::Direction, ui: &mut Ui| {
ui.selectable_value(&mut effect.direction, a, format!("{:?}", a));
@@ -69,72 +85,82 @@ pub fn aura_modes_group(
ui.vertical(|ui| {
let h = 16.0;
ui.set_row_height(22.0);
if has_keyzones || has_lightbar || has_logo {
ui.add_enabled_ui(allowed.zone, |ui| {
if has_keyzones || has_lightbar || has_logo {
ui.horizontal_wrapped(|ui| {
ui.label(RichText::new("Zone").size(h));
});
}
});
ui.add_enabled_ui(allowed.colour1, |ui| {
ui.horizontal_wrapped(|ui| {
ui.set_enabled(allowed.zone);
ui.label(RichText::new("Zone").size(h));
ui.label(RichText::new("Colour 1").size(h));
});
}
ui.horizontal_wrapped(|ui| {
ui.set_enabled(allowed.colour1);
ui.label(RichText::new("Colour 1").size(h));
});
ui.horizontal_wrapped(|ui| {
ui.set_enabled(allowed.colour2);
ui.label(RichText::new("Colour 2").size(h));
ui.add_enabled_ui(allowed.colour2, |ui| {
ui.horizontal_wrapped(|ui| {
ui.label(RichText::new("Colour 2").size(h));
});
});
ui.horizontal_wrapped(|ui| {
ui.set_enabled(allowed.speed);
ui.label(RichText::new("Speed").size(h));
ui.add_enabled_ui(allowed.speed, |ui| {
ui.horizontal_wrapped(|ui| {
ui.set_enabled(allowed.speed);
ui.label(RichText::new("Speed").size(h));
});
});
ui.horizontal_wrapped(|ui| {
ui.set_enabled(allowed.direction);
ui.label(RichText::new("Direction").size(h));
ui.add_enabled_ui(allowed.direction, |ui| {
ui.horizontal_wrapped(|ui| {
ui.set_enabled(allowed.direction);
ui.label(RichText::new("Direction").size(h));
});
});
ui.set_enabled(true);
});
ui.vertical(|ui| {
ui.set_row_height(22.0);
if has_keyzones || has_lightbar || has_logo {
ui.horizontal_wrapped(|ui| {
ui.set_enabled(allowed.zone);
zone_button(AuraZone::None, ui);
if has_keyzones {
zone_button(AuraZone::Key1, ui);
zone_button(AuraZone::Key2, ui);
zone_button(AuraZone::Key3, ui);
zone_button(AuraZone::Key4, ui);
}
if has_logo {
zone_button(AuraZone::Logo, ui);
}
if has_lightbar {
zone_button(AuraZone::BarLeft, ui);
zone_button(AuraZone::BarRight, ui);
}
});
}
ui.set_enabled(allowed.colour1);
egui::color_picker::color_edit_button_srgb(ui, &mut c1);
ui.set_enabled(allowed.colour2);
egui::color_picker::color_edit_button_srgb(ui, &mut c2);
ui.set_enabled(allowed.speed);
ui.horizontal_wrapped(|ui| {
speed_button(Speed::Low, ui);
speed_button(Speed::Med, ui);
speed_button(Speed::High, ui);
ui.add_enabled_ui(allowed.zone, |ui| {
if has_keyzones || has_lightbar || has_logo {
ui.horizontal_wrapped(|ui| {
zone_button(AuraZone::None, ui);
if has_keyzones {
zone_button(AuraZone::Key1, ui);
zone_button(AuraZone::Key2, ui);
zone_button(AuraZone::Key3, ui);
zone_button(AuraZone::Key4, ui);
}
if has_logo {
zone_button(AuraZone::Logo, ui);
}
if has_lightbar {
zone_button(AuraZone::BarLeft, ui);
zone_button(AuraZone::BarRight, ui);
}
});
}
});
ui.set_enabled(allowed.direction);
ui.horizontal_wrapped(|ui| {
dir_button(rog_aura::Direction::Left, ui);
dir_button(rog_aura::Direction::Down, ui);
dir_button(rog_aura::Direction::Right, ui);
dir_button(rog_aura::Direction::Up, ui);
ui.add_enabled_ui(allowed.colour1, |ui| {
egui::color_picker::color_edit_button_srgb(ui, &mut c1)
});
ui.add_enabled_ui(allowed.colour2, |ui| {
egui::color_picker::color_edit_button_srgb(ui, &mut c2)
});
ui.add_enabled_ui(allowed.speed, |ui| {
ui.horizontal_wrapped(|ui| {
speed_button(Speed::Low, ui);
speed_button(Speed::Med, ui);
speed_button(Speed::High, ui);
});
});
ui.add_enabled_ui(allowed.direction, |ui| {
ui.horizontal_wrapped(|ui| {
dir_button(rog_aura::Direction::Left, ui);
dir_button(rog_aura::Direction::Down, ui);
dir_button(rog_aura::Direction::Right, ui);
dir_button(rog_aura::Direction::Up, ui);
});
});
});
});

View File

@@ -1,6 +1,6 @@
use egui::{RichText, Ui};
use rog_aura::{
usb::{AuraDev1866, AuraDev19b6, AuraDevice, AuraPowerDev},
usb::{AuraDev1866, AuraDev19b6, AuraDevTuf, AuraDevice, AuraPowerDev},
AuraZone,
};
use rog_supported::SupportedFunctions;
@@ -20,6 +20,7 @@ pub fn aura_power_group(
aura_power1(supported, states, dbus, ui)
}
AuraDevice::X19B6 => aura_power2(supported, states, dbus, ui),
AuraDevice::Tuf => aura_power1(supported, states, dbus, ui),
AuraDevice::Unknown => {}
}
}
@@ -31,10 +32,15 @@ fn aura_power1(
ui: &mut Ui,
) {
let enabled_states = &mut states.aura.enabled;
let boot = &mut enabled_states.x1866.contains(&AuraDev1866::Boot);
let sleep = &mut enabled_states.x1866.contains(&AuraDev1866::Sleep);
let keyboard = &mut enabled_states.x1866.contains(&AuraDev1866::Keyboard);
let lightbar = &mut enabled_states.x1866.contains(&AuraDev1866::Lightbar);
let mut boot = enabled_states.x1866.contains(&AuraDev1866::Boot);
let mut sleep = enabled_states.x1866.contains(&AuraDev1866::Sleep);
let mut keyboard = enabled_states.x1866.contains(&AuraDev1866::Keyboard);
let mut lightbar = enabled_states.x1866.contains(&AuraDev1866::Lightbar);
if supported.keyboard_led.prod_id == AuraDevice::Tuf {
boot = enabled_states.tuf.contains(&AuraDevTuf::Boot);
sleep = enabled_states.tuf.contains(&AuraDevTuf::Sleep);
keyboard = enabled_states.tuf.contains(&AuraDevTuf::Awake);
}
let mut changed = false;
ui.horizontal_wrapped(|ui| {
@@ -59,22 +65,22 @@ fn aura_power1(
ui.vertical(|ui| {
ui.set_row_height(22.0);
ui.horizontal_wrapped(|ui| {
if ui.checkbox(boot, "Enable").changed() {
if ui.checkbox(&mut boot, "Enable").changed() {
changed = true;
}
});
ui.horizontal_wrapped(|ui| {
if ui.toggle_value(keyboard, "Keyboard").changed() {
if ui.toggle_value(&mut keyboard, "Keyboard").changed() {
changed = true;
}
if !supported.keyboard_led.multizone_led_mode.is_empty() {
if ui.toggle_value(lightbar, "Lightbar").changed() {
if ui.toggle_value(&mut lightbar, "Lightbar").changed() {
changed = true;
}
}
});
ui.horizontal_wrapped(|ui| {
if ui.checkbox(sleep, "Enable").changed() {
if ui.checkbox(&mut sleep, "Enable").changed() {
changed = true;
}
});
@@ -102,53 +108,102 @@ fn aura_power1(
});
if changed {
let mut enabled = Vec::new();
let mut disabled = Vec::new();
if supported.keyboard_led.prod_id == AuraDevice::Tuf {
let mut enabled = Vec::new();
let mut disabled = Vec::new();
let mut modify = |b: bool, a: AuraDev1866| {
if b {
enabled.push(a);
if !enabled_states.x1866.contains(&a) {
enabled_states.x1866.push(a);
}
} else {
disabled.push(a);
// This would be so much better as a hashset
if enabled_states.x1866.contains(&a) {
let mut idx = 0;
for (i, n) in enabled_states.x1866.iter().enumerate() {
if *n == a {
idx = i;
break;
}
let mut modify_tuf = |b: bool, a: AuraDevTuf| {
if b {
enabled.push(a);
if !enabled_states.tuf.contains(&a) {
enabled_states.tuf.push(a);
}
} else {
disabled.push(a);
// This would be so much better as a hashset
if enabled_states.tuf.contains(&a) {
let mut idx = 0;
for (i, n) in enabled_states.tuf.iter().enumerate() {
if *n == a {
idx = i;
break;
}
}
enabled_states.tuf.remove(idx);
}
enabled_states.x1866.remove(idx);
}
}
};
modify(*boot, AuraDev1866::Boot);
modify(*sleep, AuraDev1866::Sleep);
modify(*keyboard, AuraDev1866::Keyboard);
if !supported.keyboard_led.multizone_led_mode.is_empty() {
modify(*lightbar, AuraDev1866::Lightbar);
}
let mut send = |enable: bool, data: Vec<AuraDev1866>| {
let options = AuraPowerDev {
x1866: data,
x19b6: vec![],
};
// build data to send
dbus.proxies()
.led()
.set_leds_power(options, enable)
.map_err(|err| {
states.error = Some(err.to_string());
})
.ok();
};
send(true, enabled);
send(false, disabled);
modify_tuf(boot, AuraDevTuf::Boot);
modify_tuf(sleep, AuraDevTuf::Sleep);
modify_tuf(keyboard, AuraDevTuf::Awake);
let mut send = |enable: bool, data: Vec<AuraDevTuf>| {
let options = AuraPowerDev {
tuf: data,
x1866: vec![],
x19b6: vec![],
};
// build data to send
dbus.proxies()
.led()
.set_leds_power(options, enable)
.map_err(|err| {
states.error = Some(err.to_string());
})
.ok();
};
send(true, enabled);
send(false, disabled);
} else {
let mut enabled = Vec::new();
let mut disabled = Vec::new();
let mut modify_x1866 = |b: bool, a: AuraDev1866| {
if b {
enabled.push(a);
if !enabled_states.x1866.contains(&a) {
enabled_states.x1866.push(a);
}
} else {
disabled.push(a);
// This would be so much better as a hashset
if enabled_states.x1866.contains(&a) {
let mut idx = 0;
for (i, n) in enabled_states.x1866.iter().enumerate() {
if *n == a {
idx = i;
break;
}
}
enabled_states.x1866.remove(idx);
}
}
};
modify_x1866(boot, AuraDev1866::Boot);
modify_x1866(sleep, AuraDev1866::Sleep);
modify_x1866(keyboard, AuraDev1866::Keyboard);
if !supported.keyboard_led.multizone_led_mode.is_empty() {
modify_x1866(lightbar, AuraDev1866::Lightbar);
}
let mut send = |enable: bool, data: Vec<AuraDev1866>| {
let options = AuraPowerDev {
tuf: vec![],
x1866: data,
x19b6: vec![],
};
// build data to send
dbus.proxies()
.led()
.set_leds_power(options, enable)
.map_err(|err| {
states.error = Some(err.to_string());
})
.ok();
};
send(true, enabled);
send(false, disabled);
}
}
}
@@ -271,6 +326,7 @@ fn aura_power2(
let mut send = |enable: bool, data: Vec<AuraDev19b6>| {
let options = AuraPowerDev {
tuf: vec![],
x1866: vec![],
x19b6: data,
};

View File

@@ -3,7 +3,12 @@ use rog_aura::{keys::KeyShape, layouts::KeyLayout, AuraModeNum};
use crate::page_states::AuraState;
pub fn keyboard(ui: &mut egui::Ui, keyboard_layout: &KeyLayout, states: &mut AuraState, mut colour: Color32) {
pub fn keyboard(
ui: &mut egui::Ui,
keyboard_layout: &KeyLayout,
states: &mut AuraState,
mut colour: Color32,
) {
ui.spacing_mut().item_spacing = egui::vec2(0.0, 0.0);
let mut arrows_done = false;
let mut rog_done = false;
@@ -13,8 +18,8 @@ pub fn keyboard(ui: &mut egui::Ui, keyboard_layout: &KeyLayout, states: &mut Aur
if states.current_mode == AuraModeNum::Rainbow {
colour = Color32::from_rgb(
(states.wave_red[i] as u32 * 255 / 100) as u8,
(states.wave_green[i]as u32 * 255 / 100) as u8,
(states.wave_blue[i]as u32 * 255 / 100) as u8,
(states.wave_green[i] as u32 * 255 / 100) as u8,
(states.wave_blue[i] as u32 * 255 / 100) as u8,
);
}
// your boat

View File

@@ -38,15 +38,16 @@ impl<'a> RogApp<'a> {
}
}
if self.supported.anime_ctrl.0 {
ui.separator();
if ui
.selectable_value(page, Page::AnimeMatrix, "AniMe Matrix")
.clicked()
{
*page = Page::AnimeMatrix;
}
}
// TODO: Anime page is not complete
// if self.supported.anime_ctrl.0 {
// ui.separator();
// if ui
// .selectable_value(page, Page::AnimeMatrix, "AniMe Matrix")
// .clicked()
// {
// *page = Page::AnimeMatrix;
// }
// }
ui.with_layout(egui::Layout::bottom_up(egui::Align::LEFT), |ui| {
ui.horizontal(|ui| {