Skip to content

Instantly share code, notes, and snippets.

@l0ll098
Created April 21, 2022 15:33
Show Gist options
  • Save l0ll098/36ecada4ac32cbb9aa3f6b45dba9f4b6 to your computer and use it in GitHub Desktop.
Save l0ll098/36ecada4ac32cbb9aa3f6b45dba9f4b6 to your computer and use it in GitHub Desktop.
A Windows script written in Python 3.6+ to control brightness of connected monitors
"""
A Windows script written in Python 3.6+ to control brightness of connected monitors.
Potentially this works only with Display Port connected monitors.
Other type of cables could be supported as long as they use the DDC/CI protocol.
Author: Lorenzo Montanari
"""
from ctypes import windll, byref, Structure, WinError, POINTER, WINFUNCTYPE
from ctypes.wintypes import BOOL, HMONITOR, HDC, RECT, LPARAM, DWORD, BYTE, WCHAR, HANDLE
import sys
import getopt
from enum import IntFlag
_MONITORENUMPROC = WINFUNCTYPE(BOOL, HMONITOR, HDC, POINTER(RECT), LPARAM)
DEFAULT_PARAMETERS = {
"brightness": 10
}
class Commands(IntFlag):
"""
Short list of commonly used DDC commands.
Taken from: https://github.com/bhuvanchandra/ddcci
"""
FACTORY_RESET = 0x04
RESET_BRIGHTNESS_CONTRAST = 0x05
FACTORY_RESET_GEOMETRY = 0x06
FACTORY_RESET_COLOR = 0x08
BRIGHTNESS = 0x10
CONTRAST = 0x12
INPUT_SOURCE_SELECT = 0x60
AUDIO_SPEAKER_VOLUME = 0x62
SETTINGS = 0xb0
OSD = 0xca
OSD_LANG = 0xcc
COLOR_PRESET = 0xe0
POWER_CONTROL = 0xe1
class PhysicalMonitor(Structure):
_fields_ = [
('handle', HANDLE),
('description', WCHAR * 128)
]
def __repr__(self) -> str:
return self.description
def list_monitors():
monitors = []
def callback(hmonitor, hdc, lprect, lparam):
monitors.append(HMONITOR(hmonitor))
return True
if not windll.user32.EnumDisplayMonitors(None, None, _MONITORENUMPROC(callback), None):
raise WinError('EnumDisplayMonitors failed')
physical_devices = []
for monitor in monitors:
# Get physical monitor count
count = DWORD()
if not windll.dxva2.GetNumberOfPhysicalMonitorsFromHMONITOR(monitor, byref(count)):
raise WinError()
# Get physical monitor handles
physical_array = (PhysicalMonitor * count.value)()
if not windll.dxva2.GetPhysicalMonitorsFromHMONITOR(monitor, count.value, physical_array):
raise WinError()
physical_devices.extend(physical_array)
return physical_devices
def close_handle(handle):
if not windll.dxva2.DestroyPhysicalMonitor(handle):
raise WinError()
def set_vcp_feature(monitor, code, value):
"""Sends a DDC command to the specified monitor."""
if not windll.dxva2.SetVCPFeature(HANDLE(monitor), BYTE(code), DWORD(value)):
raise WinError()
def parse_args(argv):
args_dict = {}
def _print_help_and_exit(exit_code = 0):
print("bc.py -b <brightness>")
sys.exit(exit_code)
try:
opts, args = getopt.getopt(argv, "hb:", ["brightness="])
except getopt.GetoptError:
_print_help_and_exit(1)
for opt, arg in opts:
if opt == '-h':
_print_help_and_exit()
if opt in ("-b", "--brightness"):
args_dict["brightness"] = int(arg)
return args_dict
def main(argv):
parsed = parse_args(argv)
args = { **DEFAULT_PARAMETERS, **parsed }
monitors = list_monitors()
for monitor in monitors:
handle = monitor.handle
set_vcp_feature(handle, Commands.BRIGHTNESS, args["brightness"])
close_handle(handle)
if __name__ == '__main__':
main(sys.argv[1:])
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment