Exemplo n.º 1
0
 def _on_button_capture_held(self):
     """Called when the capture button is pressed.
     """
     if all(self.buttons.value):
         self.buttons.capture.hold_repeat = True
         if self._multipress_timer.elapsed() == 0:
             self._multipress_timer.start()
         if self._multipress_timer.is_timeout():
             # Capture was held while printer was pressed
             if self._menu and self._menu.is_shown():
                 # Convert HW button events to keyboard events for menu
                 event = self._menu.create_back_event()
                 LOGGER.debug("BUTTONDOWN: generate MENU-ESC event")
             else:
                 event = pygame.event.Event(BUTTONDOWN,
                                            capture=1,
                                            printer=1,
                                            button=self.buttons)
                 LOGGER.debug("BUTTONDOWN: generate DOUBLE buttons event")
             self.buttons.capture.hold_repeat = False
             self._multipress_timer.reset()
             pygame.event.post(event)
     else:
         # Capture was held but printer not pressed
         if self._menu and self._menu.is_shown():
             # Convert HW button events to keyboard events for menu
             event = self._menu.create_next_event()
             LOGGER.debug("BUTTONDOWN: generate MENU-NEXT event")
         else:
             event = pygame.event.Event(BUTTONDOWN,
                                        capture=1,
                                        printer=0,
                                        button=self.buttons.capture)
             LOGGER.debug("BUTTONDOWN: generate CAPTURE button event")
         self.buttons.capture.hold_repeat = False
         self._multipress_timer.reset()
         pygame.event.post(event)
Exemplo n.º 2
0
def init(filename, clear=False):
    """Initialize the translation system.

    :param filename: path to the translations file
    :type filename: str
    :param clear: restore default translations
    :type clear: bool
    """
    PARSER.filename = osp.abspath(osp.expanduser(filename))

    if not osp.isfile(PARSER.filename) or clear:
        LOGGER.info("Generate the translation file in '%s'", PARSER.filename)
        dirname = osp.dirname(PARSER.filename)
        if not osp.isdir(dirname):
            os.makedirs(dirname)

        with io.open(PARSER.filename, 'w', encoding="utf-8") as fp:
            for section, options in DEFAULT.items():
                fp.write("[{}]\n".format(section))
                for name, value in options.items():
                    value = value.splitlines()
                    fp.write("{} = {}\n".format(name, value[0]))
                    if len(value) > 1:
                        for part in value[1:]:
                            fp.write("    {}\n".format(part))
                fp.write("\n\n")

    PARSER.read(PARSER.filename, encoding='utf-8')

    # Update the current file with missing language(s) and key(s)
    changed = False
    for section, options in DEFAULT.items():
        if not PARSER.has_section(section):
            changed = True
            LOGGER.debug("Add [%s] to available language list", section)
            PARSER.add_section(section)

        for option, value in options.items():
            if not PARSER.has_option(section, option):
                changed = True
                LOGGER.debug("Add [%s][%s] to available translations", section,
                             option)
                PARSER.set(section, option, value)

    if changed:
        with io.open(PARSER.filename, 'w', encoding="utf-8") as fp:
            PARSER.write(fp)
Exemplo n.º 3
0
    def __init__(self, name='default'):
        self._conn = cups.Connection() if cups else None
        self._notif_server = NotificationServer(self._conn, self._on_event)
        self.name = None
        if not cups:
            LOGGER.warning("No printer found (pycups not installed)")
            return  # CUPS is not installed
        elif not name or name.lower() == 'default':
            self.name = self._conn.getDefault()
            if not self.name and self._conn.getPrinters():
                self.name = list(
                    self._conn.getPrinters().keys())[0]  # Take first one
        elif name in self._conn.getPrinters():
            self.name = name

        if not self.name:
            LOGGER.warning("No printer found (nothing defined in CUPS)")
        else:
            LOGGER.info("Connected to printer '%s'", self.name)
