use crate::config::save_config; use crate::ui_code::{AppState, SocketConnectionUpdate}; use crate::JoystickThreadUpdate; use async_channel::{Receiver, Sender}; use gilrs::{ev::filter::FilterFn, Axis, Button, Event, EventType, Filter, Gilrs, GilrsBuilder}; use std::panic::{self, AssertUnwindSafe}; use std::{ sync::{atomic::AtomicBool, Arc}, time::{Duration, Instant}, }; use websocket::client::{sync::Client, ClientBuilder}; use websocket::Message; struct UnknownSlayer; impl FilterFn for UnknownSlayer { fn filter(&self, ev: Option, _gilrs: &mut Gilrs) -> Option { match ev { Some(Event { event: EventType::ButtonPressed(Button::Unknown, ..), id, .. }) | Some(Event { event: EventType::ButtonReleased(Button::Unknown, ..), id, .. }) | Some(Event { event: EventType::AxisChanged(Axis::Unknown, ..), id, .. }) => Some(Event::new(id, EventType::Dropped)), _ => ev, } } } pub fn joystick_websocket_loop( tx: Sender, do_run: Arc, rx: Receiver, ) { let mut gilrs = GilrsBuilder::new().set_update_state(false).build().unwrap(); let mut ip: String; let mut port: u32; let mut websocket: Option> = None; let mut curr_x: i32 = 0; let mut curr_y: i32 = 0; let mut last_update_time = Instant::now(); loop { match rx.try_recv() { Ok(msg) => { ip = msg.ip; port = msg.port; save_config(&AppState { ip: ip.clone(), port, }); println!("ws://{}:{}", ip, port); if let Some(mut x) = websocket { println!("closing websocket"); x.send_message(&Message::close()).unwrap(); x.shutdown().unwrap(); websocket = None; } else { websocket = { if let Ok(mut val) = ClientBuilder::new(format!("ws://{}:{}", ip, port).as_str()) { if let Ok(val2) = val.connect_insecure() { Some(val2) } else { println!("couldn't connect websocket! : Step 1"); None } } else { println!("couldn't connect websocket! : Step 2"); None } }; } } Err(async_channel::TryRecvError::Closed) => break, Err(async_channel::TryRecvError::Empty) => {} } match panic::catch_unwind(AssertUnwindSafe(|| { while let Some(evt) = gilrs.next_event().filter_ev(&UnknownSlayer {}, &mut gilrs) { match evt.event { gilrs::EventType::AxisChanged(gilrs::Axis::LeftStickY, val, _) => { curr_y = (val * 100.0) as i32; if curr_y > -10 && curr_y < 10 { curr_y = 0; } } gilrs::EventType::AxisChanged(gilrs::Axis::LeftStickX, val, _) => { curr_x = (val * 100.0) as i32; if curr_x > -10 && curr_x < 10 { curr_x = 0; } } _ => {} } } })) { Ok(_) => {} Err(_) => { println!("panic-causing event captured") } } if websocket.is_some() && Instant::now().duration_since(last_update_time) >= Duration::from_millis(150) { let mut message: String; if curr_y > 0 { message = format!("D{}:", curr_y); } else { message = format!("U{}:", curr_y.abs()); } if curr_x > 0 { message.push_str(&format!("R{}", curr_x)); } else { message.push_str(&format!("L{}", curr_x.abs())); } if let Some(mut websocket_tx) = websocket { websocket_tx.send_message(&Message::text(message)).unwrap(); websocket = Some(websocket_tx); } last_update_time = Instant::now(); continue; } match tx.try_send(JoystickThreadUpdate { connected: websocket.is_some(), x_axis: Some(curr_x.to_string()), y_axis: Some(curr_y.to_string()), }) { Ok(_) => {} Err(async_channel::TrySendError::Closed(_)) => break, Err(async_channel::TrySendError::Full(_)) => {} } if !do_run.load(std::sync::atomic::Ordering::SeqCst) { println!("Exiting thread"); break; } std::thread::sleep(Duration::from_millis(25)); } }