93 lines
2.1 KiB
Python
93 lines
2.1 KiB
Python
#!/usr/bin/env python3
|
|
"""Reads hex-framed display data from stdin, writes PBM, auto-launches feh."""
|
|
|
|
import sys
|
|
import os
|
|
import signal
|
|
import subprocess
|
|
import time
|
|
|
|
WIDTH = 200
|
|
HEIGHT = 200
|
|
BUFSIZE = (WIDTH * HEIGHT) // 8
|
|
OUT = "/tmp/nrfwarch.pbm"
|
|
FRAME_START = "!F!"
|
|
FRAME_END = "!E!"
|
|
|
|
feh_proc = None
|
|
|
|
|
|
def write_pbm(data):
|
|
header = f"P4\n{WIDTH} {HEIGHT}\n".encode()
|
|
inverted = bytes((~b) & 0xFF for b in data)
|
|
tmp = OUT + ".tmp"
|
|
with open(tmp, "wb") as f:
|
|
f.write(header)
|
|
f.write(inverted)
|
|
os.replace(tmp, OUT)
|
|
|
|
|
|
def launch_feh():
|
|
global feh_proc
|
|
if feh_proc is not None and feh_proc.poll() is None:
|
|
return
|
|
try:
|
|
feh_proc = subprocess.Popen(
|
|
[
|
|
"feh",
|
|
"--force-aliasing",
|
|
"--scale",
|
|
"auto",
|
|
"--auto-reload",
|
|
"--title", "nrfwarch sim",
|
|
OUT,
|
|
],
|
|
stdout=subprocess.DEVNULL,
|
|
stderr=subprocess.DEVNULL,
|
|
)
|
|
except FileNotFoundError:
|
|
print("feh not found, writing PBM to " + OUT)
|
|
|
|
|
|
def cleanup(*_):
|
|
global feh_proc
|
|
if feh_proc and feh_proc.poll() is None:
|
|
feh_proc.terminate()
|
|
sys.exit(0)
|
|
|
|
|
|
def main():
|
|
signal.signal(signal.SIGTERM, cleanup)
|
|
signal.signal(signal.SIGINT, cleanup)
|
|
|
|
write_pbm(bytes([0xFF] * BUFSIZE))
|
|
launch_feh()
|
|
|
|
capturing = False
|
|
hex_buf = ""
|
|
frame_count = 0
|
|
|
|
for line in sys.stdin:
|
|
line = line.strip()
|
|
if line == FRAME_START:
|
|
capturing = True
|
|
hex_buf = ""
|
|
elif line == FRAME_END:
|
|
if capturing and hex_buf:
|
|
try:
|
|
data = bytes.fromhex(hex_buf)
|
|
if len(data) == BUFSIZE:
|
|
write_pbm(data)
|
|
frame_count += 1
|
|
print(f" frame {frame_count}", file=sys.stderr)
|
|
except ValueError:
|
|
pass
|
|
capturing = False
|
|
hex_buf = ""
|
|
elif capturing:
|
|
hex_buf += line
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|