From b8df4605b42d9a61bb4ae4731efabbdc38166063 Mon Sep 17 00:00:00 2001 From: Tim Keller Date: Mon, 16 Jun 2025 21:50:38 -0500 Subject: add config and add application thread manager --- manager.py | 97 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 97 insertions(+) create mode 100644 manager.py (limited to 'manager.py') diff --git a/manager.py b/manager.py new file mode 100644 index 0000000..a7d8ebd --- /dev/null +++ b/manager.py @@ -0,0 +1,97 @@ +import os +import sys +import signal +from threading import Thread +from OpenGL.GLUT import glutLeaveMainLoop + + +class PixMan: + _instance = None + _initialized = False + + @staticmethod + def handle_sigint(sig, frame): + try: + # Threads are started as daemons so will automatically shut down + glutLeaveMainLoop() + sys.exit(0) + except: + pass + finally: + print("Exiting...") + + def __new__(cls, *args, **kwargs): + if cls._instance is None: + cls._instance = super().__new__(cls) + else: + assert not args and not kwargs, f"Singleton {cls.__name__} cannot be called with arguments more than once" + return cls._instance + + def __init__(self): + pass + + @classmethod + def initialize(cls, configfile, app, socketio, host, port): + assert not cls._initialized, "Already initialized" + if cls._initialized: + return + cls._initialized = True + self = cls() + + self.app = app + self.socketio = socketio + self.immich_connector = None + self.texture_list = None + self.display = None + self.t_flask = None + self.t_idle_download = None + + signal.signal(signal.SIGINT, PixMan.handle_sigint) + + self.configfile = configfile + config = Config.load(self.configfile) if os.path.exists(self.configfile) else Config(file=self.configfile) + + self.init_web(host, port) + self.update_config(config) + + def init_web(self, host, port): + self.t_flask = Thread(target=self.app.run, kwargs={ "host": host, "port": port }) + self.t_flask.start() + + def init_window(self): + # Initialize immich connector + self.immich_connector = ImmichConnector() + if not self.immich_connector.validate_connection(): + self.immich_connector = None + return + + # Initialize texture list + change_callback = lambda d: self.socketio.emit("seek", d) + album_keys = [ "38617851-6b57-44f1-b5f7-82577606afc4" ] + self.texture_list = LazyCachingTextureList(album_keys, max_cache_items=self.config.max_cache_assets, change_callback=change_callback) + + # Begin downloading images + self.t_idle_download = Thread(target=self.immich_connector.idle, daemon=True) + self.t_idle_download.start() + + # Create display + self.display = PixDisplay(self.texture_list) + self.display.main({}) # TODO glut args + + def update_config(self, config): + #old_config = self.config + self.config = config + + # Initialize window if immich parameters are valid + if config.immich_url and config.immich_api_key and not self.display: + self.init_window() + + # If all goes well + config.save(self.configfile) + return True + + +from lazycachelist import LazyCachingTextureList +from window import PixDisplay +from immich import ImmichConnector +from settings import Config -- cgit v1.2.3 From c5465f7ceed37f1ba6575248e1035e1430e78921 Mon Sep 17 00:00:00 2001 From: Tim Keller Date: Mon, 16 Jun 2025 21:58:13 -0500 Subject: config route and fix config saving/creation --- manager.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'manager.py') diff --git a/manager.py b/manager.py index a7d8ebd..b2e101f 100644 --- a/manager.py +++ b/manager.py @@ -49,7 +49,7 @@ class PixMan: signal.signal(signal.SIGINT, PixMan.handle_sigint) self.configfile = configfile - config = Config.load(self.configfile) if os.path.exists(self.configfile) else Config(file=self.configfile) + config = Config.load(self.configfile) if os.path.exists(self.configfile) else Config() self.init_web(host, port) self.update_config(config) -- cgit v1.2.3 From ce64f1a42c9570efa75cc2f568e59d683f499bdd Mon Sep 17 00:00:00 2001 From: Tim Keller Date: Fri, 20 Jun 2025 22:32:28 -0500 Subject: config update and more endpoints for api fromtend --- manager.py | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) (limited to 'manager.py') diff --git a/manager.py b/manager.py index b2e101f..27ebab3 100644 --- a/manager.py +++ b/manager.py @@ -52,7 +52,7 @@ class PixMan: config = Config.load(self.configfile) if os.path.exists(self.configfile) else Config() self.init_web(host, port) - self.update_config(config) + self.replace_config(config) def init_web(self, host, port): self.t_flask = Thread(target=self.app.run, kwargs={ "host": host, "port": port }) @@ -78,16 +78,27 @@ class PixMan: self.display = PixDisplay(self.texture_list) self.display.main({}) # TODO glut args - def update_config(self, config): + def replace_config(self, config): #old_config = self.config self.config = config # Initialize window if immich parameters are valid - if config.immich_url and config.immich_api_key and not self.display: + if self.config.immich_url and self.config.immich_api_key and not self.display: self.init_window() # If all goes well - config.save(self.configfile) + self.config.save(self.configfile) + return True + + def update_config(self, **config): + self.config.update(**config) + + # Initialize window if immich parameters are valid + if self.config.immich_url and self.config.immich_api_key and not self.display: + self.init_window() + + # If all goes well + self.config.save(self.configfile) return True -- cgit v1.2.3 From 0b0c1978c4f7b57a240575de56b8e40d29c3c219 Mon Sep 17 00:00:00 2001 From: Tim Keller Date: Tue, 24 Jun 2025 18:34:07 -0500 Subject: live reload window display config --- manager.py | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) (limited to 'manager.py') diff --git a/manager.py b/manager.py index 27ebab3..8f7ed80 100644 --- a/manager.py +++ b/manager.py @@ -52,7 +52,7 @@ class PixMan: config = Config.load(self.configfile) if os.path.exists(self.configfile) else Config() self.init_web(host, port) - self.replace_config(config) + self.update_config(config, replace=True) def init_web(self, host, port): self.t_flask = Thread(target=self.app.run, kwargs={ "host": host, "port": port }) @@ -78,24 +78,17 @@ class PixMan: self.display = PixDisplay(self.texture_list) self.display.main({}) # TODO glut args - def replace_config(self, config): - #old_config = self.config - self.config = config + def update_config(self, config, replace=False): + if replace: + self.config = config + else: + self.config.update(**config) # Initialize window if immich parameters are valid if self.config.immich_url and self.config.immich_api_key and not self.display: self.init_window() - # If all goes well - self.config.save(self.configfile) - return True - - def update_config(self, **config): - self.config.update(**config) - - # Initialize window if immich parameters are valid - if self.config.immich_url and self.config.immich_api_key and not self.display: - self.init_window() + self.display.update_config() # If all goes well self.config.save(self.configfile) -- cgit v1.2.3 From 2f03f39e24053377dce108e45fde13ccd1e0ae22 Mon Sep 17 00:00:00 2001 From: Tim Keller Date: Tue, 24 Jun 2025 18:56:53 -0500 Subject: window can now handle no selected albums --- manager.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'manager.py') diff --git a/manager.py b/manager.py index 8f7ed80..918a0c4 100644 --- a/manager.py +++ b/manager.py @@ -1,6 +1,7 @@ import os import sys import signal +import copy from threading import Thread from OpenGL.GLUT import glutLeaveMainLoop @@ -49,10 +50,10 @@ class PixMan: signal.signal(signal.SIGINT, PixMan.handle_sigint) self.configfile = configfile - config = Config.load(self.configfile) if os.path.exists(self.configfile) else Config() + self.config = Config.load(self.configfile) if os.path.exists(self.configfile) else Config() self.init_web(host, port) - self.update_config(config, replace=True) + self.update_config(self.config, replace=True) def init_web(self, host, port): self.t_flask = Thread(target=self.app.run, kwargs={ "host": host, "port": port }) @@ -67,7 +68,7 @@ class PixMan: # Initialize texture list change_callback = lambda d: self.socketio.emit("seek", d) - album_keys = [ "38617851-6b57-44f1-b5f7-82577606afc4" ] + album_keys = [ ] self.texture_list = LazyCachingTextureList(album_keys, max_cache_items=self.config.max_cache_assets, change_callback=change_callback) # Begin downloading images @@ -79,6 +80,7 @@ class PixMan: self.display.main({}) # TODO glut args def update_config(self, config, replace=False): + oldconfig = copy.deepcopy(self.config) if replace: self.config = config else: @@ -90,6 +92,10 @@ class PixMan: self.display.update_config() + if oldconfig.album_list != self.config.album_list: + self.texture_list = LazyCachingTextureList(album_keys) + self.display.update_textures() + # If all goes well self.config.save(self.configfile) return True -- cgit v1.2.3 From 4c3d572eb850c32a45ec9cbaf82688d45c1eebf4 Mon Sep 17 00:00:00 2001 From: Tim Keller Date: Tue, 24 Jun 2025 19:16:36 -0500 Subject: add ability to change out albums list during runtime --- manager.py | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) (limited to 'manager.py') diff --git a/manager.py b/manager.py index 918a0c4..af1e4a7 100644 --- a/manager.py +++ b/manager.py @@ -67,9 +67,7 @@ class PixMan: return # Initialize texture list - change_callback = lambda d: self.socketio.emit("seek", d) - album_keys = [ ] - self.texture_list = LazyCachingTextureList(album_keys, max_cache_items=self.config.max_cache_assets, change_callback=change_callback) + self.update_textures() # Begin downloading images self.t_idle_download = Thread(target=self.immich_connector.idle, daemon=True) @@ -79,6 +77,14 @@ class PixMan: self.display = PixDisplay(self.texture_list) self.display.main({}) # TODO glut args + def update_textures(self): + if self.texture_list: + self.texture_list.free() + change_callback = lambda d: self.socketio.emit("seek", d) + self.texture_list = LazyCachingTextureList(self.config.album_list, max_cache_items=self.config.max_cache_assets, change_callback=change_callback) + if self.display: + self.display.update_textures(self.texture_list) + def update_config(self, config, replace=False): oldconfig = copy.deepcopy(self.config) if replace: @@ -93,8 +99,9 @@ class PixMan: self.display.update_config() if oldconfig.album_list != self.config.album_list: - self.texture_list = LazyCachingTextureList(album_keys) - self.display.update_textures() + self.update_textures() + else: + self.texture_list.max_cache_items = self.config.max_cache_assets # If all goes well self.config.save(self.configfile) -- cgit v1.2.3