use crate::config::Engine; use hidapi::HidApi; use rusb::UsbContext; use gilrs::{Gilrs, Button, Event}; pub trait InputEngine { fn get(&mut self) -> Vec; } pub fn build_input_engine(cfg: &Engine) -> Result, String> { match cfg.name.as_str() { "stdin" => return Ok(Box::new(InputEngineStdin{})), "kafka" => return build_input_engine_kafka(&cfg), "udp" => return build_input_engine_udp(&cfg), "device" => return build_input_engine_device(&cfg), _ => return Err("unknown input engine name".to_string() + &cfg.name), } } struct InputEngineDevice { } pub fn build_input_engine_device(cfg: &Engine) -> Result, String> { return build_input_engine_device_gilrs(cfg) } pub fn build_input_engine_device_gilrs(cfg: &Engine) -> Result, String> { let _device_cfg = cfg.device.as_ref().unwrap(); let mut gilrs = Gilrs::new().unwrap(); println!("printing gamepads"); for (_id, gamepad) in gilrs.gamepads() { println!("{} is {:?}", gamepad.name(), gamepad.power_info()); } println!("printing gamepads events"); loop { // println!("reading gamepads events"); // Examine new events while let Some(Event { id, event, time }) = gilrs.next_event() { println!("{:?} New event from {}: {:?}", time, id, event); let active_gamepad = Some(id); println!("inspecting event"); // You can also use cached gamepad state if let Some(gamepad) = active_gamepad.map(|id| gilrs.gamepad(id)) { if gamepad.is_pressed(Button::South) { println!("Button South is pressed (XBox - A, PS - X)"); } } break; } std::thread::sleep(std::time::Duration::from_millis(15)); break; } return Err("do what".to_string()); } pub fn build_input_engine_device_hidapi(cfg: &Engine) -> Result, String> { let _device_cfg = cfg.device.as_ref().unwrap(); match HidApi::new() { Ok(api) => { for device in api.devices() { println!("{:#?}", device); } }, Err(e) => { eprintln!("Error: {}", e); }, }; return Err("do what".to_string()); } pub fn build_input_engine_device_rusb(cfg: &Engine) -> Result, String> { let _device_cfg = cfg.device.as_ref().unwrap(); assert!(rusb::has_capability()); let ctx = rusb::Context::new().unwrap(); assert!(ctx.devices().unwrap().len() > 0); for device in ctx.devices().unwrap().iter() { let device_desc = device.device_descriptor().unwrap(); println!("Bus {:03} Device {:03} ID {:04x}:{:04x}", device.bus_number(), device.address(), device_desc.vendor_id(), device_desc.product_id()); } return Err("do what".to_string()); } impl InputEngine for InputEngineDevice { fn get(&mut self) -> Vec { Err("end".to_string()).unwrap() } } struct InputEngineUDP { last_socket: Option, port: i32, } pub fn build_input_engine_udp(cfg: &Engine) -> Result, String> { let udp_cfg = cfg.udp.as_ref().unwrap(); return Ok(Box::new(InputEngineUDP{ last_socket: None, port: udp_cfg.port, })); } impl InputEngine for InputEngineUDP { fn get(&mut self) -> Vec { let addr = "0.0.0.0:".to_string() + &self.port.to_string(); println!("$ echo -n 'hello world' | nc -4u -w0 localhost {}", &self.port.to_string()); if self.last_socket.is_none() { self.last_socket = Some(std::net::UdpSocket::bind(addr).unwrap()); } let result = self._get(); if result.is_err() { self.last_socket = None; return Vec::::new(); } return result.unwrap(); } } impl InputEngineUDP { fn _get(&mut self) -> Result, std::io::Error> { let mut buf = [0; 128]; let socket = self.last_socket.ok_or(std::io::Error::new(std::io::ErrorKind::Other, "no socket"))?; let (amt, _) = socket.recv_from(&mut buf)?; let buf = &mut buf[..amt]; return Ok(std::str::from_utf8(buf).unwrap().chars().collect()); } } struct InputEngineKafka { } pub fn build_input_engine_kafka(cfg: &Engine) -> Result, String> { let _kafka_cfg = cfg.kafka.as_ref().unwrap(); return Err("do what".to_string()); } impl InputEngine for InputEngineKafka { fn get(&mut self) -> Vec { Err("end".to_string()).unwrap() } } struct InputEngineStdin {} impl InputEngine for InputEngineStdin { fn get(&mut self) -> Vec { let stdin = std::io::stdin(); let mut result = String::new(); stdin.read_line(&mut result).unwrap(); return result.trim().chars().collect(); } } #[cfg(test)] mod test_input { use super::*; struct InputEngineTest {} impl InputEngine for InputEngineTest { fn get(&mut self) -> Vec { return "hello world".chars().collect(); } } #[test] fn test_input_engine_impl() { let mut input_engine_test = InputEngineTest{}; _test_input_engine_impl(&mut input_engine_test); } fn _test_input_engine_impl(engine: &mut dyn InputEngine) { assert_eq!("hello world".to_string(), engine.get().iter().cloned().collect::()); } } pub trait OutputEngine { fn put(&self, v: Vec); } pub fn build_output_engine(cfg: &Engine) -> Result, String> { match cfg.name.as_str() { "stdout" => return Ok(Box::new(OutputEngineStdout{})), "udp" => return build_output_engine_udp(&cfg), _ => return Err("unknown output engine name".to_string() + &cfg.name), } } struct OutputEngineStdout {} impl OutputEngine for OutputEngineStdout { fn put(&self, v: Vec) { println!("{}", v.iter().cloned().collect::()); } } #[cfg(test)] mod test_output { use super::*; struct OutputEngineTest {} impl OutputEngine for OutputEngineTest { fn put(&self, _v: Vec) { } } #[test] fn test_output_engine_impl() { let output_engine_test = OutputEngineTest{}; _test_output_engine_impl(&output_engine_test); } fn _test_output_engine_impl(engine: &dyn OutputEngine) { engine.put("teehee".to_string().chars().collect()); } } struct OutputEngineUDP { host: String, port: i32, } pub fn build_output_engine_udp(cfg: &Engine) -> Result, String> { let udp_cfg = cfg.udp.as_ref().unwrap(); return Ok(Box::new(OutputEngineUDP{ host: udp_cfg.host.clone().unwrap(), port: udp_cfg.port, })); } impl OutputEngine for OutputEngineUDP { fn put(&self, v: Vec) { let socket = std::net::UdpSocket::bind("127.0.0.1:".to_string() + &(self.port+10).to_string()).unwrap(); socket.connect(self.host.to_string() + ":" + &self.port.to_string()).unwrap(); socket.send(&v.iter().cloned().collect::().as_bytes()).unwrap(); } }