Exemplo n.º 4
0
def pibooth_startup(app, cfg):
    """Create the GooglePhotosUpload instance."""
    app.previous_picture_url = None
    client_id_file = cfg.getpath('GOOGLE', 'client_id_file')

    if not client_id_file:
        LOGGER.debug(
            "No credentials file defined in [GOOGLE][client_id_file], upload deactivated"
        )
    elif not os.path.exists(client_id_file):
        LOGGER.error(
            "No such file [GOOGLE][client_id_file]='%s', please check config",
            client_id_file)
    elif client_id_file and os.path.getsize(client_id_file) == 0:
        LOGGER.error(
            "Empty file [GOOGLE][client_id_file]='%s', please check config",
            client_id_file)
    else:
        app.google_photos = GooglePhotosApi(client_id_file)
Exemplo n.º 5
0
    def state_processing_do(self, cfg, app):
        idx = app.capture_choices.index(app.capture_nbr)
        self.texts_vars['date'] = datetime.strptime(app.capture_date,
                                                    "%Y-%m-%d-%H-%M-%S")
        self.texts_vars['count'] = app.count

        LOGGER.info("Saving raw captures")
        captures = app.camera.get_captures()

        for savedir in cfg.gettuple('GENERAL', 'directory', 'path'):
            rawdir = osp.join(savedir, "raw", app.capture_date)
            os.makedirs(rawdir)

            for capture in captures:
                count = captures.index(capture)
                capture.save(osp.join(rawdir,
                                      "pibooth{:03}.jpg".format(count)))

        LOGGER.info("Creating the final picture")
        default_factory = get_picture_factory(
            captures, cfg.get('PICTURE', 'orientation'))
        factory = self._pm.hook.pibooth_setup_picture_factory(
            cfg=cfg, opt_index=idx, factory=default_factory)
        app.previous_picture = factory.build()

        for savedir in cfg.gettuple('GENERAL', 'directory', 'path'):
            app.previous_picture_file = osp.join(savedir, app.picture_filename)
            factory.save(app.previous_picture_file)

        if cfg.getboolean('WINDOW', 'animate') and app.capture_nbr > 1:
            LOGGER.info("Asyncronously generate pictures for animation")
            for capture in captures:
                default_factory = get_picture_factory(
                    (capture, ),
                    cfg.get('PICTURE', 'orientation'),
                    force_pil=True,
                    dpi=200)
                factory = self._pm.hook.pibooth_setup_picture_factory(
                    cfg=cfg, opt_index=idx, factory=default_factory)
                factory.set_margin(factory._margin //
                                   3)  # 1/3 since DPI is divided by 3
                self.factory_pool.add(factory)
Exemplo n.º 6
0
 def set_config_value(self, section, option, value):
     """Set camera configuration. This method don't send the updated
     configuration to the camera (avoid connection flooding if several
     values have to be changed)
     """
     try:
         LOGGER.debug('Setting option %s/%s=%s', section, option, value)
         config = self._cam.get_config()
         child = config.get_child_by_name(section).get_child_by_name(option)
         if child.get_type() == gp.GP_WIDGET_RADIO:
             choices = [c for c in child.get_choices()]
         else:
             choices = None
         data_type = type(child.get_value())
         value = data_type(value)  # Cast value
         if choices and value not in choices:
             LOGGER.warning(
                 "Invalid value '%s' for option %s (possible choices: %s), trying to set it anyway", value, option, choices)
         child.set_value(value)
         self._cam.set_config(config)
     except gp.GPhoto2Error as ex:
         LOGGER.error('Unsupported option %s/%s=%s (%s), configure your DSLR manually', section, option, value, ex)
Exemplo n.º 7
0
 def preview_wait(self, timeout, alpha=60):
     """Wait the given time.
     """
     LOGGER.info("Arducam - previe_wait...")
     raise NotImplementedError
Exemplo n.º 8
0
 def print_picture(self, cfg, app):
     LOGGER.info("Send final picture to printer")
     app.printer.print_file(app.previous_picture_file,
                            cfg.getint('PRINTER', 'pictures_per_page'))
     app.count.printed += 1
     app.count.remaining_duplicates -= 1
