From: Plom Heller Date: Thu, 17 Sep 2026 02:41:51 +0000 (+0200) Subject: Add pulseaudio and a tool for setting mute, volume; refactor with backlight script. X-Git-Url: https://plomlompom.com/repos/new_day?a=commitdiff_plain;h=HEAD;p=confplom Add pulseaudio and a tool for setting mute, volume; refactor with backlight script. --- diff --git a/home/user/.local/bin/backlight b/home/user/.local/bin/backlight index 6273512..33b2826 100755 --- a/home/user/.local/bin/backlight +++ b/home/user/.local/bin/backlight @@ -1,33 +1,23 @@ #!/usr/bin/env python3 -'Simple wrapper for manipulating backlight device brightness file(s).' -from argparse import ArgumentError, ArgumentParser +'Wrapper for manipulating backlight device brightness file(s).' from pathlib import Path +from lib.argparsing import ArgParser + +APP_DESC = 'Set backlight strength.' FILENAME_MAX = 'max_brightness' FILENAME_TARGET = 'brightness' PATH_BACKLIGHTS = '/sys/class/backlight' -PERCENTAGE_MIN = 0 -PERCENTAGE_MAX = 100 -APP_DESC = 'Set backlight strength.' +PERCENTAGE_MAX = 100 ARG_NAME = 'strength' ARG_HELP = f'percentage of possible maximum (default: {PERCENTAGE_MAX})' -ARG_ERR_RANGE = f'must be >={PERCENTAGE_MIN}, <={PERCENTAGE_MAX}' if __name__ == '__main__': - parser = ArgumentParser(description=APP_DESC) - arg = parser.add_argument( - ARG_NAME, - metavar=ARG_NAME.upper(), - type=int, - nargs='?', - default=PERCENTAGE_MAX, - help=ARG_HELP - ) - args = parser.parse_args() - target_percentage = getattr(args, ARG_NAME) - if not PERCENTAGE_MIN <= target_percentage <= PERCENTAGE_MAX: - parser.error(str(ArgumentError(arg, ARG_ERR_RANGE))) + parser = ArgParser(APP_DESC) + parser.add_arg_ranged_int(ARG_NAME, PERCENTAGE_MAX, + help=ARG_HELP, default=PERCENTAGE_MAX) + target_percentage = getattr(parser.args, ARG_NAME) for path_backlight in Path(PATH_BACKLIGHTS).iterdir(): path_max = Path(path_backlight).joinpath(FILENAME_MAX) path_target = Path(path_backlight).joinpath(FILENAME_TARGET) diff --git a/home/user/.local/bin/lib/__init__.py b/home/user/.local/bin/lib/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/home/user/.local/bin/lib/argparsing.py b/home/user/.local/bin/lib/argparsing.py new file mode 100644 index 0000000..f1bb54c --- /dev/null +++ b/home/user/.local/bin/lib/argparsing.py @@ -0,0 +1,60 @@ +'Some conveniences around argument parsing.' +from argparse import Action, ArgumentParser, ArgumentError, Namespace +from typing import Optional + +_INT_MIN = 0 + + +class ArgParser: + 'Wrapper around argparse.ArgumentParser.' + _args: Optional[Namespace] = None + + def __init__( + self, + app_desc: str + ) -> None: + self._parser = ArgumentParser(description=app_desc) + + def add_arg( + self, + arg_name, + *args, + **kwargs + ) -> Action: + 'Public access to ._parser.add_argument().' + return self._parser.add_argument(arg_name, *args, **kwargs) + + @property + def args( + self + ) -> Namespace: + 'Result of ._parser.parse_args(), running same if not done yet.' + if self._args is None: + self._args = self._parser.parse_args() + return self._args + + def add_arg_ranged_int( + self, + arg_name: str, + int_max: int, + **kwargs + ) -> None: + 'Add argument for int ranged >= _INT_MIN, <= int_max.' + def int_ranged( + arg: str + ) -> int: + err = ArgumentError( + action, + f'must be int >={_INT_MIN}, <={int_max}') + try: + arg_int = int(arg) + except ValueError as exc: + raise err from exc + if not _INT_MIN <= arg_int <= int_max: + raise err + return arg_int + action = self.add_arg(arg_name, + metavar=arg_name.upper(), + type=int_ranged, + nargs='?', + **kwargs) diff --git a/home/user/.local/bin/vol b/home/user/.local/bin/vol new file mode 100755 index 0000000..a1f70b3 --- /dev/null +++ b/home/user/.local/bin/vol @@ -0,0 +1,51 @@ +#!/usr/bin/env python3 +'Wrapper for manipulating audio device muteness and volume.' +from subprocess import CompletedProcess, run as subprocess_run +from lib.argparsing import ArgParser + +APP_DESC = 'Set audio device volume, muteness.' + +VOL_AT_100 = 65536 +DEVICES = (('sink', 'speaker', '@DEFAULT_SINK@'), + ('source', 'microphone', '@DEFAULT_SOURCE@')) + +PERCENTAGE_MAX = 150 +ARG_NAME = 'volume' +ARG_HELP = 'percentage of possible maximum; if omitted: toggle muteness' + +if __name__ == '__main__': + parser = ArgParser(APP_DESC) + parser.add_arg_ranged_int(ARG_NAME, PERCENTAGE_MAX, help=ARG_HELP) + parser.add_arg('--mic', + action='store_true', + help='manipulate microphone rather than speaker') + dev_type, dev_name, dev_target = DEVICES[int(parser.args.mic)] + target_percentage = getattr(parser.args, ARG_NAME) + + def pactl( + verb: str, + target: str, + bonus_arg='', + **run_kwargs + ) -> CompletedProcess: + 'Run pactl command via subprocess_run.' + return subprocess_run( + ['pactl', f'{verb}-{dev_type}-{target}', dev_target + ] + ([bonus_arg] if bonus_arg else []), + check=True, + **run_kwargs) + + toks = pactl('get', 'mute', capture_output=True, text=True + ).stdout.strip().split() + assert (len(toks) == 2 + and toks[0] == 'Mute:' + and toks[1] in {'yes', 'no'}), toks + was_mute = toks[1] == 'yes' + if target_percentage is None: + pactl('set', 'mute', str(int(not was_mute))) + print(f'{dev_name} muteness toggled {"off" if was_mute else "on"}.') + else: + target_abs = int((target_percentage / 100) * VOL_AT_100) + pactl('set', 'volume', str(target_abs)) + print(f'{dev_name} volume set to {target_percentage}% ({target_abs})' + + (' (muted)' if was_mute else '')) diff --git a/to_install/t490s b/to_install/t490s index cff3404..e13553d 100644 --- a/to_install/t490s +++ b/to_install/t490s @@ -21,4 +21,6 @@ vim-gtk3 sway wmenu xwayland +# multimedia +pulseaudio # last line ignored