Browse Source

add systray version

Thomas B 1 month ago
parent
commit
4503840c48
5 changed files with 161 additions and 5 deletions
  1. 15
    1
      README.md
  2. 17
    0
      client/AutoBrightness.desktop
  3. 16
    0
      client/autobrightness.service
  4. 29
    4
      client/brightness.py
  5. 84
    0
      client/tray.py

+ 15
- 1
README.md View File

@@ -35,9 +35,23 @@ Uses [KWin scripting](https://develop.kde.org/docs/plasma/kwin/) to get the acti
35 35
 This is used to pause adjustments while a fullscreen window is focused (eg. while gaming).
36 36
 Also sends status updates to a local InfluxDB.
37 37
 
38
+Run the command-line version with systemd automatically (modify paths in the commands and file accordingly):
39
+
40
+    mkdir -p ~/.config/systemd/user
41
+    ln -s /home/thomas/Projekte/AutoBrightness/client/autobrightness.service ~/.config/systemd/user
42
+    systemctl --user daemon-reload
43
+    systemctl --user enable --now autobrightness
44
+
45
+Or alternatively modify the paths in the `AutoBrightness.desktop` file and copy it to `~/.local/share/applications` for a graphical version that you can easily auto-start on boot in eg. the KDE settings menu.
46
+
38 47
 ### Quick Start
39 48
 
40
-Install dependency and run the client.
49
+Install dependencies and run the systray client:
50
+
51
+    yay -S python-pyusb python-pystray python-pillow python-cairosvg
52
+    ./client/tray.py
53
+
54
+Or for just the command-line version:
41 55
 
42 56
     yay -S python-pyusb
43 57
     ./client/brightness.py

+ 17
- 0
client/AutoBrightness.desktop View File

@@ -0,0 +1,17 @@
1
+[Desktop Entry]
2
+Comment[en_US]=
3
+Comment=
4
+Exec=/home/thomas/Projekte/AutoBrightness/client/tray.py
5
+GenericName[en_US]=
6
+GenericName=
7
+Icon=brightness-high
8
+MimeType=
9
+Name[en_US]=AutoBrightness
10
+Name=AutoBrightness
11
+Path=/home/thomas/Projekte/AutoBrightness/client/
12
+StartupNotify=true
13
+Terminal=false
14
+TerminalOptions=
15
+Type=Application
16
+X-KDE-SubstituteUID=false
17
+X-KDE-Username=

+ 16
- 0
client/autobrightness.service View File

@@ -0,0 +1,16 @@
1
+[Unit]
2
+Description=Auto DDC/CI display brightness
3
+
4
+[Service]
5
+Type=exec
6
+WorkingDirectory=/home/thomas/Projekte/AutoBrightness
7
+ExecStart=/home/thomas/Projekte/AutoBrightness/client/brightness.py
8
+StandardOutput=journal
9
+StandardError=journal
10
+SyslogIdentifier=fritzinfluxdb
11
+RemainAfterExit=no
12
+Restart=always
13
+RestartSec=5s
14
+
15
+[Install]
16
+WantedBy=default.target

+ 29
- 4
client/brightness.py View File

@@ -2,10 +2,13 @@
2 2
 
3 3
 import lux
4 4
 import ddc
5
-import time
6 5
 import influx
7 6
 import window
8 7
 
8
+import time
9
+import sys
10
+import select
11
+
9 12
 filter_fact = 0.90
10 13
 
11 14
 c_in = 0.6, -30.0, # in_a, in_b
@@ -19,6 +22,10 @@ calibration = {
19 22
     ],
20 23
 }
21 24
 
25
+running = True
26
+is_active = True
27
+last_brightness = 0
28
+
22 29
 def cal(v, c):
23 30
     # out = out_b + out_a * in_a * max(0, in_b + in)
24 31
     return c[1] + c[0] * c_in[0] * max(0, c_in[1] + v)
@@ -34,14 +41,20 @@ def lux_to_disp(name, val):
34 41
     val = int(val)
35 42
     return min(max(val, 0), 100)
36 43
 
37
-if __name__ == "__main__":
44
+def main():
45
+    global running, is_active, last_brightness
46
+
47
+    print("usb init")
38 48
     usb = lux.usb_init()
49
+    print("check usb connection")
39 50
     lux.check_connection(usb)
40 51
 
52
+    print("detect displays")
41 53
     disps = ddc.ddc_detect()
