mirror of https://git.sr.ht/~michalr/menu
Animated screensaver, command line args for ssaver delay and fullscreen
This commit is contained in:
parent
607057868d
commit
598c882076
|
@ -0,0 +1,16 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
from abc import abstractmethod
|
||||||
|
|
||||||
|
from pygame import Surface
|
||||||
|
from pygame.event import Event
|
||||||
|
|
||||||
|
|
||||||
|
class IBoard:
|
||||||
|
@abstractmethod
|
||||||
|
def draw(self, screen: Surface):
|
||||||
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def handle_event(self, event: Event):
|
||||||
|
raise NotImplementedError()
|
51
menu.py
51
menu.py
|
@ -4,16 +4,18 @@ import math
|
||||||
import argparse
|
import argparse
|
||||||
import json
|
import json
|
||||||
from enum import Enum, auto
|
from enum import Enum, auto
|
||||||
from time import sleep, strftime
|
from time import sleep
|
||||||
from threading import Thread
|
from threading import Thread
|
||||||
from queue import Queue, Empty
|
from queue import Queue, Empty
|
||||||
from abc import abstractmethod
|
|
||||||
from typing import Tuple, Callable, TypedDict, List
|
from typing import Tuple, Callable, TypedDict, List
|
||||||
|
|
||||||
import pygame
|
import pygame
|
||||||
import pygame.freetype
|
import pygame.freetype
|
||||||
import requests
|
import requests
|
||||||
|
|
||||||
|
from iboard import IBoard
|
||||||
|
from screensavers import ClockScreensaver
|
||||||
|
|
||||||
|
|
||||||
class ButtonDef(TypedDict):
|
class ButtonDef(TypedDict):
|
||||||
text: str
|
text: str
|
||||||
|
@ -31,36 +33,6 @@ class Action(TypedDict):
|
||||||
param: str
|
param: str
|
||||||
|
|
||||||
|
|
||||||
class IBoard:
|
|
||||||
@abstractmethod
|
|
||||||
def draw(self, screen: pygame.Surface):
|
|
||||||
raise NotImplementedError()
|
|
||||||
|
|
||||||
@abstractmethod
|
|
||||||
def handle_event(self, event: pygame.event.Event):
|
|
||||||
raise NotImplementedError()
|
|
||||||
|
|
||||||
|
|
||||||
class Screensaver(IBoard):
|
|
||||||
def handle_event(self, _):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class ClockScreensaver(Screensaver):
|
|
||||||
def __init__(self):
|
|
||||||
self.font = pygame.freetype.SysFont(name="Sans", size=20)
|
|
||||||
|
|
||||||
def draw(self, screen: pygame.Surface):
|
|
||||||
text = strftime("%H:%M:%S")
|
|
||||||
screen.fill("black")
|
|
||||||
pygame.Rect(0, 0, screen.get_width(), screen.get_height())
|
|
||||||
text_rect = self.font.get_rect(text)
|
|
||||||
text_pos = pygame.Rect((screen.get_width() - text_rect.width)/2,
|
|
||||||
(screen.get_height() - text_rect.height)/2,
|
|
||||||
text_rect.width, text_rect.height)
|
|
||||||
self.font.render_to(screen, text_pos, text, fgcolor="pink")
|
|
||||||
|
|
||||||
|
|
||||||
class Button:
|
class Button:
|
||||||
PRESS_OFFSET = 2
|
PRESS_OFFSET = 2
|
||||||
|
|
||||||
|
@ -161,12 +133,14 @@ class MenuBoard(IBoard):
|
||||||
|
|
||||||
class App:
|
class App:
|
||||||
FPS = 30
|
FPS = 30
|
||||||
TICKS_UNTIL_SCREENSAVER = 1 * FPS
|
|
||||||
|
|
||||||
def __init__(self, urls: List[Action], bg_color: str):
|
def __init__(self, urls: List[Action], bg_color: str, fullscreen: bool, screensaver_delay: int):
|
||||||
pygame.init()
|
pygame.init()
|
||||||
info = pygame.display.Info()
|
info = pygame.display.Info()
|
||||||
self.screen = pygame.display.set_mode((info.current_w, info.current_h), flags=pygame.FULLSCREEN)
|
flags = 0
|
||||||
|
if fullscreen:
|
||||||
|
flags = pygame.FULLSCREEN
|
||||||
|
self.screen = pygame.display.set_mode((info.current_w, info.current_h), flags=flags)
|
||||||
self.clock = pygame.time.Clock()
|
self.clock = pygame.time.Clock()
|
||||||
self.running = False
|
self.running = False
|
||||||
self.bg_color = bg_color
|
self.bg_color = bg_color
|
||||||
|
@ -175,6 +149,7 @@ class App:
|
||||||
self.board: IBoard = MenuBoard(self.get_screen_rect(), buttons, bg_color)
|
self.board: IBoard = MenuBoard(self.get_screen_rect(), buttons, bg_color)
|
||||||
self.task_q = Queue()
|
self.task_q = Queue()
|
||||||
self.screensaver = ClockScreensaver()
|
self.screensaver = ClockScreensaver()
|
||||||
|
self.TICKS_UNTIL_SCREENSAVER = screensaver_delay * self.FPS
|
||||||
self.screensaver_ticks = self.TICKS_UNTIL_SCREENSAVER
|
self.screensaver_ticks = self.TICKS_UNTIL_SCREENSAVER
|
||||||
|
|
||||||
def get_screen_rect(self) -> pygame.Rect:
|
def get_screen_rect(self) -> pygame.Rect:
|
||||||
|
@ -262,6 +237,9 @@ def get_url_defs(config_data: dict) -> List[Action]:
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
parser = argparse.ArgumentParser()
|
parser = argparse.ArgumentParser()
|
||||||
parser.add_argument("config_path", help="Path to the config file.", type=str)
|
parser.add_argument("config_path", help="Path to the config file.", type=str)
|
||||||
|
parser.add_argument("--no-fullscreen", help="Fullscreen", action='store_true')
|
||||||
|
parser.add_argument("--screensaver-delay", help="Screensaver delay, in seconds. Default=30",
|
||||||
|
type=int, default=30)
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
url_defs: List[Action] = []
|
url_defs: List[Action] = []
|
||||||
|
@ -269,5 +247,6 @@ if __name__ == '__main__':
|
||||||
data = json.load(f)
|
data = json.load(f)
|
||||||
url_defs = get_url_defs(data)
|
url_defs = get_url_defs(data)
|
||||||
|
|
||||||
app = App(url_defs, bg_color=data["bg_color"])
|
app = App(url_defs, bg_color=data["bg_color"], fullscreen=not args.no_fullscreen,
|
||||||
|
screensaver_delay=args.screensaver_delay)
|
||||||
app.loop()
|
app.loop()
|
||||||
|
|
|
@ -0,0 +1,37 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
from time import strftime
|
||||||
|
from typing import Tuple
|
||||||
|
|
||||||
|
import pygame
|
||||||
|
|
||||||
|
from iboard import IBoard
|
||||||
|
|
||||||
|
|
||||||
|
class Screensaver(IBoard):
|
||||||
|
def handle_event(self, _):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class ClockScreensaver(Screensaver):
|
||||||
|
def __init__(self):
|
||||||
|
self.font = pygame.freetype.SysFont(name="Sans", size=40)
|
||||||
|
self.dx = 1
|
||||||
|
self.dy = 1
|
||||||
|
self.text_xy: Tuple[int, int] = (0, 0)
|
||||||
|
|
||||||
|
def draw(self, screen: pygame.Surface):
|
||||||
|
text = strftime("%H:%M:%S")
|
||||||
|
screen.fill("black")
|
||||||
|
pygame.Rect(0, 0, screen.get_width(), screen.get_height())
|
||||||
|
text_rect = self.font.get_rect(text)
|
||||||
|
if ((self.text_xy[0] + self.dx + text_rect.width) > screen.get_width()) or \
|
||||||
|
((self.text_xy[0] + self.dx) < 0):
|
||||||
|
self.dx *= -1
|
||||||
|
if ((self.text_xy[1] + self.dy + text_rect.height) > screen.get_height()) or \
|
||||||
|
((self.text_xy[1] + self.dy) < 0):
|
||||||
|
self.dy *= -1
|
||||||
|
self.text_xy = (self.text_xy[0] + self.dx, self.text_xy[1] + self.dy)
|
||||||
|
text_pos = pygame.Rect(self.text_xy[0], self.text_xy[1],
|
||||||
|
text_rect.width, text_rect.height)
|
||||||
|
self.font.render_to(screen, text_pos, text, fgcolor="pink")
|
Loading…
Reference in New Issue