use std::{
iter::zip,
sync::{Arc, Mutex},
time::Duration,
};
use crate::{device::Device, error::MirajazzError, types::DeviceInput};
#[derive(Copy, Clone, Debug, Hash)]
pub enum DeviceStateUpdate {
ButtonDown(u8),
ButtonUp(u8),
EncoderDown(u8),
EncoderUp(u8),
EncoderTwist(u8, i8),
}
#[derive(Default)]
pub struct DeviceState {
pub buttons: Vec<bool>,
pub encoders: Vec<bool>,
}
pub struct DeviceStateReader {
pub device: Arc<Device>,
pub states: Mutex<DeviceState>,
}
impl DeviceStateReader {
pub fn read(
&self,
timeout: Option<Duration>,
process_input: impl Fn(u8, u8) -> Result<DeviceInput, MirajazzError>,
supports_both_states: bool,
) -> Result<Vec<DeviceStateUpdate>, MirajazzError> {
let input = self.device.read_input(timeout, process_input)?;
let mut my_states = self.states.lock()?;
let mut updates = vec![];
match input {
DeviceInput::ButtonStateChange(buttons) => {
for (index, (their, mine)) in
zip(buttons.iter(), my_states.buttons.iter()).enumerate()
{
if !supports_both_states {
if *their {
updates.push(DeviceStateUpdate::ButtonDown(index as u8));
updates.push(DeviceStateUpdate::ButtonUp(index as u8));
}
} else if their != mine {
if *their {
updates.push(DeviceStateUpdate::ButtonDown(index as u8));
} else {
updates.push(DeviceStateUpdate::ButtonUp(index as u8));
}
}
}
my_states.buttons = buttons;
}
DeviceInput::EncoderStateChange(encoders) => {
for (index, (their, mine)) in
zip(encoders.iter(), my_states.encoders.iter()).enumerate()
{
if !supports_both_states {
if *their {
updates.push(DeviceStateUpdate::EncoderDown(index as u8));
updates.push(DeviceStateUpdate::EncoderUp(index as u8));
}
} else if *their != *mine {
if *their {
updates.push(DeviceStateUpdate::EncoderDown(index as u8));
} else {
updates.push(DeviceStateUpdate::EncoderUp(index as u8));
}
}
}
my_states.encoders = encoders;
}
DeviceInput::EncoderTwist(twist) => {
for (index, change) in twist.iter().enumerate() {
if *change != 0 {
updates.push(DeviceStateUpdate::EncoderTwist(index as u8, *change));
}
}
}
_ => {}
}
drop(my_states);
Ok(updates)
}
}