Brightness Controller-源码记录

Brightness Controller 亮度控制

一、概述

项目:https://github.com/SunStorm2018/Brightness.git

原理:Brightness Controlle 是我在 Ubuntu 发现上调节亮度的一个工具,我觉得很好用,我后面对它的实现比较感兴趣,就去找了他的源项目来满足我的好奇心,也许后面做项目时候会使用,特此记录。

这个小工具是用的 python3 实现,界面使用 pyqt5 ,控制显示器功能用的命令完成的,会用到 ddcutilxrandr

在亮度调节后台的命令优先使用 ddcutil,其次才使用 xrandr。

二、ddcutil 与 xrandr

这里简单介绍一下 ddcutil

1. ddcutil

ddcutil 是一个 Linux 命令行工具,用于通过 DDC/CI(Display Data Channel Command Interface) 协议与支持该协议的显示器进行通信。它允许用户通过软件控制显示器的硬件设置,如亮度、对比度、输入源等。

  • . 调整显示器设置:
    • 亮度、对比度、音量等。
    • 切换输入源(如 HDMI、DP、VGA)。
    • 调整色彩设置(如 RGB 值)。
  • 查询显示器信息:
    • 获取显示器的制造商、型号、支持的 DDC/CI 功能等。
  • 自动化控制:
    • 通过脚本批量调整多台显示器的设置。

2. xrandr

xrandr 是一个 Linux 命令行工具,用于管理和配置显示器的分辨率、刷新率、旋转、镜像以及多显示器布局。它是 X Window System(Xorg)的一部分,主要用于与 X Server 交互,因此仅适用于运行 Xorg 的 Linux 系统。

三、部分代码解析

1. icons

图标文件夹

2. ui

界面文件夹,包含ui文件,以及通过uic工具对ui文件生成的pyqt脚本文件。

3. util

包含了基础的工具集

  1. check_displays.py
    查询连接的显示器工具,通过运行 xrandr --query 命令,再对输出用正则匹配出显示器名称
python 复制代码
import subprocess
import shlex
import re

def query_xrandr():
    query = "xrandr --query"
    xrandr_output = subprocess.Popen(shlex.split(query), stdout=subprocess.PIPE,
                                     stderr=subprocess.STDOUT)
    stdout, stderr = xrandr_output.communicate()
    return str(stdout, "utf-8")

def extract_displays(output):
    pattern = re.compile(r'\b({0})\b'.format("connected"), flags=re.IGNORECASE)
    lines = output.splitlines()
    connected = [line for line in lines if pattern.search(line)]
    connected_displays = list(
        map(lambda display: display.split()[0], connected))
    return connected_displays

def detect_display_devices():
    """
    Detects available displays.
    returns connected_displays
    This contains the available device names compatible with xrandr
    """
    return extract_displays(query_xrandr())


if __name__ == '__main__':
    print(detect_display_devices())
  1. executor.py
    封装的进程控制器,是调节亮度这些的后台命令
python 复制代码
import subprocess

def execute_command(string_cmd):
    subprocess.check_output(string_cmd, shell=True)

使用的例子如下

python 复制代码
def change_value_pr(self, value):
        """Changes Primary Display Red ratio"""
        cmd_value = "xrandr\
		--output %s \
		--brightness %s\
		--gamma %s:%s:%s" % \
                    (self.display1,
                     self.values[self.ui.primary_brightness.value() - 1],
                     self.values[value],
                     self.values[self.ui.primary_green.value()],
                     self.values[self.ui.primary_blue.value()])
        Executor.execute_command(cmd_value)
  1. read_config.py 和 write_config.py

    读写配置,没有特别内容

  2. QtSingleApplication.py

    封装的单例工具,它的核心作用是确保同一时间只有一个应用程序实例运行,并支持在多个实例尝试启动时,将消息传递给已经运行的实例,并激活窗口。使用QLocalSocket 作为进程间通信的工具。

python 复制代码
class QtSingleApplication(QApplication):
    messageReceived = Signal(str)

    def __init__(self, id, *argv):

        super(QtSingleApplication, self).__init__(*argv)
        self._id = id
        self._activationWindow = None
        self._activateOnMessage = False

        # Is there another instance running?
        self._outSocket = QLocalSocket()
        self._outSocket.connectToServer(self._id)
        self._isRunning = self._outSocket.waitForConnected()

        if self._isRunning:
            # Yes, there is.
            self._outStream = QTextStream(self._outSocket)
            self._outStream.setCodec('UTF-8')
        else:
            # No, there isn't.
            self._outSocket = None
            self._outStream = None
            self._inSocket = None
            self._inStream = None
            self._server = QLocalServer()
            self._server.listen(self._id)
            self._server.newConnection.connect(self._onNewConnection)

    def isRunning(self):
        return self._isRunning

    def id(self):
        return self._id

    def activationWindow(self):
        return self._activationWindow

    def setActivationWindow(self, activationWindow, activateOnMessage=True):
        self._activationWindow = activationWindow
        self._activateOnMessage = activateOnMessage

    def activateWindow(self):
        if not self._activationWindow:
            return
        self._activationWindow.setWindowState(
            self._activationWindow.windowState() & ~Qt.WindowMinimized)
        self._activationWindow.raise_()
        self._activationWindow.activateWindow()

    def sendMessage(self, msg):
        if not self._outStream:
            return False
        self._outStream << msg << '\n'
        self._outStream.flush()
        return self._outSocket.waitForBytesWritten()

    def _onNewConnection(self):
        if self._inSocket:
            self._inSocket.readyRead.disconnect(self._onReadyRead)
        self._inSocket = self._server.nextPendingConnection()
        if not self._inSocket:
            return
        self._inStream = QTextStream(self._inSocket)
        self._inStream.setCodec('UTF-8')
        self._inSocket.readyRead.connect(self._onReadyRead)
        if self._activateOnMessage:
            self.activateWindow()

    def _onReadyRead(self):
        while True:
            msg = self._inStream.readLine()
            if not msg: break
            self.messageReceived.emit(msg)

使用例子

python 复制代码
def main():
    UUID = 'PHIR-HWOH-MEIZ-AHTA'
    APP = QtSingleApplication(UUID, sys.argv)
    if APP.isRunning():
        sys.exit(0)
    WINDOW = MyApplication()
    WINDOW.APP = APP
    APP.setActivationWindow(WINDOW)
    WINDOW.show()
    sys.exit(APP.exec_())

if __name__ == "__main__":
    main()

init.py

此文件为完整的应用

  • main:为启动函数

  • class HelpForm :帮助界面

  • class AboutForm :关于界面

  • class LicenseForm :版权页面

  • MyApplication:为主应用

下面change_value_p 开头为 调节主屏幕

下面change_value_s 开头为 调节副屏幕

pbr 是主屏亮度,pr,pg,pb 分别代表 RGB分量

看看调节主屏幕代码,

调节色彩分量均是使用 xrandr

相关推荐
lcm_linux1 年前
win10笔记本显示器根据页面显示亮度自动调节亮度的问题
windows·计算机外设·亮度调节