Pipe changed to duplex pipe

This commit is contained in:
Balthasar Reuter
2018-05-10 21:28:57 +02:00
parent 8b2cc27647
commit e13ccc5eb5
3 changed files with 66 additions and 50 deletions

View File

@@ -20,10 +20,9 @@ class TeardownException(Exception):
class Photobooth: class Photobooth:
def __init__(self, config, camera, send, recv): def __init__(self, config, camera, conn):
self._send = send self._conn = conn
self._recv = recv
self.initCamera(config, camera) self.initCamera(config, camera)
self.initGpio(config) self.initGpio(config)
@@ -74,7 +73,7 @@ class Photobooth:
def recvEvent(self, expected): def recvEvent(self, expected):
event = self._recv.recv() event = self._conn.recv()
try: try:
event_idx = expected.index(str(event)) event_idx = expected.index(str(event))
@@ -118,7 +117,7 @@ class Photobooth:
def initRun(self): def initRun(self):
self.setCameraIdle() self.setCameraIdle()
self._send.send(gui.IdleState()) self._conn.send(gui.IdleState())
self.triggerOn() self.triggerOn()
@@ -137,7 +136,7 @@ class Photobooth:
self.trigger() self.trigger()
except RuntimeError as e: except RuntimeError as e:
print('Camera error: ' + str(e)) print('Camera error: ' + str(e))
self._send.send( gui.ErrorState('Camera error', str(e)) ) self._conn.send( gui.ErrorState('Camera error', str(e)) )
self.recvAck() self.recvAck()
except TeardownException: except TeardownException:
@@ -157,10 +156,10 @@ class Photobooth:
def showCounterPreview(self): def showCounterPreview(self):
self._send.send(gui.CountdownState()) self._conn.send(gui.CountdownState())
while not self._recv.poll(): while not self._conn.poll():
self._send.send( self._conn.send(
gui.PreviewState(picture = ImageOps.mirror(self._cap.getPreview())) ) gui.PreviewState(picture = ImageOps.mirror(self._cap.getPreview())) )
self.recvAck() self.recvAck()
@@ -168,14 +167,14 @@ class Photobooth:
def showCounterNoPreview(self): def showCounterNoPreview(self):
self._send.send(gui.CountdownState()) self._conn.send(gui.CountdownState())
self.recvAck() self.recvAck()
print('ack received') print('ack received')
def showPose(self): def showPose(self):
self._send.send( gui.PoseState() ) self._conn.send(gui.PoseState())
def captureSinglePicture(self): def captureSinglePicture(self):
@@ -203,24 +202,24 @@ class Photobooth:
def trigger(self): def trigger(self):
self._send.send(gui.GreeterState()) self._conn.send(gui.GreeterState())
self.triggerOff() self.triggerOff()
self.setCameraActive() self.setCameraActive()
self.recvAck() self.recvAck()
pics = self.capturePictures() pics = self.capturePictures()
self._send.send(gui.AssembleState()) self._conn.send(gui.AssembleState())
img = self.assemblePictures(pics) img = self.assemblePictures(pics)
img.save(self.getNextFilename(), 'JPEG') img.save(self.getNextFilename(), 'JPEG')
self._send.send(gui.PictureState(img)) self._conn.send(gui.PictureState(img))
self.setCameraIdle() self.setCameraIdle()
self.recvAck() self.recvAck()
self._send.send(gui.IdleState()) self._conn.send(gui.IdleState())
self.triggerOn() self.triggerOn()
@@ -231,7 +230,7 @@ class Photobooth:
def gpioExit(self): def gpioExit(self):
self._send.send(gui.TeardownState()) self._conn.send(gui.TeardownState())
def triggerOff(self): def triggerOff(self):
@@ -243,4 +242,4 @@ class Photobooth:
def triggerOn(self): def triggerOn(self):
self._lampOn() self._lampOn()
self._gpioTrigger = lambda : self._send.send(gui.TriggerState()) self._gpioTrigger = lambda : self._conn.send(gui.TriggerState())

View File

