pub mod delay;
pub mod hook;
pub mod map;
pub mod merge;
pub mod print;
pub mod withhold;
use std::collections::HashMap;
use self::hook::Hook;
use self::map::{Map, Toggle};
use self::merge::Merge;
use self::print::EventPrinter;
use self::withhold::Withhold;
use crate::capability::{Capability, InputCapabilites};
use crate::error::RuntimeError;
use crate::event::{Event, Namespace};
use crate::io::input::InputDevice;
use crate::io::output::OutputSystem;
use crate::loopback::{Delay, Loopback, LoopbackHandle};
use crate::predevice::PreOutputDevice;
use crate::state::{State, ToggleIndex};
pub enum StreamEntry {
Map(Map),
Hook(Hook),
Toggle(Toggle),
Print(EventPrinter),
Merge(Merge),
Withhold(Withhold),
Delay(self::delay::Delay),
}
pub struct Setup {
stream: Vec<StreamEntry>,
output: OutputSystem,
state: State,
toggle_indices: HashMap<String, ToggleIndex>,
loopback: Loopback,
input_caps: InputCapabilites,
staged_events: Vec<Event>,
}
impl Setup {
pub fn create(
stream: Vec<StreamEntry>,
pre_output: Vec<PreOutputDevice>,
state: State,
toggle_indices: HashMap<String, ToggleIndex>,
input_caps: InputCapabilites,
) -> Result<Setup, RuntimeError> {
let caps_vec: Vec<Capability> = crate::capability::input_caps_to_vec(&input_caps);
let caps_out = run_caps(&stream, caps_vec);
let output = OutputSystem::create(pre_output, caps_out)?;
Ok(Setup {
stream,
output,
state,
toggle_indices,
input_caps,
loopback: Loopback::new(),
staged_events: Vec::new(),
})
}
pub fn update_caps(&mut self, new_device: &InputDevice) {
let old_caps_opt = self
.input_caps
.insert(new_device.domain(), new_device.capabilities().clone());
if let Some(old_caps) = old_caps_opt {
if new_device.capabilities().is_compatible_with(&old_caps) {
return;
}
}
let caps_vec: Vec<Capability> = crate::capability::input_caps_to_vec(&self.input_caps);
let caps_out = run_caps(&self.stream, caps_vec);
self.output.update_caps(caps_out);
}
pub fn time_until_next_wakeup(&self) -> Delay {
self.loopback.time_until_next_wakeup()
}
pub fn toggle_indices(&self) -> &HashMap<String, ToggleIndex> {
&self.toggle_indices
}
pub fn state(&self) -> &State {
&self.state
}
pub fn state_mut(&mut self) -> &mut State {
&mut self.state
}
}
pub fn run(setup: &mut Setup, event: Event) {
if event.ev_type().is_syn() {
syn(setup);
} else {
if cfg!(feature = "auto-scan") {
if event.code == crate::event::EventCode::MSC_SCAN {
return;
}
}
let mut loopback_handle = setup.loopback.get_handle_lazy();
let mut events_out = Vec::new();
run_events(
vec![event],
&mut events_out,
&mut setup.stream,
&mut setup.state,
&mut loopback_handle,
);
match events_out.len() {
0 => {}
1 => setup.staged_events.extend(events_out),
_ => {
for event in events_out {
setup.staged_events.push(event);
syn(setup);
}
}
}
}
}
pub fn wakeup(setup: &mut Setup) {
while let Some((instant, token)) = setup.loopback.poll_once() {
let mut loopback_handle = setup.loopback.get_handle(instant);
run_wakeup(
token,
&mut setup.staged_events,
&mut setup.stream,
&mut setup.state,
&mut loopback_handle,
);
syn(setup);
}
}
pub fn syn(setup: &mut Setup) {
setup.output.route_events(&setup.staged_events);
setup.staged_events.clear();
setup.output.synchronize();
}
fn run_events(
events_in: Vec<Event>,
events_out: &mut Vec<Event>,
stream: &mut [StreamEntry],
state: &mut State,
loopback: &mut LoopbackHandle,
) {
let mut events: Vec<Event> = events_in;
let mut buffer: Vec<Event> = Vec::new();
for entry in stream {
match entry {
StreamEntry::Map(map) => {
map.apply_to_all(&events, &mut buffer);
events.clear();
std::mem::swap(&mut events, &mut buffer);
}
StreamEntry::Toggle(toggle) => {
toggle.apply_to_all(&events, &mut buffer, state);
events.clear();
std::mem::swap(&mut events, &mut buffer);
}
StreamEntry::Merge(merge) => {
merge.apply_to_all(&events, &mut buffer);
events.clear();
std::mem::swap(&mut events, &mut buffer);
}
StreamEntry::Hook(hook) => {
hook.apply_to_all(&events, &mut buffer, state, loopback);
events.clear();
std::mem::swap(&mut events, &mut buffer);
}
StreamEntry::Delay(delay) => {
delay.apply_to_all(&events, &mut buffer, loopback);
events.clear();
std::mem::swap(&mut events, &mut buffer);
}
StreamEntry::Withhold(withhold) => {
withhold.apply_to_all(&events, &mut buffer, loopback);
events.clear();
std::mem::swap(&mut events, &mut buffer);
}
StreamEntry::Print(printer) => {
printer.apply_to_all(&events);
}
}
}
events_out.extend(
events
.into_iter()
.filter(|event| event.namespace == Namespace::Output),
);
}
fn run_wakeup(
token: crate::loopback::Token,
events_out: &mut Vec<Event>,
stream: &mut [StreamEntry],
state: &mut State,
loopback: &mut LoopbackHandle,
) {
let mut events: Vec<Event> = Vec::new();
for index in 0..stream.len() {
match &mut stream[index] {
StreamEntry::Map(_map) => {}
StreamEntry::Toggle(_toggle) => {}
StreamEntry::Merge(_merge) => {}
StreamEntry::Hook(hook) => {
hook.wakeup(&token);
}
StreamEntry::Delay(delay) => {
delay.wakeup(&token, &mut events);
}
StreamEntry::Withhold(withhold) => {
withhold.wakeup(&token, &mut events);
}
StreamEntry::Print(_printer) => {}
}
if !events.is_empty() {
run_events(
events,
events_out,
&mut stream[index + 1..],
state,
loopback,
);
events = Vec::new();
}
}
}
pub fn run_caps(stream: &[StreamEntry], capabilities: Vec<Capability>) -> Vec<Capability> {
let mut caps: Vec<Capability> = capabilities;
let mut buffer: Vec<Capability> = Vec::new();
let mut last_num_caps = caps.len();
for entry in stream {
match entry {
StreamEntry::Map(map) => {
map.apply_to_all_caps(&caps, &mut buffer);
caps.clear();
std::mem::swap(&mut caps, &mut buffer);
}
StreamEntry::Toggle(toggle) => {
toggle.apply_to_all_caps(&caps, &mut buffer);
caps.clear();
std::mem::swap(&mut caps, &mut buffer);
}
StreamEntry::Merge(_) => (),
StreamEntry::Hook(hook) => {
hook.apply_to_all_caps(&caps, &mut buffer);
caps.clear();
std::mem::swap(&mut caps, &mut buffer);
}
StreamEntry::Print(_) => (),
StreamEntry::Delay(_) => (),
StreamEntry::Withhold(_) => (),
}
if caps.len() >= 2 * last_num_caps {
caps = crate::capability::aggregate_capabilities(caps);
last_num_caps = caps.len();
}
}
caps.into_iter()
.filter(|cap| cap.namespace == Namespace::Output)
.collect()
}