Add mute change notification, remove nwg trash, package updates
This commit is contained in:
@@ -3,7 +3,7 @@ use std::{
|
||||
env,
|
||||
error::Error,
|
||||
fs::{self, File},
|
||||
io::{BufRead, BufReader},
|
||||
io::{BufRead, BufReader}
|
||||
};
|
||||
|
||||
use auto_mute_lib::muter::MuterThread;
|
||||
@@ -14,18 +14,10 @@ use windows::{
|
||||
FindCloseChangeNotification, FindFirstChangeNotificationW, FindNextChangeNotification,
|
||||
FILE_NOTIFY_CHANGE_LAST_WRITE,
|
||||
},
|
||||
System::{
|
||||
Com::{CoInitializeEx, COINIT_MULTITHREADED},
|
||||
Threading::{WaitForSingleObject, INFINITE}
|
||||
},
|
||||
System::Threading::{WaitForSingleObject, INFINITE},
|
||||
}, core::w,
|
||||
};
|
||||
|
||||
pub fn load_mute_txt(file_name: &str) -> HashSet<String> {
|
||||
let file = File::open(file_name).unwrap();
|
||||
HashSet::from_iter(BufReader::new(file).lines().map(|line| line.unwrap()))
|
||||
}
|
||||
|
||||
pub fn await_file_change(file_name: &str) -> Result<(), Box<dyn Error>> {
|
||||
unsafe {
|
||||
let md = fs::metadata(file_name)?.modified()?;
|
||||
@@ -40,13 +32,17 @@ pub fn await_file_change(file_name: &str) -> Result<(), Box<dyn Error>> {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub fn load_mute_txt(file_name: &str) -> HashSet<String> {
|
||||
let file = File::open(file_name).unwrap();
|
||||
HashSet::from_iter(BufReader::new(file).lines().map(|line| line.unwrap()))
|
||||
}
|
||||
|
||||
fn main() {
|
||||
unsafe {
|
||||
CoInitializeEx(None, COINIT_MULTITHREADED).unwrap();
|
||||
}
|
||||
MuterThread::com_init();
|
||||
let mute_file: String = env::args().nth(1).unwrap_or("mute.txt".to_string());
|
||||
loop {
|
||||
let mut _mt = MuterThread::new(load_mute_txt(&mute_file));
|
||||
let mut _mt = MuterThread::new(load_mute_txt(&mute_file), None);
|
||||
await_file_change(&mute_file).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,8 +3,20 @@ name = "auto_mute_gui"
|
||||
version = "0.2.0"
|
||||
edition = "2021"
|
||||
|
||||
[build-dependencies]
|
||||
winresource = "0.1.17"
|
||||
|
||||
[dependencies]
|
||||
auto_mute_lib = { path = "../auto_mute_lib" }
|
||||
native-windows-gui = "1.0.13"
|
||||
native-windows-derive = "1.0.5"
|
||||
windows-core = "0.58.0"
|
||||
|
||||
[dependencies.windows]
|
||||
version = "0.58.0"
|
||||
features = [
|
||||
"Win32_UI",
|
||||
"Win32_UI_Accessibility",
|
||||
"Win32_UI_WindowsAndMessaging",
|
||||
"Win32_UI_Shell",
|
||||
"Win32_Foundation",
|
||||
"Win32_System_LibraryLoader",
|
||||
]
|
||||
|
||||
11
crates/auto_mute_gui/build.rs
Normal file
11
crates/auto_mute_gui/build.rs
Normal file
@@ -0,0 +1,11 @@
|
||||
extern crate winresource;
|
||||
|
||||
fn main() {
|
||||
if cfg!(target_os = "windows") {
|
||||
winresource::WindowsResource::new()
|
||||
.set_icon(r"C:\Users\ultra\ownCloud\ShitMuter\ShitMuter\icon1.ico")
|
||||
.set_icon_with_id(r"C:\Users\ultra\ownCloud\ShitMuter\ShitMuter\icon1.ico", "ICO_UNMUTE")
|
||||
.set_icon_with_id(r"C:\Users\ultra\ownCloud\ShitMuter\ShitMuter\icon2.ico", "ICO_MUTE")
|
||||
.compile().unwrap();
|
||||
}
|
||||
}
|
||||
@@ -1,70 +1,55 @@
|
||||
extern crate native_windows_gui as nwg;
|
||||
extern crate native_windows_derive as nwd;
|
||||
use std::{collections::HashSet, env, fs::File, io::{BufRead, BufReader}};
|
||||
|
||||
use nwd::NwgUi;
|
||||
use nwg::NativeUi;
|
||||
use auto_mute_lib::muter::MuterThread;
|
||||
use windows::Win32::{Foundation::HWND, System::LibraryLoader::GetModuleHandleW, UI::{Shell::{Shell_NotifyIconW, NIF_ICON, NIF_MESSAGE, NIM_ADD, NOTIFYICONDATAW}, WindowsAndMessaging::{LoadIconW, WM_USER}}};
|
||||
use windows_core::w;
|
||||
|
||||
const WM_TRAY_MENU: u32 = WM_USER;
|
||||
|
||||
#[derive(Default, NwgUi)]
|
||||
pub struct BasicApp {
|
||||
#[nwg_control(size: (300, 515), position: (300, 300), title: "Basic example", flags: "WINDOW")]
|
||||
window: nwg::Window,
|
||||
|
||||
#[nwg_resource(source_file: Some("./res/muted.ico"))]
|
||||
muted_icon: nwg::Icon,
|
||||
|
||||
#[nwg_resource(source_file: Some("./res/unmuted.ico"))]
|
||||
unmuted_icon: nwg::Icon,
|
||||
|
||||
#[nwg_layout(parent: window, spacing: 1)]
|
||||
grid: nwg::GridLayout,
|
||||
|
||||
#[nwg_control()]
|
||||
#[nwg_layout_item(layout: grid, row: 0, col: 0)]
|
||||
listbox: nwg::ListBox<String>,
|
||||
|
||||
#[nwg_control(text: "Test", size: (50, 50))]
|
||||
#[nwg_layout_item(layout: grid, col: 0, row: 1, row_span: 2)]
|
||||
hello_button: nwg::Button,
|
||||
|
||||
#[nwg_control(parent: window, popup: true)]
|
||||
tray_menu: nwg::Menu,
|
||||
|
||||
#[nwg_control(parent: tray_menu, text: "Show")]
|
||||
#[nwg_events(OnMenuItemSelected: [BasicApp::on_show])]
|
||||
tray_show: nwg::MenuItem,
|
||||
|
||||
#[nwg_control(parent: tray_menu)]
|
||||
tray_sep: nwg::MenuSeparator,
|
||||
|
||||
#[nwg_control(parent: tray_menu, text: "Exit")]
|
||||
#[nwg_events(OnMenuItemSelected: [BasicApp::on_close])]
|
||||
tray_exit: nwg::MenuItem,
|
||||
|
||||
#[nwg_control(icon: Some(&data.muted_icon))]
|
||||
#[nwg_events( OnContextMenu: [BasicApp::on_menu] )]
|
||||
tray: nwg::TrayNotification,
|
||||
pub struct MagicTray {
|
||||
pub notifdata: NOTIFYICONDATAW
|
||||
}
|
||||
|
||||
impl BasicApp {
|
||||
fn on_close(&self) {
|
||||
nwg::stop_thread_dispatch();
|
||||
}
|
||||
|
||||
fn on_show(&self) {
|
||||
self.window.set_visible(true);
|
||||
self.listbox.set_collection(vec!["potato".to_string(), "good".to_string()]);
|
||||
impl MagicTray {
|
||||
fn new() -> MagicTray {
|
||||
unsafe {
|
||||
let mut mt = MagicTray {
|
||||
notifdata: NOTIFYICONDATAW {
|
||||
cbSize: size_of::<NOTIFYICONDATAW>().try_into().unwrap(),
|
||||
hWnd: HWND::default(),
|
||||
uID: 1,
|
||||
uFlags: NIF_ICON | NIF_MESSAGE,
|
||||
uCallbackMessage: WM_TRAY_MENU,
|
||||
hIcon: LoadIconW(GetModuleHandleW(None).unwrap(), w!("ICO_UNMUTE")).unwrap(),
|
||||
..Default::default()
|
||||
}
|
||||
};
|
||||
mt.init();
|
||||
mt
|
||||
}
|
||||
}
|
||||
fn init(&mut self) {
|
||||
unsafe {
|
||||
Shell_NotifyIconW(NIM_ADD, &self.notifdata).unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn on_menu(&self) {
|
||||
let (x, y) = nwg::GlobalCursor::position();
|
||||
self.tray_menu.popup(x, y);
|
||||
impl Default for MagicTray {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub fn load_mute_txt(file_name: &str) -> HashSet<String> {
|
||||
let file = File::open(file_name).unwrap();
|
||||
HashSet::from_iter(BufReader::new(file).lines().map(|line| line.unwrap()))
|
||||
}
|
||||
|
||||
fn main() {
|
||||
nwg::init().expect("Failed to init Native Windows GUI");
|
||||
nwg::Font::set_global_family("Segoe UI").expect("Failed to set default font");
|
||||
let _app = BasicApp::build_ui(Default::default()).expect("Failed to build UI");
|
||||
nwg::dispatch_thread_events();
|
||||
MuterThread::com_init();
|
||||
let mute_file: String = env::args().nth(1).unwrap_or("mute.txt".to_string());
|
||||
let _mt = MuterThread::new(load_mute_txt(&mute_file), None);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
use std::{
|
||||
collections::HashSet,
|
||||
error::Error,
|
||||
@@ -13,10 +12,12 @@ use crate::sm_session_notifier::SMSessionNotifierThread;
|
||||
use crate::window_change::WindowChangeMonitor;
|
||||
use windows::{
|
||||
core::Interface,
|
||||
Win32::Media::Audio::{IAudioSessionControl2, ISimpleAudioVolume},
|
||||
Win32::{
|
||||
Media::Audio::{IAudioSessionControl2, ISimpleAudioVolume},
|
||||
System::Com::{CoInitializeEx, COINIT_MULTITHREADED},
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
use crate::pid_to_exe::pid_to_exe_path;
|
||||
enum MuterMessage {
|
||||
WindowChange(String),
|
||||
@@ -24,6 +25,10 @@ enum MuterMessage {
|
||||
Exit(),
|
||||
}
|
||||
|
||||
pub enum MuteChangeNotification {
|
||||
MuteChanged(bool),
|
||||
}
|
||||
|
||||
unsafe impl Send for MuterMessage {}
|
||||
|
||||
struct SessionMuter {
|
||||
@@ -33,6 +38,7 @@ struct SessionMuter {
|
||||
_session_notifier: SMSessionNotifierThread,
|
||||
_win_change_mon: WindowChangeMonitor,
|
||||
rx: Receiver<MuterMessage>,
|
||||
notify_tx: Option<Sender<MuteChangeNotification>>,
|
||||
}
|
||||
|
||||
impl SessionMuter {
|
||||
@@ -40,6 +46,7 @@ impl SessionMuter {
|
||||
mute_executables: HashSet<String>,
|
||||
rx: Receiver<MuterMessage>,
|
||||
tx: Sender<MuterMessage>,
|
||||
notify_tx: Option<Sender<MuteChangeNotification>>,
|
||||
) -> SessionMuter {
|
||||
SessionMuter {
|
||||
sessions: Vec::new(),
|
||||
@@ -57,6 +64,7 @@ impl SessionMuter {
|
||||
}))
|
||||
},
|
||||
rx,
|
||||
notify_tx,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -84,6 +92,8 @@ impl SessionMuter {
|
||||
volume.SetMute(self.mute_flag, null_mut())?;
|
||||
}
|
||||
self.sessions.push(session);
|
||||
} else {
|
||||
println!("Skipping session from: {:?}", fn_str);
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
@@ -91,6 +101,9 @@ impl SessionMuter {
|
||||
|
||||
fn set_mute_all(self: &mut SessionMuter, mute: bool) {
|
||||
unsafe {
|
||||
self.notify_tx
|
||||
.as_ref()
|
||||
.and_then(|x| x.send(MuteChangeNotification::MuteChanged(mute)).ok());
|
||||
let results = self
|
||||
.sessions
|
||||
.iter()
|
||||
@@ -141,12 +154,18 @@ pub struct MuterThread {
|
||||
}
|
||||
|
||||
impl MuterThread {
|
||||
pub fn new(s: HashSet<String>) -> MuterThread {
|
||||
pub fn com_init() {
|
||||
unsafe { CoInitializeEx(None, COINIT_MULTITHREADED).unwrap() };
|
||||
}
|
||||
pub fn new(
|
||||
s: HashSet<String>,
|
||||
notify_tx: Option<Sender<MuteChangeNotification>>,
|
||||
) -> MuterThread {
|
||||
let (sender, receiver) = mpsc::channel::<MuterMessage>();
|
||||
MuterThread {
|
||||
sender: sender.clone(),
|
||||
handle: Some(thread::spawn(move || {
|
||||
let mut muter = SessionMuter::new(s, receiver, sender);
|
||||
let mut muter = SessionMuter::new(s, receiver, sender, notify_tx);
|
||||
muter.run();
|
||||
})),
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user