Exemplo n.º 9
0
def get_camera(iso, resolution, rotation, flip, delete_internal_memory):
    """Initialize the camera depending of the connected one. If a gPhoto2 camera
    is used, try to kill any process using gPhoto2 as it may block camera access.

    The priority order is chosen in order to have best rendering during preview
    and to take captures.
    """
    LOGGER.info("get_camera")
    if gp_camera_connected() and rpi_camera_connected():
        LOGGER.info("Configuring hybrid camera (Picamera + gPhoto2) ...")
        cam_class = HybridCamera
        pkill('*gphoto2*')
    elif gpomx_camera_connected():
        LOGGER.info("Configuring gPhoto2 camera (preview with OMXPlayer) ...")
        cam_class = GpOmxCamera
        pkill('*gphoto2*')
    elif gp_camera_connected():
        LOGGER.info("Configuring gPhoto2 camera ...")
        cam_class = GpCamera
        pkill('*gphoto2*')
    elif rpi_camera_connected():
        LOGGER.info("Configuring Picamera camera ...")
        cam_class = RpiCamera
    elif cv_camera_connected():
        LOGGER.info("Configuring OpenCV camera ...")
        cam_class = CvCamera
    elif ardu_camera_connected():
        LOGGER.info("Configuring Arducam camera ...")
        cam_class = ArduCamera
    else:
        raise EnvironmentError("Neither Raspberry Pi nor GPhoto2 nor OpenCV camera detected")

    return cam_class(iso, resolution, rotation, flip, delete_internal_memory)
Exemplo n.º 10
0
def pibooth_startup(app, cfg):
    """display if plugin is activate."""
    if cfg.getboolean('QRCODE', 'activate'):
        LOGGER.info("Plugin 'QRCODE' is enable")
    else:
        LOGGER.info("Plugin 'QRCODE' is disable")
Exemplo n.º 11
0
    def do_actions(self, events):
        with timeit("Creating the final picture"):
            captures = self.app.camera.get_captures()

            backgrounds = self.app.config.gettuple('PICTURE', 'backgrounds',
                                                   ('color', 'path'), 2)
            if self.app.capture_nbr == self.app.capture_choices[0]:
                background = backgrounds[0]
            else:
                background = backgrounds[1]

            overlays = self.app.config.gettuple('PICTURE', 'overlays', 'path',
                                                2)
            if self.app.capture_nbr == self.app.capture_choices[0]:
                overlay = overlays[0]
            else:
                overlay = overlays[1]

            texts = [
                self.app.config.get('PICTURE', 'footer_text1').strip('"'),
                self.app.config.get('PICTURE', 'footer_text2').strip('"')
            ]
            colors = self.app.config.gettuple('PICTURE', 'text_colors',
                                              'color', len(texts))
            text_fonts = self.app.config.gettuple('PICTURE', 'text_fonts', str,
                                                  len(texts))
            alignments = self.app.config.gettuple('PICTURE', 'text_alignments',
                                                  str, len(texts))

            def _setup_maker(m):
                m.set_background(background)
                if any(elem != '' for elem in texts):
                    for params in zip(texts, text_fonts, colors, alignments):
                        m.add_text(*params)
                if self.app.config.getboolean('PICTURE', 'captures_cropping'):
                    m.set_cropping()
                if overlay:
                    m.set_overlay(overlay)
                if self.app.config.getboolean('GENERAL', 'debug'):
                    m.set_outlines()

            maker = get_picture_maker(
                captures, self.app.config.get('PICTURE', 'orientation'))
            _setup_maker(maker)
            self.app.previous_picture = maker.build()

        self.app.previous_picture_file = osp.join(
            self.app.savedir,
            osp.basename(self.app.dirname) + "_pibooth.jpg")
        maker.save(self.app.previous_picture_file)

        # Generate image id
        pic_crypt_name = gen_hash_filename(self.app.previous_picture_file)

        # Write exif informations in image file
        write_exif(self.app.previous_picture_file, self.app.capture_nbr,
                   pic_crypt_name)

        # Upload picture to server
        LOGGER.info("Uploading picture")

        shutil.copyfile(self.app.previous_picture_file,
                        "./pictures/" + pic_crypt_name)
        generate_qr_code("www.prinsenhof.de/~fotobox/" + pic_crypt_name,
                         "link.jpg", "./pictures/")
        ftp_upload("./pictures/" + pic_crypt_name, "", "", "", "")
        os.remove("./pictures/" + pic_crypt_name)

        if self.app.config.getboolean('WINDOW',
                                      'animate') and self.app.capture_nbr > 1:
            with timeit("Asyncronously generate pictures for animation"):
                for capture in captures:
                    maker = get_picture_maker(
                        (capture, ),
                        self.app.config.get('PICTURE', 'orientation'),
                        force_pil=True)
                    _setup_maker(maker)
                    self.app.makers_pool.add(maker)