@@ -32,13 +32,13 @@ class PyQt5Gui(Gui):
cfg.getInt('Printer', 'height')), True) cfg.getInt('Printer', 'height')), True)
def run(self, send, recv): def run(self, conn):
receiver = PyQt5Receiver(recv) receiver = PyQt5Receiver(conn)
receiver.notify.connect(self.handleState) receiver.notify.connect(self.handleState)
receiver.start() receiver.start()
self._transport = send self._conn = conn
self.showStart() self.showStart()
@@ -58,20 +58,37 @@ class PyQt5Gui(Gui):
self._app.exit(-2) self._app.exit(-2)
def sendAck(self):
self._conn.send('ack')
def sendCancel(self):
self._conn.send('cancel')
def sendTrigger(self):
self._conn.send('triggered')
def sendTeardown(self):
self._conn.send('teardown')
def handleKeypressEvent(self, event): def handleKeypressEvent(self, event):
if event.key() == Qt.Key_Escape: if event.key() == Qt.Key_Escape:
# self.showStart()
self.handleState(TeardownState()) self.handleState(TeardownState())
elif event.key() == Qt.Key_Space: elif event.key() == Qt.Key_Space:
# self._transport.send('triggered')
self.handleState(TriggerState()) self.handleState(TriggerState())
def handleKeypressEventNoTrigger(self, event): def handleKeypressEventNoTrigger(self, event):
if event.key() == Qt.Key_Escape: if event.key() == Qt.Key_Escape:
# self.showStart()
self.handleState(TeardownState()) self.handleState(TeardownState())
@@ -84,7 +101,7 @@ class PyQt5Gui(Gui):
self.showIdle() self.showIdle()
elif isinstance(state, TriggerState): elif isinstance(state, TriggerState):
self._transport.send('triggered') self.sendTrigger()
elif isinstance(state, GreeterState): elif isinstance(state, GreeterState):
global cfg global cfg
@@ -94,10 +111,10 @@ class PyQt5Gui(Gui):
cfg.getInt('Picture', 'num_y') ) cfg.getInt('Picture', 'num_y') )
self._p.setCentralWidget( self._p.setCentralWidget(
PyQt5PictureMessage('Will capture {} pictures!'.format(num_pictures))) PyQt5PictureMessage('Will capture {} pictures!'.format(num_pictures)))
QTimer.singleShot(cfg.getInt('Photobooth', 'greeter_time') * 1000, lambda : self._transport.send('ack')) QTimer.singleShot(cfg.getInt('Photobooth', 'greeter_time') * 1000, self.sendAck)
elif isinstance(state, CountdownState): elif isinstance(state, CountdownState):
self._p.setCentralWidget(PyQt5CountdownMessage(cfg.getInt('Photobooth', 'countdown_time'), lambda : self._transport.send('ack'))) self._p.setCentralWidget(PyQt5CountdownMessage(cfg.getInt('Photobooth', 'countdown_time'), self.sendAck))
elif isinstance(state, PreviewState): elif isinstance(state, PreviewState):
self._p.centralWidget().picture = ImageQt.ImageQt(state.picture) self._p.centralWidget().picture = ImageQt.ImageQt(state.picture)
@@ -112,12 +129,12 @@ class PyQt5Gui(Gui):
elif isinstance(state, PictureState): elif isinstance(state, PictureState):
img = ImageQt.ImageQt(state.picture) img = ImageQt.ImageQt(state.picture)
self._p.setCentralWidget(PyQt5PictureMessage('', img)) self._p.setCentralWidget(PyQt5PictureMessage('', img))
QTimer.singleShot(cfg.getInt('Photobooth', 'display_time') * 1000, lambda : self._transport.send('ack')) QTimer.singleShot(cfg.getInt('Photobooth', 'display_time') * 1000, lambda : self.sendAck())
self._printer.print(state.picture) self._printer.print(state.picture)
elif isinstance(state, TeardownState): elif isinstance(state, TeardownState):
self._transport.send('teardown') self._conn.send('teardown')
self.showStart() self.showStart()
elif isinstance(state, ErrorState): elif isinstance(state, ErrorState):
@@ -146,7 +163,7 @@ class PyQt5Gui(Gui):
def showStartPhotobooth(self): def showStartPhotobooth(self):
self._lastState = self.showStartPhotobooth self._lastState = self.showStartPhotobooth
self._transport.send('start') self._conn.send('start')
self._p.setCentralWidget(PyQt5WaitMessage('Starting the photobooth...')) self._p.setCentralWidget(PyQt5WaitMessage('Starting the photobooth...'))
if cfg.getBool('Gui', 'hide_cursor'): if cfg.getBool('Gui', 'hide_cursor'):
QApplication.setOverrideCursor(Qt.BlankCursor) QApplication.setOverrideCursor(Qt.BlankCursor)
@@ -165,10 +182,10 @@ class PyQt5Gui(Gui):
reply = QMessageBox.warning(self._p, title, message, QMessageBox.Close | QMessageBox.Retry, reply = QMessageBox.warning(self._p, title, message, QMessageBox.Close | QMessageBox.Retry,
QMessageBox.Retry) QMessageBox.Retry)
if reply == QMessageBox.Retry: if reply == QMessageBox.Retry:
self._transport.send('ack') self.sendAck()
self._lastState() self._lastState()
else: else:
self._transport.send('cancel') self.sendCancel()
self.showStart() self.showStart()
@@ -176,11 +193,11 @@ class PyQt5Receiver(QThread):
notify = pyqtSignal(object) notify = pyqtSignal(object)
def __init__(self, transport): def __init__(self, conn):
super().__init__() super().__init__()
self._transport = transport self._conn = conn
def handle(self, state): def handle(self, state):
@@ -192,7 +209,7 @@ class PyQt5Receiver(QThread):
while True: while True:
try: try:
state = self._transport.recv() state = self._conn.recv()
except EOFError: except EOFError:
break break
else: else:
@@ -246,7 +263,6 @@ class PyQt5MainWindow(QMainWindow):
QMessageBox.Yes | QMessageBox.No, QMessageBox.No) QMessageBox.Yes | QMessageBox.No, QMessageBox.No)
if reply == QMessageBox.Yes: if reply == QMessageBox.Yes:
# self.transport.close()
e.accept() e.accept()
else: else:
e.ignore() e.ignore()

