diff options
| author | Tim Keller <tjk@tjkeller.xyz> | 2025-12-09 22:16:48 -0600 |
|---|---|---|
| committer | Tim Keller <tjk@tjkeller.xyz> | 2025-12-09 22:16:57 -0600 |
| commit | 3e7fdfb6c8a50c59ac933f701526ad1815dded92 (patch) | |
| tree | d2c699ff93e23d0fe45845a4c2dc05d820ec317b /src/server/window.py | |
| parent | 39738b84e9164b0f2d01f22440548c4393160013 (diff) | |
| download | immich-frame-3e7fdfb6c8a50c59ac933f701526ad1815dded92.tar.xz immich-frame-3e7fdfb6c8a50c59ac933f701526ad1815dded92.zip | |
refactor codebase. Reorganize file structure. Replace webpack for vite. Setup setuptools for application. Move closer to distributable appv0.3.0
Diffstat (limited to 'src/server/window.py')
| -rw-r--r-- | src/server/window.py | 154 |
1 files changed, 154 insertions, 0 deletions
diff --git a/src/server/window.py b/src/server/window.py new file mode 100644 index 0000000..4597c54 --- /dev/null +++ b/src/server/window.py @@ -0,0 +1,154 @@ +import pygame +from pygame.locals import * +from OpenGL.GL import * +from queue import Queue + +from .renderer import ImageRenderer, TransitionMix +from .manager import PixMan + +class PixDisplay: + def __init__(self, textures): + self.screen = None + self.last_time = 0 + self.start_time = 0 + self.image_time = 0 + self.paused = False + self.textures = textures + self.current_texture_index = 0 + self.renderer = None + self.win_w = 0 + self.win_h = 0 + + self.transition_reverse = False + self.text_prev = None + self.tex = None + + self._force_redraw = False + self.queue = Queue() + + self.update_config() + + def update_config(self): + config = PixMan().config + self.max_framerate = config.max_framerate + self.image_duration = config.image_duration + self.transition_duration = config.transition_duration + self.auto_transition = config.auto_transition + + def update_textures(self, textures): + self.textures = textures + self.current_texture_index = 0 + + def increment_texture_index(self, increment): + self.transition_reverse = increment < 0 + + self.tex_prev = self.textures[self.current_texture_index] + self.current_texture_index = (self.current_texture_index + increment) % len(self.textures) + self.tex = self.textures[self.current_texture_index] + + if not self.tex.initialized or not self.tex_prev.initialized: + return + + # Ensure textures are initialized for opengl + self.tex_prev.gl_init() + self.tex.gl_init() + + # Main display function + def display(self): + # Calculate timings + alive_time = pygame.time.get_ticks() / 1000 + delta_time = alive_time - self.last_time + self.last_time = alive_time + + if not self.tex or not self.tex.initialized or not self.tex.id: + if self.textures.asset_count > 0: + self.increment_texture_index(0) + # Draw black window if no textures are available + if not self.tex or not self.tex.id: + glClearColor(0.0, 0.0, 0.0, 1.0) + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) + pygame.display.flip() + return + + # Run queue events + while not self.queue.empty(): + f = self.queue.get() # Get the task and its data + f() + + # Progress image time + if not self.paused: + self.image_time += delta_time + + # Get window size + old_win_w, old_win_h = self.win_w, self.win_h + self.win_w, self.win_h = self.screen.get_size() + + # Draw static image except during a transition + if self.image_time < self.image_duration: + # Avoid unforced-redraw unless window size has changed + if self._force_redraw or self.win_w != old_win_w or self.win_h != old_win_h: + self.renderer.draw_static(self.tex, self.win_w, self.win_h, 1.0) + self._force_redraw = False + return + + # Start drawing transition once image_time >= image_duration + if self.auto_transition: + self.increment_texture_index(1) + self.auto_transition = False + + transition_time = self.image_time - self.image_duration + + self.renderer.draw_transition(self.tex_prev, self.tex, self.win_w, self.win_h, delta_time, transition_time, self.transition_duration, self.transition_reverse) + + if transition_time >= self.transition_duration: + self.image_time = 0 + self.auto_transition = True + + def seek(self, increment): + self.auto_transition = False + self.increment_texture_index(increment) + self.image_time = self.image_duration + + # Initialization and main loop + def main(self, fullscreen=False): + # Initialize the window + pygame.init() + self.screen = pygame.display.set_mode((0, 0), DOUBLEBUF | OPENGL | (FULLSCREEN if fullscreen else 0)) + pygame.mouse.set_visible(False) + + # Set up the OpenGL viewport and projection + glEnable(GL_TEXTURE_2D) + glMatrixMode(GL_PROJECTION) + glLoadIdentity() + glOrtho(-1, 1, -1, 1, -1, 1) + glMatrixMode(GL_MODELVIEW) + + # Enable alpha blending + glEnable(GL_BLEND) + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) + + # Setup renderer and slide timing + self.renderer = ImageRenderer() + self.renderer.set_transition(TransitionMix) + self.image_time = 0 + self.last_time = 0 + + # Run display + clock = pygame.time.Clock() + while True: + for event in pygame.event.get(): + if event.type == QUIT: + pygame.quit() + return + elif event.type == KEYDOWN: + # Quit with escape or ctrl+q + if event.key == pygame.K_ESCAPE or event.key == pygame.K_q and event.mod & pygame.KMOD_CTRL: + pygame.quit() + return + # Seek with left/right arrow + elif event.key == pygame.K_LEFT: + self.seek(-1) + elif event.key == pygame.K_RIGHT: + self.seek(+1) + self.display() + clock.tick(self.max_framerate) |
