Removed obsolete files
This commit is contained in:
@@ -1,255 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
# Photobooth - a flexible photo booth software
|
|
||||||
# Copyright (C) 2018 Balthasar Reuter <photobooth at re - web dot eu>
|
|
||||||
#
|
|
||||||
# This program is free software: you can redistribute it and/or modify
|
|
||||||
# it under the terms of the GNU Affero General Public License as published by
|
|
||||||
# the Free Software Foundation, either version 3 of the License, or
|
|
||||||
# (at your option) any later version.
|
|
||||||
#
|
|
||||||
# This program is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU Affero General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU Affero General Public License
|
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
import logging
|
|
||||||
|
|
||||||
from PIL import Image, ImageOps
|
|
||||||
|
|
||||||
from .PictureDimensions import PictureDimensions
|
|
||||||
|
|
||||||
from .gui import GuiState
|
|
||||||
|
|
||||||
from .Worker import PictureSaver
|
|
||||||
|
|
||||||
|
|
||||||
class TeardownException(Exception):
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
|
|
||||||
super().__init__()
|
|
||||||
|
|
||||||
|
|
||||||
class Photobooth:
|
|
||||||
|
|
||||||
def __init__(self, config, camera, conn, queue):
|
|
||||||
|
|
||||||
self._conn = conn
|
|
||||||
self._queue = queue
|
|
||||||
|
|
||||||
self._worker_list = [PictureSaver(config)]
|
|
||||||
|
|
||||||
self.initCamera(config, camera())
|
|
||||||
self.initGpio(config)
|
|
||||||
|
|
||||||
self.triggerOff()
|
|
||||||
|
|
||||||
def initCamera(self, config, camera):
|
|
||||||
|
|
||||||
self._cap = camera
|
|
||||||
self._pic_dims = PictureDimensions(config, self._cap.getPicture().size)
|
|
||||||
|
|
||||||
if (config.getBool('Photobooth', 'show_preview') and
|
|
||||||
self._cap.hasPreview):
|
|
||||||
logging.info('Countdown with preview activated')
|
|
||||||
self._show_counter = self.showCountdownPreview
|
|
||||||
else:
|
|
||||||
logging.info('Countdown without preview activated')
|
|
||||||
self._show_counter = self.showCountdownNoPreview
|
|
||||||
|
|
||||||
def initGpio(self, config):
|
|
||||||
|
|
||||||
if config.getBool('Gpio', 'enable'):
|
|
||||||
lamp_pin = config.getInt('Gpio', 'lamp_pin')
|
|
||||||
trigger_pin = config.getInt('Gpio', 'trigger_pin')
|
|
||||||
exit_pin = config.getInt('Gpio', 'exit_pin')
|
|
||||||
|
|
||||||
logging.info(('GPIO enabled (lamp_pin=%d, trigger_pin=%d, '
|
|
||||||
'exit_pin=%d)'), lamp_pin, trigger_pin, exit_pin)
|
|
||||||
|
|
||||||
from Gpio import Gpio
|
|
||||||
|
|
||||||
self._gpio = Gpio()
|
|
||||||
|
|
||||||
lamp = self._gpio.setLamp(lamp_pin)
|
|
||||||
self._lampOn = lambda: self._gpio.lampOn(lamp)
|
|
||||||
self._lampOff = lambda: self._gpio.lampOff(lamp)
|
|
||||||
|
|
||||||
self._gpio.setButton(trigger_pin, self.gpioTrigger)
|
|
||||||
self._gpio.setButton(exit_pin, self.gpioExit)
|
|
||||||
else:
|
|
||||||
logging.info('GPIO disabled')
|
|
||||||
self._lampOn = lambda: None
|
|
||||||
self._lampOff = lambda: None
|
|
||||||
|
|
||||||
def teardown(self):
|
|
||||||
|
|
||||||
logging.info('Teardown of camera')
|
|
||||||
self.triggerOff()
|
|
||||||
self.setCameraIdle()
|
|
||||||
self._cap.cleanup()
|
|
||||||
|
|
||||||
def recvEvent(self, expected):
|
|
||||||
|
|
||||||
event = self._conn.recv()
|
|
||||||
|
|
||||||
try:
|
|
||||||
event_idx = expected.index(str(event))
|
|
||||||
except ValueError:
|
|
||||||
logging.error('Unknown event received: %s', str(event))
|
|
||||||
raise ValueError('Unknown event received', str(event))
|
|
||||||
|
|
||||||
return event_idx
|
|
||||||
|
|
||||||
def recvAck(self):
|
|
||||||
|
|
||||||
events = ['ack', 'cancel', 'teardown']
|
|
||||||
|
|
||||||
if self.recvEvent(events) != 0:
|
|
||||||
logging.info('Teardown of camera requested')
|
|
||||||
raise TeardownException()
|
|
||||||
|
|
||||||
def recvTriggered(self):
|
|
||||||
|
|
||||||
events = ['triggered', 'teardown']
|
|
||||||
|
|
||||||
if self.recvEvent(events) != 0:
|
|
||||||
logging.info('Teardown of camera requested')
|
|
||||||
raise TeardownException()
|
|
||||||
|
|
||||||
@property
|
|
||||||
def showCountdown(self):
|
|
||||||
|
|
||||||
return self._show_counter
|
|
||||||
|
|
||||||
def initRun(self):
|
|
||||||
|
|
||||||
self.setCameraIdle()
|
|
||||||
self._conn.send(GuiState.IdleState())
|
|
||||||
self.triggerOn()
|
|
||||||
|
|
||||||
def run(self):
|
|
||||||
|
|
||||||
self.initRun()
|
|
||||||
|
|
||||||
try:
|
|
||||||
while True:
|
|
||||||
try:
|
|
||||||
self.recvTriggered()
|
|
||||||
except EOFError:
|
|
||||||
return 0
|
|
||||||
|
|
||||||
try:
|
|
||||||
self.trigger()
|
|
||||||
except RuntimeError as e:
|
|
||||||
logging.error('Camera error: %s', str(e))
|
|
||||||
self._conn.send(GuiState.ErrorState('Cam error', str(e)))
|
|
||||||
self.recvAck()
|
|
||||||
|
|
||||||
except TeardownException:
|
|
||||||
self.teardown()
|
|
||||||
return 123
|
|
||||||
|
|
||||||
def setCameraActive(self):
|
|
||||||
|
|
||||||
self._cap.setActive()
|
|
||||||
|
|
||||||
def setCameraIdle(self):
|
|
||||||
|
|
||||||
if self._cap.hasIdle:
|
|
||||||
self._cap.setIdle()
|
|
||||||
|
|
||||||
def showCountdownPreview(self):
|
|
||||||
|
|
||||||
self._conn.send(GuiState.CountdownState())
|
|
||||||
|
|
||||||
while not self._conn.poll():
|
|
||||||
picture = ImageOps.mirror(self._cap.getPreview())
|
|
||||||
self._conn.send(GuiState.PreviewState(picture=picture))
|
|
||||||
|
|
||||||
self.recvAck()
|
|
||||||
|
|
||||||
def showCountdownNoPreview(self):
|
|
||||||
|
|
||||||
self._conn.send(GuiState.CountdownState())
|
|
||||||
self.recvAck()
|
|
||||||
|
|
||||||
def showPose(self, num_picture):
|
|
||||||
|
|
||||||
self._conn.send(GuiState.PoseState(num_picture))
|
|
||||||
|
|
||||||
def captureSinglePicture(self, num_picture):
|
|
||||||
|
|
||||||
self.showCountdown()
|
|
||||||
self.setCameraIdle()
|
|
||||||
self.showPose(num_picture)
|
|
||||||
picture = self._cap.getPicture()
|
|
||||||
self.setCameraActive()
|
|
||||||
return picture
|
|
||||||
|
|
||||||
def capturePictures(self):
|
|
||||||
|
|
||||||
return [self.captureSinglePicture(i+1)
|
|
||||||
for i in range(self._pic_dims.totalNumPictures)]
|
|
||||||
|
|
||||||
def assemblePictures(self, pictures):
|
|
||||||
|
|
||||||
image = Image.new('RGB', self._pic_dims.outputSize, (255, 255, 255))
|
|
||||||
|
|
||||||
for i in range(self._pic_dims.totalNumPictures):
|
|
||||||
image.paste(pictures[i].resize(self._pic_dims.thumbnailSize),
|
|
||||||
self._pic_dims.thumbnailOffset[i])
|
|
||||||
|
|
||||||
return image
|
|
||||||
|
|
||||||
def enqueueWorkerTasks(self, picture):
|
|
||||||
|
|
||||||
for task in self._worker_list:
|
|
||||||
self._queue.put(task.get(picture))
|
|
||||||
|
|
||||||
def trigger(self):
|
|
||||||
|
|
||||||
logging.info('Photobooth triggered')
|
|
||||||
|
|
||||||
self.triggerOff()
|
|
||||||
self._conn.send(GuiState.GreeterState())
|
|
||||||
|
|
||||||
self.setCameraActive()
|
|
||||||
self.recvAck()
|
|
||||||
|
|
||||||
pics = self.capturePictures()
|
|
||||||
self._conn.send(GuiState.AssembleState())
|
|
||||||
|
|
||||||
img = self.assemblePictures(pics)
|
|
||||||
self._conn.send(GuiState.ReviewState(picture=img))
|
|
||||||
|
|
||||||
self.enqueueWorkerTasks(img)
|
|
||||||
|
|
||||||
self.setCameraIdle()
|
|
||||||
self.recvAck()
|
|
||||||
|
|
||||||
self._conn.send(GuiState.IdleState())
|
|
||||||
self.triggerOn()
|
|
||||||
|
|
||||||
def gpioTrigger(self):
|
|
||||||
|
|
||||||
self._gpioTrigger()
|
|
||||||
|
|
||||||
def gpioExit(self):
|
|
||||||
|
|
||||||
self._conn.send(GuiState.TeardownState())
|
|
||||||
|
|
||||||
def triggerOff(self):
|
|
||||||
|
|
||||||
self._lampOff()
|
|
||||||
self._gpioTrigger = lambda: None
|
|
||||||
|
|
||||||
def triggerOn(self):
|
|
||||||
|
|
||||||
self._lampOn()
|
|
||||||
self._gpioTrigger = lambda: self._conn.send(GuiState.TriggerState())
|
|
||||||
@@ -21,7 +21,7 @@ import logging
|
|||||||
|
|
||||||
from PIL import Image, ImageOps
|
from PIL import Image, ImageOps
|
||||||
|
|
||||||
from ..PictureDimensions import PictureDimensions
|
from .PictureDimensions import PictureDimensions
|
||||||
from .. import StateMachine
|
from .. import StateMachine
|
||||||
from ..Threading import Workers
|
from ..Threading import Workers
|
||||||
|
|
||||||
|
|||||||
@@ -1,210 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
# Photobooth - a flexible photo booth software
|
|
||||||
# Copyright (C) 2018 Balthasar Reuter <photobooth at re - web dot eu>
|
|
||||||
#
|
|
||||||
# This program is free software: you can redistribute it and/or modify
|
|
||||||
# it under the terms of the GNU Affero General Public License as published by
|
|
||||||
# the Free Software Foundation, either version 3 of the License, or
|
|
||||||
# (at your option) any later version.
|
|
||||||
#
|
|
||||||
# This program is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU Affero General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU Affero General Public License
|
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
|
|
||||||
class GuiState:
|
|
||||||
|
|
||||||
def __init__(self, **kwargs):
|
|
||||||
|
|
||||||
assert not kwargs
|
|
||||||
|
|
||||||
|
|
||||||
class ErrorState(GuiState):
|
|
||||||
|
|
||||||
def __init__(self, title, message, **kwargs):
|
|
||||||
|
|
||||||
super().__init__(**kwargs)
|
|
||||||
|
|
||||||
self.title = title
|
|
||||||
self.message = message
|
|
||||||
|
|
||||||
@property
|
|
||||||
def title(self):
|
|
||||||
|
|
||||||
return self._title
|
|
||||||
|
|
||||||
@title.setter
|
|
||||||
def title(self, title):
|
|
||||||
|
|
||||||
self._title = title
|
|
||||||
|
|
||||||
@property
|
|
||||||
def message(self):
|
|
||||||
|
|
||||||
return self._message
|
|
||||||
|
|
||||||
@message.setter
|
|
||||||
def message(self, message):
|
|
||||||
|
|
||||||
self._message = message
|
|
||||||
|
|
||||||
|
|
||||||
class IdleState(GuiState):
|
|
||||||
|
|
||||||
def __init__(self, **kwargs):
|
|
||||||
|
|
||||||
super().__init__(**kwargs)
|
|
||||||
|
|
||||||
|
|
||||||
class PictureState(GuiState):
|
|
||||||
|
|
||||||
def __init__(self, picture, **kwargs):
|
|
||||||
|
|
||||||
super().__init__(**kwargs)
|
|
||||||
|
|
||||||
self.picture = picture
|
|
||||||
|
|
||||||
@property
|
|
||||||
def picture(self):
|
|
||||||
|
|
||||||
return self._pic
|
|
||||||
|
|
||||||
@picture.setter
|
|
||||||
def picture(self, picture):
|
|
||||||
|
|
||||||
self._pic = picture
|
|
||||||
|
|
||||||
|
|
||||||
class MessageState(GuiState):
|
|
||||||
|
|
||||||
def __init__(self, message, **kwargs):
|
|
||||||
|
|
||||||
super().__init__(**kwargs)
|
|
||||||
|
|
||||||
self.message = message
|
|
||||||
|
|
||||||
@property
|
|
||||||
def message(self):
|
|
||||||
|
|
||||||
return self._msg
|
|
||||||
|
|
||||||
@message.setter
|
|
||||||
def message(self, message):
|
|
||||||
|
|
||||||
if not isinstance(message, str):
|
|
||||||
raise ValueError('Message must be a string')
|
|
||||||
|
|
||||||
self._msg = message
|
|
||||||
|
|
||||||
|
|
||||||
class TriggerState(GuiState):
|
|
||||||
|
|
||||||
def __init__(self, **kwargs):
|
|
||||||
|
|
||||||
super().__init__(**kwargs)
|
|
||||||
|
|
||||||
|
|
||||||
class GreeterState(GuiState):
|
|
||||||
|
|
||||||
def __init__(self, **kwargs):
|
|
||||||
|
|
||||||
super().__init__(**kwargs)
|
|
||||||
|
|
||||||
|
|
||||||
class PoseState(GuiState):
|
|
||||||
|
|
||||||
def __init__(self, num_picture, **kwargs):
|
|
||||||
|
|
||||||
super().__init__(**kwargs)
|
|
||||||
|
|
||||||
self.num_picture = num_picture
|
|
||||||
|
|
||||||
@property
|
|
||||||
def num_picture(self):
|
|
||||||
|
|
||||||
return self._num_picture
|
|
||||||
|
|
||||||
@num_picture.setter
|
|
||||||
def num_picture(self, num_picture):
|
|
||||||
|
|
||||||
if not isinstance(num_picture, int):
|
|
||||||
raise ValueError('Picture number must be an integer')
|
|
||||||
|
|
||||||
self._num_picture = num_picture
|
|
||||||
|
|
||||||
|
|
||||||
class AssembleState(GuiState):
|
|
||||||
|
|
||||||
def __init__(self, **kwargs):
|
|
||||||
|
|
||||||
super().__init__(**kwargs)
|
|
||||||
|
|
||||||
|
|
||||||
class CountdownState(GuiState):
|
|
||||||
|
|
||||||
def __init__(self, **kwargs):
|
|
||||||
|
|
||||||
super().__init__(**kwargs)
|
|
||||||
|
|
||||||
|
|
||||||
class PreviewState(PictureState):
|
|
||||||
|
|
||||||
def __init__(self, **kwargs):
|
|
||||||
|
|
||||||
super().__init__(**kwargs)
|
|
||||||
|
|
||||||
|
|
||||||
class ReviewState(PictureState):
|
|
||||||
|
|
||||||
def __init__(self, **kwargs):
|
|
||||||
|
|
||||||
super().__init__(**kwargs)
|
|
||||||
|
|
||||||
|
|
||||||
class TeardownState(GuiState):
|
|
||||||
|
|
||||||
def __init__(self, **kwargs):
|
|
||||||
|
|
||||||
super().__init__(**kwargs)
|
|
||||||
|
|
||||||
|
|
||||||
class PrintState(GuiState):
|
|
||||||
|
|
||||||
def __init__(self, handler, confirmed, **kwargs):
|
|
||||||
|
|
||||||
super().__init__(**kwargs)
|
|
||||||
|
|
||||||
self.handler = handler
|
|
||||||
self.confirmed = confirmed
|
|
||||||
|
|
||||||
@property
|
|
||||||
def handler(self):
|
|
||||||
|
|
||||||
return self._handler
|
|
||||||
|
|
||||||
@handler.setter
|
|
||||||
def handler(self, handler):
|
|
||||||
|
|
||||||
if not callable(handler):
|
|
||||||
raise ValueError('handler must be callable')
|
|
||||||
|
|
||||||
self._handler = handler
|
|
||||||
|
|
||||||
@property
|
|
||||||
def confirmed(self):
|
|
||||||
|
|
||||||
return self._confirmed
|
|
||||||
|
|
||||||
@confirmed.setter
|
|
||||||
def confirmed(self, confirmed):
|
|
||||||
|
|
||||||
if not isinstance(confirmed, bool):
|
|
||||||
raise ValueError('confirmed status must be bool')
|
|
||||||
|
|
||||||
self._confirmed = confirmed
|
|
||||||
@@ -17,7 +17,5 @@
|
|||||||
# You should have received a copy of the GNU Affero General Public License
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
from . import GuiState # noqa
|
|
||||||
|
|
||||||
# Available gui modules as tuples of (config name, module name, class name)
|
# Available gui modules as tuples of (config name, module name, class name)
|
||||||
modules = (('PyQt5', 'Qt5Gui', 'PyQt5Gui'), )
|
modules = (('PyQt5', 'Qt5Gui', 'PyQt5Gui'), )
|
||||||
|
|||||||
Reference in New Issue
Block a user