Skip to content

Instantly share code, notes, and snippets.

@stduhpf
Last active May 3, 2024 16:36
Show Gist options
  • Save stduhpf/d12d0eb321005467d1a7f36d32554042 to your computer and use it in GitHub Desktop.
Save stduhpf/d12d0eb321005467d1a7f36d32554042 to your computer and use it in GitHub Desktop.
Force mute out of focus Windows app
# This code is licensed under the terms of the MIT license
# This script is made to force some Windows app to stop outputting sound when not focused.
# Requirements: - Windows operating system (tested on Windows 10 22H2)
# - python 3
# - pycaw (Python Core Audio Windows Library): `pip install pycaw`
# Acknowledgments:
# - Most of the credit goes to superuser.com user steve0: https://superuser.com/a/1796210
# - Refactoring and improved UX by stduhpf, with the help of a local llama-3 8B (4bit) instance
from pycaw.pycaw import AudioUtilities
import win32gui
import win32process
import time
from sys import argv
def autoSelectTargetWindow():
# Find second to last focused window (to use as default)
selfHwnd = 0
if len(argv)<=1 or argv[1]=="--":
def callback(hwnd:int,_):
nonlocal selfHwnd
if win32gui.IsWindowVisible(hwnd) and win32gui.GetWindowText(hwnd).strip():
status = selfHwnd
selfHwnd = hwnd
return status==0
return True
try:
win32gui.EnumWindows(callback,None)
except:
pass
return selfHwnd
#########################################
def find_process_id(hwnd_target):
if hwnd_target != 0:
_, process_id = win32process.GetWindowThreadProcessId(hwnd_target)
return process_id
return None
def app_is_in_foreground(hwnd_target):
try:
fg_hwnd = win32gui.GetForegroundWindow()
if hwnd_target == fg_hwnd:
return True
except Exception as e:
print(f"Error: {e}")
return False
def change_app_mute(process_id, mute=1):
sessions = AudioUtilities.GetAllSessions()
for session in sessions:
if session.Process and session.Process.pid == process_id:
session.SimpleAudioVolume.SetMute(mute, None)
#########################################
def worker(hwnd_target,interval,dbg):
mute_state = -1
prev_mute_state = mute_state
while True:
process_id = find_process_id(hwnd_target)
if process_id and win32gui.IsWindow(hwnd_target):
mute_state = 0 if app_is_in_foreground(hwnd_target) else 1
if mute_state != prev_mute_state:
change_app_mute(process_id, mute_state)
if dbg:
print(f"Toggled mute {'ON' if mute_state else 'OFF'}")
prev_mute_state = mute_state
else:
print(f"Target process terminated! {'(App will remain muted after next launch)' if mute_state else ''}")
break
time.sleep(interval)
#########################################
def printUsage():
print(f"USAGE: {argv[0]} TARGETED_WINDOW_NAME Debug=[True|False] update_interval")
print(f"\t- TARGETED_WINDOW_NAME: Name of the target window (defaults to the previous focused window)")
print(f"\t- Debug: \t\tSet to False to suppress output (defaults to True)")
print(f"\t- update_interval: \tDelay in-between consecutive checks of the state of the target window (in s) (defaults to 1)")
print(f"To use default values, you can ignore an argument by setting it to '--'")
print(f"\t(example: `{argv[0]} -- -- 0.1` to only affect update_interval)\n")
def printWindowError():
print("ERROR: Couldn't find valid hwnd for target window")
if (len(argv) > 1 and argv[1]!="--"):
def dumpAvailableWindowTexts():
def callback(hwnd:int,_):
text = win32gui.GetWindowText(hwnd).strip()
if win32gui.IsWindowVisible(hwnd) and text:
print(f"\t{text}")
return True
try:
win32gui.EnumWindows(callback,None)
except:
pass
print(f"No window named \"{argv[1]}\" found\nAvailable windows:")
dumpAvailableWindowTexts()
exit(-1)
if __name__ == "__main__":
try:
dbg = bool(argv[2]) if len(argv) > 2 and argv[2]!="--" else True
interval = float(argv[3]) if len(argv) > 3 and argv[3]!="--" else 1
except ValueError:
printUsage()
exit(-1)
hwnd_target = win32gui.FindWindow(None, argv[1]) if len(argv) > 1 and argv[1]!="--" else autoSelectTargetWindow()
if hwnd_target==0:
printUsage()
printWindowError()
if dbg:
print(f"Targeted window: {win32gui.GetWindowText(hwnd_target)}")
try:
worker(hwnd_target, interval, dbg)
except KeyboardInterrupt:
print("Un-muting target app...")
try:
process_id = find_process_id(hwnd_target)
change_app_mute(process_id, 0)
except:
print("Error: un-muting might have failed")
print("Exiting...")
exit(0)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment