feat: latch to discord window
This commit is contained in:
parent
2c80d4a41d
commit
edc9db64de
4 changed files with 116 additions and 29 deletions
41
Cargo.lock
generated
41
Cargo.lock
generated
|
@ -2,26 +2,11 @@
|
||||||
# It is not intended for manual editing.
|
# It is not intended for manual editing.
|
||||||
version = 3
|
version = 3
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "libc"
|
|
||||||
version = "0.2.158"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "libc-print"
|
|
||||||
version = "0.1.23"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "a4a660208db49e35faf57b37484350f1a61072f2a5becf0592af6015d9ddd4b0"
|
|
||||||
dependencies = [
|
|
||||||
"libc",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "muter"
|
name = "muter"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc-print",
|
"thiserror",
|
||||||
"windows",
|
"windows",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -45,15 +30,35 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "2.0.77"
|
version = "2.0.87"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed"
|
checksum = "25aa4ce346d03a6dcd68dd8b4010bcb74e54e62c90c573f394c46eae99aba32d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"unicode-ident",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "thiserror"
|
||||||
|
version = "2.0.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c006c85c7651b3cf2ada4584faa36773bd07bac24acfb39f3c431b36d7e667aa"
|
||||||
|
dependencies = [
|
||||||
|
"thiserror-impl",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "thiserror-impl"
|
||||||
|
version = "2.0.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f077553d607adc1caf65430528a576c757a71ed73944b66ebb58ef2bbd243568"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-ident"
|
name = "unicode-ident"
|
||||||
version = "1.0.13"
|
version = "1.0.13"
|
||||||
|
|
11
Cargo.toml
11
Cargo.toml
|
@ -1,14 +1,21 @@
|
||||||
[package]
|
[package]
|
||||||
name = "muter"
|
name = "muter"
|
||||||
|
publish = false
|
||||||
|
authors = ["newt <hi@newty.dev>"]
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
libc-print = "0.1.23"
|
thiserror = "2.0.3"
|
||||||
|
|
||||||
[dependencies.windows]
|
[dependencies.windows]
|
||||||
version = "0.58.0"
|
version = "0.58.0"
|
||||||
features = [
|
features = [
|
||||||
"Win32_Media_Audio_Endpoints",
|
"Win32_Media_Audio_Endpoints",
|
||||||
"Win32_System_Com"
|
|
||||||
|
"Win32_System_Com",
|
||||||
|
"Win32_System_Threading",
|
||||||
|
|
||||||
|
"Win32_UI_Input_KeyboardAndMouse",
|
||||||
|
"Win32_UI_WindowsAndMessaging",
|
||||||
]
|
]
|
||||||
|
|
5
src/lib.rs
Normal file
5
src/lib.rs
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
#[derive(thiserror::Error, Debug)]
|
||||||
|
pub enum Error {
|
||||||
|
#[error("Failed to initialize COM library: {0}")]
|
||||||
|
Windows(#[from] windows::core::Error),
|
||||||
|
}
|
88
src/main.rs
88
src/main.rs
|
@ -1,15 +1,69 @@
|
||||||
#![no_std]
|
use std::sync::atomic::{AtomicPtr, Ordering};
|
||||||
|
use std::time::Duration;
|
||||||
use libc_print::std_name::println;
|
use std::{ptr, thread};
|
||||||
|
use windows::Win32::UI::Input::KeyboardAndMouse::{
|
||||||
|
MapVirtualKeyW, SendInput, INPUT, INPUT_0, INPUT_KEYBOARD, KEYBDINPUT, KEYBD_EVENT_FLAGS,
|
||||||
|
KEYEVENTF_KEYUP, KEYEVENTF_SCANCODE, MAPVK_VK_TO_VSC,
|
||||||
|
};
|
||||||
|
use windows::Win32::UI::WindowsAndMessaging::{FindWindowExW, GetClassNameW, SetForegroundWindow};
|
||||||
use windows::Win32::{
|
use windows::Win32::{
|
||||||
|
Foundation::{BOOL, HWND, LPARAM, WPARAM},
|
||||||
Media::Audio::{
|
Media::Audio::{
|
||||||
eCapture, eMultimedia, Endpoints::IAudioEndpointVolume, IMMDevice, IMMDeviceEnumerator,
|
eCapture, eMultimedia, Endpoints::IAudioEndpointVolume, IMMDevice, IMMDeviceEnumerator,
|
||||||
MMDeviceEnumerator,
|
MMDeviceEnumerator,
|
||||||
},
|
},
|
||||||
System::Com::{CoCreateInstance, CoInitializeEx, CLSCTX_ALL, COINIT_MULTITHREADED},
|
System::Com::{CoCreateInstance, CoInitializeEx, CLSCTX_ALL, COINIT_MULTITHREADED},
|
||||||
|
UI::{
|
||||||
|
Input::KeyboardAndMouse::{VIRTUAL_KEY, VK_CONTROL, VK_M, VK_SHIFT},
|
||||||
|
WindowsAndMessaging::{EnumWindows, GetWindowTextW, PostMessageW, WM_KEYDOWN, WM_KEYUP},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
fn main() -> windows::core::Result<()> {
|
static mut DISCORD_WHND: AtomicPtr<HWND> = AtomicPtr::new(ptr::null_mut());
|
||||||
|
|
||||||
|
unsafe extern "system" fn search_windows(hwnd: HWND, _: LPARAM) -> BOOL {
|
||||||
|
let mut name = [0u16; 1024];
|
||||||
|
let len = unsafe { GetWindowTextW(hwnd, &mut name) };
|
||||||
|
let name = String::from_utf16_lossy(&name[..len as usize]);
|
||||||
|
|
||||||
|
if name.to_lowercase().contains(&"- discord".to_string()) {
|
||||||
|
println!("Discord window found: {:?}", name);
|
||||||
|
DISCORD_WHND.store(Box::into_raw(Box::new(hwnd)), Ordering::SeqCst);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn press_keys(window: HWND, keys: &[VIRTUAL_KEY]) -> windows::core::Result<()> {
|
||||||
|
let keys = keys.iter().map(|key| {
|
||||||
|
(
|
||||||
|
key.0 as usize,
|
||||||
|
MapVirtualKeyW(key.0.into(), MAPVK_VK_TO_VSC) as isize,
|
||||||
|
)
|
||||||
|
});
|
||||||
|
let down = keys
|
||||||
|
.clone()
|
||||||
|
.map(|(key, scan)| (WPARAM(key), LPARAM(scan << 16)))
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
let up = keys
|
||||||
|
.map(|(key, scan)| (WPARAM(key), LPARAM(0x7FFF | (scan << 16) | (0b11 << 30))))
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
for (wparam, lparam) in down {
|
||||||
|
println!("Pressing key: {:?}", wparam);
|
||||||
|
PostMessageW(window, WM_KEYDOWN, wparam, lparam)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
thread::sleep(Duration::from_secs(10));
|
||||||
|
|
||||||
|
for (wparam, lparam) in up {
|
||||||
|
PostMessageW(window, WM_KEYUP, wparam, lparam)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() -> Result<(), muter::Error> {
|
||||||
unsafe {
|
unsafe {
|
||||||
// Initialize the COM library
|
// Initialize the COM library
|
||||||
CoInitializeEx(None, COINIT_MULTITHREADED).unwrap();
|
CoInitializeEx(None, COINIT_MULTITHREADED).unwrap();
|
||||||
|
@ -24,6 +78,20 @@ fn main() -> windows::core::Result<()> {
|
||||||
// Activate the IAudioEndpointVolume interface for the capture device
|
// Activate the IAudioEndpointVolume interface for the capture device
|
||||||
let endpoint_volume: IAudioEndpointVolume = default_device.Activate(CLSCTX_ALL, None)?;
|
let endpoint_volume: IAudioEndpointVolume = default_device.Activate(CLSCTX_ALL, None)?;
|
||||||
|
|
||||||
|
// Attach process to Discord
|
||||||
|
EnumWindows(Some(search_windows), LPARAM(0))?;
|
||||||
|
|
||||||
|
let discord = {
|
||||||
|
let hwnd = DISCORD_WHND.load(Ordering::SeqCst);
|
||||||
|
|
||||||
|
if hwnd.is_null() {
|
||||||
|
println!("Discord window not found");
|
||||||
|
return Ok(());
|
||||||
|
};
|
||||||
|
|
||||||
|
*hwnd
|
||||||
|
};
|
||||||
|
|
||||||
// Check if the microphone is muted
|
// Check if the microphone is muted
|
||||||
let mut is_muted = endpoint_volume.GetMute()?.as_bool();
|
let mut is_muted = endpoint_volume.GetMute()?.as_bool();
|
||||||
|
|
||||||
|
@ -31,11 +99,13 @@ fn main() -> windows::core::Result<()> {
|
||||||
let is_new_muted = endpoint_volume.GetMute()?.as_bool();
|
let is_new_muted = endpoint_volume.GetMute()?.as_bool();
|
||||||
if is_new_muted != is_muted {
|
if is_new_muted != is_muted {
|
||||||
is_muted = is_new_muted;
|
is_muted = is_new_muted;
|
||||||
if is_muted {
|
println!(
|
||||||
println!("Microphone is muted.");
|
"Microphone is {}",
|
||||||
} else {
|
if is_muted { "muted" } else { "unmuted" }
|
||||||
println!("Microphone is not muted.");
|
);
|
||||||
}
|
|
||||||
|
// send keybind to discord (ctrl+shift+m)
|
||||||
|
press_keys(discord, &[VK_CONTROL, VK_SHIFT, VK_M])?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue