diff --git a/data/ui/CameraMugshotDialog.ui b/data/ui/CameraMugshotDialog.ui
new file mode 100644
index 0000000..2370e78
--- /dev/null
+++ b/data/ui/CameraMugshotDialog.ui
@@ -0,0 +1,102 @@
+
+
+
+
+
+
diff --git a/data/ui/MugshotWindow.ui b/data/ui/MugshotWindow.ui
index 0a881ce..a34342a 100644
--- a/data/ui/MugshotWindow.ui
+++ b/data/ui/MugshotWindow.ui
@@ -39,10 +39,10 @@
Capture from camera...True
- FalseFalseimage2False
+
diff --git a/data/ui/camera_mugshot_dialog.xml b/data/ui/camera_mugshot_dialog.xml
new file mode 100644
index 0000000..12b16d2
--- /dev/null
+++ b/data/ui/camera_mugshot_dialog.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
diff --git a/mugshot/CameraMugshotDialog.py b/mugshot/CameraMugshotDialog.py
new file mode 100644
index 0000000..b17cbfc
--- /dev/null
+++ b/mugshot/CameraMugshotDialog.py
@@ -0,0 +1,193 @@
+# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
+### BEGIN LICENSE
+# Copyright (C) 2013 Sean Davis
+# This program is free software: you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 3, as published
+# by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranties of
+# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
+# PURPOSE. See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program. If not, see .
+### END LICENSE
+
+from locale import gettext as _
+
+import logging
+logger = logging.getLogger('mugshot')
+
+from gi.repository import Gtk, GdkX11, GObject, Gst, GstVideo
+
+from mugshot_lib.CameraDialog import CameraDialog
+
+class CameraMugshotDialog(CameraDialog):
+ __gtype_name__ = "CameraMugshotDialog"
+
+ def finish_initializing(self, builder): # pylint: disable=E1002
+ """Set up the preferences dialog"""
+ super(CameraMugshotDialog, self).finish_initializing(builder)
+
+ Gst.init(None)
+
+ # Code for other initialization actions should be added here.
+ vbox = builder.get_object('camera_box')
+ self.video_window = Gtk.DrawingArea()
+ self.video_window.connect("realize",self.__on_video_window_realized)
+ vbox.pack_start(self.video_window, True, True, 0)
+ self.video_window.show()
+
+ self.camerabin = Gst.ElementFactory.make("camerabin", "camera-source")
+ bus = self.camerabin.get_bus()
+ bus.add_signal_watch()
+ bus.enable_sync_message_emission()
+ bus.connect("message", self._on_message)
+ bus.connect("sync-message::element", self._on_sync_message)
+ self.realized = False
+ self.show_all()
+ ##self.play()
+
+ def play(self):
+ """play - Start the camera streaming and display the output. It is
+ necessary to start the camera playing before using most other functions.
+
+ This function has no arguments
+
+ """
+
+ if not self.realized:
+ self._set_video_window_id()
+ if not self.realized:
+ print _("Cannot display web cam output. Ignoring play command")
+ else:
+ self.camerabin.set_state(Gst.State.PLAYING)
+
+ def pause(self):
+ """pause - Pause the camera output. It will cause the image to
+ "freeze". Use play() to start the camera playng again. Note that
+ calling pause before play may cause errors on certain camera.
+
+ This function has no arguments
+
+ """
+
+ self.camerabin.set_state(Gst.State.PAUSED)
+
+ def take_picture(self, filename):
+ """take_picture - grab a frame from the web cam and save it to
+ ~/Pictures/datestamp.png, where datestamp is the current datestamp.
+ It's possible to add a prefix to the datestamp by setting the
+ filename_prefix property.
+
+ If play is not called before take_picture,
+ an error may occur. If take_picture is called immediately after play,
+ the camera may not be fully initialized, and an error may occur.
+
+ Connect to the signal "image-captured" to be alerted when the picture
+ is saved.
+
+ This function has no arguments
+
+ returns - a string of the filename used to save the image
+
+ """
+ self.camerabin.set_property("location", filename)
+ self.camerabin.emit("start-capture")
+ return filename
+
+ def stop(self):
+ """stop - Stop the camera streaming and display the output.
+
+ This function has no arguments
+
+ """
+
+ self.camerabin.set_state(Gst.State.NULL)
+
+ def _on_message(self, bus, message):
+ """ _on_message - internal signal handler for bus messages.
+ May be useful to extend in a base class to handle messages
+ produced from custom behaviors.
+
+
+ arguments -
+ bus: the bus from which the message was sent, typically self.bux
+ message: the message sent
+
+ """
+
+ if message is None:
+ return
+
+ t = message.type
+ #if t == Gst.MessageType.ASYNC_DONE:
+ # print 'finally'
+ if t == Gst.MessageType.ELEMENT:
+ if message.get_structure().get_name() == "image-captured":
+ #work around to keep the camera working after lots
+ #of pictures are taken
+ self.camerabin.set_state(Gst.Sate.NULL)
+ self.camerabin.set_state(Gst.State.PLAYING)
+
+ self.emit("image-captured", self.filename)
+
+ if t == Gst.MessageType.EOS:
+ self.camerabin.set_state(Gst.State.NULL)
+ elif t == Gst.MessageType.ERROR:
+ err, debug = message.parse_error()
+ print "Error: %s" % err, debug
+
+ def _on_sync_message(self, bus, message):
+ """ _on_sync_message - internal signal handler for bus messages.
+ May be useful to extend in a base class to handle messages
+ produced from custom behaviors.
+
+
+ arguments -
+ bus: the bus from which the message was sent, typically self.bux
+ message: the message sent
+
+ """
+
+ if message.get_structure() is None:
+ return
+ message_name = message.get_structure().get_name()
+ if message_name == "prepare-window-handle":
+ imagesink = message.src
+ imagesink.set_property("force-aspect-ratio", True)
+ imagesink.set_window_handle(self.video_window.get_window().get_xid())
+
+ def __on_video_window_realized(self, widget, data=None):
+ """__on_video_window_realized - internal signal handler, used
+ to set up the xid for the drawing area in thread safe manner.
+ Do not call directly.
+
+ """
+ self._set_video_window_id()
+
+ def _set_video_window_id(self):
+ if not self.realized and self.video_window.get_window() is not None:
+ x = self.video_window.get_window().get_xid()
+ self.realized = True
+
+ def on_camera_mugshot_dialog_destroy(self, widget, data=None):
+ #clean up the camera before exiting
+ self.camerabin.set_state(Gst.State.NULL)
+
+ def on_camera_mugshot_dialog_hide(self, widget, data=None):
+ self.pause()
+
+ def on_camera_mugshot_dialog_show(self, widget, data=None):
+ self.show_all()
+ self.play()
+
+ def on_camera_mugshot_dialog_delete_event(self, widget, data=None):
+ self.hide()
+ return True
+
+ __gsignals__ = {'image-captured' : (GObject.SIGNAL_RUN_LAST, GObject.TYPE_NONE,
+ (GObject.TYPE_PYOBJECT,)),
+ }
+
diff --git a/mugshot/MugshotWindow.py b/mugshot/MugshotWindow.py
index acd17b6..3d14eeb 100644
--- a/mugshot/MugshotWindow.py
+++ b/mugshot/MugshotWindow.py
@@ -31,6 +31,7 @@ import logging
logger = logging.getLogger('mugshot')
from mugshot_lib import Window
+from mugshot.CameraMugshotDialog import CameraMugshotDialog
username = os.getenv('USER')
if not username:
@@ -99,6 +100,8 @@ class MugshotWindow(Window):
def finish_initializing(self, builder): # pylint: disable=E1002
"""Set up the main window"""
super(MugshotWindow, self).finish_initializing(builder)
+
+ self.CameraDialog = CameraMugshotDialog
# User Image widgets
self.image_button = builder.get_object('image_button')
diff --git a/mugshot_lib/CameraDialog.py b/mugshot_lib/CameraDialog.py
new file mode 100644
index 0000000..cf8aae3
--- /dev/null
+++ b/mugshot_lib/CameraDialog.py
@@ -0,0 +1,61 @@
+# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
+### BEGIN LICENSE
+# Copyright (C) 2013 Sean Davis
+# This program is free software: you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 3, as published
+# by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranties of
+# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
+# PURPOSE. See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program. If not, see .
+### END LICENSE
+
+### DO NOT EDIT THIS FILE ###
+
+from gi.repository import Gtk # pylint: disable=E0611
+import logging
+logger = logging.getLogger('mugshot_lib')
+
+from . helpers import get_builder, show_uri, get_help_uri
+
+class CameraDialog(Gtk.Dialog):
+ __gtype_name__ = "CameraDialog"
+
+ def __new__(cls):
+ """Special static method that's automatically called by Python when
+ constructing a new instance of this class.
+
+ Returns a fully instantiated PreferencesDialog object.
+ """
+ builder = get_builder('CameraMugshotDialog')
+ new_object = builder.get_object("camera_mugshot_dialog")
+ new_object.finish_initializing(builder)
+ return new_object
+
+ def finish_initializing(self, builder):
+ """Called while initializing this instance in __new__
+
+ finish_initalizing should be called after parsing the ui definition
+ and creating a PreferencesDialog object with it in order to
+ finish initializing the start of the new PerferencesMugshotDialog
+ instance.
+
+ Put your initialization code in here and leave __init__ undefined.
+ """
+
+ # Get a reference to the builder and set up the signals.
+ self.builder = builder
+ self.ui = builder.get_ui(self, True)
+
+ # code for other initialization actions should be added here
+
+ def on_btn_close_clicked(self, widget, data=None):
+ self.destroy()
+
+ def on_btn_help_clicked(self, widget, data=None):
+ show_uri(self, "ghelp:%s" % get_help_uri('preferences'))
+
diff --git a/mugshot_lib/Window.py b/mugshot_lib/Window.py
index 1d25162..9a1222c 100644
--- a/mugshot_lib/Window.py
+++ b/mugshot_lib/Window.py
@@ -58,12 +58,37 @@ class Window(Gtk.Window):
# Get a reference to the builder and set up the signals.
self.builder = builder
self.ui = builder.get_ui(self, True)
+ self.CameraDialog = None # class
+ self.camera_dialog = None # instance
self.settings = Gio.Settings("apps.mugshot")
self.settings.connect('changed', self.on_preferences_changed)
def on_help_activate(self, widget, data=None):
show_uri(self, "ghelp:%s" % get_help_uri())
+
+ def on_menu_camera_activate(self, widget, data=None):
+ """Display the camera window for mugshot."""
+ if self.camera_dialog is not None:
+ logger.debug('show existing camera_dialog')
+ self.camera_dialog.show()
+ elif self.CameraDialog is not None:
+ logger.debug('create new camera_dialog')
+ self.camera_dialog = self.CameraDialog() # pylint: disable=E1102
+ #self.camera_dialog.connect('destroy', self.on_camera_dialog_destroyed)
+ self.camera_dialog.show()
+
+
+
+ #def on_camera_dialog_destroyed(self, widget, data=None):
+ # '''only affects gui
+ #
+ # logically there is no difference between the user closing,
+ # minimising or ignoring the camera dialog'''
+ # logger.debug('on_camera_dialog_destroyed')
+ # # to determine whether to create or present camera_dialog
+ # self.camera_dialog.hide()
+ # #self.camera_dialog = None
def on_destroy(self, widget, data=None):
"""Called when the MugshotWindow is closed."""