feat: two-way sync
This commit is contained in:
parent
bac19ec2b8
commit
1c181a70fd
4 changed files with 29 additions and 74 deletions
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
[submodule "vencord"]
|
||||
path = vencord
|
||||
url = ssh://git@git.newty.dev:2222/newt/muter-vencord.git
|
85
src/main.rs
85
src/main.rs
|
@ -1,10 +1,5 @@
|
|||
use muter::ORDERING;
|
||||
use std::{
|
||||
ptr,
|
||||
sync::atomic::{AtomicBool, AtomicPtr},
|
||||
thread,
|
||||
time::Duration,
|
||||
};
|
||||
use std::{ptr, sync::atomic::AtomicBool};
|
||||
use warp::Filter;
|
||||
use windows::Win32::{
|
||||
Foundation::{BOOL, HWND, LPARAM, WPARAM},
|
||||
|
@ -21,50 +16,9 @@ use windows::Win32::{
|
|||
|
||||
mod ws;
|
||||
|
||||
static mut DISCORD_WHND: AtomicPtr<HWND> = AtomicPtr::new(ptr::null_mut());
|
||||
const PORT: u16 = 3034;
|
||||
static mut IS_MUTED: AtomicBool = AtomicBool::new(false);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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(())
|
||||
}
|
||||
static mut PREFER: AtomicBool = AtomicBool::new(false);
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<(), muter::Error> {
|
||||
|
@ -82,20 +36,6 @@ async fn main() -> Result<(), muter::Error> {
|
|||
// Activate the IAudioEndpointVolume interface for the capture device
|
||||
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);
|
||||
|
||||
if hwnd.is_null() {
|
||||
println!("Discord window not found");
|
||||
return Ok(());
|
||||
};
|
||||
|
||||
*hwnd
|
||||
};
|
||||
|
||||
// Setup WSS serve
|
||||
let server = warp::serve(
|
||||
warp::path::end()
|
||||
|
@ -104,7 +44,7 @@ async fn main() -> Result<(), muter::Error> {
|
|||
ws.on_upgrade(move |socket| ws::user_connected(socket))
|
||||
}),
|
||||
)
|
||||
.run(([127, 0, 0, 1], 3034));
|
||||
.run(([127, 0, 0, 1], PORT));
|
||||
tokio::task::spawn(server);
|
||||
|
||||
// Check if the microphone is muted
|
||||
|
@ -112,14 +52,19 @@ async fn main() -> Result<(), muter::Error> {
|
|||
|
||||
loop {
|
||||
// check if the mute status has changed
|
||||
let prefer = PREFER.load(ORDERING);
|
||||
let muted = IS_MUTED.load(ORDERING);
|
||||
let is_new_muted = endpoint_volume.GetMute()?.as_bool();
|
||||
if is_new_muted != muted {
|
||||
IS_MUTED.store(is_new_muted, ORDERING);
|
||||
println!("Microphone is {}", if muted { "muted" } else { "unmuted" });
|
||||
|
||||
// send keybind to discord (ctrl+shift+m)
|
||||
// press_keys(discord, &[VK_CONTROL, VK_SHIFT, VK_M])?;
|
||||
if prefer {
|
||||
endpoint_volume.SetMute(BOOL(muted as i32), ptr::null())?;
|
||||
PREFER.store(false, ORDERING);
|
||||
println!("Microphone is {}", if muted { "muted" } else { "unmuted" });
|
||||
} else {
|
||||
let new = endpoint_volume.GetMute()?.as_bool();
|
||||
if muted != new {
|
||||
IS_MUTED.store(new, ORDERING);
|
||||
println!("Microphone is {}", if new { "muted" } else { "unmuted" });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
14
src/ws.rs
14
src/ws.rs
|
@ -4,19 +4,25 @@ use std::time::Duration;
|
|||
use tokio::time::timeout;
|
||||
use warp::{filters::ws::Message, ws::WebSocket};
|
||||
|
||||
use crate::IS_MUTED;
|
||||
use crate::{IS_MUTED, PREFER};
|
||||
|
||||
pub async fn user_connected(socket: WebSocket) {
|
||||
println!("User connected");
|
||||
|
||||
let (mut tx, mut rx) = socket.split();
|
||||
|
||||
let mut prev_mute = unsafe { !IS_MUTED.load(ORDERING) };
|
||||
|
||||
loop {
|
||||
match timeout(Duration::from_millis(100), rx.next()).await {
|
||||
Ok(Some(Ok(msg))) => {
|
||||
if msg.is_close() {
|
||||
// check for mute message
|
||||
if msg.is_binary() {
|
||||
let mute = msg.as_bytes() != [1];
|
||||
unsafe {
|
||||
IS_MUTED.store(mute, ORDERING);
|
||||
PREFER.store(true, ORDERING);
|
||||
}
|
||||
} else if msg.is_close() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -31,7 +37,7 @@ pub async fn user_connected(socket: WebSocket) {
|
|||
let mute = unsafe { IS_MUTED.load(ORDERING) };
|
||||
|
||||
if mute != prev_mute {
|
||||
tx.send(Message::binary(vec![if mute { 1 } else { 0 }]))
|
||||
tx.send(Message::binary(if mute { vec![1] } else { vec![] }))
|
||||
.await
|
||||
.unwrap();
|
||||
prev_mute = mute;
|
||||
|
|
1
vencord
Submodule
1
vencord
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit 6c6e2098364bc70659c57856375ba10ccb3888e7
|
Loading…
Reference in a new issue