feat: two-way sync

This commit is contained in:
newt 2024-11-17 12:43:15 +00:00
parent bac19ec2b8
commit 1c181a70fd
4 changed files with 29 additions and 74 deletions

3
.gitmodules vendored Normal file
View file

@ -0,0 +1,3 @@
[submodule "vencord"]
path = vencord
url = ssh://git@git.newty.dev:2222/newt/muter-vencord.git

View file

@ -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" });
}
}
}
}

View file

@ -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

@ -0,0 +1 @@
Subproject commit 6c6e2098364bc70659c57856375ba10ccb3888e7