View File

@@ -24,7 +24,8 @@ def lookup_and_import(module_list, name, package=None):
if package == None: if package == None:
import_module = importlib.import_module('photobooth.' + result[0]) import_module = importlib.import_module('photobooth.' + result[0])
else: else:
import_module = importlib.import_module('photobooth.' + package + '.' + result[0]) import_module = importlib.import_module(
'photobooth.' + package + '.' + result[0])
if result[1] == None: if result[1] == None:
return import_module return import_module
@@ -32,19 +33,20 @@ def lookup_and_import(module_list, name, package=None):
return getattr(import_module, result[1]) return getattr(import_module, result[1])
def start_photobooth(config, send, recv): def start_worker(config, conn):
while True: while True:
try: try:
Camera = lookup_and_import(camera.modules, config.get('Camera', 'module'), 'camera') Camera = lookup_and_import(
camera.modules, config.get('Camera', 'module'), 'camera')
with Camera() as cap: with Camera() as cap:
photobooth = Photobooth(config, cap, send, recv) photobooth = Photobooth(config, cap, conn)
return photobooth.run() return photobooth.run()
except BaseException as e: except BaseException as e:
send.send( gui.ErrorState('Camera error', str(e)) ) conn.send( gui.ErrorState('Camera error', str(e)) )
event = recv.recv() event = conn.recv()
if str(event) in ('cancel', 'ack'): if str(event) in ('cancel', 'ack'):
return -1 return -1
else: else:
@@ -52,15 +54,15 @@ def start_photobooth(config, send, recv):
raise RuntimeError('Unknown event received', str(event)) raise RuntimeError('Unknown event received', str(event))
def main_photobooth(config, send, recv): def main_worker(config, conn):
while True: while True:
event = recv.recv() event = conn.recv()
if str(event) != 'start': if str(event) != 'start':
continue continue
status_code = start_photobooth(config, send, recv) status_code = start_worker(config, conn)
print('Camera exit') print('Camera exit')
if status_code != -1: if status_code != -1:
@@ -73,16 +75,15 @@ def run(argv):
config = Config('photobooth.cfg') config = Config('photobooth.cfg')
event_recv, event_send = Pipe(duplex=False) gui_conn, worker_conn = Pipe()
gui_recv, gui_send = Pipe(duplex=False)
photobooth = Process(target=main_photobooth, args=(config, gui_send, event_recv), daemon=True) worker = Process(target=main_worker, args=(config, worker_conn), daemon=True)
photobooth.start() worker.start()
Gui = lookup_and_import(gui.modules, config.get('Gui', 'module'), 'gui') Gui = lookup_and_import(gui.modules, config.get('Gui', 'module'), 'gui')
status_code = Gui(argv, config).run(event_send, gui_recv) status_code = Gui(argv, config).run(gui_conn)
photobooth.join(1) worker.join(1)
return status_code return status_code