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:
def __init__(self, config, camera, send, recv):
def __init__(self, config, camera, conn):
self._send = send
self._recv = recv
self._conn = conn
self.initCamera(config, camera)
self.initGpio(config)
@@ -74,7 +73,7 @@ class Photobooth:
def recvEvent(self, expected):
event = self._recv.recv()
event = self._conn.recv()
try:
event_idx = expected.index(str(event))
@@ -118,7 +117,7 @@ class Photobooth:
def initRun(self):
self.setCameraIdle()
self._send.send(gui.IdleState())
self._conn.send(gui.IdleState())
self.triggerOn()
@@ -137,7 +136,7 @@ class Photobooth:
self.trigger()
except RuntimeError as 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()
except TeardownException:
@@ -157,10 +156,10 @@ class Photobooth:
def showCounterPreview(self):
self._send.send(gui.CountdownState())
self._conn.send(gui.CountdownState())
while not self._recv.poll():
self._send.send(
while not self._conn.poll():
self._conn.send(
gui.PreviewState(picture = ImageOps.mirror(self._cap.getPreview())) )
self.recvAck()
@@ -168,14 +167,14 @@ class Photobooth:
def showCounterNoPreview(self):
self._send.send(gui.CountdownState())
self._conn.send(gui.CountdownState())
self.recvAck()
print('ack received')
def showPose(self):
self._send.send( gui.PoseState() )
self._conn.send(gui.PoseState())
def captureSinglePicture(self):
@@ -203,24 +202,24 @@ class Photobooth:
def trigger(self):
self._send.send(gui.GreeterState())
self._conn.send(gui.GreeterState())
self.triggerOff()
self.setCameraActive()
self.recvAck()
pics = self.capturePictures()
self._send.send(gui.AssembleState())
self._conn.send(gui.AssembleState())
img = self.assemblePictures(pics)
img.save(self.getNextFilename(), 'JPEG')
self._send.send(gui.PictureState(img))
self._conn.send(gui.PictureState(img))
self.setCameraIdle()
self.recvAck()
self._send.send(gui.IdleState())
self._conn.send(gui.IdleState())
self.triggerOn()
@@ -231,7 +230,7 @@ class Photobooth:
def gpioExit(self):
self._send.send(gui.TeardownState())
self._conn.send(gui.TeardownState())
def triggerOff(self):
@@ -243,4 +242,4 @@ class Photobooth:
def triggerOn(self):
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)
def run(self, send, recv):
def run(self, conn):
receiver = PyQt5Receiver(recv)
receiver = PyQt5Receiver(conn)
receiver.notify.connect(self.handleState)
receiver.start()
self._transport = send
self._conn = conn
self.showStart()
@@ -58,20 +58,37 @@ class PyQt5Gui(Gui):
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):
if event.key() == Qt.Key_Escape:
# self.showStart()
self.handleState(TeardownState())
elif event.key() == Qt.Key_Space:
# self._transport.send('triggered')
self.handleState(TriggerState())
def handleKeypressEventNoTrigger(self, event):
if event.key() == Qt.Key_Escape:
# self.showStart()
self.handleState(TeardownState())
@@ -84,7 +101,7 @@ class PyQt5Gui(Gui):
self.showIdle()
elif isinstance(state, TriggerState):
self._transport.send('triggered')
self.sendTrigger()
elif isinstance(state, GreeterState):
global cfg
@@ -94,10 +111,10 @@ class PyQt5Gui(Gui):
cfg.getInt('Picture', 'num_y') )
self._p.setCentralWidget(
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):
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):
self._p.centralWidget().picture = ImageQt.ImageQt(state.picture)
@@ -112,12 +129,12 @@ class PyQt5Gui(Gui):
elif isinstance(state, PictureState):
img = ImageQt.ImageQt(state.picture)
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)
elif isinstance(state, TeardownState):
self._transport.send('teardown')
self._conn.send('teardown')
self.showStart()
elif isinstance(state, ErrorState):
@@ -146,7 +163,7 @@ class PyQt5Gui(Gui):
def showStartPhotobooth(self):
self._lastState = self.showStartPhotobooth
self._transport.send('start')
self._conn.send('start')
self._p.setCentralWidget(PyQt5WaitMessage('Starting the photobooth...'))
if cfg.getBool('Gui', 'hide_cursor'):
QApplication.setOverrideCursor(Qt.BlankCursor)
@@ -165,10 +182,10 @@ class PyQt5Gui(Gui):
reply = QMessageBox.warning(self._p, title, message, QMessageBox.Close | QMessageBox.Retry,
QMessageBox.Retry)
if reply == QMessageBox.Retry:
self._transport.send('ack')
self.sendAck()
self._lastState()
else:
self._transport.send('cancel')
self.sendCancel()
self.showStart()
@@ -176,11 +193,11 @@ class PyQt5Receiver(QThread):
notify = pyqtSignal(object)
def __init__(self, transport):
def __init__(self, conn):
super().__init__()
self._transport = transport
self._conn = conn
def handle(self, state):
@@ -192,7 +209,7 @@ class PyQt5Receiver(QThread):
while True:
try:
state = self._transport.recv()
state = self._conn.recv()
except EOFError:
break
else:
@@ -246,7 +263,6 @@ class PyQt5MainWindow(QMainWindow):
QMessageBox.Yes | QMessageBox.No, QMessageBox.No)
if reply == QMessageBox.Yes:
# self.transport.close()
e.accept()
else:
e.ignore()

View File

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