diff options
Diffstat (limited to 'brightness')
-rw-r--r-- | brightness/__init__.py | 85 |
1 files changed, 85 insertions, 0 deletions
diff --git a/brightness/__init__.py b/brightness/__init__.py new file mode 100644 index 0000000..c5b497f --- /dev/null +++ b/brightness/__init__.py @@ -0,0 +1,85 @@ +# Copyright (C) 2023 Tomasz Kramkowski <tomasz@kramkow.ski> +# SPDX-License-Identifier: MIT + +import argparse +import math +import sys +from pathlib import Path +from typing import Type, TypeVar + +T = TypeVar("T", bound="LogFloat") + + +class LogFloat(float): + @classmethod + def from_val(cls: Type[T], val: int) -> T: + return cls(math.log(val + 1)) + + @classmethod + def from_pct(cls: Type[T], pct: float, log_max: "LogFloat") -> T: + return cls(pct / 100.0 * log_max) + + def to_val(self) -> int: + return round(math.e**self) - 1 + + def __add__(self, other: "LogFloat") -> "LogFloat": + return LogFloat(super().__add__(other)) + + +def _parse_limit(limit: str, log_max_brightness: LogFloat) -> int: + if limit[-1] == "%": + return LogFloat.from_pct(float(limit[:-1]), log_max_brightness).to_val() + return int(limit) + + +def main(argv: list[str] = sys.argv) -> int: + ap = argparse.ArgumentParser(description="Adjust sysfs backlight with a log scale") + ap.add_argument( + "-m", + "--min", + help="An artificial minimum brightness (percentage or raw value) limit", + default="0", + ) + ap.add_argument( + "-M", + "--max", + help="An artificial maximum brightness (percentage or raw value) limit", + ) + ap.add_argument( + "backlight", + help="Path to sysfs backlight (e.g. /sys/class/backlight/amdgpu_bl0)", + ) + ap.add_argument( + "adjustment", + help="Percentage adjustment (e.g. +10 or -6.25) or absolute value (e.g. 50)", + ) + args = ap.parse_args(argv[1:]) + + backlight = Path(args.backlight) + + with open(backlight / "brightness") as f: + brightness = int(f.read().rstrip()) + log_brightness = LogFloat.from_val(brightness) + + with open(backlight / "max_brightness") as f: + max_brightness = int(f.read().rstrip()) + log_max_brightness = LogFloat.from_val(max_brightness) + + if args.adjustment[0] in {"-", "+"}: + diff = LogFloat.from_pct(float(args.adjustment), log_max_brightness) + new_brightness = (log_brightness + diff).to_val() + if diff != 0 and new_brightness == brightness: + new_brightness += int(math.copysign(1, diff)) + else: + new_brightness = LogFloat.from_pct( + float(args.adjustment), log_max_brightness + ).to_val() + + max_limit = max_brightness + if args.max is not None: + max_limit = _parse_limit(args.max, log_max_brightness) + min_limit = _parse_limit(args.min, log_max_brightness) + new_brightness = max(min_limit, min(new_brightness, max_limit)) + with open(backlight / "brightness", "w") as f: + f.write(str(new_brightness)) + return 0 |