diff --git a/photobooth/Photobooth.py b/photobooth/Photobooth.py index 6faa5e3..df657d8 100644 --- a/photobooth/Photobooth.py +++ b/photobooth/Photobooth.py @@ -24,7 +24,7 @@ class Photobooth: self._conn = conn - self.initCamera(config, camera) + self.initCamera(config, camera()) self.initGpio(config) self.triggerOff() diff --git a/photobooth/gui/PyQt5Gui.py b/photobooth/gui/PyQt5Gui.py index 347d6be..e744937 100644 --- a/photobooth/gui/PyQt5Gui.py +++ b/photobooth/gui/PyQt5Gui.py @@ -1,6 +1,8 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- +import multiprocessing as mp + from PIL import ImageQt from PyQt5.QtCore import Qt, QObject, QPoint, QThread, QTimer, pyqtSignal @@ -35,13 +37,13 @@ class PyQt5Gui(Gui): cfg.getInt('Printer', 'height')), True) - def run(self, conn): + def run(self, camera_conn): - receiver = PyQt5Receiver(conn) + receiver = PyQt5Receiver([camera_conn]) receiver.notify.connect(self.handleState) receiver.start() - self._conn = conn + self._conn = camera_conn self.showStart() @@ -57,8 +59,8 @@ class PyQt5Gui(Gui): def restart(self): - - self._app.exit(-2) + + self._app.exit(123) def sendAck(self): @@ -210,13 +212,14 @@ class PyQt5Receiver(QThread): def run(self): - while True: - try: - state = self._conn.recv() - except EOFError: - break - else: - self.handle(state) + while self._conn: + for c in mp.connection.wait(self._conn): + try: + state = c.recv() + except EOFError: + break + else: + self.handle(state) diff --git a/photobooth/main.py b/photobooth/main.py index f821131..0de9fd0 100644 --- a/photobooth/main.py +++ b/photobooth/main.py @@ -7,8 +7,9 @@ try: except DistributionNotFound: __version__ = 'unknown' -from multiprocessing import Pipe, Process +import multiprocessing as mp import importlib +import sys from . import camera, gui from .Config import Config @@ -33,40 +34,68 @@ def lookup_and_import(module_list, name, package=None): return getattr(import_module, result[1]) -def start_worker(config, conn): +class CameraProcess(mp.Process): - while True: + def __init__(self, config, conn): + + super().__init__() + self.daemon = True + + self.cfg = config + self.conn = conn + + + def run_camera(self): + + # while True: try: - Camera = lookup_and_import( - camera.modules, config.get('Camera', 'module'), 'camera') + cap = lookup_and_import( + camera.modules, self.cfg.get('Camera', 'module'), 'camera') - with Camera() as cap: - photobooth = Photobooth(config, cap, conn) - return photobooth.run() + photobooth = Photobooth(self.cfg, cap, self.conn) + return photobooth.run() except BaseException as e: - conn.send( gui.ErrorState('Camera error', str(e)) ) - event = conn.recv() + self.conn.send( gui.ErrorState('Camera error', str(e)) ) + event = self.conn.recv() if str(event) in ('cancel', 'ack'): - return -1 + return 123 else: print('Unknown event received: ' + str(event)) raise RuntimeError('Unknown event received', str(event)) -def main_worker(config, conn): + def run(self): - while True: - event = conn.recv() + status_code = 123 - if str(event) != 'start': - continue + while status_code == 123: + event = self.conn.recv() - status_code = start_worker(config, conn) - print('Camera exit') + if str(event) != 'start': + continue - if status_code != -1: - return status_code + status_code = self.run_camera() + print('Camera exit') + + sys.exit(status_code) + + +class GuiProcess(mp.Process): + + def __init__(self, argv, config, conn): + + super().__init__() + + self.argv = argv + self.cfg = config + self.conn = conn + + + def run(self): + + Gui = lookup_and_import(gui.modules, self.cfg.get('Gui', 'module'), 'gui') + sys.exit(Gui(self.argv, self.cfg).run(self.conn)) def run(argv): @@ -75,26 +104,30 @@ def run(argv): config = Config('photobooth.cfg') - gui_conn, worker_conn = Pipe() + gui_conn, camera_conn = mp.Pipe() - worker = Process(target=main_worker, args=(config, worker_conn), daemon=True) - worker.start() + camera_worker = CameraProcess(config, camera_conn) + camera_worker.start() - Gui = lookup_and_import(gui.modules, config.get('Gui', 'module'), 'gui') - status_code = Gui(argv, config).run(gui_conn) + gui_worker = GuiProcess(argv, config, gui_conn) + gui_worker.start() - worker.join(1) - return status_code + gui_conn.close() + camera_conn.close() + + gui_worker.join() + camera_worker.join(5) + return gui_worker.exitcode def main(argv): known_status_codes = { - -1: 'Initializing photobooth', - -2: 'Restarting photobooth and reloading config' + 999: 'Initializing photobooth', + 123: 'Restarting photobooth and reloading config' } - status_code = -1 + status_code = 999 while status_code in known_status_codes: print(known_status_codes[status_code])