mirror of
https://github.com/4yn/slidershim.git
synced 2024-11-27 23:10:49 +01:00
keyboard out, untested
This commit is contained in:
parent
7e842971e7
commit
7d5b552aec
1
src-tauri/Cargo.lock
generated
1
src-tauri/Cargo.lock
generated
@ -2749,6 +2749,7 @@ dependencies = [
|
||||
"serde_json",
|
||||
"tauri",
|
||||
"tauri-build",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -20,6 +20,7 @@ serde = { version = "1.0", features = ["derive"] }
|
||||
tauri = { version = "1.0.0-beta.8", features = ["api-all", "system-tray"] }
|
||||
rusb = "0.9.0"
|
||||
palette = "0.6.0"
|
||||
winapi = "0.3.9"
|
||||
|
||||
[features]
|
||||
default = [ "custom-protocol" ]
|
||||
|
@ -17,6 +17,21 @@ impl ControllerState {
|
||||
extra_state: [0; 3],
|
||||
}
|
||||
}
|
||||
|
||||
pub fn flat(&self, sensitivity: &u8) -> Vec<bool> {
|
||||
self
|
||||
.ground_state
|
||||
.iter()
|
||||
.map(|x| x > sensitivity)
|
||||
.chain(
|
||||
self
|
||||
.air_state
|
||||
.iter()
|
||||
.chain(self.extra_state.iter())
|
||||
.map(|x| x > &0),
|
||||
)
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct LedState {
|
||||
|
140
src-tauri/src/slider_io/keyboard.rs
Normal file
140
src-tauri/src/slider_io/keyboard.rs
Normal file
@ -0,0 +1,140 @@
|
||||
use std::mem;
|
||||
|
||||
use winapi::{
|
||||
ctypes::c_int,
|
||||
um::winuser::{SendInput, INPUT, INPUT_KEYBOARD, KEYBDINPUT, KEYEVENTF_KEYUP},
|
||||
};
|
||||
|
||||
use crate::slider_io::{config::KeyboardLayout, controller_state::ControllerState};
|
||||
|
||||
#[rustfmt::skip]
|
||||
const tasoller_kb_map: [usize; 41] = [
|
||||
0x41 /* A */, 0x31 /* 1 */, 0x5a /* Z */, 0x51 /* Q */, 0x53 /* S */, 0x32 /* 2 */, 0x58 /* X */, 0x57 /* W */,
|
||||
0x44 /* D */, 0x33 /* 3 */, 0x43 /* C */, 0x45 /* E */, 0x46 /* F */, 0x34 /* 4 */, 0x56 /* V */, 0x52 /* R */,
|
||||
0x47 /* G */, 0x35 /* 5 */, 0x42 /* B */, 0x54 /* T */, 0x48 /* H */, 0x36 /* 6 */, 0x4e /* N */, 0x59 /* Y */,
|
||||
0x4a /* J */, 0x37 /* 7 */, 0x4d /* M */, 0x55 /* U */, 0x4b /* K */, 0x38 /* 8 */, 0xbc /* VK_OEM_COMMA */, 0x49 /* I */,
|
||||
0xbf, 0xde, 0xbe, // VK_OEM_2, VK_OEM_7, VK_OEM_PERIOD,
|
||||
0xba, 0xdd, 0xdb, // VK_OEM_1, VK_OEM_6, VK_OEM_4
|
||||
0x0d, 0x20, 0x1b // VK_RETURN, VK_SPACE, VK_ESCAPE
|
||||
];
|
||||
|
||||
#[rustfmt::skip]
|
||||
const yuancon_kb_map: [usize; 41] = [
|
||||
0x36 /* 6 */, 0x35 /* 5 */, 0x34 /* 4 */, 0x33 /* 3 */, 0x32 /* 2 */, 0x31 /* 1 */, 0x5a /* Z */, 0x59 /* Y */,
|
||||
0x58 /* X */, 0x57 /* W */, 0x56 /* V */, 0x55 /* U */, 0x54 /* T */, 0x53 /* S */, 0x52 /* R */, 0x51 /* Q */,
|
||||
0x50 /* P */, 0x4f /* O */, 0x4e /* N */, 0x4d /* M */, 0x4c /* L */, 0x4b /* K */, 0x4a /* J */, 0x49 /* I */,
|
||||
0x48 /* H */, 0x47 /* G */, 0x46 /* F */, 0x45 /* E */, 0x44 /* D */, 0x43 /* C */, 0x42 /* B */, 0x41 /* A */,
|
||||
0xbd, 0xbb, 0xdb, // VK_OEM_MINUS, VK_OEM_PLUS, VK_OEM_4,
|
||||
0xdd, 0xdc, 0xba, // VK_OEM_6, VK_OEM_5, VK_OEM_1,
|
||||
0x0d, 0x20, 0x1b, // VK_RETURN, VK_SPACE, VK_ESCAPE
|
||||
];
|
||||
|
||||
pub struct KeyboardOutput {
|
||||
ground_to_idx: [usize; 41],
|
||||
idx_to_keycode: [u16; 41],
|
||||
keycode_to_idx: [usize; 256],
|
||||
|
||||
next_keys: [bool; 41],
|
||||
last_keys: [bool; 41],
|
||||
|
||||
kb_buf: [INPUT; 41],
|
||||
n_kb_buf: u32,
|
||||
}
|
||||
|
||||
impl KeyboardOutput {
|
||||
pub fn new(layout: KeyboardLayout) -> Self {
|
||||
let kb_map = match layout {
|
||||
KeyboardLayout::Tasoller => &tasoller_kb_map,
|
||||
KeyboardLayout::Yuancon => &yuancon_kb_map,
|
||||
KeyboardLayout::Deemo => {
|
||||
panic!("Not yet")
|
||||
}
|
||||
};
|
||||
|
||||
let mut ground_to_idx = [0 as usize; 41];
|
||||
let mut idx_to_keycode = [0 as u16; 41];
|
||||
let mut keycode_to_idx = [0xffff as usize; 256];
|
||||
let mut keycode_count: usize = 0;
|
||||
|
||||
for (ground, keycode) in kb_map.iter().enumerate() {
|
||||
if keycode_to_idx[*keycode] == 0xffff {
|
||||
keycode_to_idx[*keycode] = keycode_count;
|
||||
idx_to_keycode[keycode_count] = *keycode as u16;
|
||||
keycode_count += 1;
|
||||
}
|
||||
ground_to_idx[ground] = keycode_to_idx[*keycode]
|
||||
}
|
||||
|
||||
let mut kb_buf = [INPUT {
|
||||
type_: INPUT_KEYBOARD,
|
||||
u: unsafe { mem::zeroed() },
|
||||
}; 41];
|
||||
|
||||
for i in kb_buf.iter_mut() {
|
||||
let mut inner = unsafe { i.u.ki_mut() };
|
||||
inner.wVk = 0;
|
||||
inner.wScan = 0;
|
||||
inner.dwFlags = 0;
|
||||
inner.time = 0;
|
||||
inner.dwExtraInfo = 0;
|
||||
}
|
||||
|
||||
Self {
|
||||
ground_to_idx,
|
||||
idx_to_keycode,
|
||||
keycode_to_idx,
|
||||
next_keys: [false; 41],
|
||||
last_keys: [false; 41],
|
||||
kb_buf,
|
||||
n_kb_buf: 0,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn tick(&mut self, controller_state: &ControllerState, sensitivity: &u8) {
|
||||
self
|
||||
.next_keys
|
||||
.iter_mut()
|
||||
.zip(controller_state.flat(sensitivity))
|
||||
.for_each(|(a, b)| {
|
||||
*a = b;
|
||||
});
|
||||
self.send();
|
||||
}
|
||||
|
||||
pub fn reset(&mut self) {
|
||||
self.next_keys.fill(false);
|
||||
self.send();
|
||||
}
|
||||
|
||||
fn send(&mut self) {
|
||||
self.n_kb_buf = 0;
|
||||
|
||||
for (i, (n, l)) in self.next_keys.iter().zip(self.last_keys.iter()).enumerate() {
|
||||
match (*n, *l) {
|
||||
(false, true) => {
|
||||
let inner: &mut KEYBDINPUT = unsafe { self.kb_buf[self.n_kb_buf as usize].u.ki_mut() };
|
||||
inner.wVk = self.idx_to_keycode[i];
|
||||
inner.dwFlags = 0;
|
||||
self.n_kb_buf += 1;
|
||||
}
|
||||
(true, false) => {
|
||||
let inner: &mut KEYBDINPUT = unsafe { self.kb_buf[self.n_kb_buf as usize].u.ki_mut() };
|
||||
inner.wVk = self.idx_to_keycode[i];
|
||||
inner.dwFlags = KEYEVENTF_KEYUP;
|
||||
self.n_kb_buf += 1;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
if self.n_kb_buf != 0 {
|
||||
unsafe {
|
||||
SendInput(
|
||||
self.n_kb_buf,
|
||||
self.kb_buf.as_mut_ptr(),
|
||||
mem::size_of::<INPUT>() as c_int,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -20,7 +20,7 @@ fn update_reactive(
|
||||
controller_state: &ControllerState,
|
||||
led_state: &mut LedState,
|
||||
reactive_layout: &ReactiveLayout,
|
||||
sensitivity: u8,
|
||||
sensitivity: &u8,
|
||||
) {
|
||||
let splits = match reactive_layout {
|
||||
ReactiveLayout::Four => 4,
|
||||
@ -30,11 +30,18 @@ fn update_reactive(
|
||||
let buttons_per_split = 32 / splits;
|
||||
|
||||
let banks: Vec<bool> = controller_state
|
||||
.ground_state
|
||||
.flat(sensitivity)
|
||||
.chunks(buttons_per_split)
|
||||
.map(|x| x.iter().max().unwrap() > &sensitivity)
|
||||
.take(splits)
|
||||
.map(|x| x.iter().any(|x| *x))
|
||||
.collect();
|
||||
|
||||
// controller_state
|
||||
// .ground_state
|
||||
// .chunks(buttons_per_split)
|
||||
// .map(|x| x.iter().max().unwrap() > &sensitivity)
|
||||
// .collect();
|
||||
|
||||
// (0..splits)
|
||||
// .map(|i| {
|
||||
// controller_state.ground_state[i * buttons_per_split..(i + 1) * buttons_per_split]
|
||||
@ -120,7 +127,7 @@ impl LedThread {
|
||||
controller_state_handle.deref(),
|
||||
led_state_handle.deref_mut(),
|
||||
layout,
|
||||
20,
|
||||
&20,
|
||||
)
|
||||
}
|
||||
LedMode::Attract => {
|
||||
|
@ -2,5 +2,7 @@ pub mod config;
|
||||
pub mod controller_state;
|
||||
pub mod device;
|
||||
pub mod hid;
|
||||
pub mod keyboard;
|
||||
pub mod led;
|
||||
pub mod manager;
|
||||
pub mod output;
|
||||
|
64
src-tauri/src/slider_io/output.rs
Normal file
64
src-tauri/src/slider_io/output.rs
Normal file
@ -0,0 +1,64 @@
|
||||
use std::{
|
||||
ops::Deref,
|
||||
sync::{
|
||||
atomic::{AtomicBool, Ordering},
|
||||
Arc,
|
||||
},
|
||||
thread::{self, JoinHandle},
|
||||
time::Duration,
|
||||
};
|
||||
|
||||
use crate::slider_io::{config::OutputMode, controller_state::FullState, keyboard};
|
||||
|
||||
pub struct OutputThread {
|
||||
thread: Option<JoinHandle<()>>,
|
||||
stop_signal: Arc<AtomicBool>,
|
||||
}
|
||||
|
||||
impl OutputThread {
|
||||
pub fn new(state: &FullState, mode: OutputMode) -> Self {
|
||||
let controller_state = state.clone_controller();
|
||||
let stop_signal = Arc::new(AtomicBool::new(false));
|
||||
|
||||
let stop_signal_clone = Arc::clone(&stop_signal);
|
||||
|
||||
Self {
|
||||
thread: Some(match mode {
|
||||
OutputMode::None => thread::spawn(|| {}),
|
||||
OutputMode::Keyboard {
|
||||
layout,
|
||||
sensitivity,
|
||||
} => thread::spawn(move || {
|
||||
let mut keyboard_output = keyboard::KeyboardOutput::new(layout);
|
||||
loop {
|
||||
{
|
||||
let controller_state_handle = controller_state.lock().unwrap();
|
||||
keyboard_output.tick(controller_state_handle.deref(), &sensitivity);
|
||||
}
|
||||
|
||||
{
|
||||
if stop_signal_clone.load(Ordering::SeqCst) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
thread::sleep(Duration::from_millis(10));
|
||||
}
|
||||
|
||||
keyboard_output.reset();
|
||||
}),
|
||||
OutputMode::Websocket { .. } => thread::spawn(|| {}),
|
||||
}),
|
||||
stop_signal,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for OutputThread {
|
||||
fn drop(&mut self) {
|
||||
self.stop_signal.swap(true, Ordering::SeqCst);
|
||||
if self.thread.is_some() {
|
||||
self.thread.take().unwrap().join().ok();
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user