Exemplo n.º 12
0
def main():
    """Application entry point.
    """
    parser = argparse.ArgumentParser(usage="%(prog)s [options]", description=pibooth.__doc__)

    parser.add_argument('--version', action='version', version=pibooth.__version__,
                        help=u"show program's version number and exit")

    parser.add_argument("--config", action='store_true',
                        help=u"edit the current configuration and exit")

    parser.add_argument("--translate", action='store_true',
                        help=u"edit the GUI translations and exit")

    parser.add_argument("--reset", action='store_true',
                        help=u"restore the default configuration/translations and exit")

    parser.add_argument("--fonts", action='store_true',
                        help=u"display all available fonts and exit")

    parser.add_argument("--log", default=None,
                        help=u"save logs output to the given file")

    group = parser.add_mutually_exclusive_group()
    group.add_argument("-v", "--verbose", dest='logging', action='store_const', const=logging.DEBUG,
                       help=u"report more information about operations", default=logging.INFO)
    group.add_argument("-q", "--quiet", dest='logging', action='store_const', const=logging.WARNING,
                       help=u"report only errors and warnings", default=logging.INFO)

    options, _args = parser.parse_known_args()

    configure_logging(options.logging, '[ %(levelname)-8s] %(name)-18s: %(message)s', filename=options.log)

    # Create plugin manager and defined hooks specification
    plugin_manager = pluggy.PluginManager(hookspecs.hookspec.project_name)
    plugin_manager.add_hookspecs(hookspecs)
    plugin_manager.load_setuptools_entrypoints(hookspecs.hookspec.project_name)

    # Load the configuration and languages
    config = PiConfigParser("~/.config/pibooth/pibooth.cfg", plugin_manager, options.reset)
    language.init("~/.config/pibooth/translations.cfg", options.reset)

    # Register plugins
    custom_paths = [p for p in config.gettuple('GENERAL', 'plugins', 'path') if p]
    load_plugins(plugin_manager, *custom_paths)
    LOGGER.info("Installed plugins: %s", ", ".join(list_plugin_names(plugin_manager)))

    # Update plugins configuration
    plugin_manager.hook.pibooth_configure(cfg=config)
    if not osp.isfile(config.filename):
        config.save()

    if options.config:
        LOGGER.info("Editing the pibooth configuration...")
        config.edit()
    elif options.translate:
        LOGGER.info("Editing the GUI translations...")
        language.edit()
    elif options.fonts:
        LOGGER.info("Listing all fonts available...")
        print_columns_words(get_available_fonts(), 3)
    elif options.reset:
        config.save()
    else:
        LOGGER.info("Starting the photo booth application %s", GPIO_INFO)
        app = PiApplication(config, plugin_manager)
        app.main_loop()
Exemplo n.º 13
0
 def state_preview_enter(self, cfg, app, win):
     LOGGER.info("Show preview before next capture")
     if not app.capture_date:
         app.capture_date = time.strftime("%Y-%m-%d-%H-%M-%S")
     app.camera.preview(win)
