vcs-controller/src/joystick_loop.rs

108 lines
3.5 KiB
Rust
Raw Normal View History

2024-04-06 10:49:19 -07:00
use crate::coordinator::{ApplicationEvent, MoveEvent};
2024-03-25 16:28:13 -07:00
2024-04-06 10:49:19 -07:00
use async_channel::Sender;
2024-03-25 16:28:13 -07:00
use gilrs::{ev::filter::FilterFn, Axis, Button, Event, EventType, Filter, Gilrs, GilrsBuilder};
2024-04-06 11:05:18 -07:00
use log::{info, warn};
2024-03-25 16:28:13 -07:00
use std::{
2024-04-06 11:03:21 -07:00
panic::{self, AssertUnwindSafe},
sync::{atomic::AtomicBool, Arc},
time::Duration
2024-03-25 16:28:13 -07:00
};
2024-04-06 11:03:21 -07:00
static MAX_SENT_ZEROS: u32 = 10;
2024-03-26 18:56:33 -07:00
struct UnknownSlayer;
2024-03-25 16:28:13 -07:00
impl FilterFn for UnknownSlayer {
fn filter(&self, ev: Option<Event>, _gilrs: &mut Gilrs) -> Option<Event> {
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,
}
}
}
2024-04-06 10:49:19 -07:00
pub async fn joystick_loop(
tx: Sender<ApplicationEvent>,
is_alive: Arc<AtomicBool>
2024-03-25 16:28:13 -07:00
) {
let mut gilrs = GilrsBuilder::new().set_update_state(false).build().unwrap();
2024-04-06 10:49:19 -07:00
is_alive.store(true, std::sync::atomic::Ordering::SeqCst);
2024-04-06 10:49:19 -07:00
let mut curr_x: i32 = 0;
let mut curr_y: i32 = 0;
let mut past_x: i32 = 0;
let mut past_y: i32 = 0;
2024-04-06 11:03:21 -07:00
let mut count_zeros: u32 = 0;
2024-03-25 16:28:13 -07:00
loop {
2024-03-26 18:56:33 -07:00
// catch unwind because some buttons on the joystick will panic the gilrs object
2024-03-25 16:28:13 -07:00
match panic::catch_unwind(AssertUnwindSafe(|| {
2024-03-26 18:56:33 -07:00
// get the next event, and if it is an axis we are interested in, update the
// corresponding variable
2024-03-25 16:28:13 -07:00
while let Some(evt) = gilrs.next_event().filter_ev(&UnknownSlayer {}, &mut gilrs) {
match evt.event {
gilrs::EventType::AxisChanged(gilrs::Axis::LeftStickY, val, _) => {
2024-04-06 10:49:19 -07:00
curr_y = (val * 100.0) as i32;
if curr_y > -10 && curr_y < 10 {
curr_y = 0;
2024-03-25 16:28:13 -07:00
}
}
gilrs::EventType::AxisChanged(gilrs::Axis::LeftStickX, val, _) => {
2024-04-06 10:49:19 -07:00
curr_x = (val * 100.0) as i32;
if curr_x > -10 && curr_x < 10 {
curr_x = 0;
2024-03-25 16:28:13 -07:00
}
}
_ => {}
}
}
})) {
Ok(_) => {}
2024-03-25 16:28:13 -07:00
Err(_) => {
info!("panic-causing event captured in gilrs event handler")
2024-03-25 16:28:13 -07:00
}
}
2024-04-06 11:03:21 -07:00
if (curr_x != past_x || curr_y != past_y) || (count_zeros < MAX_SENT_ZEROS) {
2024-04-06 10:49:19 -07:00
past_x = curr_x;
past_y = curr_y;
2024-04-06 11:03:21 -07:00
if curr_x == 0 && curr_y == 0 {
count_zeros += 1;
} else {
count_zeros = 0;
}
2024-04-06 10:49:19 -07:00
match tx.try_send(ApplicationEvent::MoveEvent(MoveEvent {
x: curr_x,
y: curr_y,
})) {
Ok(_) => {}
Err(async_channel::TrySendError::Closed(_)) => {
info!("MEC is closed, stopping Joystick loop");
break
2024-03-26 18:56:33 -07:00
}
2024-04-06 10:49:19 -07:00
Err(async_channel::TrySendError::Full(_)) => {warn!("[joystick loop] The MEC is full!")}
2024-03-25 16:28:13 -07:00
}
}
2024-04-06 10:49:19 -07:00
tokio::time::sleep(Duration::from_millis(50)).await;
2024-03-25 16:28:13 -07:00
}
2024-04-06 10:49:19 -07:00
is_alive.store(false, std::sync::atomic::Ordering::SeqCst);
2024-03-25 16:28:13 -07:00
}