Allow dropping old muters.
This commit is contained in:
@@ -46,3 +46,9 @@ impl IMMNotificationClient_Impl for DeviceNotificationClient {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for DeviceNotificationClient {
|
||||
fn drop(&mut self) {
|
||||
println!("DNC Drop");
|
||||
}
|
||||
}
|
||||
67
src/main.rs
67
src/main.rs
@@ -16,7 +16,7 @@ use std::{
|
||||
};
|
||||
|
||||
use sm_session_notifier::SMSessionNotifier;
|
||||
use window_change::{await_win_change_events};
|
||||
use window_change::WindowChangeMonitor;
|
||||
use windows::{
|
||||
core::Interface,
|
||||
Win32::{
|
||||
@@ -31,20 +31,38 @@ struct SessionMuter {
|
||||
sessions: Vec<IAudioSessionControl2>,
|
||||
mute_executables: HashSet<String>,
|
||||
mute_flag: bool,
|
||||
}
|
||||
|
||||
fn load_mute_txt() -> HashSet<String> {
|
||||
let file = File::open("mute.txt").unwrap();
|
||||
return HashSet::from_iter(BufReader::new(file).lines().map(|line| line.unwrap()));
|
||||
win: Option<WindowChangeMonitor>
|
||||
}
|
||||
|
||||
impl SessionMuter {
|
||||
fn new() -> SessionMuter {
|
||||
SessionMuter {
|
||||
fn start(mute_executables: HashSet<String>) -> Arc<Mutex<SessionMuter>> {
|
||||
let muter = Arc::new(Mutex::new(SessionMuter {
|
||||
sessions: Vec::new(),
|
||||
mute_executables: load_mute_txt(),
|
||||
mute_executables,
|
||||
mute_flag: true,
|
||||
win: None
|
||||
}));
|
||||
{
|
||||
let muter = Arc::downgrade(&muter);
|
||||
let muter_internal = muter.clone();
|
||||
muter.upgrade().unwrap().lock().as_mut().unwrap().win = Some(WindowChangeMonitor::start(Box::new(move |s| {
|
||||
muter_internal.upgrade().map(|f| f.lock().unwrap().notify_window_changed(&s));
|
||||
})));
|
||||
}
|
||||
|
||||
{
|
||||
let muter = Arc::downgrade(&muter);
|
||||
let sn = SMSessionNotifier::new(Box::new(move |session| {
|
||||
muter.upgrade().unwrap().lock().unwrap().add_session(session).unwrap()
|
||||
}));
|
||||
sn.lock()
|
||||
.unwrap()
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.boot_devices()
|
||||
.expect("failed to get initial audio devices and sessions");
|
||||
}
|
||||
return muter;
|
||||
}
|
||||
|
||||
fn add_session(
|
||||
@@ -114,24 +132,23 @@ impl SessionMuter {
|
||||
|
||||
unsafe impl Send for SessionMuter {}
|
||||
|
||||
|
||||
fn load_mute_txt() -> HashSet<String> {
|
||||
let file = File::open("mute.txt").unwrap();
|
||||
return HashSet::from_iter(BufReader::new(file).lines().map(|line| line.unwrap()));
|
||||
}
|
||||
|
||||
|
||||
fn test_muter() {
|
||||
SessionMuter::start(load_mute_txt());
|
||||
}
|
||||
|
||||
fn main() {
|
||||
unsafe {
|
||||
CoInitializeEx(None, COINIT_MULTITHREADED).unwrap();
|
||||
}
|
||||
let muter = Arc::new(Mutex::new(SessionMuter::new()));
|
||||
let muter2 = muter.clone();
|
||||
let sn = SMSessionNotifier::new(Box::new(move |session| {
|
||||
muter2.lock().unwrap().add_session(session).unwrap()
|
||||
}));
|
||||
|
||||
sn.lock()
|
||||
.unwrap()
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.boot_devices()
|
||||
.expect("failed to get initial audio devices and sessions");
|
||||
|
||||
await_win_change_events(Box::new(move |s| {
|
||||
muter.lock().unwrap().notify_window_changed(&s)
|
||||
}));
|
||||
loop {
|
||||
test_muter();
|
||||
println!("Test_muter done");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,3 +23,9 @@ impl IAudioSessionNotification_Impl for SessionNotification {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for SessionNotification {
|
||||
fn drop(&mut self) {
|
||||
println!("SN drop");
|
||||
}
|
||||
}
|
||||
@@ -31,8 +31,8 @@ impl SMSessionNotifier {
|
||||
) -> Arc<Mutex<Option<SMSessionNotifier>>> {
|
||||
let session_notifier_arc: Arc<Mutex<Option<SMSessionNotifier>>> =
|
||||
Arc::new(Mutex::new(None));
|
||||
let sn2 = session_notifier_arc.clone();
|
||||
let sn3 = session_notifier_arc.clone();
|
||||
let sn2 = Arc::downgrade(&session_notifier_arc);
|
||||
let sn3 = sn2.clone();
|
||||
let notifier = SMSessionNotifier {
|
||||
session_managers: Vec::new(),
|
||||
device_enumerator: unsafe {
|
||||
@@ -40,7 +40,7 @@ impl SMSessionNotifier {
|
||||
},
|
||||
device_notification_client: IMMNotificationClient::from(DeviceNotificationClient {
|
||||
callback: Box::new(move |id| {
|
||||
match sn2.lock().unwrap().as_mut().unwrap().add_device_by_id(id) {
|
||||
match sn2.upgrade().unwrap().lock().unwrap().as_mut().unwrap().add_device_by_id(id) {
|
||||
Ok(_) => {},
|
||||
Err(e) => {
|
||||
println!("Failed to add new device: {:?}", e);
|
||||
@@ -50,13 +50,13 @@ impl SMSessionNotifier {
|
||||
}),
|
||||
session_notification: IAudioSessionNotification::from(SessionNotification {
|
||||
callback: Box::new(move |session| {
|
||||
(sn3.lock().unwrap().as_mut().unwrap().notification_function)(session)
|
||||
(sn3.upgrade().unwrap().lock().unwrap().as_mut().unwrap().notification_function)(session)
|
||||
}),
|
||||
}),
|
||||
notification_function: callback,
|
||||
};
|
||||
*session_notifier_arc.lock().unwrap() = Some(notifier);
|
||||
return session_notifier_arc.clone();
|
||||
return session_notifier_arc;
|
||||
}
|
||||
|
||||
pub(crate) fn boot_devices(self: &mut SMSessionNotifier) -> Result<(), Box<dyn Error>> {
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
use std::sync::Mutex;
|
||||
use std::{sync::{Mutex, atomic::AtomicU32, Arc}, thread::{self, JoinHandle}};
|
||||
|
||||
use windows::Win32::{
|
||||
Foundation::{HINSTANCE, HWND},
|
||||
Foundation::{HINSTANCE, HWND, WPARAM, LPARAM},
|
||||
UI::{
|
||||
Accessibility::{SetWinEventHook, HWINEVENTHOOK},
|
||||
WindowsAndMessaging::{
|
||||
DispatchMessageW, GetForegroundWindow, GetMessageW, GetWindowThreadProcessId,
|
||||
TranslateMessage, EVENT_SYSTEM_FOREGROUND, EVENT_SYSTEM_MINIMIZEEND, MSG,
|
||||
WINEVENT_OUTOFCONTEXT, WINEVENT_SKIPOWNPROCESS,
|
||||
WINEVENT_OUTOFCONTEXT, WINEVENT_SKIPOWNPROCESS, PostThreadMessageW, WM_QUIT,
|
||||
},
|
||||
},
|
||||
}, System::Threading::GetCurrentThreadId,
|
||||
};
|
||||
|
||||
use crate::pid_to_exe::pid_to_exe_path;
|
||||
@@ -48,7 +48,9 @@ unsafe extern "system" fn win_event_proc(
|
||||
}
|
||||
}
|
||||
|
||||
pub fn await_win_change_events(callback: Box<dyn Fn(&str) + Send>) {
|
||||
type WinCallback = Box<dyn Fn(&str) + Send>;
|
||||
|
||||
pub fn await_win_change_events(callback: WinCallback) {
|
||||
*WIN_CHANGE_CALLBACK.lock().unwrap() = Some(callback);
|
||||
unsafe {
|
||||
SetWinEventHook(
|
||||
@@ -71,9 +73,53 @@ pub fn await_win_change_events(callback: Box<dyn Fn(&str) + Send>) {
|
||||
);
|
||||
|
||||
let mut msg: MSG = MSG::default();
|
||||
while GetMessageW(&mut msg, HWND::default(), 0, 0).as_bool() {
|
||||
while GetMessageW(&mut msg, HWND::default(), 0, 0).0 > 0 {
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessageW(&msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct WindowChangeMonitor {
|
||||
join_handle: Option<JoinHandle<()>>,
|
||||
win_thread_id: Arc<AtomicU32>
|
||||
}
|
||||
|
||||
impl Drop for WindowChangeMonitor {
|
||||
fn drop(&mut self) {
|
||||
if let Some(join_handle) = self.join_handle.take() {
|
||||
let tid : u32 = self.win_thread_id.load(std::sync::atomic::Ordering::Relaxed);
|
||||
|
||||
if tid != 0 {
|
||||
unsafe {
|
||||
PostThreadMessageW(tid, WM_QUIT, WPARAM(0), LPARAM(0)).ok().unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
join_handle.join().expect("Unable to terminate window change thread");
|
||||
}
|
||||
println!("Joined window change thread");
|
||||
}
|
||||
}
|
||||
|
||||
impl WindowChangeMonitor {
|
||||
pub(crate) fn start(f : WinCallback) -> WindowChangeMonitor {
|
||||
let win_thread_id = Arc::new(AtomicU32::new(0));
|
||||
let join_handle = {
|
||||
let win_thread_id = win_thread_id.clone();
|
||||
thread::spawn(move || {
|
||||
win_thread_id.store(unsafe { GetCurrentThreadId() }.into(), std::sync::atomic::Ordering::Relaxed);
|
||||
await_win_change_events(f);
|
||||
})
|
||||
};
|
||||
|
||||
{
|
||||
let win_thread_id = win_thread_id.clone();
|
||||
WindowChangeMonitor {
|
||||
join_handle: Some(join_handle),
|
||||
win_thread_id
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
5
todo.txt
5
todo.txt
@@ -1 +1,4 @@
|
||||
- create session-focused API - should provide a callback for all existing sessions and any time a new sessions is created
|
||||
- Add the ability to reload/restart the mute list - must essentially restart/refresh all sessions if this occurs?
|
||||
- can we simply release everything in this case? Should work given the way the windows-rs COM wrapper works I think.
|
||||
- Tray icon
|
||||
- Simple GUI to select from open windows and add to the list
|
||||
|
||||
Reference in New Issue
Block a user