diff --git a/rog-core/src/daemon.rs b/rog-core/src/daemon.rs index 3b443448..d0be5622 100644 --- a/rog-core/src/daemon.rs +++ b/rog-core/src/daemon.rs @@ -13,9 +13,9 @@ use dbus_tokio::connection; use log::{error, info, warn}; use rog_client::{DBUS_IFACE, DBUS_NAME, DBUS_PATH}; use std::error::Error; -use std::sync::{mpsc, Arc}; +use std::sync::Arc; use std::time::{Duration, Instant}; -use tokio::sync::Mutex; +use tokio::sync::{mpsc, Mutex}; pub(super) type FanModeType = Arc>>; pub(super) type LedMsgType = Arc>>>; @@ -87,10 +87,14 @@ pub async fn start_daemon() -> Result<(), Box> { .request_name(DBUS_NAME, false, true, true) .await?; - let (aura_command_send, aura_command_recv) = mpsc::sync_channel::(1); - - let (tree, input, effect, mut animatrix_recv, fan_mode, effect_cancel_signal) = - dbus_create_tree(); + let ( + tree, + aura_command_sender, + mut aura_command_recv, + mut animatrix_recv, + fan_mode, + effect_cancel_signal, + ) = dbus_create_tree(); // We add the tree to the connection so that incoming method calls will be handled. tree.start_receive_send(&*connection); @@ -115,11 +119,10 @@ pub async fn start_daemon() -> Result<(), Box> { .unwrap_or_else(|err| warn!("{:?}", err)); } } - let acs = aura_command_send.clone(); let data = keyboard_reader.poll_keyboard().await; if let Some(bytes) = data { laptop - .run(&mut rogcore, &config1, bytes, acs) + .run(&mut rogcore, &config1, bytes, aura_command_sender.clone()) .await .unwrap_or_else(|err| warn!("{:?}", err)); } @@ -128,80 +131,31 @@ pub async fn start_daemon() -> Result<(), Box> { // start the LED writer loop let led_write_handle = tokio::spawn(async move { - let mut time_mark = Instant::now(); loop { - connection.process_all(); + //connection.process_all(); // Check if a key press issued a command - let res = aura_command_recv.recv_timeout(Duration::from_micros(50)); - if let Ok(command) = res { + while let Some(command) = aura_command_recv.recv().await { let mut config = config.lock().await; - led_writer - .do_command(command, &mut config) - .await - .unwrap_or_else(|err| warn!("{:?}", err)); - - connection - .send( - effect_cancel_signal - .msg(&DBUS_PATH.into(), &DBUS_IFACE.into()) - .append1(true), - ) - .unwrap_or_else(|_| 0); - // Clear any possible queued effect - let mut effect = effect.lock().await; - *effect = None; - time_mark = Instant::now(); - } else { - // Check if single mode - if let Ok(mut lock) = input.try_lock() { - if let Some(bytes) = lock.take() { - if !bytes.is_empty() { - let mut config = config.lock().await; - led_writer - .do_command(AuraCommand::WriteBytes(bytes), &mut config) - .await - .unwrap_or_else(|err| warn!("{:?}", err)); - // Also cancel any effect client - connection - .send( - effect_cancel_signal.msg(&DBUS_PATH.into(), &DBUS_IFACE.into()), - ) - .unwrap(); - time_mark = Instant::now(); - } + match command { + AuraCommand::WriteEffect(_) | AuraCommand::WriteMultizone(_) => led_writer + .do_command(command, &mut config) + .await + .unwrap_or_else(|err| warn!("{:?}", err)), + _ => { + led_writer + .do_command(command, &mut config) + .await + .unwrap_or_else(|err| warn!("{:?}", err)); + connection + .send( + effect_cancel_signal + .msg(&DBUS_PATH.into(), &DBUS_IFACE.into()) + .append1(true), + ) + .unwrap_or_else(|_| 0); } } - // Write a colour block - let mut effect_lock = effect.lock().await; - if let Some(effect) = effect_lock.take() { - if effect.len() == 11 { - let mut config = config.lock().await; - if effect.len() > 4 { - led_writer - .do_command(AuraCommand::WriteEffect(effect), &mut config) - .await - .unwrap_or_else(|err| warn!("{:?}", err)); - } else { - led_writer - .do_command(AuraCommand::WriteMultizone(effect), &mut config) - .await - .unwrap_or_else(|err| warn!("{:?}", err)); - } - time_mark = Instant::now(); - } - } - } - - let now = Instant::now(); - // Cool-down steps - // This block is to prevent the loop spooling as fast as possible and saturating the CPU - if now.duration_since(time_mark).as_millis() > 500 { - tokio::time::delay_for(Duration::from_millis(200)).await; - } else if now.duration_since(time_mark).as_millis() > 100 { - tokio::time::delay_for(Duration::from_millis(50)).await; - } else { - tokio::time::delay_for(Duration::from_micros(300)).await; } } }); diff --git a/rog-core/src/laptops.rs b/rog-core/src/laptops.rs index bac6a1fe..09c0cae7 100644 --- a/rog-core/src/laptops.rs +++ b/rog-core/src/laptops.rs @@ -109,8 +109,7 @@ pub(super) struct LaptopBase { //backlight: Backlight, } -use std::sync::mpsc; -use tokio::sync::Mutex; +use tokio::sync::{mpsc, Mutex}; impl LaptopBase { /// Pass in LedWriter as Mutex so it is only locked when required @@ -119,7 +118,7 @@ impl LaptopBase { rogcore: &mut RogCore, config: &Mutex, key_buf: [u8; 32], - aura_command: mpsc::SyncSender, + aura_command: mpsc::Sender, ) -> Result<(), AuraError> { match self.usb_product { 0x1869 | 0x1866 => { @@ -168,20 +167,32 @@ impl LaptopBase { rogcore: &mut RogCore, config: &Mutex, key_buf: [u8; 32], - aura_command: mpsc::SyncSender, + mut aura_command: mpsc::Sender, ) -> Result<(), AuraError> { match GX502Keys::from(key_buf[1]) { GX502Keys::LedBrightUp => { - aura_command.send(AuraCommand::BrightInc).unwrap(); + aura_command + .send(AuraCommand::BrightInc) + .await + .unwrap_or_else(|_| {}); } GX502Keys::LedBrightDown => { - aura_command.send(AuraCommand::BrightDec).unwrap(); + aura_command + .send(AuraCommand::BrightDec) + .await + .unwrap_or_else(|_| {}); } GX502Keys::AuraNext => { - aura_command.send(AuraCommand::BuiltinNext).unwrap(); + aura_command + .send(AuraCommand::BuiltinNext) + .await + .unwrap_or_else(|_| {}); } GX502Keys::AuraPrevious => { - aura_command.send(AuraCommand::BuiltinPrev).unwrap(); + aura_command + .send(AuraCommand::BuiltinPrev) + .await + .unwrap_or_else(|_| {}); } GX502Keys::ScreenBrightUp => { rogcore.virt_keys().press(ConsumerKeys::BacklightInc.into()) @@ -231,14 +242,20 @@ impl LaptopBase { rogcore: &mut RogCore, _config: &Mutex, key_buf: [u8; 32], - aura_command: mpsc::SyncSender, + mut aura_command: mpsc::Sender, ) -> Result<(), AuraError> { match GL753Keys::from(key_buf[1]) { GL753Keys::LedBrightUp => { - aura_command.send(AuraCommand::BrightInc).unwrap(); + aura_command + .send(AuraCommand::BrightInc) + .await + .unwrap_or_else(|_| {}); } GL753Keys::LedBrightDown => { - aura_command.send(AuraCommand::BrightDec).unwrap(); + aura_command + .send(AuraCommand::BrightDec) + .await + .unwrap_or_else(|_| {}); } GL753Keys::ScreenBrightUp => { rogcore.virt_keys().press(ConsumerKeys::BacklightInc.into()) diff --git a/rog-core/src/rog_dbus.rs b/rog-core/src/rog_dbus.rs index 1c41b00a..5a447726 100644 --- a/rog-core/src/rog_dbus.rs +++ b/rog-core/src/rog_dbus.rs @@ -1,6 +1,8 @@ use crate::daemon::{FanModeType, LedMsgType, NestedVecType}; +use crate::led_control::AuraCommand; use crate::rogcore::FanLevel; use dbus::tree::{Factory, MTSync, Method, MethodErr, Signal, Tree}; +use log::{error, info, warn}; use rog_client::{DBUS_IFACE, DBUS_PATH}; use std::sync::Arc; use tokio::sync::{ @@ -8,15 +10,17 @@ use tokio::sync::{ Mutex, }; -pub(super) fn dbus_create_ledmsg_method(msg: LedMsgType) -> Method { +pub(super) fn dbus_create_ledmsg_method(sender: Mutex>) -> Method { let factory = Factory::new_sync::<()>(); factory // method for ledmessage .method("LedWriteBytes", (), { move |m| { let bytes: Vec = m.msg.read1()?; - if let Ok(mut lock) = msg.try_lock() { - *lock = Some(bytes.to_vec()); + if let Ok(mut lock) = sender.try_lock() { + let command = AuraCommand::WriteBytes(bytes.to_vec()); + lock.try_send(command) + .unwrap_or_else(|err| warn!("LedWriteBytes over mpsc failed: {}", err)); let mret = m .msg .method_return() @@ -31,17 +35,21 @@ pub(super) fn dbus_create_ledmsg_method(msg: LedMsgType) -> Method { .inarg::, _>("bytearray") } -pub(super) fn dbus_create_ledmultizone_method(effect: NestedVecType) -> Method { +pub(super) fn dbus_create_ledmultizone_method( + sender: Mutex>, +) -> Method { let factory = Factory::new_sync::<()>(); factory // method for ledmessage .method("LedWriteMultizone", (), { move |m| { - if let Ok(mut lock) = effect.try_lock() { + if let Ok(mut lock) = sender.try_lock() { let mut iter = m.msg.iter_init(); let byte_array: Vec> = vec![iter.read()?, iter.read()?, iter.read()?, iter.read()?]; - *lock = Some(byte_array); + let command = AuraCommand::WriteMultizone(byte_array); + lock.try_send(command) + .unwrap_or_else(|err| warn!("LedWriteMultizone over mpsc failed: {}", err)); let mret = m .msg .method_return() @@ -60,13 +68,15 @@ pub(super) fn dbus_create_ledmultizone_method(effect: NestedVecType) -> Method Method { +pub(super) fn dbus_create_ledeffect_method( + sender: Mutex>, +) -> Method { let factory = Factory::new_sync::<()>(); factory // method for ledmessage .method("LedWriteEffect", (), { move |m| { - if let Ok(mut lock) = effect.try_lock() { + if let Ok(mut lock) = sender.try_lock() { let mut iter = m.msg.iter_init(); let byte_array: Vec> = vec![ iter.read()?, @@ -81,7 +91,9 @@ pub(super) fn dbus_create_ledeffect_method(effect: NestedVecType) -> Method Method ( Tree, - LedMsgType, - NestedVecType, + Sender, + Receiver, Receiver>>, FanModeType, Arc>, ) { - let input_bytes: LedMsgType = Arc::new(Mutex::new(None)); - let input_effect: NestedVecType = Arc::new(Mutex::new(None)); + let (aura_command_send, aura_command_recv) = channel::(1); let (animatrix_send, animatrix_recv) = channel::>>(1); let fan_mode: FanModeType = Arc::new(Mutex::new(None)); @@ -171,9 +182,15 @@ pub(super) fn dbus_create_tree() -> ( factory.object_path(DBUS_PATH, ()).introspectable().add( factory .interface(DBUS_IFACE, ()) - .add_m(dbus_create_ledmsg_method(input_bytes.clone())) - .add_m(dbus_create_ledmultizone_method(input_effect.clone())) - .add_m(dbus_create_ledeffect_method(input_effect.clone())) + .add_m(dbus_create_ledmsg_method(Mutex::new( + aura_command_send.clone(), + ))) + .add_m(dbus_create_ledmultizone_method(Mutex::new( + aura_command_send.clone(), + ))) + .add_m(dbus_create_ledeffect_method(Mutex::new( + aura_command_send.clone(), + ))) .add_m(dbus_create_animatrix_method(Mutex::new(animatrix_send))) .add_m(dbus_create_fan_mode_method(fan_mode.clone())) .add_s(effect_cancel_sig.clone()), @@ -182,8 +199,8 @@ pub(super) fn dbus_create_tree() -> ( .add(factory.object_path("/", ()).introspectable()); ( tree, - input_bytes, - input_effect, + aura_command_send, + aura_command_recv, animatrix_recv, fan_mode, effect_cancel_sig,