mirror of
https://github.com/DeeJanuz/frametop.git
synced 2026-10-06 08:00:09 +02:00
Turning gaze mode on without a calibration opened Calibrate only on the off-to-on change, and only if it could open right then. With the headset off, the eye tracker silent, or the panel not built, or with gaze mode already on when the gaze service started, nothing opened and nothing said why: the pointer just stayed a mouse. - The gaze service now checks every second: gaze mode on, no calibration for the tracker in use, eyes seen -> the full calibration opens. One that closes unfinished opens again only after the headset comes off and on, gaze mode off and on, or Calibrate, so it doesn't loop. A start that fails retries every 10 s. - Its status says why gaze mode can't work yet (checks.problem): not calibrated and opening, open, closed unfinished, or can't open and why. - Input Settings shows that under the Gaze pointer switch, along with the gaze service not installed or not running and our tracker missing its frame grabber. - ft-gazectl on notes a missing calibration. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
64 lines
2.2 KiB
Python
Executable File
64 lines
2.2 KiB
Python
Executable File
#!/usr/bin/python3
|
|
"""ft-gazectl: turn the gaze pointer on or off, and ask the gaze service how it's doing.
|
|
|
|
ft-gazectl on|off|toggle gaze mode in the pointer helper (until it restarts; the
|
|
setting is POINTER_GAZE in ~/.config/frametop.conf)
|
|
ft-gazectl status the gaze service (ft-gazed): samples, lessons, the correction
|
|
ft-gazectl forget drop what the pointer's lessons taught (the calibration stays)
|
|
ft-gazectl reload the service reads calibration.json again
|
|
"""
|
|
|
|
import json
|
|
import os
|
|
import socket
|
|
import sys
|
|
|
|
|
|
def ask(name, msg, timeout=1.0):
|
|
s = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM | socket.SOCK_CLOEXEC)
|
|
s.bind(f"\0ft_gazectl.{os.getpid()}")
|
|
s.settimeout(timeout)
|
|
try:
|
|
s.sendto(msg.encode(), "\0" + name)
|
|
return s.recv(4096).decode()
|
|
except ConnectionRefusedError:
|
|
return None
|
|
except socket.timeout:
|
|
return ""
|
|
finally:
|
|
s.close()
|
|
|
|
|
|
def main():
|
|
cmd = sys.argv[1] if len(sys.argv) > 1 else "status"
|
|
if cmd in ("on", "off", "toggle"):
|
|
r = ask("ft_pointer_helper", f"gaze {cmd}")
|
|
if r is None:
|
|
sys.exit("the pointer helper isn't running")
|
|
print(f"gaze mode {r.removeprefix('ok ')}" if r else "no answer (an older pointer helper without gaze mode?)")
|
|
st = ask("ft_gazed", "status", 0.3)
|
|
if st is None:
|
|
print("note: the gaze service (ft-gazed) isn't running, so the pointer has no gaze to follow")
|
|
elif r == "ok on":
|
|
try:
|
|
calibrated = (json.loads(st).get("checks") or {}).get("calibrated")
|
|
except ValueError:
|
|
calibrated = None
|
|
if calibrated is False:
|
|
print("note: no calibration for this eye tracker yet; it opens in the headset "
|
|
"(if it can't, ft-gazectl status says why: checks.problem)")
|
|
elif cmd in ("status", "forget", "reload"):
|
|
r = ask("ft_gazed", cmd)
|
|
if r is None:
|
|
sys.exit("the gaze service (ft-gazed) isn't running")
|
|
try:
|
|
print(json.dumps(json.loads(r), indent=1))
|
|
except ValueError:
|
|
print(r)
|
|
else:
|
|
sys.exit(__doc__)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|