-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathwindows_volume.py
143 lines (120 loc) · 5.23 KB
/
windows_volume.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
# https://github.com/AndreMiras/pycaw
# https://docs.microsoft.com/en-us/windows-hardware/drivers/audio/default-audio-volume-settings
# https://docs.microsoft.com/en-us/windows/desktop/CoreAudio/audio-tapered-volume-controls
'''
zero seems to be:
20 * math.log10(1/65535)
which is -96.329...
100% seems to be:
20 * math.log10(65535/65535)
which is 0
This gets the value from the slider.
GetMasterVolumeLevelScalar()
'''
from ctypes import cast, POINTER
from comtypes import CLSCTX_ALL
#from pycaw.pycaw import AudioUtilities, IAudioEndpointVolume
from pycaw import pycaw
import psutil
import win32gui
import win32process
class WindowsAudio():
def __init__(self):
self.devices = pycaw.AudioUtilities.GetSpeakers()
self.interface = self.devices.Activate(
pycaw.IAudioEndpointVolume._iid_, CLSCTX_ALL, None)
self.volume = cast(self.interface, POINTER(pycaw.IAudioEndpointVolume))
@property
def mute(self):
return bool(self.volume.GetMute())
@mute.setter
def mute(self, state):
if not isinstance(state, bool):
raise ValueError
self.volume.SetMute(state, None)
@property
def master_volume(self):
'''Master volume slider value.'''
return round(self.volume.GetMasterVolumeLevelScalar(), 2)
@master_volume.setter
def master_volume(self, value):
'''Set master volume using slider value.'''
value = float(value)
if not 0.0 <= value <= 1:
raise ValueError('master volume value not between 0.0 and 1.0')
self.volume.SetMasterVolumeLevelScalar(value, None)
@property
def master_decibels(self):
return self.volume.GetMasterVolumeLevel()
@master_decibels.setter
def master_decibels(self, value):
'''This can be set from -96 (0%) to 0 (100%). See notes. -10.5 is 50%'''
self.volume.SetMasterVolumeLevel(value, None)
def master_volume_range(self):
return self.volume.GetVolumeRange()
@property
def sessions(self):
return pycaw.AudioUtilities.GetAllSessions()
def set_all_to_master(self):
# TODO: This master volume isn't related to the app.
# Just set it or figure out where the current volume really is.
for session in self.sessions:
volume = session._ctl.QueryInterface(pycaw.ISimpleAudioVolume)
starting_volume = volume.GetMasterVolume()
print(starting_volume)
if starting_volume != 1.0 or True:
# Set individual application volume to 100% of master volume.
volume.SetMasterVolume(1, None)
ending_volume = volume.GetMasterVolume()
#print('set {} volume from {} to {}'.format('app', starting_volume, ending_volume))
print('set PID {} volume from {} to {}'.format(session.ProcessId, starting_volume, ending_volume))
def all_apps_to_master_volume():
'''Set individual application volume to 100% of master volume.'''
sessions = pycaw.AudioUtilities.GetAllSessions()
for session in sessions:
print(dir(session))
volume = session._ctl.QueryInterface(pycaw.ISimpleAudioVolume)
volume.SetMasterVolume(1, None)
#starting_volume = volume.GetMasterVolume()
#if starting_volume != 1.0:
# # Set individual application volume to 100% of master volume.
# volume.SetMasterVolume(1, None)
# ending_volume = volume.GetMasterVolume()
# print('set {} volume from {} to {}'.format('app', starting_volume, ending_volume))
# use the psutil ppid to get the parent pid, then put into this function.
def get_hwnds(pid):
"""return a list of window handlers based on it process id"""
def callback(hwnd, hwnds):
if win32gui.IsWindowVisible(hwnd) and win32gui.IsWindowEnabled(hwnd):
_, found_pid = win32process.GetWindowThreadProcessId(hwnd)
if found_pid == pid:
hwnds.append(hwnd)
return True
hwnds = []
win32gui.EnumWindows(callback, hwnds)
return hwnds
# This will get the description (friendly name) of an exe.
def getFileDescription(windows_exe):
try:
language, codepage = win32api.GetFileVersionInfo(windows_exe, '\\VarFileInfo\\Translation')[0]
stringFileInfo = u'\\StringFileInfo\\%04X%04X\\%s' % (language, codepage, "FileDescription")
description = win32api.GetFileVersionInfo(windows_exe, stringFileInfo)
except:
description = "unknown"
return description
def get_session_process_names(sessions):
'''Build a list of tuples containing process names and descriptions.'''
names = []
for session in sessions:
if session.Process:
try:
exe_description = getFileDescription(session.Process.exe())
print(exe_description)
names.append((session.Process.name(), exe_description))
except psutil.AccessDenied:
print('denied for', session.Process)
names.append((session.Process.name(), None))
else:
print('no process')
names.append((None, None))
return names