diff --git a/src/config.rs b/src/config.rs index d7c2ee8..8420773 100644 --- a/src/config.rs +++ b/src/config.rs @@ -4,7 +4,7 @@ use log::{error, info}; use std::fs::File; use std::io::Write; -use crate::ui_code::AppState; +use crate::ui::AppState; pub fn load_config() -> AppState { let settings = Config::builder() diff --git a/src/coordinator.rs b/src/coordinator.rs index a9602e6..3d20ef1 100644 --- a/src/coordinator.rs +++ b/src/coordinator.rs @@ -3,6 +3,7 @@ use std::sync::{ atomic::{AtomicBool, Ordering}, Arc, }; +use std::time::{Duration, Instant}; use async_channel::{Receiver, Sender}; use futures_util::{ @@ -15,7 +16,10 @@ use tokio::runtime::Handle; use tokio_tungstenite::{connect_async, tungstenite::Message, MaybeTlsStream, WebSocketStream}; use crate::remote_sources; -use crate::{joystick_source::joystick_loop, ui_code::GuiUpdate}; +use crate::{joystick_source::joystick_loop, ui::GuiUpdate}; + + +const PRIORITY_TIMEOUT: Duration = Duration::from_secs(2); #[derive(Clone)] pub struct MoveEvent { @@ -23,6 +27,7 @@ pub struct MoveEvent { pub y: i32, } +#[derive(Clone, Copy, PartialEq, PartialOrd, Debug)] pub enum ConnectionType { Local, Remote, @@ -41,6 +46,9 @@ struct CoordState<'a> { pub sck_alive_recvr: Arc, pub joystick_loop_alive: Arc, + pub current_priority: ConnectionType, + pub last_update_of_priority: Instant, + pub mec: Pin<&'a mut Receiver>, pub to_mec: Sender, pub to_gui: Sender, @@ -60,6 +68,9 @@ impl<'a> CoordState<'a> { sck_alive_server: Arc::new(AtomicBool::new(false)), joystick_loop_alive: Arc::new(AtomicBool::new(false)), + current_priority: ConnectionType::Local, + last_update_of_priority: Instant::now(), + mec, to_mec, to_gui, @@ -185,20 +196,27 @@ pub async fn start_coordinator( state.socket_send(socket_message).await; } ApplicationEvent::MoveEvent(coord, priority) => { - if let Err(e) = state.to_gui.send(GuiUpdate::MoveEvent(coord.clone())).await { - panic!("Could not set message to gui channel; Unrecoverable: {e}"); - } + // If Automatic control, but local event happens, override the automatice events for 2 seconds + if priority <= state.current_priority || Instant::now() > state.last_update_of_priority + PRIORITY_TIMEOUT { + state.last_update_of_priority = Instant::now(); + state.current_priority = priority; - if state.socket_connected() { - let message = format!( - "{}{}:{}{}", - if coord.y > 0 { "D" } else { "U" }, - coord.y.abs(), - if coord.x > 0 { "R" } else { "L" }, - coord.x.abs() - ); + if let Err(e) = state.to_gui.send(GuiUpdate::MoveEvent(coord.clone())).await { + panic!("Could not set message to gui channel; Unrecoverable: {e}"); + } + + if state.socket_connected() { + let message = format!( + "{}{}:{}{}", + if coord.y > 0 { "D" } else { "U" }, + coord.y.abs(), + if coord.x > 0 { "R" } else { "L" }, + coord.x.abs() + ); + + state.socket_send(Message::Text(message)).await; + } - state.socket_send(Message::Text(message)).await; } } } diff --git a/src/main.rs b/src/main.rs index 41ee91f..8dcf1d1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -10,7 +10,7 @@ mod config; mod coordinator; mod joystick_source; mod remote_sources; -mod ui_code; +mod ui; const APP_ID: &str = "net.nickiel.joystick-controller-client"; fn main() -> glib::ExitCode { @@ -30,7 +30,7 @@ fn main() -> glib::ExitCode { app.connect_startup(|_| load_css()); app.connect_activate(move |app| { - ui_code::build_ui(app, handle.clone()); + ui::build_ui(app, handle.clone()); }); let exit_code = app.run(); diff --git a/src/ui_code.rs b/src/ui/mod.rs similarity index 99% rename from src/ui_code.rs rename to src/ui/mod.rs index dcdc74b..2ee0d11 100644 --- a/src/ui_code.rs +++ b/src/ui/mod.rs @@ -1,3 +1,4 @@ + use gtk::{glib, prelude::*, Box, Entry, Label, ListBox}; use gtk::{Application, ApplicationWindow, Button}; use log::error; @@ -167,4 +168,4 @@ pub fn build_ui(app: &Application, runtime: Handle) { // Present window window.present(); -} +} \ No newline at end of file