This commit is contained in:
2024-05-27 21:00:55 +02:00
commit 431fb25d85
7 changed files with 1887 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
/target
.vscode

1765
Cargo.lock generated Normal file

File diff suppressed because it is too large Load Diff

14
Cargo.toml Normal file
View File

@@ -0,0 +1,14 @@
[package]
name = "space"
version = "0.1.0"
edition = "2021"
[dependencies]
rodio = "0.11.0"
tray-item = "0.10.0"
windows = { version = "0.56.0", features = ["Win32", "Win32_System", "Win32_System_Console", "Win32_Graphics", "Win32_Graphics_Gdi", "Win32_System_Memory", "Win32_System_LibraryLoader", "UI", "UI_Core", "Win32_UI", "Win32_UI_Input", "Win32_UI_Input_KeyboardAndMouse", "Win32_UI_WindowsAndMessaging"] }
winit = "0.25.0"
[build-dependencies]
embed-resource = "2.3"

BIN
assets/launch.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

5
build.rs Normal file
View File

@@ -0,0 +1,5 @@
extern crate embed_resource;
fn main() {
embed_resource::compile("tray-example.rc", embed_resource::NONE);
}

100
src/main.rs Normal file
View File

@@ -0,0 +1,100 @@
#![windows_subsystem = "windows"]
use rodio::source::SineWave;
use rodio::{Sink, Source};
use std::sync::mpsc;
use std::{thread, time::Duration};
use tray_item::{IconSource, TrayItem};
use windows::Win32::UI::Input::KeyboardAndMouse::{GetAsyncKeyState, VK_SPACE};
fn detect_space() -> bool {
unsafe {
let state = GetAsyncKeyState(VK_SPACE.0.into());
// Check if the key is pressed (the most significant bit is set)
(state & (1 << (i16::BITS - 1))) != 0
}
}
fn holding_space() -> bool {
for _ in 0..10 {
if !detect_space() {
thread::sleep(Duration::from_millis(10));
return false;
}
thread::sleep(Duration::from_millis(20));
}
true
}
fn play_sound_while_holding_space() {
enum Message {
Pause,
Play,
}
let (tx, rx) = mpsc::sync_channel(1);
thread::spawn(move || {
let source = SineWave::new(440)
.take_duration(Duration::from_secs(300))
.amplify(0.05);
let sink = Sink::new(&rodio::default_output_device().unwrap());
sink.pause();
loop {
if !sink.is_paused() && sink.empty() {
sink.append(source.clone());
}
match rx.recv() {
Ok(Message::Pause) => sink.pause(),
Ok(Message::Play) => {
sink.append(source.clone());
sink.play();
}
_ => {}
}
}
});
loop {
if holding_space() {
tx.send(Message::Play).unwrap();
while detect_space() {
thread::sleep(Duration::from_millis(10));
}
tx.send(Message::Pause).unwrap();
}
}
}
fn tray() {
enum TrayMessage {
Quit,
}
let mut tray = TrayItem::new("Space Watcher", IconSource::Resource("tray-icon")).unwrap();
tray.add_label("Space Watcher").unwrap();
tray.inner_mut().add_separator().unwrap();
let (tx, rx) = mpsc::sync_channel(1);
let quit_tx = tx.clone();
tray.add_menu_item("Quit", move || {
quit_tx.send(TrayMessage::Quit).unwrap();
})
.unwrap();
loop {
match rx.recv() {
Ok(TrayMessage::Quit) => {
break;
}
_ => {}
}
}
}
fn main() {
thread::spawn(|| play_sound_while_holding_space());
tray();
}

1
tray-example.rc Normal file
View File

@@ -0,0 +1 @@
tray-icon ICON "assets/launch.ico"