Exemplo n.º 14
0
 def state_choose_enter(self, app, win):
     LOGGER.info("Show picture choice (nothing selected)")
     win.set_print_number(0, False)  # Hide printer status
     win.show_choice(app.capture_choices)
     self.choose_timer.start()
Exemplo n.º 15
0
 def cleanup(self):
     LOGGER.debug("GPIO Mock: quit")
Exemplo n.º 16
0
 def setup(self, pin, direction, **kwargs):
     LOGGER.debug("GPIO Mock: setup pin %s to %s", pin, direction)
Exemplo n.º 17
0
 def setmode(self, mode):
     LOGGER.debug("GPIO Mock: set mode %s", mode)
Exemplo n.º 18
0
 def _on_receive_signal(self, pin, frame, callback, bouncetime):
     last = self._last_signal_time.setdefault(pin, 0)
     if abs(time.time() - last) * 1000 >= bouncetime:
         LOGGER.debug('GPIO Mock: pin %s triggered', pin)
         self._last_signal_time[pin] = time.time()
         callback(pin)
Exemplo n.º 19
0
 def stop_preview(self):
     """Stop the preview.
     """
     LOGGER.info("Arducam - stop_preview...")
     self._cam.stop_preview()
     self._window = None
Exemplo n.º 20
0
 def quit(self):
     """Close the camera driver, it's definitive.
     """
     LOGGER.info("Arducam - Close camera...")
     self._cam.close_camera()
Exemplo n.º 21
0
    def upload_photos(self, photo_file_list, album_name, activate):
        """Funtion use to upload list of photos to google album

        :param photo_file_list: list of photos name with full path
        :type photo_file_list: file
        :param album_name: name of albums to upload
        :type album_name: str
        :param activate: use to disable the upload
        :type activate: bool
        """
        self.activate = activate
        # interrupt upload no internet
        if not self._is_internet():
            LOGGER.error("Interrupt upload no internet connexion!!!!")
            return
        # if plugin is disable
        if not self.activate:
            return
        # plugin is disable at startup but activate after so check credential file
        elif not self.credentials:
            self._get_authorized_session()

        self.album_name = album_name
        self._create_or_retrieve_album()

        # interrupt upload if no album id can't read or create
        if self.album_name and not self.album_id:
            LOGGER.error("Interrupt upload album not found!!!!")
            return

        self.session.headers["Content-type"] = "application/octet-stream"
        self.session.headers["X-Goog-Upload-Protocol"] = "raw"

        for photo_file_name in photo_file_list:

            try:
                photo_file = open(photo_file_name, mode='rb')
                photo_bytes = photo_file.read()
            except OSError as err:
                LOGGER.error("Could not read file '%s' -- %s", photo_file_name,
                             err)
                continue

            self.session.headers["X-Goog-Upload-File-Name"] = os.path.basename(
                photo_file_name)

            LOGGER.info("Uploading photo -- '%s'", photo_file_name)

            upload_token = self.session.post(
                'https://photoslibrary.googleapis.com/v1/uploads', photo_bytes)

            if (upload_token.status_code == 200) and upload_token.content:

                create_body = json.dumps(
                    {
                        "albumId":
                        self.album_id,
                        "newMediaItems": [{
                            "description": "",
                            "simpleMediaItem": {
                                "uploadToken": upload_token.content.decode()
                            }
                        }]
                    },
                    indent=4)

                resp = self.session.post(
                    'https://photoslibrary.googleapis.com/v1/mediaItems:batchCreate',
                    create_body).json()

                LOGGER.debug("Server response: %s", resp)

                if "newMediaItemResults" in resp:
                    status = resp["newMediaItemResults"][0]["status"]
                    if status.get("code") and (status.get("code") > 0):
                        LOGGER.error("Could not add '%s' to library -- %s",
                                     os.path.basename(photo_file_name),
                                     status["message"])
                    else:
                        LOGGER.info("Added '%s' to library and album '%s' ",
                                    os.path.basename(photo_file_name),
                                    album_name)
                else:
                    LOGGER.error(
                        "Could not add '%s' to library. Server Response -- %s",
                        os.path.basename(photo_file_name), resp)

            else:
                LOGGER.error("Could not upload '%s'. Server Response -- %s",
                             os.path.basename(photo_file_name), upload_token)

        try:
            del self.session.headers["Content-type"]
            del self.session.headers["X-Goog-Upload-Protocol"]
            del self.session.headers["X-Goog-Upload-File-Name"]
        except KeyError:
            pass