42 54
     if len(disps) <= 0:
43 55
         raise ValueError("no displays found")
44 56
 
57
+    print("query displays")
45 58
     for d in disps:
46 59
         # select i2c bus if available, id otherwise
47 60
         if "bus" in d:
@@ -62,16 +75,25 @@ if __name__ == "__main__":
62 75
     print()
63 76
 
64 77
     time_brightness = time.time()
65
-    time_displays = time.time()
78
+    time_displays = time.time() - 8.0
66 79
     time_window = time.time()
67 80
 
68 81
     is_active = True
69 82
 
70
-    while True:
83
+    while running:
71 84
         # read brightness at approx. 1Hz with low-pass filtering
72 85
         time.sleep(1.0)
73 86
         brightness = filter_lux(brightness, lux.read_brightness(usb))
74 87
 
88
+        if select.select([sys.stdin, ], [], [], 0.0)[0]:
89
+            line = sys.stdin.readline()
90
+            print("Resetting displays")
91
+            for d in disps:
92
+                try:
93
+                    ddc.ddc_set(d["_id"], d["prev"])
94
+                except Exception as e:
95
+                    print(e)
96
+
75 97
         # print brightness changes at most every 5s
76 98
         if (time.time() - time_brightness) > 5.0:
77 99
             time_brightness = time.time()
@@ -122,3 +144,6 @@ if __name__ == "__main__":
122 144
 
123 145
                         # set to zero to show display is disconnected
124 146
                         d["prev"] = -1
147
+
148
+if __name__ == "__main__":
149
+    main()

+ 84
- 0
client/tray.py View File

@@ -0,0 +1,84 @@
1
+#!/usr/bin/env python
2
+
3
+import brightness
4
+import threading
5
+import time
6
+
7
+import pystray
8
+from io import BytesIO
9
+import cairosvg
10
+from PIL import Image
11
+
12
+#icon_path = "/usr/share/icons/breeze-dark/devices/22/video-display-brightness.svg"
13
+#icon_path = "/usr/share/icons/breeze-dark/devices/32/video-display-brightness-symbolic.svg"
14
+#icon_path = "/usr/share/icons/breeze-dark/status/32/input-keyboard-brightness.svg"
15
+icon_path = "/usr/share/icons/breeze-dark/actions/24/brightness-high.svg"
16
+
17
+def is_running():
18
+    #print("check1")
19
+    return "Active" if brightness.is_active else "Inactive"
20
+
21
+def get_value():
22
+    #print("check2")
23
+    return f"Brightness: {brightness.last_brightness}"
24
+
25
+def quit(icon):
26
+    print("stop brightness")
27
+    brightness.running = False
28
+
29
+    print("stop tray")
30
+    icon.stop()
31
+
32
+def poll(icon):
33
+    while brightness.running:
34
+        #print("update")
35
+        icon.update_menu()
36
+        time.sleep(5.0)
37
+
38
+def main():
39
+    out = BytesIO()
40
+    cairosvg.svg2png(url=icon_path, write_to=out)
41
+    image = Image.open(out)
42
+
43
+    print("start brightness")
44
+    t_b = threading.Thread(target=brightness.main)
45
+    t_b.start()
46
+
47
+    print("prepare tray")
48
+    icon = pystray.Icon("AutoBrightness", image, "AutoBrightness",
49
+        menu=pystray.Menu(
50
+            pystray.MenuItem(
51
+                'Activated',
52
+                None,
53
+                enabled=False,
54
+                checked=lambda icon=pystray.Icon: is_running(),
55
+            ),
56
+
57
+            pystray.MenuItem(
58
+                lambda icon=pystray.Icon: get_value(),
59
+                None,
60
+                enabled=False,
61
+            ),
62
+
63
+            pystray.MenuItem(
64
+                "Quit",
65
+                lambda icon=pystray.Icon: quit(icon),
66
+            ),
67
+        )
68
+    )
69
+
70
+    print("start polling")
71
+    t_p = threading.Thread(target=poll, args=(icon,))
72
+    t_p.start()
73
+
74
+    print("start tray")
75
+    icon.run()
76
+
77
+    print("join brightness")
78
+    t_b.join()
79
+    t_p.join()
80
+
81
+    print("done")
82
+
83
+if __name__ == "__main__":
84
+    main()

Loading…
Cancel
Save