Pipe changed to duplex pipe
This commit is contained in:
@@ -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())
|
||||||
|
|||||||
@@ -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()
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user