1#![windows_subsystem = "windows"]
2
3use std::collections::HashSet;
4use std::{collections::HashMap, time::Duration};
5
6use device_query::{DeviceState, Keycode};
7use quad_snd::{AudioContext, Sound};
8
9fn main() {
10 let ctx = AudioContext::new();
11 let sounds = std::fs::read_dir("sounds")
12 .expect("cant read sounds")
13 .flat_map(|f| {
14 let p = f.ok()?.path();
15 let n = p.file_stem()?.to_string_lossy().into_owned();
16 (n != "LICENSE" && n != "README").then(|| {
17 (
18 n,
19 Sound::load(&ctx, &std::fs::read(p).expect("can't load sound")),
20 )
21 })
22 })
23 .collect::<HashMap<String, Sound>>();
24 let play_sound = |name: &str| {
25 let sound = sounds.get(name).unwrap();
26 sound.play(&ctx, Default::default());
27 };
28 let play_sound_for_key = |key: Keycode| match key {
29 Keycode::CapsLock => play_sound("caps"),
30 Keycode::Delete | Keycode::Backspace => play_sound("delete"),
31 Keycode::Up | Keycode::Down | Keycode::Left | Keycode::Right => play_sound("movement"),
32 _ => {
33 let no = fastrand::u8(1..=4);
34 play_sound(&format!("press-{no}"));
35 }
36 };
37
38 let state = DeviceState::new();
39 let mut previously_held_keys = HashSet::<Keycode>::new();
40 let mut key_press_times = HashMap::<Keycode, std::time::Instant>::new();
41 let mut last_sound_time = std::time::Instant::now();
42
43 let initial_delay = Duration::from_millis(500); // Wait 500ms before starting to repeat
44 let repeat_interval = Duration::from_millis(50); // Then repeat every 50ms
45
46 loop {
47 let currently_held_keys: HashSet<Keycode> = state.query_keymap().into_iter().collect();
48
49 // Track when keys were first pressed
50 for key in ¤tly_held_keys {
51 if !previously_held_keys.contains(key) {
52 // Key just pressed, record the time and play initial sound
53 key_press_times.insert(*key, std::time::Instant::now());
54 play_sound_for_key(*key);
55 }
56 }
57
58 // Remove timing info for released keys
59 key_press_times.retain(|key, _| currently_held_keys.contains(key));
60
61 // Play repeating sounds every 50ms, but only after initial delay
62 if last_sound_time.elapsed() >= repeat_interval {
63 let now = std::time::Instant::now();
64 for key in ¤tly_held_keys {
65 if matches!(
66 key,
67 Keycode::LShift
68 | Keycode::RShift
69 | Keycode::LControl
70 | Keycode::RControl
71 | Keycode::RAlt
72 | Keycode::LAlt
73 | Keycode::RMeta
74 | Keycode::LMeta
75 | Keycode::CapsLock
76 ) {
77 continue;
78 }
79 if let Some(press_time) = key_press_times.get(key) {
80 // Only repeat if key has been held longer than initial delay
81 if now.duration_since(*press_time) >= initial_delay {
82 play_sound_for_key(*key);
83 }
84 }
85 }
86 last_sound_time = now;
87 }
88
89 previously_held_keys = currently_held_keys;
90
91 // Buffer inputs at lower interval (5ms)
92 std::thread::sleep(Duration::from_millis(5));
93 }
94}