cunt
This commit is contained in:
54
display.py
54
display.py
@@ -2,21 +2,10 @@
|
|||||||
"""
|
"""
|
||||||
JARVIS Display
|
JARVIS Display
|
||||||
──────────────
|
──────────────
|
||||||
Renders the JARVIS UI overlay. Works in two modes:
|
Renders the JARVIS UI overlay via X11.
|
||||||
|
|
||||||
X11 (development laptop):
|
Development: python display.py
|
||||||
python display.py
|
Kiosk: DISPLAY=:0 python display.py --fullscreen
|
||||||
|
|
||||||
Linux framebuffer (device – no windowing system):
|
|
||||||
python display.py --framebuffer
|
|
||||||
# or
|
|
||||||
JARVIS_FB=1 python display.py
|
|
||||||
|
|
||||||
Framebuffer prerequisites on Debian (device):
|
|
||||||
sudo apt install python3-pygame
|
|
||||||
sudo usermod -aG video $USER # then log out/in
|
|
||||||
# If fbdev fails (common on newer kernels) try KMS/DRM:
|
|
||||||
SDL_VIDEODRIVER=kmsdrm python display.py --framebuffer
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import os
|
import os
|
||||||
@@ -24,34 +13,17 @@ import math
|
|||||||
import argparse
|
import argparse
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
# ── CLI / env-var flags ─────────────────────────────────────────────────────
|
|
||||||
# These must be parsed BEFORE pygame is imported so we can set SDL env vars
|
|
||||||
# in time for pygame.init() to pick them up.
|
|
||||||
|
|
||||||
_parser = argparse.ArgumentParser(description='JARVIS display', add_help=True)
|
_parser = argparse.ArgumentParser(description='JARVIS display', add_help=True)
|
||||||
_parser.add_argument(
|
|
||||||
'--framebuffer', '-fb', action='store_true',
|
|
||||||
help='Render to Linux framebuffer instead of an X11/Wayland window')
|
|
||||||
_parser.add_argument(
|
_parser.add_argument(
|
||||||
'--fullscreen', '-fs', action='store_true',
|
'--fullscreen', '-fs', action='store_true',
|
||||||
help='Run fullscreen under X11/Wayland')
|
help='Run fullscreen under X11/Wayland')
|
||||||
_parser.add_argument('--width', type=int, default=1280,
|
_parser.add_argument('--width', type=int, default=1280,
|
||||||
help='Screen / framebuffer width (default 1280)')
|
help='Screen width (default 1280)')
|
||||||
_parser.add_argument('--height', type=int, default=800,
|
_parser.add_argument('--height', type=int, default=800,
|
||||||
help='Screen / framebuffer height (default 800)')
|
help='Screen height (default 800)')
|
||||||
_args, _ = _parser.parse_known_args()
|
_args, _ = _parser.parse_known_args()
|
||||||
|
|
||||||
USE_FB: bool = _args.framebuffer or bool(os.environ.get('JARVIS_FB'))
|
import pygame
|
||||||
|
|
||||||
if USE_FB:
|
|
||||||
# SDL2 env vars must be set before pygame.display.init()
|
|
||||||
os.environ.setdefault('SDL_VIDEODRIVER', 'kmsdrm')
|
|
||||||
os.environ.setdefault('SDL_RENDER_DRIVER', 'software')
|
|
||||||
os.environ.setdefault('SDL_FBDEV', os.environ.get('JARVIS_FBDEV', '/dev/fb0'))
|
|
||||||
# Prevent SDL trying to open a mouse device on the framebuffer
|
|
||||||
os.environ.setdefault('SDL_NOMOUSE', '1')
|
|
||||||
|
|
||||||
import pygame # noqa: E402 — import after env setup
|
|
||||||
|
|
||||||
# ── Colour palette ───────────────────────────────────────────────────────────
|
# ── Colour palette ───────────────────────────────────────────────────────────
|
||||||
BLACK = ( 0, 0, 0)
|
BLACK = ( 0, 0, 0)
|
||||||
@@ -210,7 +182,7 @@ def main() -> None:
|
|||||||
|
|
||||||
W, H = _args.width, _args.height
|
W, H = _args.width, _args.height
|
||||||
|
|
||||||
if USE_FB or _args.fullscreen:
|
if _args.fullscreen:
|
||||||
screen = pygame.display.set_mode((W, H), pygame.FULLSCREEN | pygame.NOFRAME)
|
screen = pygame.display.set_mode((W, H), pygame.FULLSCREEN | pygame.NOFRAME)
|
||||||
else:
|
else:
|
||||||
screen = pygame.display.set_mode((W, H))
|
screen = pygame.display.set_mode((W, H))
|
||||||
@@ -219,13 +191,13 @@ def main() -> None:
|
|||||||
pygame.mouse.set_visible(False)
|
pygame.mouse.set_visible(False)
|
||||||
|
|
||||||
fonts = {
|
fonts = {
|
||||||
'large': _load_font(56),
|
'large': _load_font(38),
|
||||||
'small': _load_font(18),
|
'small': _load_font(13),
|
||||||
}
|
}
|
||||||
|
|
||||||
# Layout anchors — all relative to screen size so they adapt to resolution
|
# Layout anchors — all relative to screen size so they adapt to resolution
|
||||||
face_rx = int(min(W, H) * 0.115) # half-width at cheek level
|
face_rx = int(min(W, H) * 0.085) # half-width at cheek level
|
||||||
face_ry = int(min(W, H) * 0.135) # half-height crown→chin
|
face_ry = int(min(W, H) * 0.100) # half-height crown→chin
|
||||||
face_cx = W // 2
|
face_cx = W // 2
|
||||||
face_cy = int(face_ry * 1.2) + 8 # nearly touches the top edge
|
face_cy = int(face_ry * 1.2) + 8 # nearly touches the top edge
|
||||||
status_y = int(H * 0.82)
|
status_y = int(H * 0.82)
|
||||||
@@ -261,10 +233,6 @@ def main() -> None:
|
|||||||
if event.key in (pygame.K_ESCAPE, pygame.K_q):
|
if event.key in (pygame.K_ESCAPE, pygame.K_q):
|
||||||
pygame.quit()
|
pygame.quit()
|
||||||
return
|
return
|
||||||
# Touch / mouse tap anywhere also quits in kiosk mode
|
|
||||||
if USE_FB and event.type == pygame.MOUSEBUTTONDOWN:
|
|
||||||
pygame.quit()
|
|
||||||
return
|
|
||||||
|
|
||||||
screen.fill(BLACK)
|
screen.fill(BLACK)
|
||||||
if face_img:
|
if face_img:
|
||||||
|
|||||||
Reference in New Issue
Block a user