You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

166 lines
5.1 KiB

# -*- coding: utf-8 -*-
#
# brightness.py
#
# Copyright © 2021 JezerM
#
# This file is part of Web Greeter.
#
# Web Greeter is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# Web Greeter is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# The following additional terms are in effect as per Section 7 of the license:
#
# The preservation of all legal notices and author attributions in
# the material or in the Appropriate Legal Notices displayed
# by works containing it is required.
#
# You should have received a copy of the GNU General Public License
# along with Web Greeter; If not, see <http://www.gnu.org/licenses/>.
import os
import stat
import time
import pyinotify
from typing import List
from threading import Thread
import globals
from logger import logger
from config import web_greeter_config
sys_path = ["/sys/class/backlight/"]
def get_controllers() -> List[str]:
ctrls: List[str] = []
for dev in sys_path:
if os.path.exists(dev) and stat.S_ISDIR(os.stat(dev).st_mode):
drs = os.listdir(dev)
for name in drs:
ctrls.append(os.path.join(dev, name))
return ctrls
class EventHandler(pyinotify.ProcessEvent):
def process_IN_MODIFY(self, event):
if globals.greeter:
globals.greeter.greeter.brightness_update.emit()
# Behavior based on "acpilight"
# Copyright(c) 2016-2019 by wave++ "Yuri D'Elia" <wavexx@thregr.org>
# See https://gitlab.com/wavexx/acpilight
class BrightnessController:
_controllers: List[str] = []
_available: bool = False
_brightness_path: str
_max_brightness_path: str
steps: int
delay: int
_brightness: int
_max_brightness: int = -1
def __init__(self):
self._controllers = get_controllers()
if (len(self._controllers) == 0 or
self._controllers[0] == None or
web_greeter_config["config"]["features"]["backlight"]["enabled"] == False):
self._available = False
return
b_path = self._controllers[0]
self._available = True
self._brightness_path = os.path.join(b_path, "brightness")
self._max_brightness_path = os.path.join(b_path, "max_brightness")
with open(self._max_brightness_path, "r") as f:
self._max_brightness = int(f.read())
steps = web_greeter_config["config"]["features"]["backlight"]["steps"]
self.steps = 1 if steps <= 1 else steps
self.delay = 200
self.watch_brightness()
def _watch(self):
wm = pyinotify.WatchManager()
handler = EventHandler()
wm.add_watch(self._brightness_path, pyinotify.IN_MODIFY)
notifier = pyinotify.Notifier(wm, handler)
notifier.loop()
def watch_brightness(self):
if not self._available:
return
thread = Thread(target = self._watch)
thread.daemon = True
thread.start()
@property
def max_brightness(self) -> int:
return self._max_brightness
@property
def real_brightness(self) -> int:
if not self._available: return -1
try:
with open(self._brightness_path, "r") as f:
return int(f.read())
except OSError:
logger.error("Couldn't read from \"" + self._brightness_path + "\"")
return -1
@real_brightness.setter
def real_brightness(self, v: int):
if not self._available: return
if v > self.max_brightness: v = self.max_brightness
elif v <= 0: v = 0
if not os.path.exists(self._brightness_path): return
try:
with open(self._brightness_path, "w") as f:
f.write(str(round(v)))
except OSError:
logger.error("Couldn't write to \"" + self._brightness_path + "\"")
@property
def brightness(self) -> int:
if not self._available: return -1
return round(self.real_brightness * 100 / self.max_brightness)
@brightness.setter
def brightness(self, v: int):
self.real_brightness = round(v * self.max_brightness / 100)
def _set_brightness(self, value: int):
if not self._available: return
steps = self.steps or 1
sleep = self.delay / steps
current = self.brightness
if steps <= 1:
self.brightness = value
return
for i in range(steps + 1):
time.sleep(sleep / 1000)
brigh = current + ((value - current) * i) / steps
self.brightness = round(brigh)
def set_brightness(self, value: int):
thread = Thread(target = self._set_brightness, args = (value,))
thread.start()
def inc_brightness(self, value: int):
self.set_brightness(self.brightness + value)
def dec_brightness(self, value: int):
self.set_brightness(self.brightness - value)