Ambilight per Plasma 6: demone Adalight + plasmoide con slider
- backend/ambicapture.py: cattura Wayland via ScreenCast portal + PipeWire - backend/ambilightd.py: demone, 47 zone sul bordo superiore, luminosita/contrasto/ saturazione/banda, invio Adalight su seriale, servizio D-Bus org.enne2.Ambilight - backend/ambilight-ctl: CLI JSON per il plasmoide - backend/ambilight.service: avvio automatico (systemd --user) - package/org.enne2.ambilight: applet vassoio con popup e slider - install.sh / uninstall.sh senza root
This commit is contained in:
Executable
+99
@@ -0,0 +1,99 @@
|
||||
#!/usr/bin/env python3
|
||||
"""ambilight-ctl — interfaccia a riga di comando per il demone ambilightd.
|
||||
|
||||
Parla con il demone via D-Bus e stampa JSON, cosi' il plasmoide puo' usarla
|
||||
attraverso il DataSource "executable" di Plasma.
|
||||
|
||||
ambilight-ctl state # JSON con tutto lo stato
|
||||
ambilight-ctl start | stop | toggle
|
||||
ambilight-ctl set brightness 0.8 # brightness|contrast|saturation|band|reverse|leds
|
||||
ambilight-ctl get contrast
|
||||
"""
|
||||
import json
|
||||
import sys
|
||||
|
||||
BUS_NAME = "org.enne2.Ambilight"
|
||||
OBJ_PATH = "/org/enne2/Ambilight"
|
||||
IFACE = "org.enne2.Ambilight"
|
||||
|
||||
FALLBACK = {"daemon": False, "running": False, "brightness": 1.0, "contrast": 1.0,
|
||||
"saturation": 1.0, "band": 0.12, "reverse": True, "leds": 47, "fps": 0.0,
|
||||
"error": "demone non raggiungibile"}
|
||||
|
||||
|
||||
def proxy():
|
||||
from gi.repository import Gio, GLib
|
||||
return Gio.DBusProxy.new_for_bus_sync(
|
||||
Gio.BusType.SESSION, Gio.DBusProxyFlags.NONE, None,
|
||||
BUS_NAME, OBJ_PATH, IFACE, None)
|
||||
|
||||
|
||||
def call(method, args=None):
|
||||
from gi.repository import Gio
|
||||
return proxy().call_sync(method, args, Gio.DBusCallFlags.NONE, 1500, None)
|
||||
|
||||
|
||||
def state():
|
||||
try:
|
||||
res = call("GetState")
|
||||
data = json.loads(res.unpack()[0] if isinstance(res.unpack(), tuple) else res.unpack())
|
||||
data["daemon"] = True
|
||||
return data
|
||||
except Exception as e:
|
||||
d = dict(FALLBACK)
|
||||
d["error"] = f"{type(e).__name__}: {e}".strip()
|
||||
return d
|
||||
|
||||
|
||||
def main(argv):
|
||||
cmd = argv[1] if len(argv) > 1 else "state"
|
||||
|
||||
if cmd == "state":
|
||||
d = state()
|
||||
print(json.dumps(d))
|
||||
return 0 if d.get("daemon") else 1
|
||||
|
||||
if cmd in ("start", "stop", "toggle"):
|
||||
try:
|
||||
call({"start": "Start", "stop": "Stop", "toggle": "Toggle"}[cmd])
|
||||
except Exception as e:
|
||||
print(json.dumps({"ok": False, "error": str(e)}))
|
||||
return 1
|
||||
print(json.dumps({"ok": True, "state": state()}))
|
||||
return 0
|
||||
|
||||
if cmd == "set" and len(argv) >= 4:
|
||||
key, raw = argv[2], argv[3]
|
||||
if key in ("reverse",):
|
||||
value = raw.lower() in ("1", "true", "yes", "on")
|
||||
elif key == "leds":
|
||||
value = int(raw)
|
||||
else:
|
||||
value = float(raw)
|
||||
try:
|
||||
from gi.repository import GLib
|
||||
res = call("SetParam", GLib.Variant("(sv)", (key, GLib.Variant(
|
||||
"b" if isinstance(value, bool) else "d" if isinstance(value, float) else "i",
|
||||
value))))
|
||||
err = res.unpack()[0]
|
||||
if err:
|
||||
print(json.dumps({"ok": False, "error": err}))
|
||||
return 1
|
||||
except Exception as e:
|
||||
print(json.dumps({"ok": False, "error": str(e)}))
|
||||
return 1
|
||||
print(json.dumps({"ok": True, "state": state()}))
|
||||
return 0
|
||||
|
||||
if cmd == "get" and len(argv) >= 3:
|
||||
d = state()
|
||||
key = argv[2]
|
||||
print(d.get(key, ""))
|
||||
return 0 if d.get("daemon") else 1
|
||||
|
||||
print(__doc__)
|
||||
return 2
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main(sys.argv))
|
||||
Reference in New Issue
Block a user