summaryrefslogtreecommitdiff
path: root/window.py
diff options
context:
space:
mode:
authorTim Keller <tjk@tjkeller.xyz>2025-06-24 19:26:15 -0500
committerTim Keller <tjk@tjkeller.xyz>2025-06-24 19:26:15 -0500
commit4be4fd53b3f71d1da55fc7f4c31640bf6f1c4992 (patch)
tree2a930728b4d5d81820211bd7790d9684f0a9f252 /window.py
parentffa5ff333eabffe07394fb21bc413d7d238ee651 (diff)
parent4c3d572eb850c32a45ec9cbaf82688d45c1eebf4 (diff)
downloadimmich-frame-4be4fd53b3f71d1da55fc7f4c31640bf6f1c4992.tar.xz
immich-frame-4be4fd53b3f71d1da55fc7f4c31640bf6f1c4992.zip
merge pixpy repo into this repo
Diffstat (limited to 'window.py')
-rw-r--r--window.py169
1 files changed, 169 insertions, 0 deletions
diff --git a/window.py b/window.py
new file mode 100644
index 0000000..5387930
--- /dev/null
+++ b/window.py
@@ -0,0 +1,169 @@
+from OpenGL.GL import *
+from OpenGL.GLUT import *
+from OpenGL.GLU import *
+from time import time
+from queue import Queue
+
+from renderer import ImageRenderer, TransitionMix
+from manager import PixMan
+
+class PixDisplay:
+ def __init__(self, textures):
+ 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
+
+ @property
+ def max_framerate(self):
+ #return int(1000/int(1000/self.frame_time))
+ return self.frame_time
+
+ @max_framerate.setter
+ def max_framerate(self, max_fps):
+ self._max_fps = max_fps # This is just for the getter since otherwise e.g. int(1000/int(1000/60)) would round to 62
+ self.frame_time = int(1000 / max_fps) # In ms
+
+ 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
+ current_time = time()
+ alive_time = current_time - self.start_time
+ delta_time = current_time - self.last_time
+ self.last_time = current_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)
+ glutSwapBuffers()
+ 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 = glutGet(GLUT_WINDOW_WIDTH), glutGet(GLUT_WINDOW_HEIGHT)
+
+ # 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
+
+ # Limit framerate
+ def timer(self, value):
+ glutPostRedisplay()
+ glutTimerFunc(self.frame_time, self.timer, 0) # Schedule next frame
+
+ def seek(self, increment):
+ self.auto_transition = False
+ self.increment_texture_index(increment)
+ self.image_time = self.image_duration
+
+ def handle_special_key(self, key, x, y):
+ if key == GLUT_KEY_LEFT:
+ self.seek(-1)
+ elif key == GLUT_KEY_RIGHT:
+ self.seek(1)
+
+ def handle_visibility_change(self, state):
+ if state == GLUT_VISIBLE:
+ self._force_redraw = True
+ glutPostRedisplay()
+
+ # Initialization and main loop
+ def main(self, glut_args):
+ # Initialize the window
+ glutInit(glut_args)
+ glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB)
+ glutCreateWindow("Image Viewer with Fade Transition")
+ glEnable(GL_TEXTURE_2D)
+
+ self.renderer = ImageRenderer()
+ self.renderer.set_transition(TransitionMix)
+ self.image_time = 0
+ self.start_time = time()
+ self.last_time = time()
+
+ # Set up the OpenGL viewport and projection
+ 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)
+
+ # Run display
+ glutDisplayFunc(self.display)
+ glutTimerFunc(self.frame_time, self.timer, 0)
+ glutVisibilityFunc(self.handle_visibility_change) # Redraw in case framebuffer gets destroyed when window is obscured
+ glutSpecialFunc(self.handle_special_key)
+ glutMainLoop()
+