home · contact · privacy
To sway status bar add audio devices status. master
authorPlom Heller <plom@plomlompom.com>
Thu, 17 Sep 2026 10:23:19 +0000 (12:23 +0200)
committerPlom Heller <plom@plomlompom.com>
Thu, 17 Sep 2026 10:23:19 +0000 (12:23 +0200)
home/user/.config/sway/status.py

index 303a5b382ab7a1f2d8d0d74c747f9b934bf3dd51..1fdee79b32f4e15c01cb758bab3020eb567477d6 100755 (executable)
@@ -1,16 +1,17 @@
 #!/usr/bin/env python3
 'Sway bar status line generator.'
-from json import dumps as json_dumps
+from json import dumps as json_dumps, loads as json_loads
 from datetime import datetime
 from pathlib import Path
 from re import compile as re_compile
 from subprocess import run as subprocess_run
 from time import sleep
+from typing import Any
 
 METADATA = {'version': 1}
 
-PATH_THERMAL = Path('/sys/class/thermal')
-GLOB_THERMAL = 'thermal_zone*/temp'
+AUDIO_DEVS_LABELS = (('sink', 'vol'),
+                     ('source', '--mic'))
 
 PATH_POWER_SUPPLY = Path('/sys/class/power_supply')
 GLOB_BATTERY = 'BAT*'
@@ -20,6 +21,9 @@ BATTERY_STATUS_SYMBOLS = {
         'Not charging': '-',
 }
 
+PATH_THERMAL = Path('/sys/class/thermal')
+GLOB_THERMAL = 'thermal_zone*/temp'
+
 
 def int_at_path(
         path: Path
@@ -30,6 +34,27 @@ def int_at_path(
     return int(stripped_text)
 
 
+def info_audio(
+        ) -> str:
+    "Produce audio devices' volume, muteness."
+    def pactl_json(
+            *args: str
+            ) -> Any:
+        return json_loads(subprocess_run(
+            ('pactl', '-f', 'json', *args),
+            check=True, capture_output=True, text=True
+            ).stdout)
+    defaults = pactl_json('info')
+    texts = []
+    for dev_type, label in AUDIO_DEVS_LABELS:
+        dev = next(dev for dev in pactl_json('list', f'{dev_type}s')
+                   if dev['name'] == defaults[f'default_{dev_type}_name'])
+        items_pc = {item['value_percent'] for item in dev['volume'].values()}
+        assert len(items_pc) == 1
+        texts += [f'{label} {items_pc.pop()}' + 'M' * int(dev['mute'])]
+    return ' '.join(texts)
+
+
 def info_battery(
         ) -> str:
     'Produce battery charge, status, health status bar text.'
@@ -125,6 +150,7 @@ if __name__ == '__main__':
         print(json_dumps([{'full_text': text}
                           for text in info_network() + (info_battery(),
                                                         info_thermal(),
-                                                        info_datetime())]),
+                                                        info_datetime(),
+                                                        info_audio())]),
               end=',\n', flush=True)
         sleep(1)