mirror of
https://gitlab.com/asus-linux/asusctl.git
synced 2026-02-06 00:15:04 +01:00
Merge branch 'fluke/aura_advanced' into 'main'
Fluke/aura advanced See merge request asus-linux/asusctl!148
This commit is contained in:
3
Cargo.lock
generated
3
Cargo.lock
generated
@@ -666,6 +666,7 @@ dependencies = [
|
|||||||
"serde",
|
"serde",
|
||||||
"serde_derive",
|
"serde_derive",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
|
"toml",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -816,6 +817,8 @@ version = "4.5.8"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"config-traits",
|
"config-traits",
|
||||||
"dirs",
|
"dirs",
|
||||||
|
"env_logger",
|
||||||
|
"log",
|
||||||
"rog_anime",
|
"rog_anime",
|
||||||
"rog_aura",
|
"rog_aura",
|
||||||
"rog_dbus",
|
"rog_dbus",
|
||||||
|
|||||||
128
MANUAL.md
128
MANUAL.md
@@ -117,60 +117,67 @@ I'm unsure of how many laptops this works on, so please try it.
|
|||||||
|
|
||||||
An Aura config itself is a file with contents:
|
An Aura config itself is a file with contents:
|
||||||
|
|
||||||
```json
|
```ron
|
||||||
{
|
(
|
||||||
"name": "aura-default",
|
name: "aura-default",
|
||||||
"aura": [
|
aura: (
|
||||||
{
|
effects: [
|
||||||
"Breathe": {
|
Breathe((
|
||||||
"led_type": {
|
led: W,
|
||||||
"Key": "W"
|
start_colour1: (255, 0, 20),
|
||||||
},
|
start_colour2: (20, 255, 0),
|
||||||
"start_colour1": [
|
speed: Low,
|
||||||
255,
|
)),
|
||||||
0,
|
Breathe((
|
||||||
20
|
led: A,
|
||||||
|
start_colour1: (255, 0, 20),
|
||||||
|
start_colour2: (20, 255, 0),
|
||||||
|
speed: Low,
|
||||||
|
)),
|
||||||
|
Breathe((
|
||||||
|
led: S,
|
||||||
|
start_colour1: (255, 0, 20),
|
||||||
|
start_colour2: (20, 255, 0),
|
||||||
|
speed: Low,
|
||||||
|
)),
|
||||||
|
Breathe((
|
||||||
|
led: D,
|
||||||
|
start_colour1: (255, 0, 20),
|
||||||
|
start_colour2: (20, 255, 0),
|
||||||
|
speed: Low,
|
||||||
|
)),
|
||||||
|
Breathe((
|
||||||
|
led: F,
|
||||||
|
start_colour1: (255, 0, 0),
|
||||||
|
start_colour2: (255, 0, 0),
|
||||||
|
speed: High,
|
||||||
|
)),
|
||||||
|
Static((
|
||||||
|
led: RCtrl,
|
||||||
|
colour: (0, 0, 255),
|
||||||
|
)),
|
||||||
|
Static((
|
||||||
|
led: LCtrl,
|
||||||
|
colour: (0, 0, 255),
|
||||||
|
)),
|
||||||
|
Static((
|
||||||
|
led: Esc,
|
||||||
|
colour: (0, 0, 255),
|
||||||
|
)),
|
||||||
|
DoomFlicker((
|
||||||
|
led: N9,
|
||||||
|
start_colour: (0, 0, 255),
|
||||||
|
max_percentage: 80,
|
||||||
|
min_percentage: 40,
|
||||||
|
)),
|
||||||
],
|
],
|
||||||
"start_colour2": [
|
zoned: false,
|
||||||
20,
|
),
|
||||||
255,
|
)
|
||||||
0
|
|
||||||
],
|
|
||||||
"speed": "Low"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Static": {
|
|
||||||
"led_type": {
|
|
||||||
"Key": "Esc"
|
|
||||||
},
|
|
||||||
"colour": [
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
255
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Flicker": {
|
|
||||||
"led_type": {
|
|
||||||
"Key": "N9"
|
|
||||||
},
|
|
||||||
"start_colour": [
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
255
|
|
||||||
],
|
|
||||||
"max_percentage": 80,
|
|
||||||
"min_percentage": 40
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
If your laptop supports multizone, `"led_type"` can also be `"Zone": <one of the following>`
|
If your laptop supports multizone, `"led"` can also be `"Zone": <one of the following>`
|
||||||
- `"None"`
|
- `SingleZone` // Keyboards with only one zone
|
||||||
- `ZonedKbLeft` // keyboard left
|
- `ZonedKbLeft` // keyboard left
|
||||||
- `ZonedKbLeftMid` // keyboard left-middle
|
- `ZonedKbLeftMid` // keyboard left-middle
|
||||||
- `ZonedKbRightMid` // etc
|
- `ZonedKbRightMid` // etc
|
||||||
@@ -182,6 +189,25 @@ If your laptop supports multizone, `"led_type"` can also be `"Zone": <one of the
|
|||||||
- `LightbarLeftCorner`
|
- `LightbarLeftCorner`
|
||||||
- `LightbarLeft`
|
- `LightbarLeft`
|
||||||
|
|
||||||
|
Single zone example:
|
||||||
|
|
||||||
|
```ron
|
||||||
|
(
|
||||||
|
name: "aura-default",
|
||||||
|
aura: (
|
||||||
|
effects: [
|
||||||
|
DoomFlicker((
|
||||||
|
led: SingleZone,
|
||||||
|
start_colour: (200, 40, 5),
|
||||||
|
max_percentage: 80,
|
||||||
|
min_percentage: 40,
|
||||||
|
)),
|
||||||
|
],
|
||||||
|
zoned: true,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
At the moment there are only three effects available as shown in the example. More will come in the future
|
At the moment there are only three effects available as shown in the example. More will come in the future
|
||||||
but this may take me some time.
|
but this may take me some time.
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ edition = "2021"
|
|||||||
serde.workspace = true
|
serde.workspace = true
|
||||||
serde_derive.workspace = true
|
serde_derive.workspace = true
|
||||||
serde_json.workspace = true
|
serde_json.workspace = true
|
||||||
|
toml.workspace = true
|
||||||
ron.workspace = true
|
ron.workspace = true
|
||||||
|
|
||||||
log.workspace = true
|
log.workspace = true
|
||||||
@@ -31,6 +31,46 @@ where
|
|||||||
.unwrap_or_else(|e| panic!("Could not create {:?} {e}", Self::config_dir()));
|
.unwrap_or_else(|e| panic!("Could not create {:?} {e}", Self::config_dir()));
|
||||||
}
|
}
|
||||||
config.push(self.file_name());
|
config.push(self.file_name());
|
||||||
|
let mut do_rename = !config.exists();
|
||||||
|
let mut cfg_old = config.clone();
|
||||||
|
// Migrating all configs to .ron format, so we do need to check for older ones
|
||||||
|
if do_rename {
|
||||||
|
warn!("Config {cfg_old:?} does not exist, looking for .cfg next");
|
||||||
|
cfg_old.pop();
|
||||||
|
let tmp = self.file_name();
|
||||||
|
let parts: Vec<_> = tmp.split('.').collect();
|
||||||
|
cfg_old.push(format!("{}.cfg", parts[0]));
|
||||||
|
}
|
||||||
|
if do_rename && cfg_old.exists() {
|
||||||
|
// Now we gotta rename it
|
||||||
|
warn!("Renaming {cfg_old:?} to {config:?}");
|
||||||
|
std::fs::rename(&cfg_old, &config).unwrap_or_else(|err| {
|
||||||
|
error!(
|
||||||
|
"Could not rename. Please remove {} then restart service: Error {}",
|
||||||
|
self.file_name(),
|
||||||
|
err
|
||||||
|
)
|
||||||
|
});
|
||||||
|
do_rename = false;
|
||||||
|
}
|
||||||
|
if do_rename && !cfg_old.exists() {
|
||||||
|
warn!("Config {cfg_old:?} does not exist, looking for .conf next");
|
||||||
|
cfg_old.pop();
|
||||||
|
let tmp = self.file_name();
|
||||||
|
let parts: Vec<_> = tmp.split('.').collect();
|
||||||
|
cfg_old.push(format!("{}.conf", parts[0]));
|
||||||
|
}
|
||||||
|
if do_rename && cfg_old.exists() {
|
||||||
|
// Now we gotta rename it
|
||||||
|
warn!("Renaming {cfg_old:?} to {config:?}");
|
||||||
|
std::fs::rename(&cfg_old, &config).unwrap_or_else(|err| {
|
||||||
|
error!(
|
||||||
|
"Could not rename. Please remove {} then restart service: Error {}",
|
||||||
|
self.file_name(),
|
||||||
|
err
|
||||||
|
)
|
||||||
|
});
|
||||||
|
}
|
||||||
config
|
config
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -146,6 +186,8 @@ where
|
|||||||
self = data;
|
self = data;
|
||||||
} else if let Ok(data) = serde_json::from_str(&buf) {
|
} else if let Ok(data) = serde_json::from_str(&buf) {
|
||||||
self = data;
|
self = data;
|
||||||
|
} else if let Ok(data) = toml::from_str(&buf) {
|
||||||
|
self = data;
|
||||||
} else {
|
} else {
|
||||||
self.rename_file_old();
|
self.rename_file_old();
|
||||||
self = Self::new();
|
self = Self::new();
|
||||||
@@ -205,8 +247,12 @@ where
|
|||||||
self = data;
|
self = data;
|
||||||
} else if let Ok(data) = serde_json::from_str(&buf) {
|
} else if let Ok(data) = serde_json::from_str(&buf) {
|
||||||
self = data;
|
self = data;
|
||||||
|
} else if let Ok(data) = toml::from_str(&buf) {
|
||||||
|
self = data;
|
||||||
} else if let Ok(data) = serde_json::from_str::<OldConfig>(&buf) {
|
} else if let Ok(data) = serde_json::from_str::<OldConfig>(&buf) {
|
||||||
self = data.into();
|
self = data.into();
|
||||||
|
} else if let Ok(data) = toml::from_str::<OldConfig>(&buf) {
|
||||||
|
self = data.into();
|
||||||
} else {
|
} else {
|
||||||
self.rename_file_old();
|
self.rename_file_old();
|
||||||
self = Self::new();
|
self = Self::new();
|
||||||
@@ -274,10 +320,16 @@ where
|
|||||||
self = data;
|
self = data;
|
||||||
} else if let Ok(data) = serde_json::from_str(&buf) {
|
} else if let Ok(data) = serde_json::from_str(&buf) {
|
||||||
self = data;
|
self = data;
|
||||||
|
} else if let Ok(data) = toml::from_str(&buf) {
|
||||||
|
self = data;
|
||||||
} else if let Ok(data) = serde_json::from_str::<OldConfig>(&buf) {
|
} else if let Ok(data) = serde_json::from_str::<OldConfig>(&buf) {
|
||||||
self = data.into();
|
self = data.into();
|
||||||
|
} else if let Ok(data) = toml::from_str::<OldConfig>(&buf) {
|
||||||
|
self = data.into();
|
||||||
} else if let Ok(data) = serde_json::from_str::<OldConfig2>(&buf) {
|
} else if let Ok(data) = serde_json::from_str::<OldConfig2>(&buf) {
|
||||||
self = data.into();
|
self = data.into();
|
||||||
|
} else if let Ok(data) = toml::from_str::<OldConfig2>(&buf) {
|
||||||
|
self = data.into();
|
||||||
} else {
|
} else {
|
||||||
self.rename_file_old();
|
self.rename_file_old();
|
||||||
self = Self::new();
|
self = Self::new();
|
||||||
|
|||||||
@@ -30,3 +30,7 @@ rog_platform = { path = "../rog-platform" }
|
|||||||
config-traits = { path = "../config-traits" }
|
config-traits = { path = "../config-traits" }
|
||||||
|
|
||||||
zbus.workspace = true
|
zbus.workspace = true
|
||||||
|
|
||||||
|
# cli and logging
|
||||||
|
log.workspace = true
|
||||||
|
env_logger.workspace = true
|
||||||
@@ -1,92 +1,30 @@
|
|||||||
use std::fs::{create_dir, OpenOptions};
|
use std::path::PathBuf;
|
||||||
use std::io::{Read, Write};
|
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
|
use config_traits::{StdConfig, StdConfigLoad1};
|
||||||
use rog_anime::{ActionLoader, AnimTime, AnimeType, Fade, Sequences as AnimeSequences, Vec2};
|
use rog_anime::{ActionLoader, AnimTime, AnimeType, Fade, Sequences as AnimeSequences, Vec2};
|
||||||
use rog_aura::advanced::LedCode;
|
use rog_aura::advanced::LedCode;
|
||||||
use rog_aura::effects::{AdvancedEffects as AuraSequences, Breathe, DoomFlicker, Effect, Static};
|
use rog_aura::effects::{AdvancedEffects as AuraSequences, Breathe, DoomFlicker, Effect, Static};
|
||||||
use rog_aura::{Colour, Speed};
|
use rog_aura::{Colour, Speed};
|
||||||
use serde::de::DeserializeOwned;
|
|
||||||
use serde_derive::{Deserialize, Serialize};
|
use serde_derive::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::error::Error;
|
use crate::error::Error;
|
||||||
|
|
||||||
pub trait ConfigLoadSave<T: DeserializeOwned + serde::Serialize> {
|
const ROOT_CONF_DIR: &str = "rog";
|
||||||
fn name(&self) -> String;
|
|
||||||
|
|
||||||
fn default_with_name(name: String) -> T;
|
fn root_conf_dir() -> PathBuf {
|
||||||
|
let mut dir = dirs::config_dir().unwrap_or_else(|| PathBuf::from("/tmp"));
|
||||||
fn write(&self) -> Result<(), Error>
|
dir.push(ROOT_CONF_DIR);
|
||||||
where
|
dir
|
||||||
Self: serde::Serialize,
|
|
||||||
{
|
|
||||||
let mut path = if let Some(dir) = dirs::config_dir() {
|
|
||||||
dir
|
|
||||||
} else {
|
|
||||||
return Err(Error::XdgVars);
|
|
||||||
};
|
|
||||||
|
|
||||||
path.push("rog");
|
|
||||||
if !path.exists() {
|
|
||||||
create_dir(path.clone())?;
|
|
||||||
}
|
|
||||||
let name = self.name();
|
|
||||||
path.push(name + ".cfg");
|
|
||||||
|
|
||||||
let mut file = OpenOptions::new()
|
|
||||||
.write(true)
|
|
||||||
.create(true)
|
|
||||||
.truncate(true)
|
|
||||||
.open(&path)?;
|
|
||||||
|
|
||||||
let json = serde_json::to_string_pretty(&self).unwrap();
|
|
||||||
file.write_all(json.as_bytes())?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn load(name: String) -> Result<T, Error> {
|
|
||||||
let mut path = if let Some(dir) = dirs::config_dir() {
|
|
||||||
dir
|
|
||||||
} else {
|
|
||||||
return Err(Error::XdgVars);
|
|
||||||
};
|
|
||||||
|
|
||||||
path.push("rog");
|
|
||||||
if !path.exists() {
|
|
||||||
create_dir(path.clone())?;
|
|
||||||
}
|
|
||||||
|
|
||||||
path.push(name.clone() + ".cfg");
|
|
||||||
|
|
||||||
let mut file = OpenOptions::new()
|
|
||||||
.read(true)
|
|
||||||
.write(true)
|
|
||||||
.create(true)
|
|
||||||
.open(&path)?;
|
|
||||||
|
|
||||||
let mut buf = String::new();
|
|
||||||
|
|
||||||
if let Ok(read_len) = file.read_to_string(&mut buf) {
|
|
||||||
if read_len == 0 {
|
|
||||||
let default = Self::default_with_name(name);
|
|
||||||
let json = serde_json::to_string_pretty(&default).unwrap();
|
|
||||||
file.write_all(json.as_bytes())?;
|
|
||||||
return Ok(default);
|
|
||||||
} else if let Ok(data) = serde_json::from_str::<T>(&buf) {
|
|
||||||
return Ok(data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Err(Error::ConfigLoadFail)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize)]
|
#[derive(Debug, Deserialize, Serialize)]
|
||||||
pub struct UserAnimeConfig {
|
pub struct ConfigAnime {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub anime: Vec<ActionLoader>,
|
pub anime: Vec<ActionLoader>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl UserAnimeConfig {
|
impl ConfigAnime {
|
||||||
pub fn create(&self, anime_type: AnimeType) -> Result<AnimeSequences, Error> {
|
pub fn create(&self, anime_type: AnimeType) -> Result<AnimeSequences, Error> {
|
||||||
let mut seq = AnimeSequences::new(anime_type);
|
let mut seq = AnimeSequences::new(anime_type);
|
||||||
|
|
||||||
@@ -96,25 +34,17 @@ impl UserAnimeConfig {
|
|||||||
|
|
||||||
Ok(seq)
|
Ok(seq)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl ConfigLoadSave<UserAnimeConfig> for UserAnimeConfig {
|
pub fn set_name(mut self, name: String) -> Self {
|
||||||
fn name(&self) -> String {
|
self.name = name;
|
||||||
self.name.clone()
|
self
|
||||||
}
|
|
||||||
|
|
||||||
fn default_with_name(name: String) -> Self {
|
|
||||||
UserAnimeConfig {
|
|
||||||
name,
|
|
||||||
..Default::default()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for UserAnimeConfig {
|
impl Default for ConfigAnime {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
name: "default".to_owned(),
|
name: "anime-default".to_owned(),
|
||||||
anime: vec![
|
anime: vec![
|
||||||
ActionLoader::AsusImage {
|
ActionLoader::AsusImage {
|
||||||
file: "/usr/share/asusd/anime/custom/diagonal-template.png".into(),
|
file: "/usr/share/asusd/anime/custom/diagonal-template.png".into(),
|
||||||
@@ -172,26 +102,36 @@ impl Default for UserAnimeConfig {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl StdConfig for ConfigAnime {
|
||||||
|
fn new() -> Self {
|
||||||
|
Self::default()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn file_name(&self) -> String {
|
||||||
|
format!("{}.ron", self.name)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn config_dir() -> std::path::PathBuf {
|
||||||
|
root_conf_dir()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl StdConfigLoad1 for ConfigAnime {}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize)]
|
#[derive(Debug, Deserialize, Serialize)]
|
||||||
pub struct UserAuraConfig {
|
pub struct ConfigAura {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub aura: AuraSequences,
|
pub aura: AuraSequences,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ConfigLoadSave<UserAuraConfig> for UserAuraConfig {
|
impl ConfigAura {
|
||||||
fn name(&self) -> String {
|
pub fn set_name(mut self, name: String) -> Self {
|
||||||
self.name.clone()
|
self.name = name;
|
||||||
}
|
self
|
||||||
|
|
||||||
fn default_with_name(name: String) -> Self {
|
|
||||||
UserAuraConfig {
|
|
||||||
name,
|
|
||||||
..Default::default()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for UserAuraConfig {
|
impl Default for ConfigAura {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
let mut seq = AuraSequences::new(false);
|
let mut seq = AuraSequences::new(false);
|
||||||
let mut key = Effect::Breathe(Breathe::new(
|
let mut key = Effect::Breathe(Breathe::new(
|
||||||
@@ -228,86 +168,52 @@ impl Default for UserAuraConfig {
|
|||||||
seq.push(key);
|
seq.push(key);
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
name: "default".to_owned(),
|
name: "aura-default".to_owned(),
|
||||||
aura: seq,
|
aura: seq,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl StdConfig for ConfigAura {
|
||||||
|
fn new() -> Self {
|
||||||
|
Self::default()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn file_name(&self) -> String {
|
||||||
|
format!("{}.ron", self.name)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn config_dir() -> std::path::PathBuf {
|
||||||
|
root_conf_dir()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl StdConfigLoad1 for ConfigAura {}
|
||||||
|
|
||||||
#[derive(Debug, Default, Deserialize, Serialize)]
|
#[derive(Debug, Default, Deserialize, Serialize)]
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub struct UserConfig {
|
pub struct ConfigBase {
|
||||||
/// Name of active anime config file in the user config directory
|
/// Name of active anime config file in the user config directory
|
||||||
pub active_anime: Option<String>,
|
pub active_anime: Option<String>,
|
||||||
/// Name of active aura config file in the user config directory
|
/// Name of active aura config file in the user config directory
|
||||||
pub active_aura: Option<String>,
|
pub active_aura: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl UserConfig {
|
impl StdConfig for ConfigBase {
|
||||||
pub fn new() -> Self {
|
fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
active_anime: Some("anime-default".to_owned()),
|
active_anime: Some("anime-default".to_owned()),
|
||||||
active_aura: Some("aura-default".to_owned()),
|
active_aura: Some("aura-default".to_owned()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn load(&mut self) -> Result<(), Error> {
|
fn file_name(&self) -> String {
|
||||||
let mut path = if let Some(dir) = dirs::config_dir() {
|
"rog-user.ron".to_owned()
|
||||||
dir
|
|
||||||
} else {
|
|
||||||
return Err(Error::XdgVars);
|
|
||||||
};
|
|
||||||
|
|
||||||
path.push("rog");
|
|
||||||
if !path.exists() {
|
|
||||||
create_dir(path.clone())?;
|
|
||||||
}
|
|
||||||
|
|
||||||
path.push("rog-user.cfg");
|
|
||||||
|
|
||||||
let mut file = OpenOptions::new()
|
|
||||||
.read(true)
|
|
||||||
.write(true)
|
|
||||||
.create(true)
|
|
||||||
.open(&path)?;
|
|
||||||
|
|
||||||
let mut buf = String::new();
|
|
||||||
|
|
||||||
if let Ok(read_len) = file.read_to_string(&mut buf) {
|
|
||||||
if read_len == 0 {
|
|
||||||
let json = serde_json::to_string_pretty(&self).unwrap();
|
|
||||||
file.write_all(json.as_bytes())?;
|
|
||||||
} else if let Ok(data) = serde_json::from_str::<UserConfig>(&buf) {
|
|
||||||
self.active_anime = data.active_anime;
|
|
||||||
self.active_aura = data.active_aura;
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn write(&self) -> Result<(), Error> {
|
fn config_dir() -> std::path::PathBuf {
|
||||||
let mut path = if let Some(dir) = dirs::config_dir() {
|
root_conf_dir()
|
||||||
dir
|
|
||||||
} else {
|
|
||||||
return Err(Error::XdgVars);
|
|
||||||
};
|
|
||||||
|
|
||||||
path.push("rog");
|
|
||||||
if !path.exists() {
|
|
||||||
create_dir(path.clone())?;
|
|
||||||
}
|
|
||||||
|
|
||||||
path.push("rog-user.cfg");
|
|
||||||
|
|
||||||
let mut file = OpenOptions::new()
|
|
||||||
.write(true)
|
|
||||||
.create(true)
|
|
||||||
.truncate(true)
|
|
||||||
.open(&path)?;
|
|
||||||
|
|
||||||
let json = serde_json::to_string_pretty(&self).unwrap();
|
|
||||||
file.write_all(json.as_bytes())?;
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl StdConfigLoad1 for ConfigBase {}
|
||||||
@@ -4,6 +4,7 @@ use std::sync::{Arc, Mutex};
|
|||||||
use std::thread::sleep;
|
use std::thread::sleep;
|
||||||
use std::time::{Duration, Instant};
|
use std::time::{Duration, Instant};
|
||||||
|
|
||||||
|
use config_traits::StdConfig;
|
||||||
use rog_anime::error::AnimeError;
|
use rog_anime::error::AnimeError;
|
||||||
use rog_anime::{ActionData, ActionLoader, AnimTime, Fade, Sequences, Vec2};
|
use rog_anime::{ActionData, ActionLoader, AnimTime, Fade, Sequences, Vec2};
|
||||||
use rog_dbus::RogDbusClientBlocking;
|
use rog_dbus::RogDbusClientBlocking;
|
||||||
@@ -11,8 +12,8 @@ use serde_derive::{Deserialize, Serialize};
|
|||||||
use zbus::dbus_interface;
|
use zbus::dbus_interface;
|
||||||
use zbus::zvariant::{ObjectPath, Type};
|
use zbus::zvariant::{ObjectPath, Type};
|
||||||
|
|
||||||
|
use crate::config::ConfigAnime;
|
||||||
use crate::error::Error;
|
use crate::error::Error;
|
||||||
use crate::user_config::{ConfigLoadSave, UserAnimeConfig};
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Deserialize, Serialize, Type)]
|
#[derive(Debug, Clone, Deserialize, Serialize, Type)]
|
||||||
pub struct Timer {
|
pub struct Timer {
|
||||||
@@ -134,7 +135,7 @@ impl<'a> CtrlAnimeInner<'static> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct CtrlAnime<'a> {
|
pub struct CtrlAnime<'a> {
|
||||||
config: Arc<Mutex<UserAnimeConfig>>,
|
config: Arc<Mutex<ConfigAnime>>,
|
||||||
client: RogDbusClientBlocking<'a>,
|
client: RogDbusClientBlocking<'a>,
|
||||||
inner: Arc<Mutex<CtrlAnimeInner<'a>>>,
|
inner: Arc<Mutex<CtrlAnimeInner<'a>>>,
|
||||||
/// Must be the same Atomic as in CtrlAnimeInner
|
/// Must be the same Atomic as in CtrlAnimeInner
|
||||||
@@ -143,7 +144,7 @@ pub struct CtrlAnime<'a> {
|
|||||||
|
|
||||||
impl CtrlAnime<'static> {
|
impl CtrlAnime<'static> {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
config: Arc<Mutex<UserAnimeConfig>>,
|
config: Arc<Mutex<ConfigAnime>>,
|
||||||
inner: Arc<Mutex<CtrlAnimeInner<'static>>>,
|
inner: Arc<Mutex<CtrlAnimeInner<'static>>>,
|
||||||
client: RogDbusClientBlocking<'static>,
|
client: RogDbusClientBlocking<'static>,
|
||||||
inner_early_return: Arc<AtomicBool>,
|
inner_early_return: Arc<AtomicBool>,
|
||||||
@@ -206,7 +207,7 @@ impl CtrlAnime<'static> {
|
|||||||
.map_err(|err| zbus::fdo::Error::Failed(err.to_string()))?;
|
.map_err(|err| zbus::fdo::Error::Failed(err.to_string()))?;
|
||||||
}
|
}
|
||||||
config.anime.push(action);
|
config.anime.push(action);
|
||||||
config.write()?;
|
config.write();
|
||||||
|
|
||||||
let json = serde_json::to_string_pretty(&*config).expect("Parse config to JSON failed");
|
let json = serde_json::to_string_pretty(&*config).expect("Parse config to JSON failed");
|
||||||
|
|
||||||
@@ -251,7 +252,7 @@ impl CtrlAnime<'static> {
|
|||||||
.map_err(|err| zbus::fdo::Error::Failed(err.to_string()))?;
|
.map_err(|err| zbus::fdo::Error::Failed(err.to_string()))?;
|
||||||
}
|
}
|
||||||
config.anime.push(action);
|
config.anime.push(action);
|
||||||
config.write()?;
|
config.write();
|
||||||
|
|
||||||
let json =
|
let json =
|
||||||
serde_json::to_string_pretty(&*config.anime).expect("Parse config to JSON failed");
|
serde_json::to_string_pretty(&*config.anime).expect("Parse config to JSON failed");
|
||||||
@@ -296,7 +297,7 @@ impl CtrlAnime<'static> {
|
|||||||
.map_err(|err| zbus::fdo::Error::Failed(err.to_string()))?;
|
.map_err(|err| zbus::fdo::Error::Failed(err.to_string()))?;
|
||||||
}
|
}
|
||||||
config.anime.push(action);
|
config.anime.push(action);
|
||||||
config.write()?;
|
config.write();
|
||||||
|
|
||||||
let json =
|
let json =
|
||||||
serde_json::to_string_pretty(&*config.anime).expect("Parse config to JSON failed");
|
serde_json::to_string_pretty(&*config.anime).expect("Parse config to JSON failed");
|
||||||
@@ -321,7 +322,7 @@ impl CtrlAnime<'static> {
|
|||||||
.map_err(|err| zbus::fdo::Error::Failed(err.to_string()))?;
|
.map_err(|err| zbus::fdo::Error::Failed(err.to_string()))?;
|
||||||
}
|
}
|
||||||
config.anime.push(action);
|
config.anime.push(action);
|
||||||
config.write()?;
|
config.write();
|
||||||
|
|
||||||
let json =
|
let json =
|
||||||
serde_json::to_string_pretty(&*config.anime).expect("Parse config to JSON failed");
|
serde_json::to_string_pretty(&*config.anime).expect("Parse config to JSON failed");
|
||||||
@@ -344,7 +345,7 @@ impl CtrlAnime<'static> {
|
|||||||
if (index as usize) < config.anime.len() {
|
if (index as usize) < config.anime.len() {
|
||||||
config.anime.remove(index as usize);
|
config.anime.remove(index as usize);
|
||||||
}
|
}
|
||||||
config.write()?;
|
config.write();
|
||||||
|
|
||||||
let json =
|
let json =
|
||||||
serde_json::to_string_pretty(&*config.anime).expect("Parse config to JSON failed");
|
serde_json::to_string_pretty(&*config.anime).expect("Parse config to JSON failed");
|
||||||
|
|||||||
@@ -1,15 +1,16 @@
|
|||||||
use std::fs::OpenOptions;
|
use std::fs::OpenOptions;
|
||||||
use std::io::Read;
|
use std::io::{Read, Write};
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::sync::atomic::AtomicBool;
|
use std::sync::atomic::AtomicBool;
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
|
|
||||||
|
use config_traits::{StdConfig, StdConfigLoad1};
|
||||||
use rog_anime::usb::get_anime_type;
|
use rog_anime::usb::get_anime_type;
|
||||||
use rog_aura::aura_detection::LaptopLedData;
|
use rog_aura::aura_detection::LaptopLedData;
|
||||||
use rog_aura::layouts::KeyLayout;
|
use rog_aura::layouts::KeyLayout;
|
||||||
use rog_dbus::RogDbusClientBlocking;
|
use rog_dbus::RogDbusClientBlocking;
|
||||||
|
use rog_user::config::*;
|
||||||
use rog_user::ctrl_anime::{CtrlAnime, CtrlAnimeInner};
|
use rog_user::ctrl_anime::{CtrlAnime, CtrlAnimeInner};
|
||||||
use rog_user::user_config::*;
|
|
||||||
use rog_user::DBUS_NAME;
|
use rog_user::DBUS_NAME;
|
||||||
use smol::Executor;
|
use smol::Executor;
|
||||||
use zbus::Connection;
|
use zbus::Connection;
|
||||||
@@ -21,6 +22,13 @@ const DATA_DIR: &str = env!("CARGO_MANIFEST_DIR");
|
|||||||
const BOARD_NAME: &str = "/sys/class/dmi/id/board_name";
|
const BOARD_NAME: &str = "/sys/class/dmi/id/board_name";
|
||||||
|
|
||||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
|
let mut logger = env_logger::Builder::new();
|
||||||
|
logger
|
||||||
|
.parse_default_env()
|
||||||
|
.target(env_logger::Target::Stdout)
|
||||||
|
.format(|buf, record| writeln!(buf, "{}: {}", record.level(), record.args()))
|
||||||
|
.init();
|
||||||
|
|
||||||
println!(" user daemon v{}", rog_user::VERSION);
|
println!(" user daemon v{}", rog_user::VERSION);
|
||||||
println!(" rog-anime v{}", rog_anime::VERSION);
|
println!(" rog-anime v{}", rog_anime::VERSION);
|
||||||
println!(" rog-dbus v{}", rog_dbus::VERSION);
|
println!(" rog-dbus v{}", rog_dbus::VERSION);
|
||||||
@@ -29,8 +37,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
let (client, _) = RogDbusClientBlocking::new()?;
|
let (client, _) = RogDbusClientBlocking::new()?;
|
||||||
let supported = client.proxies().supported().supported_functions()?;
|
let supported = client.proxies().supported().supported_functions()?;
|
||||||
|
|
||||||
let mut config = UserConfig::new();
|
let config = ConfigBase::new().load();
|
||||||
config.load()?;
|
|
||||||
|
|
||||||
let executor = Executor::new();
|
let executor = Executor::new();
|
||||||
|
|
||||||
@@ -39,7 +46,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
if supported.anime_ctrl.0 {
|
if supported.anime_ctrl.0 {
|
||||||
if let Some(cfg) = config.active_anime {
|
if let Some(cfg) = config.active_anime {
|
||||||
let anime_type = get_anime_type()?;
|
let anime_type = get_anime_type()?;
|
||||||
let anime_config = UserAnimeConfig::load(cfg)?;
|
let anime_config = ConfigAnime::new().set_name(cfg).load();
|
||||||
let anime = anime_config.create(anime_type)?;
|
let anime = anime_config.create(anime_type)?;
|
||||||
let anime_config = Arc::new(Mutex::new(anime_config));
|
let anime_config = Arc::new(Mutex::new(anime_config));
|
||||||
|
|
||||||
@@ -70,7 +77,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
|
|
||||||
// if supported.keyboard_led.per_key_led_mode {
|
// if supported.keyboard_led.per_key_led_mode {
|
||||||
if let Some(cfg) = config.active_aura {
|
if let Some(cfg) = config.active_aura {
|
||||||
let mut aura_config = UserAuraConfig::load(cfg)?;
|
let mut aura_config = ConfigAura::new().set_name(cfg).load();
|
||||||
|
|
||||||
// Find and load a matching layout for laptop
|
// Find and load a matching layout for laptop
|
||||||
let mut file = OpenOptions::new()
|
let mut file = OpenOptions::new()
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
pub mod user_config;
|
pub mod config;
|
||||||
|
|
||||||
pub mod error;
|
pub mod error;
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use config_traits::{StdConfig, StdConfigLoad3};
|
use config_traits::{StdConfig, StdConfigLoad3};
|
||||||
use serde_derive::{Deserialize, Serialize};
|
use serde_derive::{Deserialize, Serialize};
|
||||||
|
|
||||||
const CONFIG_FILE: &str = "asusd.conf";
|
const CONFIG_FILE: &str = "asusd.ron";
|
||||||
|
|
||||||
#[derive(Deserialize, Serialize, Default)]
|
#[derive(Deserialize, Serialize, Default)]
|
||||||
pub struct Config {
|
pub struct Config {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ use rog_anime::error::AnimeError;
|
|||||||
use rog_anime::{ActionData, ActionLoader, AnimTime, AnimeType, Fade, Vec2};
|
use rog_anime::{ActionData, ActionLoader, AnimTime, AnimeType, Fade, Vec2};
|
||||||
use serde_derive::{Deserialize, Serialize};
|
use serde_derive::{Deserialize, Serialize};
|
||||||
|
|
||||||
const CONFIG_FILE: &str = "anime.conf";
|
const CONFIG_FILE: &str = "anime.ron";
|
||||||
|
|
||||||
#[derive(Deserialize, Serialize)]
|
#[derive(Deserialize, Serialize)]
|
||||||
pub struct AnimeConfigV341 {
|
pub struct AnimeConfigV341 {
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ use rog_platform::hid_raw::HidRaw;
|
|||||||
use rog_platform::keyboard_led::KeyboardLed;
|
use rog_platform::keyboard_led::KeyboardLed;
|
||||||
use serde_derive::{Deserialize, Serialize};
|
use serde_derive::{Deserialize, Serialize};
|
||||||
|
|
||||||
const CONFIG_FILE: &str = "aura.conf";
|
const CONFIG_FILE: &str = "aura.ron";
|
||||||
|
|
||||||
/// Enable/disable LED control in various states such as
|
/// Enable/disable LED control in various states such as
|
||||||
/// when the device is awake, suspended, shutting down or
|
/// when the device is awake, suspended, shutting down or
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ use serde_derive::{Deserialize, Serialize};
|
|||||||
|
|
||||||
use crate::CONFIG_PATH_BASE;
|
use crate::CONFIG_PATH_BASE;
|
||||||
|
|
||||||
const CONFIG_FILE: &str = "profile.conf";
|
const CONFIG_FILE: &str = "profile.ron";
|
||||||
const CONFIG_FAN_FILE: &str = "fan_curves.conf";
|
const CONFIG_FAN_FILE: &str = "fan_curves.ron";
|
||||||
|
|
||||||
#[derive(Deserialize, Serialize, Debug)]
|
#[derive(Deserialize, Serialize, Debug)]
|
||||||
pub struct ProfileConfig {
|
pub struct ProfileConfig {
|
||||||
|
|||||||
Reference in New Issue
Block a user