Exemplo n.º 22
0
 def _show_overlay(self, text, alpha):
     """Add an image as an overlay.
     """
     LOGGER.info("Arducam - show_overlay...")
     raise NotImplementedError
Exemplo n.º 23
0
    def upload(self, filename, album_name):
        """Upload a photo file to the given Google Photos album.

        :param filename: photo file full path
        :type filename: str
        :param album_name: name of albums to upload
        :type album_name: str

        :returns: URL of the uploaded photo
        :rtype: str
        """
        photo_url = None

        if not self.is_reachable():
            LOGGER.error(
                "Google Photos upload failure: no internet connexion!")
            return photo_url

        if not self._credentials:
            # Plugin was disabled at startup but activated after
            self._session = self._get_authorized_session()

        album_id = self.get_album_id(album_name)
        if not album_id:
            album_id = self.create_album(album_name)
        if not album_id:
            LOGGER.error("Google Photos upload failure: album '%s' not found!",
                         album_name)
            return photo_url

        self._session.headers["Content-type"] = "application/octet-stream"
        self._session.headers["X-Goog-Upload-Protocol"] = "raw"

        with open(filename, mode='rb') as fp:
            data = fp.read()

        self._session.headers["X-Goog-Upload-File-Name"] = os.path.basename(
            filename)

        LOGGER.info("Uploading picture '%s' to Google Photos", filename)
        upload_token = self._session.post(self.URL + '/uploads', data)

        if upload_token.status_code == 200 and upload_token.content:
            create_body = json.dumps({
                "albumId":
                album_id,
                "newMediaItems": [{
                    "description": "",
                    "simpleMediaItem": {
                        "uploadToken": upload_token.content.decode()
                    }
                }]
            })

            resp = self._session.post(self.URL + '/mediaItems:batchCreate',
                                      create_body).json()
            LOGGER.debug("Google Photos server response: %s", resp)

            if "newMediaItemResults" in resp:
                status = resp["newMediaItemResults"][0]["status"]
                if status.get("code") and (status.get("code") > 0):
                    LOGGER.error(
                        "Google Photos upload failure: can not add '%s' to library: %s",
                        os.path.basename(filename), status["message"])
                else:
                    photo_url = resp["newMediaItemResults"][0][
                        'mediaItem'].get('productUrl')
                    LOGGER.info(
                        "Google Photos upload successful: '%s' added to album '%s'",
                        os.path.basename(filename), album_name)
            else:
                LOGGER.error(
                    "Google Photos upload failure: can not add '%s' to library",
                    os.path.basename(filename))

        elif upload_token.status_code != 200:
            LOGGER.error(
                "Google Photos upload failure: can not connect to '%s' (HTTP error %s)",
                self.URL, upload_token.status_code)
        else:
            LOGGER.error(
                "Google Photos upload failure: no response content from server '%s'",
                self.URL)

        try:
            del self._session.headers["Content-type"]
            del self._session.headers["X-Goog-Upload-Protocol"]
            del self._session.headers["X-Goog-Upload-File-Name"]
        except KeyError:
            pass

        return photo_url
Exemplo n.º 24
0
 def _hide_overlay(self):
     """Remove any existing overlay.
     """
     LOGGER.info("Arducam - hide_overlay...")
     raise NotImplementedError
Exemplo n.º 25
0
def gp_log_callback(level, domain, string, data=None):
    """Logging callback for gphoto2.
    """
    LOGGER.getChild('gphoto2').debug(
        domain.decode("utf-8") + u': ' + string.decode("utf-8"))
Exemplo n.º 26
0
 def state_failsafe_enter(self, win):
     win.show_oops()
     self.failed_view_timer.start()
     LOGGER.error(get_crash_message())
Exemplo n.º 27
0
def main():
    """Application entry point.
    """
    if hasattr(multiprocessing, 'set_start_method'):
        # Avoid use 'fork': safely forking a multithreaded process is problematic
        multiprocessing.set_start_method('spawn')

    parser = argparse.ArgumentParser(usage="%(prog)s [options]",
                                     description=pibooth.__doc__)

    parser.add_argument('--version',
                        action='version',
                        version=pibooth.__version__,
                        help=u"show program's version number and exit")

    parser.add_argument("--config",
                        action='store_true',
                        help=u"edit the current configuration and exit")

    parser.add_argument("--translate",
                        action='store_true',
                        help=u"edit the GUI translations and exit")

    parser.add_argument(
        "--reset",
        action='store_true',
        help=u"restore the default configuration/translations and exit")

    parser.add_argument("--fonts",
                        action='store_true',
                        help=u"display all available fonts and exit")

    parser.add_argument(
        "--nolog",
        action='store_true',
        default=False,
        help=
        u"don't save console output in a file (avoid filling the /tmp directory)"
    )

    group = parser.add_mutually_exclusive_group()
    group.add_argument("-v",
                       "--verbose",
                       dest='logging',
                       action='store_const',
                       const=logging.DEBUG,
                       help=u"report more information about operations",
                       default=logging.INFO)
    group.add_argument("-q",
                       "--quiet",
                       dest='logging',
                       action='store_const',
                       const=logging.WARNING,
                       help=u"report only errors and warnings",
                       default=logging.INFO)

    options, _args = parser.parse_known_args()

    if not options.nolog:
        filename = osp.join(tempfile.gettempdir(), 'pibooth.log')
    else:
        filename = None
    configure_logging(options.logging,
                      '[ %(levelname)-8s] %(name)-18s: %(message)s',
                      filename=filename)

    plugin_manager = create_plugin_manager()

    # Load the configuration and languages
    config = PiConfigParser("~/.config/pibooth/pibooth.cfg", plugin_manager)
    language.init(config.join_path("translations.cfg"), options.reset)

    # Register plugins
    custom_paths = [
        p for p in config.gettuple('GENERAL', 'plugins', 'path') if p
    ]
    load_plugins(plugin_manager, *custom_paths)
    LOGGER.info("Installed plugins: %s",
                ", ".join(list_plugin_names(plugin_manager)))

    # Update configuration with plugins ones
    plugin_manager.hook.pibooth_configure(cfg=config)

    # Ensure config files are present in case of first pibooth launch
    if not options.reset:
        if not osp.isfile(config.filename):
            config.save(default=True)
        plugin_manager.hook.pibooth_reset(cfg=config, hard=False)

    if options.config:
        LOGGER.info("Editing the pibooth configuration...")
        config.edit()
    elif options.translate:
        LOGGER.info("Editing the GUI translations...")
        language.edit()
    elif options.fonts:
        LOGGER.info("Listing all fonts available...")
        print_columns_words(get_available_fonts(), 3)
    elif options.reset:
        config.save(default=True)
        plugin_manager.hook.pibooth_reset(cfg=config, hard=True)
    else:
        LOGGER.info("Starting the photo booth application %s", GPIO_INFO)
        app = PiApplication(config, plugin_manager)
        app.main_loop()
Exemplo n.º 28
0
 def on_button_down(self, pin):
     """Post a pygame event when the button is pressed.
     """
     LOGGER.debug('Hardware button (pin %s) triggered', pin)
     event = pygame.event.Event(BUTTON_DOWN, pin=pin)
     pygame.event.post(event)
Exemplo n.º 29
0
def main():
    """Application entry point.
    """
    parser = argparse.ArgumentParser(usage="%(prog)s [options]",
                                     description=pibooth.__doc__)

    parser.add_argument('--version',
                        action='version',
                        version=pibooth.__version__,
                        help=u"show program's version number and exit")

    parser.add_argument("--config",
                        action='store_true',
                        help=u"edit the current configuration and exit")

    parser.add_argument("--translate",
                        action='store_true',
                        help=u"edit the GUI translations and exit")

    parser.add_argument(
        "--reset",
        action='store_true',
        help=u"restore the default configuration/translations and exit")

    parser.add_argument("--fonts",
                        action='store_true',
                        help=u"display all available fonts and exit")

    parser.add_argument("--log",
                        default=None,
                        help=u"save logs output to the given file")

    group = parser.add_mutually_exclusive_group()
    group.add_argument("-v",
                       "--verbose",
                       dest='logging',
                       action='store_const',
                       const=logging.DEBUG,
                       help=u"report more information about operations",
                       default=logging.INFO)
    group.add_argument("-q",
                       "--quiet",
                       dest='logging',
                       action='store_const',
                       const=logging.WARNING,
                       help=u"report only errors and warnings",
                       default=logging.INFO)

    options, _args = parser.parse_known_args()

    configure_logging(options.logging,
                      '[ %(levelname)-8s] %(name)-18s: %(message)s',
                      filename=options.log)

    config = PiConfigParser("~/.config/pibooth/pibooth.cfg", options.reset)
    language.init("~/.config/pibooth/translations.cfg", options.reset)

    if options.config:
        LOGGER.info("Editing the pibooth configuration...")
        config.edit()
    elif options.translate:
        LOGGER.info("Editing the GUI translations...")
        language.edit()
    elif options.fonts:
        LOGGER.info("Listing all fonts available...")
        print_columns_words(get_available_fonts(), 3)
    elif not options.reset:
        LOGGER.info(
            "Starting the photo booth application {}".format(gpio_info))
        app = PiApplication(config)
        app.main_loop()
Exemplo n.º 30
0
def main():
    """Application entry point.
    """
    configure_logging()
    plugin_manager = create_plugin_manager()
    config = PiConfigParser("~/.config/pibooth/pibooth.cfg", plugin_manager)

    conn = cups.Connection()
    name = config.get('PRINTER', 'printer_name')

    if not name or name.lower() == 'default':
        name = conn.getDefault()
        if not name and conn.getPrinters():
            name = list(conn.getPrinters().keys())[0]  # Take first one
    elif name not in conn.getPrinters():
        name = None

    if not name:
        if name.lower() == 'default':
            LOGGER.warning(
                "No printer configured in CUPS (see http://localhost:631)")
            return
        else:
            LOGGER.warning(
                "No printer named '%s' in CUPS (see http://localhost:631)",
                name)
            return
    else:
        LOGGER.info("Connected to printer '%s'", name)

    f = conn.getPPD(name)
    ppd = cups.PPD(f)
    groups = ppd.optionGroups
    options = []
    for group in groups:
        group_name = "{} - {}".format(group.name, group.text)
        for opt in group.options:
            option = {'group': group_name}
            values = list(map(lambda x: x["choice"], opt.choices))
            texts = list(map(lambda x: x["text"], opt.choices))
            option['keyword'] = opt.keyword
            option['value'] = opt.defchoice
            option['description'] = opt.text
            if values != texts:
                option['choices'] = dict([(v, texts[values.index(v)])
                                          for v in values])
            else:
                option['choices'] = values
            options.append(option)

    if '--json' in sys.argv:
        print(
            json.dumps(
                dict([(option['keyword'], option['value'])
                      for option in options])))
    else:
        for option in options:
            print("{} = {}".format(option['keyword'], option['value']))
            print("     Description: {}".format(option['description']))
            if isinstance(option['choices'], dict):
                choices = [
                    "{} = {}".format(value, descr)
                    for value, descr in option['choices'].items()
                ]
                print("     Choices:     {}".format(choices[0]))
                for choice in choices[1:]:
                    print("                  {}".format(choice))
            else:
                print("     Choices:     {}".format(", ".join(
                    option['choices'])))

            print()